Skip to content

Commit b7c68ce

Browse files
committed
refactor(mqc): scope single-branch strand channels inside their if/else arm
The strand_*_merged + name_replacements channels were only consumed in the merged MULTIQC input build; strand_*_by_id + ch_per_sample_bundle only in the per-sample build. Move each into the branch that uses it so the reader doesn't have to jump out of the conditional to find a binding's only call site. The shared static config loads stay at top (both branches read them).
1 parent 479af56 commit b7c68ce

1 file changed

Lines changed: 66 additions & 67 deletions

File tree

  • subworkflows/local/multiqc_rnaseq

subworkflows/local/multiqc_rnaseq/main.nf

Lines changed: 66 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -88,69 +88,16 @@ workflow MULTIQC_RNASEQ {
8888
.map { f -> [[:], f] }
8989

9090
//
91-
// Strandedness checks custom-content section. Two MultiQC subsections
92-
// (summary table + stacked composition bargraph) are rendered from
93-
// the same per-sample tuple, with header / pconfig / colour config
94-
// in the bundled YAML templates. The composition section inherits
95-
// `parent_*` from the summary section so the description lives in
96-
// one place.
91+
// Strandedness checks custom-content section. Two MultiQC
92+
// subsections (summary table + stacked composition bargraph) are
93+
// rendered from the same per-sample tuple, with header / pconfig
94+
// / colour config in the bundled YAML templates. The composition
95+
// section inherits `parent_*` from the summary section so the
96+
// description lives in one place.
9797
//
9898
def strand_summary_static = loadMultiqcAsset(strand_summary_asset)
9999
def strand_composition_static = loadMultiqcAsset(strand_composition_asset) + strand_summary_static.subMap(['parent_id', 'parent_name', 'parent_description'])
100100

101-
// `.collect(flat: false)` is silent on an empty channel, so zero
102-
// strand rows -> no *_mqc.json emission -> MultiQC drops the section
103-
// cleanly.
104-
ch_strand_rows = ch_strand_data.collect(flat: false)
105-
106-
ch_strand_summary_merged = ch_strand_rows
107-
.map { rows -> strandCheckSummaryYaml(strand_summary_static, rows) }
108-
.collectFile(name: 'strand_check_summary_mqc.json')
109-
.map { f -> [[:], f] }
110-
111-
ch_strand_summary_by_id = ch_strand_data
112-
.collectFile { row ->
113-
[
114-
"${row[0].id}_strand_check_summary_mqc.json",
115-
strandCheckSummaryYaml(strand_summary_static, [row]),
116-
]
117-
}
118-
.map { f -> [f.baseName.replace('_strand_check_summary_mqc', ''), f] }
119-
120-
ch_strand_composition_merged = ch_strand_rows
121-
.map { rows -> strandCheckCompositionYaml(strand_composition_static, rows) }
122-
.collectFile(name: 'strand_check_composition_mqc.json')
123-
.map { f -> [[:], f] }
124-
125-
ch_strand_composition_by_id = ch_strand_data
126-
.collectFile { row ->
127-
[
128-
"${row[0].id}_strand_check_composition_mqc.json",
129-
strandCheckCompositionYaml(strand_composition_static, [row]),
130-
]
131-
}
132-
.map { f -> [f.baseName.replace('_strand_check_composition_mqc', ''), f] }
133-
134-
//
135-
// Collapse the raw bundle with every per-sample contributor, one
136-
// `.join(remainder: true)` per stream. Each sample becomes
137-
// `[meta, [files]]`; missing streams show up as null entries that
138-
// are filtered out before MULTIQC sees them.
139-
//
140-
ch_per_sample_bundle = ch_per_sample_bundle_raw
141-
.join(ch_fail_trimmed_all.map { meta, f -> [meta.id, f] }, remainder: true)
142-
.join(ch_fail_mapped_all.map { meta, f -> [meta.id, f] }, remainder: true)
143-
.join(ch_strand_summary_by_id, remainder: true)
144-
.join(ch_strand_composition_by_id, remainder: true)
145-
.map { row ->
146-
[
147-
row[1],
148-
row.drop(2)
149-
.findAll { it != null }
150-
.collectMany { entry -> (entry instanceof List) ? entry : [entry] },
151-
]
152-
}
153-
154101
// Per-run table_sample_merge config: only PE samples from the
155102
// samplesheet get their _1 / _2 rows grouped in the General Stats
156103
// table.
@@ -166,20 +113,18 @@ workflow MULTIQC_RNASEQ {
166113
.value(methodsDescriptionText(methods_description_yml))
167114
.collectFile(name: 'methods_description_mqc.yaml')
168115

169-
// --replace-names TSV so MultiQC uses sample IDs rather than FASTQ basenames.
170-
ch_name_replacements = multiqcNameReplacements(ch_fastq)
171-
172116
//
173117
// Two execution modes for MULTIQC:
174118
// - merged (default): one report covers the whole run.
175119
// - per-sample (--skip_quantification_merge): one report per
176120
// sample; workflow-level versions are replaced with a
177-
// pipeline-identity manifest so the report doesn't wait on the
178-
// global versions topic.
121+
// pipeline-identity manifest so the report doesn't wait on
122+
// the global versions topic.
179123
//
180-
// Each branch ends with a tuple matching the MULTIQC input contract
181-
// (id, files, configs, logo, replace_names, extra); the closure
182-
// below builds it so the branches stay focused on file assembly.
124+
// Each branch ends with a tuple matching the MULTIQC input
125+
// contract (id, files, configs, logo, replace_names, extra); the
126+
// closure below builds it so the branches stay focused on file
127+
// assembly.
183128
//
184129
def buildMultiqcInputTuple = { id, files, dynamic_config, replace_names = [] ->
185130
[
@@ -193,6 +138,42 @@ workflow MULTIQC_RNASEQ {
193138
}
194139

195140
if (skip_quantification_merge) {
141+
ch_strand_summary_by_id = ch_strand_data
142+
.collectFile { row ->
143+
[
144+
"${row[0].id}_strand_check_summary_mqc.json",
145+
strandCheckSummaryYaml(strand_summary_static, [row]),
146+
]
147+
}
148+
.map { f -> [f.baseName.replace('_strand_check_summary_mqc', ''), f] }
149+
150+
ch_strand_composition_by_id = ch_strand_data
151+
.collectFile { row ->
152+
[
153+
"${row[0].id}_strand_check_composition_mqc.json",
154+
strandCheckCompositionYaml(strand_composition_static, [row]),
155+
]
156+
}
157+
.map { f -> [f.baseName.replace('_strand_check_composition_mqc', ''), f] }
158+
159+
// Collapse the raw bundle with every per-sample contributor,
160+
// one `.join(remainder: true)` per stream. Each sample becomes
161+
// `[meta, [files]]`; missing streams show up as null entries
162+
// that are filtered out before MULTIQC sees them.
163+
ch_per_sample_bundle = ch_per_sample_bundle_raw
164+
.join(ch_fail_trimmed_all.map { meta, f -> [meta.id, f] }, remainder: true)
165+
.join(ch_fail_mapped_all.map { meta, f -> [meta.id, f] }, remainder: true)
166+
.join(ch_strand_summary_by_id, remainder: true)
167+
.join(ch_strand_composition_by_id, remainder: true)
168+
.map { row ->
169+
[
170+
row[1],
171+
row.drop(2)
172+
.findAll { it != null }
173+
.collectMany { entry -> (entry instanceof List) ? entry : [entry] },
174+
]
175+
}
176+
196177
ch_manifest_versions = channel.value(workflowVersionToYAML())
197178
.collectFile(name: 'nf_core_rnaseq_software_mqc_versions.yml')
198179

@@ -220,6 +201,24 @@ workflow MULTIQC_RNASEQ {
220201
)
221202
}
222203
} else {
204+
// `.collect(flat: false)` is silent on an empty channel, so
205+
// zero strand rows -> no *_mqc.json emission -> MultiQC drops
206+
// the section cleanly.
207+
ch_strand_rows = ch_strand_data.collect(flat: false)
208+
209+
ch_strand_summary_merged = ch_strand_rows
210+
.map { rows -> strandCheckSummaryYaml(strand_summary_static, rows) }
211+
.collectFile(name: 'strand_check_summary_mqc.json')
212+
.map { f -> [[:], f] }
213+
214+
ch_strand_composition_merged = ch_strand_rows
215+
.map { rows -> strandCheckCompositionYaml(strand_composition_static, rows) }
216+
.collectFile(name: 'strand_check_composition_mqc.json')
217+
.map { f -> [[:], f] }
218+
219+
// --replace-names TSV so MultiQC uses sample IDs rather than FASTQ basenames.
220+
ch_name_replacements = multiqcNameReplacements(ch_fastq)
221+
223222
// `multiqc_report` is a sentinel meta.id used by
224223
// conf/modules/multiqc.config to pick the merged output path.
225224
ch_multiqc_files_merged = ch_multiqc_files

0 commit comments

Comments
 (0)