diff --git a/CHANGELOG.md b/CHANGELOG.md index dccde28..9bb3a0c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -25,16 +25,18 @@ Initial release of nf-core/deepmutscan, created with the [nf-core](https://nf-co - DMS library QC per library: count and count-per-coverage heatmaps, sorted count distributions with LogDiff (variants without counts drawn at a floor derived from the data and counted separately; LogDiff not reported when more than 10% of variants have no counts), sliding-window coverage and count profiles (`--sliding_window_size`, `--aimed_cov`), and sequencing-depth rarefaction on a geometric depth grid (`--run_seqdepth`) - Optional fitness estimation (`--fitness`): merged count tables, experimental design, synonymous wildtype proxy selection, default log-ratio fitness with replicate rescaling and summary statistics, replicate correlation plots and fitness heatmap - Optional fitness estimation with DiMSum (`--dimsum`) and mutscan edgeR / limma (`--mutscan`) -- Minimum observation count for a variant to be retained (`--min_counts`, default 1), applied during variant counting; the sequencing-error correction runs on the pre-threshold counts +- Minimum number of reads a variant needs in every `input` replicate to receive a fitness estimate (`--min_counts`, default 10), applied in the same way by the default estimator, DiMSum and mutscan; variant counting, the sequencing-error correction and the library QC always use all reads +- Pseudocount for variants that drop out of an `output` replicate (`--output_pseudocount`, default 1; 0 gives dropouts no fitness value) - Optional interactive 3D variant effect inspection tool built from a user-supplied wildtype structure (`--pdb`) -- Self-contained, all-in-one run report (`deepmutscan_report.html`) embedding QC, error-correction, fitness, MultiQC and run statistics +- Self-contained, all-in-one run report (`deepmutscan_report.html`) embedding QC, error-correction, fitness and MultiQC results, with links to Nextflow's execution report and timeline +- Docker and Singularity images (amd64 and arm64) and conda lock files for all modules, built from each module's `environment.yml`; DiMSum and mutscan are amd64 only for now - `test` profile on a 50,000 read-pair subsample of a GID1A nicking-mutagenesis GluePCA experiment, with three nf-test pipeline tests (all options; without fitness, error correction, SeqDepth and structure; stub run), and `test_full` profile on the complete dataset (ENA PRJEB110196); test data and the PDB structure are hosted on [nf-core/test-datasets](https://github.com/nf-core/test-datasets/tree/deepmutscan) ### `Dependencies` | Dependency | Version | | ------------- | --------------------- | -| `fastqc` | 0.12.1 | +| `fastqc` | 0.13.0 | | `fq` | 0.12.0 | | `multiqc` | 1.35 | | `bwa` | 0.7.19 | diff --git a/assets/summary_report/summary_report_template.html b/assets/summary_report/summary_report_template.html index f528a5d..bc178a9 100644 --- a/assets/summary_report/summary_report_template.html +++ b/assets/summary_report/summary_report_template.html @@ -1319,56 +1319,16 @@ (s) => `${esc(s.id)}${s.ec ? fmt(s.ec.n_variants) : "–"}${s.ec ? fmt(s.ec.total_corrected) : "–"}`, ).join("")}`; - // Run statistics from the Nextflow execution trace (Overview), when it was available. - const RS = (DATA.run || {}).stats; - if (RS && RS.processes && RS.processes.length) { - const dur = (s) => { - s = Math.round(s); - if (s < 60) return s + " s"; - const m = Math.floor(s / 60), - ss = s % 60; - if (m < 60) return m + "m" + (ss ? " " + ss + "s" : ""); - return Math.floor(m / 60) + "h " + (m % 60) + "m"; - }; - const sz = (b) => { - if (!b) return "–"; - const u = ["B", "KB", "MB", "GB", "TB"]; - let i = 0; - while (b >= 1000 && i < u.length - 1) ((b /= 1000), i++); - return (b < 10 ? b.toFixed(1) : Math.round(b)) + " " + u[i]; - }; - const t = RS.total; - h += `

Run statistics ${info( - "Per-process compute from Nextflow's execution trace at report time (excludes this report and the trailing version collation). CPU time sums task runtimes; CACHED tasks reused earlier results.", - )}

`; - h += `
${[ - ["Tasks", fmt(t.tasks)], - ["Cached", fmt(t.cached)], - ["CPU time", dur(t.cpu_time)], - ["Peak memory", sz(t.peak_rss)], - ] - .map(([k, v]) => `
${esc(k)}
${esc(v)}
`) - .join("")}
`; - h += `
${RS.processes - .map( - (p) => - ``, - ) - .join("")}
ProcessTasksCachedCPU timeMean %CPUPeak RSS
${esc(p.process)}${fmt(p.tasks)}${fmt(p.cached)}${dur( - p.cpu_time, - )}${p.cpu_pct == null ? "–" : fmt(p.cpu_pct) + "%"}${sz(p.peak_rss)}
`; - // Straight into Nextflow's own richer report + timeline, which sit next to this file in - // pipeline_info/. Relative links, so they resolve when the report is opened from the results - // folder (the location it is published to). - const sfx = (DATA.run || {}).trace_report_suffix; - if (sfx) - h += `

Nextflow's own outputs, next to this file: execution report ↗ · timeline ↗

`; - h += `
`; - } + // Run statistics: Nextflow's own execution report and timeline, which sit next to this file in + // pipeline_info/. Linked rather than parsed, because the trace is still being written while this + // report is built. Relative links resolve when the report is opened from the results folder. + const sfx = (DATA.run || {}).trace_report_suffix; + if (sfx) + h += `

Run statistics

Task runtimes, CPU and memory usage of this run are in Nextflow's own reports, next to this file: execution report ↗ · timeline ↗

`; // README: what this file is and how it maps onto the results folder. The report is meant as // the way in - a reader should be able to orient here and then find the underlying files. const ec = r.error_correction && r.error_correction !== "none"; diff --git a/docs/output.md b/docs/output.md index 3272267..75b9f4a 100644 --- a/docs/output.md +++ b/docs/output.md @@ -198,7 +198,7 @@ This tool projects the mean per-residue fitness, coverage, counts, counts per co -The report brings all the important metrics and visual results of a run together in one file; it can be opened in any browser and shared without any accompanying files. Features are a complete `nf-core` run overview with parameters and execution statistics, interactive sequencing and library QC plots per library, the error-correction report, the fitness results and heatmap (with `--fitness`), the DiMSum and mutscan results (if run), a 3D structure view (with `--pdb`), the MultiQC report, and the citations of all the tools and major dependencies that were used in the run. +The report brings all the important metrics and visual results of a run together in one file; it can be opened in any browser and shared without any accompanying files. Features are a complete `nf-core` run overview with parameters and links to Nextflow's execution report and timeline, interactive sequencing and library QC plots per library, the error-correction report, the fitness results and heatmap (with `--fitness`), the DiMSum and mutscan results (if run), a 3D structure view (with `--pdb`), the MultiQC report, and the citations of all the tools and major dependencies that were used in the run. ![Run overview](images/run_overview.png) diff --git a/docs/usage.md b/docs/usage.md index 9fe4ad3..76a02af 100644 --- a/docs/usage.md +++ b/docs/usage.md @@ -207,7 +207,7 @@ When `--fitness` is set and a wildtype 3D structure is supplied via `--pdb per-process compute stats - try: - run["stats"] = run_stats(path) - except Exception as exc: # a malformed/partial trace must never sink the whole report - print(f"WARNING: could not parse execution trace: {exc}") # Coverage needed for every residue outcome to reach --aimed_cov counts, assuming all 21 outcomes # are equally represented. Same expression as the reference line in global_position_biases_cov.R; diff --git a/workflows/deepmutscan.nf b/workflows/deepmutscan.nf index 25a4bf7..8cac135 100644 --- a/workflows/deepmutscan.nf +++ b/workflows/deepmutscan.nf @@ -453,14 +453,6 @@ workflow DEEPMUTSCAN { ch_report_assets = ch_report_assets.mix( ch_collated_versions.map { f -> [['versions', 'run', 'versions.yml'], f] } ) - // Nextflow's own execution trace drives the Overview run-statistics table. It is still being - // appended to as the report is built, so it captures every compute-heavy task (all but the report - // task itself) - the page labels it as of report generation. checkIfExists is off because the file - // is engine-managed, not a process output. - ch_report_assets = ch_report_assets.mix( - Channel.fromPath("${outdir}/pipeline_info/execution_trace_${params.trace_report_suffix}.txt", checkIfExists: false) - .map { f -> [['trace', 'run', 'execution_trace.txt'], f] } - ) // Sorting keeps the manifest and the staged files in one deterministic, matching order. def ch_summary_input = ch_report_assets