@@ -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