Skip to content
Merged
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
6 changes: 6 additions & 0 deletions assets/catalog/catalog.md
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,12 @@
- [spliceai/derive](../../modules/nextflow/spliceai/derive/main.nf) — Derive splice event scores from SpliceAI predictions.
- [spliceai/predict](../../modules/nextflow/spliceai/predict/main.nf) — Predict splice junctions from genomic sequences using SpliceAI.
- [spliceai/publish](../../modules/nextflow/spliceai/publish/main.nf) — Collect and organize SpliceAI output files.
- [spliceai2/chunk](../../modules/nextflow/spliceai2/chunk/main.nf) — Chunk genomic sequences for parallel SpliceAI2 prediction.
- [spliceai2/predict](../../modules/nextflow/spliceai2/predict/main.nf) — Predict splice sites from genomic sequences using SpliceAI2.
- [spliceai2/publish](../../modules/nextflow/spliceai2/publish/main.nf) — Collect and organize SpliceAI2 output files.
- [spliceai2/transcripts](../../modules/nextflow/spliceai2/transcripts/main.nf) — Decode transcript structures for a set of loci using SpliceAI2.
- [subworkflows/spliceai2](../../subworkflows/spliceai2/main.nf) — Chunk, predict, convert, merge, and optionally decode SpliceAI2 outputs.
- [workflows/spliceai2](../../workflows/spliceai2/main.nf) — Standalone SpliceAI2 pipeline.
- [aparent/chunk](../../modules/nextflow/aparent/chunk/main.nf) — Chunk genomic regions for parallel APARENT prediction.
- [aparent/predict](../../modules/nextflow/aparent/predict/main.nf) — Predict polyadenylation sites using the APARENT deep learning model.
- [minisplice/download](../../modules/nextflow/minisplice/download/main.nf) — Download MiniSplice model and calibration files.
Expand Down
59 changes: 59 additions & 0 deletions modules/nextflow/spliceai2/chunk/main.nf
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
/*
Copyright (c) 2026 The Hiller Lab at the Senckenberg Gessellschaft für Naturforschung
Distributed under the terms of the Apache License, Version 2.0.
*/

/*
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
SPLICEAI2_CHUNK — Chunk genomic sequences for parallel SpliceAI2 prediction.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
*/

process SPLICEAI2_CHUNK {
tag "$meta.id"
label 'process_low'

container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ?
'' :
'ghcr.io/hillerlab/spliceai2:latest' }"

input:
tuple val(meta), path(genome)
val compression

output:
tuple val(meta), path("chunks/*.fa"), optional: true, emit: fasta
tuple val(meta), path("chunks/*.fa.gz"), optional: true, emit: fasta_gz
path "versions.yml", emit: versions

when:
task.ext.when == null || task.ext.when

script:
def args = task.ext.args ?: ''
def gzip = compression ? '--gzip' : ''
"""
spliceai2 chunk \\
$args \\
$gzip \\
--threads ${task.cpus} \\
--sequence "${genome}"

cat <<-END_VERSIONS > versions.yml
"${task.process}":
spliceai2 chunk: \$( spliceai2 chunk --version | sed 's/^spliceai-chunk //g' )
END_VERSIONS
"""

stub:
def extension = compression ? 'fa.gz' : 'fa'
"""
mkdir -p chunks
touch chunks/stub.${extension}

cat <<-END_VERSIONS > versions.yml
"${task.process}":
spliceai2 chunk: \$( spliceai2 chunk --version | sed 's/^spliceai-chunk //g' )
END_VERSIONS
"""
}
64 changes: 64 additions & 0 deletions modules/nextflow/spliceai2/predict/main.nf
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
/*
Copyright (c) 2026 The Hiller Lab at the Senckenberg Gessellschaft für Naturforschung
Distributed under the terms of the Apache License, Version 2.0.
*/

/*
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
SPLICEAI2_PREDICT — Predict splice sites for one sequence chunk.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
*/

process SPLICEAI2_PREDICT {
tag "$meta.id"
label 'process_low'
label 'process_gpu'

container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ?
'' :
'ghcr.io/hillerlab/spliceai2:latest' }"

input:
tuple val(meta), path(fasta)
path models
val species

output:
tuple val(meta), path("spliceai/*.donor_plus.wig"), emit: donor_plus
tuple val(meta), path("spliceai/*.donor_minus.wig"), emit: donor_minus
tuple val(meta), path("spliceai/*.acceptor_plus.wig"), emit: acceptor_plus
tuple val(meta), path("spliceai/*.acceptor_minus.wig"), emit: acceptor_minus
tuple val(meta), path("spliceai/*.wig"), emit: all
path "versions.yml", emit: versions

when:
task.ext.when == null || task.ext.when

script:
def args = task.ext.args ?: ''
"""
spliceai2 predict --no-compile \\
$args \\
--sequence "${fasta}" \\
--models "${models}" \\
--species "${species}" \\
--outdir spliceai

cat <<-END_VERSIONS > versions.yml
"${task.process}":
spliceai2: \$( spliceai2 --version | sed 's/^spliceai2 //g' )
END_VERSIONS
"""

stub:
"""
mkdir -p spliceai
touch spliceai/stub.donor_plus.wig spliceai/stub.donor_minus.wig \\
spliceai/stub.acceptor_plus.wig spliceai/stub.acceptor_minus.wig

cat <<-END_VERSIONS > versions.yml
"${task.process}":
spliceai2: \$( spliceai2 --version | sed 's/^spliceai2 //g' )
END_VERSIONS
"""
}
40 changes: 40 additions & 0 deletions modules/nextflow/spliceai2/publish/main.nf
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
/*
Copyright (c) 2026 The Hiller Lab at the Senckenberg Gessellschaft für Naturforschung
Distributed under the terms of the Apache License, Version 2.0.
*/

/*
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
SPLICEAI2_PUBLISH — Collect the four SpliceAI2 strand and site BigWigs.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
*/

process SPLICEAI2_PUBLISH {
tag "publish"
label 'process_single'

input:
tuple val(meta), path(donor_plus)
tuple val(meta1), path(donor_minus)
tuple val(meta2), path(acceptor_plus)
tuple val(meta3), path(acceptor_minus)

output:
path("spliceai2"), emit: spliceai2

script:
"""
mkdir -p spliceai2
cp "${donor_plus}" spliceai2/
cp "${donor_minus}" spliceai2/
cp "${acceptor_plus}" spliceai2/
cp "${acceptor_minus}" spliceai2/
"""

stub:
"""
mkdir -p spliceai2
touch spliceai2/donor_plus.bw spliceai2/donor_minus.bw \\
spliceai2/acceptor_plus.bw spliceai2/acceptor_minus.bw
"""
}
64 changes: 64 additions & 0 deletions modules/nextflow/spliceai2/transcripts/main.nf
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
/*
Copyright (c) 2026 The Hiller Lab at the Senckenberg Gessellschaft für Naturforschung
Distributed under the terms of the Apache License, Version 2.0.
*/

/*
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
SPLICEAI2_TRANSCRIPTS — Decode transcript structures for a set of loci.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
*/

process SPLICEAI2_TRANSCRIPTS {
tag "$meta.id"
label 'process_high'
label 'process_gpu'

container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ?
'' :
'ghcr.io/hillerlab/spliceai2:latest' }"

input:
tuple val(meta), path(genome), path(genome_fai), path(loci)
path models
val species

output:
tuple val(meta), path("transcripts/*.transcripts.bed"), emit: transcripts
tuple val(meta), path("transcripts/*.skipped.bed"), emit: skipped
path "versions.yml", emit: versions

when:
task.ext.when == null || task.ext.when

script:
def args = task.ext.args ?: ''
"""
test -s "${genome_fai}"

spliceai2 transcripts --no-compile \\
$args \\
--genome "${genome}" \\
--loci "${loci}" \\
--models "${models}" \\
--species "${species}" \\
--outdir transcripts

cat <<-END_VERSIONS > versions.yml
"${task.process}":
spliceai2: \$( spliceai2 --version | sed 's/^spliceai2 //g' )
END_VERSIONS
"""

stub:
def prefix = meta.id
"""
mkdir -p transcripts
touch "transcripts/${prefix}.transcripts.bed" "transcripts/${prefix}.skipped.bed"

cat <<-END_VERSIONS > versions.yml
"${task.process}":
spliceai2: \$( spliceai2 --version | sed 's/^spliceai2 //g' )
END_VERSIONS
"""
}
4 changes: 2 additions & 2 deletions modules/nextflow/splicetransformer/derive/main.nf
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ process SPLICETRANSFORMER_DERIVE {

cat <<-END_VERSIONS > versions.yml
"${task.process}":
splicetransformer derive: $( splicetransformer derive --version | sed 's/splicetransformer derive //g' )
splicetransformer derive: \$( splicetransformer derive --version | sed 's/splicetransformer derive //g' )
END_VERSIONS
"""

Expand All @@ -56,7 +56,7 @@ process SPLICETRANSFORMER_DERIVE {

cat <<-END_VERSIONS > versions.yml
"${task.process}":
splicetransformer derive: $( splicetransformer derive --version | sed 's/splicetransformer derive //g' )
splicetransformer derive: \$( splicetransformer derive --version | sed 's/splicetransformer derive //g' )
END_VERSIONS
"""
}
122 changes: 122 additions & 0 deletions subworkflows/spliceai2/main.nf
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
/*
Copyright (c) 2026 The Hiller Lab at the Senckenberg Gessellschaft für Naturforschung
Distributed under the terms of the Apache License, Version 2.0.
*/

/*
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
IMPORT LOCAL MODULES/SUBWORKFLOWS
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
*/

include { SPLICEAI2_CHUNK } from '../../modules/nextflow/spliceai2/chunk/main.nf'
include { SPLICEAI2_PREDICT } from '../../modules/nextflow/spliceai2/predict/main.nf'
include { SPLICEAI2_TRANSCRIPTS } from '../../modules/nextflow/spliceai2/transcripts/main.nf'
include { SPLICEAI2_PUBLISH } from '../../modules/nextflow/spliceai2/publish/main.nf'

include { UCSC_WIGTOBIGWIG as WIGTOBIGWIG_DONOR_PLUS } from '../../modules/nextflow/ucsc/wigtobigwig/main.nf'
include { UCSC_WIGTOBIGWIG as WIGTOBIGWIG_DONOR_MINUS } from '../../modules/nextflow/ucsc/wigtobigwig/main.nf'
include { UCSC_WIGTOBIGWIG as WIGTOBIGWIG_ACCEPTOR_PLUS } from '../../modules/nextflow/ucsc/wigtobigwig/main.nf'
include { UCSC_WIGTOBIGWIG as WIGTOBIGWIG_ACCEPTOR_MINUS } from '../../modules/nextflow/ucsc/wigtobigwig/main.nf'

include { BIGWIGMERGE as BIGWIGMERGE_DONOR_PLUS } from '../../modules/nextflow/bigtools/bigwigmerge/main.nf'
include { BIGWIGMERGE as BIGWIGMERGE_DONOR_MINUS } from '../../modules/nextflow/bigtools/bigwigmerge/main.nf'
include { BIGWIGMERGE as BIGWIGMERGE_ACCEPTOR_PLUS } from '../../modules/nextflow/bigtools/bigwigmerge/main.nf'
include { BIGWIGMERGE as BIGWIGMERGE_ACCEPTOR_MINUS } from '../../modules/nextflow/bigtools/bigwigmerge/main.nf'

workflow SPLICEAI2 {
take:
genome // channel: [ val(meta), path(genome) ]
chromsizes // channel: [ path(chromsizes) ]
compression // bool
models // path(model directory)
species // SpliceAI2 species name
genome_fai // path(genome.fai), required with loci
loci // path(BED6), optional
ch_versions // channel: [ path(version) ]

main:
ch_chunks = Channel.empty()
ch_transcripts = Channel.empty()
ch_skipped = Channel.empty()
SPLICEAI2_CHUNK(genome, compression)

if (compression) {
SPLICEAI2_CHUNK.out.fasta_gz
.flatMap {
meta, fa ->
def fas = fa instanceof List ? fa : [fa]
fas.collect { it ->
def identifier = it.baseName.replaceFirst(/^tmp\./, '').replaceFirst(/\.fa$/, '')
[ [ id: meta.id + '.' + identifier ], it ]
}
}
.set { ch_chunks }
} else {
SPLICEAI2_CHUNK.out.fasta
.flatMap {
meta, fa ->
def fas = fa instanceof List ? fa : [fa]
fas.collect { it ->
def identifier = it.baseName.replaceFirst(/^tmp\./, '').replaceFirst(/\.fa$/, '')
[ [ id: meta.id + '.' + identifier ], it ]
}
}
.set { ch_chunks }
}

SPLICEAI2_PREDICT(ch_chunks, models, species)

WIGTOBIGWIG_DONOR_PLUS(SPLICEAI2_PREDICT.out.donor_plus.map { meta, wig -> [ [ id: meta.id + '.donor_plus' ], wig ] }, chromsizes)
WIGTOBIGWIG_DONOR_MINUS(SPLICEAI2_PREDICT.out.donor_minus.map { meta, wig -> [ [ id: meta.id + '.donor_minus' ], wig ] }, chromsizes)
WIGTOBIGWIG_ACCEPTOR_PLUS(SPLICEAI2_PREDICT.out.acceptor_plus.map { meta, wig -> [ [ id: meta.id + '.acceptor_plus' ], wig ] }, chromsizes)
WIGTOBIGWIG_ACCEPTOR_MINUS(SPLICEAI2_PREDICT.out.acceptor_minus.map { meta, wig -> [ [ id: meta.id + '.acceptor_minus' ], wig ] }, chromsizes)

BIGWIGMERGE_DONOR_PLUS(
WIGTOBIGWIG_DONOR_PLUS.out.bigwig
.map { meta, bigwig -> bigwig }
.collect()
.map { bws -> [ [ id : 'donor_plus' ], bws ] },
)
BIGWIGMERGE_DONOR_MINUS(
WIGTOBIGWIG_DONOR_MINUS.out.bigwig
.map { meta, bigwig -> bigwig }
.collect()
.map { bws -> [ [ id : 'donor_minus' ], bws ] },
)
BIGWIGMERGE_ACCEPTOR_PLUS(
WIGTOBIGWIG_ACCEPTOR_PLUS.out.bigwig
.map { meta, bigwig -> bigwig }
.collect()
.map { bws -> [ [ id : 'acceptor_plus' ], bws ] },
)
BIGWIGMERGE_ACCEPTOR_MINUS(
WIGTOBIGWIG_ACCEPTOR_MINUS.out.bigwig
.map { meta, bigwig -> bigwig }
.collect()
.map { bws -> [ [ id : 'acceptor_minus' ], bws ] },
)

SPLICEAI2_PUBLISH(
BIGWIGMERGE_DONOR_PLUS.out.bigwig,
BIGWIGMERGE_DONOR_MINUS.out.bigwig,
BIGWIGMERGE_ACCEPTOR_PLUS.out.bigwig,
BIGWIGMERGE_ACCEPTOR_MINUS.out.bigwig,
)

if (loci != null) {
SPLICEAI2_TRANSCRIPTS(
genome.map { meta, fasta -> [ meta, fasta, genome_fai, loci ] },
models,
species
)
ch_transcripts = SPLICEAI2_TRANSCRIPTS.out.transcripts
ch_skipped = SPLICEAI2_TRANSCRIPTS.out.skipped
}

emit:
spliceai2 = SPLICEAI2_PUBLISH.out.spliceai2
transcripts = ch_transcripts
skipped = ch_skipped
versions = ch_versions
}
Loading
Loading