You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Authorship: the content below was drafted by Claude Opus 5 (an AI coding agent) and
filed via gh under @TimD1-bot, a bot account operated by @TimD1. It reflects the
agent's analysis, not a statement authored by @TimD1.
Part of #47. Splits one output file into two and fixes a long-standing format defect in the same
rewrite.
Change
write_phasing_summary (src/phase.cpp:811, declared src/phase.h:50) splits into write_phasing_variants_summary and write_phasing_blocks_summary.
The split axis is one question: can this quantity be restricted to a subset of variants at all?
Contiguity over genomic span; an NG50 computed over phase blocks intersected with a fragmented subset is not meaningful
The names say per-variant versus per-block rather than "errors" versus "metrics", because #46 adds
non-error columns (phased-variant counts and fractions) to the first file, at which point an -errors- name would be wrong.
Attribution
ctg_pbs->switches[] and flips[] hold query variant indices (src/phase.cpp:618,625;
confirmed by their comparison against variant indices at src/print.cpp:570,574). An error is
attributed to the region sets of that variant, and switchflips.tsv already reports the same index
in its VARIANT column (src/phase.cpp:751,762,783), so the two files agree by construction.
One convention to document: a switch error is localized to the interval between two consecutive
phased variants, and that interval can straddle a boundary. Attributing to the variant is a choice
made for consistency with the existing VARIANT column, not because the interval has a single
correct answer.
VARIANTS is newly exposed
Today it is only a divisor (src/phase.cpp:824-825), computed as sum(qvars->n) over contigs
(src/phase.cpp:655). Per-subset rates are unauditable without the per-subset denominator, so it
becomes a column.
#46 later substitutes ASSESSED_PAIRS — adjacent phaseable-heterozygote pairs per phase block — for
this denominator. The phaseable subset does not exist until #46 marks unphased variants, so this
issue exposes the denominator it actually divides by, under its true name. Both land before rc1, so
no user sees the intermediate.
The rate-format fix
write_phasing_summary currently emits SWITCH_ERROR_RATE/FLIP_ERROR_RATE with %.6f%%
(src/phase.cpp:826, values already scaled by 100 at :824-825) — a string with a trailing
percent sign in a numeric column — and writes its single data row without a terminating newline.
Both are worked around by every consumer today.
The split rewrites this writer anyway, so it emits bare floats as true fractions — 0.00020930, not 0.020930% — and terminates the row.
The column names do not change, so a consumer comparing a pre- and post-split run reads the same
column with values 100x apart. The legacy % sigil is self-describing, so a reader can discriminate
on the value rather than the column name; that is the mitigation, and the change is release-noted.
Out of scope
switchflips.tsv and phase-blocks.tsv stay unstratified — both are interval/event records rather
than variant records, and a phase block spans many subsets. Deferred, not blocked.
Per-subset NG50/NGC50 is explicitly declined, not deferred: these are contiguity metrics over genomic
span, and computed over phase blocks intersected with a fragmented subset they are not meaningful.
Testing
phasing-variants-summary.tsv's * row matches the old file's variant-attributed columns, and phasing-blocks-summary.tsv matches its contiguity columns — the split demonstrably loses nothing.
The rate columns parse as bare floats, and the file ends in a newline.
The current test_phase.cpp contains no write_phasing_summary case, so these writer tests are authored here rather than amended.
Depends on
Per-variant membership. Independent of the precision-recall stratum axis.
Note
Authorship: the content below was drafted by Claude Opus 5 (an AI coding agent) and
filed via
ghunder @TimD1-bot, a bot account operated by @TimD1. It reflects theagent's analysis, not a statement authored by @TimD1.
Part of #47. Splits one output file into two and fixes a long-standing format defect in the same
rewrite.
Change
write_phasing_summary(src/phase.cpp:811, declaredsrc/phase.h:50) splits intowrite_phasing_variants_summaryandwrite_phasing_blocks_summary.The split axis is one question: can this quantity be restricted to a subset of variants at all?
STRATUMphasing-variants-summary.tsvVARIANTS,SWITCH_ERRORS,FLIP_ERRORS,SWITCH_ERROR_RATE,FLIP_ERROR_RATEphasing-blocks-summary.tsvPHASE_BLOCKS,NG_50,SWITCH_NGC50,SWITCHFLIP_NGC50The names say per-variant versus per-block rather than "errors" versus "metrics", because #46 adds
non-error columns (phased-variant counts and fractions) to the first file, at which point an
-errors-name would be wrong.Attribution
ctg_pbs->switches[]andflips[]hold query variant indices (src/phase.cpp:618,625;confirmed by their comparison against variant indices at
src/print.cpp:570,574). An error isattributed to the region sets of that variant, and
switchflips.tsvalready reports the same indexin its
VARIANTcolumn (src/phase.cpp:751,762,783), so the two files agree by construction.One convention to document: a switch error is localized to the interval between two consecutive
phased variants, and that interval can straddle a boundary. Attributing to the variant is a choice
made for consistency with the existing
VARIANTcolumn, not because the interval has a singlecorrect answer.
VARIANTSis newly exposedToday it is only a divisor (
src/phase.cpp:824-825), computed assum(qvars->n)over contigs(
src/phase.cpp:655). Per-subset rates are unauditable without the per-subset denominator, so itbecomes a column.
#46 later substitutes
ASSESSED_PAIRS— adjacent phaseable-heterozygote pairs per phase block — forthis denominator. The phaseable subset does not exist until #46 marks unphased variants, so this
issue exposes the denominator it actually divides by, under its true name. Both land before rc1, so
no user sees the intermediate.
The rate-format fix
write_phasing_summarycurrently emitsSWITCH_ERROR_RATE/FLIP_ERROR_RATEwith%.6f%%(
src/phase.cpp:826, values already scaled by 100 at:824-825) — a string with a trailingpercent sign in a numeric column — and writes its single data row without a terminating newline.
Both are worked around by every consumer today.
The split rewrites this writer anyway, so it emits bare floats as true fractions —
0.00020930, not0.020930%— and terminates the row.The column names do not change, so a consumer comparing a pre- and post-split run reads the same
column with values 100x apart. The legacy
%sigil is self-describing, so a reader can discriminateon the value rather than the column name; that is the mitigation, and the change is release-noted.
Out of scope
switchflips.tsvandphase-blocks.tsvstay unstratified — both are interval/event records ratherthan variant records, and a phase block spans many subsets. Deferred, not blocked.
Per-subset NG50/NGC50 is explicitly declined, not deferred: these are contiguity metrics over genomic
span, and computed over phase blocks intersected with a fragmented subset they are not meaningful.
Testing
phasing-variants-summary.tsv's*row matches the old file's variant-attributed columns, andphasing-blocks-summary.tsvmatches its contiguity columns — the split demonstrably loses nothing.test_phase.cppcontains nowrite_phasing_summarycase, so these writer tests areauthored here rather than amended.
Depends on
Per-variant membership. Independent of the precision-recall stratum axis.