P4 validated on 2141 vendor GTCs; legacy AutoCall 1.6.2 preset
- vendor comparison (1000 Genomes Omni2.5, AutoCall 1.6.2.2): every computed field identical in 2138/2141 samples; the 3 others trace back to the single-locus raw-intensity rule (K-009); sex rule 1 matches all - AutoCall 1.6.2.x leaves GC10/GC50/#calls/#no-calls at 0 in GTC v3: new `--preset autocall-1.6.2` (1.1.2 normalization, sex rule 1, GTC v3, legacy statistics); the sample summary keeps the real statistics - NaN sign canonicalised to the x86 pattern (K-014); report P4.md
This commit is contained in:
1 parent
7fb3967c3f
commit
f469c97917
9 files changed
+792
-29
No files matched your search
@@ -37,8 +37,8 @@ ALIGN = (
|
||||
_W: dict[str, Any] = {}
|
||||
|
||||
|
||||
def _init(bpm: str, egt_dir: str, norm: str, sex_version: int) -> None:
|
||||
_W.update(bpm=bpm, egt_dir=egt_dir, norm=norm, sex_version=sex_version, ctx={})
|
||||
def _init(bpm: str, egt_dir: str, norm: str, sex_version: int, preset: str) -> None:
|
||||
_W.update(bpm=bpm, egt_dir=egt_dir, norm=norm, sex_version=sex_version, preset=preset, ctx={})
|
||||
|
||||
|
||||
def _ctx(cluster_field: str) -> Any:
|
||||
@@ -69,7 +69,7 @@ def _canon(a: np.ndarray) -> np.ndarray: # type: ignore[type-arg]
|
||||
def check(args: tuple[str, str, str]) -> dict[str, Any]:
|
||||
from simurg.formats.gtc import encode_gtc, read_gtc
|
||||
from simurg.formats.idat import read_idat
|
||||
from simurg.genotype.sample import GenotypeParams, genotype_sample
|
||||
from simurg.genotype.sample import genotype_sample, params_for_preset
|
||||
from simurg.genotype.sex import SexParams
|
||||
|
||||
gtc, grn, red = args
|
||||
@@ -77,8 +77,12 @@ def check(args: tuple[str, str, str]) -> dict[str, Any]:
|
||||
try:
|
||||
ref = read_gtc(gtc, check_write_complete=False)
|
||||
ctx = _ctx(ref.cluster_file)
|
||||
params = GenotypeParams(
|
||||
norm_version=_W["norm"], sex=SexParams(version=_W["sex_version"]), gtc_version=ref.version
|
||||
params = (
|
||||
params_for_preset(_W["preset"], gtc_version=ref.version)
|
||||
if _W["preset"]
|
||||
else params_for_preset(
|
||||
"current", norm_version=_W["norm"], sex=SexParams(version=_W["sex_version"]), gtc_version=ref.version
|
||||
)
|
||||
)
|
||||
g = genotype_sample(read_idat(grn), read_idat(red), ctx, params)
|
||||
res["cluster_file"] = ctx.cluster_file_name
|
||||
@@ -110,12 +114,13 @@ def check(args: tuple[str, str, str]) -> dict[str, Any]:
|
||||
"ploidy",
|
||||
"ploidy_type",
|
||||
"dx",
|
||||
"slide_identifier",
|
||||
):
|
||||
a, b = getattr(g, k), getattr(ref, k)
|
||||
same = a == b or (isinstance(a, float) and np.isnan(a) and np.isnan(b))
|
||||
if not same:
|
||||
diffs[k] = [repr(a), repr(b)]
|
||||
if ref.version >= 5 and g.slide_identifier != ref.slide_identifier: # field 1016 exists only in v5
|
||||
diffs["slide_identifier"] = [g.slide_identifier, ref.slide_identifier]
|
||||
if "genotype_scores" in diffs:
|
||||
d = np.abs(g.genotype_scores.astype(np.float64) - ref.genotype_scores.astype(np.float64))
|
||||
res["max_score_abs_diff"] = float(np.nanmax(d))
|
||||
@@ -155,6 +160,7 @@ def main() -> int:
|
||||
ap.add_argument("--out", required=True, type=Path)
|
||||
ap.add_argument("--norm-version", default="1.1.2")
|
||||
ap.add_argument("--sex-version", type=int, default=1)
|
||||
ap.add_argument("--preset", default="autocall-1.6.2", help="genotype preset; '' = use --norm/--sex-version")
|
||||
ap.add_argument("--workers", type=int, default=os.cpu_count() or 1)
|
||||
ap.add_argument("--limit", type=int, default=0)
|
||||
a = ap.parse_args()
|
||||
@@ -184,7 +190,7 @@ def main() -> int:
|
||||
a.workers,
|
||||
mp_context=mp.get_context("spawn"),
|
||||
initializer=_init,
|
||||
initargs=(str(a.bpm), str(a.egt_dir), a.norm_version, a.sex_version),
|
||||
initargs=(str(a.bpm), str(a.egt_dir), a.norm_version, a.sex_version, a.preset),
|
||||
) as ex:
|
||||
results = list(ex.map(check, triples, chunksize=2))
|
||||
|
||||
@@ -218,7 +224,7 @@ def main() -> int:
|
||||
},
|
||||
"ref_sex_counts": {s: sum(r.get("sex_ref") == s for r in results) for s in ("M", "F", "U")},
|
||||
"examples": [r for r in results if r.get("field_diffs")][:15],
|
||||
"params": {"norm_version": a.norm_version, "sex_version": a.sex_version},
|
||||
"params": {"preset": a.preset, "norm_version": a.norm_version, "sex_version": a.sex_version},
|
||||
"seconds": round(time.time() - t0, 1),
|
||||
}
|
||||
summary["passed"] = summary["byte_identical"] == len(results) > 0
|
||||
|
||||
Reference in new issue
Block a user