Gabi Muir
12/10/2025, 8:15 PMJim Downie
12/10/2025, 9:33 PMinput[0] = channel.of([meta, file])
3. In your nf-test assertions, do you ever do a call on workflow.out.get(0) and thus only pluck the first output entry from the channel in the assertion?Gabi Muir
12/10/2025, 10:05 PMinput[0] = Channel.of(
[
[sample_id: 'boca', single_end: false],
file('test_data/subworkflows/variants_freebayes/bams/boca_typical_accessions.bam', checkIfExists: true),
file('test_data/subworkflows/variants_freebayes/bams/boca_typical_accessions.bam.bai', checkIfExists: true)
],
[
[sample_id: 'fluMP', single_end: false],
file('test_data/subworkflows/variants_freebayes/bams/fluMP_typical_accessions.bam', checkIfExists: true),
file('test_data/subworkflows/variants_freebayes/bams/fluMP_typical_accessions.bam.bai', checkIfExists: true)
]
) // channel from path to bams, one per sample id [meta, bam, bai]
input[1] = Channel.fromPath("test_data/subworkflows/variants_freebayes/refs/typical_accessions.fa", checkIfExists: true) // channel from path to fasta with both references in it
input[2] = Channel.fromPath("test_data/subworkflows/variants_freebayes/refs/typical_accessions.fa.fai", checkIfExists: true) // channel from path to fasta.fai
input[3] = Channel.of(
['PP619522.1', file('test_data/subworkflows/variants_freebayes/snpeff_db_typical_accessions_PP619522.1', checkIfExists: true)],
['NC_012729.2', file('test_data/subworkflows/variants_freebayes/snpeff_db_typical_accessions_NC_012729.2', checkIfExists: true)]
) // channel from path to snpeff dbs, one per reference in fasta
input[4] = Channel.of(
['PP619522.1', file('test_data/subworkflows/variants_freebayes/snpeff_typical_accessions_PP619522.1.config', checkIfExists: true)],
['NC_012729.2', file('test_data/subworkflows/variants_freebayes/snpeff_typical_accessions_NC_012729.2.config', checkIfExists: true)]
) // channel from path to snpeff config/, one per reference in fasta
3. here were my asserts:
// List of all output channels
def channels = [
workflow.out.vcf_orig, // channel: [ val(meta), vcf ]. one per sample
workflow.out.vcf, // channel: [ val(meta), vcf ]. one per sample
workflow.out.tbi, // channel: [ val(meta), tbi ]. one per sample
workflow.out.snpeff_vcf_tbi, // channel: [ val(meta), [ vcf1.gz, vcf2.gz ], [tbi1.gz, tbi2.gz] ]. one channel per sample, one vcf per reference within the channel
workflow.out.snpsift_txt, // channel: [ val(meta), txt ]. one per sample
workflow.out.snpeff_vcf_tbi_concat, // channel: [ val(meta), vcf.gz, tbi]. one per sample.
]
// Each channel exists, is not null, and has 2 items (one per sample), and its files are not empty
channels.each { channel ->
assert channel != null : "Channel ${channel.name} should not be null"
assert channel.size() == 2 : "There should be one channel per sample." // fails here, only 1 for all channels
// tbd, something to check files are not empty
}
so I'm not calling workflow.out.get(0) directlyJim Downie
12/10/2025, 10:34 PM--verbose to see if you can see if (and where) two samples are reduced to one?Gabi Muir
12/11/2025, 4:10 PM--verbose didn't help much, it just output the submitted processes that look just like that trace file. It just didn't even try to use the second item in the channel, nothing was kicked off for that "fluMP" sampleJim Downie
12/11/2025, 4:13 PM--verbose , can you try throwing in some ch_blah.view { "step_x: " + it } statements, see what the contents of channels are, to try and figure out what's going wrong? Possibly a queue channel is being fully consumed when it's meant to be a value channel or something like that?Gabi Muir
12/11/2025, 4:24 PM> bam: [[id:boca.boca, single_end:false], {}/test_data/subworkflows/variants_freebayes/bams/boca_typical_accessions.bam, {}/test_data/subworkflows/variants_freebayes/bams/boca_typical_accessions.bam.bai]
> bam: [[id:fluMP.fluMP, single_end:false], {}/test_data/subworkflows/variants_freebayes/bams/fluMP_typical_accessions.bam, {}/test_data/subworkflows/variants_freebayes/bams/fluMP_typical_accessions.bam.bai]
> [a5/472bb7] Submitted process > VARIANTS_FREEBAYES:FREEBAYES (boca.boca)
> ch_freebayes_vcf: [[id:boca.boca, single_end:false], {}/.nf-test/tests/81e0fe4fbe1cafab1fd5249b228f4b40/work/a5/472bb742f81a28a29f45c50f22a22e/boca.boca.vcf]
> [aa/ab3d4a] Submitted process > VARIANTS_FREEBAYES:BCFTOOLS_SORT (boca.boca)
...Jim Downie
12/11/2025, 4:28 PMJim Downie
12/11/2025, 4:37 PMinput[1] = Channel.fromPath("test_data/subworkflows/variants_freebayes/refs/typical_accessions.fa", checkIfExists: true) // channel from path to fasta with both references in it
input[2] = Channel.fromPath("test_data/subworkflows/variants_freebayes/refs/typical_accessions.fa.fai", checkIfExists: true) // channel from path to fasta.fai
These are queue channels, so the reference will be used up after the first instance.Jim Downie
12/11/2025, 4:38 PM.collect() , or modify the subworkflow to join the reference to the BAM files then split them apart again with .multiMap() to duplicate the channel for each BAMGabi Muir
12/11/2025, 4:47 PMJim Downie
12/11/2025, 4:51 PMinput[1] = Channel.fromPath("test_data/subworkflows/variants_freebayes/refs/typical_accessions.fa", checkIfExists: true).collect()Gabi Muir
12/11/2025, 5:17 PMChannel.fromPath() . This makes a queue channel which is "used up" on the first sample.
The fix: use Channel.fromPath().collect() to force into a value channel, which can be used multiple timesJim Downie
12/11/2025, 5:19 PM