{{ detection.call }}
{% elif detection.detected is false %}
{{ detection.call }}
{% else %}
{{ detection.call }}
{% endif %}
ctDNA VAF
{{ vaf_str }}
p-value (Binomial)
{{ binom_p_str }}
Binom(N={{ detection.n_effective }}, p_err={{ noise_rate_str }})
Sample-specific LOD
{{ lod_str }}
{{ "%.0f"|format(detection.lod_recall * 100) }}% recall · {{ "%.0f"|format(detection.lod_fpr * 100) }}% FPR
Supporting Reads
{{ detection.matched_supporting_reads }}
{% if detection.jeffreys_prior_applied %}
ℹ No background reads observed in synthetic controls — noise rate estimated via Jeffreys prior (p_err = {{ noise_rate_str }}).
{% endif %}
{% if detection.n_synthetic_controls < 20 %}
⚠ Only {{ detection.n_synthetic_controls }} synthetic controls — p-value reliability is reduced.
{% endif %}
{% if detection.qc_checks %}
QC Checks
{% for check in detection.qc_checks %}
{% if check.passed %}✅{% else %}⚠️{% endif %}
{{ check.label }}
{{ check.value_str }}
threshold: {{ check.threshold_str }}
{% endfor %}
{% endif %}
Assay Metrics
Signature Size
{{ "{:,}".format(detection.signature_size) }}
filtered loci
Mean Coverage
{{ "%.1f"|format(detection.mean_coverage) }}×
at signature loci
Corrected Coverage
{{ "{:,.0f}".format(detection.corrected_coverage) }}
effective depth × loci
Coverage Correction Ratio
{{ "%.2f"|format(denom_ratio) }}
corrected / original coverage
Patient vs. Controls
Left plot — Left axis: ctDNA VAF (log scale). Right axis: Signature supporting reads (= VAF × corrected coverage).
★ Patient: matched patient signature.
● Synthetic control signatures: Signatures drawn from db_control.
Blue violin: Fitted Binomial, according to synthetic control error-rates: Binom(N={{ detection.n_effective }}, p_err={{ noise_rate_str }}).
⎯⎯ Detection threshold (min VAF for Binomial p < {{ "%.0f"|format(detection.alpha * 100) }}%).
·–· LOD (min VAF for {{ "%.0f"|format(detection.lod_recall * 100) }}% recall at {{ "%.0f"|format(detection.lod_fpr * 100) }}% FPR).
◆ Cohort control signatures.
{% if sbs6_vaf_plots or sbs96_plots %}
Signature Profile & VAF
{% for img in sbs6_vaf_plots %}
{% endfor %}
{% if sbs96_plots %}
{% for img in sbs96_plots %}
COSMIC-format SBS96 profile from all filtered signature variants.
96 trinucleotide channels grouped by substitution type, normalised to pyrimidine strand.
{% endfor %}
{% endif %}
{% endif %}
{% if intersection_af_img %}
cfDNA Intersection Allele Fraction
Allele-fraction distribution at signature loci with ≥1 supporting cfDNA read.
Red: patient signature loci (signal). Blue: control signature loci (noise).
{% endif %}
{% if read_length_img %}
Read Length Distribution
Read length distribution of cfDNA reads at signature loci (after read filter).
Red: patient signature loci. Blue: control signature loci.
Shorter fragment lengths are enriched in ctDNA due to nucleosomal positioning.
{% endif %}
{% if intersection_snvq_img %}
cfDNA Intersection SNVQ Distribution
SNVQ score distribution of cfDNA reads at signature loci (after read filter).
Red: patient signature loci. Blue: control signature loci.
Higher SNVQ indicates higher confidence in the SNV call.
{% endif %}
{% if lq_fraction_hist_img %}
LQ-Reads Fraction per Locus
Per-locus fraction of reads failing the read filter (LQ reads) for matched signature loci.
Blue: loci kept (LQ fraction ≤ threshold). Red: loci excluded by the noisy-loci filter.
Dashed line: threshold{% if thresh_noise_lq_reads is not none %} ({{ thresh_noise_lq_reads }}){% endif %}.
{% endif %}
{% if supporting_reads_hist_img %}
Alt-Supporting Reads per Variant Locus
Distribution of alt-supporting cfDNA read counts per signature locus (after read filter).
Red: patient loci — signal. Blue: control loci — noise baseline.
Loci with zero supporting reads are not shown; their count is annotated in the plot.
{% endif %}
{% if applied_filters %}
Applied Filters
| Filter | Description |
{% for name, desc in applied_filters.items() %}
| {{ name }} | {{ desc }} |
{% endfor %}
{% endif %}
{% if control_profiles %}
Control Signature Profiles
{% for profile in control_profiles %}
{{ profile.label }}
{% endfor %}
{% endif %}
{% if fragment_length_img %}
cfDNA Fragment Length Distributions
{% endif %}
QC Analysis — Unfiltered Signature
Filtered reads + unfiltered signatures: assesses the impact of signature QC filters.
{% if unfilt_sig_signal_noise_img %}
{% endif %}
{% if unfilt_sig_sbs_vaf_img %}
{% endif %}
{% if unfilt_sig_intersection_img %}
{% endif %}
QC Analysis — Unfiltered Reads
Unfiltered reads + filtered signatures: assesses the impact of read-level QC filters.
{% if unfilt_reads_signal_noise_img %}
{% endif %}
{% if unfilt_reads_sbs_vaf_img %}
{% endif %}
{% if unfilt_reads_intersection_img %}
{% endif %}
{% if noise_filter_comparison %}
QC Analysis — Noisy Loci Filter Sensitivity
Impact of the noisy loci filter
(lq_fraction > {{ noise_filter_comparison.thresh_lq }})
on detection. Loci where more than
{{ "%.0f"|format(noise_filter_comparison.thresh_lq * 100) }}%
of reads fail the read filter
low-quality read(s) are excluded from the primary result.
| Analysis |
Call |
p-value |
Supporting Reads |
ctDNA VAF |
{% for row in [noise_filter_comparison.with_filter, noise_filter_comparison.without_filter] %}
| {{ row.label }} |
{{ row.call }}
|
{{ row.p_str }} |
{{ row.supporting_reads }} |
{{ row.vaf_str }} |
{% endfor %}
{% if noise_filter_comparison.no_noise_signal_img %}
Signal vs Noise — Without noisy loci filter
{% endif %}
{% endif %}
{% if multi_read_filter_comparison %}
QC Analysis — Multi-Read Locus Filter Sensitivity
Impact of the multi-read locus filter (Poisson Bonferroni-corrected p <
{{ multi_read_filter_comparison.thresh_pvalue }}) on detection.
Matched loci whose per-locus HQ supporting-read count is unexpectedly high
given the estimated tumour fraction (λ = TF × mean coverage)
are removed as likely germline or artifact variants.
| Analysis |
Call |
p-value |
Supporting Reads |
ctDNA VAF |
{% for row in [multi_read_filter_comparison.with_filter, multi_read_filter_comparison.without_filter] %}
| {{ row.label }} |
{{ row.call }}
|
{{ row.p_str }} |
{{ row.supporting_reads }} |
{{ row.vaf_str }} |
{% endfor %}
{% if multi_read_filter_comparison.pre_filter_signal_img %}
Signal vs Noise — Without multi-read filter
{% endif %}
{% endif %}