Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 2 additions & 6 deletions main.nf
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,7 @@ workflow NFCORE_RNASEQ {
params.bowtie2_index,
params.bbsplit_index,
params.sortmerna_index,
params.bowtie2_rrna_index,
params.aligner,
params.pseudo_aligner,
params.skip_bbsplit,
Expand All @@ -126,11 +127,6 @@ workflow NFCORE_RNASEQ {
// WORKFLOW: Run nf-core/rnaseq workflow
//
ch_samplesheet = channel.value(file(params.input, checkIfExists: true))

// Bowtie2 rRNA index is built on-demand inside the fastq_remove_rrna subworkflow
// rather than in PREPARE_GENOME_INDICES, to avoid duplicating the rRNA FASTA preparation logic
ch_bowtie2_rrna_index = channel.empty()

def qc_tools = defineQcTools(params)

RNASEQ (
Expand All @@ -149,7 +145,7 @@ workflow NFCORE_RNASEQ {
PREPARE_GENOME_INDICES.out.bbsplit_index,
PREPARE_GENOME_REFERENCES.out.rrna_fastas,
PREPARE_GENOME_INDICES.out.sortmerna_index,
ch_bowtie2_rrna_index,
PREPARE_GENOME_INDICES.out.bowtie2_rrna_index,
PREPARE_GENOME_INDICES.out.splicesites,
PREPARE_GENOME_REFERENCES.out.kraken_db,
qc_tools
Expand Down
8 changes: 8 additions & 0 deletions nextflow_schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -330,6 +330,14 @@
"help_text": "Choose between 'sortmerna' (default), 'bowtie2', or 'ribodetector' for rRNA removal.\n\n- **sortmerna**: Reference-based filtering (default). Requires `--ribo_database_manifest`. Note: Default databases include SILVA sequences requiring licensing for commercial use.\n- **bowtie2**: Alignment-based filtering. Requires `--ribo_database_manifest`. Recommended for users with SILVA licensing concerns as it supports custom databases.\n- **ribodetector**: ML-based detection without a reference requirement. Useful for organisms lacking well-characterized rRNA sequences or to avoid database licensing requirements.",
"enum": ["sortmerna", "ribodetector", "bowtie2"]
},
"bowtie2_rrna_index": {
"type": "string",
"format": "path",
"exists": true,
"fa_icon": "fas fa-bezier-curve",
"description": "Path to directory or tar.gz archive for pre-built Bowtie2 index for rRNA removal.",
"help_text": "Optional when using `--remove_ribo_rna` and `--ribo_removal_tool` is set to `bowtie2`. If not provided, the index will be built using the database provided with `--ribo_database_manifest`"
},
"use_gpu_ribodetector": {
"type": "boolean",
"description": "Enable GPU acceleration for ribodetector.",
Expand Down
35 changes: 26 additions & 9 deletions subworkflows/local/prepare_genome_indices/main.nf
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

include { UNTAR as UNTAR_BBSPLIT_INDEX } from '../../../modules/nf-core/untar'
include { UNTAR as UNTAR_SORTMERNA_INDEX } from '../../../modules/nf-core/untar'
include { UNTAR as UNTAR_BOWTIE2_RRNA_INDEX } from '../../../modules/nf-core/untar'
include { UNTAR as UNTAR_STAR_INDEX } from '../../../modules/nf-core/untar'
include { UNTAR as UNTAR_RSEM_INDEX } from '../../../modules/nf-core/untar'
include { UNTAR as UNTAR_HISAT2_INDEX } from '../../../modules/nf-core/untar'
Expand Down Expand Up @@ -43,6 +44,7 @@ workflow PREPARE_GENOME_INDICES {
bowtie2_index // directory: /path/to/bowtie2/index/
bbsplit_index // directory: /path/to/bbsplit/index/
sortmerna_index // directory: /path/to/sortmerna/index/
bowtie2_rrna_index // directory: /path/to/bowtie2/index/
aligner // string: Specifies the alignment algorithm to use - available options are 'star_salmon', 'star_rsem', 'hisat2', and 'bowtie2_salmon'
pseudo_aligner // string: Specifies the pseudo aligner to use - available options are 'salmon'. Runs in addition to '--aligner'
skip_bbsplit // boolean: Skip BBSplit for removal of non-reference genome reads
Expand All @@ -62,6 +64,7 @@ workflow PREPARE_GENOME_INDICES {
def prepare_tool_indices = []
if (!skip_bbsplit) { prepare_tool_indices << 'bbsplit' }
if (ribo_removal_tool == 'sortmerna') { prepare_tool_indices << 'sortmerna' }
if (ribo_removal_tool == 'bowtie2' && bowtie2_rrna_index) { prepare_tool_indices << 'bowtie2_rrna' } // If no index is provided, this subworkflow does not need to build an index as that is handled by the fastq_remove_rrna subworkflow.
if ((!skip_alignment && aligner) || aligner == 'star_rsem') { prepare_tool_indices << aligner }
if (!skip_pseudo_alignment && pseudo_aligner) { prepare_tool_indices << pseudo_aligner }

Expand Down Expand Up @@ -124,6 +127,19 @@ workflow PREPARE_GENOME_INDICES {
}
}

//-------------------------------------------------------------
// 3b) Bowtie2 rRNA index - only handles untar
//-------------------------------------------------------------
ch_bowtie2_rrna_index = channel.empty()
if ('bowtie2_rrna' in prepare_tool_indices) {
if (bowtie2_rrna_index.endsWith('.tar.gz')) {
ch_bowtie2_rrna_index = UNTAR_BOWTIE2_RRNA_INDEX ([ [:], file(bowtie2_rrna_index, checkIfExists: true) ]).untar.first()
} else {
ch_bowtie2_rrna_index = channel.value([ [:], file(bowtie2_rrna_index, checkIfExists: true) ])
}
// No need to build as that is handled in the fastq_remove_rrna subworkflow from nf-core
}

//----------------------------------------------------
// 4) STAR index (e.g. for 'star_salmon') -> needs FASTA if built
//----------------------------------------------------
Expand Down Expand Up @@ -267,13 +283,14 @@ workflow PREPARE_GENOME_INDICES {
}

emit:
splicesites = ch_splicesites // channel: path(genome.splicesites.txt)
bbsplit_index = ch_bbsplit_index // channel: path(bbsplit/index/)
sortmerna_index = ch_sortmerna_index // channel: path(sortmerna/index/)
star_index = ch_star_index // channel: path(star/index/)
rsem_index = ch_rsem_index // channel: path(rsem/index/)
hisat2_index = ch_hisat2_index // channel: path(hisat2/index/)
bowtie2_index = ch_bowtie2_index // channel: path(bowtie2/index/)
salmon_index = ch_salmon_index // channel: path(salmon/index/)
kallisto_index = ch_kallisto_index // channel: [ meta, path(kallisto/index/) ]
splicesites = ch_splicesites // channel: path(genome.splicesites.txt)
bbsplit_index = ch_bbsplit_index // channel: path(bbsplit/index/)
sortmerna_index = ch_sortmerna_index // channel: path(sortmerna/index/)
bowtie2_rrna_index = ch_bowtie2_rrna_index // channel: path(bowtie2/index/)
star_index = ch_star_index // channel: path(star/index/)
rsem_index = ch_rsem_index // channel: path(rsem/index/)
hisat2_index = ch_hisat2_index // channel: path(hisat2/index/)
bowtie2_index = ch_bowtie2_index // channel: path(bowtie2/index/)
salmon_index = ch_salmon_index // channel: path(salmon/index/)
kallisto_index = ch_kallisto_index // channel: [ meta, path(kallisto/index/) ]
}
85 changes: 85 additions & 0 deletions tests/remove_ribo_rna.nf.test
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,91 @@ nextflow_pipeline {
)
}

cleanup {
// Only prune/delete on CI - keeping local VM state intact prevents
// cross-test launchDir wipes that break nf-test snapshot walks.
if (System.getenv("CI") == "true") {
if (System.getenv("NFT_PROFILE")?.contains("docker")) {
"docker system prune -a -f --volumes".execute()
}
new File("${launchDir}").deleteDir()
}
}
}
test("Params: --remove_ribo_rna --ribo_removal_tool bowtie2 --bowtie2_rrna_index") {

when {
params {
outdir = "$outputDir"
remove_ribo_rna = true
ribo_removal_tool = 'bowtie2'
bowtie2_rrna_index = '' // Pending PR of test dataset on nf-core/test-datasets:rnaseq
skip_qc = true
skip_stringtie = true
skip_bigwig = true
}
}

then {
def stable_name = getAllFilesFromDir(params.outdir, relative: true, includeDir: true, ignore: ['pipeline_info/*.{html,json,txt}', 'seqkit', 'seqkit/**'])
def stable_path = getAllFilesFromDir(params.outdir, ignoreFile: 'tests/.nftignore')
assertAll(
{ assert workflow.success},
{ assert snapshot(
// Number of tasks should be lower than the standard bowtie2 test because the index build step is skipped
workflow.trace.succeeded().size(),
removeFromYamlMap("$outputDir/pipeline_info/nf_core_rnaseq_software_mqc_versions.yml", "Workflow").findAll { it.key != "SEQKIT_REPLACE" && it.key != "SEQKIT_REPLACE_U2T" },
stable_name,
stable_path
).match() }
)
}

cleanup {
if (System.getenv("CI") == "true") {
if (System.getenv("NFT_PROFILE")?.contains("docker")) {
"docker system prune -a -f --volumes".execute()
}
new File("${launchDir}").deleteDir()
}
}
}
test("Params: --remove_ribo_rna --ribo_removal_tool bowtie2 --bowtie2_rrna_index - stub") {

options "-stub"

when {
params {
outdir = "$outputDir"
remove_ribo_rna = true
ribo_removal_tool = 'bowtie2'
bowtie2_rrna_index = '' // Pending PR of test dataset on nf-core/test-datasets:rnaseq
skip_qc = true
skip_stringtie = true
skip_bigwig = true
}
}

then {
// stable_name: All files + folders in ${params.outdir}/ with a stable name
def stable_name = getAllFilesFromDir(params.outdir, relative: true, includeDir: true, ignore: ['pipeline_info/*.{html,json,txt}', 'seqkit', 'seqkit/**'])
// stable_path: All files in ${params.outdir}/ with stable content
def stable_path = getAllFilesFromDir(params.outdir, ignoreFile: 'tests/.nftignore')
assertAll(
{ assert workflow.success},
{ assert snapshot(
// Number of successful tasks
workflow.trace.succeeded().size(),
// pipeline versions.yml file for multiqc from which Nextflow and pipeline versions are removed (all from the workflow key)
removeFromYamlMap("$outputDir/pipeline_info/nf_core_rnaseq_software_mqc_versions.yml", "Workflow").findAll { it.key != "SEQKIT_REPLACE" && it.key != "SEQKIT_REPLACE_U2T" },
// All stable path name, with a relative path
stable_name,
// All files with stable contents
stable_path
).match() }
)
}

cleanup {
// Only prune/delete on CI - keeping local VM state intact prevents
// cross-test launchDir wipes that break nf-test snapshot walks.
Expand Down
2 changes: 1 addition & 1 deletion workflows/rnaseq/main.nf
Original file line number Diff line number Diff line change
Expand Up @@ -203,7 +203,7 @@ workflow RNASEQ {

// Determine if we need to build rRNA removal indexes
def make_sortmerna_index = !params.sortmerna_index && params.remove_ribo_rna && params.ribo_removal_tool == 'sortmerna'
def make_bowtie2_index = params.remove_ribo_rna && params.ribo_removal_tool == 'bowtie2'
def make_bowtie2_index = !params.bowtie2_rrna_index && params.remove_ribo_rna && params.ribo_removal_tool == 'bowtie2'

FASTQ_QC_TRIM_FILTER_SETSTRANDEDNESS (
ch_fastq, // ch_reads
Expand Down