3
$\begingroup$

I was trying to use plink in nextflow. My first process will split the input (single bed|bim|fam file) into 22 chromosomes (each with bed|bim|fam files) which would be used in subsequent processes. My code and error log is below. Any help?

params.dir='data/'
params.publish="output2/"
Channel
.fromFilePairs("${params.dir}*.{bed,bim,fam}",size:3)
.set {data}

Channel
.of(1..22)
.set {chr_names}
    
process step1a {
publishDir params.publish
input:
tuple val(sample_name), path(bfiles) from data
output:
tuple val("${prefix}"), path("${prefix}.step1a.{bed,bim,fam}") into step1a_results
tuple val("${prefix}"), path("${prefix}.step1b.{bed,bim,fam}") into step1a_out
tuple val("${prefix}"), path("${prefix}.step1b.bim") into step1a_bims
path("${prefix}.log") into step1a_logs
path("${prefix}.step1a.dupvar") into step1a_duplicates
path("${prefix}.step1a.log") into step1a_log
path("${prefix}.step1b.log") into step1_log
script:
prefix=chr"${chr_names}"
"""
plink --bfile "${sample_name}" --chr "${chr_names}" --out "${prefix}" --make-bed
plink --bfile "${prefix}" --list-duplicate-vars ids-only suppress-first --out "${prefix}.step1a"
plink --bfile "${prefix}" --exclude "${prefix}.step1a.dupvar" --make-bed --out "${prefix}.step1a"
plink --bfile "${prefix}.step1a" --snps-only just-acgt --make-bed --out "${prefix}.step1b"
"""
}
process step1b {
publishDir params.publish
input:
tuple val(sample_name), path(bfiles) from step1a_out
tuple val(bims), path("${prefix}.step1b.bim") from step1a_bims
output:
tuple val("${sample_name}"), path("${sample_name}.step1c.{bed,bim,fam}") into step1b_results
path("${sample_name}.step1c.log") into step1b_logs
path("${sample_name}.step1b.snplist.txt") into step1b_snplist
script:
"""
awk '{ if ((\\\$5=="T" && \\\$6=="A")||(\\\$5=="A" && \\\$6=="T")||(\\\$5=="C" && \\\$6=="G")||(\\\$5=="G" && \\\$6=="C")) print \\\$2, "ambig" ; else print \\\$2 ;}' "${prefix}.step1b.bim" | grep ambig > "${prefix}.step1b.snplist.txt"
plink --bfile "${prefix}.step1b --exclude "${prefix}.step1b.snplist.txt" --make-bed --out "${prefix}.step1c"
"""
}

The error message is:

N E X T F L O W  ~  version 20.10.0
Launching `t4.hf` [zen_picasso] - revision: b0ff8db413
[-        ] process > step1a -
[-        ] process > step1b -
Error executing process > 'step1a (1)'

Caused by:
[-        ] process > step1a -
[-        ] process > step1b -
Error executing process > 'step1a (1)'

Caused by:
  No signature of method: chr() is applicable for argument types: (org.codehaus.groovy.runtime.GStringImpl) values: [DataflowQueue(queue=[DataflowVariable(value=1), DataflowVariable(value=2), DataflowVariable(value=3), DataflowVariable(value=4), DataflowVariable(value=5), DataflowVariable(value=6), DataflowVariable(value=7), DataflowVariable(value=8), DataflowVariable(value=9), DataflowVariable(value=10), DataflowVariable(value=11), DataflowVariable(value=12), DataflowVariable(value=13), DataflowVariable(value=14), DataflowVariable(value=15), DataflowVariable(value=16), DataflowVariable(value=17), DataflowVariable(value=18), DataflowVariable(value=19), DataflowVariable(value=20), DataflowVariable(value=21), DataflowVariable(value=22), DataflowVariable(value=groovyx.gpars.dataflow.operator.PoisonPill@28c22659)])]
Possible solutions: run(), run(), any(), is(java.lang.Object), use([Ljava.lang.Object;), tap(groovy.lang.Closure)

Source block:
  prefix=chr"${chr_names}"
  """
  plink --bfile "${sample_name}" --chr "${chr_names}" --out "${prefix}" --make-bed
  plink --bfile "${prefix}" --list-duplicate-vars ids-only suppress-first --out "${prefix}.step1a"
  plink --bfile "${prefix}" --exclude "${prefix}.step1a.dupvar" --make-bed --out "${prefix}.step1a"
  plink --bfile "${prefix}.step1a" --snps-only just-acgt --make-bed --out "${prefix}.step1b"
  """

Tip: when you have fixed the problem you can continue the execution adding the option `-resume` to the run command line

If I use "prefix=chr"${chr_names}" " inside the code block (""") it shows: unknown variable 'prefix'

$\endgroup$
0

1 Answer 1

4
$\begingroup$

The documation re conditional scripts is useful here:

Process scripts can contain conditional statements by simply prefixing the script block with the keyword script:. By doing that the interpreter will evaluate all the following statements as a code block that must return the script string to be executed.

But the statements don't necessarily need to be conditional. I.e. they can just be declarations like in your example. You get the error 'No signature of Method: chr()' because Nextflow interprets 'chr' as a method call when you use:

prefix = chr"${chr_name}"

If your intention is to simply add the 'chr' prefix to each chromosome name, you'd need:

prefix = "chr${chr_name}"

Notice that I changed your variable name. This is because in your code, you still need to feed in the channel of chromosome names. The easiest way to do this is to use the each qualifier:

process myprocess {

    input:
    tuple val(sample_name), path(bfiles) from plink_data
    each chr_name from chr_names

    script:
    prefix = "chr${chr_name}"

    """
    echo "My sample name is: ${sample_name}"
    echo "My prefixed chromosome name is: ${prefix}"
    """
}

Unless you need chromosome names without the 'chr' prefix, another solution might be to simply add the prefix to each one initially and simply avoid having to prefix them later:

Channel
    .of(1..22)
    .map { "chr${it}" }
    .set { chr_names }
$\endgroup$
14
  • 1
    $\begingroup$ I suspect the problem arises because you've specified two input and output channels ('step1a_out' and 'step1a_bims'). It's not clear to me why you need the two channels, since the 'step1a_bims' looks like a subset of 'step1a_out'? Please see understanding how multiple input channels work $\endgroup$
    – Steve
    Mar 22, 2021 at 12:05
  • 1
    $\begingroup$ Does my answer to your most recent question answer your question? $\endgroup$
    – Steve
    Mar 22, 2021 at 15:37
  • 1
    $\begingroup$ Yes. Thank you. Still wondering how could I declare prefix (characters before first .) as input in the next process which is the output of the previous process. $\endgroup$ Mar 22, 2021 at 16:06
  • 1
    $\begingroup$ No worries at all @zillurrahman. If I understand correctly, the easy way would be to include it in your output tuple as an extra value for your prefix. But if it's already part of (i.e. the prefix) of another value then you could again use the map operator to get it back. Perhaps something like: map { some_name, some_thing -> tuple( some_name.substring(0, some_name.indexOf('.')), some_name, some_thing ) } ? A concrete example would be great if the above doesn't help. $\endgroup$
    – Steve
    Mar 23, 2021 at 1:51
  • 1
    $\begingroup$ Thanks a lot. In that case how can I declare inputs in the next process? If I use step1a_out two time (first for bfiles, and then for bim) I got error Channel 'step1a_out' has been used twice as an input by process 'step1b' $\endgroup$ Mar 23, 2021 at 18:05

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.