Skip to content

fastq_qc

fastq_qc

Raw FASTQ QC results: the sample_fastq_qc table (schema 008).

One row per sample with the headline numbers and flags of its FASTQ quality control, written by noxqc noxdb register from the sample's QC JSON (which is itself registered in sample_files as file type fastq_qc)::

fastq_qc.upsert(cur, sample_id, row)       # -> "inserted" | "updated" | "unchanged"
fastq_qc.get(cur, sample_id)               # -> dict | None
fastq_qc.for_project(cur, project_id)      # -> DataFrame, one row per project sample
fastq_qc.delete(cur, sample_id)            # -> bool

upsert is idempotent (INSERT ... ON DUPLICATE KEY UPDATE on the primary key): re-running the QC of a sample overwrites its row.

upsert

upsert(cur, sample_id: int, row: dict[str, Any]) -> SetResult

Insert or overwrite the QC row of a sample. Idempotent.

Parameters:

Name Type Description Default
cur

Audit-logging cursor from transaction().

required
sample_id int

The sample (must exist).

required
row dict[str, Any]

Column -> value. Unknown columns are rejected; qc_version, qc_run_at (datetime or ISO string, stored as UTC), pair_ok and worst_flag are required, the rest default to NULL (barcode_match to 'unknown').

required

Returns:

Type Description
SetResult

"inserted", "updated" or "unchanged".

Raises:

Type Description
ValueError

On unknown or missing columns, or an invalid enum value.

Source code in src/noxdb/fastq_qc.py
def upsert(cur, sample_id: int, row: dict[str, Any]) -> SetResult:
    """Insert or overwrite the QC row of a sample. Idempotent.

    Args:
        cur: Audit-logging cursor from `transaction()`.
        sample_id: The sample (must exist).
        row: Column -> value. Unknown columns are rejected; ``qc_version``,
            ``qc_run_at`` (datetime or ISO string, stored as UTC),
            ``pair_ok`` and ``worst_flag`` are required, the rest default
            to NULL (``barcode_match`` to ``'unknown'``).

    Returns:
        ``"inserted"``, ``"updated"`` or ``"unchanged"``.

    Raises:
        ValueError: On unknown or missing columns, or an invalid enum value.
    """
    values = _validate(row)
    cols = ", ".join(COLUMNS)
    marks = ", ".join("?" for _ in COLUMNS)
    updates = ", ".join(f"{c} = VALUES({c})" for c in COLUMNS)
    cur.execute(
        f"INSERT INTO sample_fastq_qc (sample_id, {cols}) VALUES (?, {marks}) "
        f"ON DUPLICATE KEY UPDATE {updates}",
        (sample_id, *values.values()),
    )
    # MariaDB INSERT ... ON DUPLICATE KEY UPDATE rowcount:
    #   1 = row inserted, 2 = row updated, 0 = row matched but unchanged.
    rc = cur.rowcount
    if rc == 1:
        return "inserted"
    if rc == 2:
        return "updated"
    return "unchanged"

get

get(cur, sample_id: int) -> dict[str, Any] | None

Return the QC row of a sample, or None if it has none.

Source code in src/noxdb/fastq_qc.py
def get(cur, sample_id: int) -> dict[str, Any] | None:
    """Return the QC row of a sample, or ``None`` if it has none."""
    cur.execute("SELECT * FROM sample_fastq_qc WHERE sample_id = ?", (sample_id,))
    rows = _fetch_dicts(cur)
    return rows[0] if rows else None

delete

delete(cur, sample_id: int) -> bool

Delete the QC row of a sample. Returns True if a row was removed.

Source code in src/noxdb/fastq_qc.py
def delete(cur, sample_id: int) -> bool:
    """Delete the QC row of a sample. Returns ``True`` if a row was removed."""
    cur.execute("DELETE FROM sample_fastq_qc WHERE sample_id = ?", (sample_id,))
    return cur.rowcount > 0

for_project

for_project(cur, project_id: int) -> 'pd.DataFrame'

One row per sample of a project (controls included), with its QC.

Samples without a QC result are kept, with NULL QC columns, so the result also shows what is still unchecked.

Parameters:

Name Type Description Default
cur

Audit-logging cursor from transaction().

required
project_id int

Project to scan.

required

Returns:

Type Description
'pd.DataFrame'

A pandas.DataFrame with sample_id, sample_name,

'pd.DataFrame'

sample_type, SQR, SQRP, IPR, IPRP and every

'pd.DataFrame'

sample_fastq_qc column.

Raises:

Type Description
ImportError

If pandas is not installed.

Source code in src/noxdb/fastq_qc.py
def for_project(cur, project_id: int) -> "pd.DataFrame":
    """One row per sample of a project (controls included), with its QC.

    Samples without a QC result are kept, with NULL QC columns, so the
    result also shows what is still unchecked.

    Args:
        cur: Audit-logging cursor from `transaction()`.
        project_id: Project to scan.

    Returns:
        A ``pandas.DataFrame`` with ``sample_id``, ``sample_name``,
        ``sample_type``, ``SQR``, ``SQRP``, ``IPR``, ``IPRP`` and every
        ``sample_fastq_qc`` column.

    Raises:
        ImportError: If pandas is not installed.
    """
    pd = _pd()
    qc_cols = ", ".join(f"q.{c}" for c in COLUMNS)
    cur.execute(
        "SELECT sm.sample_id, sm.sample_name, sm.sample_type, sm.SQR, sm.SQRP, sm.IPR, sm.IPRP, "
        f"{qc_cols} "
        "FROM project_samples ps "
        "JOIN samples sm ON sm.sample_id = ps.sample_id "
        "LEFT JOIN sample_fastq_qc q ON q.sample_id = sm.sample_id "
        "WHERE ps.project_id = ? ORDER BY sm.sample_name",
        (project_id,),
    )
    return pd.DataFrame(_fetch_dicts(cur))