Add brief description to each section in report

This commit is contained in:
Sarah Griffiths 2026-05-27 16:17:22 +00:00
parent 0129592acc
commit e17fec8bc0

View File

@ -650,16 +650,15 @@ def main(args):
with open(args.metadata, "r") as handle:
metadata = json.load(handle)
with report.add_section("Workflow overview", "Overview"):
p(
"This report summarises joint bambu transcript discovery "
"and quantification, per-sample transcriptomes, optional "
"SQANTI3 structural classification, and optional "
"differential analysis outputs."
)
if args.stats:
with report.add_section("Read summary", "Reads"):
p(
"Read quality and alignment statistics generated by fastcat bamstats "
"for each input sample. Shown are distributions of read "
"length and quality score, and a summary of alignment "
"outcomes (mapped, unmapped, primary, supplementary) "
"against the reference genome."
)
stats = tuple(args.stats)
sample_names = tuple(
item["alias"] for item in metadata if item.get("has_stats")
@ -690,6 +689,12 @@ def main(args):
)
with report.add_section("Sample metadata", "Samples"):
p(
"Metadata for each input sample as parsed from the sample sheet "
"and workflow parameters. Includes the sample alias, barcode, "
"type, and any experimental design columns such as condition or "
"batch that were supplied for differential analysis."
)
tabs = Tabs()
for item in sorted(metadata, key=lambda value: value["alias"]):
with tabs.add_tab(item["alias"]):
@ -702,6 +707,10 @@ def main(args):
mod_summaries = _sample_mod_summaries(args.mod_summary_dir)
if mod_summaries is not None and not mod_summaries.empty:
with report.add_section("Modified base summaries", "Modifications"):
p(
"Summary of base modification calls from modkit pileup for each "
"combination of sample and modification type."
)
dom_style(raw(_mod_summary_matrix_style()))
raw(_render_mod_summary_matrix(mod_summaries))
small(raw(
@ -720,6 +729,14 @@ def main(args):
if annotation_reference_summary:
with report.add_section("Reference and Annotation Checks", "Reference"):
p(
"Results of compatibility checks between the supplied reference "
"genome and annotation performed before bambu transcript "
"modelling. "
"Build and provider hints are inferred from sequence names and "
"file content to help identify mismatched genome/annotation "
"combinations."
)
for warning in annotation_reference_summary.get("warnings", []):
_create_warning_banner(warning, level="warning")
@ -819,6 +836,17 @@ def main(args):
# Add Bambu QC section with warnings
if bambu_qc:
with report.add_section("Bambu Quality Control", "Bambu QC"):
p(
"Quality metrics from the bambu transcript discovery and "
"quantification run. Library size statistics show cohort-level "
"summary values to "
"flag large inter-sample variation that could affect CPM "
"normalisation, with the individual per-sample counts listed "
"below. The transcript discovery table shows the transcriptome "
"mode used, the novel discovery rate (NDR) threshold applied, "
"and how many transcripts were present before and after "
"low-count filtering."
)
# Check for warnings
if bambu_qc.get("library_size_warning"):
_create_warning_banner(
@ -939,6 +967,13 @@ def main(args):
f"{primary_label} transcriptome",
f"{primary_label} transcriptome"
):
p(
f"Summary of the "
f"{'per-sample' if is_single_sample else 'joint cohort'} bambu "
"transcriptome model. Shows the total number of transcripts and "
"genes in the final model, and "
f"the top 500 rows of the transcript abundance count table."
)
transcriptome_metrics, transcriptome_classes = _transcriptome_summary(bambu_dir)
if transcriptome_metrics is not None:
DataTable.from_pandas(
@ -972,6 +1007,13 @@ def main(args):
"Per-sample transcriptomes",
"Per-sample transcriptomes"
):
p(
"Per-sample transcript and gene count summaries derived from "
"the individual bambu quantification runs. Each tab shows the "
"number of transcripts and genes detected in that sample after "
"filtering. These can be used to spot samples with unusually "
"low transcript detection compared to the rest of the cohort."
)
tabs = Tabs()
for sample, summary_df in _sample_summaries(args.samples_dir).items():
with tabs.add_tab(sample):
@ -985,7 +1027,14 @@ def main(args):
sqanti_table = _sqanti_table(args.sqanti_dir)
if sqanti_table is not None and not sqanti_table.empty:
with report.add_section("SQANTI3 classification", "SQANTI3"):
p("Summary of structural classification of isoforms using SQANTI3.")
p(
"Structural classification of transcript isoforms by SQANTI3. "
"Each transcript is assigned a category based on how its "
"splice junctions and exon structure compared to the reference "
"annotation. The table shows the count of "
"transcripts in each category per sample and for "
"the whole cohort."
)
DataTable.from_pandas(sqanti_table, use_index=False)
with p():
for category, description in classification_categories.items():
@ -1002,6 +1051,18 @@ def main(args):
"Differential Analysis Quality Control",
"DE/DTU QC",
):
p(
"Quality control summary for the differential expression "
"analyses. Shows the experimental design "
"and the number of samples per group. For each contrast, "
"the statistical methods chosen by DESeq2 and DEXSeq are "
"reported , including the dispersion estimation strategy "
"(parametric or gene-wise fallback) and size factor "
"normalisation method, alongside the analysis status and "
"count of significant hits. Any warnings about low sample "
"numbers, dispersion fallbacks, dropped covariates, or "
"analysis failures are highlighted here."
)
# Check for critical warnings
has_warnings = False
sample_size_warnings = _as_string_list(
@ -1279,6 +1340,16 @@ def main(args):
cohort_samples = _load_cohort_samples(args.cohort_dir)
with report.add_section("Differential gene expression", "DGE"):
p(
"Differential gene expression results from DESeq2. The "
"heatmap, PCA plot, and sample distance matrix are derived "
"from CPM-normalised counts "
"and give an overview of sample clustering relative to "
"the experimental conditions. Each contrast tab shows a "
"results table of genes ranked by adjusted p-value and a "
"volcano plot highlighting significantly up- and "
"down-regulated genes."
)
dom_style(raw(_heatmap_style() + _volcano_style()))
if condition_column:
if cohort_cpm['gene'] is None:
@ -1352,6 +1423,16 @@ def main(args):
EZChart(gn_selected_table, width="100%", height="auto")
with report.add_section("Differential transcript usage", "DTU"):
p(
"Differential transcript usage results from DEXSeq. Unlike "
"DGE, DTU tests whether individual transcripts change their "
"proportional contribution to total gene expression between "
"conditions , i.e. isoform switching , rather than testing "
"for changes in total gene abundance. The heatmap, PCA, and "
"sample distance matrix use CPM-normalised counts. "
"Each contrast tab shows a "
"results table ranked by adjusted p-value and a volcano plot."
)
if condition_column:
if cohort_cpm["transcript"] is None:
_create_warning_banner(