diff --git a/modules/nf-core/parabricks/fq2bam/main.nf b/modules/nf-core/parabricks/fq2bam/main.nf index 61be1b457dd..5b5fcac034d 100644 --- a/modules/nf-core/parabricks/fq2bam/main.nf +++ b/modules/nf-core/parabricks/fq2bam/main.nf @@ -2,8 +2,6 @@ process PARABRICKS_FQ2BAM { tag "${meta.id}" label 'process_high' label 'process_gpu' - // needed by the module to run on a cluster because we need to copy the fasta reference, see https://github.com/nf-core/modules/issues/9230 - stageInMode 'copy' container "nvcr.io/nvidia/clara/clara-parabricks:4.6.0-1" @@ -44,14 +42,38 @@ process PARABRICKS_FQ2BAM { def known_sites_output_cmd = known_sites ? "--out-recal-file ${prefix}.table" : "" def interval_file_command = interval_file ? (interval_file instanceof List ? interval_file.collect { "--interval-file ${it}" }.join(' ') : "--interval-file ${interval_file}") : "" - def num_gpus = task.accelerator ? "--num-gpus ${task.accelerator.request}" : '' - """ + def num_gpus = task.accelerator ? "--num-gpus ${task.accelerator.request}" : '' + + if (!fasta && extension=="cram") error "Fasta reference is required for CRAM output" + + """ + # The section below checks if the reference is present with the index files. + # If it is not, then we create a dummy reference file to allow Parabricks to run without erroring out + # For BAMs, this index file is empty, for CRAMs we symlink the fasta to the expected index path + INDEX=`find -L ./ -name "*.amb" | sed 's/\\.amb\$//'` - cp ${fasta} \$INDEX + + echo "Inferred reference at: \$INDEX" + + dummy_index=0 + ref_path=${fasta} + + if [[ "${extension}" == "bam" ]] && [ ! -e \$INDEX ]; then + echo "BAM requested but ref path does not exist. Creating dummy reference." + dummy_index=1 + touch \$INDEX + ref_path="\$INDEX" + elif [[ "${extension}" == "cram" ]] && [ ! -e \$INDEX ]; then + echo "CRAM requested but ref does not follow pattern. Creating symlink." + dummy_index=1 + ln -sf \$(realpath ${fasta}) \$(realpath \$INDEX) + ref_path="\$INDEX" + fi pbrun \\ fq2bam \\ - --ref \$INDEX \\ + --preserve-file-symlinks \\ + --ref \$ref_path \\ ${in_fq_command} \\ --out-bam ${prefix}.${extension} \\ ${known_sites_command} \\ @@ -62,6 +84,11 @@ process PARABRICKS_FQ2BAM { --monitor-usage \\ ${args} + # Remove the dummy index if we added one + if [ dummy_index ]; then + rm \$INDEX + fi + cat <<-END_VERSIONS > versions.yml "${task.process}": pbrun: \$(echo \$(pbrun version 2>&1) | sed 's/^Please.* //' ) diff --git a/modules/nf-core/parabricks/fq2bam/meta.yml b/modules/nf-core/parabricks/fq2bam/meta.yml index b2859d25a67..88e31c64bc6 100644 --- a/modules/nf-core/parabricks/fq2bam/meta.yml +++ b/modules/nf-core/parabricks/fq2bam/meta.yml @@ -33,7 +33,7 @@ input: Groovy Map containing fasta information - fasta: type: file - description: reference fasta file - must be unzipped + description: (optional for BAM, required for CRAM) reference fasta file - must be unzipped pattern: "*.fasta" ontologies: - edam: "http://edamontology.org/format_1929" # FASTA diff --git a/modules/nf-core/parabricks/fq2bam/tests/main.nf.test b/modules/nf-core/parabricks/fq2bam/tests/main.nf.test index dd63c691e82..d76292e485d 100644 --- a/modules/nf-core/parabricks/fq2bam/tests/main.nf.test +++ b/modules/nf-core/parabricks/fq2bam/tests/main.nf.test @@ -137,6 +137,86 @@ nextflow_process { } } + test("SRR389222 - fastq - se - no reference") { + + config './nextflow.config' + + when { + params { + module_args = '--low-memory' + // Ref: https://forums.developer.nvidia.com/t/problem-with-gpu/256825/6 + // Parabricks’s fq2bam requires 24GB of memory. + // Using --low-memory for testing + bwa_prefix = 'genome.fa' + } + process { + """ + input[0] = Channel.of([ + [ id:'test', single_end:true ], // meta map + [ + file('https://github.com/nf-core/test-datasets/raw/methylseq/testdata/SRR389222_sub1.fastq.gz', checkIfExists: true) + ] + ]) + input[1] = [ [], [] ] + input[2] = BWA_INDEX.out.index + input[3] = [ [], [] ] + input[4] = [ [], [] ] + input[5] = 'bam' + """ + } + } + + then { + assertAll( + { assert process.success }, + { assert snapshot( + bam(process.out.bam[0][1]).getReadsMD5(), + file(process.out.bai[0][1]).name, + process.out.versions, + path(process.out.versions[0]).yaml + ).match() } + ) + } + } + + test("SRR389222 - fastq - se - no reference - stub") { + + options '-stub' + + when { + params { + module_args = '' + bwa_prefix = '' + } + process { + """ + input[0] = Channel.of([ + [ id:'test', single_end:true ], // meta map + [ + file('https://github.com/nf-core/test-datasets/raw/methylseq/testdata/SRR389222_sub1.fastq.gz', checkIfExists: true) + ] + ]) + input[1] = [ [], [] ] + input[2] = BWA_INDEX.out.index + input[3] = [ [], [] ] + input[4] = [ [], [] ] + input[5] = 'bam' + """ + } + } + + then { + assertAll( + { assert process.success }, + { assert snapshot( + process.out, + path(process.out.versions.get(0)).yaml, + path(process.out.compatible_versions.get(0)).yaml + ).match() } + ) + } + } + test("sarscov2 - fastq - pe") { when { diff --git a/modules/nf-core/parabricks/fq2bam/tests/main.nf.test.snap b/modules/nf-core/parabricks/fq2bam/tests/main.nf.test.snap index aa6fef3cdfb..faf7ff011d8 100644 --- a/modules/nf-core/parabricks/fq2bam/tests/main.nf.test.snap +++ b/modules/nf-core/parabricks/fq2bam/tests/main.nf.test.snap @@ -235,6 +235,105 @@ }, "timestamp": "2025-10-13T16:48:32.435485918" }, + "SRR389222 - fastq - se - no reference - stub": { + "content": [ + { + "0": [ + [ + { + "id": "test", + "single_end": true + }, + "test.bam:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "1": [ + [ + { + "id": "test", + "single_end": true + }, + "test.bam.bai:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "2": [ + + ], + "3": [ + + ], + "4": [ + + ], + "5": [ + + ], + "6": [ + + ], + "7": [ + "compatible_versions.yml:md5,01a6599f855da953f58c26a0c1df301e" + ], + "8": [ + "versions.yml:md5,0c47791a7efece8e797f064b663ef855" + ], + "bai": [ + [ + { + "id": "test", + "single_end": true + }, + "test.bam.bai:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "bam": [ + [ + { + "id": "test", + "single_end": true + }, + "test.bam:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "bqsr_table": [ + + ], + "compatible_versions": [ + "compatible_versions.yml:md5,01a6599f855da953f58c26a0c1df301e" + ], + "crai": [ + + ], + "cram": [ + + ], + "duplicate_metrics": [ + + ], + "qc_metrics": [ + + ], + "versions": [ + "versions.yml:md5,0c47791a7efece8e797f064b663ef855" + ] + }, + { + "PARABRICKS_FQ2BAM": { + "pbrun": "4.6.0-1" + } + }, + { + "PARABRICKS_FQ2BAM": null, + "pbrun_version": "4.6.0-1", + "compatible_with": "BWA mem: 0.7.15, Picard: 2.18.25" + } + ], + "meta": { + "nf-test": "0.9.3", + "nextflow": "25.04.8" + }, + "timestamp": "2025-10-31T18:59:39.126259477" + }, "sarscov2 - fastq - pe - cram - stub": { "content": [ { @@ -347,5 +446,24 @@ "nextflow": "25.04.8" }, "timestamp": "2025-10-13T16:46:33.272405432" + }, + "SRR389222 - fastq - se - no reference": { + "content": [ + "3d5b94990c7fdf90a682edb5ee0f59de", + "test.bam.bai", + [ + "versions.yml:md5,0c47791a7efece8e797f064b663ef855" + ], + { + "PARABRICKS_FQ2BAM": { + "pbrun": "4.6.0-1" + } + } + ], + "meta": { + "nf-test": "0.9.3", + "nextflow": "25.04.8" + }, + "timestamp": "2025-10-31T19:22:35.643220011" } } \ No newline at end of file