diff --git a/bin/do_it_gz.sh b/bin/do_it_gz.sh deleted file mode 100755 index 05b4097..0000000 --- a/bin/do_it_gz.sh +++ /dev/null @@ -1,77 +0,0 @@ - ############################################################### - # This is HotCount verion 0 # - # # - # released under GNU General Public Licence (see LICENCE.md) # - # # - # # - # # - ############################################################### - -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see . - -# WARNING: doMreps use a slightly modified version of mreps. -# The original version should be downloaded from -# http://mreps.univ-mlv.fr/. -# The aim of the modification was to have a less verbose output to -# accelerate the processing (a more specific output for fastq data) -# -# mreps is released by the author under the GNU GPL licence -# (see LICENCE.md) - -#!/bin/bash -f -version=0.0 -## usage : ./do_it_gz.sh design.txt *.fastq.gz - -d=`date` -echo "## script do_it.sh running in version $version" -echo "## date is $d" - -design=$1; -shift; - -echo -n "Sample" -while read line -do - mut=`echo $line | sed -e s/=\.\*//g` - echo -n " $mut"; -done < $design -echo "" - - -for file in $* -do - - echo -n $file - total=0 - - while read line - do - Forward=`echo $line | sed -e s/\.\*=//g` - Reversed=`echo $Forward | rev` -# echo "1 REVERSE=${Reversed}" - Reversed=`echo $Reversed | tr A W | tr C X | tr G Y | tr T Z` -# echo "2 REVERSE=${Reversed}" - Reversed=`echo $Reversed | sed -e s/\(/V+/g | sed -e s/\+\)/S/g` -# echo "3 REVERSE=${Reversed}" - Reversed=`echo $Reversed | tr W T | tr X G | tr Y C | tr Z A | tr V ")" | tr S "("` -# echo "4 REVERSE=${Reversed}" - nb=$(zgrep -c -E "${Forward}"\|"${Reversed}" $file) -# echo "nb=\$(zgrep -c -E \"${Forward}\"\|\"${Reversed}\" $file)" - echo -n " $nb" -# echo "" - done < $design - - echo "" - -done diff --git a/bin/updated_spothot.py b/bin/updated_spothot.py deleted file mode 100644 index c6b928d..0000000 --- a/bin/updated_spothot.py +++ /dev/null @@ -1,272 +0,0 @@ -#!/usr/bin/python3 - -import sys -import argparse -import configparser -import os.path -import grp -import shutil -import subprocess -import xlsxwriter -import re -import glob - -######################### -### read config file ### -######################### -config_file = "./config_seqcap_v2.ini" -config = configparser.ConfigParser() -config.read(config_file) - -######################### -### functions ### -######################### - -def config_section_map(section, config_obj): - """ - reads a section of the config file and returns it as a dictionary. - raise keyerror if the section does not exist - """ - if section not in config_obj: - raise KeyError(f"Section '{section}' not found in config file.") - return dict(config_obj[section]) - -def read_panel_file(file, paneldictionary): - """ - extract panel and design info from the panellist - """ - with open(file, "r") as f1: - for line in f1: - items = line.rstrip("\n").split("\t") - panel = items[0] - design = items[1] - paneldictionary[panel] = design - return paneldictionary - -def read_runinfo_file(file, paneldictionary, patients, design_query): - """ - Extract all patients from a specific design from HyperCap runinfo file - """ - with open(file, mode = "r") as f2: - for line in f2: - items = line.rstrip("\n").split("\t") - patient = items[0] - first_panel = items[1].split(',')[0] - if paneldictionary[first_panel] == design_query: - patients.append(patient) - return patients - -### user and group asked but nowhere used, can be removed? ### -def count_reads_at_target(crams, outputdir, pos, user, group, samtools, hotcount, pear, log, output, query): - """ - count reads with certain variant/wildtype sequence overlapping a target position - """ - sample_coverage_to_low = [] - - for sample, cram in crams.items(): - ### Log sample that is being processed ### - print(f"\t{sample}") - subprocess.check_output(f"echo\t{sample} >> {log}", stderr=subprocess.STDOUT, shell=True) - ### Defining file paths for intermediate files ### - bam = f"{outputdir}/{sample}_var.bam" - bam_sorted = f"{outputdir}/{sample}_var_sorted.bam" - fq_r1 = f"{outputdir}/{sample}_R1.fastq" - fq_r2 = f"{outputdir}/{sample}_R2.fastq" - fq_p = f"{outputdir}/{sample}_paired" - fq_s = f"{outputdir}/{sample}_singletons.fastq" - fq_all = f"{outputdir}/{sample}_all.fastq.gz" - - ### extract reads from BAM/CRAM ### - subprocess.check_output(f"{samtools} view -T {reference_genome} {cram} {pos} -F 12 -b -o {bam}", stderr=subprocess.STDOUT, shell=True) - subprocess.check_output(f"{samtools} sort -n -o {bam_sorted} {bam}", stderr=subprocess.STDOUT, shell=True) - subprocess.check_output(f"{samtools} fastq -n -1 {fq_r1} -2 {fq_r2} -s {fq_s} {bam_sorted} 2>> {log}", shell=True) - - ### check if file is not empty (otherwise pear goes in ERROR) ### - if os.path.getsize(fq_r1) != 0: - ### merge overlapping read pairs using pear ### - subprocess.check_output(f"{pear} --forward-fastq {fq_r1} --reverse-fastq {fq_r2} --output {fq_p} >> {log}", stderr=subprocess.STDOUT, shell=True) - ### count target sequences in merged/singleton reads ### - subprocess.check_output(f"cat {fq_p}.* {fq_s} | gzip -c > {fq_all}", stderr=subprocess.STDOUT, shell=True) - subprocess.check_output(f"{hotcount} {query} {fq_all} >> {output}", shell=True) - subprocess.check_output(f"rm {bam} {fq_r1} {fq_r2} {fq_p}* {fq_s}", shell=True) - else: - sample_coverage_to_low.append(sample) - subprocess.check_output(f"rm {bam} {fq_r1} {fq_r2} {fq_s}", shell=True) - return sample_coverage_to_low - -def parse_count_output(outp, var_dict): - """ - Extract counts from hotcount output - """ - with open(outp, "r") as f3: - for line in f3: - if line.startswith('/'): - dnanumber = line.split(' ')[0].split('/')[-1].split('_all.fastq')[0] - var_dict[dnanumber] = tuple(line.split(' ')[1:]) - return var_dict - - -################################ -### input parameters ### -################################ - -parser = argparse.ArgumentParser(usage='Usage: python SpotHot.py --run NVQ_828') -parser.add_argument('--run', type=str, required=True, help='run name') -args = parser.parse_args() -run = args.run - -### config sections ### -targeted_variants = config_section_map("targeted_variants", config) -directories = config_section_map("dir", config) -files = config_section_map("files", config) -analysis = config_section_map("analysis", config) -### config keys ### -designs = targeted_variants["designs"] -designs_list = designs.split(',') -panelfile = files["seqcap_panels_file"] -results_dir = f"{directories["documents"]}{directories["results"]}_{analysis["variant_caller"]}" -runinfofile = files["runinfofile"] -bin = directories["bin"] -samtools_path = os.path.expanduser(targeted_variants["samtools"]) -hotcount_path = targeted_variants["hotcount"] -pear_path = os.path.expanduser(targeted_variants["pear"]) -msh2_hotspot_var = targeted_variants["msh2"].split(',') -vaf_detection_treshold = float(targeted_variants["vaf_detection_threshold"]) -reference_genome = files["reference_genome"] - -### error messages ### -if not os.path.exists(results_dir): - print(f'Map "{results_dir}" bestaat niet') - os.makedirs(results_dir) - -if not os.path.exists(runinfofile): - print(f'Bestand "{runinfofile}" bestaat niet') - -### get user and group id ### -user_id = os.getuid() -group_id = grp.getgrnam("seqcap").gr_gid - -### read panel file ### -panel_vs_design = read_panel_file(panelfile, {}) -samples_coverage_to_low = [] - -for designs_plus_gene in designs_list: - ### variables ### - design, rest = designs_plus_gene.split('~') - gene, position = rest.split('/') - hotspot_count = {} - query_list = f"{design}_{gene}.txt" - - ### read runinfo ### - patients_design = read_runinfo_file(runinfofile, panel_vs_design, [], design) - print(f"\n*** Start analyse voor {len(patients_design)} stalen ***") - if patients_design: - ### check output ### - excel_output_sub_dir = f"{results_dir}/{design}_targeted" - if os.path.exists(excel_output_sub_dir): - print(f"-> !!! Opgelet: de map {excel_output_sub_dir} bestond al en wordt overschreven !!!") - shutil.rmtree(excel_output_sub_dir) - if not os.path.exists(excel_output_sub_dir): - os.makedirs(excel_output_sub_dir) - print(f"-> Map \"{excel_output_sub_dir}\" gemaakt") - os.chmod(excel_output_sub_dir, 0o775) - os.chown(excel_output_sub_dir, user_id, group_id) - print(f"-> {len(patients_design)} {design} patienten te analyseren") - ### read variant query file ### - if not os.path.isfile(query_list): - print(f"Error: {gene} variant bestand \"{query_list}\" kon niet worden geopend\n") - sys.exit() - - ### retrieving CRAM files ### - print("-> Ophalen CRAM files") - MAPPING_files = { - patient: cram - for patient in patients_design - for cram in [os.path.abspath(f"{patient}-ready.cram"), - os.path.abspath(f"{patient}-ready.bam")] - if (print(f"Checking {cram}... Exists: {os.path.exists(cram)}") or os.path.exists(cram)) - } - print(MAPPING_files) - if len(MAPPING_files) < len(patients_design): - missing = set(patients_design) - set(MAPPING_files) - print(f"Error: CRAM/BAM files missing for: {', '.join(missing)}") - sys.exit() - ### counting reads with specific target sequences ### - print(f"-> Tellen van reads in positie {gene} {position}:\n") - logfile = f"{excel_output_sub_dir}/{run}_{design}_{gene}_varcount.log" - outputfile = f"{excel_output_sub_dir}/{run}_{design}_{gene}_varcount.txt" - output_excel = f"{results_dir}/{run}_{design}_targeted_{gene}.xlsx" - output_txt = f"{excel_output_sub_dir}/{run}_{design}_targeted_{gene}.txt" - samples_coverage_to_low = count_reads_at_target(MAPPING_files, excel_output_sub_dir, position, user_id, group_id, samtools_path, hotcount_path, pear_path, logfile, outputfile, query_list) - if samples_coverage_to_low: - print(f"\tWARNING: volgende stalen hadden geen coverage in de ROI van de variant: {samples_coverage_to_low}") - hotspot_count = parse_count_output(outputfile, hotspot_count) - - ### Write to excel and txt output file ### - with open(output_txt, "w+") as txt: - workbook = xlsxwriter.Workbook(output_excel) - worksheet = workbook.add_worksheet(f"{design} patienten") - worksheet.set_column('A:B', 16) - worksheet.set_column('C:F', 25) - - format_overview_title = workbook.add_format({'bold': 1, 'font_size': 18, 'font_color': 'black', 'align': 'left'}) - run_overview_format = workbook.add_format({'bold': 1, 'font_size': 14, 'font_color': 'black','bg_color': '#D8D8D8', 'align': 'centre'}) - header_overview_format = workbook.add_format({'bold': 1, 'font_size': 11, 'font_color': 'black', 'bg_color': '#D8D8D8', 'align': 'left'}) - body_overview_format = workbook.add_format({'bold': 0, 'font_size': 11, 'font_color': 'black', 'align': 'left'}) - body_overview_format_bg = workbook.add_format({'bold': 1, 'font_size': 11, 'font_color': 'black', 'bg_color': '#4db8ff', 'align': 'left'}) - - if gene == 'MSH2': - worksheet.write(0, 0, f"Controle van {gene} hotspot varianten {','.join(msh2_hotspot_var)}", format_overview_title) - worksheet.write(1, 0, f"Run {run}", run_overview_format) - worksheet.write(4, 0, "DNA-nummer", header_overview_format) - worksheet.write(4, 1, "WT count", header_overview_format) - my_header = "DNA-nummer\tWT count" - for column, hotspot_var in enumerate(msh2_hotspot_var, start=2): - label = hotspot_var.split(':')[1] if ':' in hotspot_var else hotspot_var - worksheet.write(4, column, f"{label} frequentie (count)", header_overview_format) - my_header += f"\t{label} frequentie (count)" - txt.write(my_header + "\n") - rownum = 5 - - ### sort on 2nd key of tuple, reverse order ### - for patient, my_tuple in sorted(hotspot_count.items(), key=lambda item: int(item[1][1]), reverse=True): - wt, *alt_list = my_tuple - worksheet.write(rownum, 0, patient, body_overview_format) - worksheet.write(rownum, 1, wt, body_overview_format) - my_row = f"{patient}\t{wt}" - for i, hotspot_var in enumerate(msh2_hotspot_var): - colnum = i + 2 - try: - alt = alt_list[i] - frequency = round(float(alt) / (float(alt) + float(wt)) * 100, 2) - if frequency >= vaf_detection_treshold: - freq_str = f"{frequency}({alt}) - Sangeren!" - worksheet.write(rownum, colnum, freq_str, body_overview_format_bg) - else: - worksheet.write(rownum, colnum, f"{frequency}") - my_row += f"\t{frequency}({alt})" - except IndexError: - # If alt_list is too short, write zero - worksheet.write(rownum, colnum, "0", body_overview_format) - my_row += "\t0(0)" - txt.write(my_row + "\n") - rownum += 1 - - for patient in samples_coverage_to_low: - worksheet.write(rownum, 0, patient, body_overview_format) - worksheet.write(rownum, 1, "0", body_overview_format) - my_row = f"{patient}\t0" - for colnum in range(2, 2 + len(msh2_hotspot_var)): - worksheet.write(rownum, colnum, "0", body_overview_format) - my_row += "\t0(0)" - txt.write(my_row + "\n") - rownum += 1 - workbook.close() - txt.close() - os.chmod(output_excel, 0o664) - os.chown(output_excel, user_id, group_id) - os.chmod(output_txt, 0o664) - os.chown(output_txt, user_id, group_id) - print(f"\nDe analyse is afgelopen ({output_excel})\n") - else: - print(f"->Geen patienten aanwezig voor design {design}") diff --git a/conf/igenomes.config b/conf/igenomes.config deleted file mode 100644 index 9fb1aca..0000000 --- a/conf/igenomes.config +++ /dev/null @@ -1,440 +0,0 @@ -/* -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - Nextflow config file for iGenomes paths -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - Defines reference genomes using iGenome paths. - Can be used by any config that customises the base path using: - $params.igenomes_base / --igenomes_base ----------------------------------------------------------------------------------------- -*/ - -params { - // illumina iGenomes reference file paths - genomes { - GRCh37 { - fasta = "${params.igenomes_base}/Homo_sapiens/Ensembl/GRCh37/Sequence/WholeGenomeFasta/genome.fa" - bwa = "${params.igenomes_base}/Homo_sapiens/Ensembl/GRCh37/Sequence/BWAIndex/version0.6.0/" - bowtie2 = "${params.igenomes_base}/Homo_sapiens/Ensembl/GRCh37/Sequence/Bowtie2Index/" - star = "${params.igenomes_base}/Homo_sapiens/Ensembl/GRCh37/Sequence/STARIndex/" - bismark = "${params.igenomes_base}/Homo_sapiens/Ensembl/GRCh37/Sequence/BismarkIndex/" - gtf = "${params.igenomes_base}/Homo_sapiens/Ensembl/GRCh37/Annotation/Genes/genes.gtf" - bed12 = "${params.igenomes_base}/Homo_sapiens/Ensembl/GRCh37/Annotation/Genes/genes.bed" - readme = "${params.igenomes_base}/Homo_sapiens/Ensembl/GRCh37/Annotation/README.txt" - mito_name = "MT" - macs_gsize = "2.7e9" - blacklist = "${projectDir}/assets/blacklists/GRCh37-blacklist.bed" - } - GRCh38 { - fasta = "${params.igenomes_base}/Homo_sapiens/NCBI/GRCh38/Sequence/WholeGenomeFasta/genome.fa" - bwa = "${params.igenomes_base}/Homo_sapiens/NCBI/GRCh38/Sequence/BWAIndex/version0.6.0/" - bowtie2 = "${params.igenomes_base}/Homo_sapiens/NCBI/GRCh38/Sequence/Bowtie2Index/" - star = "${params.igenomes_base}/Homo_sapiens/NCBI/GRCh38/Sequence/STARIndex/" - bismark = "${params.igenomes_base}/Homo_sapiens/NCBI/GRCh38/Sequence/BismarkIndex/" - gtf = "${params.igenomes_base}/Homo_sapiens/NCBI/GRCh38/Annotation/Genes/genes.gtf" - bed12 = "${params.igenomes_base}/Homo_sapiens/NCBI/GRCh38/Annotation/Genes/genes.bed" - mito_name = "chrM" - macs_gsize = "2.7e9" - blacklist = "${projectDir}/assets/blacklists/hg38-blacklist.bed" - } - CHM13 { - fasta = "${params.igenomes_base}/Homo_sapiens/UCSC/CHM13/Sequence/WholeGenomeFasta/genome.fa" - bwa = "${params.igenomes_base}/Homo_sapiens/UCSC/CHM13/Sequence/BWAIndex/" - bwamem2 = "${params.igenomes_base}/Homo_sapiens/UCSC/CHM13/Sequence/BWAmem2Index/" - gtf = "${params.igenomes_base}/Homo_sapiens/NCBI/CHM13/Annotation/Genes/genes.gtf" - gff = "ftp://ftp.ncbi.nlm.nih.gov/genomes/all/GCF/009/914/755/GCF_009914755.1_T2T-CHM13v2.0/GCF_009914755.1_T2T-CHM13v2.0_genomic.gff.gz" - mito_name = "chrM" - } - GRCm38 { - fasta = "${params.igenomes_base}/Mus_musculus/Ensembl/GRCm38/Sequence/WholeGenomeFasta/genome.fa" - bwa = "${params.igenomes_base}/Mus_musculus/Ensembl/GRCm38/Sequence/BWAIndex/version0.6.0/" - bowtie2 = "${params.igenomes_base}/Mus_musculus/Ensembl/GRCm38/Sequence/Bowtie2Index/" - star = "${params.igenomes_base}/Mus_musculus/Ensembl/GRCm38/Sequence/STARIndex/" - bismark = "${params.igenomes_base}/Mus_musculus/Ensembl/GRCm38/Sequence/BismarkIndex/" - gtf = "${params.igenomes_base}/Mus_musculus/Ensembl/GRCm38/Annotation/Genes/genes.gtf" - bed12 = "${params.igenomes_base}/Mus_musculus/Ensembl/GRCm38/Annotation/Genes/genes.bed" - readme = "${params.igenomes_base}/Mus_musculus/Ensembl/GRCm38/Annotation/README.txt" - mito_name = "MT" - macs_gsize = "1.87e9" - blacklist = "${projectDir}/assets/blacklists/GRCm38-blacklist.bed" - } - TAIR10 { - fasta = "${params.igenomes_base}/Arabidopsis_thaliana/Ensembl/TAIR10/Sequence/WholeGenomeFasta/genome.fa" - bwa = "${params.igenomes_base}/Arabidopsis_thaliana/Ensembl/TAIR10/Sequence/BWAIndex/version0.6.0/" - bowtie2 = "${params.igenomes_base}/Arabidopsis_thaliana/Ensembl/TAIR10/Sequence/Bowtie2Index/" - star = "${params.igenomes_base}/Arabidopsis_thaliana/Ensembl/TAIR10/Sequence/STARIndex/" - bismark = "${params.igenomes_base}/Arabidopsis_thaliana/Ensembl/TAIR10/Sequence/BismarkIndex/" - gtf = "${params.igenomes_base}/Arabidopsis_thaliana/Ensembl/TAIR10/Annotation/Genes/genes.gtf" - bed12 = "${params.igenomes_base}/Arabidopsis_thaliana/Ensembl/TAIR10/Annotation/Genes/genes.bed" - readme = "${params.igenomes_base}/Arabidopsis_thaliana/Ensembl/TAIR10/Annotation/README.txt" - mito_name = "Mt" - } - EB2 { - fasta = "${params.igenomes_base}/Bacillus_subtilis_168/Ensembl/EB2/Sequence/WholeGenomeFasta/genome.fa" - bwa = "${params.igenomes_base}/Bacillus_subtilis_168/Ensembl/EB2/Sequence/BWAIndex/version0.6.0/" - bowtie2 = "${params.igenomes_base}/Bacillus_subtilis_168/Ensembl/EB2/Sequence/Bowtie2Index/" - star = "${params.igenomes_base}/Bacillus_subtilis_168/Ensembl/EB2/Sequence/STARIndex/" - bismark = "${params.igenomes_base}/Bacillus_subtilis_168/Ensembl/EB2/Sequence/BismarkIndex/" - gtf = "${params.igenomes_base}/Bacillus_subtilis_168/Ensembl/EB2/Annotation/Genes/genes.gtf" - bed12 = "${params.igenomes_base}/Bacillus_subtilis_168/Ensembl/EB2/Annotation/Genes/genes.bed" - readme = "${params.igenomes_base}/Bacillus_subtilis_168/Ensembl/EB2/Annotation/README.txt" - } - 'UMD3.1' { - fasta = "${params.igenomes_base}/Bos_taurus/Ensembl/UMD3.1/Sequence/WholeGenomeFasta/genome.fa" - bwa = "${params.igenomes_base}/Bos_taurus/Ensembl/UMD3.1/Sequence/BWAIndex/version0.6.0/" - bowtie2 = "${params.igenomes_base}/Bos_taurus/Ensembl/UMD3.1/Sequence/Bowtie2Index/" - star = "${params.igenomes_base}/Bos_taurus/Ensembl/UMD3.1/Sequence/STARIndex/" - bismark = "${params.igenomes_base}/Bos_taurus/Ensembl/UMD3.1/Sequence/BismarkIndex/" - gtf = "${params.igenomes_base}/Bos_taurus/Ensembl/UMD3.1/Annotation/Genes/genes.gtf" - bed12 = "${params.igenomes_base}/Bos_taurus/Ensembl/UMD3.1/Annotation/Genes/genes.bed" - readme = "${params.igenomes_base}/Bos_taurus/Ensembl/UMD3.1/Annotation/README.txt" - mito_name = "MT" - } - WBcel235 { - fasta = "${params.igenomes_base}/Caenorhabditis_elegans/Ensembl/WBcel235/Sequence/WholeGenomeFasta/genome.fa" - bwa = "${params.igenomes_base}/Caenorhabditis_elegans/Ensembl/WBcel235/Sequence/BWAIndex/version0.6.0/" - bowtie2 = "${params.igenomes_base}/Caenorhabditis_elegans/Ensembl/WBcel235/Sequence/Bowtie2Index/" - star = "${params.igenomes_base}/Caenorhabditis_elegans/Ensembl/WBcel235/Sequence/STARIndex/" - bismark = "${params.igenomes_base}/Caenorhabditis_elegans/Ensembl/WBcel235/Sequence/BismarkIndex/" - gtf = "${params.igenomes_base}/Caenorhabditis_elegans/Ensembl/WBcel235/Annotation/Genes/genes.gtf" - bed12 = "${params.igenomes_base}/Caenorhabditis_elegans/Ensembl/WBcel235/Annotation/Genes/genes.bed" - mito_name = "MtDNA" - macs_gsize = "9e7" - } - 'CanFam3.1' { - fasta = "${params.igenomes_base}/Canis_familiaris/Ensembl/CanFam3.1/Sequence/WholeGenomeFasta/genome.fa" - bwa = "${params.igenomes_base}/Canis_familiaris/Ensembl/CanFam3.1/Sequence/BWAIndex/version0.6.0/" - bowtie2 = "${params.igenomes_base}/Canis_familiaris/Ensembl/CanFam3.1/Sequence/Bowtie2Index/" - star = "${params.igenomes_base}/Canis_familiaris/Ensembl/CanFam3.1/Sequence/STARIndex/" - bismark = "${params.igenomes_base}/Canis_familiaris/Ensembl/CanFam3.1/Sequence/BismarkIndex/" - gtf = "${params.igenomes_base}/Canis_familiaris/Ensembl/CanFam3.1/Annotation/Genes/genes.gtf" - bed12 = "${params.igenomes_base}/Canis_familiaris/Ensembl/CanFam3.1/Annotation/Genes/genes.bed" - readme = "${params.igenomes_base}/Canis_familiaris/Ensembl/CanFam3.1/Annotation/README.txt" - mito_name = "MT" - } - GRCz10 { - fasta = "${params.igenomes_base}/Danio_rerio/Ensembl/GRCz10/Sequence/WholeGenomeFasta/genome.fa" - bwa = "${params.igenomes_base}/Danio_rerio/Ensembl/GRCz10/Sequence/BWAIndex/version0.6.0/" - bowtie2 = "${params.igenomes_base}/Danio_rerio/Ensembl/GRCz10/Sequence/Bowtie2Index/" - star = "${params.igenomes_base}/Danio_rerio/Ensembl/GRCz10/Sequence/STARIndex/" - bismark = "${params.igenomes_base}/Danio_rerio/Ensembl/GRCz10/Sequence/BismarkIndex/" - gtf = "${params.igenomes_base}/Danio_rerio/Ensembl/GRCz10/Annotation/Genes/genes.gtf" - bed12 = "${params.igenomes_base}/Danio_rerio/Ensembl/GRCz10/Annotation/Genes/genes.bed" - mito_name = "MT" - } - BDGP6 { - fasta = "${params.igenomes_base}/Drosophila_melanogaster/Ensembl/BDGP6/Sequence/WholeGenomeFasta/genome.fa" - bwa = "${params.igenomes_base}/Drosophila_melanogaster/Ensembl/BDGP6/Sequence/BWAIndex/version0.6.0/" - bowtie2 = "${params.igenomes_base}/Drosophila_melanogaster/Ensembl/BDGP6/Sequence/Bowtie2Index/" - star = "${params.igenomes_base}/Drosophila_melanogaster/Ensembl/BDGP6/Sequence/STARIndex/" - bismark = "${params.igenomes_base}/Drosophila_melanogaster/Ensembl/BDGP6/Sequence/BismarkIndex/" - gtf = "${params.igenomes_base}/Drosophila_melanogaster/Ensembl/BDGP6/Annotation/Genes/genes.gtf" - bed12 = "${params.igenomes_base}/Drosophila_melanogaster/Ensembl/BDGP6/Annotation/Genes/genes.bed" - mito_name = "M" - macs_gsize = "1.2e8" - } - EquCab2 { - fasta = "${params.igenomes_base}/Equus_caballus/Ensembl/EquCab2/Sequence/WholeGenomeFasta/genome.fa" - bwa = "${params.igenomes_base}/Equus_caballus/Ensembl/EquCab2/Sequence/BWAIndex/version0.6.0/" - bowtie2 = "${params.igenomes_base}/Equus_caballus/Ensembl/EquCab2/Sequence/Bowtie2Index/" - star = "${params.igenomes_base}/Equus_caballus/Ensembl/EquCab2/Sequence/STARIndex/" - bismark = "${params.igenomes_base}/Equus_caballus/Ensembl/EquCab2/Sequence/BismarkIndex/" - gtf = "${params.igenomes_base}/Equus_caballus/Ensembl/EquCab2/Annotation/Genes/genes.gtf" - bed12 = "${params.igenomes_base}/Equus_caballus/Ensembl/EquCab2/Annotation/Genes/genes.bed" - readme = "${params.igenomes_base}/Equus_caballus/Ensembl/EquCab2/Annotation/README.txt" - mito_name = "MT" - } - EB1 { - fasta = "${params.igenomes_base}/Escherichia_coli_K_12_DH10B/Ensembl/EB1/Sequence/WholeGenomeFasta/genome.fa" - bwa = "${params.igenomes_base}/Escherichia_coli_K_12_DH10B/Ensembl/EB1/Sequence/BWAIndex/version0.6.0/" - bowtie2 = "${params.igenomes_base}/Escherichia_coli_K_12_DH10B/Ensembl/EB1/Sequence/Bowtie2Index/" - star = "${params.igenomes_base}/Escherichia_coli_K_12_DH10B/Ensembl/EB1/Sequence/STARIndex/" - bismark = "${params.igenomes_base}/Escherichia_coli_K_12_DH10B/Ensembl/EB1/Sequence/BismarkIndex/" - gtf = "${params.igenomes_base}/Escherichia_coli_K_12_DH10B/Ensembl/EB1/Annotation/Genes/genes.gtf" - bed12 = "${params.igenomes_base}/Escherichia_coli_K_12_DH10B/Ensembl/EB1/Annotation/Genes/genes.bed" - readme = "${params.igenomes_base}/Escherichia_coli_K_12_DH10B/Ensembl/EB1/Annotation/README.txt" - } - Galgal4 { - fasta = "${params.igenomes_base}/Gallus_gallus/Ensembl/Galgal4/Sequence/WholeGenomeFasta/genome.fa" - bwa = "${params.igenomes_base}/Gallus_gallus/Ensembl/Galgal4/Sequence/BWAIndex/version0.6.0/" - bowtie2 = "${params.igenomes_base}/Gallus_gallus/Ensembl/Galgal4/Sequence/Bowtie2Index/" - star = "${params.igenomes_base}/Gallus_gallus/Ensembl/Galgal4/Sequence/STARIndex/" - bismark = "${params.igenomes_base}/Gallus_gallus/Ensembl/Galgal4/Sequence/BismarkIndex/" - gtf = "${params.igenomes_base}/Gallus_gallus/Ensembl/Galgal4/Annotation/Genes/genes.gtf" - bed12 = "${params.igenomes_base}/Gallus_gallus/Ensembl/Galgal4/Annotation/Genes/genes.bed" - mito_name = "MT" - } - Gm01 { - fasta = "${params.igenomes_base}/Glycine_max/Ensembl/Gm01/Sequence/WholeGenomeFasta/genome.fa" - bwa = "${params.igenomes_base}/Glycine_max/Ensembl/Gm01/Sequence/BWAIndex/version0.6.0/" - bowtie2 = "${params.igenomes_base}/Glycine_max/Ensembl/Gm01/Sequence/Bowtie2Index/" - star = "${params.igenomes_base}/Glycine_max/Ensembl/Gm01/Sequence/STARIndex/" - bismark = "${params.igenomes_base}/Glycine_max/Ensembl/Gm01/Sequence/BismarkIndex/" - gtf = "${params.igenomes_base}/Glycine_max/Ensembl/Gm01/Annotation/Genes/genes.gtf" - bed12 = "${params.igenomes_base}/Glycine_max/Ensembl/Gm01/Annotation/Genes/genes.bed" - readme = "${params.igenomes_base}/Glycine_max/Ensembl/Gm01/Annotation/README.txt" - } - Mmul_1 { - fasta = "${params.igenomes_base}/Macaca_mulatta/Ensembl/Mmul_1/Sequence/WholeGenomeFasta/genome.fa" - bwa = "${params.igenomes_base}/Macaca_mulatta/Ensembl/Mmul_1/Sequence/BWAIndex/version0.6.0/" - bowtie2 = "${params.igenomes_base}/Macaca_mulatta/Ensembl/Mmul_1/Sequence/Bowtie2Index/" - star = "${params.igenomes_base}/Macaca_mulatta/Ensembl/Mmul_1/Sequence/STARIndex/" - bismark = "${params.igenomes_base}/Macaca_mulatta/Ensembl/Mmul_1/Sequence/BismarkIndex/" - gtf = "${params.igenomes_base}/Macaca_mulatta/Ensembl/Mmul_1/Annotation/Genes/genes.gtf" - bed12 = "${params.igenomes_base}/Macaca_mulatta/Ensembl/Mmul_1/Annotation/Genes/genes.bed" - readme = "${params.igenomes_base}/Macaca_mulatta/Ensembl/Mmul_1/Annotation/README.txt" - mito_name = "MT" - } - 'IRGSP-1.0' { - fasta = "${params.igenomes_base}/Oryza_sativa_japonica/Ensembl/IRGSP-1.0/Sequence/WholeGenomeFasta/genome.fa" - bwa = "${params.igenomes_base}/Oryza_sativa_japonica/Ensembl/IRGSP-1.0/Sequence/BWAIndex/version0.6.0/" - bowtie2 = "${params.igenomes_base}/Oryza_sativa_japonica/Ensembl/IRGSP-1.0/Sequence/Bowtie2Index/" - star = "${params.igenomes_base}/Oryza_sativa_japonica/Ensembl/IRGSP-1.0/Sequence/STARIndex/" - bismark = "${params.igenomes_base}/Oryza_sativa_japonica/Ensembl/IRGSP-1.0/Sequence/BismarkIndex/" - gtf = "${params.igenomes_base}/Oryza_sativa_japonica/Ensembl/IRGSP-1.0/Annotation/Genes/genes.gtf" - bed12 = "${params.igenomes_base}/Oryza_sativa_japonica/Ensembl/IRGSP-1.0/Annotation/Genes/genes.bed" - mito_name = "Mt" - } - 'CHIMP2.1.4' { - fasta = "${params.igenomes_base}/Pan_troglodytes/Ensembl/CHIMP2.1.4/Sequence/WholeGenomeFasta/genome.fa" - bwa = "${params.igenomes_base}/Pan_troglodytes/Ensembl/CHIMP2.1.4/Sequence/BWAIndex/version0.6.0/" - bowtie2 = "${params.igenomes_base}/Pan_troglodytes/Ensembl/CHIMP2.1.4/Sequence/Bowtie2Index/" - star = "${params.igenomes_base}/Pan_troglodytes/Ensembl/CHIMP2.1.4/Sequence/STARIndex/" - bismark = "${params.igenomes_base}/Pan_troglodytes/Ensembl/CHIMP2.1.4/Sequence/BismarkIndex/" - gtf = "${params.igenomes_base}/Pan_troglodytes/Ensembl/CHIMP2.1.4/Annotation/Genes/genes.gtf" - bed12 = "${params.igenomes_base}/Pan_troglodytes/Ensembl/CHIMP2.1.4/Annotation/Genes/genes.bed" - readme = "${params.igenomes_base}/Pan_troglodytes/Ensembl/CHIMP2.1.4/Annotation/README.txt" - mito_name = "MT" - } - 'Rnor_5.0' { - fasta = "${params.igenomes_base}/Rattus_norvegicus/Ensembl/Rnor_5.0/Sequence/WholeGenomeFasta/genome.fa" - bwa = "${params.igenomes_base}/Rattus_norvegicus/Ensembl/Rnor_5.0/Sequence/BWAIndex/version0.6.0/" - bowtie2 = "${params.igenomes_base}/Rattus_norvegicus/Ensembl/Rnor_5.0/Sequence/Bowtie2Index/" - star = "${params.igenomes_base}/Rattus_norvegicus/Ensembl/Rnor_5.0/Sequence/STARIndex/" - bismark = "${params.igenomes_base}/Rattus_norvegicus/Ensembl/Rnor_5.0/Sequence/BismarkIndex/" - gtf = "${params.igenomes_base}/Rattus_norvegicus/Ensembl/Rnor_5.0/Annotation/Genes/genes.gtf" - bed12 = "${params.igenomes_base}/Rattus_norvegicus/Ensembl/Rnor_5.0/Annotation/Genes/genes.bed" - mito_name = "MT" - } - 'Rnor_6.0' { - fasta = "${params.igenomes_base}/Rattus_norvegicus/Ensembl/Rnor_6.0/Sequence/WholeGenomeFasta/genome.fa" - bwa = "${params.igenomes_base}/Rattus_norvegicus/Ensembl/Rnor_6.0/Sequence/BWAIndex/version0.6.0/" - bowtie2 = "${params.igenomes_base}/Rattus_norvegicus/Ensembl/Rnor_6.0/Sequence/Bowtie2Index/" - star = "${params.igenomes_base}/Rattus_norvegicus/Ensembl/Rnor_6.0/Sequence/STARIndex/" - bismark = "${params.igenomes_base}/Rattus_norvegicus/Ensembl/Rnor_6.0/Sequence/BismarkIndex/" - gtf = "${params.igenomes_base}/Rattus_norvegicus/Ensembl/Rnor_6.0/Annotation/Genes/genes.gtf" - bed12 = "${params.igenomes_base}/Rattus_norvegicus/Ensembl/Rnor_6.0/Annotation/Genes/genes.bed" - mito_name = "MT" - } - 'R64-1-1' { - fasta = "${params.igenomes_base}/Saccharomyces_cerevisiae/Ensembl/R64-1-1/Sequence/WholeGenomeFasta/genome.fa" - bwa = "${params.igenomes_base}/Saccharomyces_cerevisiae/Ensembl/R64-1-1/Sequence/BWAIndex/version0.6.0/" - bowtie2 = "${params.igenomes_base}/Saccharomyces_cerevisiae/Ensembl/R64-1-1/Sequence/Bowtie2Index/" - star = "${params.igenomes_base}/Saccharomyces_cerevisiae/Ensembl/R64-1-1/Sequence/STARIndex/" - bismark = "${params.igenomes_base}/Saccharomyces_cerevisiae/Ensembl/R64-1-1/Sequence/BismarkIndex/" - gtf = "${params.igenomes_base}/Saccharomyces_cerevisiae/Ensembl/R64-1-1/Annotation/Genes/genes.gtf" - bed12 = "${params.igenomes_base}/Saccharomyces_cerevisiae/Ensembl/R64-1-1/Annotation/Genes/genes.bed" - mito_name = "MT" - macs_gsize = "1.2e7" - } - EF2 { - fasta = "${params.igenomes_base}/Schizosaccharomyces_pombe/Ensembl/EF2/Sequence/WholeGenomeFasta/genome.fa" - bwa = "${params.igenomes_base}/Schizosaccharomyces_pombe/Ensembl/EF2/Sequence/BWAIndex/version0.6.0/" - bowtie2 = "${params.igenomes_base}/Schizosaccharomyces_pombe/Ensembl/EF2/Sequence/Bowtie2Index/" - star = "${params.igenomes_base}/Schizosaccharomyces_pombe/Ensembl/EF2/Sequence/STARIndex/" - bismark = "${params.igenomes_base}/Schizosaccharomyces_pombe/Ensembl/EF2/Sequence/BismarkIndex/" - gtf = "${params.igenomes_base}/Schizosaccharomyces_pombe/Ensembl/EF2/Annotation/Genes/genes.gtf" - bed12 = "${params.igenomes_base}/Schizosaccharomyces_pombe/Ensembl/EF2/Annotation/Genes/genes.bed" - readme = "${params.igenomes_base}/Schizosaccharomyces_pombe/Ensembl/EF2/Annotation/README.txt" - mito_name = "MT" - macs_gsize = "1.21e7" - } - Sbi1 { - fasta = "${params.igenomes_base}/Sorghum_bicolor/Ensembl/Sbi1/Sequence/WholeGenomeFasta/genome.fa" - bwa = "${params.igenomes_base}/Sorghum_bicolor/Ensembl/Sbi1/Sequence/BWAIndex/version0.6.0/" - bowtie2 = "${params.igenomes_base}/Sorghum_bicolor/Ensembl/Sbi1/Sequence/Bowtie2Index/" - star = "${params.igenomes_base}/Sorghum_bicolor/Ensembl/Sbi1/Sequence/STARIndex/" - bismark = "${params.igenomes_base}/Sorghum_bicolor/Ensembl/Sbi1/Sequence/BismarkIndex/" - gtf = "${params.igenomes_base}/Sorghum_bicolor/Ensembl/Sbi1/Annotation/Genes/genes.gtf" - bed12 = "${params.igenomes_base}/Sorghum_bicolor/Ensembl/Sbi1/Annotation/Genes/genes.bed" - readme = "${params.igenomes_base}/Sorghum_bicolor/Ensembl/Sbi1/Annotation/README.txt" - } - 'Sscrofa10.2' { - fasta = "${params.igenomes_base}/Sus_scrofa/Ensembl/Sscrofa10.2/Sequence/WholeGenomeFasta/genome.fa" - bwa = "${params.igenomes_base}/Sus_scrofa/Ensembl/Sscrofa10.2/Sequence/BWAIndex/version0.6.0/" - bowtie2 = "${params.igenomes_base}/Sus_scrofa/Ensembl/Sscrofa10.2/Sequence/Bowtie2Index/" - star = "${params.igenomes_base}/Sus_scrofa/Ensembl/Sscrofa10.2/Sequence/STARIndex/" - bismark = "${params.igenomes_base}/Sus_scrofa/Ensembl/Sscrofa10.2/Sequence/BismarkIndex/" - gtf = "${params.igenomes_base}/Sus_scrofa/Ensembl/Sscrofa10.2/Annotation/Genes/genes.gtf" - bed12 = "${params.igenomes_base}/Sus_scrofa/Ensembl/Sscrofa10.2/Annotation/Genes/genes.bed" - readme = "${params.igenomes_base}/Sus_scrofa/Ensembl/Sscrofa10.2/Annotation/README.txt" - mito_name = "MT" - } - AGPv3 { - fasta = "${params.igenomes_base}/Zea_mays/Ensembl/AGPv3/Sequence/WholeGenomeFasta/genome.fa" - bwa = "${params.igenomes_base}/Zea_mays/Ensembl/AGPv3/Sequence/BWAIndex/version0.6.0/" - bowtie2 = "${params.igenomes_base}/Zea_mays/Ensembl/AGPv3/Sequence/Bowtie2Index/" - star = "${params.igenomes_base}/Zea_mays/Ensembl/AGPv3/Sequence/STARIndex/" - bismark = "${params.igenomes_base}/Zea_mays/Ensembl/AGPv3/Sequence/BismarkIndex/" - gtf = "${params.igenomes_base}/Zea_mays/Ensembl/AGPv3/Annotation/Genes/genes.gtf" - bed12 = "${params.igenomes_base}/Zea_mays/Ensembl/AGPv3/Annotation/Genes/genes.bed" - mito_name = "Mt" - } - hg38 { - fasta = "${params.igenomes_base}/Homo_sapiens/UCSC/hg38/Sequence/WholeGenomeFasta/genome.fa" - bwa = "${params.igenomes_base}/Homo_sapiens/UCSC/hg38/Sequence/BWAIndex/version0.6.0/" - bowtie2 = "${params.igenomes_base}/Homo_sapiens/UCSC/hg38/Sequence/Bowtie2Index/" - star = "${params.igenomes_base}/Homo_sapiens/UCSC/hg38/Sequence/STARIndex/" - bismark = "${params.igenomes_base}/Homo_sapiens/UCSC/hg38/Sequence/BismarkIndex/" - gtf = "${params.igenomes_base}/Homo_sapiens/UCSC/hg38/Annotation/Genes/genes.gtf" - bed12 = "${params.igenomes_base}/Homo_sapiens/UCSC/hg38/Annotation/Genes/genes.bed" - mito_name = "chrM" - macs_gsize = "2.7e9" - blacklist = "${projectDir}/assets/blacklists/hg38-blacklist.bed" - } - hg19 { - fasta = "${params.igenomes_base}/Homo_sapiens/UCSC/hg19/Sequence/WholeGenomeFasta/genome.fa" - bwa = "${params.igenomes_base}/Homo_sapiens/UCSC/hg19/Sequence/BWAIndex/version0.6.0/" - bowtie2 = "${params.igenomes_base}/Homo_sapiens/UCSC/hg19/Sequence/Bowtie2Index/" - star = "${params.igenomes_base}/Homo_sapiens/UCSC/hg19/Sequence/STARIndex/" - bismark = "${params.igenomes_base}/Homo_sapiens/UCSC/hg19/Sequence/BismarkIndex/" - gtf = "${params.igenomes_base}/Homo_sapiens/UCSC/hg19/Annotation/Genes/genes.gtf" - bed12 = "${params.igenomes_base}/Homo_sapiens/UCSC/hg19/Annotation/Genes/genes.bed" - readme = "${params.igenomes_base}/Homo_sapiens/UCSC/hg19/Annotation/README.txt" - mito_name = "chrM" - macs_gsize = "2.7e9" - blacklist = "${projectDir}/assets/blacklists/hg19-blacklist.bed" - } - mm10 { - fasta = "${params.igenomes_base}/Mus_musculus/UCSC/mm10/Sequence/WholeGenomeFasta/genome.fa" - bwa = "${params.igenomes_base}/Mus_musculus/UCSC/mm10/Sequence/BWAIndex/version0.6.0/" - bowtie2 = "${params.igenomes_base}/Mus_musculus/UCSC/mm10/Sequence/Bowtie2Index/" - star = "${params.igenomes_base}/Mus_musculus/UCSC/mm10/Sequence/STARIndex/" - bismark = "${params.igenomes_base}/Mus_musculus/UCSC/mm10/Sequence/BismarkIndex/" - gtf = "${params.igenomes_base}/Mus_musculus/UCSC/mm10/Annotation/Genes/genes.gtf" - bed12 = "${params.igenomes_base}/Mus_musculus/UCSC/mm10/Annotation/Genes/genes.bed" - readme = "${params.igenomes_base}/Mus_musculus/UCSC/mm10/Annotation/README.txt" - mito_name = "chrM" - macs_gsize = "1.87e9" - blacklist = "${projectDir}/assets/blacklists/mm10-blacklist.bed" - } - bosTau8 { - fasta = "${params.igenomes_base}/Bos_taurus/UCSC/bosTau8/Sequence/WholeGenomeFasta/genome.fa" - bwa = "${params.igenomes_base}/Bos_taurus/UCSC/bosTau8/Sequence/BWAIndex/version0.6.0/" - bowtie2 = "${params.igenomes_base}/Bos_taurus/UCSC/bosTau8/Sequence/Bowtie2Index/" - star = "${params.igenomes_base}/Bos_taurus/UCSC/bosTau8/Sequence/STARIndex/" - bismark = "${params.igenomes_base}/Bos_taurus/UCSC/bosTau8/Sequence/BismarkIndex/" - gtf = "${params.igenomes_base}/Bos_taurus/UCSC/bosTau8/Annotation/Genes/genes.gtf" - bed12 = "${params.igenomes_base}/Bos_taurus/UCSC/bosTau8/Annotation/Genes/genes.bed" - mito_name = "chrM" - } - ce10 { - fasta = "${params.igenomes_base}/Caenorhabditis_elegans/UCSC/ce10/Sequence/WholeGenomeFasta/genome.fa" - bwa = "${params.igenomes_base}/Caenorhabditis_elegans/UCSC/ce10/Sequence/BWAIndex/version0.6.0/" - bowtie2 = "${params.igenomes_base}/Caenorhabditis_elegans/UCSC/ce10/Sequence/Bowtie2Index/" - star = "${params.igenomes_base}/Caenorhabditis_elegans/UCSC/ce10/Sequence/STARIndex/" - bismark = "${params.igenomes_base}/Caenorhabditis_elegans/UCSC/ce10/Sequence/BismarkIndex/" - gtf = "${params.igenomes_base}/Caenorhabditis_elegans/UCSC/ce10/Annotation/Genes/genes.gtf" - bed12 = "${params.igenomes_base}/Caenorhabditis_elegans/UCSC/ce10/Annotation/Genes/genes.bed" - readme = "${params.igenomes_base}/Caenorhabditis_elegans/UCSC/ce10/Annotation/README.txt" - mito_name = "chrM" - macs_gsize = "9e7" - } - canFam3 { - fasta = "${params.igenomes_base}/Canis_familiaris/UCSC/canFam3/Sequence/WholeGenomeFasta/genome.fa" - bwa = "${params.igenomes_base}/Canis_familiaris/UCSC/canFam3/Sequence/BWAIndex/version0.6.0/" - bowtie2 = "${params.igenomes_base}/Canis_familiaris/UCSC/canFam3/Sequence/Bowtie2Index/" - star = "${params.igenomes_base}/Canis_familiaris/UCSC/canFam3/Sequence/STARIndex/" - bismark = "${params.igenomes_base}/Canis_familiaris/UCSC/canFam3/Sequence/BismarkIndex/" - gtf = "${params.igenomes_base}/Canis_familiaris/UCSC/canFam3/Annotation/Genes/genes.gtf" - bed12 = "${params.igenomes_base}/Canis_familiaris/UCSC/canFam3/Annotation/Genes/genes.bed" - readme = "${params.igenomes_base}/Canis_familiaris/UCSC/canFam3/Annotation/README.txt" - mito_name = "chrM" - } - danRer10 { - fasta = "${params.igenomes_base}/Danio_rerio/UCSC/danRer10/Sequence/WholeGenomeFasta/genome.fa" - bwa = "${params.igenomes_base}/Danio_rerio/UCSC/danRer10/Sequence/BWAIndex/version0.6.0/" - bowtie2 = "${params.igenomes_base}/Danio_rerio/UCSC/danRer10/Sequence/Bowtie2Index/" - star = "${params.igenomes_base}/Danio_rerio/UCSC/danRer10/Sequence/STARIndex/" - bismark = "${params.igenomes_base}/Danio_rerio/UCSC/danRer10/Sequence/BismarkIndex/" - gtf = "${params.igenomes_base}/Danio_rerio/UCSC/danRer10/Annotation/Genes/genes.gtf" - bed12 = "${params.igenomes_base}/Danio_rerio/UCSC/danRer10/Annotation/Genes/genes.bed" - mito_name = "chrM" - macs_gsize = "1.37e9" - } - dm6 { - fasta = "${params.igenomes_base}/Drosophila_melanogaster/UCSC/dm6/Sequence/WholeGenomeFasta/genome.fa" - bwa = "${params.igenomes_base}/Drosophila_melanogaster/UCSC/dm6/Sequence/BWAIndex/version0.6.0/" - bowtie2 = "${params.igenomes_base}/Drosophila_melanogaster/UCSC/dm6/Sequence/Bowtie2Index/" - star = "${params.igenomes_base}/Drosophila_melanogaster/UCSC/dm6/Sequence/STARIndex/" - bismark = "${params.igenomes_base}/Drosophila_melanogaster/UCSC/dm6/Sequence/BismarkIndex/" - gtf = "${params.igenomes_base}/Drosophila_melanogaster/UCSC/dm6/Annotation/Genes/genes.gtf" - bed12 = "${params.igenomes_base}/Drosophila_melanogaster/UCSC/dm6/Annotation/Genes/genes.bed" - mito_name = "chrM" - macs_gsize = "1.2e8" - } - equCab2 { - fasta = "${params.igenomes_base}/Equus_caballus/UCSC/equCab2/Sequence/WholeGenomeFasta/genome.fa" - bwa = "${params.igenomes_base}/Equus_caballus/UCSC/equCab2/Sequence/BWAIndex/version0.6.0/" - bowtie2 = "${params.igenomes_base}/Equus_caballus/UCSC/equCab2/Sequence/Bowtie2Index/" - star = "${params.igenomes_base}/Equus_caballus/UCSC/equCab2/Sequence/STARIndex/" - bismark = "${params.igenomes_base}/Equus_caballus/UCSC/equCab2/Sequence/BismarkIndex/" - gtf = "${params.igenomes_base}/Equus_caballus/UCSC/equCab2/Annotation/Genes/genes.gtf" - bed12 = "${params.igenomes_base}/Equus_caballus/UCSC/equCab2/Annotation/Genes/genes.bed" - readme = "${params.igenomes_base}/Equus_caballus/UCSC/equCab2/Annotation/README.txt" - mito_name = "chrM" - } - galGal4 { - fasta = "${params.igenomes_base}/Gallus_gallus/UCSC/galGal4/Sequence/WholeGenomeFasta/genome.fa" - bwa = "${params.igenomes_base}/Gallus_gallus/UCSC/galGal4/Sequence/BWAIndex/version0.6.0/" - bowtie2 = "${params.igenomes_base}/Gallus_gallus/UCSC/galGal4/Sequence/Bowtie2Index/" - star = "${params.igenomes_base}/Gallus_gallus/UCSC/galGal4/Sequence/STARIndex/" - bismark = "${params.igenomes_base}/Gallus_gallus/UCSC/galGal4/Sequence/BismarkIndex/" - gtf = "${params.igenomes_base}/Gallus_gallus/UCSC/galGal4/Annotation/Genes/genes.gtf" - bed12 = "${params.igenomes_base}/Gallus_gallus/UCSC/galGal4/Annotation/Genes/genes.bed" - readme = "${params.igenomes_base}/Gallus_gallus/UCSC/galGal4/Annotation/README.txt" - mito_name = "chrM" - } - panTro4 { - fasta = "${params.igenomes_base}/Pan_troglodytes/UCSC/panTro4/Sequence/WholeGenomeFasta/genome.fa" - bwa = "${params.igenomes_base}/Pan_troglodytes/UCSC/panTro4/Sequence/BWAIndex/version0.6.0/" - bowtie2 = "${params.igenomes_base}/Pan_troglodytes/UCSC/panTro4/Sequence/Bowtie2Index/" - star = "${params.igenomes_base}/Pan_troglodytes/UCSC/panTro4/Sequence/STARIndex/" - bismark = "${params.igenomes_base}/Pan_troglodytes/UCSC/panTro4/Sequence/BismarkIndex/" - gtf = "${params.igenomes_base}/Pan_troglodytes/UCSC/panTro4/Annotation/Genes/genes.gtf" - bed12 = "${params.igenomes_base}/Pan_troglodytes/UCSC/panTro4/Annotation/Genes/genes.bed" - readme = "${params.igenomes_base}/Pan_troglodytes/UCSC/panTro4/Annotation/README.txt" - mito_name = "chrM" - } - rn6 { - fasta = "${params.igenomes_base}/Rattus_norvegicus/UCSC/rn6/Sequence/WholeGenomeFasta/genome.fa" - bwa = "${params.igenomes_base}/Rattus_norvegicus/UCSC/rn6/Sequence/BWAIndex/version0.6.0/" - bowtie2 = "${params.igenomes_base}/Rattus_norvegicus/UCSC/rn6/Sequence/Bowtie2Index/" - star = "${params.igenomes_base}/Rattus_norvegicus/UCSC/rn6/Sequence/STARIndex/" - bismark = "${params.igenomes_base}/Rattus_norvegicus/UCSC/rn6/Sequence/BismarkIndex/" - gtf = "${params.igenomes_base}/Rattus_norvegicus/UCSC/rn6/Annotation/Genes/genes.gtf" - bed12 = "${params.igenomes_base}/Rattus_norvegicus/UCSC/rn6/Annotation/Genes/genes.bed" - mito_name = "chrM" - } - sacCer3 { - fasta = "${params.igenomes_base}/Saccharomyces_cerevisiae/UCSC/sacCer3/Sequence/WholeGenomeFasta/genome.fa" - bwa = "${params.igenomes_base}/Saccharomyces_cerevisiae/UCSC/sacCer3/Sequence/BWAIndex/version0.6.0/" - bowtie2 = "${params.igenomes_base}/Saccharomyces_cerevisiae/UCSC/sacCer3/Sequence/Bowtie2Index/" - star = "${params.igenomes_base}/Saccharomyces_cerevisiae/UCSC/sacCer3/Sequence/STARIndex/" - bismark = "${params.igenomes_base}/Saccharomyces_cerevisiae/UCSC/sacCer3/Sequence/BismarkIndex/" - readme = "${params.igenomes_base}/Saccharomyces_cerevisiae/UCSC/sacCer3/Annotation/README.txt" - mito_name = "chrM" - macs_gsize = "1.2e7" - } - susScr3 { - fasta = "${params.igenomes_base}/Sus_scrofa/UCSC/susScr3/Sequence/WholeGenomeFasta/genome.fa" - bwa = "${params.igenomes_base}/Sus_scrofa/UCSC/susScr3/Sequence/BWAIndex/version0.6.0/" - bowtie2 = "${params.igenomes_base}/Sus_scrofa/UCSC/susScr3/Sequence/Bowtie2Index/" - star = "${params.igenomes_base}/Sus_scrofa/UCSC/susScr3/Sequence/STARIndex/" - bismark = "${params.igenomes_base}/Sus_scrofa/UCSC/susScr3/Sequence/BismarkIndex/" - gtf = "${params.igenomes_base}/Sus_scrofa/UCSC/susScr3/Annotation/Genes/genes.gtf" - bed12 = "${params.igenomes_base}/Sus_scrofa/UCSC/susScr3/Annotation/Genes/genes.bed" - readme = "${params.igenomes_base}/Sus_scrofa/UCSC/susScr3/Annotation/README.txt" - mito_name = "chrM" - } - } -} diff --git a/conf/modules.config b/conf/modules.config index 928a191..31a884e 100644 --- a/conf/modules.config +++ b/conf/modules.config @@ -1,27 +1,42 @@ process { withName: SAMTOOLS_VIEW { + cpus = { 2 } + memory = { 6.GB * task.attempt } ext.prefix = { "${meta.id}.samtools_view" } ext.args = '-F 12 --output-fmt bam' ext.args2 = { params.targeted.gene == 'MSH2' ? 'chr2:47414420-47414421' : null } } withName: SAMTOOLS_SORT { + cpus = { 2 } + memory = { 6.GB * task.attempt } ext.prefix = { "${meta.id}.samtools_sorted" } ext.args = '-n' } withName: SAMTOOLS_FASTQ { + cpus = { 2 } + memory = { 6.GB * task.attempt } ext.prefix = { "${meta.id}.samtools_fastq" } ext.args = '-n' } - withName: 'MULTIQC' { + withName: PEAR { + cpus = { 2 } + memory = { 6.GB * task.attempt } + } + + withName: HOTCOUNT { + cpus = { 1 } + memory = { 4.GB * task.attempt } + } + + withName: MULTIQC { // Use custom CMGG MultiQC container container = 'quay.io/cmgg/multiqc_cmgg:0.0.5-multiqc-v1.33' // Generate report with optional title - ext.args = { params.multiqc_title ? "--title \"$params.multiqc_title\"" : '' } + ext.args = { params.multiqc_title ? "--title \"${params.multiqc_title}\"" : '' } } - } diff --git a/conf/test.config b/conf/test.config index 9e22843..7c8d1a6 100644 --- a/conf/test.config +++ b/conf/test.config @@ -16,17 +16,17 @@ params { genome = 'R64-1-1' // Targeted flow - targeted.input = "${projectDir}/assets/samplesheet_targeted.csv" - targeted.fasta = 'https://github.com/nf-cmgg/test-datasets/raw/refs/heads/report/data/genomics/homo_sapiens/genome/seq/subset.fa' + targeted.input = "${projectDir}/assets/samplesheet_targeted.csv" + targeted.fasta = 'https://github.com/nf-cmgg/test-datasets/raw/refs/heads/report/data/genomics/homo_sapiens/genome/seq/subset.fa' // RNAfusion flow - rnafusion.input = "${projectDir}/assets/samplesheet_rnafusion.csv" - rnafusion.genes = "https://github.com/nf-cmgg/test-datasets/raw/refs/heads/report/data/genomics/homo_sapiens/genome/varcov_files/RNAseq_genes_2.txt" - rnafusion.fusions = "https://github.com/nf-cmgg/test-datasets/raw/refs/heads/report/data/genomics/homo_sapiens/genome/varcov_files/fusions.txt" - rnafusion.mane = "https://github.com/nf-cmgg/test-datasets/raw/refs/heads/report/data/genomics/homo_sapiens/genome/varcov_files/2026_01_20_MANE.csv" + rnafusion.input = "${projectDir}/assets/samplesheet_rnafusion.csv" + rnafusion.genes = "https://github.com/nf-cmgg/test-datasets/raw/refs/heads/report/data/genomics/homo_sapiens/genome/varcov_files/RNAseq_genes_2.txt" + rnafusion.fusions = "https://github.com/nf-cmgg/test-datasets/raw/refs/heads/report/data/genomics/homo_sapiens/genome/varcov_files/fusions.txt" + rnafusion.mane = "https://github.com/nf-cmgg/test-datasets/raw/refs/heads/report/data/genomics/homo_sapiens/genome/varcov_files/2026_01_20_MANE.csv" // Pacvar repeat flow - pacvar_repeat.input = "${projectDir}/assets/samplesheet_pacvar_repeat.csv" + pacvar_repeat.input = "${projectDir}/assets/samplesheet_pacvar_repeat.csv" } process { @@ -36,7 +36,7 @@ process { memory: 6.GB, time: 6.h, ] - withName: SAMTOOLS_VIEW { + withName: SAMTOOLS_VIEW { ext.prefix = { "${meta.id}.samtools_view" } ext.args = '-F 12 --output-fmt bam' ext.args2 = 'chr2:47414420-47414421' diff --git a/main.nf b/main.nf index c1ef264..bbbc9a5 100644 --- a/main.nf +++ b/main.nf @@ -12,10 +12,6 @@ IMPORT FUNCTIONS / MODULES / SUBWORKFLOWS / WORKFLOWS ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ -include { getGenomeAttribute } from './subworkflows/local/utils_nfcore_report_pipeline' - -params.targeted.fasta = params.targeted.fasta ?: getGenomeAttribute('fasta') -params.targeted.queries_dir = "${projectDir}/assets/targeted/" include { TARGETED } from './workflows/targeted' include { RNAFUSION } from './workflows/rnafusion' @@ -27,10 +23,13 @@ include { samplesheetToList } from 'plugin/nf-schema' include { paramsSummaryMap } from 'plugin/nf-schema' include { paramsSummaryMultiqc } from './subworkflows/nf-core/utils_nfcore_pipeline' include { methodsDescriptionText } from './subworkflows/local/utils_nfcore_report_pipeline' +include { check_required_params } from './subworkflows/local/utils_nfcore_report_pipeline' // Modules include { MULTIQC } from './modules/nf-core/multiqc/main' +params.targeted.queries_dir = "${projectDir}/assets/targeted/" + /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ RUN MAIN WORKFLOW @@ -47,7 +46,7 @@ workflow { params.version, params.validate_params, args, - params.outdir + params.outdir, ) // @@ -55,25 +54,31 @@ workflow { // def out_targeted_hotcount = channel.empty() - if(params.targeted.input) { + if (params.targeted.input) { def required_parameters = ['fasta', 'queries_dir', 'gene'] check_required_params(params.get('targeted'), 'targeted', required_parameters) def targeted_params = params.targeted def ch_samplesheet = channel.fromList(samplesheetToList(targeted_params.input, "${projectDir}/assets/schema_targeted_input.json")) - def fasta = channel.value([[id:'reference'], file(targeted_params.fasta)]) + def fasta_file = file(targeted_params.fasta) + def fai_file = file("${targeted_params.fasta}.fai") + def fasta = channel.value([ + [id: 'reference'], + fasta_file, + fai_file.exists() ? fai_file : null + ]) TARGETED( ch_samplesheet, fasta, targeted_params.queries_dir, - targeted_params.gene + targeted_params.gene, ) out_targeted_hotcount = TARGETED.out.hotcount } def out_rnafusion_excels = channel.empty() - if(params.rnafusion.input) { + if (params.rnafusion.input) { def required_parameters = ['genes', 'fusions', 'mane'] check_required_params(params.get('rnafusion'), 'rnafusion', required_parameters) def rnafusion_params = params.rnafusion @@ -88,13 +93,13 @@ workflow { genes, fusions, mane, - workflow.manifest.version + workflow.manifest.version, ) out_rnafusion_excels = RNAFUSION.out.excels } def out_pacvar_repeat_excels = channel.empty() - if(params.pacvar_repeat.input) { + if (params.pacvar_repeat.input) { def required_parameters = ['input'] check_required_params(params.get('pacvar_repeat'), 'pacvar_repeat', required_parameters) def pacvar_repeat_params = params.pacvar_repeat @@ -116,64 +121,59 @@ workflow { def topic_versions_string = topic_versions.versions_tuple .map { process, tool, version -> - [ process[process.lastIndexOf(':')+1..-1], " ${tool}: ${version}" ] + [process[process.lastIndexOf(':') + 1..-1], " ${tool}: ${version}"] } - .groupTuple(by:0) + .groupTuple(by: 0) .map { process, tool_versions -> tool_versions.unique().sort() "${process}:\n${tool_versions.join('\n')}" } - def ch_versions_yaml = softwareVersionsToYAML(topic_versions.versions_file) - .mix(topic_versions_string) + def ch_versions_yaml = softwareVersionsToYAML(topic_versions.versions_file).mix(topic_versions_string) - def ch_versions_file = ch_versions_yaml - .collectFile( - storeDir: "${params.outdir}/pipeline_info", - name: 'report_mqc_versions.yml', - sort: true, - newLine: true - ) + def ch_versions_file = ch_versions_yaml.collectFile( + storeDir: "${params.outdir}/pipeline_info", + name: 'report_mqc_versions.yml', + sort: true, + newLine: true, + ) // // Perform multiQC on all QC data // - def ch_multiqc_config = channel.fromPath( - "$projectDir/assets/multiqc_config.yml", checkIfExists: true) - def ch_multiqc_custom_config = params.multiqc_config ? - channel.fromPath(params.multiqc_config, checkIfExists: true) : - channel.empty() - def ch_multiqc_logo = params.multiqc_logo ? - channel.fromPath(params.multiqc_logo, checkIfExists: true) : - channel.empty() - - def summary_params = paramsSummaryMap(workflow, parameters_schema: "nextflow_schema.json") - def ch_workflow_summary = channel.value(paramsSummaryMultiqc(summary_params)) - def ch_multiqc_custom_methods_description = params.multiqc_methods_description ? - file(params.multiqc_methods_description, checkIfExists: true) : - file("$projectDir/assets/methods_description_template.yml", checkIfExists: true) - def ch_methods_description = channel.value(methodsDescriptionText(ch_multiqc_custom_methods_description)) - def ch_multiqc_outdir = params.outdir ? channel.value(file(params.outdir)) : channel.empty() - - def ch_multiqc_files = channel.empty() - ch_multiqc_files = ch_multiqc_files.mix( - ch_workflow_summary.collectFile(name: 'workflow_summary_mqc.yaml'), - ch_versions_file, - ch_methods_description.collectFile( - name: 'methods_description_mqc.yaml', - sort: false - ), - ch_multiqc_outdir - ) - - MULTIQC ( - ch_multiqc_files.collect(), - ch_multiqc_config.toList(), - ch_multiqc_custom_config.toList(), - ch_multiqc_logo.toList(), - [], - [] + def summary_params = paramsSummaryMap(workflow, parameters_schema: "nextflow_schema.json") + def ch_workflow_summary = channel.value(paramsSummaryMultiqc(summary_params)) + def ch_multiqc_custom_methods_description = params.multiqc_methods_description + ? file(params.multiqc_methods_description, checkIfExists: true) + : file("${projectDir}/assets/methods_description_template.yml", checkIfExists: true) + def ch_methods_description = channel.value(methodsDescriptionText(ch_multiqc_custom_methods_description)) + def ch_multiqc_outdir = params.outdir ? channel.value(file(params.outdir)) : channel.empty() + + def ch_multiqc_files = channel.empty() + ch_multiqc_files = ch_multiqc_files.mix( + ch_workflow_summary.collectFile(name: 'workflow_summary_mqc.yaml'), + ch_versions_file, + ch_methods_description.collectFile( + name: 'methods_description_mqc.yaml', + sort: false, + ), + ch_multiqc_outdir, + ) + + MULTIQC( + ch_multiqc_files.flatten().collect().map { files -> + [ + [id: 'nf-report'], + files, + params.multiqc_config + ? file(params.multiqc_config, checkIfExists: true) + : file("${projectDir}/assets/multiqc_config.yml", checkIfExists: true), + params.multiqc_logo ? file(params.multiqc_logo, checkIfExists: true) : [], + [], + [], + ] + } ) // // SUBWORKFLOW: Run completion tasks @@ -184,15 +184,14 @@ workflow { params.plaintext_email, params.outdir, params.monochrome_logs, - params.hook_url, ) publish: - targeted_hotcount = out_targeted_hotcount - rnafusion_excels = out_rnafusion_excels - pacvar_repeat_excels = out_pacvar_repeat_excels - multiqc_report = MULTIQC.out.report - multiqc_data = MULTIQC.out.data + targeted_hotcount = out_targeted_hotcount + rnafusion_excels = out_rnafusion_excels + pacvar_repeat_excels = out_pacvar_repeat_excels + multiqc_report = MULTIQC.out.report + multiqc_data = MULTIQC.out.data } /* @@ -218,36 +217,13 @@ output { } } multiqc_report { - path { report -> - report >> "multiqc/multiqc_report.html" + path { _meta, report -> + report >> "multiqc/" } } multiqc_data { - path { data -> - data >> "multiqc/multiqc_data" + path { _meta, data -> + data >> "multiqc/multiqc_data/" } } } - -/* -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - FUNCTIONS -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -*/ - -def check_required_params(Map scope_params, String scope_name, List required_params) { - if (scope_params == null) { - error "Could not find a parameters scope called '${scope_name}'" - } - - def missing_params = [] - required_params.each { param -> - if (scope_params.get(param, null) == null) { - missing_params << param - } - } - - if (missing_params) { - error "The following required parameters are missing from the '${scope_name}' parameters scope: ${missing_params.join(', ')}" - } -} diff --git a/modules.json b/modules.json index 7379ba8..e5cfa99 100644 --- a/modules.json +++ b/modules.json @@ -5,9 +5,14 @@ "https://github.com/nf-core/modules.git": { "modules": { "nf-core": { + "cat/fastq": { + "branch": "master", + "git_sha": "5d28ea7cfaebcfae6f74d1067ea766d8ff19dff3", + "installed_by": ["modules"] + }, "multiqc": { "branch": "master", - "git_sha": "575e1a4b51a9bad7a8cd1316a88fb85684ef7c7b", + "git_sha": "cb9f4bec379866ca560f7f79d9a9a06bea8c9b51", "installed_by": ["modules"] }, "pear": { @@ -17,17 +22,17 @@ }, "samtools/fastq": { "branch": "master", - "git_sha": "1d2fbdcbca677bbe8da0f9d0d2bb7c02f2cab1c9", + "git_sha": "156feda0cb6589cd29c04902004fa3b53bc00205", "installed_by": ["modules"] }, "samtools/sort": { "branch": "master", - "git_sha": "5cb9a8694da0a0e550921636bb60bc8c56445fd7", + "git_sha": "156feda0cb6589cd29c04902004fa3b53bc00205", "installed_by": ["modules"] }, "samtools/view": { "branch": "master", - "git_sha": "b2e78932ef01165fd85829513eaca29eff8e640a", + "git_sha": "156feda0cb6589cd29c04902004fa3b53bc00205", "installed_by": ["modules"] }, "untar": { @@ -46,7 +51,7 @@ }, "utils_nfcore_pipeline": { "branch": "master", - "git_sha": "65f5e638d901a51534c68fd5c1c19e8112fb4df1", + "git_sha": "f0b535b3ae20080f8db03dd5388876ad1ec29d70", "installed_by": ["subworkflows"] }, "utils_nfschema_plugin": { diff --git a/modules/local/hotcount/main.nf b/modules/local/hotcount/main.nf index 3d73654..95608a7 100644 --- a/modules/local/hotcount/main.nf +++ b/modules/local/hotcount/main.nf @@ -17,7 +17,41 @@ process HOTCOUNT { script: def prefix = task.ext.prefix ?: "${meta.id}" """ - do_it_gz.sh ${query_file} ${assembled_fastq} > ${prefix}.counts.txt + design="${query_file}" + assembled_file="${assembled_fastq}" + sample_name=\$(basename "\${assembled_file}") + run_date=\$(date) + + { + echo "## script do_it.sh running in version 0.0" + echo "## date is \${run_date}" + echo -n "Sample" + while IFS= read -r line || [ -n "\${line}" ]; do + line="\${line%\$'\r'}" + [ -z "\${line}" ] && continue + mut="\${line%%=*}" + echo -n " \${mut}" + done < "\${design}" + echo "" + + echo -n "\${sample_name}" + while IFS= read -r line || [ -n "\${line}" ]; do + line="\${line%\$'\r'}" + [ -z "\${line}" ] && continue + forward="\${line#*=}" + [ -z "\${forward}" ] && continue + reversed=\$(printf '%s' "\${forward}" | rev | tr 'ACGT' 'TGCA') + + if [[ "\${assembled_file}" == *.gz ]]; then + nb=\$(zgrep -c -E "\${forward}|\${reversed}" "\${assembled_file}" || true) + else + nb=\$(grep -c -E "\${forward}|\${reversed}" "\${assembled_file}" || true) + fi + nb="\${nb:-0}" + echo -n " \${nb}" + done < "\${design}" + echo "" + } > "${prefix}.counts.txt" """ stub: diff --git a/modules/local/mergereads/main.nf b/modules/local/mergereads/main.nf deleted file mode 100644 index d4f208a..0000000 --- a/modules/local/mergereads/main.nf +++ /dev/null @@ -1,32 +0,0 @@ -process MERGE_READS { - tag "${meta.id}" - label 'process_low' - - conda "${moduleDir}/environment.yml" - container "${workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container - ? 'https://community-cr-prod.seqera.io/docker/registry/v2/blobs/sha256/52/52ccce28d2ab928ab862e25aae26314d69c8e38bd41ca9431c67ef05221348aa/data' - : 'community.wave.seqera.io/library/coreutils_grep_gzip_lbzip2_pruned:838ba80435a629f8'}" - - input: - tuple val(meta), path(pear_assembled), path(samtools_singleton) - - output: - tuple val(meta), path("*.merged.fastq.gz"), emit: merged - tuple val("${task.process}"), val('cat'), eval("cat --version 2>&1 | head -n 1 | sed 's/^.* //'"), topic: versions, emit: versions_cat - tuple val("${task.process}"), val('gunzip'), eval("gunzip --version 2>&1 | head -n 1 | sed 's/^.* //'"), topic: versions, emit: versions_gunzip - tuple val("${task.process}"), val('gzip'), eval("gzip --version 2>&1 | head -n 1 | sed 's/^.* //'"), topic: versions, emit: versions_gzip - - script: - def prefix = task.ext.prefix ?: "${meta.id}" - """ - gunzip -c ${pear_assembled} > pear_unzipped.fastq - gunzip -c ${samtools_singleton} > singleton_unzipped.fastq - cat pear_unzipped.fastq singleton_unzipped.fastq | gzip > ${prefix}.merged.fastq.gz - """ - - stub: - def prefix = task.ext.prefix ?: "${meta.id}" - """ - gzip -c < /dev/null > ${prefix}.merged.fastq.gz - """ -} diff --git a/modules/local/mergereads/tests/main.nf.test b/modules/local/mergereads/tests/main.nf.test deleted file mode 100644 index 17616ae..0000000 --- a/modules/local/mergereads/tests/main.nf.test +++ /dev/null @@ -1,55 +0,0 @@ -nextflow_process{ - - name "Test Process MERGE_READS" - script "../main.nf" - process "MERGE_READS" - - tag "modules" - tag "mergereads" - - test("chr2-subset - [meta, pear_assembled, samtools_singleton]") { - - when { - process { - """ - input[0] = [ - [ id:'test' ], - file('https://github.com/nf-cmgg/test-datasets/raw/refs/heads/report/data/genomics/homo_sapiens/illumina/testfiles/test1.pear_assembled.fastq.gz', checkIfExists: true), - file('https://github.com/nf-cmgg/test-datasets/raw/refs/heads/report/data/genomics/homo_sapiens/illumina/testfiles/test1.samtools_fastq_singleton.fastq.gz', checkIfExists: true) - ] - """ - } - } - - then { - assertAll ( - { assert process.success }, - { assert snapshot(process.out).match() } - ) - } - - } - - test("stub") { - options "-stub" - - when { - process { - """ - input[0] = [ - [ id:'test'], - file('https://github.com/nf-cmgg/test-datasets/raw/refs/heads/report/data/genomics/homo_sapiens/illumina/testfiles/test1.pear_assembled.fastq.gz', checkIfExists: true), - file('https://github.com/nf-cmgg/test-datasets/raw/refs/heads/report/data/genomics/homo_sapiens/illumina/testfiles/test1.samtools_fastq_singleton.fastq.gz', checkIfExists: true) - ] - """ - } - } - - then { - assertAll ( - { assert process.success }, - { assert snapshot(process.out).match() } - ) - } - } -} diff --git a/modules/local/mergereads/tests/main.nf.test.snap b/modules/local/mergereads/tests/main.nf.test.snap deleted file mode 100644 index 4f9910f..0000000 --- a/modules/local/mergereads/tests/main.nf.test.snap +++ /dev/null @@ -1,140 +0,0 @@ -{ - "stub": { - "content": [ - { - "0": [ - [ - { - "id": "test" - }, - "test.merged.fastq.gz:md5,d41d8cd98f00b204e9800998ecf8427e" - ] - ], - "1": [ - [ - "MERGE_READS", - "cat", - "9.5" - ] - ], - "2": [ - [ - "MERGE_READS", - "gunzip", - "1.13" - ] - ], - "3": [ - [ - "MERGE_READS", - "gzip", - "1.13" - ] - ], - "merged": [ - [ - { - "id": "test" - }, - "test.merged.fastq.gz:md5,d41d8cd98f00b204e9800998ecf8427e" - ] - ], - "versions_cat": [ - [ - "MERGE_READS", - "cat", - "9.5" - ] - ], - "versions_gunzip": [ - [ - "MERGE_READS", - "gunzip", - "1.13" - ] - ], - "versions_gzip": [ - [ - "MERGE_READS", - "gzip", - "1.13" - ] - ] - } - ], - "meta": { - "nf-test": "0.9.2", - "nextflow": "25.04.6" - }, - "timestamp": "2025-10-13T10:39:32.107720042" - }, - "chr2-subset - [meta, pear_assembled, samtools_singleton]": { - "content": [ - { - "0": [ - [ - { - "id": "test" - }, - "test.merged.fastq.gz:md5,59c73d5ea391b6c469b6989621a5cc45" - ] - ], - "1": [ - [ - "MERGE_READS", - "cat", - "9.5" - ] - ], - "2": [ - [ - "MERGE_READS", - "gunzip", - "1.13" - ] - ], - "3": [ - [ - "MERGE_READS", - "gzip", - "1.13" - ] - ], - "merged": [ - [ - { - "id": "test" - }, - "test.merged.fastq.gz:md5,59c73d5ea391b6c469b6989621a5cc45" - ] - ], - "versions_cat": [ - [ - "MERGE_READS", - "cat", - "9.5" - ] - ], - "versions_gunzip": [ - [ - "MERGE_READS", - "gunzip", - "1.13" - ] - ], - "versions_gzip": [ - [ - "MERGE_READS", - "gzip", - "1.13" - ] - ] - } - ], - "meta": { - "nf-test": "0.9.2", - "nextflow": "25.04.6" - }, - "timestamp": "2025-10-13T10:39:21.775427847" - } -} \ No newline at end of file diff --git a/modules/local/pacvarrepeat/main.nf b/modules/local/pacvarrepeat/main.nf index c85f446..b0206d6 100644 --- a/modules/local/pacvarrepeat/main.nf +++ b/modules/local/pacvarrepeat/main.nf @@ -1,11 +1,11 @@ process PACVAR_REPEAT { - tag "$meta.id" + tag "${meta.id}" label 'process_single' conda "${moduleDir}/environment.yml" - container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container + container "${workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? 'https://community-cr-prod.seqera.io/docker/registry/v2/blobs/sha256/92/92f382f0f3c2af60bdaa142a038896267c45fa6c34ee6a9b04a3eae5b4bb1639/data' - : 'community.wave.seqera.io/library/pip_openpyxl_pandas:9248bb616642565e' }" + : 'community.wave.seqera.io/library/pip_openpyxl_pandas:9248bb616642565e'}" input: tuple val(meta), path(vcf) diff --git a/modules/local/mergereads/environment.yml b/modules/nf-core/cat/fastq/environment.yml similarity index 100% rename from modules/local/mergereads/environment.yml rename to modules/nf-core/cat/fastq/environment.yml diff --git a/modules/nf-core/cat/fastq/main.nf b/modules/nf-core/cat/fastq/main.nf new file mode 100644 index 0000000..24c0e92 --- /dev/null +++ b/modules/nf-core/cat/fastq/main.nf @@ -0,0 +1,73 @@ +process CAT_FASTQ { + tag "${meta.id}" + label 'process_single' + + conda "${moduleDir}/environment.yml" + container "${workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container + ? 'https://community-cr-prod.seqera.io/docker/registry/v2/blobs/sha256/52/52ccce28d2ab928ab862e25aae26314d69c8e38bd41ca9431c67ef05221348aa/data' + : 'community.wave.seqera.io/library/coreutils_grep_gzip_lbzip2_pruned:838ba80435a629f8'}" + + input: + tuple val(meta), path(reads, stageAs: "input*/*") + + output: + tuple val(meta), path("*.merged.fastq.gz"), emit: reads + tuple val("${task.process}"), val("cat"), eval("cat --version 2>&1 | head -n 1 | sed 's/^.*coreutils) //; s/ .*\$//'"), emit: versions_cat, topic: versions + + when: + task.ext.when == null || task.ext.when + + script: + def prefix = task.ext.prefix ?: "${meta.id}" + def readList = reads instanceof List ? reads.collect { item -> item.toString() } : [reads.toString()] + def compress = readList[0]?.endsWith('.gz') ? '' : '| gzip' + if (meta.single_end) { + if (readList.size >= 1) { + """ + cat ${readList.join(' ')} ${compress} > ${prefix}.merged.fastq.gz + """ + } + else { + error("Could not find any FASTQ files to concatenate in the process input") + } + } + else { + if (readList.size >= 2) { + def read1 = [] + def read2 = [] + readList.eachWithIndex { v, ix -> (ix & 1 ? read2 : read1) << v } + """ + cat ${read1.join(' ')} ${compress} > ${prefix}_1.merged.fastq.gz + cat ${read2.join(' ')} ${compress} > ${prefix}_2.merged.fastq.gz + """ + } + else { + error("Could not find any FASTQ file pairs to concatenate in the process input") + } + } + + stub: + def prefix = task.ext.prefix ?: "${meta.id}" + def readList = reads instanceof List ? reads.collect { item -> item.toString() } : [reads.toString()] + if (meta.single_end) { + if (readList.size >= 1) { + """ + echo '' | gzip > ${prefix}.merged.fastq.gz + """ + } + else { + error("Could not find any FASTQ files to concatenate in the process input") + } + } + else { + if (readList.size >= 2) { + """ + echo '' | gzip > ${prefix}_1.merged.fastq.gz + echo '' | gzip > ${prefix}_2.merged.fastq.gz + """ + } + else { + error("Could not find any FASTQ file pairs to concatenate in the process input") + } + } +} diff --git a/modules/nf-core/cat/fastq/meta.yml b/modules/nf-core/cat/fastq/meta.yml new file mode 100644 index 0000000..6fefd6e --- /dev/null +++ b/modules/nf-core/cat/fastq/meta.yml @@ -0,0 +1,67 @@ +name: cat_fastq +description: Concatenates fastq files. Supports both compressed (.gz) and uncompressed inputs; uncompressed files are automatically gzip-compressed during concatenation. +keywords: + - cat + - fastq + - concatenate + - compress +tools: + - cat: + description: | + The cat utility reads files sequentially, writing them to the standard output. + documentation: https://www.gnu.org/software/coreutils/manual/html_node/cat-invocation.html + licence: ["GPL-3.0-or-later"] + identifier: "" +input: + - - meta: + type: map + description: | + Groovy Map containing sample information + e.g. [ id:'test', single_end:false ] + - reads: + type: file + description: | + List of input FastQ files to be concatenated. + Accepts both gzip-compressed (.fastq.gz) and uncompressed (.fastq) files. + ontologies: [] +output: + reads: + - - meta: + type: map + description: | + Groovy Map containing sample information + e.g. [ id:'test', single_end:false ] + - "*.merged.fastq.gz": + type: file + description: Merged fastq file + pattern: "*.{merged.fastq.gz}" + ontologies: [] + versions_cat: + - - ${task.process}: + type: string + description: The process the versions were collected from + - cat: + type: string + description: The tool name + - cat --version 2>&1 | head -n 1 | sed 's/^.*coreutils) //; s/ .*\$//': + type: eval + description: The expression to obtain the version of the tool + +topics: + versions: + - - ${task.process}: + type: string + description: The process the versions were collected from + - cat: + type: string + description: The tool name + - cat --version 2>&1 | head -n 1 | sed 's/^.*coreutils) //; s/ .*\$//': + type: eval + description: The expression to obtain the version of the tool + +authors: + - "@joseespinosa" + - "@drpatelh" +maintainers: + - "@joseespinosa" + - "@drpatelh" diff --git a/modules/nf-core/cat/fastq/tests/main.nf.test b/modules/nf-core/cat/fastq/tests/main.nf.test new file mode 100644 index 0000000..21052d9 --- /dev/null +++ b/modules/nf-core/cat/fastq/tests/main.nf.test @@ -0,0 +1,405 @@ +nextflow_process { + + name "Test Process CAT_FASTQ" + script "../main.nf" + process "CAT_FASTQ" + tag "modules" + tag "modules_nfcore" + tag "cat" + tag "cat/fastq" + tag "gunzip" + + test("test_cat_fastq_single_end") { + + when { + process { + """ + input[0] = Channel.of([ + [ id:'test', single_end:true ], // meta map + [ file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test_1.fastq.gz', checkIfExists: true), + file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test_2.fastq.gz', checkIfExists: true)] + ]) + """ + } + } + + then { + assertAll( + { assert process.success }, + { assert snapshot(process.out).match() } + ) + } + } + + test("test_cat_fastq_paired_end") { + + when { + process { + """ + input[0] = Channel.of([ + [ id:'test', single_end:false ], // meta map + [ file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test_1.fastq.gz', checkIfExists: true), + file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test_2.fastq.gz', checkIfExists: true), + file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test2_1.fastq.gz', checkIfExists: true), + file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test2_2.fastq.gz', checkIfExists: true)] + ]) + """ + } + } + + then { + assertAll( + { assert process.success }, + { assert snapshot(process.out).match() } + ) + } + } + + test("test_cat_fastq_single_end_same_name") { + + when { + process { + """ + input[0] = Channel.of([ + [ id:'test', single_end:true ], // meta map + [ file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test_1.fastq.gz', checkIfExists: true), + file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test_1.fastq.gz', checkIfExists: true)] + ]) + """ + } + } + + then { + assertAll( + { assert process.success }, + { assert snapshot(process.out).match() } + ) + } + } + + test("test_cat_fastq_paired_end_same_name") { + + when { + process { + """ + input[0] = Channel.of([ + [ id:'test', single_end:false ], // meta map + [ file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test_1.fastq.gz', checkIfExists: true), + file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test_2.fastq.gz', checkIfExists: true), + file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test_1.fastq.gz', checkIfExists: true), + file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test_2.fastq.gz', checkIfExists: true)] + ]) + """ + } + } + + then { + assertAll( + { assert process.success }, + { assert snapshot(process.out).match() } + ) + } + } + + test("test_cat_fastq_single_end_uncompressed") { + + setup { + run("GUNZIP") { + script "../../../gunzip/main.nf" + process { + """ + input[0] = Channel.of( + [[ id:'r1' ], file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test_1.fastq.gz', checkIfExists: true)], + [[ id:'r2' ], file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test_2.fastq.gz', checkIfExists: true)] + ) + """ + } + } + } + + when { + process { + """ + input[0] = GUNZIP.out.gunzip + .toSortedList { a, b -> a[0].id <=> b[0].id } + .map { items -> [[ id: 'test', single_end: true ], items.collect { it[1] }] } + """ + } + } + + then { + assertAll( + { assert process.success }, + { assert snapshot(process.out).match() } + ) + } + } + + test("test_cat_fastq_paired_end_uncompressed") { + + setup { + run("GUNZIP") { + script "../../../gunzip/main.nf" + process { + """ + input[0] = Channel.of( + [[ id:'a' ], file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test_1.fastq.gz', checkIfExists: true)], + [[ id:'b' ], file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test_2.fastq.gz', checkIfExists: true)], + [[ id:'c' ], file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test2_1.fastq.gz', checkIfExists: true)], + [[ id:'d' ], file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test2_2.fastq.gz', checkIfExists: true)] + ) + """ + } + } + } + + when { + process { + """ + input[0] = GUNZIP.out.gunzip + .toSortedList { a, b -> a[0].id <=> b[0].id } + .map { items -> [[ id: 'test', single_end: false ], items.collect { it[1] }] } + """ + } + } + + then { + assertAll( + { assert process.success }, + { assert snapshot(process.out).match() } + ) + } + } + + test("test_cat_fastq_single_end_single_file") { + + when { + process { + """ + input[0] = Channel.of([ + [ id:'test', single_end:true ], // meta map + [ file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test_1.fastq.gz', checkIfExists: true)] + ]) + """ + } + } + + then { + assertAll( + { assert process.success }, + { assert snapshot(process.out).match() } + ) + } + } + + test("test_cat_fastq_single_end - stub") { + + options "-stub" + + when { + process { + """ + input[0] = Channel.of([ + [ id:'test', single_end:true ], // meta map + [ file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test_1.fastq.gz', checkIfExists: true), + file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test_2.fastq.gz', checkIfExists: true)] + ]) + """ + } + } + + then { + assertAll( + { assert process.success }, + { assert snapshot(process.out).match() } + ) + } + } + + test("test_cat_fastq_paired_end - stub") { + + options "-stub" + + when { + process { + """ + input[0] = Channel.of([ + [ id:'test', single_end:false ], // meta map + [ file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test_1.fastq.gz', checkIfExists: true), + file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test_2.fastq.gz', checkIfExists: true), + file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test2_1.fastq.gz', checkIfExists: true), + file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test2_2.fastq.gz', checkIfExists: true)] + ]) + """ + } + } + + then { + assertAll( + { assert process.success }, + { assert snapshot(process.out).match() } + ) + } + } + + test("test_cat_fastq_single_end_same_name - stub") { + + options "-stub" + + when { + process { + """ + input[0] = Channel.of([ + [ id:'test', single_end:true ], // meta map + [ file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test_1.fastq.gz', checkIfExists: true), + file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test_1.fastq.gz', checkIfExists: true)] + ]) + """ + } + } + + then { + assertAll( + { assert process.success }, + { assert snapshot(process.out).match() } + ) + } + } + + test("test_cat_fastq_paired_end_same_name - stub") { + + options "-stub" + + when { + process { + """ + input[0] = Channel.of([ + [ id:'test', single_end:false ], // meta map + [ file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test_1.fastq.gz', checkIfExists: true), + file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test_2.fastq.gz', checkIfExists: true), + file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test_1.fastq.gz', checkIfExists: true), + file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test_2.fastq.gz', checkIfExists: true)] + ]) + """ + } + } + + then { + assertAll( + { assert process.success }, + { assert snapshot(process.out).match() } + ) + } + } + + test("test_cat_fastq_single_end_single_file - stub") { + + options "-stub" + + when { + process { + """ + input[0] = Channel.of([ + [ id:'test', single_end:true ], // meta map + [ file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test_1.fastq.gz', checkIfExists: true)] + ]) + """ + } + } + + then { + assertAll( + { assert process.success }, + { assert snapshot(process.out).match() } + ) + } + } + + test("test_cat_fastq_single_end_no_files") { + + when { + process { + """ + input[0] = Channel.of([ + [ id:'test', single_end:true ], // meta map + [] + ]) + """ + } + } + + then { + assertAll( + { assert process.failed }, + { assert snapshot(process.stdout.find { it.contains("-- Check script") }.split(" -- Check script")[0]).match() } + ) + } + } + + test("test_cat_fastq_paired_end_no_files") { + + when { + process { + """ + input[0] = Channel.of([ + [ id:'test', single_end:false ], // meta map + [] + ]) + """ + } + } + + then { + assertAll( + { assert process.failed }, + { assert snapshot(process.stdout.find { it.contains("-- Check script") }.split(" -- Check script")[0]).match() } + ) + } + } + + test("test_cat_fastq_single_end_no_files - stub") { + + options "-stub" + + when { + process { + """ + input[0] = Channel.of([ + [ id:'test', single_end:true ], // meta map + [] + ]) + """ + } + } + + then { + assertAll( + { assert process.failed }, + { assert snapshot(process.stdout.find { it.contains("-- Check script") }.split(" -- Check script")[0]).match() } + ) + } + } + + test("test_cat_fastq_paired_end_no_files - stub") { + + options "-stub" + + when { + process { + """ + input[0] = Channel.of([ + [ id:'test', single_end:false ], // meta map + [] + ]) + """ + } + } + + then { + assertAll( + { assert process.failed }, + { assert snapshot(process.stdout.find { it.contains("-- Check script") }.split(" -- Check script")[0]).match() } + ) + } + } +} diff --git a/modules/nf-core/cat/fastq/tests/main.nf.test.snap b/modules/nf-core/cat/fastq/tests/main.nf.test.snap new file mode 100644 index 0000000..6375b2a --- /dev/null +++ b/modules/nf-core/cat/fastq/tests/main.nf.test.snap @@ -0,0 +1,588 @@ +{ + "test_cat_fastq_paired_end_no_files - stub": { + "content": [ + " Could not find any FASTQ file pairs to concatenate in the process input" + ], + "meta": { + "nf-test": "0.9.2", + "nextflow": "24.10.4" + }, + "timestamp": "2025-02-25T17:14:51.248685461" + }, + "test_cat_fastq_single_end_single_file": { + "content": [ + { + "0": [ + [ + { + "id": "test", + "single_end": true + }, + "test.merged.fastq.gz:md5,4161df271f9bfcd25d5845a1e220dbec" + ] + ], + "1": [ + [ + "CAT_FASTQ", + "cat", + "9.5" + ] + ], + "reads": [ + [ + { + "id": "test", + "single_end": true + }, + "test.merged.fastq.gz:md5,4161df271f9bfcd25d5845a1e220dbec" + ] + ], + "versions_cat": [ + [ + "CAT_FASTQ", + "cat", + "9.5" + ] + ] + } + ], + "meta": { + "nf-test": "0.9.3", + "nextflow": "25.10.2" + }, + "timestamp": "2025-12-10T14:31:42.84401526" + }, + "test_cat_fastq_paired_end_same_name": { + "content": [ + { + "0": [ + [ + { + "id": "test", + "single_end": false + }, + [ + "test_1.merged.fastq.gz:md5,3ad9406595fafec8172368f9cd0b6a22", + "test_2.merged.fastq.gz:md5,a52cab0b840c7178b0ea83df1fdbe8d5" + ] + ] + ], + "1": [ + [ + "CAT_FASTQ", + "cat", + "9.5" + ] + ], + "reads": [ + [ + { + "id": "test", + "single_end": false + }, + [ + "test_1.merged.fastq.gz:md5,3ad9406595fafec8172368f9cd0b6a22", + "test_2.merged.fastq.gz:md5,a52cab0b840c7178b0ea83df1fdbe8d5" + ] + ] + ], + "versions_cat": [ + [ + "CAT_FASTQ", + "cat", + "9.5" + ] + ] + } + ], + "meta": { + "nf-test": "0.9.3", + "nextflow": "25.10.2" + }, + "timestamp": "2025-12-10T14:31:36.820489323" + }, + "test_cat_fastq_paired_end_same_name - stub": { + "content": [ + { + "0": [ + [ + { + "id": "test", + "single_end": false + }, + [ + "test_1.merged.fastq.gz:md5,68b329da9893e34099c7d8ad5cb9c940", + "test_2.merged.fastq.gz:md5,68b329da9893e34099c7d8ad5cb9c940" + ] + ] + ], + "1": [ + [ + "CAT_FASTQ", + "cat", + "9.5" + ] + ], + "reads": [ + [ + { + "id": "test", + "single_end": false + }, + [ + "test_1.merged.fastq.gz:md5,68b329da9893e34099c7d8ad5cb9c940", + "test_2.merged.fastq.gz:md5,68b329da9893e34099c7d8ad5cb9c940" + ] + ] + ], + "versions_cat": [ + [ + "CAT_FASTQ", + "cat", + "9.5" + ] + ] + } + ], + "meta": { + "nf-test": "0.9.3", + "nextflow": "25.10.2" + }, + "timestamp": "2025-12-10T14:32:06.262192935" + }, + "test_cat_fastq_single_end_uncompressed": { + "content": [ + { + "0": [ + [ + { + "id": "test", + "single_end": true + }, + "test.merged.fastq.gz:md5,ee314a9bd568d06617171b0c85f508da" + ] + ], + "1": [ + [ + "CAT_FASTQ", + "cat", + "9.5" + ] + ], + "reads": [ + [ + { + "id": "test", + "single_end": true + }, + "test.merged.fastq.gz:md5,ee314a9bd568d06617171b0c85f508da" + ] + ], + "versions_cat": [ + [ + "CAT_FASTQ", + "cat", + "9.5" + ] + ] + } + ], + "meta": { + "nf-test": "0.9.3", + "nextflow": "25.10.2" + }, + "timestamp": "2026-02-09T10:03:24.344628" + }, + "test_cat_fastq_paired_end_uncompressed": { + "content": [ + { + "0": [ + [ + { + "id": "test", + "single_end": false + }, + [ + "test_1.merged.fastq.gz:md5,3ad9406595fafec8172368f9cd0b6a22", + "test_2.merged.fastq.gz:md5,a52cab0b840c7178b0ea83df1fdbe8d5" + ] + ] + ], + "1": [ + [ + "CAT_FASTQ", + "cat", + "9.5" + ] + ], + "reads": [ + [ + { + "id": "test", + "single_end": false + }, + [ + "test_1.merged.fastq.gz:md5,3ad9406595fafec8172368f9cd0b6a22", + "test_2.merged.fastq.gz:md5,a52cab0b840c7178b0ea83df1fdbe8d5" + ] + ] + ], + "versions_cat": [ + [ + "CAT_FASTQ", + "cat", + "9.5" + ] + ] + } + ], + "meta": { + "nf-test": "0.9.3", + "nextflow": "25.10.2" + }, + "timestamp": "2026-02-09T10:03:37.568053" + }, + "test_cat_fastq_single_end": { + "content": [ + { + "0": [ + [ + { + "id": "test", + "single_end": true + }, + "test.merged.fastq.gz:md5,ee314a9bd568d06617171b0c85f508da" + ] + ], + "1": [ + [ + "CAT_FASTQ", + "cat", + "9.5" + ] + ], + "reads": [ + [ + { + "id": "test", + "single_end": true + }, + "test.merged.fastq.gz:md5,ee314a9bd568d06617171b0c85f508da" + ] + ], + "versions_cat": [ + [ + "CAT_FASTQ", + "cat", + "9.5" + ] + ] + } + ], + "meta": { + "nf-test": "0.9.3", + "nextflow": "25.10.2" + }, + "timestamp": "2025-12-10T14:31:18.859169785" + }, + "test_cat_fastq_single_end_same_name": { + "content": [ + { + "0": [ + [ + { + "id": "test", + "single_end": true + }, + "test.merged.fastq.gz:md5,3ad9406595fafec8172368f9cd0b6a22" + ] + ], + "1": [ + [ + "CAT_FASTQ", + "cat", + "9.5" + ] + ], + "reads": [ + [ + { + "id": "test", + "single_end": true + }, + "test.merged.fastq.gz:md5,3ad9406595fafec8172368f9cd0b6a22" + ] + ], + "versions_cat": [ + [ + "CAT_FASTQ", + "cat", + "9.5" + ] + ] + } + ], + "meta": { + "nf-test": "0.9.3", + "nextflow": "25.10.2" + }, + "timestamp": "2025-12-10T14:31:30.942615287" + }, + "test_cat_fastq_single_end - stub": { + "content": [ + { + "0": [ + [ + { + "id": "test", + "single_end": true + }, + "test.merged.fastq.gz:md5,68b329da9893e34099c7d8ad5cb9c940" + ] + ], + "1": [ + [ + "CAT_FASTQ", + "cat", + "9.5" + ] + ], + "reads": [ + [ + { + "id": "test", + "single_end": true + }, + "test.merged.fastq.gz:md5,68b329da9893e34099c7d8ad5cb9c940" + ] + ], + "versions_cat": [ + [ + "CAT_FASTQ", + "cat", + "9.5" + ] + ] + } + ], + "meta": { + "nf-test": "0.9.3", + "nextflow": "25.10.2" + }, + "timestamp": "2025-12-10T14:31:48.827990633" + }, + "test_cat_fastq_paired_end_no_files": { + "content": [ + " Could not find any FASTQ file pairs to concatenate in the process input" + ], + "meta": { + "nf-test": "0.9.2", + "nextflow": "24.10.4" + }, + "timestamp": "2025-02-25T17:14:40.806088747" + }, + "test_cat_fastq_single_end_no_files - stub": { + "content": [ + " Could not find any FASTQ files to concatenate in the process input" + ], + "meta": { + "nf-test": "0.9.2", + "nextflow": "24.10.4" + }, + "timestamp": "2025-02-25T17:14:45.852365218" + }, + "test_cat_fastq_single_end_same_name - stub": { + "content": [ + { + "0": [ + [ + { + "id": "test", + "single_end": true + }, + "test.merged.fastq.gz:md5,68b329da9893e34099c7d8ad5cb9c940" + ] + ], + "1": [ + [ + "CAT_FASTQ", + "cat", + "9.5" + ] + ], + "reads": [ + [ + { + "id": "test", + "single_end": true + }, + "test.merged.fastq.gz:md5,68b329da9893e34099c7d8ad5cb9c940" + ] + ], + "versions_cat": [ + [ + "CAT_FASTQ", + "cat", + "9.5" + ] + ] + } + ], + "meta": { + "nf-test": "0.9.3", + "nextflow": "25.10.2" + }, + "timestamp": "2025-12-10T14:32:00.586584379" + }, + "test_cat_fastq_paired_end": { + "content": [ + { + "0": [ + [ + { + "id": "test", + "single_end": false + }, + [ + "test_1.merged.fastq.gz:md5,3ad9406595fafec8172368f9cd0b6a22", + "test_2.merged.fastq.gz:md5,a52cab0b840c7178b0ea83df1fdbe8d5" + ] + ] + ], + "1": [ + [ + "CAT_FASTQ", + "cat", + "9.5" + ] + ], + "reads": [ + [ + { + "id": "test", + "single_end": false + }, + [ + "test_1.merged.fastq.gz:md5,3ad9406595fafec8172368f9cd0b6a22", + "test_2.merged.fastq.gz:md5,a52cab0b840c7178b0ea83df1fdbe8d5" + ] + ] + ], + "versions_cat": [ + [ + "CAT_FASTQ", + "cat", + "9.5" + ] + ] + } + ], + "meta": { + "nf-test": "0.9.3", + "nextflow": "25.10.2" + }, + "timestamp": "2025-12-10T14:31:25.159365603" + }, + "test_cat_fastq_single_end_no_files": { + "content": [ + " Could not find any FASTQ files to concatenate in the process input" + ], + "meta": { + "nf-test": "0.9.2", + "nextflow": "24.10.4" + }, + "timestamp": "2025-02-25T17:14:35.695192409" + }, + "test_cat_fastq_paired_end - stub": { + "content": [ + { + "0": [ + [ + { + "id": "test", + "single_end": false + }, + [ + "test_1.merged.fastq.gz:md5,68b329da9893e34099c7d8ad5cb9c940", + "test_2.merged.fastq.gz:md5,68b329da9893e34099c7d8ad5cb9c940" + ] + ] + ], + "1": [ + [ + "CAT_FASTQ", + "cat", + "9.5" + ] + ], + "reads": [ + [ + { + "id": "test", + "single_end": false + }, + [ + "test_1.merged.fastq.gz:md5,68b329da9893e34099c7d8ad5cb9c940", + "test_2.merged.fastq.gz:md5,68b329da9893e34099c7d8ad5cb9c940" + ] + ] + ], + "versions_cat": [ + [ + "CAT_FASTQ", + "cat", + "9.5" + ] + ] + } + ], + "meta": { + "nf-test": "0.9.3", + "nextflow": "25.10.2" + }, + "timestamp": "2025-12-10T14:31:54.850702874" + }, + "test_cat_fastq_single_end_single_file - stub": { + "content": [ + { + "0": [ + [ + { + "id": "test", + "single_end": true + }, + "test.merged.fastq.gz:md5,68b329da9893e34099c7d8ad5cb9c940" + ] + ], + "1": [ + [ + "CAT_FASTQ", + "cat", + "9.5" + ] + ], + "reads": [ + [ + { + "id": "test", + "single_end": true + }, + "test.merged.fastq.gz:md5,68b329da9893e34099c7d8ad5cb9c940" + ] + ], + "versions_cat": [ + [ + "CAT_FASTQ", + "cat", + "9.5" + ] + ] + } + ], + "meta": { + "nf-test": "0.9.3", + "nextflow": "25.10.2" + }, + "timestamp": "2025-12-10T14:32:11.746498148" + } +} \ No newline at end of file diff --git a/modules/nf-core/multiqc/main.nf b/modules/nf-core/multiqc/main.nf index 3b0e975..5376aea 100644 --- a/modules/nf-core/multiqc/main.nf +++ b/modules/nf-core/multiqc/main.nf @@ -1,25 +1,21 @@ process MULTIQC { + tag "${meta.id}" label 'process_single' conda "${moduleDir}/environment.yml" - container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? - 'https://community-cr-prod.seqera.io/docker/registry/v2/blobs/sha256/34/34e733a9ae16a27e80fe00f863ea1479c96416017f24a907996126283e7ecd4d/data' : - 'community.wave.seqera.io/library/multiqc:1.33--ee7739d47738383b' }" + container "${workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container + ? 'https://community-cr-prod.seqera.io/docker/registry/v2/blobs/sha256/34/34e733a9ae16a27e80fe00f863ea1479c96416017f24a907996126283e7ecd4d/data' + : 'community.wave.seqera.io/library/multiqc:1.33--ee7739d47738383b'}" input: - path multiqc_files, stageAs: "?/*" - path(multiqc_config) - path(extra_multiqc_config) - path(multiqc_logo) - path(replace_names) - path(sample_names) + tuple val(meta), path(multiqc_files, stageAs: "?/*"), path(multiqc_config, stageAs: "?/*"), path(multiqc_logo), path(replace_names), path(sample_names) output: - path "*.html" , emit: report - path "*_data" , emit: data - path "*_plots" , optional:true, emit: plots - tuple val("${task.process}"), val('multiqc'), eval('multiqc --version | sed "s/.* //g"'), emit: versions + tuple val(meta), path("*.html"), emit: report + tuple val(meta), path("*_data"), emit: data + tuple val(meta), path("*_plots"), emit: plots, optional: true // MultiQC should not push its versions to the `versions` topic. Its input depends on the versions topic to be resolved thus outputting to the topic will let the pipeline hang forever + tuple val("${task.process}"), val('multiqc'), eval('multiqc --version | sed "s/.* //g"'), emit: versions when: task.ext.when == null || task.ext.when @@ -27,8 +23,7 @@ process MULTIQC { script: def args = task.ext.args ?: '' def prefix = task.ext.prefix ? "--filename ${task.ext.prefix}.html" : '' - def config = multiqc_config ? "--config ${multiqc_config}" : '' - def extra_config = extra_multiqc_config ? "--config ${extra_multiqc_config}" : '' + def config = multiqc_config ? multiqc_config instanceof List ? "--config ${multiqc_config.join(' --config ')}" : "--config ${multiqc_config}" : "" def logo = multiqc_logo ? "--cl-config 'custom_logo: \"${multiqc_logo}\"'" : '' def replace = replace_names ? "--replace-names ${replace_names}" : '' def samples = sample_names ? "--sample-names ${sample_names}" : '' @@ -38,7 +33,6 @@ process MULTIQC { ${args} \\ ${config} \\ ${prefix} \\ - ${extra_config} \\ ${logo} \\ ${replace} \\ ${samples} \\ @@ -50,6 +44,7 @@ process MULTIQC { mkdir multiqc_data touch multiqc_data/.stub mkdir multiqc_plots + touch multiqc_plots/.stub touch multiqc_report.html """ } diff --git a/modules/nf-core/multiqc/meta.yml b/modules/nf-core/multiqc/meta.yml index 9fd34f3..ef434a9 100644 --- a/modules/nf-core/multiqc/meta.yml +++ b/modules/nf-core/multiqc/meta.yml @@ -1,6 +1,6 @@ name: multiqc -description: Aggregate results from bioinformatics analyses across many samples into - a single report +description: Aggregate results from bioinformatics analyses across many samples + into a single report keywords: - QC - bioinformatics tools @@ -12,67 +12,81 @@ tools: It's a general use tool, perfect for summarising the output from numerous bioinformatics tools. homepage: https://multiqc.info/ documentation: https://multiqc.info/docs/ - licence: ["GPL-3.0-or-later"] + licence: + - "GPL-3.0-or-later" identifier: biotools:multiqc input: - - multiqc_files: - type: file - description: | - List of reports / files recognised by MultiQC, for example the html and zip output of FastQC - ontologies: [] - - multiqc_config: - type: file - description: Optional config yml for MultiQC - pattern: "*.{yml,yaml}" - ontologies: - - edam: http://edamontology.org/format_3750 # YAML - - extra_multiqc_config: - type: file - description: Second optional config yml for MultiQC. Will override common sections - in multiqc_config. - pattern: "*.{yml,yaml}" - ontologies: - - edam: http://edamontology.org/format_3750 # YAML - - multiqc_logo: - type: file - description: Optional logo file for MultiQC - pattern: "*.{png}" - ontologies: [] - - replace_names: - type: file - description: | - Optional two-column sample renaming file. First column a set of - patterns, second column a set of corresponding replacements. Passed via - MultiQC's `--replace-names` option. - pattern: "*.{tsv}" - ontologies: - - edam: http://edamontology.org/format_3475 # TSV - - sample_names: - type: file - description: | - Optional TSV file with headers, passed to the MultiQC --sample_names - argument. - pattern: "*.{tsv}" - ontologies: - - edam: http://edamontology.org/format_3475 # TSV -output: - report: - - "*.html": + - - meta: + type: map + description: | + Groovy Map containing sample information + e.g. [ id:'sample1', single_end:false ] + - multiqc_files: type: file - description: MultiQC report file - pattern: ".html" + description: | + List of reports / files recognised by MultiQC, for example the html and zip output of FastQC ontologies: [] - data: - - "*_data": - type: directory - description: MultiQC data dir - pattern: "multiqc_data" - plots: - - "*_plots": + - multiqc_config: type: file - description: Plots created by MultiQC - pattern: "*_plots" + description: Optional config yml for MultiQC + pattern: "*.{yml,yaml}" + ontologies: + - edam: http://edamontology.org/format_3750 + - multiqc_logo: + type: file + description: Optional logo file for MultiQC + pattern: "*.{png}" ontologies: [] + - replace_names: + type: file + description: | + Optional two-column sample renaming file. First column a set of + patterns, second column a set of corresponding replacements. Passed via + MultiQC's `--replace-names` option. + pattern: "*.{tsv}" + ontologies: + - edam: http://edamontology.org/format_3475 + - sample_names: + type: file + description: | + Optional TSV file with headers, passed to the MultiQC --sample_names + argument. + pattern: "*.{tsv}" + ontologies: + - edam: http://edamontology.org/format_3475 +output: + report: + - - meta: + type: map + description: | + Groovy Map containing sample information + e.g. [ id:'sample1', single_end:false ] + - "*.html": + type: file + description: MultiQC report file + pattern: ".html" + ontologies: [] + data: + - - meta: + type: map + description: | + Groovy Map containing sample information + e.g. [ id:'sample1', single_end:false ] + - "*_data": + type: directory + description: MultiQC data dir + pattern: "multiqc_data" + plots: + - - meta: + type: map + description: | + Groovy Map containing sample information + e.g. [ id:'sample1', single_end:false ] + - "*_plots": + type: file + description: Plots created by MultiQC + pattern: "*_plots" + ontologies: [] versions: - - ${task.process}: type: string diff --git a/modules/nf-core/multiqc/tests/custom_prefix.config b/modules/nf-core/multiqc/tests/custom_prefix.config index b30b135..4bc66e3 100644 --- a/modules/nf-core/multiqc/tests/custom_prefix.config +++ b/modules/nf-core/multiqc/tests/custom_prefix.config @@ -1,5 +1,5 @@ process { - withName: 'MULTIQC' { + withName: MULTIQC { ext.prefix = "custom_prefix" } } diff --git a/modules/nf-core/multiqc/tests/main.nf.test b/modules/nf-core/multiqc/tests/main.nf.test index d1ae8b0..4cbdb95 100644 --- a/modules/nf-core/multiqc/tests/main.nf.test +++ b/modules/nf-core/multiqc/tests/main.nf.test @@ -15,25 +15,41 @@ nextflow_process { when { process { """ - input[0] = Channel.of(file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastqc/test_fastqc.zip', checkIfExists: true)) - input[1] = [] - input[2] = [] - input[3] = [] - input[4] = [] - input[5] = [] + input[0] = channel.of([ + [ id: 'FASTQC' ], + file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastqc/test_fastqc.zip', checkIfExists: true), + [], + [], + [], + [] + ]) """ } } then { - assertAll( - { assert process.success }, - { assert process.out.report[0] ==~ ".*/multiqc_report.html" }, - { assert process.out.data[0] ==~ ".*/multiqc_data" }, - { assert snapshot(process.out.findAll { key, val -> key.startsWith("versions")}).match() } - ) + assert process.success + assert snapshot( + sanitizeOutput(process.out).collectEntries { key, val -> + if (key == "data") { + return [key, val.collect { [path(it[1]).list().collect { file(it.toString()).name }] }] + } + else if (key == "plots") { + return [key, val.collect { [ + "pdf", + path("${it[1]}/pdf").list().collect { file(it.toString()).name }, + "png", + path("${it[1]}/png").list().collect { file(it.toString()).name }, + "svg", + path("${it[1]}/svg").list().collect { file(it.toString()).name }] }] + } + else if (key == "report") { + return [key, file(val[0][1].toString()).name] + } + return [key, val] + } + ).match() } - } test("sarscov2 single-end [fastqc] - custom prefix") { @@ -42,24 +58,41 @@ nextflow_process { when { process { """ - input[0] = Channel.of(file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastqc/test_fastqc.zip', checkIfExists: true)) - input[1] = [] - input[2] = [] - input[3] = [] - input[4] = [] - input[5] = [] + input[0] = channel.of([ + [ id: 'FASTQC' ], + file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastqc/test_fastqc.zip', checkIfExists: true), + [], + [], + [], + [] + ]) """ } } then { - assertAll( - { assert process.success }, - { assert process.out.report[0] ==~ ".*/custom_prefix.html" }, - { assert process.out.data[0] ==~ ".*/custom_prefix_data" } - ) + assert process.success + assert snapshot( + sanitizeOutput(process.out).collectEntries { key, val -> + if (key == "data") { + return [key, val.collect { [path(it[1]).list().collect { file(it.toString()).name }] }] + } + else if (key == "plots") { + return [key, val.collect { [ + "pdf", + path("${it[1]}/pdf").list().collect { file(it.toString()).name }, + "png", + path("${it[1]}/png").list().collect { file(it.toString()).name }, + "svg", + path("${it[1]}/svg").list().collect { file(it.toString()).name }] }] + } + else if (key == "report") { + return [key, file(val[0][1].toString()).name] + } + return [key, val] + } + ).match() } - } test("sarscov2 single-end [fastqc] [config]") { @@ -67,23 +100,85 @@ nextflow_process { when { process { """ - input[0] = Channel.of(file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastqc/test_fastqc.zip', checkIfExists: true)) - input[1] = Channel.of(file("https://github.com/nf-core/tools/raw/dev/nf_core/pipeline-template/assets/multiqc_config.yml", checkIfExists: true)) - input[2] = [] - input[3] = [] - input[4] = [] - input[5] = [] + input[0] = channel.of([ + [ id: 'FASTQC' ], + file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastqc/test_fastqc.zip', checkIfExists: true), + file("https://raw.githubusercontent.com/nf-core/seqinspector/1.0.0/assets/multiqc_config.yml", checkIfExists: true), + [], + [], + [] + ]) """ } } then { - assertAll( - { assert process.success }, - { assert process.out.report[0] ==~ ".*/multiqc_report.html" }, - { assert process.out.data[0] ==~ ".*/multiqc_data" }, - { assert snapshot(process.out.findAll { key, val -> key.startsWith("versions")}).match() } - ) + assert process.success + assert snapshot( + sanitizeOutput(process.out).collectEntries { key, val -> + if (key == "data") { + return [key, val.collect { [path(it[1]).list().collect { file(it.toString()).name }] }] + } + else if (key == "plots") { + return [key, val.collect { [ + "pdf", + path("${it[1]}/pdf").list().collect { file(it.toString()).name }, + "png", + path("${it[1]}/png").list().collect { file(it.toString()).name }, + "svg", + path("${it[1]}/svg").list().collect { file(it.toString()).name }] }] + } + else if (key == "report") { + return [key, file(val[0][1].toString()).name] + } + return [key, val] + } + ).match() + } + } + + test("sarscov2 single-end [fastqc] [multiple configs]") { + + when { + process { + """ + input[0] = channel.of([ + [ id: 'FASTQC' ], + file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastqc/test_fastqc.zip', checkIfExists: true), + [ + file("https://raw.githubusercontent.com/nf-core/seqinspector/1.0.0/assets/multiqc_config.yml", checkIfExists: true), + file("https://raw.githubusercontent.com/nf-core/seqinspector/1.0.0/assets/multiqc_config.yml", checkIfExists: true) + ], + [], + [], + [] + ]) + """ + } + } + + then { + assert process.success + assert snapshot( + sanitizeOutput(process.out).collectEntries { key, val -> + if (key == "data") { + return [key, val.collect { [path(it[1]).list().collect { file(it.toString()).name }] }] + } + else if (key == "plots") { + return [key, val.collect { [ + "pdf", + path("${it[1]}/pdf").list().collect { file(it.toString()).name }, + "png", + path("${it[1]}/png").list().collect { file(it.toString()).name }, + "svg", + path("${it[1]}/svg").list().collect { file(it.toString()).name }] }] + } + else if (key == "report") { + return [key, file(val[0][1].toString()).name] + } + return [key, val] + } + ).match() } } @@ -94,25 +189,23 @@ nextflow_process { when { process { """ - input[0] = Channel.of(file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastqc/test_fastqc.zip', checkIfExists: true)) - input[1] = [] - input[2] = [] - input[3] = [] - input[4] = [] - input[5] = [] + input[0] = channel.of([ + [ id: 'FASTQC' ], + file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastqc/test_fastqc.zip', checkIfExists: true), + [], + [], + [], + [] + ]) """ } } then { + assert process.success assertAll( - { assert process.success }, - { assert snapshot(process.out.report.collect { file(it).getName() } + - process.out.data.collect { file(it).getName() } + - process.out.plots.collect { file(it).getName() } + - process.out.findAll { key, val -> key.startsWith("versions")} ).match() } + { assert snapshot(sanitizeOutput(process.out)).match() } ) } - } } diff --git a/modules/nf-core/multiqc/tests/main.nf.test.snap b/modules/nf-core/multiqc/tests/main.nf.test.snap index d72d35b..3bfc524 100644 --- a/modules/nf-core/multiqc/tests/main.nf.test.snap +++ b/modules/nf-core/multiqc/tests/main.nf.test.snap @@ -1,7 +1,176 @@ { + "sarscov2 single-end [fastqc] [multiple configs]": { + "content": [ + { + "data": [ + [ + [ + "fastqc-status-check-heatmap.txt", + "fastqc_overrepresented_sequences_plot.txt", + "fastqc_per_base_n_content_plot.txt", + "fastqc_per_base_sequence_quality_plot.txt", + "fastqc_per_sequence_gc_content_plot_Counts.txt", + "fastqc_per_sequence_gc_content_plot_Percentages.txt", + "fastqc_per_sequence_quality_scores_plot.txt", + "fastqc_sequence_counts_plot.txt", + "fastqc_sequence_duplication_levels_plot.txt", + "fastqc_sequence_length_distribution_plot.txt", + "fastqc_top_overrepresented_sequences_table.txt", + "llms-full.txt", + "multiqc.log", + "multiqc.parquet", + "multiqc_citations.txt", + "multiqc_data.json", + "multiqc_fastqc.txt", + "multiqc_general_stats.txt", + "multiqc_sources.txt" + ] + ] + ], + "plots": [ + [ + "pdf", + [ + "fastqc-status-check-heatmap.pdf", + "fastqc_overrepresented_sequences_plot.pdf", + "fastqc_per_base_n_content_plot.pdf", + "fastqc_per_base_sequence_quality_plot.pdf", + "fastqc_per_sequence_gc_content_plot_Counts.pdf", + "fastqc_per_sequence_gc_content_plot_Percentages.pdf", + "fastqc_per_sequence_quality_scores_plot.pdf", + "fastqc_sequence_counts_plot-cnt.pdf", + "fastqc_sequence_counts_plot-pct.pdf", + "fastqc_sequence_duplication_levels_plot.pdf", + "fastqc_sequence_length_distribution_plot.pdf", + "fastqc_top_overrepresented_sequences_table.pdf" + ], + "png", + [ + "fastqc-status-check-heatmap.png", + "fastqc_overrepresented_sequences_plot.png", + "fastqc_per_base_n_content_plot.png", + "fastqc_per_base_sequence_quality_plot.png", + "fastqc_per_sequence_gc_content_plot_Counts.png", + "fastqc_per_sequence_gc_content_plot_Percentages.png", + "fastqc_per_sequence_quality_scores_plot.png", + "fastqc_sequence_counts_plot-cnt.png", + "fastqc_sequence_counts_plot-pct.png", + "fastqc_sequence_duplication_levels_plot.png", + "fastqc_sequence_length_distribution_plot.png", + "fastqc_top_overrepresented_sequences_table.png" + ], + "svg", + [ + "fastqc-status-check-heatmap.svg", + "fastqc_overrepresented_sequences_plot.svg", + "fastqc_per_base_n_content_plot.svg", + "fastqc_per_base_sequence_quality_plot.svg", + "fastqc_per_sequence_gc_content_plot_Counts.svg", + "fastqc_per_sequence_gc_content_plot_Percentages.svg", + "fastqc_per_sequence_quality_scores_plot.svg", + "fastqc_sequence_counts_plot-cnt.svg", + "fastqc_sequence_counts_plot-pct.svg", + "fastqc_sequence_duplication_levels_plot.svg", + "fastqc_sequence_length_distribution_plot.svg", + "fastqc_top_overrepresented_sequences_table.svg" + ] + ] + ], + "report": "multiqc_report.html", + "versions": [ + [ + "MULTIQC", + "multiqc", + "1.33" + ] + ] + } + ], + "timestamp": "2026-03-17T16:15:42.577775492", + "meta": { + "nf-test": "0.9.4", + "nextflow": "25.10.4" + } + }, "sarscov2 single-end [fastqc]": { "content": [ { + "data": [ + [ + [ + "fastqc-status-check-heatmap.txt", + "fastqc_overrepresented_sequences_plot.txt", + "fastqc_per_base_n_content_plot.txt", + "fastqc_per_base_sequence_quality_plot.txt", + "fastqc_per_sequence_gc_content_plot_Counts.txt", + "fastqc_per_sequence_gc_content_plot_Percentages.txt", + "fastqc_per_sequence_quality_scores_plot.txt", + "fastqc_sequence_counts_plot.txt", + "fastqc_sequence_duplication_levels_plot.txt", + "fastqc_sequence_length_distribution_plot.txt", + "fastqc_top_overrepresented_sequences_table.txt", + "llms-full.txt", + "multiqc.log", + "multiqc.parquet", + "multiqc_citations.txt", + "multiqc_data.json", + "multiqc_fastqc.txt", + "multiqc_general_stats.txt", + "multiqc_software_versions.txt", + "multiqc_sources.txt" + ] + ] + ], + "plots": [ + [ + "pdf", + [ + "fastqc-status-check-heatmap.pdf", + "fastqc_overrepresented_sequences_plot.pdf", + "fastqc_per_base_n_content_plot.pdf", + "fastqc_per_base_sequence_quality_plot.pdf", + "fastqc_per_sequence_gc_content_plot_Counts.pdf", + "fastqc_per_sequence_gc_content_plot_Percentages.pdf", + "fastqc_per_sequence_quality_scores_plot.pdf", + "fastqc_sequence_counts_plot-cnt.pdf", + "fastqc_sequence_counts_plot-pct.pdf", + "fastqc_sequence_duplication_levels_plot.pdf", + "fastqc_sequence_length_distribution_plot.pdf", + "fastqc_top_overrepresented_sequences_table.pdf" + ], + "png", + [ + "fastqc-status-check-heatmap.png", + "fastqc_overrepresented_sequences_plot.png", + "fastqc_per_base_n_content_plot.png", + "fastqc_per_base_sequence_quality_plot.png", + "fastqc_per_sequence_gc_content_plot_Counts.png", + "fastqc_per_sequence_gc_content_plot_Percentages.png", + "fastqc_per_sequence_quality_scores_plot.png", + "fastqc_sequence_counts_plot-cnt.png", + "fastqc_sequence_counts_plot-pct.png", + "fastqc_sequence_duplication_levels_plot.png", + "fastqc_sequence_length_distribution_plot.png", + "fastqc_top_overrepresented_sequences_table.png" + ], + "svg", + [ + "fastqc-status-check-heatmap.svg", + "fastqc_overrepresented_sequences_plot.svg", + "fastqc_per_base_n_content_plot.svg", + "fastqc_per_base_sequence_quality_plot.svg", + "fastqc_per_sequence_gc_content_plot_Counts.svg", + "fastqc_per_sequence_gc_content_plot_Percentages.svg", + "fastqc_per_sequence_quality_scores_plot.svg", + "fastqc_sequence_counts_plot-cnt.svg", + "fastqc_sequence_counts_plot-pct.svg", + "fastqc_sequence_duplication_levels_plot.svg", + "fastqc_sequence_length_distribution_plot.svg", + "fastqc_top_overrepresented_sequences_table.svg" + ] + ] + ], + "report": "multiqc_report.html", "versions": [ [ "MULTIQC", @@ -11,38 +180,230 @@ ] } ], + "timestamp": "2026-03-17T16:21:17.072841555", "meta": { - "nf-test": "0.9.3", - "nextflow": "25.10.2" - }, - "timestamp": "2025-12-09T10:10:43.020315838" + "nf-test": "0.9.4", + "nextflow": "25.10.4" + } }, "sarscov2 single-end [fastqc] - stub": { "content": [ - [ - "multiqc_report.html", - "multiqc_data", - "multiqc_plots", - { - "versions": [ + { + "data": [ + [ + { + "id": "FASTQC" + }, + [ + ".stub:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ] + ], + "plots": [ + [ + { + "id": "FASTQC" + }, [ - "MULTIQC", - "multiqc", - "1.33" + ".stub:md5,d41d8cd98f00b204e9800998ecf8427e" ] ] - } - ] + ], + "report": [ + [ + { + "id": "FASTQC" + }, + "multiqc_report.html:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "versions": [ + [ + "MULTIQC", + "multiqc", + "1.33" + ] + ] + } ], + "timestamp": "2026-02-26T15:14:39.789193051", "meta": { - "nf-test": "0.9.3", - "nextflow": "25.10.2" - }, - "timestamp": "2025-12-09T10:11:14.131950776" + "nf-test": "0.9.4", + "nextflow": "25.10.4" + } }, "sarscov2 single-end [fastqc] [config]": { "content": [ { + "data": [ + [ + [ + "fastqc-status-check-heatmap.txt", + "fastqc_overrepresented_sequences_plot.txt", + "fastqc_per_base_n_content_plot.txt", + "fastqc_per_base_sequence_quality_plot.txt", + "fastqc_per_sequence_gc_content_plot_Counts.txt", + "fastqc_per_sequence_gc_content_plot_Percentages.txt", + "fastqc_per_sequence_quality_scores_plot.txt", + "fastqc_sequence_counts_plot.txt", + "fastqc_sequence_duplication_levels_plot.txt", + "fastqc_sequence_length_distribution_plot.txt", + "fastqc_top_overrepresented_sequences_table.txt", + "llms-full.txt", + "multiqc.log", + "multiqc.parquet", + "multiqc_citations.txt", + "multiqc_data.json", + "multiqc_fastqc.txt", + "multiqc_general_stats.txt", + "multiqc_sources.txt" + ] + ] + ], + "plots": [ + [ + "pdf", + [ + "fastqc-status-check-heatmap.pdf", + "fastqc_overrepresented_sequences_plot.pdf", + "fastqc_per_base_n_content_plot.pdf", + "fastqc_per_base_sequence_quality_plot.pdf", + "fastqc_per_sequence_gc_content_plot_Counts.pdf", + "fastqc_per_sequence_gc_content_plot_Percentages.pdf", + "fastqc_per_sequence_quality_scores_plot.pdf", + "fastqc_sequence_counts_plot-cnt.pdf", + "fastqc_sequence_counts_plot-pct.pdf", + "fastqc_sequence_duplication_levels_plot.pdf", + "fastqc_sequence_length_distribution_plot.pdf", + "fastqc_top_overrepresented_sequences_table.pdf" + ], + "png", + [ + "fastqc-status-check-heatmap.png", + "fastqc_overrepresented_sequences_plot.png", + "fastqc_per_base_n_content_plot.png", + "fastqc_per_base_sequence_quality_plot.png", + "fastqc_per_sequence_gc_content_plot_Counts.png", + "fastqc_per_sequence_gc_content_plot_Percentages.png", + "fastqc_per_sequence_quality_scores_plot.png", + "fastqc_sequence_counts_plot-cnt.png", + "fastqc_sequence_counts_plot-pct.png", + "fastqc_sequence_duplication_levels_plot.png", + "fastqc_sequence_length_distribution_plot.png", + "fastqc_top_overrepresented_sequences_table.png" + ], + "svg", + [ + "fastqc-status-check-heatmap.svg", + "fastqc_overrepresented_sequences_plot.svg", + "fastqc_per_base_n_content_plot.svg", + "fastqc_per_base_sequence_quality_plot.svg", + "fastqc_per_sequence_gc_content_plot_Counts.svg", + "fastqc_per_sequence_gc_content_plot_Percentages.svg", + "fastqc_per_sequence_quality_scores_plot.svg", + "fastqc_sequence_counts_plot-cnt.svg", + "fastqc_sequence_counts_plot-pct.svg", + "fastqc_sequence_duplication_levels_plot.svg", + "fastqc_sequence_length_distribution_plot.svg", + "fastqc_top_overrepresented_sequences_table.svg" + ] + ] + ], + "report": "multiqc_report.html", + "versions": [ + [ + "MULTIQC", + "multiqc", + "1.33" + ] + ] + } + ], + "timestamp": "2026-03-17T16:15:30.372239611", + "meta": { + "nf-test": "0.9.4", + "nextflow": "25.10.4" + } + }, + "sarscov2 single-end [fastqc] - custom prefix": { + "content": [ + { + "data": [ + [ + [ + "fastqc-status-check-heatmap.txt", + "fastqc_overrepresented_sequences_plot.txt", + "fastqc_per_base_n_content_plot.txt", + "fastqc_per_base_sequence_quality_plot.txt", + "fastqc_per_sequence_gc_content_plot_Counts.txt", + "fastqc_per_sequence_gc_content_plot_Percentages.txt", + "fastqc_per_sequence_quality_scores_plot.txt", + "fastqc_sequence_counts_plot.txt", + "fastqc_sequence_duplication_levels_plot.txt", + "fastqc_sequence_length_distribution_plot.txt", + "fastqc_top_overrepresented_sequences_table.txt", + "llms-full.txt", + "multiqc.log", + "multiqc.parquet", + "multiqc_citations.txt", + "multiqc_data.json", + "multiqc_fastqc.txt", + "multiqc_general_stats.txt", + "multiqc_software_versions.txt", + "multiqc_sources.txt" + ] + ] + ], + "plots": [ + [ + "pdf", + [ + "fastqc-status-check-heatmap.pdf", + "fastqc_overrepresented_sequences_plot.pdf", + "fastqc_per_base_n_content_plot.pdf", + "fastqc_per_base_sequence_quality_plot.pdf", + "fastqc_per_sequence_gc_content_plot_Counts.pdf", + "fastqc_per_sequence_gc_content_plot_Percentages.pdf", + "fastqc_per_sequence_quality_scores_plot.pdf", + "fastqc_sequence_counts_plot-cnt.pdf", + "fastqc_sequence_counts_plot-pct.pdf", + "fastqc_sequence_duplication_levels_plot.pdf", + "fastqc_sequence_length_distribution_plot.pdf", + "fastqc_top_overrepresented_sequences_table.pdf" + ], + "png", + [ + "fastqc-status-check-heatmap.png", + "fastqc_overrepresented_sequences_plot.png", + "fastqc_per_base_n_content_plot.png", + "fastqc_per_base_sequence_quality_plot.png", + "fastqc_per_sequence_gc_content_plot_Counts.png", + "fastqc_per_sequence_gc_content_plot_Percentages.png", + "fastqc_per_sequence_quality_scores_plot.png", + "fastqc_sequence_counts_plot-cnt.png", + "fastqc_sequence_counts_plot-pct.png", + "fastqc_sequence_duplication_levels_plot.png", + "fastqc_sequence_length_distribution_plot.png", + "fastqc_top_overrepresented_sequences_table.png" + ], + "svg", + [ + "fastqc-status-check-heatmap.svg", + "fastqc_overrepresented_sequences_plot.svg", + "fastqc_per_base_n_content_plot.svg", + "fastqc_per_base_sequence_quality_plot.svg", + "fastqc_per_sequence_gc_content_plot_Counts.svg", + "fastqc_per_sequence_gc_content_plot_Percentages.svg", + "fastqc_per_sequence_quality_scores_plot.svg", + "fastqc_sequence_counts_plot-cnt.svg", + "fastqc_sequence_counts_plot-pct.svg", + "fastqc_sequence_duplication_levels_plot.svg", + "fastqc_sequence_length_distribution_plot.svg", + "fastqc_top_overrepresented_sequences_table.svg" + ] + ] + ], + "report": "custom_prefix.html", "versions": [ [ "MULTIQC", @@ -52,10 +413,10 @@ ] } ], + "timestamp": "2026-03-17T16:15:18.189023981", "meta": { - "nf-test": "0.9.3", - "nextflow": "25.10.2" - }, - "timestamp": "2025-12-09T10:11:07.15692209" + "nf-test": "0.9.4", + "nextflow": "25.10.4" + } } } \ No newline at end of file diff --git a/modules/nf-core/multiqc/tests/nextflow.config b/modules/nf-core/multiqc/tests/nextflow.config index c537a6a..9b30750 100644 --- a/modules/nf-core/multiqc/tests/nextflow.config +++ b/modules/nf-core/multiqc/tests/nextflow.config @@ -1,5 +1,6 @@ process { - withName: 'MULTIQC' { + withName: MULTIQC { ext.prefix = null + ext.args = '-p' } } diff --git a/modules/nf-core/pear/main.nf b/modules/nf-core/pear/main.nf index 891cd06..1311e51 100644 --- a/modules/nf-core/pear/main.nf +++ b/modules/nf-core/pear/main.nf @@ -1,20 +1,20 @@ process PEAR { - tag "$meta.id" + tag "${meta.id}" label 'process_low' conda "${moduleDir}/environment.yml" - container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? - 'https://depot.galaxyproject.org/singularity/pear:0.9.6--h67092d7_8': - 'biocontainers/pear:0.9.6--h67092d7_8' }" + container "${workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container + ? 'https://depot.galaxyproject.org/singularity/pear:0.9.6--h67092d7_8' + : 'biocontainers/pear:0.9.6--h67092d7_8'}" input: tuple val(meta), path(reads) output: - tuple val(meta), path("*.assembled.fastq.gz") , emit: assembled - tuple val(meta), path("*.unassembled.forward.fastq.gz"), path("*.unassembled.reverse.fastq.gz") , emit: unassembled - tuple val(meta), path("*.discarded.fastq.gz") , emit: discarded - tuple val("${task.process}"), val('pear'), eval("pear -h | grep 'PEAR v' | sed 's/PEAR v//' | sed 's/ .*//'") , topic: versions, emit: versions_pear + tuple val(meta), path("*.assembled.fastq.gz"), emit: assembled + tuple val(meta), path("*.unassembled.forward.fastq.gz"), path("*.unassembled.reverse.fastq.gz"), emit: unassembled + tuple val(meta), path("*.discarded.fastq.gz"), emit: discarded + tuple val("${task.process}"), val('pear'), eval("pear -h | grep 'PEAR v' | sed 's/PEAR v//' | sed 's/ .*//'"), topic: versions, emit: versions_pear when: task.ext.when == null || task.ext.when @@ -28,9 +28,9 @@ process PEAR { pear \\ -f ${reads[0].baseName} \\ -r ${reads[1].baseName} \\ - -o $prefix \\ - -j $task.cpus \\ - $args + -o ${prefix} \\ + -j ${task.cpus} \\ + ${args} gzip -f ${prefix}.assembled.fastq gzip -f ${prefix}.unassembled.forward.fastq gzip -f ${prefix}.unassembled.reverse.fastq diff --git a/modules/nf-core/samtools/fastq/environment.yml b/modules/nf-core/samtools/fastq/environment.yml index 89e12a6..946bb36 100644 --- a/modules/nf-core/samtools/fastq/environment.yml +++ b/modules/nf-core/samtools/fastq/environment.yml @@ -5,6 +5,6 @@ channels: - bioconda dependencies: # renovate: datasource=conda depName=bioconda/htslib - - bioconda::htslib=1.22.1 + - bioconda::htslib=1.23.1 # renovate: datasource=conda depName=bioconda/samtools - - bioconda::samtools=1.22.1 + - bioconda::samtools=1.23.1 diff --git a/modules/nf-core/samtools/fastq/main.nf b/modules/nf-core/samtools/fastq/main.nf index 922dbec..3973f1e 100644 --- a/modules/nf-core/samtools/fastq/main.nf +++ b/modules/nf-core/samtools/fastq/main.nf @@ -1,21 +1,21 @@ process SAMTOOLS_FASTQ { - tag "$meta.id" + tag "${meta.id}" label 'process_low' conda "${moduleDir}/environment.yml" - container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? - 'https://depot.galaxyproject.org/singularity/samtools:1.22.1--h96c455f_0' : - 'biocontainers/samtools:1.22.1--h96c455f_0' }" + container "${workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container + ? 'https://community-cr-prod.seqera.io/docker/registry/v2/blobs/sha256/8c/8c5d2818c8b9f58e1fba77ce219fdaf32087ae53e857c4a496402978af26e78c/data' + : 'community.wave.seqera.io/library/htslib_samtools:1.23.1--5b6bb4ede7e612e5'}" input: tuple val(meta), path(input) - val(interleave) + val interleave output: - tuple val(meta), path("*_{1,2}.fastq.gz") , optional:true, emit: fastq - tuple val(meta), path("*_interleaved.fastq") , optional:true, emit: interleaved - tuple val(meta), path("*_singleton.fastq.gz") , optional:true, emit: singleton - tuple val(meta), path("*_other.fastq.gz") , optional:true, emit: other + tuple val(meta), path("*_{1,2}.fastq.gz"), optional: true, emit: fastq + tuple val(meta), path("*_interleaved.fastq"), optional: true, emit: interleaved + tuple val(meta), path("*_singleton.fastq.gz"), optional: true, emit: singleton + tuple val(meta), path("*_other.fastq.gz"), optional: true, emit: other tuple val("${task.process}"), val('samtools'), eval("samtools version | sed '1!d;s/.* //'"), emit: versions_samtools, topic: versions when: @@ -24,25 +24,29 @@ process SAMTOOLS_FASTQ { script: def args = task.ext.args ?: '' def prefix = task.ext.prefix ?: "${meta.id}" - def output = ( interleave && ! meta.single_end ) ? "> ${prefix}_interleaved.fastq" : - meta.single_end ? "-1 ${prefix}_1.fastq.gz -s ${prefix}_singleton.fastq.gz" : - "-1 ${prefix}_1.fastq.gz -2 ${prefix}_2.fastq.gz -s ${prefix}_singleton.fastq.gz" + def output = interleave && !meta.single_end + ? "> ${prefix}_interleaved.fastq" + : meta.single_end + ? "-1 ${prefix}_1.fastq.gz -s ${prefix}_singleton.fastq.gz" + : "-1 ${prefix}_1.fastq.gz -2 ${prefix}_2.fastq.gz -s ${prefix}_singleton.fastq.gz" """ # Note: --threads value represents *additional* CPUs to allocate (total CPUs = 1 + --threads). samtools \\ fastq \\ - $args \\ - --threads ${task.cpus-1} \\ + ${args} \\ + --threads ${task.cpus - 1} \\ -0 ${prefix}_other.fastq.gz \\ - $input \\ - $output + ${input} \\ + ${output} """ stub: def prefix = task.ext.prefix ?: "${meta.id}" - def output = ( interleave && ! meta.single_end ) ? "touch ${prefix}_interleaved.fastq" : - meta.single_end ? "echo | gzip > ${prefix}_1.fastq.gz && echo | gzip > ${prefix}_singleton.fastq.gz" : - "echo | gzip > ${prefix}_1.fastq.gz && echo | gzip > ${prefix}_2.fastq.gz && echo | gzip > ${prefix}_singleton.fastq.gz" + def output = interleave && !meta.single_end + ? "touch ${prefix}_interleaved.fastq" + : meta.single_end + ? "echo | gzip > ${prefix}_1.fastq.gz && echo | gzip > ${prefix}_singleton.fastq.gz" + : "echo | gzip > ${prefix}_1.fastq.gz && echo | gzip > ${prefix}_2.fastq.gz && echo | gzip > ${prefix}_singleton.fastq.gz" """ ${output} echo | gzip > ${prefix}_other.fastq.gz diff --git a/modules/nf-core/samtools/fastq/meta.yml b/modules/nf-core/samtools/fastq/meta.yml index cab17ff..ba92977 100644 --- a/modules/nf-core/samtools/fastq/meta.yml +++ b/modules/nf-core/samtools/fastq/meta.yml @@ -109,3 +109,4 @@ authors: maintainers: - "@priyanka-surana" - "@suzannejin" + - "@matthdsm" diff --git a/modules/nf-core/samtools/fastq/tests/main.nf.test.snap b/modules/nf-core/samtools/fastq/tests/main.nf.test.snap index 17b5ade..88d2bdf 100644 --- a/modules/nf-core/samtools/fastq/tests/main.nf.test.snap +++ b/modules/nf-core/samtools/fastq/tests/main.nf.test.snap @@ -67,16 +67,16 @@ [ "SAMTOOLS_FASTQ", "samtools", - "1.22.1" + "1.23.1" ] ] } ], "meta": { "nf-test": "0.9.3", - "nextflow": "25.10.2" + "nextflow": "25.10.4" }, - "timestamp": "2026-02-02T17:05:55.514934" + "timestamp": "2026-03-19T08:58:51.815096" }, "bam_fastq": { "content": [ @@ -148,16 +148,16 @@ [ "SAMTOOLS_FASTQ", "samtools", - "1.22.1" + "1.23.1" ] ] } ], "meta": { "nf-test": "0.9.3", - "nextflow": "25.10.2" + "nextflow": "25.10.4" }, - "timestamp": "2026-02-02T17:05:40.578464" + "timestamp": "2026-03-19T08:58:41.34399" }, "bam_verinterleave_sions": { "content": [ @@ -166,16 +166,16 @@ [ "SAMTOOLS_FASTQ", "samtools", - "1.22.1" + "1.23.1" ] ] } ], "meta": { "nf-test": "0.9.3", - "nextflow": "25.10.2" + "nextflow": "25.10.4" }, - "timestamp": "2026-02-02T17:05:47.62481" + "timestamp": "2026-03-19T08:58:46.729284" }, "bam_singleton": { "content": [ @@ -230,15 +230,15 @@ [ "SAMTOOLS_FASTQ", "samtools", - "1.22.1" + "1.23.1" ] ] } ], "meta": { "nf-test": "0.9.3", - "nextflow": "25.10.2" + "nextflow": "25.10.4" }, - "timestamp": "2026-02-02T17:06:03.676263" + "timestamp": "2026-03-19T08:58:56.91914" } } \ No newline at end of file diff --git a/modules/nf-core/samtools/sort/environment.yml b/modules/nf-core/samtools/sort/environment.yml index 89e12a6..946bb36 100644 --- a/modules/nf-core/samtools/sort/environment.yml +++ b/modules/nf-core/samtools/sort/environment.yml @@ -5,6 +5,6 @@ channels: - bioconda dependencies: # renovate: datasource=conda depName=bioconda/htslib - - bioconda::htslib=1.22.1 + - bioconda::htslib=1.23.1 # renovate: datasource=conda depName=bioconda/samtools - - bioconda::samtools=1.22.1 + - bioconda::samtools=1.23.1 diff --git a/modules/nf-core/samtools/sort/main.nf b/modules/nf-core/samtools/sort/main.nf index 6b5aa31..3fcd627 100644 --- a/modules/nf-core/samtools/sort/main.nf +++ b/modules/nf-core/samtools/sort/main.nf @@ -1,24 +1,22 @@ process SAMTOOLS_SORT { - tag "$meta.id" + tag "${meta.id}" label 'process_medium' conda "${moduleDir}/environment.yml" - container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? - 'https://depot.galaxyproject.org/singularity/samtools:1.22.1--h96c455f_0' : - 'biocontainers/samtools:1.22.1--h96c455f_0' }" + container "${workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container + ? 'https://community-cr-prod.seqera.io/docker/registry/v2/blobs/sha256/8c/8c5d2818c8b9f58e1fba77ce219fdaf32087ae53e857c4a496402978af26e78c/data' + : 'community.wave.seqera.io/library/htslib_samtools:1.23.1--5b6bb4ede7e612e5'}" input: - tuple val(meta) , path(bam) - tuple val(meta2), path(fasta) + tuple val(meta), path(bam) + tuple val(meta2), path(fasta), path(fai) val index_format output: - tuple val(meta), path("${prefix}.bam"), emit: bam, optional: true - tuple val(meta), path("${prefix}.cram"), emit: cram, optional: true - tuple val(meta), path("${prefix}.sam"), emit: sam, optional: true - tuple val(meta), path("${prefix}.${extension}.crai"), emit: crai, optional: true - tuple val(meta), path("${prefix}.${extension}.csi"), emit: csi, optional: true - tuple val(meta), path("${prefix}.${extension}.bai"), emit: bai, optional: true + tuple val(meta), path("${prefix}.bam"), emit: bam, optional: true + tuple val(meta), path("${prefix}.cram"), emit: cram, optional: true + tuple val(meta), path("${prefix}.sam"), emit: sam, optional: true + tuple val(meta), path("${prefix}.${extension}.{crai,csi,bai}"), emit: index, optional: true tuple val("${task.process}"), val('samtools'), eval("samtools version | sed '1!d;s/.* //'"), topic: versions, emit: versions_samtools when: @@ -27,52 +25,73 @@ process SAMTOOLS_SORT { script: def args = task.ext.args ?: '' prefix = task.ext.prefix ?: "${meta.id}" - extension = args.contains("--output-fmt sam") ? "sam" : - args.contains("--output-fmt cram") ? "cram" : - "bam" + extension = args.contains("--output-fmt sam") + ? "sam" + : args.contains("--output-fmt cram") + ? "cram" + : "bam" def reference = fasta ? "--reference ${fasta}" : "" - output_file = index_format ? "${prefix}.${extension}##idx##${prefix}.${extension}.${index_format} --write-index" : "${prefix}.${extension}" + //setting default values + def write_index = "" + def output_file = "${prefix}.${extension}" + + // Update if index is requested + if (index_format != '' && index_format) { + write_index = "--write-index" + output_file = "${prefix}.${extension}##idx##${prefix}.${extension}.${index_format}" + } + def is_sam = (bam instanceof List ? bam[0] : bam).name.endsWith('.sam') if (index_format) { if (!index_format.matches('bai|csi|crai')) { - error "Index format not one of bai, csi, crai." - } else if (extension == "sam") { - error "Indexing not compatible with SAM output" + error("Index format not one of bai, csi, crai.") + } + else if (extension == "sam") { + error("Indexing not compatible with SAM output") } } - if ("$bam" == "${prefix}.bam") error "Input and output names are the same, use \"task.ext.prefix\" to disambiguate!" + if ("${bam}" == "${prefix}.bam") { + error("Input and output names are the same, use \"task.ext.prefix\" to disambiguate!") + } + if ("${bam}" == "${prefix}.bam") { + error("Input and output names are the same, use \"task.ext.prefix\" to disambiguate!") + } + + def input_source = is_sam ? "${bam}" : "-" + def pre_command = is_sam ? "" : "samtools cat ${bam} | " """ - samtools cat \\ - ${bam} \\ - | \\ - samtools sort \\ - $args \\ + ${pre_command}samtools sort \\ + ${args} \\ -T ${prefix} \\ - --threads $task.cpus \\ + --threads ${task.cpus} \\ ${reference} \\ -o ${output_file} \\ - - - + ${write_index} \\ + ${input_source} """ stub: def args = task.ext.args ?: '' prefix = task.ext.prefix ?: "${meta.id}" - extension = args.contains("--output-fmt sam") ? "sam" : - args.contains("--output-fmt cram") ? "cram" : - "bam" + extension = args.contains("--output-fmt sam") + ? "sam" + : args.contains("--output-fmt cram") + ? "cram" + : "bam" + if (index_format) { if (!index_format.matches('bai|csi|crai')) { - error "Index format not one of bai, csi, crai." - } else if (extension == "sam") { - error "Indexing not compatible with SAM output" + error("Index format not one of bai, csi, crai.") + } + else if (extension == "sam") { + error("Indexing not compatible with SAM output") } } + index = index_format ? "touch ${prefix}.${extension}.${index_format}" : "" """ touch ${prefix}.${extension} ${index} - """ } diff --git a/modules/nf-core/samtools/sort/meta.yml b/modules/nf-core/samtools/sort/meta.yml index 6996830..0447a95 100644 --- a/modules/nf-core/samtools/sort/meta.yml +++ b/modules/nf-core/samtools/sort/meta.yml @@ -38,6 +38,12 @@ input: pattern: "*.{fa,fasta,fna}" optional: true ontologies: [] + - fai: + type: file + description: Reference genome FASTA index file + pattern: "*.{fai}" + optional: true + ontologies: [] - index_format: type: string description: Index format to use (optional) @@ -76,38 +82,16 @@ output: description: Sorted SAM file pattern: "*.{sam}" ontologies: [] - crai: + index: - - meta: type: map description: | Groovy Map containing sample information e.g. [ id:'test', single_end:false ] - - "${prefix}.${extension}.crai": + - "${prefix}.${extension}.{crai,csi,bai}": type: file description: CRAM index file (optional) - pattern: "*.crai" - ontologies: [] - csi: - - - meta: - type: map - description: | - Groovy Map containing sample information - e.g. [ id:'test', single_end:false ] - - "${prefix}.${extension}.csi": - type: file - description: BAM index file (optional) - pattern: "*.csi" - ontologies: [] - bai: - - - meta: - type: map - description: | - Groovy Map containing sample information - e.g. [ id:'test', single_end:false ] - - "${prefix}.${extension}.bai": - type: file - description: BAM index file (optional) - pattern: "*.bai" + pattern: "*.{crai,csi,bai}" ontologies: [] versions_samtools: - - ${task.process}: diff --git a/modules/nf-core/samtools/sort/tests/main.nf.test b/modules/nf-core/samtools/sort/tests/main.nf.test index df47bb2..b60edf8 100644 --- a/modules/nf-core/samtools/sort/tests/main.nf.test +++ b/modules/nf-core/samtools/sort/tests/main.nf.test @@ -21,7 +21,8 @@ nextflow_process { ]) input[1] = Channel.of([ [ id:'fasta' ], // meta map - file(params.modules_testdata_base_path + 'genomics/sarscov2/genome/genome.fasta', checkIfExists: true) + file(params.modules_testdata_base_path + 'genomics/sarscov2/genome/genome.fasta', checkIfExists: true), + file(params.modules_testdata_base_path + 'genomics/sarscov2/genome/genome.fasta.fai', checkIfExists: true) ]) input[2] = '' """ @@ -33,7 +34,7 @@ nextflow_process { { assert process.success }, { assert snapshot( process.out.bam, - process.out.bai, + process.out.index, process.out.findAll { key, val -> key.startsWith("versions") } ).match()} ) @@ -53,7 +54,8 @@ nextflow_process { ]) input[1] = Channel.of([ [ id:'fasta' ], // meta map - file(params.modules_testdata_base_path + 'genomics/sarscov2/genome/genome.fasta', checkIfExists: true) + file(params.modules_testdata_base_path + 'genomics/sarscov2/genome/genome.fasta', checkIfExists: true), + file(params.modules_testdata_base_path + 'genomics/sarscov2/genome/genome.fasta.fai', checkIfExists: true) ]) input[2] = 'bai' """ @@ -65,7 +67,7 @@ nextflow_process { { assert process.success }, { assert snapshot( process.out.bam, - process.out.bai, + process.out.index, process.out.findAll { key, val -> key.startsWith("versions") } ).match()} ) @@ -85,7 +87,8 @@ nextflow_process { ]) input[1] = Channel.of([ [ id:'fasta' ], // meta map - file(params.modules_testdata_base_path + 'genomics/sarscov2/genome/genome.fasta', checkIfExists: true) + file(params.modules_testdata_base_path + 'genomics/sarscov2/genome/genome.fasta', checkIfExists: true), + file(params.modules_testdata_base_path + 'genomics/sarscov2/genome/genome.fasta.fai', checkIfExists: true) ]) input[2] = 'csi' """ @@ -97,7 +100,7 @@ nextflow_process { { assert process.success }, { assert snapshot( process.out.bam, - process.out.csi, + process.out.index, process.out.findAll { key, val -> key.startsWith("versions") } ).match()} ) @@ -120,7 +123,8 @@ nextflow_process { ]) input[1] = Channel.of([ [ id:'fasta' ], // meta map - file(params.modules_testdata_base_path + 'genomics/homo_sapiens/genome/genome.fasta', checkIfExists: true) + file(params.modules_testdata_base_path + 'genomics/homo_sapiens/genome/genome.fasta', checkIfExists: true), + file(params.modules_testdata_base_path + 'genomics/homo_sapiens/genome/genome.fasta.fai', checkIfExists: true) ]) input[2] = '' """ @@ -132,7 +136,7 @@ nextflow_process { { assert process.success }, { assert snapshot( process.out.bam, - process.out.csi.collect { it.collect { it instanceof Map ? it : file(it).name } }, + process.out.index.collect { it.collect { it instanceof Map ? it : file(it).name } }, process.out.findAll { key, val -> key.startsWith("versions") } ).match()} ) @@ -155,7 +159,8 @@ nextflow_process { ]) input[1] = Channel.of([ [ id:'fasta' ], // meta map - file(params.modules_testdata_base_path + 'genomics/homo_sapiens/genome/genome.fasta', checkIfExists: true) + file(params.modules_testdata_base_path + 'genomics/homo_sapiens/genome/genome.fasta', checkIfExists: true), + file(params.modules_testdata_base_path + 'genomics/homo_sapiens/genome/genome.fasta.fai', checkIfExists: true) ]) input[2] = 'bai' """ @@ -167,7 +172,7 @@ nextflow_process { { assert process.success }, { assert snapshot( process.out.bam, - process.out.bai.collect { it.collect { it instanceof Map ? it : file(it).name } }, + process.out.index.collect { it.collect { it instanceof Map ? it : file(it).name } }, process.out.findAll { key, val -> key.startsWith("versions") } ).match()} ) @@ -190,7 +195,8 @@ nextflow_process { ]) input[1] = Channel.of([ [ id:'fasta' ], // meta map - file(params.modules_testdata_base_path + 'genomics/homo_sapiens/genome/genome.fasta', checkIfExists: true) + file(params.modules_testdata_base_path + 'genomics/homo_sapiens/genome/genome.fasta', checkIfExists: true), + file(params.modules_testdata_base_path + 'genomics/homo_sapiens/genome/genome.fasta.fai', checkIfExists: true) ]) input[2] = 'csi' """ @@ -202,7 +208,7 @@ nextflow_process { { assert process.success }, { assert snapshot( process.out.bam, - process.out.csi.collect { it.collect { it instanceof Map ? it : file(it).name } }, + process.out.index.collect { it.collect { it instanceof Map ? it : file(it).name } }, process.out.findAll { key, val -> key.startsWith("versions") } ).match()} ) @@ -222,7 +228,8 @@ nextflow_process { ]) input[1] = Channel.of([ [ id:'fasta' ], // meta map - file(params.modules_testdata_base_path + 'genomics/homo_sapiens/genome/genome.fasta', checkIfExists: true) + file(params.modules_testdata_base_path + 'genomics/homo_sapiens/genome/genome.fasta', checkIfExists: true), + file(params.modules_testdata_base_path + 'genomics/homo_sapiens/genome/genome.fasta.fai', checkIfExists: true) ]) input[2] = '' """ @@ -234,7 +241,7 @@ nextflow_process { { assert process.success }, { assert snapshot( process.out.cram.collect { it.collect { it instanceof Map ? it : file(it).name } }, - process.out.crai.collect { it.collect { it instanceof Map ? it : file(it).name } }, + process.out.index.collect { it.collect { it instanceof Map ? it : file(it).name } }, process.out.findAll { key, val -> key.startsWith("versions") } ).match()} ) @@ -255,7 +262,8 @@ nextflow_process { ]) input[1] = Channel.of([ [ id:'fasta' ], // meta map - file(params.modules_testdata_base_path + 'genomics/sarscov2/genome/genome.fasta', checkIfExists: true) + file(params.modules_testdata_base_path + 'genomics/sarscov2/genome/genome.fasta', checkIfExists: true), + file(params.modules_testdata_base_path + 'genomics/sarscov2/genome/genome.fasta.fai', checkIfExists: true) ]) input[2] = '' """ @@ -286,7 +294,8 @@ nextflow_process { ]) input[1] = Channel.of([ [ id:'fasta' ], // meta map - file(params.modules_testdata_base_path + 'genomics/homo_sapiens/genome/genome.fasta', checkIfExists: true) + file(params.modules_testdata_base_path + 'genomics/homo_sapiens/genome/genome.fasta', checkIfExists: true), + file(params.modules_testdata_base_path + 'genomics/homo_sapiens/genome/genome.fasta.fai', checkIfExists: true) ]) input[2] = '' """ @@ -315,7 +324,8 @@ nextflow_process { ]) input[1] = Channel.of([ [ id:'fasta' ], // meta map - file(params.modules_testdata_base_path + 'genomics/homo_sapiens/genome/genome.fasta', checkIfExists: true) + file(params.modules_testdata_base_path + 'genomics/homo_sapiens/genome/genome.fasta', checkIfExists: true), + file(params.modules_testdata_base_path + 'genomics/homo_sapiens/genome/genome.fasta.fai', checkIfExists: true) ]) input[2] = '' """ @@ -329,4 +339,72 @@ nextflow_process { ) } } + + test("multi_sam") { + + config "./nextflow_sam.config" + + when { + process { + """ + input[0] = Channel.of([ + [ id:'test', single_end:false ], // meta map + file(params.modules_testdata_base_path + 'genomics/homo_sapiens/pairtools/mock.sam', checkIfExists: true) + ]) + input[1] = Channel.of([ + [ id:'fasta' ], // meta map + file(params.modules_testdata_base_path + 'genomics/homo_sapiens/genome/genome.fasta', checkIfExists: true), + file(params.modules_testdata_base_path + 'genomics/homo_sapiens/genome/genome.fasta.fai', checkIfExists: true) + ]) + input[2] = '' + """ + } + } + + then { + assertAll ( + { assert process.success }, + { assert snapshot( + process.out.bam.collect { it.collect { it instanceof Map ? it : file(it).name } }, + process.out.index.collect { it.collect { it instanceof Map ? it : file(it).name } }, + process.out.findAll { key, val -> key.startsWith("versions") } + ).match()} + ) + } + } + + + test("sam") { + + config "./nextflow_sam.config" + + when { + process { + """ + input[0] = Channel.of([ + [ id:'test', single_end:false ], // meta map + file(params.modules_testdata_base_path + 'genomics/homo_sapiens/pairtools/mock.sam', checkIfExists: true), + file(params.modules_testdata_base_path + 'genomics/homo_sapiens/pairtools/mock.sam', checkIfExists: true) + ]) + input[1] = Channel.of([ + [ id:'fasta' ], // meta map + file(params.modules_testdata_base_path + 'genomics/homo_sapiens/genome/genome.fasta', checkIfExists: true), + file(params.modules_testdata_base_path + 'genomics/homo_sapiens/genome/genome.fasta.fai', checkIfExists: true) + ]) + input[2] = '' + """ + } + } + + then { + assertAll ( + { assert process.success }, + { assert snapshot( + process.out.bam.collect { it.collect { it instanceof Map ? it : file(it).name } }, + process.out.index.collect { it.collect { it instanceof Map ? it : file(it).name } }, + process.out.findAll { key, val -> key.startsWith("versions") } + ).match()} + ) + } + } } diff --git a/modules/nf-core/samtools/sort/tests/main.nf.test.snap b/modules/nf-core/samtools/sort/tests/main.nf.test.snap index 4e618fa..5ce05c3 100644 --- a/modules/nf-core/samtools/sort/tests/main.nf.test.snap +++ b/modules/nf-core/samtools/sort/tests/main.nf.test.snap @@ -24,16 +24,16 @@ [ "SAMTOOLS_SORT", "samtools", - "1.22.1" + "1.23.1" ] ] } ], "meta": { "nf-test": "0.9.3", - "nextflow": "25.10.0" + "nextflow": "25.10.4" }, - "timestamp": "2025-10-29T12:47:01.171084" + "timestamp": "2026-03-19T09:04:36.491063" }, "bam_csi_index": { "content": [ @@ -43,7 +43,7 @@ "id": "test", "single_end": false }, - "test.sorted.bam:md5,72ca1dff5344a5e5e6b892fe5f6b134d" + "test.sorted.bam:md5,53aea06779611856bc481c60beabecaa" ] ], [ @@ -52,7 +52,7 @@ "id": "test", "single_end": false }, - "test.sorted.bam.csi:md5,01394e702c729cb478df914ffaf9f7f8" + "test.sorted.bam.csi:md5,f77a4adb3dde616d7eafd28db2ed147c" ] ], { @@ -60,16 +60,16 @@ [ "SAMTOOLS_SORT", "samtools", - "1.22.1" + "1.23.1" ] ] } ], "meta": { "nf-test": "0.9.3", - "nextflow": "25.10.0" + "nextflow": "25.10.4" }, - "timestamp": "2025-10-29T12:46:00.961675" + "timestamp": "2026-03-19T09:04:14.341977" }, "bam - stub": { "content": [ @@ -78,16 +78,16 @@ [ "SAMTOOLS_SORT", "samtools", - "1.22.1" + "1.23.1" ] ] } ], "meta": { "nf-test": "0.9.3", - "nextflow": "25.10.0" + "nextflow": "25.10.4" }, - "timestamp": "2025-10-29T12:47:12.154354" + "timestamp": "2026-03-19T09:04:43.558376" }, "multiple bam bai index": { "content": [ @@ -97,7 +97,7 @@ "id": "test", "single_end": false }, - "test.sorted.bam:md5,3ffa2affc29f0aa6e7b36dded84625fe" + "test.sorted.bam:md5,a15f775c655d4a3b080812a8aae84d34" ] ], [ @@ -114,16 +114,16 @@ [ "SAMTOOLS_SORT", "samtools", - "1.22.1" + "1.23.1" ] ] } ], "meta": { "nf-test": "0.9.3", - "nextflow": "25.10.0" + "nextflow": "25.10.4" }, - "timestamp": "2025-10-29T12:46:25.488622" + "timestamp": "2026-03-19T09:04:25.647565" }, "cram - stub": { "content": [ @@ -132,16 +132,16 @@ [ "SAMTOOLS_SORT", "samtools", - "1.22.1" + "1.23.1" ] ] } ], "meta": { "nf-test": "0.9.3", - "nextflow": "25.10.0" + "nextflow": "25.10.4" }, - "timestamp": "2025-10-29T12:47:28.485045" + "timestamp": "2026-03-19T09:04:54.684578" }, "multiple bam": { "content": [ @@ -151,7 +151,7 @@ "id": "test", "single_end": false }, - "test.sorted.bam:md5,cd4eb0077f25e9cff395366b8883dd1f" + "test.sorted.bam:md5,f4343475d9ed2c261f31e1e49d67c1b6" ] ], [ @@ -162,16 +162,16 @@ [ "SAMTOOLS_SORT", "samtools", - "1.22.1" + "1.23.1" ] ] } ], "meta": { "nf-test": "0.9.3", - "nextflow": "25.10.0" + "nextflow": "25.10.4" }, - "timestamp": "2025-10-29T12:46:13.168476" + "timestamp": "2026-03-19T09:04:20.2368" }, "multiple bam - stub": { "content": [ @@ -180,16 +180,16 @@ [ "SAMTOOLS_SORT", "samtools", - "1.22.1" + "1.23.1" ] ] } ], "meta": { "nf-test": "0.9.3", - "nextflow": "25.10.0" + "nextflow": "25.10.4" }, - "timestamp": "2025-10-29T12:47:21.628088" + "timestamp": "2026-03-19T09:04:48.874947" }, "bam_no_index": { "content": [ @@ -199,7 +199,7 @@ "id": "test", "single_end": false }, - "test.sorted.bam:md5,26b27d1f9bcb61c25da21b562349784e" + "test.sorted.bam:md5,9277ba4bea590ae1b84e6ab06d11d79b" ] ], [ @@ -210,16 +210,40 @@ [ "SAMTOOLS_SORT", "samtools", - "1.22.1" + "1.23.1" ] ] } ], "meta": { "nf-test": "0.9.3", - "nextflow": "25.10.0" + "nextflow": "25.10.4" }, - "timestamp": "2025-10-29T12:45:47.139418" + "timestamp": "2026-03-19T09:04:03.721646" + }, + "multi_sam": { + "content": [ + [ + + ], + [ + + ], + { + "versions_samtools": [ + [ + "SAMTOOLS_SORT", + "samtools", + "1.23.1" + ] + ] + } + ], + "meta": { + "nf-test": "0.9.3", + "nextflow": "25.10.4" + }, + "timestamp": "2026-03-19T09:05:00.624092" }, "multiple bam csi index": { "content": [ @@ -229,7 +253,7 @@ "id": "test", "single_end": false }, - "test.sorted.bam:md5,295503ba5342531a3310c33ad0efbc22" + "test.sorted.bam:md5,f168809dc154156c40548c06d0f46791" ] ], [ @@ -246,16 +270,40 @@ [ "SAMTOOLS_SORT", "samtools", - "1.22.1" + "1.23.1" + ] + ] + } + ], + "meta": { + "nf-test": "0.9.3", + "nextflow": "25.10.4" + }, + "timestamp": "2026-03-19T09:04:31.11865" + }, + "sam": { + "content": [ + [ + + ], + [ + + ], + { + "versions_samtools": [ + [ + "SAMTOOLS_SORT", + "samtools", + "1.23.1" ] ] } ], "meta": { "nf-test": "0.9.3", - "nextflow": "25.10.0" + "nextflow": "25.10.4" }, - "timestamp": "2025-10-29T12:46:51.5531" + "timestamp": "2026-03-19T09:05:06.309319" }, "bam_bai_index": { "content": [ @@ -265,7 +313,7 @@ "id": "test", "single_end": false }, - "test.sorted.bam:md5,cae7564cb83bb4a5911205bf94124b54" + "test.sorted.bam:md5,2ca2d7f2368251d3f06f84afa49865a5" ] ], [ @@ -274,7 +322,7 @@ "id": "test", "single_end": false }, - "test.sorted.bam.bai:md5,50dd467c169545a4d5d1f709f7e986e0" + "test.sorted.bam.bai:md5,66dca3dc2e314029035799f6f44f60d1" ] ], { @@ -282,15 +330,15 @@ [ "SAMTOOLS_SORT", "samtools", - "1.22.1" + "1.23.1" ] ] } ], "meta": { "nf-test": "0.9.3", - "nextflow": "25.10.0" + "nextflow": "25.10.4" }, - "timestamp": "2025-10-29T12:45:52.796936" + "timestamp": "2026-03-19T09:04:09.147615" } } \ No newline at end of file diff --git a/modules/nf-core/samtools/sort/tests/nextflow.config b/modules/nf-core/samtools/sort/tests/nextflow.config index 723f62b..ca694ca 100644 --- a/modules/nf-core/samtools/sort/tests/nextflow.config +++ b/modules/nf-core/samtools/sort/tests/nextflow.config @@ -1,7 +1,6 @@ process { withName: SAMTOOLS_SORT { - ext.prefix = { "${meta.id}.sorted" } + ext.prefix = { "${meta.id}.sorted" } } - } diff --git a/modules/nf-core/samtools/sort/tests/nextflow_cram.config b/modules/nf-core/samtools/sort/tests/nextflow_cram.config index 3a8c018..8ebc9d9 100644 --- a/modules/nf-core/samtools/sort/tests/nextflow_cram.config +++ b/modules/nf-core/samtools/sort/tests/nextflow_cram.config @@ -1,8 +1,7 @@ process { withName: SAMTOOLS_SORT { - ext.prefix = { "${meta.id}.sorted" } - ext.args = "--write-index --output-fmt cram" + ext.prefix = { "${meta.id}.sorted" } + ext.args = "--write-index --output-fmt cram" } - } diff --git a/modules/nf-core/samtools/sort/tests/nextflow_sam.config b/modules/nf-core/samtools/sort/tests/nextflow_sam.config new file mode 100644 index 0000000..29ee6a8 --- /dev/null +++ b/modules/nf-core/samtools/sort/tests/nextflow_sam.config @@ -0,0 +1,7 @@ +process { + + withName: SAMTOOLS_SORT { + ext.prefix = { "${meta.id}.sorted" } + ext.args = "--output-fmt sam" + } +} diff --git a/modules/nf-core/samtools/view/environment.yml b/modules/nf-core/samtools/view/environment.yml index 89e12a6..946bb36 100644 --- a/modules/nf-core/samtools/view/environment.yml +++ b/modules/nf-core/samtools/view/environment.yml @@ -5,6 +5,6 @@ channels: - bioconda dependencies: # renovate: datasource=conda depName=bioconda/htslib - - bioconda::htslib=1.22.1 + - bioconda::htslib=1.23.1 # renovate: datasource=conda depName=bioconda/samtools - - bioconda::samtools=1.22.1 + - bioconda::samtools=1.23.1 diff --git a/modules/nf-core/samtools/view/main.nf b/modules/nf-core/samtools/view/main.nf index b189b5b..60b2286 100644 --- a/modules/nf-core/samtools/view/main.nf +++ b/modules/nf-core/samtools/view/main.nf @@ -1,11 +1,11 @@ process SAMTOOLS_VIEW { - tag "$meta.id" + tag "${meta.id}" label 'process_low' conda "${moduleDir}/environment.yml" - container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? - 'https://depot.galaxyproject.org/singularity/samtools:1.22.1--h96c455f_0' : - 'biocontainers/samtools:1.22.1--h96c455f_0' }" + container "${workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container + ? 'https://community-cr-prod.seqera.io/docker/registry/v2/blobs/sha256/8c/8c5d2818c8b9f58e1fba77ce219fdaf32087ae53e857c4a496402978af26e78c/data' + : 'community.wave.seqera.io/library/htslib_samtools:1.23.1--5b6bb4ede7e612e5'}" input: tuple val(meta), path(input), path(index) @@ -14,14 +14,14 @@ process SAMTOOLS_VIEW { val index_format output: - tuple val(meta), path("${prefix}.bam"), emit: bam, optional: true - tuple val(meta), path("${prefix}.cram"), emit: cram, optional: true - tuple val(meta), path("${prefix}.sam"), emit: sam, optional: true - tuple val(meta), path("${prefix}.${file_type}.bai"), emit: bai, optional: true - tuple val(meta), path("${prefix}.${file_type}.csi"), emit: csi, optional: true - tuple val(meta), path("${prefix}.${file_type}.crai"), emit: crai, optional: true - tuple val(meta), path("${prefix}.unselected.${file_type}"), emit: unselected, optional: true - tuple val(meta), path("${prefix}.unselected.${file_type}.{csi,crai}"), emit: unselected_index, optional: true + tuple val(meta), path("${prefix}.bam"), emit: bam, optional: true + tuple val(meta), path("${prefix}.cram"), emit: cram, optional: true + tuple val(meta), path("${prefix}.sam"), emit: sam, optional: true + tuple val(meta), path("${prefix}.${file_type}.bai"), emit: bai, optional: true + tuple val(meta), path("${prefix}.${file_type}.csi"), emit: csi, optional: true + tuple val(meta), path("${prefix}.${file_type}.crai"), emit: crai, optional: true + tuple val(meta), path("${prefix}.unselected.${file_type}"), emit: unselected, optional: true + tuple val(meta), path("${prefix}.unselected.${file_type}.{csi,crai}"), emit: unselected_index, optional: true tuple val("${task.process}"), val('samtools'), eval('samtools version | sed "1!d;s/.* //"'), emit: versions_samtools, topic: versions when: @@ -32,57 +32,69 @@ process SAMTOOLS_VIEW { def args2 = task.ext.args2 ?: '' prefix = task.ext.prefix ?: "${meta.id}" def reference = fasta ? "--reference ${fasta}" : "" - file_type = args.contains("--output-fmt sam") ? "sam" : - args.contains("--output-fmt bam") ? "bam" : - args.contains("--output-fmt cram") ? "cram" : - input.getExtension() + file_type = args.contains("--output-fmt sam") + ? "sam" + : args.contains("--output-fmt bam") + ? "bam" + : args.contains("--output-fmt cram") + ? "cram" + : input.getExtension() output_file = index_format ? "${prefix}.${file_type}##idx##${prefix}.${file_type}.${index_format} --write-index" : "${prefix}.${file_type}" // Can't choose index type of unselected file - readnames = qname ? "--qname-file ${qname} --output-unselected ${prefix}.unselected.${file_type}": "" + readnames = qname ? "--qname-file ${qname} --output-unselected ${prefix}.unselected.${file_type}" : "" - if ("$input" == "${prefix}.${file_type}") error "Input and output names are the same, use \"task.ext.prefix\" to disambiguate!" + if ("${input}" == "${prefix}.${file_type}") { + error("Input and output names are the same, use \"task.ext.prefix\" to disambiguate!") + } if (index_format) { if (!index_format.matches('bai|csi|crai')) { - error "Index format not one of bai, csi, crai." - } else if (file_type == "sam") { - error "Indexing not compatible with SAM output" + error("Index format not one of bai, csi, crai.") + } + else if (file_type == "sam") { + error("Indexing not compatible with SAM output") } } """ # Note: --threads value represents *additional* CPUs to allocate (total CPUs = 1 + --threads). samtools \\ view \\ - --threads ${task.cpus-1} \\ + --threads ${task.cpus - 1} \\ ${reference} \\ ${readnames} \\ - $args \\ + ${args} \\ -o ${output_file} \\ - $input \\ - $args2 + ${input} \\ + ${args2} """ stub: def args = task.ext.args ?: '' prefix = task.ext.prefix ?: "${meta.id}" - file_type = args.contains("--output-fmt sam") ? "sam" : - args.contains("--output-fmt bam") ? "bam" : - args.contains("--output-fmt cram") ? "cram" : - input.getExtension() - default_index_format = - file_type == "bam" ? "csi" : - file_type == "cram" ? "crai" : "" - index = index_format ? "touch ${prefix}.${file_type}.${index_format}" : args.contains("--write-index") ? "touch ${prefix}.${file_type}.${default_index_format}" : "" + file_type = args.contains("--output-fmt sam") + ? "sam" + : args.contains("--output-fmt bam") + ? "bam" + : args.contains("--output-fmt cram") + ? "cram" + : input.getExtension() + default_index_format = file_type == "bam" + ? "csi" + : file_type == "cram" ? "crai" : "" + index = index_format ? "touch ${prefix}.${file_type}.${index_format}" : args.contains("--write-index") ? "touch ${prefix}.${file_type}.${default_index_format}" : "" unselected = qname ? "touch ${prefix}.unselected.${file_type}" : "" // Can't choose index type of unselected file unselected_index = qname && (args.contains("--write-index") || index_format) ? "touch ${prefix}.unselected.${file_type}.${default_index_format}" : "" - if ("$input" == "${prefix}.${file_type}") error "Input and output names are the same, use \"task.ext.prefix\" to disambiguate!" + if ("${input}" == "${prefix}.${file_type}") { + error("Input and output names are the same, use \"task.ext.prefix\" to disambiguate!") + } if (index_format) { if (!index_format.matches('bai|csi|crai')) { - error "Index format not one of bai, csi, crai." - } else if (file_type == "sam") { - error "Indexing not compatible with SAM output." + error("Index format not one of bai, csi, crai.") + } + else if (file_type == "sam") { + error("Indexing not compatible with SAM output.") } } """ diff --git a/modules/nf-core/samtools/view/meta.yml b/modules/nf-core/samtools/view/meta.yml index 23a1af3..33e60c4 100644 --- a/modules/nf-core/samtools/view/meta.yml +++ b/modules/nf-core/samtools/view/meta.yml @@ -180,3 +180,4 @@ maintainers: - "@joseespinosa" - "@FriederikeHanssen" - "@priyanka-surana" + - "@matthdsm" diff --git a/modules/nf-core/samtools/view/tests/main.nf.test.snap b/modules/nf-core/samtools/view/tests/main.nf.test.snap index 95205e5..8d807b9 100644 --- a/modules/nf-core/samtools/view/tests/main.nf.test.snap +++ b/modules/nf-core/samtools/view/tests/main.nf.test.snap @@ -40,16 +40,16 @@ [ "SAMTOOLS_VIEW", "samtools", - "1.22.1" + "1.23.1" ] ] } ], "meta": { "nf-test": "0.9.3", - "nextflow": "25.10.3" + "nextflow": "25.10.4" }, - "timestamp": "2026-02-03T16:49:14.82588493" + "timestamp": "2026-03-19T09:06:44.475595" }, "bam_csi_index - stub": { "content": [ @@ -92,7 +92,7 @@ [ "SAMTOOLS_VIEW", "samtools", - "1.22.1" + "1.23.1" ] ], "bai": [ @@ -133,16 +133,16 @@ [ "SAMTOOLS_VIEW", "samtools", - "1.22.1" + "1.23.1" ] ] } ], "meta": { "nf-test": "0.9.3", - "nextflow": "25.10.3" + "nextflow": "25.10.4" }, - "timestamp": "2026-02-03T16:49:31.409368544" + "timestamp": "2026-03-19T09:07:04.977559" }, "bam_csi_index": { "content": [ @@ -185,16 +185,16 @@ [ "SAMTOOLS_VIEW", "samtools", - "1.22.1" + "1.23.1" ] ] } ], "meta": { "nf-test": "0.9.3", - "nextflow": "25.10.3" + "nextflow": "25.10.4" }, - "timestamp": "2026-02-03T16:48:46.36824035" + "timestamp": "2026-03-19T09:06:07.203393" }, "cram_to_bam_index_qname": { "content": [ @@ -247,16 +247,16 @@ [ "SAMTOOLS_VIEW", "samtools", - "1.22.1" + "1.23.1" ] ] } ], "meta": { "nf-test": "0.9.3", - "nextflow": "25.10.3" + "nextflow": "25.10.4" }, - "timestamp": "2026-02-03T16:49:20.747636525" + "timestamp": "2026-03-19T09:06:52.242422" }, "bam_bai_index_unselected": { "content": [ @@ -309,16 +309,16 @@ [ "SAMTOOLS_VIEW", "samtools", - "1.22.1" + "1.23.1" ] ] } ], "meta": { "nf-test": "0.9.3", - "nextflow": "25.10.3" + "nextflow": "25.10.4" }, - "timestamp": "2026-02-03T16:48:57.713608154" + "timestamp": "2026-03-19T09:06:18.267421" }, "cram_crai_index_unselected - stub": { "content": [ @@ -371,7 +371,7 @@ [ "SAMTOOLS_VIEW", "samtools", - "1.22.1" + "1.23.1" ] ], "bai": [ @@ -422,16 +422,16 @@ [ "SAMTOOLS_VIEW", "samtools", - "1.22.1" + "1.23.1" ] ] } ], "meta": { "nf-test": "0.9.3", - "nextflow": "25.10.3" + "nextflow": "25.10.4" }, - "timestamp": "2026-02-03T16:49:48.092654899" + "timestamp": "2026-03-19T09:07:27.864649" }, "bam": { "content": [ @@ -469,16 +469,16 @@ [ "SAMTOOLS_VIEW", "samtools", - "1.22.1" + "1.23.1" ] ] } ], "meta": { "nf-test": "0.9.3", - "nextflow": "25.10.3" + "nextflow": "25.10.4" }, - "timestamp": "2026-02-03T16:48:27.608944526" + "timestamp": "2026-03-19T09:06:01.906355" }, "bam_bai_index": { "content": [ @@ -521,16 +521,16 @@ [ "SAMTOOLS_VIEW", "samtools", - "1.22.1" + "1.23.1" ] ] } ], "meta": { "nf-test": "0.9.3", - "nextflow": "25.10.3" + "nextflow": "25.10.4" }, - "timestamp": "2026-02-03T16:48:52.047178732" + "timestamp": "2026-03-19T09:06:12.483533" }, "cram_to_bam": { "content": [ @@ -568,16 +568,16 @@ [ "SAMTOOLS_VIEW", "samtools", - "1.22.1" + "1.23.1" ] ] } ], "meta": { "nf-test": "0.9.3", - "nextflow": "25.10.3" + "nextflow": "25.10.4" }, - "timestamp": "2026-02-03T16:50:41.727031999" + "timestamp": "2026-03-19T09:06:37.592685" }, "bam_bai_index - stub": { "content": [ @@ -620,7 +620,7 @@ [ "SAMTOOLS_VIEW", "samtools", - "1.22.1" + "1.23.1" ] ], "bai": [ @@ -661,16 +661,16 @@ [ "SAMTOOLS_VIEW", "samtools", - "1.22.1" + "1.23.1" ] ] } ], "meta": { "nf-test": "0.9.3", - "nextflow": "25.10.3" + "nextflow": "25.10.4" }, - "timestamp": "2026-02-03T16:49:36.783381688" + "timestamp": "2026-03-19T09:07:12.214174" }, "cram": { "content": [ @@ -708,16 +708,16 @@ [ "SAMTOOLS_VIEW", "samtools", - "1.22.1" + "1.23.1" ] ] } ], "meta": { "nf-test": "0.9.3", - "nextflow": "25.10.3" + "nextflow": "25.10.4" }, - "timestamp": "2026-02-03T16:49:09.393102901" + "timestamp": "2026-03-19T09:06:29.867409" }, "bam_bai_index_uselected - stub": { "content": [ @@ -770,7 +770,7 @@ [ "SAMTOOLS_VIEW", "samtools", - "1.22.1" + "1.23.1" ] ], "bai": [ @@ -821,16 +821,16 @@ [ "SAMTOOLS_VIEW", "samtools", - "1.22.1" + "1.23.1" ] ] } ], "meta": { "nf-test": "0.9.3", - "nextflow": "25.10.3" + "nextflow": "25.10.4" }, - "timestamp": "2026-02-03T16:49:42.344755528" + "timestamp": "2026-03-19T09:07:21.14353" }, "cram_crai_index_unselected": { "content": [ @@ -854,7 +854,7 @@ { "id": "test" }, - "test.cram:md5,9b6eeca8f6b4b744297ae7cc87c031a4" + "test.cram:md5,924e27301c54060128cc259f5f83e74f" ] ], "csi": [ @@ -883,16 +883,16 @@ [ "SAMTOOLS_VIEW", "samtools", - "1.22.1" + "1.23.1" ] ] } ], "meta": { "nf-test": "0.9.3", - "nextflow": "25.10.3" + "nextflow": "25.10.4" }, - "timestamp": "2026-02-03T16:49:03.431621547" + "timestamp": "2026-03-19T09:06:23.90307" }, "bam_stub": { "content": [ @@ -935,15 +935,15 @@ [ "SAMTOOLS_VIEW", "samtools", - "1.22.1" + "1.23.1" ] ] } ], "meta": { "nf-test": "0.9.3", - "nextflow": "25.10.3" + "nextflow": "25.10.4" }, - "timestamp": "2026-02-03T16:49:26.152824543" + "timestamp": "2026-03-19T09:06:58.641723" } } \ No newline at end of file diff --git a/modules/nf-core/samtools/view/tests/nextflow.config b/modules/nf-core/samtools/view/tests/nextflow.config index 37c5643..cd05913 100644 --- a/modules/nf-core/samtools/view/tests/nextflow.config +++ b/modules/nf-core/samtools/view/tests/nextflow.config @@ -1,5 +1,5 @@ process { withName: SAMTOOLS_VIEW { - ext.args = params.samtools_args + ext.args = params.samtools_args } } diff --git a/nextflow.config b/nextflow.config index 130e8f8..c41d501 100644 --- a/nextflow.config +++ b/nextflow.config @@ -12,7 +12,7 @@ params { // Targeted flow parameters targeted { input = null - gene = "MSH2" // Set default + gene = "MSH2" } // Rnafusion flow parameters @@ -28,19 +28,18 @@ params { input = null } - // References genome = null - igenomes_base = 's3://ngi-igenomes/igenomes/' + igenomes_base = '/references' igenomes_ignore = false // MultiQC options - multiqc_config = null - multiqc_title = null - multiqc_logo = null - multiqc_logo = null - max_multiqc_email_size = '25.MB' - multiqc_methods_description = null + multiqc_config = null + multiqc_title = null + multiqc_logo = null + multiqc_logo = null + max_multiqc_email_size = '25.MB' + multiqc_methods_description = null // Boilerplate options outdir = null @@ -108,7 +107,18 @@ profiles { apptainer.enabled = false docker.runOptions = '-u $(id -u):$(id -g)' } - arm { + arm64 { + process.arch = 'arm64' + // TODO https://github.com/nf-core/modules/issues/6694 + // For now if you're using arm64 you have to use wave for the sake of the maintainers + // wave profile + apptainer.ociAutoPull = true + singularity.ociAutoPull = true + wave.enabled = true + wave.freeze = true + wave.strategy = ["conda", "container"] + } + emulate_amd64 { docker.runOptions = '-u $(id -u):$(id -g) --platform=linux/amd64' } singularity { @@ -200,9 +210,6 @@ podman.registry = 'quay.io' singularity.registry = 'quay.io' charliecloud.registry = 'quay.io' -// Load igenomes.config if required -includeConfig !params.igenomes_ignore ? 'conf/igenomes.config' : 'conf/igenomes_ignored.config' - // Export these variables to prevent local Python/R libraries from conflicting with those in the container // The JULIA depot path has been adjusted to a fixed path `/usr/local/share/julia` that needs to be used for packages in the container. // See https://apeltzer.github.io/post/03-julia-lang-nextflow/ for details on that. Once we have a common agreement on where to keep Julia packages, this is adjustable. @@ -246,24 +253,26 @@ dag { manifest { name = 'nf-cmgg/report' - author = """Tuur-ds,nvnieuwk""" - // The author field is deprecated from Nextflow version 24.10.0, use contributors instead contributors = [ [ name: 'Tuur-ds', - affiliation: '', - email: '', - github: '', - contribution: [], - orcid: '', + github: '@tuur-ds', + contribution: ["author"], + ], + [ + name: 'Nicolas Vannieuwkerke', + affiliation: 'Center For Medical Genetics Ghent', + email: 'nicolas.vannieuwkerke@ugent.be', + github: '@nvnieuwk', + contribution: ["author", "maintainer"], + orcid: '0009-0003-5619-1555', ], [ - name: 'nvnieuwk', - affiliation: '', - email: '', - github: '', - contribution: [], - orcid: '', + name: 'Matthias De Smet', + affiliation: 'Center For Medical Genetics Ghent', + email: 'matthias.desmet@ugent.be', + github: '@matthsdsm', + contribution: ["maintainer"], ], ] homePage = 'https://github.com/nf-cmgg/report' @@ -281,8 +290,7 @@ plugins { } validation { - defaultIgnoreParams = ["genomes"] - monochromeLogs = params.monochrome_logs + monochromeLogs = params.monochrome_logs } // Load modules.config for DSL2 module specific options diff --git a/nextflow_schema.json b/nextflow_schema.json index 4455e55..c29217a 100644 --- a/nextflow_schema.json +++ b/nextflow_schema.json @@ -10,7 +10,9 @@ "type": "object", "fa_icon": "fas fa-terminal", "description": "Define where the pipeline should save output data.", - "required": ["outdir"], + "required": [ + "outdir" + ], "properties": { "outdir": { "type": "string", @@ -59,7 +61,9 @@ }, "gene": { "type": "string", - "enum": ["MSH2"], + "enum": [ + "MSH2" + ], "description": "Gene name of targeted query" }, "fasta": { @@ -243,7 +247,14 @@ "description": "Method used to save pipeline results to output directory.", "help_text": "The Nextflow `publishDir` option specifies which intermediate files should be saved to the output directory. This option tells the pipeline what method should be used to move these files. See [Nextflow docs](https://www.nextflow.io/docs/latest/process.html#publishdir) for details.", "fa_icon": "fas fa-copy", - "enum": ["symlink", "rellink", "link", "copy", "copyNoFollow", "move"], + "enum": [ + "symlink", + "rellink", + "link", + "copy", + "copyNoFollow", + "move" + ], "hidden": true }, "email_on_fail": { @@ -320,7 +331,10 @@ "hidden": true }, "help": { - "type": ["boolean", "string"], + "type": [ + "boolean", + "string" + ], "description": "Display the help message." }, "help_full": { @@ -357,4 +371,4 @@ "$ref": "#/$defs/generic_options" } ] -} +} \ No newline at end of file diff --git a/nf-test.config b/nf-test.config index 3a1fff5..41183f6 100644 --- a/nf-test.config +++ b/nf-test.config @@ -1,21 +1,21 @@ config { // location for all nf-test tests - testsDir "." + testsDir = "." // nf-test directory including temporary files for each test - workDir System.getenv("NFT_WORKDIR") ?: ".nf-test" + workDir = System.getenv("NFT_WORKDIR") ?: ".nf-test" // location of an optional nextflow.config file specific for executing tests - configFile "tests/nextflow.config" + configFile = "tests/nextflow.config" // ignore tests coming from the nf-core/modules repo - ignore 'modules/nf-core/**/tests/*', 'subworkflows/nf-core/**/tests/*' + ignore = ['modules/nf-core/**/tests/*', 'subworkflows/nf-core/**/tests/*'] // run all test with defined profile(s) from the main nextflow.config - profile "test" + profile = "test" // list of filenames or patterns that should be trigger a full test run - triggers 'nextflow.config', 'nf-test.config', 'conf/test.config', 'tests/nextflow.config', 'tests/.nftignore' + triggers = ['nextflow.config', 'nf-test.config', 'conf/test.config', 'tests/nextflow.config', 'tests/.nftignore'] // load the necessary plugins plugins { diff --git a/subworkflows/local/utils_nfcore_report_pipeline/main.nf b/subworkflows/local/utils_nfcore_report_pipeline/main.nf index e9348ad..f984304 100644 --- a/subworkflows/local/utils_nfcore_report_pipeline/main.nf +++ b/subworkflows/local/utils_nfcore_report_pipeline/main.nf @@ -12,7 +12,6 @@ include { UTILS_NFSCHEMA_PLUGIN } from '../../nf-core/utils_nfschema_plugin' include { paramsSummaryMap } from 'plugin/nf-schema' include { completionEmail } from '../../nf-core/utils_nfcore_pipeline' include { completionSummary } from '../../nf-core/utils_nfcore_pipeline' -include { imNotification } from '../../nf-core/utils_nfcore_pipeline' include { UTILS_NFCORE_PIPELINE } from '../../nf-core/utils_nfcore_pipeline' include { UTILS_NEXTFLOW_PIPELINE } from '../../nf-core/utils_nextflow_pipeline' @@ -24,10 +23,10 @@ include { UTILS_NEXTFLOW_PIPELINE } from '../../nf-core/utils_nextflow_pipeline' workflow PIPELINE_INITIALISATION { take: - version // boolean: Display version and exit - validate_params // boolean: Boolean whether to validate parameters against the schema at runtime + version // boolean: Display version and exit + validate_params // boolean: Boolean whether to validate parameters against the schema at runtime nextflow_cli_args // array: List of positional nextflow CLI args - outdir // string: The output directory where the results will be saved + outdir // string: The output directory where the results will be saved main: @@ -65,7 +64,7 @@ workflow PIPELINE_INITIALISATION { params.show_hidden, before_text, "", - command + command, ) // @@ -89,12 +88,11 @@ workflow PIPELINE_INITIALISATION { workflow PIPELINE_COMPLETION { take: - email // string: email address - email_on_fail // string: email address sent on pipeline failure + email // string: email address + email_on_fail // string: email address sent on pipeline failure plaintext_email // boolean: Send plain-text email instead of HTML - outdir // path: Path to output directory where results will be published + outdir // path: Path to output directory where results will be published monochrome_logs // boolean: Disable ANSI colour codes in log output - hook_url // string: hook URL for notifications main: summary_params = paramsSummaryMap(workflow, parameters_schema: "nextflow_schema.json") @@ -116,9 +114,6 @@ workflow PIPELINE_COMPLETION { } completionSummary(monochrome_logs) - if (hook_url) { - imNotification(summary_params, hook_url) - } } workflow.onError { @@ -135,7 +130,6 @@ workflow PIPELINE_COMPLETION { // Check and validate pipeline parameters // def validateInputParameters() { - genomeExistsError() } // @@ -164,15 +158,6 @@ def getGenomeAttribute(attribute) { return null } -// -// Exit pipeline if incorrect --genome key provided -// -def genomeExistsError() { - if (params.genomes && params.genome && !params.genomes.containsKey(params.genome)) { - def error_string = "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" + " Genome '${params.genome}' not found in any config files provided to the pipeline.\n" + " Currently, the available genome keys are:\n" + " ${params.genomes.keySet().join(", ")}\n" + "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" - error(error_string) - } -} // // Generate methods description for MultiQC // @@ -192,8 +177,7 @@ def toolBibliographyText() { // TODO nf-core: Optionally add bibliographic entries to this list. // Can use ternary operators to dynamically construct based conditions, e.g. params["run_xyz"] ? "
  • Author (2023) Pub name, Journal, DOI
  • " : "", // Uncomment function in methodsDescriptionText to render in MultiQC report - def reference_text = [ - ].join(' ').trim() + def reference_text = [].join(' ').trim() return reference_text } @@ -237,3 +221,20 @@ def methodsDescriptionText(mqc_methods_yaml) { return description_html.toString() } + +def check_required_params(scope_params, scope_name, required_params) { + if (scope_params == null) { + error("Could not find a parameters scope called '${scope_name}'") + } + + def missing_params = [] + required_params.each { param -> + if (scope_params.get(param, null) == null) { + missing_params << param + } + } + + if (missing_params) { + error("The following required parameters are missing from the '${scope_name}' parameters scope: ${missing_params.join(', ')}") + } +} diff --git a/subworkflows/nf-core/utils_nfcore_pipeline/main.nf b/subworkflows/nf-core/utils_nfcore_pipeline/main.nf index 2f30e9a..bf568a0 100644 --- a/subworkflows/nf-core/utils_nfcore_pipeline/main.nf +++ b/subworkflows/nf-core/utils_nfcore_pipeline/main.nf @@ -353,67 +353,3 @@ def completionSummary(monochrome_logs=true) { log.info("-${colors.purple}[${workflow.manifest.name}]${colors.red} Pipeline completed with errors${colors.reset}-") } } - -// -// Construct and send a notification to a web server as JSON e.g. Microsoft Teams and Slack -// -def imNotification(summary_params, hook_url) { - def summary = [:] - summary_params - .keySet() - .sort() - .each { group -> - summary << summary_params[group] - } - - def misc_fields = [:] - misc_fields['start'] = workflow.start - misc_fields['complete'] = workflow.complete - misc_fields['scriptfile'] = workflow.scriptFile - misc_fields['scriptid'] = workflow.scriptId - if (workflow.repository) { - misc_fields['repository'] = workflow.repository - } - if (workflow.commitId) { - misc_fields['commitid'] = workflow.commitId - } - if (workflow.revision) { - misc_fields['revision'] = workflow.revision - } - misc_fields['nxf_version'] = workflow.nextflow.version - misc_fields['nxf_build'] = workflow.nextflow.build - misc_fields['nxf_timestamp'] = workflow.nextflow.timestamp - - def msg_fields = [:] - msg_fields['version'] = getWorkflowVersion() - msg_fields['runName'] = workflow.runName - msg_fields['success'] = workflow.success - msg_fields['dateComplete'] = workflow.complete - msg_fields['duration'] = workflow.duration - msg_fields['exitStatus'] = workflow.exitStatus - msg_fields['errorMessage'] = (workflow.errorMessage ?: 'None') - msg_fields['errorReport'] = (workflow.errorReport ?: 'None') - msg_fields['commandLine'] = workflow.commandLine.replaceFirst(/ +--hook_url +[^ ]+/, "") - msg_fields['projectDir'] = workflow.projectDir - msg_fields['summary'] = summary << misc_fields - - // Render the JSON template - def engine = new groovy.text.GStringTemplateEngine() - // Different JSON depending on the service provider - // Defaults to "Adaptive Cards" (https://adaptivecards.io), except Slack which has its own format - def json_path = hook_url.contains("hooks.slack.com") ? "slackreport.json" : "adaptivecard.json" - def hf = new File("${workflow.projectDir}/assets/${json_path}") - def json_template = engine.createTemplate(hf).make(msg_fields) - def json_message = json_template.toString() - - // POST - def post = new URL(hook_url).openConnection() - post.setRequestMethod("POST") - post.setDoOutput(true) - post.setRequestProperty("Content-Type", "application/json") - post.getOutputStream().write(json_message.getBytes("UTF-8")) - def postRC = post.getResponseCode() - if (!postRC.equals(200)) { - log.warn(post.getErrorStream().getText()) - } -} diff --git a/subworkflows/nf-core/utils_nfcore_pipeline/tests/main.workflow.nf.test b/subworkflows/nf-core/utils_nfcore_pipeline/tests/main.nf.test similarity index 100% rename from subworkflows/nf-core/utils_nfcore_pipeline/tests/main.workflow.nf.test rename to subworkflows/nf-core/utils_nfcore_pipeline/tests/main.nf.test diff --git a/subworkflows/nf-core/utils_nfcore_pipeline/tests/main.workflow.nf.test.snap b/subworkflows/nf-core/utils_nfcore_pipeline/tests/main.nf.test.snap similarity index 100% rename from subworkflows/nf-core/utils_nfcore_pipeline/tests/main.workflow.nf.test.snap rename to subworkflows/nf-core/utils_nfcore_pipeline/tests/main.nf.test.snap diff --git a/tests/nextflow.config b/tests/nextflow.config index f51392e..3a84443 100644 --- a/tests/nextflow.config +++ b/tests/nextflow.config @@ -1,4 +1,3 @@ - process { // Limit resources so that this can run on GitHub Actions resourceLimits = [ diff --git a/workflows/rnafusion.nf b/workflows/rnafusion.nf index 439470f..3702fbd 100644 --- a/workflows/rnafusion.nf +++ b/workflows/rnafusion.nf @@ -4,8 +4,8 @@ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ -include { UNTAR } from '../modules/nf-core/untar/main.nf' -include { VARCOV } from '../modules/local/varcov/main.nf' +include { UNTAR } from '../modules/nf-core/untar/main.nf' +include { VARCOV } from '../modules/local/varcov/main.nf' /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -33,19 +33,7 @@ workflow RNAFUSION { def ch_varcov_input = ch_input_branch.dir .mix(UNTAR.out.untar) .map { meta, dir -> - [ - meta, - getFilesAndCheck(dir, "vcf/*.vcf"), - getFilesAndCheck(dir, "stringtie/*.gene.abundance.txt"), - getFilesAndCheck(dir, "fusionreport/*/*.fusions.csv"), - getFilesAndCheck(dir, "ctatsplicing/*.cancer.introns"), - getFilesAndCheck(dir, "multiqc/multiqc_data/multiqc_general_stats.txt"), - getFilesAndCheck(dir, "star/*.Aligned.sortedByCoord.out.bam"), - getFilesAndCheck(dir, "star/*.Aligned.sortedByCoord.out.bam.bai"), - getFilesAndCheck(dir, "arriba/*.fusions.tsv"), - meta.run, - meta.design - ] + [meta, getFilesAndCheck(dir, "vcf/*.vcf"), getFilesAndCheck(dir, "stringtie/*.gene.abundance.txt"), getFilesAndCheck(dir, "fusionreport/*/*.fusions.csv"), getFilesAndCheck(dir, "ctatsplicing/*.cancer.introns"), getFilesAndCheck(dir, "multiqc/multiqc_data/multiqc_general_stats.txt"), getFilesAndCheck(dir, "star/*.Aligned.sortedByCoord.out.bam"), getFilesAndCheck(dir, "star/*.Aligned.sortedByCoord.out.bam.bai"), getFilesAndCheck(dir, "arriba/*.fusions.tsv"), meta.run, meta.design] } VARCOV( @@ -57,7 +45,7 @@ workflow RNAFUSION { ) emit: - excels = VARCOV.out.output // channel: [ val(meta), path(excel) ] + excels = VARCOV.out.output // channel: [ val(meta), path(excel) ] } /* diff --git a/workflows/targeted.nf b/workflows/targeted.nf index 3258b43..4aa29bb 100644 --- a/workflows/targeted.nf +++ b/workflows/targeted.nf @@ -1,9 +1,9 @@ -include { SAMTOOLS_VIEW } from '../modules/nf-core/samtools/view/main.nf' -include { SAMTOOLS_SORT } from '../modules/nf-core/samtools/sort/main.nf' -include { SAMTOOLS_FASTQ } from '../modules/nf-core/samtools/fastq/main.nf' -include { PEAR } from '../modules/nf-core/pear/main.nf' -include { MERGE_READS } from '../modules/local/mergereads/main.nf' -include { HOTCOUNT } from '../modules/local/hotcount/main.nf' +include { SAMTOOLS_VIEW } from '../modules/nf-core/samtools/view/main.nf' +include { SAMTOOLS_SORT } from '../modules/nf-core/samtools/sort/main.nf' +include { SAMTOOLS_FASTQ } from '../modules/nf-core/samtools/fastq/main.nf' +include { PEAR } from '../modules/nf-core/pear/main.nf' +include { CAT_FASTQ } from '../modules/nf-core/cat/fastq/main.nf' +include { HOTCOUNT } from '../modules/local/hotcount/main.nf' workflow TARGETED { take: @@ -16,15 +16,15 @@ workflow TARGETED { SAMTOOLS_VIEW( ch_samplesheet, - fasta.map { meta, fa -> tuple(meta, fa, [])}, + fasta.map { meta, fa, fai -> tuple(meta, fa, []) }, [], [], ) SAMTOOLS_SORT( SAMTOOLS_VIEW.out.bam, - fasta, - "" + fasta.map { meta, fa, fai -> tuple(meta, fa, fai) }, + "", ) SAMTOOLS_FASTQ( @@ -33,11 +33,10 @@ workflow TARGETED { ) // Combine fastq and singleton before branching - ch_fastq_and_singleton = SAMTOOLS_FASTQ.out.fastq - .join(SAMTOOLS_FASTQ.out.singleton) + ch_fastq_and_singleton = SAMTOOLS_FASTQ.out.fastq.join(SAMTOOLS_FASTQ.out.singleton) // Branch based on fastq content (keeping both fastq and singleton together) - ch_branched = ch_fastq_and_singleton.branch { _meta, fastq, _singleton -> + ch_branched = ch_fastq_and_singleton.branch { _meta, fastq, _singleton -> non_empty: fastq.any { f -> f.countLines() > 0 } empty: true } @@ -48,19 +47,25 @@ workflow TARGETED { ) // For non-empty fastq: merge PEAR assembled with singleton from branched output + // CAT_FASTQ expects tuple(meta, reads) where reads is a path or list of paths. ch_pear_with_singleton = PEAR.out.assembled .join(ch_branched.non_empty.map { meta, _fastq, singleton -> tuple(meta, singleton) }) + // PEAR assembled and singleton are single-end reads. + .map { meta, assembled, singleton -> tuple(meta + [single_end: true], [assembled, singleton]) } - MERGE_READS( - ch_pear_with_singleton - ) + CAT_FASTQ(ch_pear_with_singleton) + + // For empty fastq: use singleton files directly (skip PEAR and CAT_FASTQ) + ch_singleton_only = ch_branched.empty.map { meta, _fastq, singleton -> tuple(meta, singleton) } - // For empty fastq: use singleton files directly (skip PEAR and MERGE_READS) - ch_singleton_only = ch_branched.empty - .map { meta, _fastq, singleton -> tuple(meta, singleton) } + // Combine CAT_FASTQ output with singleton-only samples + ch_final_fastq = CAT_FASTQ.out.reads.mix(ch_singleton_only) - // Combine MERGE_READS output with singleton-only samples - ch_final_fastq = MERGE_READS.out.merged.mix(ch_singleton_only) + // Normalize join keys: CAT_FASTQ branch may include extra meta fields (e.g. single_end) + // that are absent on query channel metadata. + ch_final_fastq_for_join = ch_final_fastq.map { meta, fastq -> + tuple([id: meta.id, design: meta.design], fastq) + } def query_list = file("${queries}/${gene}/*.txt") @@ -71,7 +76,7 @@ workflow TARGETED { } tuple(meta, query) } - ch_hotcount_input = ch_final_fastq + ch_hotcount_input = ch_final_fastq_for_join .join(ch_queries, failOnDuplicate: true, failOnMismatch: true) .map { meta, fastq, query -> tuple(meta, query, fastq) } @@ -79,7 +84,6 @@ workflow TARGETED { ch_hotcount_input ) - emit: - hotcount = HOTCOUNT.out.counts + hotcount = HOTCOUNT.out.counts }