<p>The code can be made to work on <em>all</em> samples by changing the interface of the process and using the <code>combine</code> operator:</p>
<pre><code>ref_chl = Channel
      .fromPath(&quot;sequences/hg38.fa&quot;)
ref_index_chl = Channel
      .fromPath(&quot;sequences/hg38.fa.fai&quot;)
amplicon_chl = Channel
      .fromPath(&quot;sequences/tp53_amplicon.hg38.interval_list&quot;)
target_chl = Channel
      .fromPath(&quot;sequences/TP53.hg38.interval_list&quot;)

bam_chl = Channel
     .fromPath(&quot;bam_files/*.md.bam&quot;)
     .map{ item -&gt; tuple(item.baseName.substring(0, 18), item) }
     .combine(ref_chl)
     .combine(ref_index_chl)
     .combine(amplicon_chl)
     .combine(target_chl)

process get_pcr_metric {

  publishDir path: 'pcr_metric', pattern: '*.csv'
  
  input:
  tuple val(pair_id), path(bam), path(ref), path(ref_index), path(amplicon), path(target)

  output:
  path(&quot;*.pcr_metrics.csv&quot;)

  &quot;&quot;&quot;
  java -jar /picard.jar CollectTargetedPcrMetrics \
       I=<span class="math-container">$bam \
   O=$</span>{pair_id}_pcr_metrics.txt \
       R=<span class="math-container">$ref \
   AMPLICON_INTERVALS=$</span>amplicon \
       TARGET_INTERVALS=$target
       
  sed -n -e 7p -e 8p <span class="math-container">${pair_id}_pcr_metrics.txt |  sed 's/\t/,/g'   &gt; $</span>{pair_id}.pcr_metrics.csv
  &quot;&quot;&quot;
}

workflow {
  get_pcr_metric(bam_chl)
}
</code></pre>
<p>The <code>combine</code> operator as the name implies generates all combinations. The different file objects are then in one tuple.</p>
<p>Since only one <code>Channel</code> is passed to the process, it's now also possible to rewrite the workflow code as follows:</p>
<pre><code>workflow {

  refs = [
    &quot;sequences/hg38.fa&quot;,
    &quot;sequences/hg38.fa.fai&quot;,
    &quot;sequences/tp53_amplicon.hg38.interval_list&quot;,
    &quot;sequences/TP53.hg38.interval_list&quot;
  ]

  ref_chl = Channel.from(refs)
   | map{ pointer -&gt; file(pointer) }
   | collect

  Channel.fromPath(&quot;bam_files/*.md.bam&quot;)
   | map{ item -&gt; tuple(item.baseName.substring(0, 18), item) }
   | combine( ref_chl )
   | get_pcr_metric

}
</code></pre>

CC BY-SA 4.0
2023-06-01T12:18:30.350Z
You do not need the `combine` operator here: In general, [multiple input channels](https://www.nextflow.io/docs/latest/process.html#process-multiple-input-channels) should be used to process _combinations_ of different inputs, using the `each` qualifier or value channels.
Steve
CC BY-SA 4.0
2023-06-01T09:21:54.513Z
2023-06-01T09:21:54.513Z
Toni Verbeiren
<p>The issue here is that the <a href="https://www.nextflow.io/docs/latest/channel.html#frompath" rel="nofollow noreferrer"><code>fromPath</code></a> factory method produces a <a href="https://www.nextflow.io/docs/latest/channel.html#queue-channel" rel="nofollow noreferrer">queue channel</a>, but you don't want all of your input channels to be queue channels. Most of the time, what you want is one queue channel and one or more <a href="https://www.nextflow.io/docs/latest/channel.html#value-channel" rel="nofollow noreferrer">value</a> channels when you require <a href="https://www.nextflow.io/docs/latest/process.html#process-multiple-input-channels" rel="nofollow noreferrer">multiple input channels</a>.</p>
<p>You <em>could</em> use the <a href="https://www.nextflow.io/docs/latest/channel.html#value" rel="nofollow noreferrer"><code>value</code></a> factory method to create the value channels, but a simpler way is to just pass in some file objects. The latter works because a value channel is implicitly created by a process when it is invoked with a simple value<sup><a href="https://www.nextflow.io/docs/latest/channel.html#channel-type-value" rel="nofollow noreferrer">1</a></sup>. For example:</p>
<pre><code>params.ref_fasta = &quot;./sequences/hg38.fa&quot;
params.amplicon_intervals = &quot;./sequences/tp53_amplicon_intervals.hg38.interval_list&quot;
params.target_intervals = &quot;./sequences/TP53.hg38.interval_list&quot;

params.bam_files = &quot;./bam_files/*.md.bam&quot;
params.outdir = './results'
</code></pre>
<pre><code>process get_pcr_metric {

    publishDir path: &quot;${params.outdir}/pcr_metric&quot;, mode: 'copy'

    input:
    tuple val(pair_id), path(bam_file)
    path ref_fasta
    path amplicon_intervals
    path target_intervals

    output:
    path &quot;${pair_id}_pcr_metrics.txt&quot;

    &quot;&quot;&quot;
    picard CollectTargetedPcrMetrics \\
         I=&quot;<span class="math-container">${bam_file}" \\
         O="$</span>{pair_id}_pcr_metrics.txt&quot; \\
         R=&quot;<span class="math-container">${ref_fasta}" \\
         AMPLICON_INTERVALS="$</span>{amplicon_intervals}&quot; \\
         TARGET_INTERVALS=&quot;${target_intervals}&quot;
    &quot;&quot;&quot;
}
</code></pre>
<pre><code>workflow {

    ref_fasta = file( params.ref_fasta )
    amplicon_intervals = file( params.amplicon_intervals )
    target_intervals = file( params.target_intervals )

    Channel
        .fromPath( params.bam_files )
        .map { tuple( it.getBaseName(2), it ) }
        .set { bam_files }

    get_pcr_metric( bam_files, ref_fasta, amplicon_intervals, target_intervals )
}
</code></pre>

CC BY-SA 4.0
2023-03-08T16:43:49.000Z
2023-03-08T16:43:49.000Z
Steve
<p>I have 36 samples in total in the bam_files folder, with the name like this 20230306_CH_EP_C01.md.bam</p>
<p>I expect the code to output all the 36 samples, one by one. But the run stopped after only running one sample.
I have searched online, but did not find a solution.
I am using nextflow version 2.</p>
<pre><code>bam_chl = Channel
     .fromPath(&quot;bam_files/*.md.bam&quot;)
     .map{ item -&gt; tuple(item.baseName.substring(0, 18), item) }
     

     
ref_chl = Channel
      .fromPath(&quot;sequences/hg38.fa&quot;)
ref_index_chl = Channel
      .fromPath(&quot;sequences/hg38.fa.fai&quot;)
amplicon_chl = Channel
      .fromPath(&quot;sequences/tp53_amplicon.hg38.interval_list&quot;)
target_chl = Channel
      .fromPath(&quot;sequences/TP53.hg38.interval_list&quot;)
     


process get_pcr_metric {

  publishDir path: 'pcr_metric', pattern: '*.csv'
  
  input:
  tuple val(pair_id), path(bam)
  path(ref)
  path(ref_index)
  path(amplicon)
  path(target)

  output:
  path(&quot;*.pcr_metrics.csv&quot;)

  &quot;&quot;&quot;
  java -jar /picard.jar CollectTargetedPcrMetrics \
       I=<span class="math-container">$bam \
   O=$</span>{pair_id}_pcr_metrics.txt \
       R=<span class="math-container">$ref \
   AMPLICON_INTERVALS=$</span>amplicon \
       TARGET_INTERVALS=$target
       
  sed -n -e 7p -e 8p <span class="math-container">${pair_id}_pcr_metrics.txt |  sed 's/\t/,/g'   &gt; $</span>{pair_id}.pcr_metrics.csv
  
  

  &quot;&quot;&quot;


}


workflow {

get_pcr_metric(bam_chl, ref_chl,ref_index_chl, amplicon_chl, target_chl)
}
</code></pre>

<nextflow>
Why does this nextflow script finish after running one sample?
# Why does this nextflow script finish after running one sample?

(Asked by: username_0 on 2023-03-08)

I have 36 samples in total in the bam_files folder, with the name like this 20230306_CH_EP_C01.md.bam
I expect the code to output all the 36 samples, one by one. But the run stopped after only running one sample.
I have searched online, but did not find a solution.
I am using nextflow version 2.
bam_chl = Channel
     .fromPath("bam_files/*.md.bam")
     .map{ item -> tuple(item.baseName.substring(0, 18), item) }
     

     
ref_chl = Channel
      .fromPath("sequences/hg38.fa")
ref_index_chl = Channel
      .fromPath("sequences/hg38.fa.fai")
amplicon_chl = Channel
      .fromPath("sequences/tp53_amplicon.hg38.interval_list")
target_chl = Channel
      .fromPath("sequences/TP53.hg38.interval_list")
     


process get_pcr_metric {

  publishDir path: 'pcr_metric', pattern: '*.csv'
  
  input:
  tuple val(pair_id), path(bam)
  path(ref)
  path(ref_index)
  path(amplicon)
  path(target)

  output:
  path("*.pcr_metrics.csv")

  """
  java -jar /picard.jar CollectTargetedPcrMetrics \
       I=$bam \
   O=${pair_id}_pcr_metrics.txt \
       R=$ref \
   AMPLICON_INTERVALS=$amplicon \
       TARGET_INTERVALS=$target
       
  sed -n -e 7p -e 8p ${pair_id}_pcr_metrics.txt |  sed 's/\t/,/g'   > ${pair_id}.pcr_metrics.csv
  
  

  """


}


workflow {

get_pcr_metric(bam_chl, ref_chl,ref_index_chl, amplicon_chl, target_chl)
}

**Tags:** nextflow

---

## 2 answers

### Answer by username_2 on 2023-03-08. Score: 3 | Accepted answer

The issue here is that the fromPath factory method produces a queue channel, but you don't want all of your input channels to be queue channels. Most of the time, what you want is one queue channel and one or more value channels when you require multiple input channels.
You could use the value factory method to create the value channels, but a simpler way is to just pass in some file objects. The latter works because a value channel is implicitly created by a process when it is invoked with a simple value1. For example:
params.ref_fasta = "./sequences/hg38.fa"
params.amplicon_intervals = "./sequences/tp53_amplicon_intervals.hg38.interval_list"
params.target_intervals = "./sequences/TP53.hg38.interval_list"

params.bam_files = "./bam_files/*.md.bam"
params.outdir = './results'

process get_pcr_metric {

    publishDir path: "${params.outdir}/pcr_metric", mode: 'copy'

    input:
    tuple val(pair_id), path(bam_file)
    path ref_fasta
    path amplicon_intervals
    path target_intervals

    output:
    path "${pair_id}_pcr_metrics.txt"

    """
    picard CollectTargetedPcrMetrics \\
         I="${bam_file}" \\
         O="${pair_id}_pcr_metrics.txt" \\
         R="${ref_fasta}" \\
         AMPLICON_INTERVALS="${amplicon_intervals}" \\
         TARGET_INTERVALS="${target_intervals}"
    """
}

workflow {

    ref_fasta = file( params.ref_fasta )
    amplicon_intervals = file( params.amplicon_intervals )
    target_intervals = file( params.target_intervals )

    Channel
        .fromPath( params.bam_files )
        .map { tuple( it.getBaseName(2), it ) }
        .set { bam_files }

    get_pcr_metric( bam_files, ref_fasta, amplicon_intervals, target_intervals )
}


---

### Answer by username_1 on 2023-06-01. Score: 2

The code can be made to work on all samples by changing the interface of the process and using the combine operator:
ref_chl = Channel
      .fromPath("sequences/hg38.fa")
ref_index_chl = Channel
      .fromPath("sequences/hg38.fa.fai")
amplicon_chl = Channel
      .fromPath("sequences/tp53_amplicon.hg38.interval_list")
target_chl = Channel
      .fromPath("sequences/TP53.hg38.interval_list")

bam_chl = Channel
     .fromPath("bam_files/*.md.bam")
     .map{ item -> tuple(item.baseName.substring(0, 18), item) }
     .combine(ref_chl)
     .combine(ref_index_chl)
     .combine(amplicon_chl)
     .combine(target_chl)

process get_pcr_metric {

  publishDir path: 'pcr_metric', pattern: '*.csv'
  
  input:
  tuple val(pair_id), path(bam), path(ref), path(ref_index), path(amplicon), path(target)

  output:
  path("*.pcr_metrics.csv")

  """
  java -jar /picard.jar CollectTargetedPcrMetrics \
       I=$bam \
   O=${pair_id}_pcr_metrics.txt \
       R=$ref \
   AMPLICON_INTERVALS=$amplicon \
       TARGET_INTERVALS=$target
       
  sed -n -e 7p -e 8p ${pair_id}_pcr_metrics.txt |  sed 's/\t/,/g'   > ${pair_id}.pcr_metrics.csv
  """
}

workflow {
  get_pcr_metric(bam_chl)
}

The combine operator as the name implies generates all combinations. The different file objects are then in one tuple.
Since only one Channel is passed to the process, it's now also possible to rewrite the workflow code as follows:
workflow {

  refs = [
    "sequences/hg38.fa",
    "sequences/hg38.fa.fai",
    "sequences/tp53_amplicon.hg38.interval_list",
    "sequences/TP53.hg38.interval_list"
  ]

  ref_chl = Channel.from(refs)
   | map{ pointer -> file(pointer) }
   | collect

  Channel.fromPath("bam_files/*.md.bam")
   | map{ item -> tuple(item.baseName.substring(0, 18), item) }
   | combine( ref_chl )
   | get_pcr_metric

}

> **Comments:**
> **username_2**: You do not need the `combine` operator here: In general, [multiple input channels](https://www.nextflow.io/docs/latest/process.html#process-multiple-input-channels) should be used to process _combinations_ of different inputs, using the `each` qualifier or value channels.  

---

