text: user3964: I'm running a custom perl script using Snakemake. I use this rule:
  rule complexity_20mer_counter:
      input:
         os.path.join(fastq_trimmed_dir, '{sample}_{read}' + fastq_extension.split('.')[0] + '_val_' + '{read}'.strip('R') + '.fq.gz')
      output:
          os.path.join(custom_qc_dir, '{sample}_{read}_20mer_counter.txt')
      shell:
          '''
          #!/bin/bash
          perl scripts/20mer_counter.pl {input} > {output}
          '''
  
  It fails (I'll get to why later) with this error:
  Building DAG of jobs...
  MissingInputException in line 1 of /rst1/2017-0205_illuminaseq/scratch/swo-406/2019-01-24/rules/20mer_counter.smk:
  Missing input files for rule complexity_20mer_counter:
  fastq_trimmed/xs0067_P2018SEQE27R01_S1_R1_001_val_R1.fq.gz
  
  ... this is because I use the output of trim_galore, this rule looks like this:
  rule trim_galore:
      input:
         [os.path.join(fastq_raw_dir, '{sample}_'+ read + fastq_extension)
         for read in reads]
      output:
          timmed_fastq_files = [os.path.join(fastq_trimmed_dir, '{sample}_' + read + fastq_extension.split('.')[0] + '_val_' + read.strip('R') + '.fq.gz')
          for read in reads],
          trimming_reports = [os.path.join(trim_galore_qc_dir, '{sample}_'+ read + fastq_extension + '_trimming_report.txt')
          for read in reads]
      conda:
          "../envs/fastqc.yaml"
      shell:
          '''
          #!/bin/bash
          trim_galore --fastqc --gzip -o {fastq_trimmed_dir} --paired --retain_unpaired {input}
          # Move all qc reports to the fastq_trimmed_dir
          mv {fastq_trimmed_dir}/*.zip \
             {fastq_trimmed_dir}/*.html \
             {fastq_trimmed_dir}/*.txt \
             {trim_galore_qc_dir}
          '''
  
  As you can see, trim_galore not only uses my {read} parameter in the output filename but again adds it at the end, only now without the "R".
  I tried solving it in my first rule by applying a python .strip('R') on my {read} wildcard, but this does not seem to work. How can I correctly get '1' and '2' from 'R1' and 'R2' (which are my {read} wildcards)?
  (Extra bonus points for a nice output.trim_galore.something as input for my complexity_20mer_counter rule, which does not work because the output is a list (it needs 2 fastq files at the same time), but my complexity_20mer_counter rule can be run in parallel again.)
  
  user1310: It seems that it is not possible to apply strip() directly on the wildcard placeholders. Luckily it is possible to executed functions in the input directive. 
  So try changing your input of the complexity_20mer_counter rule to this:
  lambda wc: os.path.join(fastq_trimmed_dir, wc.sample + '_' + wc.read + fastq_extension.split('.')[0] + '_val_' + wc.read.strip('R') + '.fq.gz')
  
  The wildcard object is passed to our anonymous function. So have access to the wildcards value via wc.sample and wc.read, which are now handled as normal strings and we can apply strip on them.
  
original_text: 3964: <p>I'm running a custom perl script using Snakemake. I use this rule:</p>
  
  <pre><code>rule complexity_20mer_counter:
      input:
         os.path.join(fastq_trimmed_dir, '{sample}_{read}' + fastq_extension.split('.')[0] + '_val_' + '{read}'.strip('R') + '.fq.gz')
      output:
          os.path.join(custom_qc_dir, '{sample}_{read}_20mer_counter.txt')
      shell:
          '''
          #!/bin/bash
          perl scripts/20mer_counter.pl {input} &gt; {output}
          '''
  </code></pre>
  
  <p>It fails (I'll get to why later) with this error:</p>
  
  <pre><code>Building DAG of jobs...
  MissingInputException in line 1 of /rst1/2017-0205_illuminaseq/scratch/swo-406/2019-01-24/rules/20mer_counter.smk:
  Missing input files for rule complexity_20mer_counter:
  fastq_trimmed/xs0067_P2018SEQE27R01_S1_R1_001_val_R1.fq.gz
  </code></pre>
  
  <p>... this is because I use the output of trim_galore, this rule looks like this:</p>
  
  <pre><code>rule trim_galore:
      input:
         [os.path.join(fastq_raw_dir, '{sample}_'+ read + fastq_extension)
         for read in reads]
      output:
          timmed_fastq_files = [os.path.join(fastq_trimmed_dir, '{sample}_' + read + fastq_extension.split('.')[0] + '_val_' + read.strip('R') + '.fq.gz')
          for read in reads],
          trimming_reports = [os.path.join(trim_galore_qc_dir, '{sample}_'+ read + fastq_extension + '_trimming_report.txt')
          for read in reads]
      conda:
          "../envs/fastqc.yaml"
      shell:
          '''
          #!/bin/bash
          trim_galore --fastqc --gzip -o {fastq_trimmed_dir} --paired --retain_unpaired {input}
          # Move all qc reports to the fastq_trimmed_dir
          mv {fastq_trimmed_dir}/*.zip \
             {fastq_trimmed_dir}/*.html \
             {fastq_trimmed_dir}/*.txt \
             {trim_galore_qc_dir}
          '''
  </code></pre>
  
  <p>As you can see, trim_galore not only uses my {read} parameter in the output filename but again adds it at the end, only now without the "R".</p>
  
  <p>I tried solving it in my first rule by applying a python .strip('R') on my {read} wildcard, but this does not seem to work. How can I correctly get '1' and '2' from 'R1' and 'R2' (which are my {read} wildcards)?</p>
  
  <p>(Extra bonus points for a nice output.trim_galore.something as input for my complexity_20mer_counter rule, which does not work because the output is a list (it needs 2 fastq files at the same time), but my complexity_20mer_counter rule <em>can</em> be run in parallel again.)</p>
   1310: <p>It seems that it is not possible to apply <code>strip()</code> directly on the wildcard placeholders. Luckily it is possible to executed functions in the <code>input</code> directive. </p>
  
  <p>So try changing your input of the <code>complexity_20mer_counter</code> rule to this:</p>
  
  <pre><code>lambda wc: os.path.join(fastq_trimmed_dir, wc.sample + '_' + wc.read + fastq_extension.split('.')[0] + '_val_' + wc.read.strip('R') + '.fq.gz')
  </code></pre>
  
  <p>The wildcard object is passed to our anonymous function. So have access to the wildcards value via <code>wc.sample</code> and <code>wc.read</code>, which are now handled as normal strings and we can apply <code>strip</code> on them.</p>
  