samples¶
samples
¶
CRUD wrapper for the samples table.
Same call style as the other table modules: cursor first, dict returns,
writes audit-logged via _LoggingCursor.
sample_name is globally unique (not scoped to a visit), so the
natural-key lookup is get_by_name
and get_or_create keys on
sample_name alone.
canonical_plate_id
¶
Return the canonical form of an SQR / SQRP plate identifier.
Strips surrounding whitespace and collapses the "absent" sentinels
("", "NA", "N/A", case-insensitive) to a single
canonical empty string. Any other value is returned stripped but
otherwise verbatim — zero-padding is left intact because it is
the canonical shape here.
This is the one normalization chokepoint for plate identifiers;
create / update
call it on every write and the importer reuses it so the value the
DB stores is always canonical and SQR+SQRP matching is reliable.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
value
|
str | None
|
Raw SQR / SQRP cell (may be |
required |
Returns:
| Type | Description |
|---|---|
str
|
The canonical identifier (possibly |
Source code in src/noxdb/samples.py
create
¶
create(cur, visit_id: int, sample_name: str, sample_type: str, sqr: str, sqrp: str, library: str, *, antibody_class: str | None = None) -> int
Insert a sample and return its new sample_id.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
cur
|
Audit-logging cursor from |
required | |
visit_id
|
int
|
Parent visit. Must already exist. |
required |
sample_name
|
str
|
Globally unique sample name. |
required |
sample_type
|
str
|
One of |
required |
sqr
|
str
|
SQR plate identifier. Canonicalized via
|
required |
sqrp
|
str
|
SQRP plate identifier. Canonicalized like |
required |
library
|
str
|
Library identifier. |
required |
antibody_class
|
str | None
|
Optional antibody class label. |
None
|
Returns:
| Type | Description |
|---|---|
int
|
The newly inserted |
Raises:
| Type | Description |
|---|---|
IntegrityError
|
If |
Source code in src/noxdb/samples.py
get
¶
Return the sample row for a given id.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
cur
|
Audit-logging cursor from |
required | |
sample_id
|
int
|
Primary key to look up. |
required |
Returns:
| Type | Description |
|---|---|
dict[str, Any] | None
|
The row as |
Source code in src/noxdb/samples.py
get_by_name
¶
Return the sample row for a given name.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
cur
|
Audit-logging cursor from |
required | |
sample_name
|
str
|
Globally unique sample name. |
required |
Returns:
| Type | Description |
|---|---|
dict[str, Any] | None
|
The row as |
Source code in src/noxdb/samples.py
get_or_create
¶
get_or_create(cur, visit_id: int, sample_name: str, sample_type: str, sqr: str, sqrp: str, library: str, *, antibody_class: str | None = None) -> tuple[int, bool]
Idempotently return the sample id, inserting if needed.
Existing rows are returned as-is — the other columns are not used to update an existing row. Falls back to a re-fetch on the UNIQUE-violation race.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
cur
|
Audit-logging cursor from |
required | |
visit_id
|
int
|
Parent visit (used only on insert). |
required |
sample_name
|
str
|
Globally unique sample name. |
required |
sample_type
|
str
|
Used only on insert. See
|
required |
sqr
|
str
|
Used only on insert. |
required |
sqrp
|
str
|
Used only on insert. |
required |
library
|
str
|
Used only on insert. |
required |
antibody_class
|
str | None
|
Used only on insert. |
None
|
Returns:
| Type | Description |
|---|---|
int
|
|
bool
|
call inserted the row. |
Raises:
| Type | Description |
|---|---|
IntegrityError
|
If the race-recovery fetch also misses. |
Source code in src/noxdb/samples.py
link_to_project
¶
Register sample_id under project_id in project_samples.
Idempotent: INSERT IGNORE so re-linking an already-linked
(project, sample) pair is a no-op. project_samples is the sole
source of truth for which samples belong to which project — a
sample may be linked to several projects (e.g. plate controls
shared across studies).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
cur
|
Audit-logging cursor from |
required | |
project_id
|
int
|
Project to link the sample to. Must already exist. |
required |
sample_id
|
int
|
Sample to link. Must already exist. |
required |
Source code in src/noxdb/samples.py
list_for_visit
¶
Return all samples belonging to a visit.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
cur
|
Audit-logging cursor from |
required | |
visit_id
|
int
|
Visit to list. |
required |
order_by
|
str
|
Column name to order by. Must be a column of |
'sample_id'
|
Returns:
| Type | Description |
|---|---|
list[dict[str, Any]]
|
All matching rows as |
Raises:
| Type | Description |
|---|---|
ValueError
|
If |
Source code in src/noxdb/samples.py
count_for_visit
¶
Return the number of samples for a visit.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
cur
|
Audit-logging cursor from |
required | |
visit_id
|
int
|
Visit to count. |
required |
Returns:
| Type | Description |
|---|---|
int
|
Number of sample rows. |
Source code in src/noxdb/samples.py
update
¶
update(cur, sample_id: int, *, sample_name: str | None = None, sample_type: str | None = None, sqr: str | None = None, sqrp: str | None = None, library: str | None = None, antibody_class: str | None = None) -> bool
Partial update of a sample row.
Only kwargs with non-None values are written. visit_id and
created_at are intentionally NOT updatable — re-parenting a
sample would corrupt downstream lineage. Setting antibody_class
to NULL is also out of scope (the helper treats None as "skip");
use raw SQL if you need that.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
cur
|
Audit-logging cursor from |
required | |
sample_id
|
int
|
Row to update. |
required |
sample_name
|
str | None
|
New name (if not None). |
None
|
sample_type
|
str | None
|
New type (if not None). See
|
None
|
sqr
|
str | None
|
New SQR (if not None). Canonicalized via
|
None
|
sqrp
|
str | None
|
New SQRP (if not None). Canonicalized like |
None
|
library
|
str | None
|
New library (if not None). |
None
|
antibody_class
|
str | None
|
New antibody class (if not None). |
None
|
Returns:
| Type | Description |
|---|---|
bool
|
|
Source code in src/noxdb/samples.py
delete
¶
Delete a sample.
sample_metadata.fk_sample_metadata_sample is ON DELETE
CASCADE, so this also removes every metadata row owned by the
sample. sample_files.fk_sample_files_sample is ON DELETE
RESTRICT and will block the delete instead — clean those up
first.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
cur
|
Audit-logging cursor from |
required | |
sample_id
|
int
|
Row to delete. |
required |
Returns:
| Type | Description |
|---|---|
bool
|
|
Source code in src/noxdb/samples.py
exists
¶
Return whether a sample with the given id or name exists.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
cur
|
Audit-logging cursor from |
required | |
sample_id
|
int | None
|
Id to check (exclusive with |
None
|
name
|
str | None
|
Name to check (exclusive with |
None
|
Returns:
| Type | Description |
|---|---|
bool
|
|
Raises:
| Type | Description |
|---|---|
ValueError
|
If both or neither of |