v2 methylation control QC (WIP): simurg methyl qc|convert-manifest (MET-001..018)
Methylation CSV manifest reader (MET-002/003), raw M/U assembly with bead masking (MET-005), pOOBAH detection p-values, noob background correction, linear/nonlinear dye bias, beta and M-values (MET-010..012), the 21 methylation control metrics (MET-006, bs-conv red-bg set option), per-sample ctrl/cgs tables, summary tsv/xlsx/html with the detection histogram and a beta PCA, pcs.tsv.gz, controls_raw/controls_qc.tsv; methylation datasets load in qc report (MET-014); qc controls --array-type methylation; minfi-style Sentrix_ID/Sentrix_Position sheet keys. Vendor EPIC manifests carry a 5th field on some control lines: >= 4 fields accepted. Runs on the public minfiDataEPIC set (3 x NA12878). Co-Authored-By: Claude Opus 5.5 <[email protected]> Claude-Session: https://claude.ai/code/session_01814GKVzZVL3FuF3DeiZXhv
This commit is contained in:
1 parent
7c0e348033
commit
c1c2c30c87
13 files changed
+1292
-21
No files matched your search
@@ -51,6 +51,20 @@ canonical:
|
||||
bs conversion i u3: bs1_U3
|
||||
bs conversion i u4: bs1_U4
|
||||
bs conversion i u5: bs1_U5
|
||||
bs conversion i-c1: bs1_C1
|
||||
bs conversion i-c2: bs1_C2
|
||||
bs conversion i-c3: bs1_C3
|
||||
bs conversion i-c4: bs1_C4
|
||||
bs conversion i-c5: bs1_C5
|
||||
bs conversion i-c6: bs1_C6
|
||||
bs conversion i-u1: bs1_U1
|
||||
bs conversion i-u2: bs1_U2
|
||||
bs conversion i-u3: bs1_U3
|
||||
bs conversion i-u4: bs1_U4
|
||||
bs conversion i-u5: bs1_U5
|
||||
bs conversion i-u6: bs1_U6
|
||||
bs conversion i c6: bs1_C6
|
||||
bs conversion i u6: bs1_U6
|
||||
bs conversion ii-1: bs2_1
|
||||
bs conversion ii-2: bs2_2
|
||||
bs conversion ii-3: bs2_3
|
||||
|
||||
@@ -71,6 +71,10 @@ METRICS: tuple[Metric, ...] = (
|
||||
Metric("bs_conv_2", "bisulfiteConversionII", False, True),
|
||||
Metric("bs_conv_2_bg", "bisulfiteConversionIIBg", False, True),
|
||||
)
|
||||
GTMM_PM = [f"gtmm_{i}_pm" for i in range(1, 7)]
|
||||
GTMM_MM = [f"gtmm_{i}_mm" for i in range(1, 7)]
|
||||
SPEC2 = ["spec2_1", "spec2_2", "spec2_3"]
|
||||
BS2 = ["bs2_1", "bs2_2", "bs2_3", "bs2_4"]
|
||||
ASSAY_CONTROL_COLUMN = "assay_control_norm_r" # QC-005: copied from the sample summary
|
||||
COMPAT_METRIC_NAMES = {
|
||||
"restoration": "RestorationQC",
|
||||
@@ -223,14 +227,12 @@ def compute_control_metrics(
|
||||
red: npt.NDArray[np.float64],
|
||||
array_type: str = "genotyping",
|
||||
bg_offset: float = DEFAULT_BG_OFFSET,
|
||||
bs_conv_red_bg_set: str = "U3-U5",
|
||||
) -> ControlQC:
|
||||
"""QC-003/QC-004 metrics of one sample. Single-probe values are bead means; min/max run over all beads (QC-002)."""
|
||||
if array_type != "genotyping":
|
||||
from simurg.core.errors import SimurgError
|
||||
|
||||
raise SimurgError("E_QC_METHYLATION", "methylation control metrics are planned for v2 (QC-006)")
|
||||
p = _Probes(beads, green, red)
|
||||
x = bg_offset
|
||||
bs_red_u = ["bs1_U3", "bs1_U4", "bs1_U5"] if bs_conv_red_bg_set == "U3-U5" else ["bs1_U4", "bs1_U5", "bs1_U6"]
|
||||
formulas: dict[str, tuple[Any, Any]] = {
|
||||
# column: (numerator thunk, denominator thunk); each thunk records the probes it needs
|
||||
"restoration": (lambda: p.mean("restoration", "G"), lambda: p.max(["ext_A", "ext_T"], "G") + x),
|
||||
@@ -246,6 +248,18 @@ def compute_control_metrics(
|
||||
"nsb_red": (lambda: p.max(["ext_C", "ext_G"], "R") + x, lambda: p.max(["nsb_bkg"], "R")),
|
||||
"np_green": (lambda: p.min(["np_C", "np_G"], "G"), lambda: p.max(["np_A", "np_T"], "G")),
|
||||
"np_red": (lambda: p.min(["np_A", "np_T"], "R"), lambda: p.max(["np_C", "np_G"], "R")),
|
||||
# methylation (QC-004 rows 9, 15-24; MET-006)
|
||||
"target_removal_2": (lambda: p.max(["ext_A", "ext_T"], "G") + x, lambda: p.mean("target_removal_2", "G")),
|
||||
"specificity_1_green": (lambda: p.min(GTMM_PM[:3], "G"), lambda: p.max(GTMM_MM[:3], "G")),
|
||||
"specificity_1_red": (lambda: p.min(GTMM_PM[3:], "R"), lambda: p.max(GTMM_MM[3:], "R")),
|
||||
"specificity_2": (lambda: p.min(SPEC2, "R"), lambda: p.max(SPEC2, "G")),
|
||||
"specificity_2_bg": (lambda: p.max(["ext_A", "ext_T"], "G") + x, lambda: p.max(SPEC2, "G")),
|
||||
"bs_conv_1_green": (lambda: p.min(["bs1_C1", "bs1_C2"], "G"), lambda: p.max(["bs1_U1", "bs1_U2"], "G")),
|
||||
"bs_conv_1_green_bg": (lambda: p.max(["ext_A", "ext_T"], "G") + x, lambda: p.max(["bs1_U1", "bs1_U2"], "G")),
|
||||
"bs_conv_1_red": (lambda: p.min(["bs1_C3", "bs1_C4", "bs1_C5"], "R"), lambda: p.max(bs_red_u, "R")),
|
||||
"bs_conv_1_red_bg": (lambda: p.max(["ext_C", "ext_G"], "R") + x, lambda: p.max(bs_red_u, "R")),
|
||||
"bs_conv_2": (lambda: p.min(BS2, "R"), lambda: p.max(BS2, "G")),
|
||||
"bs_conv_2_bg": (lambda: p.max(["ext_A", "ext_T"], "G") + x, lambda: p.max(BS2, "G")),
|
||||
}
|
||||
res = ControlQC(values={})
|
||||
for m in metrics_for(array_type):
|
||||
|
||||
Reference in new issue
Block a user