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
7 changes: 7 additions & 0 deletions modules/nf-core/nirvana/environment.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
# yaml-language-server: $schema=https://raw.githubusercontent.com/nf-core/modules/master/modules/environment-schema.json
channels:
- conda-forge
- bioconda
dependencies:
- bioconda::nirvana=3.18.1
43 changes: 43 additions & 0 deletions modules/nf-core/nirvana/main.nf
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
process NIRVANA {
tag "${meta.id}"
label 'process_medium'

conda "${moduleDir}/environment.yml"
container 'community.wave.seqera.io/library/nirvana:3.18.1--51c5bd56fef22808'

input:
tuple val(meta) , path(vcf)
tuple val(meta2), path(reference)
tuple val(meta3), path(cache), val(cache_prefix)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is the cache_prefix a path or a specific string within the path?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If the data looks like this:

❯ tree
.
├── Cache
│   └── SARS-CoV-2
│       ├── SARS-CoV-2.polyphen.ndb
│       ├── SARS-CoV-2.sift.ndb
│       └── SARS-CoV-2.transcripts.ndb
├── References
│   └── SARS-CoV-2.ASM985889v3.dat
└── SupplementaryAnnotation
    └── SARS-CoV-2
        ├── SARS-COV-2_AllFreq.nsa
        ├── SARS-COV-2_AllFreq.nsa.idx
        ├── SARS-COV-2_AllFreq.nsa.schema
        ├── SARS-CoV-2_ProteinDomains.nsi
        └── SARS-CoV-2_ProteinDomains.nsi.schema

then the cache is ./Cache/SARS-CoV-2/ and thecache_prefix is SARS-CoV-2 (here the one that is the prefix of the filename), so it overall is resolved to ./Cache/SARS-CoV-2/SARS-CoV-2.

I am not certain we can enforce people to match the prefix on the actual files with the folder name. I have not seen more Nirvana caches to check how this normally looks like. Alternatively, we could possible stage in the files and somehow extract the cache prefix to build the path, but it feels brittle

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Alternatively, we could possible stage in the files and somehow extract the cache prefix to build the path, but it feels brittle

I think we should do this at the workflow level, so I'm fine with this.

tuple val(meta4), path(supplementary_annotations)

output:
tuple val(meta), path("*.json.gz"), emit: json
tuple val(meta), path("*.json.gz.jsi"), emit: jsi
tuple val("${task.process}"), val('nirvana'), eval("Nirvana -v 2>&1 | awk '{print \$2}' | cut -d'-' -f1"), topic: versions, emit: versions_nirvana

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

script:
def args = task.ext.args ?: ''
def prefix = task.ext.prefix ?: "${meta.id}"
def cache_command = cache ? "-c ${cache}/${cache_prefix}" : ""
def sa_command = supplementary_annotations ? "--sd ${supplementary_annotations}" : ""
"""
Nirvana \\
-i ${vcf} \\
-r ${reference} \\
${cache_command} \\
${sa_command} \\
${args} \\
-o ${prefix}
"""

stub:
def prefix = task.ext.prefix ?: "${meta.id}"
"""
echo "" | gzip > ${prefix}.json.gz
touch ${prefix}.json.gz.jsi
"""
}
109 changes: 109 additions & 0 deletions modules/nf-core/nirvana/meta.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
# yaml-language-server: $schema=https://raw.githubusercontent.com/nf-core/modules/master/modules/meta-schema.json
name: "nirvana"
description: Clinical-grade annotation of genomic variants including SNVs, MNVs, insertions, deletions, indels, and SVs
keywords:
- annotation
- variant annotation
- vcf
- genomics
- clinical annotation
tools:
- "nirvana":
description: "Clinical-grade annotation of genomic variants (SNVs, MNVs, insertions,
deletions, indels, and SVs)"
homepage: "https://illumina.github.io/NirvanaDocumentation/"
documentation: "https://illumina.github.io/NirvanaDocumentation/"
tool_dev_url: "https://github.com/Illumina/Nirvana"
licence: ["GPL v3"]
identifier: biotools:nirvana

input:
- - meta:
type: map
description: |
Groovy Map containing sample information
e.g. `[ id:'sample1' ]`
- vcf:
type: file
description: Input VCF file to annotate
pattern: "*.{vcf,vcf.gz}"
ontologies:
- edam: "http://edamontology.org/format_3016" # VCF
- - meta2:
type: map
description: |
Groovy Map containing reference information
e.g. `[ id:'genome' ]`
- reference:
type: file
description: Compressed Nirvana reference sequence file
pattern: "*.dat"
- - meta3:
type: map
description: |
Groovy Map containing cache information
e.g. `[ id:'cache' ]`
- cache:
type: directory
description: Nirvana cache directory
- cache_prefix:
type: string
description: Prefix for cache files (e.g., 'SARS-CoV-2' for files like SARS-CoV-2.transcripts.ndb)
- - meta4:
type: map
description: |
Groovy Map containing supplementary annotation information
e.g. `[ id:'sa' ]`
- supplementary_annotations:
type: directory
description: Nirvana supplementary annotation directory (optional)

output:
json:
- - meta:
type: map
description: |
Groovy Map containing sample information
e.g. `[ id:'sample1' ]`
- "*.json.gz":
type: file
description: Gzip-compressed JSON file with variant annotations
pattern: "*.json.gz"
ontologies:
- edam: "http://edamontology.org/format_3464" # JSON
jsi:
- - meta:
type: map
description: |
Groovy Map containing sample information
e.g. `[ id:'sample1' ]`
- "*.json.gz.jsi":
type: file
description: JSON index file for the annotations
pattern: "*.json.gz.jsi"
versions_nirvana:
- - "${task.process}":
type: string
description: The name of the process
- "nirvana":
type: string
description: The name of the tool
- "Nirvana -v 2>&1 | awk '{print $2}' | cut -d'-' -f1":
type: eval
description: The expression to obtain the version of the tool

topics:
versions:
- - ${task.process}:
type: string
description: The name of the process
- nirvana:
type: string
description: The name of the tool
- "Nirvana -v 2>&1 | awk '{print $2}' | cut -d'-' -f1":
type: eval
description: The expression to obtain the version of the tool
authors:
- "@FriederikeHanssen"
maintainers:
- "@FriederikeHanssen"
108 changes: 108 additions & 0 deletions modules/nf-core/nirvana/tests/main.nf.test
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
nextflow_process {

name "Test Process NIRVANA"
script "../main.nf"
process "NIRVANA"

tag "modules"
tag "modules_nfcore"
tag "nirvana"
tag "untar"

setup {
run("UNTAR", alias: "UNTAR_CACHE") {
script "../../untar/main.nf"
process {
"""
input[0] = [
[ id:'Cache' ],
file(params.modules_testdata_base_path + 'genomics/sarscov2/genome/nirvana/Cache.tar', checkIfExists: true)
]
"""
}
}

run("UNTAR", alias: "UNTAR_SA") {
script "../../untar/main.nf"
process {
"""
input[0] = [
[ id:'SupplementaryAnnotation' ],
file(params.modules_testdata_base_path + 'genomics/sarscov2/genome/nirvana/SupplementaryAnnotation.tar', checkIfExists: true)
]
"""
}
}
}

test("sarscov2 - vcf") {

when {
process {
"""
input[0] = [
[ id:'test' ],
file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/vcf/test.vcf.gz', checkIfExists: true)
]
input[1] = [
[ id:'reference' ],
file(params.modules_testdata_base_path + 'genomics/sarscov2/genome/nirvana/SARS-CoV-2.ASM985889v3.dat', checkIfExists: true)
]
input[2] = UNTAR_CACHE.out.untar.map { meta, dir ->
[ meta, dir, 'SARS-CoV-2' ]
}
input[3] = UNTAR_SA.out.untar
"""
}
}

then {
assertAll(
{ assert process.success },
// Remove creationTime field from JSON and snapshot the rest
{ assert snapshot(
path(process.out.json[0][1]).linesGzip.collect {
it.replaceAll(/"creationTime":"[^"]*",?/, '')
}
).match("json_content") },
// Just check JSI exists
{ assert path(process.out.jsi[0][1]).exists() },
{ assert snapshot(process.out.versions_nirvana).match() }
)
}

}

test("sarscov2 - vcf - stub") {

options "-stub"

when {
process {
"""
input[0] = [
[ id:'test' ],
file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/vcf/test.vcf.gz', checkIfExists: true)
]
input[1] = [
[ id:'reference' ],
file(params.modules_testdata_base_path + 'genomics/sarscov2/genome/nirvana/SARS-CoV-2.ASM985889v3.dat', checkIfExists: true)
]
input[2] = UNTAR_CACHE.out.untar.map { meta, dir ->
[ meta, dir, 'SARS-CoV-2' ]
}
input[3] = UNTAR_SA.out.untar
"""
}
}

then {
assertAll(
{ assert process.success },
{ assert snapshot(process.out).match() }
)
}

}

}
97 changes: 97 additions & 0 deletions modules/nf-core/nirvana/tests/main.nf.test.snap
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
{
"json_content": {
"content": [
[
"{\"header\":{\"annotator\":\"Nirvana 3.18.1\",\"genomeAssembly\":\"SARSCoV2\",\"schemaVersion\":6,\"dataVersion\":\"0.27.66\",\"dataSources\":[{\"name\":\"RefSeq\",\"version\":\"NC_045512.2\",\"description\":\"Severe acute respiratory syndrome coronavirus 2 (SARS-CoV2)\",\"releaseDate\":\"2020-03-20\"},{\"name\":\"alleleFrequency\",\"version\":\"SARS-COV-2_AllFreq.tsv\",\"releaseDate\":\"2020-05-08\"},{\"name\":\"proteinDomains\",\"version\":\"SARS-CoV-2_ProteinDomains.tsv\",\"releaseDate\":\"2020-05-08\"},{\"name\":\"MitochondrialHeteroplasmy\",\"version\":\"20180410\",\"description\":\"Variant read frequency percentiles for the Mitochondrial reference\",\"releaseDate\":\"2020-05-21\"}],\"samples\":[\"test\"]},\"positions\":[",
"{\"chromosome\":\"MT192765.1\",\"position\":197,\"refAllele\":\"G\",\"altAlleles\":[\"T\"],\"quality\":7.3081,\"filters\":[\"LowQual\"],\"mappingQuality\":60,\"samples\":[{\"genotype\":\"1/1\"}],\"variants\":[{\"vid\":\"MT192765.1-197-G-T\",\"chromosome\":\"MT192765.1\",\"begin\":197,\"end\":197,\"refAllele\":\"G\",\"altAllele\":\"T\",\"variantType\":\"SNV\",\"hgvsg\":\"MT192765.1:g.197G>T\"}]},",
"{\"chromosome\":\"MT192765.1\",\"position\":4788,\"refAllele\":\"C\",\"altAlleles\":[\"T\"],\"quality\":7.3081,\"filters\":[\"LowQual\"],\"mappingQuality\":60,\"samples\":[{\"genotype\":\"1/1\"}],\"variants\":[{\"vid\":\"MT192765.1-4788-C-T\",\"chromosome\":\"MT192765.1\",\"begin\":4788,\"end\":4788,\"refAllele\":\"C\",\"altAllele\":\"T\",\"variantType\":\"SNV\",\"hgvsg\":\"MT192765.1:g.4788C>T\"}]},",
"{\"chromosome\":\"MT192765.1\",\"position\":8236,\"refAllele\":\"C\",\"altAlleles\":[\"A\"],\"quality\":7.3081,\"filters\":[\"LowQual\"],\"mappingQuality\":60,\"samples\":[{\"genotype\":\"1/1\"}],\"variants\":[{\"vid\":\"MT192765.1-8236-C-A\",\"chromosome\":\"MT192765.1\",\"begin\":8236,\"end\":8236,\"refAllele\":\"C\",\"altAllele\":\"A\",\"variantType\":\"SNV\",\"hgvsg\":\"MT192765.1:g.8236C>A\"}]},",
"{\"chromosome\":\"MT192765.1\",\"position\":10506,\"refAllele\":\"TTATGACTGTGTCTCTTTTTGTTACATGCACCATATG\",\"altAlleles\":[\"TTATG\"],\"quality\":18.4617,\"filters\":[\"LowQual\"],\"mappingQuality\":60,\"samples\":[{\"genotype\":\"0/1\"}],\"variants\":[{\"vid\":\"MT192765.1-10510-NACTGTGTCTCTTTTTGTTACATGCACCATATG-N\",\"chromosome\":\"MT192765.1\",\"begin\":10511,\"end\":10542,\"refAllele\":\"ACTGTGTCTCTTTTTGTTACATGCACCATATG\",\"altAllele\":\"-\",\"variantType\":\"deletion\",\"hgvsg\":\"MT192765.1:g.10511_10542del\"}]},",
"{\"chromosome\":\"MT192765.1\",\"position\":11037,\"refAllele\":\"T\",\"altAlleles\":[\"C\"],\"quality\":7.3081,\"filters\":[\"LowQual\"],\"mappingQuality\":60,\"samples\":[{\"genotype\":\"1/1\"}],\"variants\":[{\"vid\":\"MT192765.1-11037-T-C\",\"chromosome\":\"MT192765.1\",\"begin\":11037,\"end\":11037,\"refAllele\":\"T\",\"altAllele\":\"C\",\"variantType\":\"SNV\",\"hgvsg\":\"MT192765.1:g.11037T>C\"}]},",
"{\"chromosome\":\"MT192765.1\",\"position\":15009,\"refAllele\":\"G\",\"altAlleles\":[\"A\"],\"quality\":30.4183,\"filters\":[\"LowQual\"],\"mappingQuality\":60,\"samples\":[{\"genotype\":\"1/1\"}],\"variants\":[{\"vid\":\"MT192765.1-15009-G-A\",\"chromosome\":\"MT192765.1\",\"begin\":15009,\"end\":15009,\"refAllele\":\"G\",\"altAllele\":\"A\",\"variantType\":\"SNV\",\"hgvsg\":\"MT192765.1:g.15009G>A\"}]},",
"{\"chromosome\":\"MT192765.1\",\"position\":18807,\"refAllele\":\"T\",\"altAlleles\":[\"C\"],\"quality\":136,\"filters\":[\"LowQual\"],\"mappingQuality\":60,\"samples\":[{\"genotype\":\"1/1\"}],\"variants\":[{\"vid\":\"MT192765.1-18807-T-C\",\"chromosome\":\"MT192765.1\",\"begin\":18807,\"end\":18807,\"refAllele\":\"T\",\"altAllele\":\"C\",\"variantType\":\"SNV\",\"hgvsg\":\"MT192765.1:g.18807T>C\"}]},",
"{\"chromosome\":\"MT192765.1\",\"position\":23813,\"refAllele\":\"T\",\"altAlleles\":[\"C\"],\"quality\":4.3847,\"filters\":[\"LowQual\"],\"mappingQuality\":60,\"samples\":[{\"genotype\":\"1/1\"}],\"variants\":[{\"vid\":\"MT192765.1-23813-T-C\",\"chromosome\":\"MT192765.1\",\"begin\":23813,\"end\":23813,\"refAllele\":\"T\",\"altAllele\":\"C\",\"variantType\":\"SNV\",\"hgvsg\":\"MT192765.1:g.23813T>C\"}]},",
"{\"chromosome\":\"MT192765.1\",\"position\":24103,\"refAllele\":\"A\",\"altAlleles\":[\"G\"],\"quality\":30.4183,\"filters\":[\"LowQual\"],\"mappingQuality\":60,\"samples\":[{\"genotype\":\"1/1\"}],\"variants\":[{\"vid\":\"MT192765.1-24103-A-G\",\"chromosome\":\"MT192765.1\",\"begin\":24103,\"end\":24103,\"refAllele\":\"A\",\"altAllele\":\"G\",\"variantType\":\"SNV\",\"hgvsg\":\"MT192765.1:g.24103A>G\"}]}",
"]}"
]
],
"meta": {
"nf-test": "0.9.3",
"nextflow": "25.10.2"
},
"timestamp": "2026-01-12T09:27:01.830246"
},
"sarscov2 - vcf": {
"content": [
[
[
"NIRVANA",
"nirvana",
"Nirvana 3.18.1"
]
]
],
"meta": {
"nf-test": "0.9.3",
"nextflow": "25.10.2"
},
"timestamp": "2026-01-12T09:27:01.842455"
},
"sarscov2 - vcf - stub": {
"content": [
{
"0": [
[
{
"id": "test"
},
"test.json.gz:md5,68b329da9893e34099c7d8ad5cb9c940"
]
],
"1": [
[
{
"id": "test"
},
"test.json.gz.jsi:md5,d41d8cd98f00b204e9800998ecf8427e"
]
],
"2": [
[
"NIRVANA",
"nirvana",
"Nirvana 3.18.1"
]
],
"jsi": [
[
{
"id": "test"
},
"test.json.gz.jsi:md5,d41d8cd98f00b204e9800998ecf8427e"
]
],
"json": [
[
{
"id": "test"
},
"test.json.gz:md5,68b329da9893e34099c7d8ad5cb9c940"
]
],
"versions_nirvana": [
[
"NIRVANA",
"nirvana",
"Nirvana 3.18.1"
]
]
}
],
"meta": {
"nf-test": "0.9.3",
"nextflow": "25.10.2"
},
"timestamp": "2026-01-12T09:27:21.144398"
}
}
Loading