Skip to content
Open
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
33 changes: 33 additions & 0 deletions subworkflows/nf-core/cram_qc_mosdepth_samtools/main.nf
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
//
// QC on CRAM
//

include { MOSDEPTH } from '../../../modules/nf-core/mosdepth'
include { SAMTOOLS_STATS } from '../../../modules/nf-core/samtools/stats'

workflow CRAM_QC_MOSDEPTH_SAMTOOLS {
take:
cram // channel: [mandatory] [ meta, cram, crai ]
fasta_fai // channel: [mandatory] [ meta, fasta, fai ]
intervals

main:
reports = channel.empty()

// Reports run on cram
SAMTOOLS_STATS(cram, fasta_fai)

ch_mosdepth_in = cram
.combine(intervals.map { meta, interval -> interval }.ifEmpty([ [] ]))
.map { meta, cram_file, crai, bed -> [ meta, cram_file, crai, bed ?: [] ] }

MOSDEPTH(ch_mosdepth_in, fasta_fai.map { meta, fasta, fai -> [ meta, fasta ] }, [])

// Gather all reports generated
reports = reports.mix(SAMTOOLS_STATS.out.stats)
reports = reports.mix(MOSDEPTH.out.global_txt)
reports = reports.mix(MOSDEPTH.out.regions_txt)

emit:
reports // channel: [ meta, report_file ]
}
63 changes: 63 additions & 0 deletions subworkflows/nf-core/cram_qc_mosdepth_samtools/meta.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
# yaml-language-server: $schema=https://raw.githubusercontent.com/nf-core/modules/master/subworkflows/yaml-schema.json
name: cram_qc_mosdepth_samtools
description: Comprehensive QC analysis on CRAM files using mosdepth and samtools
keywords:
- qc
- cram
- quality-control
- mosdepth
- samtools
- coverage
- statistics
components:
- samtools/stats
- mosdepth

input:
- meta:
type: map
description: |
Groovy Map containing sample information
e.g. [ id:'sample1', single_end:false ]
- cram:
type: file
description: CRAM file
pattern: "*.cram"
- crai:
type: file
description: CRAM file index
pattern: "*.crai"
- meta2:
type: map
description: |
Groovy Map containing reference information
e.g. [ id:'genome' ]
- fasta:
type: file
description: Reference genome FASTA file
pattern: "*.{fasta,fa,fna}"
- meta3:
type: map
description: |
Groovy Map containing interval information
e.g. [ id:'intervals' ]
- intervals:
type: optional file
description: BED file containing genomic intervals
pattern: "*.bed"

output:
- meta:
type: map
description: |
Groovy Map containing sample information
e.g. [ id:'sample1', single_end:false ]
- reports:
type: file
description: QC report files (samtools stats and mosdepth outputs)
pattern: "*{.stats,.txt,.bed.gz,.bed.gz.csi}"

authors:
- "@agrima2010"
maintainers:
- "@agrima2010"
111 changes: 111 additions & 0 deletions subworkflows/nf-core/cram_qc_mosdepth_samtools/tests/main.nf.test
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
nextflow_workflow {

name "Test Workflow CRAM_QC_MOSDEPTH_SAMTOOLS"
script "../main.nf"
workflow "CRAM_QC_MOSDEPTH_SAMTOOLS"

tag "subworkflows"
tag "subworkflows_nfcore"
tag "cram_qc_mosdepth_samtools"
tag "subworkflows/cram_qc_mosdepth_samtools"
tag "samtools/stats"
tag "mosdepth"

test("homo_sapiens - cram - without intervals") {

when {
workflow {
"""
input[0] = channel.of([
[ id:'test', single_end:false ],
file(params.modules_testdata_base_path + 'genomics/homo_sapiens/illumina/cram/test.paired_end.sorted.cram', checkIfExists: true),
file(params.modules_testdata_base_path + 'genomics/homo_sapiens/illumina/cram/test.paired_end.sorted.cram.crai', checkIfExists: true)
])
input[1] = channel.of([
[id:'genome'],
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] = channel.empty()
"""
}
}

then {
assertAll(
{ assert workflow.success },
{ assert snapshot(
workflow.out.reports[0][0],
workflow.out.reports.collect { file(it[1]).name }.sort()
).match() }
)
}
}

test("homo_sapiens - cram - with intervals") {

when {
workflow {
"""
input[0] = channel.of([
[ id:'test', single_end:false ],
file(params.modules_testdata_base_path + 'genomics/homo_sapiens/illumina/cram/test.paired_end.sorted.cram', checkIfExists: true),
file(params.modules_testdata_base_path + 'genomics/homo_sapiens/illumina/cram/test.paired_end.sorted.cram.crai', checkIfExists: true)
])
input[1] = channel.of([
[id:'genome'],
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] = channel.of([
[id:'intervals'],
file(params.modules_testdata_base_path + 'genomics/homo_sapiens/genome/genome.bed', checkIfExists: true)
])
"""
}
}

then {
assertAll(
{ assert workflow.success },
{ assert snapshot(
workflow.out.reports[0][0],
workflow.out.reports.collect { file(it[1]).name }.sort()
).match() }
)
}
}

test("homo_sapiens - cram - stub") {

options "-stub-run"

when {
workflow {
"""
input[0] = channel.of([
[ id:'test', single_end:false ],
file(params.modules_testdata_base_path + 'genomics/homo_sapiens/illumina/cram/test.paired_end.sorted.cram', checkIfExists: true),
file(params.modules_testdata_base_path + 'genomics/homo_sapiens/illumina/cram/test.paired_end.sorted.cram.crai', checkIfExists: true)
])
input[1] = channel.of([
[id:'genome'],
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] = channel.empty()
"""
}
}

then {
assertAll(
{ assert workflow.success },
{ assert snapshot(
workflow.out.reports.collect { file(it[1]).name }
).match() }
)
}
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
{
"homo_sapiens - cram - stub": {
"content": [
[
"test.global.dist.txt",
"test.region.dist.txt",
"test.stats"
]
],
"timestamp": "2026-06-23T15:00:19.878645",
"meta": {
"nf-test": "0.9.5",
"nextflow": "25.10.4"
}
},
"homo_sapiens - cram - with intervals": {
"content": [
{
"id": "test",
"single_end": false
},
[
"test.mosdepth.global.dist.txt",
"test.mosdepth.region.dist.txt",
"test.stats"
]
],
"timestamp": "2026-06-23T14:53:34.149357",
"meta": {
"nf-test": "0.9.5",
"nextflow": "25.10.4"
}
},
"homo_sapiens - cram - without intervals": {
"content": [
{
"id": "test",
"single_end": false
},
[
"test.mosdepth.global.dist.txt",
"test.stats"
]
],
"timestamp": "2026-06-23T14:53:08.874632",
"meta": {
"nf-test": "0.9.5",
"nextflow": "25.10.4"
}
}
}