From 7321fa1ab5b748ac0d1a374128b7bee1b819f53f Mon Sep 17 00:00:00 2001 From: buehlere Date: Tue, 25 Aug 2026 11:18:21 -0400 Subject: [PATCH 1/9] modules for new gbcms --- .../msk/gbcmsrs/buildgtfcache/environment.yml | 7 ++ modules/msk/gbcmsrs/buildgtfcache/main.nf | 49 ++++++++++ modules/msk/gbcmsrs/buildgtfcache/meta.yml | 54 +++++++++++ .../gbcmsrs/buildgtfcache/tests/main.nf.test | 35 +++++++ .../buildgtfcache/tests/main.nf.test.snap | 29 ++++++ .../msk/gbcmsrs/buildgtfcache/tests/tags.yml | 2 + modules/msk/gbcmsrs/dna/environment.yml | 7 ++ modules/msk/gbcmsrs/dna/main.nf | 52 +++++++++++ modules/msk/gbcmsrs/dna/meta.yml | 77 ++++++++++++++++ modules/msk/gbcmsrs/dna/tests/main.nf.test | 41 +++++++++ .../msk/gbcmsrs/dna/tests/main.nf.test.snap | 35 +++++++ modules/msk/gbcmsrs/dna/tests/tags.yml | 2 + modules/msk/gbcmsrs/merge/environment.yml | 7 ++ modules/msk/gbcmsrs/merge/main.nf | 49 ++++++++++ modules/msk/gbcmsrs/merge/meta.yml | 66 ++++++++++++++ modules/msk/gbcmsrs/merge/tests/main.nf.test | 41 +++++++++ .../msk/gbcmsrs/merge/tests/main.nf.test.snap | 35 +++++++ modules/msk/gbcmsrs/merge/tests/tags.yml | 2 + modules/msk/gbcmsrs/normalize/environment.yml | 7 ++ modules/msk/gbcmsrs/normalize/main.nf | 52 +++++++++++ modules/msk/gbcmsrs/normalize/meta.yml | 67 ++++++++++++++ .../msk/gbcmsrs/normalize/tests/main.nf.test | 39 ++++++++ .../gbcmsrs/normalize/tests/main.nf.test.snap | 35 +++++++ modules/msk/gbcmsrs/normalize/tests/tags.yml | 2 + modules/msk/gbcmsrs/rna/environment.yml | 7 ++ modules/msk/gbcmsrs/rna/main.nf | 60 ++++++++++++ modules/msk/gbcmsrs/rna/meta.yml | 91 +++++++++++++++++++ modules/msk/gbcmsrs/rna/tests/main.nf.test | 43 +++++++++ .../msk/gbcmsrs/rna/tests/main.nf.test.snap | 35 +++++++ modules/msk/gbcmsrs/rna/tests/tags.yml | 2 + 30 files changed, 1030 insertions(+) create mode 100644 modules/msk/gbcmsrs/buildgtfcache/environment.yml create mode 100644 modules/msk/gbcmsrs/buildgtfcache/main.nf create mode 100644 modules/msk/gbcmsrs/buildgtfcache/meta.yml create mode 100644 modules/msk/gbcmsrs/buildgtfcache/tests/main.nf.test create mode 100644 modules/msk/gbcmsrs/buildgtfcache/tests/main.nf.test.snap create mode 100644 modules/msk/gbcmsrs/buildgtfcache/tests/tags.yml create mode 100644 modules/msk/gbcmsrs/dna/environment.yml create mode 100644 modules/msk/gbcmsrs/dna/main.nf create mode 100644 modules/msk/gbcmsrs/dna/meta.yml create mode 100644 modules/msk/gbcmsrs/dna/tests/main.nf.test create mode 100644 modules/msk/gbcmsrs/dna/tests/main.nf.test.snap create mode 100644 modules/msk/gbcmsrs/dna/tests/tags.yml create mode 100644 modules/msk/gbcmsrs/merge/environment.yml create mode 100644 modules/msk/gbcmsrs/merge/main.nf create mode 100644 modules/msk/gbcmsrs/merge/meta.yml create mode 100644 modules/msk/gbcmsrs/merge/tests/main.nf.test create mode 100644 modules/msk/gbcmsrs/merge/tests/main.nf.test.snap create mode 100644 modules/msk/gbcmsrs/merge/tests/tags.yml create mode 100644 modules/msk/gbcmsrs/normalize/environment.yml create mode 100644 modules/msk/gbcmsrs/normalize/main.nf create mode 100644 modules/msk/gbcmsrs/normalize/meta.yml create mode 100644 modules/msk/gbcmsrs/normalize/tests/main.nf.test create mode 100644 modules/msk/gbcmsrs/normalize/tests/main.nf.test.snap create mode 100644 modules/msk/gbcmsrs/normalize/tests/tags.yml create mode 100644 modules/msk/gbcmsrs/rna/environment.yml create mode 100644 modules/msk/gbcmsrs/rna/main.nf create mode 100644 modules/msk/gbcmsrs/rna/meta.yml create mode 100644 modules/msk/gbcmsrs/rna/tests/main.nf.test create mode 100644 modules/msk/gbcmsrs/rna/tests/main.nf.test.snap create mode 100644 modules/msk/gbcmsrs/rna/tests/tags.yml diff --git a/modules/msk/gbcmsrs/buildgtfcache/environment.yml b/modules/msk/gbcmsrs/buildgtfcache/environment.yml new file mode 100644 index 00000000..4c59b932 --- /dev/null +++ b/modules/msk/gbcmsrs/buildgtfcache/environment.yml @@ -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: + - "YOUR-TOOL=HERE" diff --git a/modules/msk/gbcmsrs/buildgtfcache/main.nf b/modules/msk/gbcmsrs/buildgtfcache/main.nf new file mode 100644 index 00000000..0e2730db --- /dev/null +++ b/modules/msk/gbcmsrs/buildgtfcache/main.nf @@ -0,0 +1,49 @@ +process GBCMSRS_BUILDGTFCACHE { + tag "${variants.name}" + label 'process_single' + container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? + 'ghcr.io/msk-access/gbcms:6.3.0': + 'ghcr.io/msk-access/gbcms:6.3.0' }" + containerOptions { workflow.containerEngine in ['docker', 'podman'] ? "--entrypoint ''" : '' } + + input: + path variants + path gtf + + output: + path "gbcms_gtf_cache", emit: cache_dir + path "versions.yml" , emit: versions + + when: + task.ext.when == null || task.ext.when + + script: + if (workflow.profile.tokenize(',').intersect(['conda', 'mamba']).size() >= 1) { + error "GBCMSRS_BUILDGTFCACHE module does not support Conda. Please use Docker / Singularity instead." + } + def args = task.ext.args ?: '' + """ + mkdir -p gbcms_gtf_cache + gbcms build-gtf-cache \\ + --gtf ${gtf} \\ + --variants ${variants} \\ + --gtf-cache-dir gbcms_gtf_cache \\ + $args + + cat <<-END_VERSIONS > versions.yml + "${task.process}": + gbcms: \$(gbcms --version | sed 's/^gbcms //') + END_VERSIONS + """ + + stub: + """ + mkdir -p gbcms_gtf_cache + touch gbcms_gtf_cache/gbcms-gtf-stub.idx + + cat <<-END_VERSIONS > versions.yml + "${task.process}": + gbcms: 6.3.0 + END_VERSIONS + """ +} diff --git a/modules/msk/gbcmsrs/buildgtfcache/meta.yml b/modules/msk/gbcmsrs/buildgtfcache/meta.yml new file mode 100644 index 00000000..e126d31e --- /dev/null +++ b/modules/msk/gbcmsrs/buildgtfcache/meta.yml @@ -0,0 +1,54 @@ +# yaml-language-server: $schema=https://raw.githubusercontent.com/nf-core/modules/master/modules/yaml-schema.json +name: "gbcmsrs_buildgtfcache" +description: + Pre-build the gbcms GTF index cache once for a cohort so that per-sample + `gbcms rna` runs skip re-parsing the GTF +keywords: + - cache + - gtf + - rna + - index +tools: + - "gbcms": + description: + "A high-performance, orientation-aware genotype counting system for + genomic variants (Rust rewrite of GetBaseCountsMultiSample)" + homepage: "https://github.com/msk-access/gbcms" + documentation: "https://msk-access.github.io/gbcms/" + tool_dev_url: "https://github.com/msk-access/gbcms" + licence: ["AGPL-3.0"] + identifier: "" + +input: + - variants: + type: file + description: + Variant file (VCF/MAF) for the cohort. Only its chromosome set is + used, and it must be the same variant file the per-sample `gbcms rna` runs use + so the cache key lines up. + pattern: "*.{vcf,maf}" + ontologies: [] + - gtf: + type: file + description: GTF annotation file (Ensembl/GENCODE) + pattern: "*.gtf" + ontologies: [] +output: + cache_dir: + - gbcms_gtf_cache: + type: directory + description: + Directory containing the serialized GTF index cache. Point every + per-sample `gbcms rna --gtf-cache-dir` at this same directory. + pattern: "gbcms_gtf_cache" + versions: + - versions.yml: + type: file + description: File containing software versions + pattern: "versions.yml" + ontologies: + - edam: http://edamontology.org/format_3750 # YAML +authors: + - "@shahr" +maintainers: + - "@shahr" diff --git a/modules/msk/gbcmsrs/buildgtfcache/tests/main.nf.test b/modules/msk/gbcmsrs/buildgtfcache/tests/main.nf.test new file mode 100644 index 00000000..825c1c5e --- /dev/null +++ b/modules/msk/gbcmsrs/buildgtfcache/tests/main.nf.test @@ -0,0 +1,35 @@ +// nf-core modules test gbcmsrs/buildgtfcache +nextflow_process { + + name "Test Process GBCMSRS_BUILDGTFCACHE" + script "../main.nf" + process "GBCMSRS_BUILDGTFCACHE" + + tag "modules" + tag "modules_msk" + tag "gbcmsrs" + tag "gbcmsrs/buildgtfcache" + + test("sarscov2 illumina - vcf gtf - stub") { + + options "-stub" + + when { + process { + """ + input[0] = file(params.test_data['sarscov2']['illumina']['test_vcf'], checkIfExists: true) + input[1] = file(params.test_data['sarscov2']['genome']['genome_gtf'], checkIfExists: true) + """ + } + } + + then { + assertAll( + { assert process.success }, + { assert snapshot(process.out).match() } + ) + } + + } + +} diff --git a/modules/msk/gbcmsrs/buildgtfcache/tests/main.nf.test.snap b/modules/msk/gbcmsrs/buildgtfcache/tests/main.nf.test.snap new file mode 100644 index 00000000..9a371e59 --- /dev/null +++ b/modules/msk/gbcmsrs/buildgtfcache/tests/main.nf.test.snap @@ -0,0 +1,29 @@ +{ + "sarscov2 illumina - vcf gtf - stub": { + "content": [ + { + "0": [ + [ + "gbcms-gtf-stub.idx:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "1": [ + "versions.yml:md5,caa12a2ea191d010798bbfbaae282c28" + ], + "cache_dir": [ + [ + "gbcms-gtf-stub.idx:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "versions": [ + "versions.yml:md5,caa12a2ea191d010798bbfbaae282c28" + ] + } + ], + "timestamp": "2026-08-25T11:12:12.859755", + "meta": { + "nf-test": "0.9.5", + "nextflow": "24.10.3" + } + } +} \ No newline at end of file diff --git a/modules/msk/gbcmsrs/buildgtfcache/tests/tags.yml b/modules/msk/gbcmsrs/buildgtfcache/tests/tags.yml new file mode 100644 index 00000000..1d894761 --- /dev/null +++ b/modules/msk/gbcmsrs/buildgtfcache/tests/tags.yml @@ -0,0 +1,2 @@ +gbcmsrs/buildgtfcache: + - "modules/msk/gbcmsrs/buildgtfcache/**" diff --git a/modules/msk/gbcmsrs/dna/environment.yml b/modules/msk/gbcmsrs/dna/environment.yml new file mode 100644 index 00000000..4c59b932 --- /dev/null +++ b/modules/msk/gbcmsrs/dna/environment.yml @@ -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: + - "YOUR-TOOL=HERE" diff --git a/modules/msk/gbcmsrs/dna/main.nf b/modules/msk/gbcmsrs/dna/main.nf new file mode 100644 index 00000000..18b283a0 --- /dev/null +++ b/modules/msk/gbcmsrs/dna/main.nf @@ -0,0 +1,52 @@ +process GBCMSRS_DNA { + tag "$meta.id" + label 'process_medium' + container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? + 'ghcr.io/msk-access/gbcms:6.3.0': + 'ghcr.io/msk-access/gbcms:6.3.0' }" + containerOptions { workflow.containerEngine in ['docker', 'podman'] ? "--entrypoint ''" : '' } + + input: + tuple val(meta), path(variants), path(bams), path(bais) + path fasta + path fasta_fai + + output: + tuple val(meta), path("gbcms_out/*.{vcf,maf}"), emit: variant_file + path "versions.yml" , emit: versions + + when: + task.ext.when == null || task.ext.when + + script: + if (workflow.profile.tokenize(',').intersect(['conda', 'mamba']).size() >= 1) { + error "GBCMSRS_DNA module does not support Conda. Please use Docker / Singularity instead." + } + def args = task.ext.args ?: '' + def bam_args = bams.collect { "--bam ${it}" }.join(' ') + """ + gbcms dna \\ + --variants ${variants} \\ + ${bam_args} \\ + --fasta ${fasta} \\ + --output-dir gbcms_out \\ + --threads ${task.cpus} \\ + $args + + cat <<-END_VERSIONS > versions.yml + "${task.process}": + gbcms: \$(gbcms --version | sed 's/^gbcms //') + END_VERSIONS + """ + + stub: + """ + mkdir -p gbcms_out + touch gbcms_out/${variants.baseName}.vcf + + cat <<-END_VERSIONS > versions.yml + "${task.process}": + gbcms: 6.3.0 + END_VERSIONS + """ +} diff --git a/modules/msk/gbcmsrs/dna/meta.yml b/modules/msk/gbcmsrs/dna/meta.yml new file mode 100644 index 00000000..326b9570 --- /dev/null +++ b/modules/msk/gbcmsrs/dna/meta.yml @@ -0,0 +1,77 @@ +# yaml-language-server: $schema=https://raw.githubusercontent.com/nf-core/modules/master/modules/yaml-schema.json +name: "gbcmsrs_dna" +description: + Count alleles in cfDNA/somatic DNA BAMs at known variant sites using + gbcms +keywords: + - basecount + - genotyping + - dna + - variants +tools: + - "gbcms": + description: + "A high-performance, orientation-aware genotype counting system for + genomic variants (Rust rewrite of GetBaseCountsMultiSample)" + homepage: "https://github.com/msk-access/gbcms" + documentation: "https://msk-access.github.io/gbcms/" + tool_dev_url: "https://github.com/msk-access/gbcms" + licence: ["AGPL-3.0"] + identifier: "" + +input: + - - meta: + type: map + description: | + Groovy Map containing sample information + e.g. `[ id:'test' ]` + - variants: + type: file + description: Input variant file in VCF or MAF format + pattern: "*.{vcf,maf}" + ontologies: [] + - bams: + type: file + description: One or more indexed BAM/CRAM files to count alleles in + pattern: "*.{bam,cram}" + ontologies: [] + - bais: + type: file + description: Index file(s) for the input BAM/CRAM file(s) + pattern: "*.{bai,crai}" + ontologies: [] + - fasta: + type: file + description: Reference genome FASTA file + pattern: "*.{fasta,fa}" + ontologies: [] + - fasta_fai: + type: file + description: Index of the reference genome FASTA file + pattern: "*.fai" + ontologies: [] +output: + variant_file: + - - meta: + type: map + description: | + Groovy Map containing sample information + e.g. `[ id:'test' ]` + - "gbcms_out/*.{vcf,maf}": + type: file + description: + Variant file annotated with allele counts, strand information, + and statistical annotations + pattern: "gbcms_out/*.{vcf,maf}" + versions: + - versions.yml: + type: file + description: File containing software versions + pattern: "versions.yml" + ontologies: + - edam: http://edamontology.org/format_3750 # YAML +authors: + - "@shahr" +maintainers: + - "@buehlere" + - "@shahr" diff --git a/modules/msk/gbcmsrs/dna/tests/main.nf.test b/modules/msk/gbcmsrs/dna/tests/main.nf.test new file mode 100644 index 00000000..5ff816d5 --- /dev/null +++ b/modules/msk/gbcmsrs/dna/tests/main.nf.test @@ -0,0 +1,41 @@ +// nf-core modules test gbcmsrs/dna +nextflow_process { + + name "Test Process GBCMSRS_DNA" + script "../main.nf" + process "GBCMSRS_DNA" + + tag "modules" + tag "modules_msk" + tag "gbcmsrs" + tag "gbcmsrs/dna" + + test("sarscov2 illumina - vcf - stub") { + + options "-stub" + + when { + process { + """ + input[0] = [ + [ id:'test' ], // meta map + file(params.test_data['sarscov2']['illumina']['test_vcf'], checkIfExists: true), + [ file(params.test_data['sarscov2']['illumina']['test_single_end_sorted_bam'], checkIfExists: true) ], + [ file(params.test_data['sarscov2']['illumina']['test_single_end_sorted_bam_bai'], checkIfExists: true) ] + ] + input[1] = file(params.test_data['sarscov2']['genome']['genome_fasta'], checkIfExists: true) + input[2] = file(params.test_data['sarscov2']['genome']['genome_fasta_fai'], checkIfExists: true) + """ + } + } + + then { + assertAll( + { assert process.success }, + { assert snapshot(process.out).match() } + ) + } + + } + +} diff --git a/modules/msk/gbcmsrs/dna/tests/main.nf.test.snap b/modules/msk/gbcmsrs/dna/tests/main.nf.test.snap new file mode 100644 index 00000000..2dbe7403 --- /dev/null +++ b/modules/msk/gbcmsrs/dna/tests/main.nf.test.snap @@ -0,0 +1,35 @@ +{ + "sarscov2 illumina - vcf - stub": { + "content": [ + { + "0": [ + [ + { + "id": "test" + }, + "test.vcf:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "1": [ + "versions.yml:md5,087878e68053220863c1b7c4fabe880f" + ], + "variant_file": [ + [ + { + "id": "test" + }, + "test.vcf:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "versions": [ + "versions.yml:md5,087878e68053220863c1b7c4fabe880f" + ] + } + ], + "timestamp": "2026-08-25T11:12:17.929089", + "meta": { + "nf-test": "0.9.5", + "nextflow": "24.10.3" + } + } +} \ No newline at end of file diff --git a/modules/msk/gbcmsrs/dna/tests/tags.yml b/modules/msk/gbcmsrs/dna/tests/tags.yml new file mode 100644 index 00000000..67dab5fb --- /dev/null +++ b/modules/msk/gbcmsrs/dna/tests/tags.yml @@ -0,0 +1,2 @@ +gbcmsrs/dna: + - "modules/msk/gbcmsrs/dna/**" diff --git a/modules/msk/gbcmsrs/merge/environment.yml b/modules/msk/gbcmsrs/merge/environment.yml new file mode 100644 index 00000000..4c59b932 --- /dev/null +++ b/modules/msk/gbcmsrs/merge/environment.yml @@ -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: + - "YOUR-TOOL=HERE" diff --git a/modules/msk/gbcmsrs/merge/main.nf b/modules/msk/gbcmsrs/merge/main.nf new file mode 100644 index 00000000..64cfd205 --- /dev/null +++ b/modules/msk/gbcmsrs/merge/main.nf @@ -0,0 +1,49 @@ +process GBCMSRS_MERGE { + tag "$meta.id" + label 'process_single' + container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? + 'ghcr.io/msk-access/gbcms:6.3.0': + 'ghcr.io/msk-access/gbcms:6.3.0' }" + + containerOptions { workflow.containerEngine in ['docker', 'podman'] ? "--entrypoint ''" : '' } + + input: + tuple val(meta), val(types), path(mafs) + + output: + tuple val(meta), path("*.merged.maf"), emit: merged + path "versions.yml" , emit: versions + + when: + task.ext.when == null || task.ext.when + + script: + if (workflow.profile.tokenize(',').intersect(['conda', 'mamba']).size() >= 1) { + error "GBCMSRS_MERGE module does not support Conda. Please use Docker / Singularity instead." + } + def args = task.ext.args ?: '' + def prefix = task.ext.prefix ?: "${meta.id}" + def input_args = [types, mafs].transpose().collect { type, maf -> "--input ${type}:${maf}" }.join(' ') + """ + gbcms merge \\ + ${input_args} \\ + --output ${prefix}.merged.maf \\ + $args + + cat <<-END_VERSIONS > versions.yml + "${task.process}": + gbcms: \$(gbcms --version | sed 's/^gbcms //') + END_VERSIONS + """ + + stub: + def prefix = task.ext.prefix ?: "${meta.id}" + """ + touch ${prefix}.merged.maf + + cat <<-END_VERSIONS > versions.yml + "${task.process}": + gbcms: 6.3.0 + END_VERSIONS + """ +} diff --git a/modules/msk/gbcmsrs/merge/meta.yml b/modules/msk/gbcmsrs/merge/meta.yml new file mode 100644 index 00000000..6e01e997 --- /dev/null +++ b/modules/msk/gbcmsrs/merge/meta.yml @@ -0,0 +1,66 @@ +# yaml-language-server: $schema=https://raw.githubusercontent.com/nf-core/modules/master/modules/yaml-schema.json +name: "gbcmsrs_merge" +description: + Merge per-BAM-type genotyped MAFs (e.g. duplex/simplex) produced by gbcms + into a single type-prefixed output +keywords: + - merge + - genotyping + - maf + - duplex +tools: + - "gbcms": + description: + "A high-performance, orientation-aware genotype counting system for + genomic variants (Rust rewrite of GetBaseCountsMultiSample)" + homepage: "https://github.com/msk-access/gbcms" + documentation: "https://msk-access.github.io/gbcms/" + tool_dev_url: "https://github.com/msk-access/gbcms" + licence: ["AGPL-3.0"] + identifier: "" + +input: + - - meta: + type: map + description: | + Groovy Map containing sample information + e.g. `[ id:'test' ]` + - types: + type: string + description: + List of BAM-type labels (e.g. `['duplex', 'simplex']`), parallel + to `mafs`, used to prefix the count columns of each input MAF. At least 2 + required. + - mafs: + type: file + description: + List of genotyped MAF files to merge, parallel to `types`. At least + 2 required. + pattern: "*.maf" + ontologies: [] +output: + merged: + - - meta: + type: map + description: | + Groovy Map containing sample information + e.g. `[ id:'test' ]` + - "*.merged.maf": + type: file + description: + Outer-joined MAF with type-prefixed count columns from all input + MAFs + pattern: "*.merged.maf" + ontologies: [] + versions: + - versions.yml: + type: file + description: File containing software versions + pattern: "versions.yml" + ontologies: + - edam: http://edamontology.org/format_3750 # YAML +authors: + - "@shahr" +maintainers: + - "@buehlere" + - "@shahr" diff --git a/modules/msk/gbcmsrs/merge/tests/main.nf.test b/modules/msk/gbcmsrs/merge/tests/main.nf.test new file mode 100644 index 00000000..9b08d934 --- /dev/null +++ b/modules/msk/gbcmsrs/merge/tests/main.nf.test @@ -0,0 +1,41 @@ +// nf-core modules test gbcmsrs/merge +nextflow_process { + + name "Test Process GBCMSRS_MERGE" + script "../main.nf" + process "GBCMSRS_MERGE" + + tag "modules" + tag "modules_msk" + tag "gbcmsrs" + tag "gbcmsrs/merge" + + test("duplex simplex maf - stub") { + + options "-stub" + + when { + process { + """ + input[0] = [ + [ id:'test' ], // meta map + [ 'duplex', 'simplex' ], + [ + file(params.test_data_mskcc['genome_nexus']['test_maf'], checkIfExists: true), + file(params.test_data_mskcc['genome_nexus']['sample2_sample1_annotated_maf'], checkIfExists: true) + ] + ] + """ + } + } + + then { + assertAll( + { assert process.success }, + { assert snapshot(process.out).match() } + ) + } + + } + +} diff --git a/modules/msk/gbcmsrs/merge/tests/main.nf.test.snap b/modules/msk/gbcmsrs/merge/tests/main.nf.test.snap new file mode 100644 index 00000000..16e735c8 --- /dev/null +++ b/modules/msk/gbcmsrs/merge/tests/main.nf.test.snap @@ -0,0 +1,35 @@ +{ + "duplex simplex maf - stub": { + "content": [ + { + "0": [ + [ + { + "id": "test" + }, + "test.merged.maf:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "1": [ + "versions.yml:md5,d07a4f42f7d7d56f11bf4ba50315775e" + ], + "merged": [ + [ + { + "id": "test" + }, + "test.merged.maf:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "versions": [ + "versions.yml:md5,d07a4f42f7d7d56f11bf4ba50315775e" + ] + } + ], + "timestamp": "2026-08-25T11:12:22.907599", + "meta": { + "nf-test": "0.9.5", + "nextflow": "24.10.3" + } + } +} \ No newline at end of file diff --git a/modules/msk/gbcmsrs/merge/tests/tags.yml b/modules/msk/gbcmsrs/merge/tests/tags.yml new file mode 100644 index 00000000..431bbc82 --- /dev/null +++ b/modules/msk/gbcmsrs/merge/tests/tags.yml @@ -0,0 +1,2 @@ +gbcmsrs/merge: + - "modules/msk/gbcmsrs/merge/**" diff --git a/modules/msk/gbcmsrs/normalize/environment.yml b/modules/msk/gbcmsrs/normalize/environment.yml new file mode 100644 index 00000000..4c59b932 --- /dev/null +++ b/modules/msk/gbcmsrs/normalize/environment.yml @@ -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: + - "YOUR-TOOL=HERE" diff --git a/modules/msk/gbcmsrs/normalize/main.nf b/modules/msk/gbcmsrs/normalize/main.nf new file mode 100644 index 00000000..aa73be15 --- /dev/null +++ b/modules/msk/gbcmsrs/normalize/main.nf @@ -0,0 +1,52 @@ +process GBCMSRS_NORMALIZE { + tag "$meta.id" + label 'process_single' + container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? + 'ghcr.io/msk-access/gbcms:6.3.0': + 'ghcr.io/msk-access/gbcms:6.3.0' }" + + containerOptions { workflow.containerEngine in ['docker', 'podman'] ? "--entrypoint ''" : '' } + + input: + tuple val(meta), path(variants) + path fasta + path fasta_fai + + output: + tuple val(meta), path("*.normalized.tsv"), emit: normalized + path "versions.yml" , emit: versions + + when: + task.ext.when == null || task.ext.when + + script: + if (workflow.profile.tokenize(',').intersect(['conda', 'mamba']).size() >= 1) { + error "GBCMSRS_NORMALIZE module does not support Conda. Please use Docker / Singularity instead." + } + def args = task.ext.args ?: '' + def prefix = task.ext.prefix ?: "${meta.id}" + """ + gbcms normalize \\ + --variants ${variants} \\ + --fasta ${fasta} \\ + --output ${prefix}.normalized.tsv \\ + --threads ${task.cpus} \\ + $args + + cat <<-END_VERSIONS > versions.yml + "${task.process}": + gbcms: \$(gbcms --version | sed 's/^gbcms //') + END_VERSIONS + """ + + stub: + def prefix = task.ext.prefix ?: "${meta.id}" + """ + touch ${prefix}.normalized.tsv + + cat <<-END_VERSIONS > versions.yml + "${task.process}": + gbcms: 6.3.0 + END_VERSIONS + """ +} diff --git a/modules/msk/gbcmsrs/normalize/meta.yml b/modules/msk/gbcmsrs/normalize/meta.yml new file mode 100644 index 00000000..c13a0c22 --- /dev/null +++ b/modules/msk/gbcmsrs/normalize/meta.yml @@ -0,0 +1,67 @@ +# yaml-language-server: $schema=https://raw.githubusercontent.com/nf-core/modules/master/modules/yaml-schema.json +name: "gbcmsrs_normalize" +description: + Normalize variants (left-align and validate REF against the reference + genome) without counting, using gbcms +keywords: + - normalize + - variants + - vcf + - maf +tools: + - "gbcms": + description: + "A high-performance, orientation-aware genotype counting system for + genomic variants (Rust rewrite of GetBaseCountsMultiSample)" + homepage: "https://github.com/msk-access/gbcms" + documentation: "https://msk-access.github.io/gbcms/" + tool_dev_url: "https://github.com/msk-access/gbcms" + licence: ["AGPL-3.0"] + identifier: "" + +input: + - - meta: + type: map + description: | + Groovy Map containing sample information + e.g. `[ id:'test' ]` + - variants: + type: file + description: Input variant file in VCF or MAF format + pattern: "*.{vcf,maf}" + ontologies: [] + - fasta: + type: file + description: Reference genome FASTA file + pattern: "*.{fasta,fa}" + ontologies: [] + - fasta_fai: + type: file + description: Index of the reference genome FASTA file + pattern: "*.fai" + ontologies: [] +output: + normalized: + - - meta: + type: map + description: | + Groovy Map containing sample information + e.g. `[ id:'test' ]` + - "*.normalized.tsv": + type: file + description: TSV file with original and left-aligned/normalized variant coordinates + pattern: "*.normalized.tsv" + ontologies: + - edam: http://edamontology.org/format_3475 # TSV + versions: + - versions.yml: + type: file + description: File containing software versions + pattern: "versions.yml" + ontologies: + - edam: http://edamontology.org/format_3750 # YAML +authors: + - "@shahr" +maintainers: + - "@buehlere" + - "@shahr" diff --git a/modules/msk/gbcmsrs/normalize/tests/main.nf.test b/modules/msk/gbcmsrs/normalize/tests/main.nf.test new file mode 100644 index 00000000..7e0cedaf --- /dev/null +++ b/modules/msk/gbcmsrs/normalize/tests/main.nf.test @@ -0,0 +1,39 @@ +// nf-core modules test gbcmsrs/normalize +nextflow_process { + + name "Test Process GBCMSRS_NORMALIZE" + script "../main.nf" + process "GBCMSRS_NORMALIZE" + + tag "modules" + tag "modules_msk" + tag "gbcmsrs" + tag "gbcmsrs/normalize" + + test("sarscov2 illumina - vcf - stub") { + + options "-stub" + + when { + process { + """ + input[0] = [ + [ id:'test' ], // meta map + file(params.test_data['sarscov2']['illumina']['test_vcf'], checkIfExists: true) + ] + input[1] = file(params.test_data['sarscov2']['genome']['genome_fasta'], checkIfExists: true) + input[2] = file(params.test_data['sarscov2']['genome']['genome_fasta_fai'], checkIfExists: true) + """ + } + } + + then { + assertAll( + { assert process.success }, + { assert snapshot(process.out).match() } + ) + } + + } + +} diff --git a/modules/msk/gbcmsrs/normalize/tests/main.nf.test.snap b/modules/msk/gbcmsrs/normalize/tests/main.nf.test.snap new file mode 100644 index 00000000..a74ef373 --- /dev/null +++ b/modules/msk/gbcmsrs/normalize/tests/main.nf.test.snap @@ -0,0 +1,35 @@ +{ + "sarscov2 illumina - vcf - stub": { + "content": [ + { + "0": [ + [ + { + "id": "test" + }, + "test.normalized.tsv:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "1": [ + "versions.yml:md5,2e0066bf092cdd9574f383d862db42c9" + ], + "normalized": [ + [ + { + "id": "test" + }, + "test.normalized.tsv:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "versions": [ + "versions.yml:md5,2e0066bf092cdd9574f383d862db42c9" + ] + } + ], + "timestamp": "2026-08-25T11:12:27.900622", + "meta": { + "nf-test": "0.9.5", + "nextflow": "24.10.3" + } + } +} \ No newline at end of file diff --git a/modules/msk/gbcmsrs/normalize/tests/tags.yml b/modules/msk/gbcmsrs/normalize/tests/tags.yml new file mode 100644 index 00000000..fe68d270 --- /dev/null +++ b/modules/msk/gbcmsrs/normalize/tests/tags.yml @@ -0,0 +1,2 @@ +gbcmsrs/normalize: + - "modules/msk/gbcmsrs/normalize/**" diff --git a/modules/msk/gbcmsrs/rna/environment.yml b/modules/msk/gbcmsrs/rna/environment.yml new file mode 100644 index 00000000..4c59b932 --- /dev/null +++ b/modules/msk/gbcmsrs/rna/environment.yml @@ -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: + - "YOUR-TOOL=HERE" diff --git a/modules/msk/gbcmsrs/rna/main.nf b/modules/msk/gbcmsrs/rna/main.nf new file mode 100644 index 00000000..a4806373 --- /dev/null +++ b/modules/msk/gbcmsrs/rna/main.nf @@ -0,0 +1,60 @@ +process GBCMSRS_RNA { + tag "$meta.id" + label 'process_medium' + container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? + 'ghcr.io/msk-access/gbcms:6.3.0': + 'ghcr.io/msk-access/gbcms:6.3.0' }" + + containerOptions { workflow.containerEngine in ['docker', 'podman'] ? "--entrypoint ''" : '' } + + input: + tuple val(meta), path(variants), path(bams), path(bais) + path fasta + path fasta_fai + path gtf + path rna_editing_db + + output: + tuple val(meta), path("gbcms_out/*.{vcf,maf}"), emit: variant_file + path "versions.yml" , emit: versions + + when: + task.ext.when == null || task.ext.when + + script: + if (workflow.profile.tokenize(',').intersect(['conda', 'mamba']).size() >= 1) { + error "GBCMSRS_RNA module does not support Conda. Please use Docker / Singularity instead." + } + def args = task.ext.args ?: '' + def bam_args = bams.collect { "--bam ${it}" }.join(' ') + def gtf_arg = gtf ? "--gtf ${gtf}" : '' + def editing_db_arg = rna_editing_db ? "--rna-editing-db ${rna_editing_db}" : '' + + """ + gbcms rna \\ + --variants ${variants} \\ + ${bam_args} \\ + --fasta ${fasta} \\ + --output-dir gbcms_out \\ + --threads ${task.cpus} \\ + ${gtf_arg} \\ + ${editing_db_arg} \\ + $args + + cat <<-END_VERSIONS > versions.yml + "${task.process}": + gbcms: \$(gbcms --version | sed 's/^gbcms //') + END_VERSIONS + """ + + stub: + """ + mkdir -p gbcms_out + touch gbcms_out/${variants.baseName}.vcf + + cat <<-END_VERSIONS > versions.yml + "${task.process}": + gbcms: 6.3.0 + END_VERSIONS + """ +} diff --git a/modules/msk/gbcmsrs/rna/meta.yml b/modules/msk/gbcmsrs/rna/meta.yml new file mode 100644 index 00000000..2d68bf71 --- /dev/null +++ b/modules/msk/gbcmsrs/rna/meta.yml @@ -0,0 +1,91 @@ +# yaml-language-server: $schema=https://raw.githubusercontent.com/nf-core/modules/master/modules/yaml-schema.json +name: "gbcmsrs_rna" +description: + Count alleles in RNA-seq BAMs at known variant sites with transcriptome-aware + filtering using gbcms +keywords: + - basecount + - genotyping + - rna + - variants +tools: + - "gbcms": + description: + "A high-performance, orientation-aware genotype counting system for + genomic variants (Rust rewrite of GetBaseCountsMultiSample)" + homepage: "https://github.com/msk-access/gbcms" + documentation: "https://msk-access.github.io/gbcms/" + tool_dev_url: "https://github.com/msk-access/gbcms" + licence: ["AGPL-3.0"] + identifier: "" + +input: + - - meta: + type: map + description: | + Groovy Map containing sample information + e.g. `[ id:'test' ]` + - variants: + type: file + description: Input variant file in VCF or MAF format + pattern: "*.{vcf,maf}" + ontologies: [] + - bams: + type: file + description: One or more indexed RNA-seq BAM/CRAM files to count alleles in + pattern: "*.{bam,cram}" + ontologies: [] + - bais: + type: file + description: Index file(s) for the input BAM/CRAM file(s) + pattern: "*.{bai,crai}" + ontologies: [] + - fasta: + type: file + description: Reference genome FASTA file + pattern: "*.{fasta,fa}" + ontologies: [] + - fasta_fai: + type: file + description: Index of the reference genome FASTA file + pattern: "*.fai" + ontologies: [] + - gtf: + type: file + description: + Optional GTF annotation file (Ensembl/GENCODE) enabling exon boundary + and splice junction awareness. Pass an empty list (`[]`) to omit. + pattern: "*.gtf" + ontologies: [] + - rna_editing_db: + type: file + description: + Optional REDIportal TABLE1 file of known A-to-I RNA editing sites. + Pass an empty list (`[]`) to omit. + pattern: "*.{txt,txt.gz}" + ontologies: [] +output: + variant_file: + - - meta: + type: map + description: | + Groovy Map containing sample information + e.g. `[ id:'test' ]` + - "gbcms_out/*.{vcf,maf}": + type: file + description: + Variant file annotated with transcript-aware allele counts and + RNA editing flags + pattern: "gbcms_out/*.{vcf,maf}" + versions: + - versions.yml: + type: file + description: File containing software versions + pattern: "versions.yml" + ontologies: + - edam: http://edamontology.org/format_3750 # YAML +authors: + - "@shahr" +maintainers: + - "@buehlere" + - "@shahr" diff --git a/modules/msk/gbcmsrs/rna/tests/main.nf.test b/modules/msk/gbcmsrs/rna/tests/main.nf.test new file mode 100644 index 00000000..aee8f5a0 --- /dev/null +++ b/modules/msk/gbcmsrs/rna/tests/main.nf.test @@ -0,0 +1,43 @@ +// nf-core modules test gbcmsrs/rna +nextflow_process { + + name "Test Process GBCMSRS_RNA" + script "../main.nf" + process "GBCMSRS_RNA" + + tag "modules" + tag "modules_msk" + tag "gbcmsrs" + tag "gbcmsrs/rna" + + test("sarscov2 illumina - vcf - stub") { + + options "-stub" + + when { + process { + """ + input[0] = [ + [ id:'test' ], // meta map + file(params.test_data['sarscov2']['illumina']['test_vcf'], checkIfExists: true), + [ file(params.test_data['sarscov2']['illumina']['test_single_end_sorted_bam'], checkIfExists: true) ], + [ file(params.test_data['sarscov2']['illumina']['test_single_end_sorted_bam_bai'], checkIfExists: true) ] + ] + input[1] = file(params.test_data['sarscov2']['genome']['genome_fasta'], checkIfExists: true) + input[2] = file(params.test_data['sarscov2']['genome']['genome_fasta_fai'], checkIfExists: true) + input[3] = file(params.test_data['sarscov2']['genome']['genome_gtf'], checkIfExists: true) + input[4] = [] + """ + } + } + + then { + assertAll( + { assert process.success }, + { assert snapshot(process.out).match() } + ) + } + + } + +} diff --git a/modules/msk/gbcmsrs/rna/tests/main.nf.test.snap b/modules/msk/gbcmsrs/rna/tests/main.nf.test.snap new file mode 100644 index 00000000..c2920238 --- /dev/null +++ b/modules/msk/gbcmsrs/rna/tests/main.nf.test.snap @@ -0,0 +1,35 @@ +{ + "sarscov2 illumina - vcf - stub": { + "content": [ + { + "0": [ + [ + { + "id": "test" + }, + "test.vcf:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "1": [ + "versions.yml:md5,5a18d25acc7da7ba2920edc6d2755e1a" + ], + "variant_file": [ + [ + { + "id": "test" + }, + "test.vcf:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "versions": [ + "versions.yml:md5,5a18d25acc7da7ba2920edc6d2755e1a" + ] + } + ], + "timestamp": "2026-08-25T11:12:32.792419", + "meta": { + "nf-test": "0.9.5", + "nextflow": "24.10.3" + } + } +} \ No newline at end of file diff --git a/modules/msk/gbcmsrs/rna/tests/tags.yml b/modules/msk/gbcmsrs/rna/tests/tags.yml new file mode 100644 index 00000000..c0b5f0c9 --- /dev/null +++ b/modules/msk/gbcmsrs/rna/tests/tags.yml @@ -0,0 +1,2 @@ +gbcmsrs/rna: + - "modules/msk/gbcmsrs/rna/**" From 9109160dbbf49c82a0bc20ca6053a18a8d995fd8 Mon Sep 17 00:00:00 2001 From: buehlere Date: Wed, 26 Aug 2026 13:32:11 -0400 Subject: [PATCH 2/9] PR response real test data, fix sample names, add cache input for rna, other cleanup --- .github/skip_nf_test.json | 5 +++ modules/msk/gbcmsrs/buildgtfcache/main.nf | 2 +- .../gbcmsrs/buildgtfcache/tests/main.nf.test | 4 +-- .../buildgtfcache/tests/main.nf.test.snap | 29 --------------- modules/msk/gbcmsrs/dna/main.nf | 21 ++++++++--- modules/msk/gbcmsrs/dna/meta.yml | 7 ++++ modules/msk/gbcmsrs/dna/tests/main.nf.test | 5 ++- .../msk/gbcmsrs/dna/tests/main.nf.test.snap | 35 ------------------- modules/msk/gbcmsrs/merge/main.nf | 2 +- modules/msk/gbcmsrs/merge/tests/main.nf.test | 8 ++--- .../msk/gbcmsrs/merge/tests/main.nf.test.snap | 35 ------------------- modules/msk/gbcmsrs/normalize/main.nf | 2 +- .../msk/gbcmsrs/normalize/tests/main.nf.test | 4 +-- .../gbcmsrs/normalize/tests/main.nf.test.snap | 35 ------------------- modules/msk/gbcmsrs/rna/main.nf | 28 +++++++++++---- modules/msk/gbcmsrs/rna/meta.yml | 15 ++++++++ modules/msk/gbcmsrs/rna/tests/main.nf.test | 6 ++-- .../msk/gbcmsrs/rna/tests/main.nf.test.snap | 35 ------------------- tests/config/test_data.config | 4 +++ 19 files changed, 83 insertions(+), 199 deletions(-) delete mode 100644 modules/msk/gbcmsrs/buildgtfcache/tests/main.nf.test.snap delete mode 100644 modules/msk/gbcmsrs/dna/tests/main.nf.test.snap delete mode 100644 modules/msk/gbcmsrs/merge/tests/main.nf.test.snap delete mode 100644 modules/msk/gbcmsrs/normalize/tests/main.nf.test.snap delete mode 100644 modules/msk/gbcmsrs/rna/tests/main.nf.test.snap diff --git a/.github/skip_nf_test.json b/.github/skip_nf_test.json index 633dc3e7..4fc5cdae 100644 --- a/.github/skip_nf_test.json +++ b/.github/skip_nf_test.json @@ -5,6 +5,11 @@ "modules/msk/facets", "modules/msk/fgbio/collectduplexseqmetrics", "modules/msk/gbcms", + "modules/msk/gbcmsrs/dna", + "modules/msk/gbcmsrs/rna", + "modules/msk/gbcmsrs/normalize", + "modules/msk/gbcmsrs/merge", + "modules/msk/gbcmsrs/buildgtfcache", "modules/msk/neoantigenediting/computefitness", "modules/msk/neoantigenediting/aligntoiedb", "modules/msk/neoantigenutils/neoantigeninput", diff --git a/modules/msk/gbcmsrs/buildgtfcache/main.nf b/modules/msk/gbcmsrs/buildgtfcache/main.nf index 0e2730db..7a3437c1 100644 --- a/modules/msk/gbcmsrs/buildgtfcache/main.nf +++ b/modules/msk/gbcmsrs/buildgtfcache/main.nf @@ -43,7 +43,7 @@ process GBCMSRS_BUILDGTFCACHE { cat <<-END_VERSIONS > versions.yml "${task.process}": - gbcms: 6.3.0 + gbcms: \$(echo "${task.container}" | sed 's/.*://') END_VERSIONS """ } diff --git a/modules/msk/gbcmsrs/buildgtfcache/tests/main.nf.test b/modules/msk/gbcmsrs/buildgtfcache/tests/main.nf.test index 825c1c5e..5110cdfc 100644 --- a/modules/msk/gbcmsrs/buildgtfcache/tests/main.nf.test +++ b/modules/msk/gbcmsrs/buildgtfcache/tests/main.nf.test @@ -10,9 +10,7 @@ nextflow_process { tag "gbcmsrs" tag "gbcmsrs/buildgtfcache" - test("sarscov2 illumina - vcf gtf - stub") { - - options "-stub" + test("sarscov2 illumina - vcf gtf") { when { process { diff --git a/modules/msk/gbcmsrs/buildgtfcache/tests/main.nf.test.snap b/modules/msk/gbcmsrs/buildgtfcache/tests/main.nf.test.snap deleted file mode 100644 index 9a371e59..00000000 --- a/modules/msk/gbcmsrs/buildgtfcache/tests/main.nf.test.snap +++ /dev/null @@ -1,29 +0,0 @@ -{ - "sarscov2 illumina - vcf gtf - stub": { - "content": [ - { - "0": [ - [ - "gbcms-gtf-stub.idx:md5,d41d8cd98f00b204e9800998ecf8427e" - ] - ], - "1": [ - "versions.yml:md5,caa12a2ea191d010798bbfbaae282c28" - ], - "cache_dir": [ - [ - "gbcms-gtf-stub.idx:md5,d41d8cd98f00b204e9800998ecf8427e" - ] - ], - "versions": [ - "versions.yml:md5,caa12a2ea191d010798bbfbaae282c28" - ] - } - ], - "timestamp": "2026-08-25T11:12:12.859755", - "meta": { - "nf-test": "0.9.5", - "nextflow": "24.10.3" - } - } -} \ No newline at end of file diff --git a/modules/msk/gbcmsrs/dna/main.nf b/modules/msk/gbcmsrs/dna/main.nf index 18b283a0..da8ef5a2 100644 --- a/modules/msk/gbcmsrs/dna/main.nf +++ b/modules/msk/gbcmsrs/dna/main.nf @@ -4,10 +4,13 @@ process GBCMSRS_DNA { container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? 'ghcr.io/msk-access/gbcms:6.3.0': 'ghcr.io/msk-access/gbcms:6.3.0' }" + // The gbcms image sets ENTRYPOINT ["gbcms"], which breaks Nextflow's docker/podman + // invocation of .command.run unless the entrypoint is cleared here. Singularity + // ignores the image entrypoint already, so this is scoped to docker/podman only. containerOptions { workflow.containerEngine in ['docker', 'podman'] ? "--entrypoint ''" : '' } input: - tuple val(meta), path(variants), path(bams), path(bais) + tuple val(meta), path(variants), val(sample_names), path(bams), path(bais) path fasta path fasta_fai @@ -22,8 +25,17 @@ process GBCMSRS_DNA { if (workflow.profile.tokenize(',').intersect(['conda', 'mamba']).size() >= 1) { error "GBCMSRS_DNA module does not support Conda. Please use Docker / Singularity instead." } + // gbcms's read filters (--filter-duplicates/-secondary/-supplementary/-qc-failed) + // default to ON. A pipeline mapping its own boolean params into ext.args must emit + // the explicit --no-filter-x form when off; omitting the flag silently keeps it on. + // On Nextflow >=26.04 (strict parser), CLI param overrides arrive as Strings, so + // `params.x ? 'a' : 'b'` sees "false" as truthy — compare with `.toString() == 'true'`. def args = task.ext.args ?: '' - def bam_args = bams.collect { "--bam ${it}" }.join(' ') + // Bare `--bam path` labels the sample using the staged file's stem, which is not + // meaningful for real BAM naming conventions. Pairing each bam with an explicit + // name keeps the output filename and Tumor_Sample_Barcode/VCF sample column + // predictable and equal to what the caller intends. + def bam_args = [sample_names, bams].transpose().collect { name, bam -> "--bam ${name}:${bam}" }.join(' ') """ gbcms dna \\ --variants ${variants} \\ @@ -40,13 +52,14 @@ process GBCMSRS_DNA { """ stub: + def sample_name = sample_names[0] """ mkdir -p gbcms_out - touch gbcms_out/${variants.baseName}.vcf + touch gbcms_out/${sample_name}.vcf cat <<-END_VERSIONS > versions.yml "${task.process}": - gbcms: 6.3.0 + gbcms: \$(echo "${task.container}" | sed 's/.*://') END_VERSIONS """ } diff --git a/modules/msk/gbcmsrs/dna/meta.yml b/modules/msk/gbcmsrs/dna/meta.yml index 326b9570..2e0dd06b 100644 --- a/modules/msk/gbcmsrs/dna/meta.yml +++ b/modules/msk/gbcmsrs/dna/meta.yml @@ -30,6 +30,13 @@ input: description: Input variant file in VCF or MAF format pattern: "*.{vcf,maf}" ontologies: [] + - sample_names: + type: string + description: + List of sample names, parallel to `bams`, used to label each BAM + via `--bam :`. Without an explicit name, gbcms falls + back to the staged file's stem, which is usually not the desired + sample id. - bams: type: file description: One or more indexed BAM/CRAM files to count alleles in diff --git a/modules/msk/gbcmsrs/dna/tests/main.nf.test b/modules/msk/gbcmsrs/dna/tests/main.nf.test index 5ff816d5..97b481df 100644 --- a/modules/msk/gbcmsrs/dna/tests/main.nf.test +++ b/modules/msk/gbcmsrs/dna/tests/main.nf.test @@ -10,9 +10,7 @@ nextflow_process { tag "gbcmsrs" tag "gbcmsrs/dna" - test("sarscov2 illumina - vcf - stub") { - - options "-stub" + test("sarscov2 illumina - vcf") { when { process { @@ -20,6 +18,7 @@ nextflow_process { input[0] = [ [ id:'test' ], // meta map file(params.test_data['sarscov2']['illumina']['test_vcf'], checkIfExists: true), + [ 'test' ], [ file(params.test_data['sarscov2']['illumina']['test_single_end_sorted_bam'], checkIfExists: true) ], [ file(params.test_data['sarscov2']['illumina']['test_single_end_sorted_bam_bai'], checkIfExists: true) ] ] diff --git a/modules/msk/gbcmsrs/dna/tests/main.nf.test.snap b/modules/msk/gbcmsrs/dna/tests/main.nf.test.snap deleted file mode 100644 index 2dbe7403..00000000 --- a/modules/msk/gbcmsrs/dna/tests/main.nf.test.snap +++ /dev/null @@ -1,35 +0,0 @@ -{ - "sarscov2 illumina - vcf - stub": { - "content": [ - { - "0": [ - [ - { - "id": "test" - }, - "test.vcf:md5,d41d8cd98f00b204e9800998ecf8427e" - ] - ], - "1": [ - "versions.yml:md5,087878e68053220863c1b7c4fabe880f" - ], - "variant_file": [ - [ - { - "id": "test" - }, - "test.vcf:md5,d41d8cd98f00b204e9800998ecf8427e" - ] - ], - "versions": [ - "versions.yml:md5,087878e68053220863c1b7c4fabe880f" - ] - } - ], - "timestamp": "2026-08-25T11:12:17.929089", - "meta": { - "nf-test": "0.9.5", - "nextflow": "24.10.3" - } - } -} \ No newline at end of file diff --git a/modules/msk/gbcmsrs/merge/main.nf b/modules/msk/gbcmsrs/merge/main.nf index 64cfd205..b4b99177 100644 --- a/modules/msk/gbcmsrs/merge/main.nf +++ b/modules/msk/gbcmsrs/merge/main.nf @@ -43,7 +43,7 @@ process GBCMSRS_MERGE { cat <<-END_VERSIONS > versions.yml "${task.process}": - gbcms: 6.3.0 + gbcms: \$(echo "${task.container}" | sed 's/.*://') END_VERSIONS """ } diff --git a/modules/msk/gbcmsrs/merge/tests/main.nf.test b/modules/msk/gbcmsrs/merge/tests/main.nf.test index 9b08d934..d936b6aa 100644 --- a/modules/msk/gbcmsrs/merge/tests/main.nf.test +++ b/modules/msk/gbcmsrs/merge/tests/main.nf.test @@ -10,9 +10,7 @@ nextflow_process { tag "gbcmsrs" tag "gbcmsrs/merge" - test("duplex simplex maf - stub") { - - options "-stub" + test("duplex simplex maf") { when { process { @@ -21,8 +19,8 @@ nextflow_process { [ id:'test' ], // meta map [ 'duplex', 'simplex' ], [ - file(params.test_data_mskcc['genome_nexus']['test_maf'], checkIfExists: true), - file(params.test_data_mskcc['genome_nexus']['sample2_sample1_annotated_maf'], checkIfExists: true) + file(params.test_data_mskcc['gbcmsrs']['mfsd_single_maf'], checkIfExists: true), + file(params.test_data_mskcc['gbcmsrs']['mfsd_multi_maf'], checkIfExists: true) ] ] """ diff --git a/modules/msk/gbcmsrs/merge/tests/main.nf.test.snap b/modules/msk/gbcmsrs/merge/tests/main.nf.test.snap deleted file mode 100644 index 16e735c8..00000000 --- a/modules/msk/gbcmsrs/merge/tests/main.nf.test.snap +++ /dev/null @@ -1,35 +0,0 @@ -{ - "duplex simplex maf - stub": { - "content": [ - { - "0": [ - [ - { - "id": "test" - }, - "test.merged.maf:md5,d41d8cd98f00b204e9800998ecf8427e" - ] - ], - "1": [ - "versions.yml:md5,d07a4f42f7d7d56f11bf4ba50315775e" - ], - "merged": [ - [ - { - "id": "test" - }, - "test.merged.maf:md5,d41d8cd98f00b204e9800998ecf8427e" - ] - ], - "versions": [ - "versions.yml:md5,d07a4f42f7d7d56f11bf4ba50315775e" - ] - } - ], - "timestamp": "2026-08-25T11:12:22.907599", - "meta": { - "nf-test": "0.9.5", - "nextflow": "24.10.3" - } - } -} \ No newline at end of file diff --git a/modules/msk/gbcmsrs/normalize/main.nf b/modules/msk/gbcmsrs/normalize/main.nf index aa73be15..9619abc9 100644 --- a/modules/msk/gbcmsrs/normalize/main.nf +++ b/modules/msk/gbcmsrs/normalize/main.nf @@ -46,7 +46,7 @@ process GBCMSRS_NORMALIZE { cat <<-END_VERSIONS > versions.yml "${task.process}": - gbcms: 6.3.0 + gbcms: \$(echo "${task.container}" | sed 's/.*://') END_VERSIONS """ } diff --git a/modules/msk/gbcmsrs/normalize/tests/main.nf.test b/modules/msk/gbcmsrs/normalize/tests/main.nf.test index 7e0cedaf..4afcef91 100644 --- a/modules/msk/gbcmsrs/normalize/tests/main.nf.test +++ b/modules/msk/gbcmsrs/normalize/tests/main.nf.test @@ -10,9 +10,7 @@ nextflow_process { tag "gbcmsrs" tag "gbcmsrs/normalize" - test("sarscov2 illumina - vcf - stub") { - - options "-stub" + test("sarscov2 illumina - vcf") { when { process { diff --git a/modules/msk/gbcmsrs/normalize/tests/main.nf.test.snap b/modules/msk/gbcmsrs/normalize/tests/main.nf.test.snap deleted file mode 100644 index a74ef373..00000000 --- a/modules/msk/gbcmsrs/normalize/tests/main.nf.test.snap +++ /dev/null @@ -1,35 +0,0 @@ -{ - "sarscov2 illumina - vcf - stub": { - "content": [ - { - "0": [ - [ - { - "id": "test" - }, - "test.normalized.tsv:md5,d41d8cd98f00b204e9800998ecf8427e" - ] - ], - "1": [ - "versions.yml:md5,2e0066bf092cdd9574f383d862db42c9" - ], - "normalized": [ - [ - { - "id": "test" - }, - "test.normalized.tsv:md5,d41d8cd98f00b204e9800998ecf8427e" - ] - ], - "versions": [ - "versions.yml:md5,2e0066bf092cdd9574f383d862db42c9" - ] - } - ], - "timestamp": "2026-08-25T11:12:27.900622", - "meta": { - "nf-test": "0.9.5", - "nextflow": "24.10.3" - } - } -} \ No newline at end of file diff --git a/modules/msk/gbcmsrs/rna/main.nf b/modules/msk/gbcmsrs/rna/main.nf index a4806373..ca8e72f2 100644 --- a/modules/msk/gbcmsrs/rna/main.nf +++ b/modules/msk/gbcmsrs/rna/main.nf @@ -4,15 +4,18 @@ process GBCMSRS_RNA { container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? 'ghcr.io/msk-access/gbcms:6.3.0': 'ghcr.io/msk-access/gbcms:6.3.0' }" - + // The gbcms image sets ENTRYPOINT ["gbcms"], which breaks Nextflow's docker/podman + // invocation of .command.run unless the entrypoint is cleared here. Singularity + // ignores the image entrypoint already, so this is scoped to docker/podman only. containerOptions { workflow.containerEngine in ['docker', 'podman'] ? "--entrypoint ''" : '' } input: - tuple val(meta), path(variants), path(bams), path(bais) + tuple val(meta), path(variants), val(sample_names), path(bams), path(bais) path fasta path fasta_fai path gtf path rna_editing_db + path gtf_cache output: tuple val(meta), path("gbcms_out/*.{vcf,maf}"), emit: variant_file @@ -25,11 +28,22 @@ process GBCMSRS_RNA { if (workflow.profile.tokenize(',').intersect(['conda', 'mamba']).size() >= 1) { error "GBCMSRS_RNA module does not support Conda. Please use Docker / Singularity instead." } + // gbcms's read filters (--filter-duplicates/-secondary/-supplementary/-qc-failed) + // default to ON. A pipeline mapping its own boolean params into ext.args must emit + // the explicit --no-filter-x form when off; omitting the flag silently keeps it on. + // On Nextflow >=26.04 (strict parser), CLI param overrides arrive as Strings, so + // `params.x ? 'a' : 'b'` sees "false" as truthy — compare with `.toString() == 'true'`. def args = task.ext.args ?: '' - def bam_args = bams.collect { "--bam ${it}" }.join(' ') + // Bare `--bam path` labels the sample using the staged file's stem, which is not + // meaningful for real BAM naming conventions. Pairing each bam with an explicit + // name keeps the output filename and Tumor_Sample_Barcode/VCF sample column + // predictable and equal to what the caller intends. + def bam_args = [sample_names, bams].transpose().collect { name, bam -> "--bam ${name}:${bam}" }.join(' ') def gtf_arg = gtf ? "--gtf ${gtf}" : '' def editing_db_arg = rna_editing_db ? "--rna-editing-db ${rna_editing_db}" : '' - + // gtf_cache is produced by GBCMSRS_BUILDGTFCACHE.out.cache_dir; wiring that module's + // output into this input is a subworkflow-level concern, not this module's. + def gtf_cache_arg = gtf_cache ? "--gtf-cache-dir ${gtf_cache}" : '' """ gbcms rna \\ --variants ${variants} \\ @@ -39,6 +53,7 @@ process GBCMSRS_RNA { --threads ${task.cpus} \\ ${gtf_arg} \\ ${editing_db_arg} \\ + ${gtf_cache_arg} \\ $args cat <<-END_VERSIONS > versions.yml @@ -48,13 +63,14 @@ process GBCMSRS_RNA { """ stub: + def sample_name = sample_names[0] """ mkdir -p gbcms_out - touch gbcms_out/${variants.baseName}.vcf + touch gbcms_out/${sample_name}.vcf cat <<-END_VERSIONS > versions.yml "${task.process}": - gbcms: 6.3.0 + gbcms: \$(echo "${task.container}" | sed 's/.*://') END_VERSIONS """ } diff --git a/modules/msk/gbcmsrs/rna/meta.yml b/modules/msk/gbcmsrs/rna/meta.yml index 2d68bf71..3e1d9d80 100644 --- a/modules/msk/gbcmsrs/rna/meta.yml +++ b/modules/msk/gbcmsrs/rna/meta.yml @@ -30,6 +30,13 @@ input: description: Input variant file in VCF or MAF format pattern: "*.{vcf,maf}" ontologies: [] + - sample_names: + type: string + description: + List of sample names, parallel to `bams`, used to label each BAM + via `--bam :`. Without an explicit name, gbcms falls + back to the staged file's stem, which is usually not the desired + sample id. - bams: type: file description: One or more indexed RNA-seq BAM/CRAM files to count alleles in @@ -64,6 +71,14 @@ input: Pass an empty list (`[]`) to omit. pattern: "*.{txt,txt.gz}" ontologies: [] + - gtf_cache: + type: directory + description: + Optional prebuilt GTF index cache directory, as produced by + GBCMSRS_BUILDGTFCACHE.out.cache_dir, avoiding a re-parse of the GTF + for this sample. Pass an empty list (`[]`) to omit. Wiring the two + modules together is a subworkflow-level concern. + pattern: "gbcms_gtf_cache" output: variant_file: - - meta: diff --git a/modules/msk/gbcmsrs/rna/tests/main.nf.test b/modules/msk/gbcmsrs/rna/tests/main.nf.test index aee8f5a0..e4ee9088 100644 --- a/modules/msk/gbcmsrs/rna/tests/main.nf.test +++ b/modules/msk/gbcmsrs/rna/tests/main.nf.test @@ -10,9 +10,7 @@ nextflow_process { tag "gbcmsrs" tag "gbcmsrs/rna" - test("sarscov2 illumina - vcf - stub") { - - options "-stub" + test("sarscov2 illumina - vcf") { when { process { @@ -20,6 +18,7 @@ nextflow_process { input[0] = [ [ id:'test' ], // meta map file(params.test_data['sarscov2']['illumina']['test_vcf'], checkIfExists: true), + [ 'test' ], [ file(params.test_data['sarscov2']['illumina']['test_single_end_sorted_bam'], checkIfExists: true) ], [ file(params.test_data['sarscov2']['illumina']['test_single_end_sorted_bam_bai'], checkIfExists: true) ] ] @@ -27,6 +26,7 @@ nextflow_process { input[2] = file(params.test_data['sarscov2']['genome']['genome_fasta_fai'], checkIfExists: true) input[3] = file(params.test_data['sarscov2']['genome']['genome_gtf'], checkIfExists: true) input[4] = [] + input[5] = [] """ } } diff --git a/modules/msk/gbcmsrs/rna/tests/main.nf.test.snap b/modules/msk/gbcmsrs/rna/tests/main.nf.test.snap deleted file mode 100644 index c2920238..00000000 --- a/modules/msk/gbcmsrs/rna/tests/main.nf.test.snap +++ /dev/null @@ -1,35 +0,0 @@ -{ - "sarscov2 illumina - vcf - stub": { - "content": [ - { - "0": [ - [ - { - "id": "test" - }, - "test.vcf:md5,d41d8cd98f00b204e9800998ecf8427e" - ] - ], - "1": [ - "versions.yml:md5,5a18d25acc7da7ba2920edc6d2755e1a" - ], - "variant_file": [ - [ - { - "id": "test" - }, - "test.vcf:md5,d41d8cd98f00b204e9800998ecf8427e" - ] - ], - "versions": [ - "versions.yml:md5,5a18d25acc7da7ba2920edc6d2755e1a" - ] - } - ], - "timestamp": "2026-08-25T11:12:32.792419", - "meta": { - "nf-test": "0.9.5", - "nextflow": "24.10.3" - } - } -} \ No newline at end of file diff --git a/tests/config/test_data.config b/tests/config/test_data.config index 347b83d6..0e952f37 100644 --- a/tests/config/test_data.config +++ b/tests/config/test_data.config @@ -816,5 +816,9 @@ params { test_chr22_collapsed_grouped_bam = "${params.test_data_base_msk}/feature/fgbio_collectduplexseqmetrics/testdata/chr22_collapsed_grouped.bam" test_chr22_collapsed_grouped_bam_bai = "${params.test_data_base_msk}/feature/fgbio_collectduplexseqmetrics/testdata/chr22_collapsed_grouped.bam.bai" } + 'gbcmsrs' { + mfsd_single_maf = "${params.test_data_base_msk}/feature/getbase/getbasecount/merge/mfsd_single.maf" + mfsd_multi_maf = "${params.test_data_base_msk}/feature/getbase/getbasecount/merge/mfsd_multi.maf" + } } } From 1cb83b3fbec5052070e7628f71ca8129b6619c6a Mon Sep 17 00:00:00 2001 From: buehlere Date: Wed, 26 Aug 2026 13:46:39 -0400 Subject: [PATCH 3/9] add snapshots --- .../buildgtfcache/tests/main.nf.test.snap | 29 +++++++++++++++ .../msk/gbcmsrs/dna/tests/main.nf.test.snap | 35 +++++++++++++++++++ .../msk/gbcmsrs/merge/tests/main.nf.test.snap | 35 +++++++++++++++++++ .../gbcmsrs/normalize/tests/main.nf.test.snap | 35 +++++++++++++++++++ .../msk/gbcmsrs/rna/tests/main.nf.test.snap | 35 +++++++++++++++++++ 5 files changed, 169 insertions(+) create mode 100644 modules/msk/gbcmsrs/buildgtfcache/tests/main.nf.test.snap create mode 100644 modules/msk/gbcmsrs/dna/tests/main.nf.test.snap create mode 100644 modules/msk/gbcmsrs/merge/tests/main.nf.test.snap create mode 100644 modules/msk/gbcmsrs/normalize/tests/main.nf.test.snap create mode 100644 modules/msk/gbcmsrs/rna/tests/main.nf.test.snap diff --git a/modules/msk/gbcmsrs/buildgtfcache/tests/main.nf.test.snap b/modules/msk/gbcmsrs/buildgtfcache/tests/main.nf.test.snap new file mode 100644 index 00000000..f9b6d9a3 --- /dev/null +++ b/modules/msk/gbcmsrs/buildgtfcache/tests/main.nf.test.snap @@ -0,0 +1,29 @@ +{ + "sarscov2 illumina - vcf gtf": { + "content": [ + { + "0": [ + [ + "gbcms-gtf-38d6bc761606825e.idx:md5,d4ff9cf32c02b05359f11ea9fbfb1974" + ] + ], + "1": [ + "versions.yml:md5,caa12a2ea191d010798bbfbaae282c28" + ], + "cache_dir": [ + [ + "gbcms-gtf-38d6bc761606825e.idx:md5,d4ff9cf32c02b05359f11ea9fbfb1974" + ] + ], + "versions": [ + "versions.yml:md5,caa12a2ea191d010798bbfbaae282c28" + ] + } + ], + "timestamp": "2026-08-26T13:41:43.602052101", + "meta": { + "nf-test": "0.9.5", + "nextflow": "26.04.6" + } + } +} \ No newline at end of file diff --git a/modules/msk/gbcmsrs/dna/tests/main.nf.test.snap b/modules/msk/gbcmsrs/dna/tests/main.nf.test.snap new file mode 100644 index 00000000..2d5aea0b --- /dev/null +++ b/modules/msk/gbcmsrs/dna/tests/main.nf.test.snap @@ -0,0 +1,35 @@ +{ + "sarscov2 illumina - vcf": { + "content": [ + { + "0": [ + [ + { + "id": "test" + }, + "test.vcf:md5,bfda580e0db5ca9c213a56015ee71f46" + ] + ], + "1": [ + "versions.yml:md5,087878e68053220863c1b7c4fabe880f" + ], + "variant_file": [ + [ + { + "id": "test" + }, + "test.vcf:md5,bfda580e0db5ca9c213a56015ee71f46" + ] + ], + "versions": [ + "versions.yml:md5,087878e68053220863c1b7c4fabe880f" + ] + } + ], + "timestamp": "2026-08-26T13:41:53.095468094", + "meta": { + "nf-test": "0.9.5", + "nextflow": "26.04.6" + } + } +} \ No newline at end of file diff --git a/modules/msk/gbcmsrs/merge/tests/main.nf.test.snap b/modules/msk/gbcmsrs/merge/tests/main.nf.test.snap new file mode 100644 index 00000000..9fc537ef --- /dev/null +++ b/modules/msk/gbcmsrs/merge/tests/main.nf.test.snap @@ -0,0 +1,35 @@ +{ + "duplex simplex maf": { + "content": [ + { + "0": [ + [ + { + "id": "test" + }, + "test.merged.maf:md5,81bbe12fb5511ce9c66d3375b9ed71dc" + ] + ], + "1": [ + "versions.yml:md5,d07a4f42f7d7d56f11bf4ba50315775e" + ], + "merged": [ + [ + { + "id": "test" + }, + "test.merged.maf:md5,81bbe12fb5511ce9c66d3375b9ed71dc" + ] + ], + "versions": [ + "versions.yml:md5,d07a4f42f7d7d56f11bf4ba50315775e" + ] + } + ], + "timestamp": "2026-08-26T13:42:02.192305177", + "meta": { + "nf-test": "0.9.5", + "nextflow": "26.04.6" + } + } +} \ No newline at end of file diff --git a/modules/msk/gbcmsrs/normalize/tests/main.nf.test.snap b/modules/msk/gbcmsrs/normalize/tests/main.nf.test.snap new file mode 100644 index 00000000..c6e236f7 --- /dev/null +++ b/modules/msk/gbcmsrs/normalize/tests/main.nf.test.snap @@ -0,0 +1,35 @@ +{ + "sarscov2 illumina - vcf": { + "content": [ + { + "0": [ + [ + { + "id": "test" + }, + "test.normalized.tsv:md5,292c3a20d32eadc93f4402a99b8d409b" + ] + ], + "1": [ + "versions.yml:md5,2e0066bf092cdd9574f383d862db42c9" + ], + "normalized": [ + [ + { + "id": "test" + }, + "test.normalized.tsv:md5,292c3a20d32eadc93f4402a99b8d409b" + ] + ], + "versions": [ + "versions.yml:md5,2e0066bf092cdd9574f383d862db42c9" + ] + } + ], + "timestamp": "2026-08-26T13:42:11.315734263", + "meta": { + "nf-test": "0.9.5", + "nextflow": "26.04.6" + } + } +} \ No newline at end of file diff --git a/modules/msk/gbcmsrs/rna/tests/main.nf.test.snap b/modules/msk/gbcmsrs/rna/tests/main.nf.test.snap new file mode 100644 index 00000000..9ea4edcf --- /dev/null +++ b/modules/msk/gbcmsrs/rna/tests/main.nf.test.snap @@ -0,0 +1,35 @@ +{ + "sarscov2 illumina - vcf": { + "content": [ + { + "0": [ + [ + { + "id": "test" + }, + "test.vcf:md5,29be2e30fb1b8fb652d7c900977896a1" + ] + ], + "1": [ + "versions.yml:md5,5a18d25acc7da7ba2920edc6d2755e1a" + ], + "variant_file": [ + [ + { + "id": "test" + }, + "test.vcf:md5,29be2e30fb1b8fb652d7c900977896a1" + ] + ], + "versions": [ + "versions.yml:md5,5a18d25acc7da7ba2920edc6d2755e1a" + ] + } + ], + "timestamp": "2026-08-26T13:42:20.736716024", + "meta": { + "nf-test": "0.9.5", + "nextflow": "26.04.6" + } + } +} \ No newline at end of file From c7be359daf14a9806d04d74ad49b364d1163d90b Mon Sep 17 00:00:00 2001 From: buehlere Date: Wed, 26 Aug 2026 14:19:13 -0400 Subject: [PATCH 4/9] make cache deterministic --- .../gbcmsrs/buildgtfcache/tests/main.nf.test | 4 ++- .../buildgtfcache/tests/main.nf.test.snap | 29 ------------------- 2 files changed, 3 insertions(+), 30 deletions(-) delete mode 100644 modules/msk/gbcmsrs/buildgtfcache/tests/main.nf.test.snap diff --git a/modules/msk/gbcmsrs/buildgtfcache/tests/main.nf.test b/modules/msk/gbcmsrs/buildgtfcache/tests/main.nf.test index 5110cdfc..e80d3432 100644 --- a/modules/msk/gbcmsrs/buildgtfcache/tests/main.nf.test +++ b/modules/msk/gbcmsrs/buildgtfcache/tests/main.nf.test @@ -22,9 +22,11 @@ nextflow_process { } then { + def idx_files = file(process.out.cache_dir[0]).listFiles().findAll { it.name.endsWith('.idx') } assertAll( { assert process.success }, - { assert snapshot(process.out).match() } + { assert idx_files.size() == 1 }, + { assert snapshot(process.out.versions).match() } ) } diff --git a/modules/msk/gbcmsrs/buildgtfcache/tests/main.nf.test.snap b/modules/msk/gbcmsrs/buildgtfcache/tests/main.nf.test.snap deleted file mode 100644 index f9b6d9a3..00000000 --- a/modules/msk/gbcmsrs/buildgtfcache/tests/main.nf.test.snap +++ /dev/null @@ -1,29 +0,0 @@ -{ - "sarscov2 illumina - vcf gtf": { - "content": [ - { - "0": [ - [ - "gbcms-gtf-38d6bc761606825e.idx:md5,d4ff9cf32c02b05359f11ea9fbfb1974" - ] - ], - "1": [ - "versions.yml:md5,caa12a2ea191d010798bbfbaae282c28" - ], - "cache_dir": [ - [ - "gbcms-gtf-38d6bc761606825e.idx:md5,d4ff9cf32c02b05359f11ea9fbfb1974" - ] - ], - "versions": [ - "versions.yml:md5,caa12a2ea191d010798bbfbaae282c28" - ] - } - ], - "timestamp": "2026-08-26T13:41:43.602052101", - "meta": { - "nf-test": "0.9.5", - "nextflow": "26.04.6" - } - } -} \ No newline at end of file From a7b5699a640a934c75e7f82087f5a0b4b9c3cd5a Mon Sep 17 00:00:00 2001 From: buehlere Date: Wed, 26 Aug 2026 14:24:24 -0400 Subject: [PATCH 5/9] update snapshot --- .../gbcmsrs/buildgtfcache/tests/main.nf.test.snap | 14 ++++++++++++++ 1 file changed, 14 insertions(+) create mode 100644 modules/msk/gbcmsrs/buildgtfcache/tests/main.nf.test.snap diff --git a/modules/msk/gbcmsrs/buildgtfcache/tests/main.nf.test.snap b/modules/msk/gbcmsrs/buildgtfcache/tests/main.nf.test.snap new file mode 100644 index 00000000..da9ba1d8 --- /dev/null +++ b/modules/msk/gbcmsrs/buildgtfcache/tests/main.nf.test.snap @@ -0,0 +1,14 @@ +{ + "sarscov2 illumina - vcf gtf": { + "content": [ + [ + "versions.yml:md5,caa12a2ea191d010798bbfbaae282c28" + ] + ], + "timestamp": "2026-08-26T14:24:08.409623634", + "meta": { + "nf-test": "0.9.5", + "nextflow": "26.04.6" + } + } +} \ No newline at end of file From bd17f9ec6fb675cbedebac257b037f9e06d74907 Mon Sep 17 00:00:00 2001 From: buehlere Date: Thu, 27 Aug 2026 10:11:35 -0400 Subject: [PATCH 6/9] update image --- modules/msk/gbcmsrs/buildgtfcache/main.nf | 5 ++--- modules/msk/gbcmsrs/dna/main.nf | 8 ++------ modules/msk/gbcmsrs/merge/main.nf | 6 ++---- modules/msk/gbcmsrs/normalize/main.nf | 6 ++---- modules/msk/gbcmsrs/rna/main.nf | 8 ++------ 5 files changed, 10 insertions(+), 23 deletions(-) diff --git a/modules/msk/gbcmsrs/buildgtfcache/main.nf b/modules/msk/gbcmsrs/buildgtfcache/main.nf index 7a3437c1..031b9905 100644 --- a/modules/msk/gbcmsrs/buildgtfcache/main.nf +++ b/modules/msk/gbcmsrs/buildgtfcache/main.nf @@ -2,9 +2,8 @@ process GBCMSRS_BUILDGTFCACHE { tag "${variants.name}" label 'process_single' container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? - 'ghcr.io/msk-access/gbcms:6.3.0': - 'ghcr.io/msk-access/gbcms:6.3.0' }" - containerOptions { workflow.containerEngine in ['docker', 'podman'] ? "--entrypoint ''" : '' } + 'ghcr.io/mskcc-omics-workflows/gbcms:6.3.1': + 'ghcr.io/mskcc-omics-workflows/gbcms:6.3.1' }" input: path variants diff --git a/modules/msk/gbcmsrs/dna/main.nf b/modules/msk/gbcmsrs/dna/main.nf index da8ef5a2..f28ae070 100644 --- a/modules/msk/gbcmsrs/dna/main.nf +++ b/modules/msk/gbcmsrs/dna/main.nf @@ -2,12 +2,8 @@ process GBCMSRS_DNA { tag "$meta.id" label 'process_medium' container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? - 'ghcr.io/msk-access/gbcms:6.3.0': - 'ghcr.io/msk-access/gbcms:6.3.0' }" - // The gbcms image sets ENTRYPOINT ["gbcms"], which breaks Nextflow's docker/podman - // invocation of .command.run unless the entrypoint is cleared here. Singularity - // ignores the image entrypoint already, so this is scoped to docker/podman only. - containerOptions { workflow.containerEngine in ['docker', 'podman'] ? "--entrypoint ''" : '' } + 'ghcr.io/mskcc-omics-workflows/gbcms:6.3.1': + 'ghcr.io/mskcc-omics-workflows/gbcms:6.3.1' }" input: tuple val(meta), path(variants), val(sample_names), path(bams), path(bais) diff --git a/modules/msk/gbcmsrs/merge/main.nf b/modules/msk/gbcmsrs/merge/main.nf index b4b99177..4ca2a82d 100644 --- a/modules/msk/gbcmsrs/merge/main.nf +++ b/modules/msk/gbcmsrs/merge/main.nf @@ -2,10 +2,8 @@ process GBCMSRS_MERGE { tag "$meta.id" label 'process_single' container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? - 'ghcr.io/msk-access/gbcms:6.3.0': - 'ghcr.io/msk-access/gbcms:6.3.0' }" - - containerOptions { workflow.containerEngine in ['docker', 'podman'] ? "--entrypoint ''" : '' } + 'ghcr.io/mskcc-omics-workflows/gbcms:6.3.1': + 'ghcr.io/mskcc-omics-workflows/gbcms:6.3.1' }" input: tuple val(meta), val(types), path(mafs) diff --git a/modules/msk/gbcmsrs/normalize/main.nf b/modules/msk/gbcmsrs/normalize/main.nf index 9619abc9..b074613c 100644 --- a/modules/msk/gbcmsrs/normalize/main.nf +++ b/modules/msk/gbcmsrs/normalize/main.nf @@ -2,10 +2,8 @@ process GBCMSRS_NORMALIZE { tag "$meta.id" label 'process_single' container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? - 'ghcr.io/msk-access/gbcms:6.3.0': - 'ghcr.io/msk-access/gbcms:6.3.0' }" - - containerOptions { workflow.containerEngine in ['docker', 'podman'] ? "--entrypoint ''" : '' } + 'ghcr.io/mskcc-omics-workflows/gbcms:6.3.1': + 'ghcr.io/mskcc-omics-workflows/gbcms:6.3.1' }" input: tuple val(meta), path(variants) diff --git a/modules/msk/gbcmsrs/rna/main.nf b/modules/msk/gbcmsrs/rna/main.nf index ca8e72f2..8c8b30ed 100644 --- a/modules/msk/gbcmsrs/rna/main.nf +++ b/modules/msk/gbcmsrs/rna/main.nf @@ -2,12 +2,8 @@ process GBCMSRS_RNA { tag "$meta.id" label 'process_medium' container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? - 'ghcr.io/msk-access/gbcms:6.3.0': - 'ghcr.io/msk-access/gbcms:6.3.0' }" - // The gbcms image sets ENTRYPOINT ["gbcms"], which breaks Nextflow's docker/podman - // invocation of .command.run unless the entrypoint is cleared here. Singularity - // ignores the image entrypoint already, so this is scoped to docker/podman only. - containerOptions { workflow.containerEngine in ['docker', 'podman'] ? "--entrypoint ''" : '' } + 'ghcr.io/mskcc-omics-workflows/gbcms:6.3.1': + 'ghcr.io/mskcc-omics-workflows/gbcms:6.3.1' }" input: tuple val(meta), path(variants), val(sample_names), path(bams), path(bais) From 915b999bc02fe5887adc02de778e5f96b811958e Mon Sep 17 00:00:00 2001 From: buehlere Date: Thu, 27 Aug 2026 10:14:16 -0400 Subject: [PATCH 7/9] update snapshots --- .../buildgtfcache/tests/main.nf.test.snap | 14 -------- .../msk/gbcmsrs/dna/tests/main.nf.test.snap | 35 ------------------- .../msk/gbcmsrs/merge/tests/main.nf.test.snap | 35 ------------------- .../gbcmsrs/normalize/tests/main.nf.test.snap | 35 ------------------- .../msk/gbcmsrs/rna/tests/main.nf.test.snap | 35 ------------------- 5 files changed, 154 deletions(-) delete mode 100644 modules/msk/gbcmsrs/buildgtfcache/tests/main.nf.test.snap delete mode 100644 modules/msk/gbcmsrs/dna/tests/main.nf.test.snap delete mode 100644 modules/msk/gbcmsrs/merge/tests/main.nf.test.snap delete mode 100644 modules/msk/gbcmsrs/normalize/tests/main.nf.test.snap delete mode 100644 modules/msk/gbcmsrs/rna/tests/main.nf.test.snap diff --git a/modules/msk/gbcmsrs/buildgtfcache/tests/main.nf.test.snap b/modules/msk/gbcmsrs/buildgtfcache/tests/main.nf.test.snap deleted file mode 100644 index da9ba1d8..00000000 --- a/modules/msk/gbcmsrs/buildgtfcache/tests/main.nf.test.snap +++ /dev/null @@ -1,14 +0,0 @@ -{ - "sarscov2 illumina - vcf gtf": { - "content": [ - [ - "versions.yml:md5,caa12a2ea191d010798bbfbaae282c28" - ] - ], - "timestamp": "2026-08-26T14:24:08.409623634", - "meta": { - "nf-test": "0.9.5", - "nextflow": "26.04.6" - } - } -} \ No newline at end of file diff --git a/modules/msk/gbcmsrs/dna/tests/main.nf.test.snap b/modules/msk/gbcmsrs/dna/tests/main.nf.test.snap deleted file mode 100644 index 2d5aea0b..00000000 --- a/modules/msk/gbcmsrs/dna/tests/main.nf.test.snap +++ /dev/null @@ -1,35 +0,0 @@ -{ - "sarscov2 illumina - vcf": { - "content": [ - { - "0": [ - [ - { - "id": "test" - }, - "test.vcf:md5,bfda580e0db5ca9c213a56015ee71f46" - ] - ], - "1": [ - "versions.yml:md5,087878e68053220863c1b7c4fabe880f" - ], - "variant_file": [ - [ - { - "id": "test" - }, - "test.vcf:md5,bfda580e0db5ca9c213a56015ee71f46" - ] - ], - "versions": [ - "versions.yml:md5,087878e68053220863c1b7c4fabe880f" - ] - } - ], - "timestamp": "2026-08-26T13:41:53.095468094", - "meta": { - "nf-test": "0.9.5", - "nextflow": "26.04.6" - } - } -} \ No newline at end of file diff --git a/modules/msk/gbcmsrs/merge/tests/main.nf.test.snap b/modules/msk/gbcmsrs/merge/tests/main.nf.test.snap deleted file mode 100644 index 9fc537ef..00000000 --- a/modules/msk/gbcmsrs/merge/tests/main.nf.test.snap +++ /dev/null @@ -1,35 +0,0 @@ -{ - "duplex simplex maf": { - "content": [ - { - "0": [ - [ - { - "id": "test" - }, - "test.merged.maf:md5,81bbe12fb5511ce9c66d3375b9ed71dc" - ] - ], - "1": [ - "versions.yml:md5,d07a4f42f7d7d56f11bf4ba50315775e" - ], - "merged": [ - [ - { - "id": "test" - }, - "test.merged.maf:md5,81bbe12fb5511ce9c66d3375b9ed71dc" - ] - ], - "versions": [ - "versions.yml:md5,d07a4f42f7d7d56f11bf4ba50315775e" - ] - } - ], - "timestamp": "2026-08-26T13:42:02.192305177", - "meta": { - "nf-test": "0.9.5", - "nextflow": "26.04.6" - } - } -} \ No newline at end of file diff --git a/modules/msk/gbcmsrs/normalize/tests/main.nf.test.snap b/modules/msk/gbcmsrs/normalize/tests/main.nf.test.snap deleted file mode 100644 index c6e236f7..00000000 --- a/modules/msk/gbcmsrs/normalize/tests/main.nf.test.snap +++ /dev/null @@ -1,35 +0,0 @@ -{ - "sarscov2 illumina - vcf": { - "content": [ - { - "0": [ - [ - { - "id": "test" - }, - "test.normalized.tsv:md5,292c3a20d32eadc93f4402a99b8d409b" - ] - ], - "1": [ - "versions.yml:md5,2e0066bf092cdd9574f383d862db42c9" - ], - "normalized": [ - [ - { - "id": "test" - }, - "test.normalized.tsv:md5,292c3a20d32eadc93f4402a99b8d409b" - ] - ], - "versions": [ - "versions.yml:md5,2e0066bf092cdd9574f383d862db42c9" - ] - } - ], - "timestamp": "2026-08-26T13:42:11.315734263", - "meta": { - "nf-test": "0.9.5", - "nextflow": "26.04.6" - } - } -} \ No newline at end of file diff --git a/modules/msk/gbcmsrs/rna/tests/main.nf.test.snap b/modules/msk/gbcmsrs/rna/tests/main.nf.test.snap deleted file mode 100644 index 9ea4edcf..00000000 --- a/modules/msk/gbcmsrs/rna/tests/main.nf.test.snap +++ /dev/null @@ -1,35 +0,0 @@ -{ - "sarscov2 illumina - vcf": { - "content": [ - { - "0": [ - [ - { - "id": "test" - }, - "test.vcf:md5,29be2e30fb1b8fb652d7c900977896a1" - ] - ], - "1": [ - "versions.yml:md5,5a18d25acc7da7ba2920edc6d2755e1a" - ], - "variant_file": [ - [ - { - "id": "test" - }, - "test.vcf:md5,29be2e30fb1b8fb652d7c900977896a1" - ] - ], - "versions": [ - "versions.yml:md5,5a18d25acc7da7ba2920edc6d2755e1a" - ] - } - ], - "timestamp": "2026-08-26T13:42:20.736716024", - "meta": { - "nf-test": "0.9.5", - "nextflow": "26.04.6" - } - } -} \ No newline at end of file From 47924778dd83898d33309d23fffab175957bec41 Mon Sep 17 00:00:00 2001 From: buehlere Date: Thu, 27 Aug 2026 10:16:02 -0400 Subject: [PATCH 8/9] update snapshot --- .../buildgtfcache/tests/main.nf.test.snap | 14 ++++++++ .../msk/gbcmsrs/dna/tests/main.nf.test.snap | 35 +++++++++++++++++++ .../msk/gbcmsrs/merge/tests/main.nf.test.snap | 35 +++++++++++++++++++ .../gbcmsrs/normalize/tests/main.nf.test.snap | 35 +++++++++++++++++++ .../msk/gbcmsrs/rna/tests/main.nf.test.snap | 35 +++++++++++++++++++ 5 files changed, 154 insertions(+) create mode 100644 modules/msk/gbcmsrs/buildgtfcache/tests/main.nf.test.snap create mode 100644 modules/msk/gbcmsrs/dna/tests/main.nf.test.snap create mode 100644 modules/msk/gbcmsrs/merge/tests/main.nf.test.snap create mode 100644 modules/msk/gbcmsrs/normalize/tests/main.nf.test.snap create mode 100644 modules/msk/gbcmsrs/rna/tests/main.nf.test.snap diff --git a/modules/msk/gbcmsrs/buildgtfcache/tests/main.nf.test.snap b/modules/msk/gbcmsrs/buildgtfcache/tests/main.nf.test.snap new file mode 100644 index 00000000..6abdc6ed --- /dev/null +++ b/modules/msk/gbcmsrs/buildgtfcache/tests/main.nf.test.snap @@ -0,0 +1,14 @@ +{ + "sarscov2 illumina - vcf gtf": { + "content": [ + [ + "versions.yml:md5,9d75c19a947df6e008a3918a2e97ebc6" + ] + ], + "timestamp": "2026-08-27T10:14:42.910180254", + "meta": { + "nf-test": "0.9.5", + "nextflow": "26.04.6" + } + } +} \ No newline at end of file diff --git a/modules/msk/gbcmsrs/dna/tests/main.nf.test.snap b/modules/msk/gbcmsrs/dna/tests/main.nf.test.snap new file mode 100644 index 00000000..fc85fa09 --- /dev/null +++ b/modules/msk/gbcmsrs/dna/tests/main.nf.test.snap @@ -0,0 +1,35 @@ +{ + "sarscov2 illumina - vcf": { + "content": [ + { + "0": [ + [ + { + "id": "test" + }, + "test.vcf:md5,6263b41090085c08a45c28b2c1010836" + ] + ], + "1": [ + "versions.yml:md5,4bf00939eda0ee2c812c22755a0ebb19" + ], + "variant_file": [ + [ + { + "id": "test" + }, + "test.vcf:md5,6263b41090085c08a45c28b2c1010836" + ] + ], + "versions": [ + "versions.yml:md5,4bf00939eda0ee2c812c22755a0ebb19" + ] + } + ], + "timestamp": "2026-08-27T10:14:53.601840015", + "meta": { + "nf-test": "0.9.5", + "nextflow": "26.04.6" + } + } +} \ No newline at end of file diff --git a/modules/msk/gbcmsrs/merge/tests/main.nf.test.snap b/modules/msk/gbcmsrs/merge/tests/main.nf.test.snap new file mode 100644 index 00000000..4d05a992 --- /dev/null +++ b/modules/msk/gbcmsrs/merge/tests/main.nf.test.snap @@ -0,0 +1,35 @@ +{ + "duplex simplex maf": { + "content": [ + { + "0": [ + [ + { + "id": "test" + }, + "test.merged.maf:md5,81bbe12fb5511ce9c66d3375b9ed71dc" + ] + ], + "1": [ + "versions.yml:md5,d11192a5fe8053ad55df36e0d666e768" + ], + "merged": [ + [ + { + "id": "test" + }, + "test.merged.maf:md5,81bbe12fb5511ce9c66d3375b9ed71dc" + ] + ], + "versions": [ + "versions.yml:md5,d11192a5fe8053ad55df36e0d666e768" + ] + } + ], + "timestamp": "2026-08-27T10:15:04.577509879", + "meta": { + "nf-test": "0.9.5", + "nextflow": "26.04.6" + } + } +} \ No newline at end of file diff --git a/modules/msk/gbcmsrs/normalize/tests/main.nf.test.snap b/modules/msk/gbcmsrs/normalize/tests/main.nf.test.snap new file mode 100644 index 00000000..2568fcc7 --- /dev/null +++ b/modules/msk/gbcmsrs/normalize/tests/main.nf.test.snap @@ -0,0 +1,35 @@ +{ + "sarscov2 illumina - vcf": { + "content": [ + { + "0": [ + [ + { + "id": "test" + }, + "test.normalized.tsv:md5,292c3a20d32eadc93f4402a99b8d409b" + ] + ], + "1": [ + "versions.yml:md5,1b32163099847e6066c17372a3a1ede5" + ], + "normalized": [ + [ + { + "id": "test" + }, + "test.normalized.tsv:md5,292c3a20d32eadc93f4402a99b8d409b" + ] + ], + "versions": [ + "versions.yml:md5,1b32163099847e6066c17372a3a1ede5" + ] + } + ], + "timestamp": "2026-08-27T10:15:15.124502571", + "meta": { + "nf-test": "0.9.5", + "nextflow": "26.04.6" + } + } +} \ No newline at end of file diff --git a/modules/msk/gbcmsrs/rna/tests/main.nf.test.snap b/modules/msk/gbcmsrs/rna/tests/main.nf.test.snap new file mode 100644 index 00000000..a7bebcdc --- /dev/null +++ b/modules/msk/gbcmsrs/rna/tests/main.nf.test.snap @@ -0,0 +1,35 @@ +{ + "sarscov2 illumina - vcf": { + "content": [ + { + "0": [ + [ + { + "id": "test" + }, + "test.vcf:md5,a769b29c5747dfabde1802306cd2233b" + ] + ], + "1": [ + "versions.yml:md5,48db84911219f83e8870c5c493b21114" + ], + "variant_file": [ + [ + { + "id": "test" + }, + "test.vcf:md5,a769b29c5747dfabde1802306cd2233b" + ] + ], + "versions": [ + "versions.yml:md5,48db84911219f83e8870c5c493b21114" + ] + } + ], + "timestamp": "2026-08-27T10:15:27.562904488", + "meta": { + "nf-test": "0.9.5", + "nextflow": "26.04.6" + } + } +} \ No newline at end of file From 63acd41942bfe0b3829b7746c8272986af052154 Mon Sep 17 00:00:00 2001 From: buehlere Date: Thu, 27 Aug 2026 14:39:00 -0400 Subject: [PATCH 9/9] add note about filter duplicates --- modules/msk/gbcmsrs/dna/meta.yml | 16 +++++++++++++--- modules/msk/gbcmsrs/rna/meta.yml | 15 +++++++++++++-- 2 files changed, 26 insertions(+), 5 deletions(-) diff --git a/modules/msk/gbcmsrs/dna/meta.yml b/modules/msk/gbcmsrs/dna/meta.yml index 2e0dd06b..3299b130 100644 --- a/modules/msk/gbcmsrs/dna/meta.yml +++ b/modules/msk/gbcmsrs/dna/meta.yml @@ -1,8 +1,18 @@ # yaml-language-server: $schema=https://raw.githubusercontent.com/nf-core/modules/master/modules/yaml-schema.json name: "gbcmsrs_dna" -description: - Count alleles in cfDNA/somatic DNA BAMs at known variant sites using - gbcms +description: | + Count alleles in cfDNA/somatic DNA BAMs at known variant sites using gbcms. + + Note: gbcms's read filters (--filter-duplicates/-secondary/-supplementary/-qc-failed) + default to ON. A pipeline that maps its own boolean params into ext.args must emit the + explicit --no-filter-x form when off, or the filter silently stays on since omitting + the flag just falls back to the CLI default. On Nextflow >=26.04 (strict parser), CLI + param overrides arrive as Strings, so `params.x ? 'a' : 'b'` sees "false" as truthy. + Example ext.args mapping: + + ext.args = { [ + params.filter_qc_failed.toString() == 'true' ? '--filter-qc-failed' : '--no-filter-qc-failed', + ].join(' ') } keywords: - basecount - genotyping diff --git a/modules/msk/gbcmsrs/rna/meta.yml b/modules/msk/gbcmsrs/rna/meta.yml index 3e1d9d80..d2f422cd 100644 --- a/modules/msk/gbcmsrs/rna/meta.yml +++ b/modules/msk/gbcmsrs/rna/meta.yml @@ -1,8 +1,19 @@ # yaml-language-server: $schema=https://raw.githubusercontent.com/nf-core/modules/master/modules/yaml-schema.json name: "gbcmsrs_rna" -description: +description: | Count alleles in RNA-seq BAMs at known variant sites with transcriptome-aware - filtering using gbcms + filtering using gbcms. + + Note: gbcms's read filters (--filter-duplicates/-secondary/-supplementary/-qc-failed) + default to ON. A pipeline that maps its own boolean params into ext.args must emit the + explicit --no-filter-x form when off, or the filter silently stays on since omitting + the flag just falls back to the CLI default. On Nextflow >=26.04 (strict parser), CLI + param overrides arrive as Strings, so `params.x ? 'a' : 'b'` sees "false" as truthy. + Example ext.args mapping: + + ext.args = { [ + params.filter_qc_failed.toString() == 'true' ? '--filter-qc-failed' : '--no-filter-qc-failed', + ].join(' ') } keywords: - basecount - genotyping