<p>I am not sure if i get what you mean by encapsulate, you can give your tuple a name using emit?</p>
<pre><code>process get_vars {
  output:
    tuple env(var_a), env(var_b), env(var_c), env(var_d), emit: vars

  script:
  '''
  var_a=<span class="math-container">$(echo "1")
  var_b=$</span>(echo &quot;2&quot;)
  var_c=<span class="math-container">$(echo "3")
  var_d=$</span>(echo &quot;4&quot;)
  '''
}

workflow {
  get_vars()
  get_vars.out.vars.view()
}
</code></pre>
<p>That gives:</p>
<pre><code> [1, 2, 3, 4]
</code></pre>

CC BY-SA 4.0
2023-09-21T16:11:06.480Z
If I'm not mistaken, using `emit` (described [in the DSL2 docs](https://www.nextflow.io/docs/latest/dsl2.html#process-named-output)) is to create a separate (named) channel, so I still have to ensure that it keeps the order in sync with other channels, right?
Alexlok
CC BY-SA 4.0
2023-09-21T16:11:45.487Z
Here is an illustration keeping in sync with a main channel:
`process get_vars {
  input:
    val(main_chan)
  output:
    tuple env(var_a), env(var_b), env(var_c), env(var_d), emit: vars
    val(main_chan), emit: main_chan

  shell:
  '''
  var_a=!{main_chan}
  var_b=$((!{main_chan} + 1))
  var_c=$((!{main_chan} + 2))
  var_d=$((!{main_chan} + 3))
  '''
}`

`process next_process {
  input:
    val(vars)
    val(main_chan)
  output:
    tuple(val(vars), val(main_chan))

 script:
 '''
 '''
}`
Alexlok
CC BY-SA 4.0
2023-09-21T16:11:49.847Z
`workflow {
  main_chan = Channel.of( 1, 2, 3 )
  get_vars(main_chan)
  next_process(get_vars.out.vars, get_vars.out.main_chan)
  next_process.out.view()
}`
Alexlok
CC BY-SA 4.0
2023-09-21T16:13:38.790Z
The key here is that `next_process(get_vars.out.vars, get_vars.out.main_chan)` needs to receive *both* channels from the previous process at once. Feel free to include this in your answer if you think it would be relevant
Alexlok
CC BY-SA 4.0
2023-09-21T16:42:16.160Z
I see, you can use a id (like sample-name or meta.id in nfcore) that you include in both channels and then use to join them together into a single channel to make sure that information for one sample moves though the pipeline together.
Niklas
CC BY-SA 4.0
2023-09-21T09:46:05.803Z
2023-09-21T09:46:05.803Z
Niklas
<p>Within a Nextflow workflow, some process runs a shell script that creates multiple variables, e.g.</p>
<pre class="lang-bash prettyprint-override"><code>var_a=$(echo &quot;1&quot;)
var_b=$(echo &quot;2&quot;)
var_c=$(echo &quot;3&quot;)
var_d=$(echo &quot;4&quot;)
</code></pre>
<p>These variables contain statistics (e.g. number of input reads, quality scores, ...) that I want to keep until the end of the pipeline, to then save them and perform QC. So I'd like to export them out of this process and carry them to the end of the workflow. To be clear, the number of variables is not unknown, it's just too many for convenience if I need to list them all every time.</p>
<p>I <a href="https://stackoverflow.com/questions/70862345/how-to-declare-a-new-nextflow-variable-in-a-shell-block">understand</a> that I can use the <code>env</code> qualifier or an intermediate file to export the variables individually:</p>
<pre><code>process get_vars {
  output:
    tuple env(var_a), env(var_b), env(var_c), env(var_d)
  
  shell:
  '''
  var_a=<span class="math-container">$(echo "1")
  var_b=$</span>(echo &quot;2&quot;)
  var_c=<span class="math-container">$(echo "3")
  var_d=$</span>(echo &quot;4&quot;)
  '''
}

workflow{
  get_vars | view
}
</code></pre>
<p>with output:</p>
<pre><code>[ea/a145b4] process &gt; get_vars [100%] 1 of 1 ✔
[1, 2, 3, 4]
</code></pre>
<p>However that becomes very impractical if I have a lot of such variables (that I do want to continue passing along to later processes, along with a much longer tuple of other relevant variables).</p>
<p>My question: is there a convenient way to &quot;encapsulate&quot; all these variables in the output channel, for example with a Groovy map similar to the <code>meta</code> map in <a href="https://nf-co.re/docs/contributing/modules#what-is-the-meta-map" rel="nofollow noreferrer">nf-core</a>? So I could directly write something like:</p>
<pre><code>process get_vars {
  output:
    val(my_vars)
  
  script:
  '''
  var_a=<span class="math-container">$(echo "1")
  var_b=$</span>(echo &quot;2&quot;)
  var_c=<span class="math-container">$(echo "3")
  var_d=$</span>(echo &quot;4&quot;)
  '''
  
  my_vars = [:]
  my_vars.a = var_a
  my_vars.b = var_b
  my_vars.c = var_c
  my_vars.d = var_d
}

workflow{
  get_vars | view
}
</code></pre>
<p>which obviously fails because <code>var_a</code> is not defined outside of the <code>'''</code> block.</p>

CC BY-SA 4.0
2023-09-20T08:16:06.640Z
Can't you simple write all vars to a plain text file and then have some groovy/nf code to loop over the content and pass the it to any data structure that is appropriate, be it a map, list, anything?
ATpoint
CC BY-SA 4.0
2023-09-20T14:23:11.023Z
That does sound like a solution, at least I would only have to pass along a `path`. But that means parsing again a file of variables I have already parsed, which doesn't feel like the most direct approach. If you post it as an answer I would accept it.
Alexlok
CC BY-SA 4.0
2023-09-20T19:27:22.463Z
I think you can use output for this, ouput: env varname, as is mentioned here https://www.nextflow.io/docs/latest/process.html#outputs
Niklas
<nextflow>
Export multiple variables from shell script into a Nextflow output channel
# Export multiple variables from shell script into a Nextflow output channel

(Asked by: username_0 on 2023-09-19)

Within a Nextflow workflow, some process runs a shell script that creates multiple variables, e.g.
var_a=$(echo "1")
var_b=$(echo "2")
var_c=$(echo "3")
var_d=$(echo "4")

These variables contain statistics (e.g. number of input reads, quality scores, ...) that I want to keep until the end of the pipeline, to then save them and perform QC. So I'd like to export them out of this process and carry them to the end of the workflow. To be clear, the number of variables is not unknown, it's just too many for convenience if I need to list them all every time.
I understand that I can use the env qualifier or an intermediate file to export the variables individually:
process get_vars {
  output:
    tuple env(var_a), env(var_b), env(var_c), env(var_d)
  
  shell:
  '''
  var_a=$(echo "1")
  var_b=$(echo "2")
  var_c=$(echo "3")
  var_d=$(echo "4")
  '''
}

workflow{
  get_vars | view
}

with output:
[ea/a145b4] process > get_vars [100%] 1 of 1 ✔
[1, 2, 3, 4]

However that becomes very impractical if I have a lot of such variables (that I do want to continue passing along to later processes, along with a much longer tuple of other relevant variables).
My question: is there a convenient way to "encapsulate" all these variables in the output channel, for example with a Groovy map similar to the meta map in nf-core? So I could directly write something like:
process get_vars {
  output:
    val(my_vars)
  
  script:
  '''
  var_a=$(echo "1")
  var_b=$(echo "2")
  var_c=$(echo "3")
  var_d=$(echo "4")
  '''
  
  my_vars = [:]
  my_vars.a = var_a
  my_vars.b = var_b
  my_vars.c = var_c
  my_vars.d = var_d
}

workflow{
  get_vars | view
}

which obviously fails because var_a is not defined outside of the ''' block.

**Tags:** nextflow
> **Comments:**
> **username_1**: Can't you simple write all vars to a plain text file and then have some groovy/nf code to loop over the content and pass the it to any data structure that is appropriate, be it a map, list, anything?  
> **username_0**: That does sound like a solution, at least I would only have to pass along a `path`. But that means parsing again a file of variables I have already parsed, which doesn't feel like the most direct approach. If you post it as an answer I would accept it.  
> **username_2**: I think you can use output for this, ouput: env varname, as is mentioned here https://www.nextflow.io/docs/latest/process.html#outputs  

---

## 1 answers

### Answer by username_2 on 2023-09-21. Score: 3 | Accepted answer

I am not sure if i get what you mean by encapsulate, you can give your tuple a name using emit?
process get_vars {
  output:
    tuple env(var_a), env(var_b), env(var_c), env(var_d), emit: vars

  script:
  '''
  var_a=$(echo "1")
  var_b=$(echo "2")
  var_c=$(echo "3")
  var_d=$(echo "4")
  '''
}

workflow {
  get_vars()
  get_vars.out.vars.view()
}

That gives:
 [1, 2, 3, 4]

> **Comments:**
> **username_0**: If I'm not mistaken, using `emit` (described [in the DSL2 docs](https://www.nextflow.io/docs/latest/dsl2.html#process-named-output)) is to create a separate (named) channel, so I still have to ensure that it keeps the order in sync with other channels, right?  
> **username_0**: Here is an illustration keeping in sync with a main channel: `process get_vars {   input:     val(main_chan)   output:     tuple env(var_a), env(var_b), env(var_c), env(var_d), emit: vars     val(main_chan), emit: main_chan    shell:   '''   var_a=!{main_chan}   var_b=$((!{main_chan} + 1))   var_c=$((!{main_chan} + 2))   var_d=$((!{main_chan} + 3))   ''' }`  `process next_process {   input:     val(vars)     val(main_chan)   output:     tuple(val(vars), val(main_chan))   script:  '''  ''' }`  
> **username_0**: `workflow {   main_chan = Channel.of( 1, 2, 3 )   get_vars(main_chan)   next_process(get_vars.out.vars, get_vars.out.main_chan)   next_process.out.view() }`  
> **username_0**: The key here is that `next_process(get_vars.out.vars, get_vars.out.main_chan)` needs to receive *both* channels from the previous process at once. Feel free to include this in your answer if you think it would be relevant  
> **username_2**: I see, you can use a id (like sample-name or meta.id in nfcore) that you include in both channels and then use to join them together into a single channel to make sure that information for one sample moves though the pipeline together.  

---

