Answers.Body: <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>
  
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2023-06-01T12:18:30.350Z
Answers.Text: 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.
Answers.UserDisplayName: Steve
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2023-06-01T09:21:54.513Z
Answers.LastActivityDate: 2023-06-01T09:21:54.513Z
Answers.UserDisplayName: Toni Verbeiren
Answers.Body: <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>
  
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2023-03-08T16:43:49.000Z
Answers.LastActivityDate: 2023-03-08T16:43:49.000Z
Answers.UserDisplayName: Steve
Body: <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>
  
Tags: <nextflow>
Title: Why does this nextflow script finish after running one sample?
ThreadText: # 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`](https://www.nextflow.io/docs/latest/channel.html#frompath) factory method produces a [queue channel](https://www.nextflow.io/docs/latest/channel.html#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](https://www.nextflow.io/docs/latest/channel.html#value-channel) channels when you require [multiple input channels](https://www.nextflow.io/docs/latest/process.html#process-multiple-input-channels).
  
  You *could* use the [`value`](https://www.nextflow.io/docs/latest/channel.html#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 value[1](https://www.nextflow.io/docs/latest/channel.html#channel-type-value). 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.  
  
  ---
  
  