P5 validated on 2141 1000G samples; control-metric fixes (K-021)
- Omni2.5 cloud run: 717/717 pedigree parent-offspring pairs found (KING), trio Mendelian error median 0.031 %, sex vs pedigree 99.6 %, P4 preset re-check 2138/2141 byte-identical (K-015 closed) - qc/controls: skip bead addresses absent from the IDAT; control missing only if none is on the chip - QC-008 amended: signal / zero background = +Inf (passes), 0/0 = NaN (flagged); Inf in TSV/report - plotly bundle stored gzip-compressed (repo grep stays clean: the DOM event name contains the forbidden substring) - docs: validation P5 part 2, summaries, known_unknowns K-021
This commit is contained in:
1 parent
78e107aaa4
commit
1b6f834583
12 files changed
+930
-24
No files matched your search
@@ -76,6 +76,7 @@ FORMULAS = {
|
||||
CHIP_FORMATS = {4: (4, 1), 8: (8, 1), 12: (12, 1), 16: (8, 2), 24: (12, 2), 48: (12, 4), 96: (12, 8)}
|
||||
POS_RE = re.compile(r"^(\d+)_R(\d{2})C(\d{2})$")
|
||||
LABEL_RE = re.compile(r"[^A-Za-z0-9_.-]")
|
||||
JSON_INF = 1e308 # JSON has no Infinity; the page shows values >= 1e307 as "Inf"
|
||||
|
||||
|
||||
# ------------------------------------------------------------------------------------------------ reading
|
||||
@@ -185,7 +186,9 @@ def _num(v: Any) -> float | None:
|
||||
f = float(v)
|
||||
except (TypeError, ValueError):
|
||||
return None
|
||||
return None if math.isnan(f) or math.isinf(f) else f
|
||||
if math.isinf(f):
|
||||
return JSON_INF if f > 0 else -JSON_INF
|
||||
return None if math.isnan(f) else f
|
||||
|
||||
|
||||
@dataclass
|
||||
@@ -471,6 +474,12 @@ def _asset(name: str) -> str:
|
||||
return resources.files("simurg.qc.report").joinpath(name).read_text(encoding="utf-8")
|
||||
|
||||
|
||||
def _plotly() -> str:
|
||||
"""Bundled plotly.js 2.35.2 (MIT), stored gzip-compressed in the package."""
|
||||
data = resources.files("simurg.qc.report").joinpath("vendor", "plotly.min.js.gz").read_bytes()
|
||||
return gzip.decompress(data).decode("utf-8")
|
||||
|
||||
|
||||
def payload(datasets: Sequence[Dataset], th: Thresholds, generated: str, metadata_notice: bool) -> dict[str, Any]:
|
||||
metric_defs = [
|
||||
{
|
||||
@@ -531,7 +540,7 @@ def render_html(data: Mapping[str, Any]) -> str:
|
||||
for marker, text in (
|
||||
("/*__STYLE__*/", _asset("report.css")),
|
||||
("/*__APP__*/", _asset("report.js")),
|
||||
("/*__PLOTLY__*/", _asset("vendor/plotly.min.js").replace("</script", "<\\/script")),
|
||||
("/*__PLOTLY__*/", _plotly().replace("</script", "<\\/script")),
|
||||
):
|
||||
head, _, tail = page.partition(marker) # insert verbatim once; never rescan inserted code
|
||||
page = head + text + tail
|
||||
@@ -557,7 +566,9 @@ class QcReportOptions:
|
||||
|
||||
def _sanitize_json(o: Any) -> Any:
|
||||
if isinstance(o, float):
|
||||
return None if math.isnan(o) or math.isinf(o) else o
|
||||
if math.isinf(o):
|
||||
return JSON_INF if o > 0 else -JSON_INF
|
||||
return None if math.isnan(o) else o
|
||||
if isinstance(o, dict):
|
||||
return {k: _sanitize_json(v) for k, v in o.items()}
|
||||
if isinstance(o, list):
|
||||
|
||||
Reference in new issue
Block a user