From 03e4a0de3d4c5295bbbb21b0017cc89467ae2bf0 Mon Sep 17 00:00:00 2001 From: LouisLeNezet Date: Thu, 21 Mar 2024 12:54:47 +0100 Subject: [PATCH] Fix linting with eclint --- subworkflows/local/compute_gl/main.nf | 76 +-- subworkflows/local/get_panel/main.nf | 180 ++--- .../utils_nfcore_phaseimpute_pipeline/main.nf | 624 +++++++++--------- 3 files changed, 440 insertions(+), 440 deletions(-) diff --git a/subworkflows/local/compute_gl/main.nf b/subworkflows/local/compute_gl/main.nf index 2011561d..277933d1 100644 --- a/subworkflows/local/compute_gl/main.nf +++ b/subworkflows/local/compute_gl/main.nf @@ -1,38 +1,38 @@ -include { BCFTOOLS_MPILEUP } from '../../../modules/nf-core/bcftools/mpileup/main.nf' -include { BCFTOOLS_INDEX } from '../../../modules/nf-core/bcftools/index/main.nf' - - -workflow COMPUTE_GL { - - take: - ch_input // channel: [ [id, ref], bam, bai ] - ch_target // channel: [ [panel], sites, tsv] - ch_fasta // channel: [ [ref], fasta, fai] - - main: - - ch_versions = Channel.empty() - ch_multiqc_files = Channel.empty() - - ch_mpileup = ch_input - .combine(ch_target) - .map{metaI, bam, bai, metaP, sites, tsv -> - [metaI + metaP, bam, sites, tsv]} - - BCFTOOLS_MPILEUP( - ch_mpileup, - ch_fasta, - false - ) - ch_versions = ch_versions.mix(BCFTOOLS_MPILEUP.out.versions.first()) - - ch_output = BCFTOOLS_MPILEUP.out.vcf - .combine(BCFTOOLS_MPILEUP.out.tbi, by:0) - - ch_multiqc_files = ch_multiqc_files.mix(BCFTOOLS_MPILEUP.out.stats.map{ it[1] }) - - emit: - vcf = ch_output // channel: [ [id, panel], vcf, tbi ] - versions = ch_versions // channel: [ versions.yml ] - multiqc_files = ch_multiqc_files -} +include { BCFTOOLS_MPILEUP } from '../../../modules/nf-core/bcftools/mpileup/main.nf' +include { BCFTOOLS_INDEX } from '../../../modules/nf-core/bcftools/index/main.nf' + + +workflow COMPUTE_GL { + + take: + ch_input // channel: [ [id, ref], bam, bai ] + ch_target // channel: [ [panel], sites, tsv] + ch_fasta // channel: [ [ref], fasta, fai] + + main: + + ch_versions = Channel.empty() + ch_multiqc_files = Channel.empty() + + ch_mpileup = ch_input + .combine(ch_target) + .map{metaI, bam, bai, metaP, sites, tsv -> + [metaI + metaP, bam, sites, tsv]} + + BCFTOOLS_MPILEUP( + ch_mpileup, + ch_fasta, + false + ) + ch_versions = ch_versions.mix(BCFTOOLS_MPILEUP.out.versions.first()) + + ch_output = BCFTOOLS_MPILEUP.out.vcf + .combine(BCFTOOLS_MPILEUP.out.tbi, by:0) + + ch_multiqc_files = ch_multiqc_files.mix(BCFTOOLS_MPILEUP.out.stats.map{ it[1] }) + + emit: + vcf = ch_output // channel: [ [id, panel], vcf, tbi ] + versions = ch_versions // channel: [ versions.yml ] + multiqc_files = ch_multiqc_files +} diff --git a/subworkflows/local/get_panel/main.nf b/subworkflows/local/get_panel/main.nf index 69ffcb8f..4539647b 100644 --- a/subworkflows/local/get_panel/main.nf +++ b/subworkflows/local/get_panel/main.nf @@ -1,90 +1,90 @@ -include { BCFTOOLS_VIEW as VIEW_VCF_SNPS } from '../../../modules/nf-core/bcftools/view/main.nf' -include { BCFTOOLS_VIEW as VIEW_VCF_SITES } from '../../../modules/nf-core/bcftools/view/main.nf' -include { BCFTOOLS_INDEX as VCF_INDEX1 } from '../../../modules/nf-core/bcftools/index/main.nf' -include { BCFTOOLS_INDEX as VCF_INDEX3 } from '../../../modules/nf-core/bcftools/index/main.nf' -include { BCFTOOLS_INDEX as VCF_INDEX4 } from '../../../modules/nf-core/bcftools/index/main.nf' -include { BCFTOOLS_INDEX as VCF_INDEX5 } from '../../../modules/nf-core/bcftools/index/main.nf' -include { BCFTOOLS_NORM } from '../../../modules/nf-core/bcftools/norm/main.nf' -include { BCFTOOLS_QUERY } from '../../../modules/nf-core/bcftools/query/main.nf' -include { TABIX_BGZIP } from '../../../modules/nf-core/tabix/bgzip/main' -include { TABIX_TABIX } from '../../../modules/nf-core/tabix/tabix/main' -include { VCF_PHASE_SHAPEIT5 } from '../../../subworkflows/nf-core/vcf_phase_shapeit5/main' - - -workflow GET_PANEL { - take: - ch_vcf // channel: [ [id], vcf, index ] - ch_fasta // channel: [ [genome], fasta, fai ] - - main: - - ch_versions = Channel.empty() - - BCFTOOLS_NORM(ch_vcf, ch_fasta.map{ genome, fasta, fai -> [genome, fasta] }) - ch_versions = ch_versions.mix(BCFTOOLS_NORM.out.versions.first()) - - // Extract only the SNP - VIEW_VCF_SNPS(BCFTOOLS_NORM.out.vcf // [ meta, vcf ] - .combine(Channel.of([[]])), [], [], []) - ch_versions = ch_versions.mix(VIEW_VCF_SNPS.out.versions.first()) - - VCF_INDEX3(VIEW_VCF_SNPS.out.vcf) - ch_versions = ch_versions.mix(VCF_INDEX3.out.versions.first()) - - ch_panel_norm = VIEW_VCF_SNPS.out.vcf - .combine(VCF_INDEX3.out.csi, by:0) - - // Extract sites positions - vcf_region = VIEW_VCF_SNPS.out.vcf - .combine(VCF_INDEX3.out.csi, by:0) - VIEW_VCF_SITES( ch_panel_norm, - [], [], []) - ch_versions = ch_versions.mix(VIEW_VCF_SITES.out.versions.first()) - - VCF_INDEX4(VIEW_VCF_SITES.out.vcf) - ch_versions = ch_versions.mix(VCF_INDEX4.out.versions.first()) - - ch_panel_sites = VIEW_VCF_SITES.out.vcf - .combine(VCF_INDEX4.out.csi, by:0) - - // Convert to TSV - BCFTOOLS_QUERY(ch_panel_sites, - [], [], []) - ch_versions = ch_versions.mix(BCFTOOLS_QUERY.out.versions.first()) - - TABIX_BGZIP(BCFTOOLS_QUERY.out.output) - ch_versions = ch_versions.mix(TABIX_BGZIP.out.versions.first()) - - TABIX_TABIX(TABIX_BGZIP.out.output) - ch_versions = ch_versions.mix(TABIX_TABIX.out.versions.first()) - - ch_panel_tsv = TABIX_BGZIP.out.output - .combine(TABIX_TABIX.out.tbi, by: 0) - - // Phase panel - if (params.phased == false) { - VCF_PHASE_SHAPEIT5(vcf_region - .map { meta, vcf, csi -> [meta, vcf, csi, [], meta.region] }, - Channel.of([[],[],[]]).collect(), - Channel.of([[],[],[]]).collect(), - Channel.of([[],[]]).collect()) - ch_versions = ch_versions.mix(VCF_PHASE_SHAPEIT5.out.versions.first()) - ch_panel_phased = VCF_PHASE_SHAPEIT5.out.variants_phased - .combine(VCF_PHASE_SHAPEIT5.out.variants_index, by: 0) - } else { - ch_panel_phased = VIEW_VCF_SNPS.out.vcf - .combine(VCF_INDEX3.out.csi, by: 0) - } - - ch_panel = ch_panel_norm - .combine(ch_panel_sites, by: 0) - .combine(ch_panel_tsv, by: 0) - .combine(ch_panel_phased, by: 0) - .map{ metaI, norm, n_index, sites, s_index, tsv, t_index, phased, p_index - -> [[panel:metaI.id], norm, n_index, sites, s_index, tsv, t_index, phased, p_index] - } - - emit: - panel = ch_panel // channel: [ [panel], norm, n_index, sites, s_index, tsv, t_index, phased, p_index] - versions = ch_versions // channel: [ versions.yml ] -} +include { BCFTOOLS_VIEW as VIEW_VCF_SNPS } from '../../../modules/nf-core/bcftools/view/main.nf' +include { BCFTOOLS_VIEW as VIEW_VCF_SITES } from '../../../modules/nf-core/bcftools/view/main.nf' +include { BCFTOOLS_INDEX as VCF_INDEX1 } from '../../../modules/nf-core/bcftools/index/main.nf' +include { BCFTOOLS_INDEX as VCF_INDEX3 } from '../../../modules/nf-core/bcftools/index/main.nf' +include { BCFTOOLS_INDEX as VCF_INDEX4 } from '../../../modules/nf-core/bcftools/index/main.nf' +include { BCFTOOLS_INDEX as VCF_INDEX5 } from '../../../modules/nf-core/bcftools/index/main.nf' +include { BCFTOOLS_NORM } from '../../../modules/nf-core/bcftools/norm/main.nf' +include { BCFTOOLS_QUERY } from '../../../modules/nf-core/bcftools/query/main.nf' +include { TABIX_BGZIP } from '../../../modules/nf-core/tabix/bgzip/main' +include { TABIX_TABIX } from '../../../modules/nf-core/tabix/tabix/main' +include { VCF_PHASE_SHAPEIT5 } from '../../../subworkflows/nf-core/vcf_phase_shapeit5/main' + + +workflow GET_PANEL { + take: + ch_vcf // channel: [ [id], vcf, index ] + ch_fasta // channel: [ [genome], fasta, fai ] + + main: + + ch_versions = Channel.empty() + + BCFTOOLS_NORM(ch_vcf, ch_fasta.map{ genome, fasta, fai -> [genome, fasta] }) + ch_versions = ch_versions.mix(BCFTOOLS_NORM.out.versions.first()) + + // Extract only the SNP + VIEW_VCF_SNPS(BCFTOOLS_NORM.out.vcf // [ meta, vcf ] + .combine(Channel.of([[]])), [], [], []) + ch_versions = ch_versions.mix(VIEW_VCF_SNPS.out.versions.first()) + + VCF_INDEX3(VIEW_VCF_SNPS.out.vcf) + ch_versions = ch_versions.mix(VCF_INDEX3.out.versions.first()) + + ch_panel_norm = VIEW_VCF_SNPS.out.vcf + .combine(VCF_INDEX3.out.csi, by:0) + + // Extract sites positions + vcf_region = VIEW_VCF_SNPS.out.vcf + .combine(VCF_INDEX3.out.csi, by:0) + VIEW_VCF_SITES( ch_panel_norm, + [], [], []) + ch_versions = ch_versions.mix(VIEW_VCF_SITES.out.versions.first()) + + VCF_INDEX4(VIEW_VCF_SITES.out.vcf) + ch_versions = ch_versions.mix(VCF_INDEX4.out.versions.first()) + + ch_panel_sites = VIEW_VCF_SITES.out.vcf + .combine(VCF_INDEX4.out.csi, by:0) + + // Convert to TSV + BCFTOOLS_QUERY(ch_panel_sites, + [], [], []) + ch_versions = ch_versions.mix(BCFTOOLS_QUERY.out.versions.first()) + + TABIX_BGZIP(BCFTOOLS_QUERY.out.output) + ch_versions = ch_versions.mix(TABIX_BGZIP.out.versions.first()) + + TABIX_TABIX(TABIX_BGZIP.out.output) + ch_versions = ch_versions.mix(TABIX_TABIX.out.versions.first()) + + ch_panel_tsv = TABIX_BGZIP.out.output + .combine(TABIX_TABIX.out.tbi, by: 0) + + // Phase panel + if (params.phased == false) { + VCF_PHASE_SHAPEIT5(vcf_region + .map { meta, vcf, csi -> [meta, vcf, csi, [], meta.region] }, + Channel.of([[],[],[]]).collect(), + Channel.of([[],[],[]]).collect(), + Channel.of([[],[]]).collect()) + ch_versions = ch_versions.mix(VCF_PHASE_SHAPEIT5.out.versions.first()) + ch_panel_phased = VCF_PHASE_SHAPEIT5.out.variants_phased + .combine(VCF_PHASE_SHAPEIT5.out.variants_index, by: 0) + } else { + ch_panel_phased = VIEW_VCF_SNPS.out.vcf + .combine(VCF_INDEX3.out.csi, by: 0) + } + + ch_panel = ch_panel_norm + .combine(ch_panel_sites, by: 0) + .combine(ch_panel_tsv, by: 0) + .combine(ch_panel_phased, by: 0) + .map{ metaI, norm, n_index, sites, s_index, tsv, t_index, phased, p_index + -> [[panel:metaI.id], norm, n_index, sites, s_index, tsv, t_index, phased, p_index] + } + + emit: + panel = ch_panel // channel: [ [panel], norm, n_index, sites, s_index, tsv, t_index, phased, p_index] + versions = ch_versions // channel: [ versions.yml ] +} diff --git a/subworkflows/local/utils_nfcore_phaseimpute_pipeline/main.nf b/subworkflows/local/utils_nfcore_phaseimpute_pipeline/main.nf index 2a26704d..164b78d5 100644 --- a/subworkflows/local/utils_nfcore_phaseimpute_pipeline/main.nf +++ b/subworkflows/local/utils_nfcore_phaseimpute_pipeline/main.nf @@ -1,312 +1,312 @@ -// -// Subworkflow with functionality specific to the nf-core/phaseimpute pipeline -// - -/* -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - IMPORT FUNCTIONS / MODULES / SUBWORKFLOWS -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -*/ - -include { UTILS_NFVALIDATION_PLUGIN } from '../../nf-core/utils_nfvalidation_plugin' -include { paramsSummaryMap } from 'plugin/nf-validation' -include { fromSamplesheet } from 'plugin/nf-validation' -include { UTILS_NEXTFLOW_PIPELINE } from '../../nf-core/utils_nextflow_pipeline' -include { completionEmail } from '../../nf-core/utils_nfcore_pipeline' -include { completionSummary } from '../../nf-core/utils_nfcore_pipeline' -include { dashedLine } from '../../nf-core/utils_nfcore_pipeline' -include { nfCoreLogo } from '../../nf-core/utils_nfcore_pipeline' -include { imNotification } from '../../nf-core/utils_nfcore_pipeline' -include { UTILS_NFCORE_PIPELINE } from '../../nf-core/utils_nfcore_pipeline' -include { workflowCitation } from '../../nf-core/utils_nfcore_pipeline' -include { GET_REGION } from '../get_region' -include { SAMTOOLS_FAIDX } from '../../../modules/nf-core/samtools/faidx' - -/* -======================================================================================== - SUBWORKFLOW TO INITIALISE PIPELINE -======================================================================================== -*/ - -workflow PIPELINE_INITIALISATION { - - take: - version // boolean: Display version and exit - help // boolean: Display help text - validate_params // boolean: Boolean whether to validate parameters against the schema at runtime - monochrome_logs // boolean: Do not use coloured log outputs - nextflow_cli_args // array: List of positional nextflow CLI args - outdir // string: The output directory where the results will be saved - input // string: Path to input samplesheet - - main: - - ch_versions = Channel.empty() - - // - // Print version and exit if required and dump pipeline parameters to JSON file - // - UTILS_NEXTFLOW_PIPELINE ( - version, - true, - outdir, - workflow.profile.tokenize(',').intersect(['conda', 'mamba']).size() >= 1 - ) - - // - // Validate parameters and generate parameter summary to stdout - // - pre_help_text = nfCoreLogo(monochrome_logs) - post_help_text = '\n' + workflowCitation() + '\n' + dashedLine(monochrome_logs) - def String workflow_command = "nextflow run ${workflow.manifest.name} -profile --input samplesheet.csv --outdir " - UTILS_NFVALIDATION_PLUGIN ( - help, - workflow_command, - pre_help_text, - post_help_text, - validate_params, - "nextflow_schema.json" - ) - - // - // Check config provided to the pipeline - // - UTILS_NFCORE_PIPELINE ( - nextflow_cli_args - ) - // - // Custom validation for pipeline parameters - // - validateInputParameters() - - // - // Create fasta channel - // - genome = params.genome ? params.genome : file(params.fasta, checkIfExists:true).getBaseName() - if (params.genome) { - genome = params.genome - ch_fasta = Channel.of([[genome:genome], getGenomeAttribute('fasta')]) - fai = getGenomeAttribute('fai') - if (fai == null) { - SAMTOOLS_FAIDX(ch_fasta, Channel.of([[], []])) - ch_versions = ch_versions.mix(SAMTOOLS_FAIDX.out.versions.first()) - fai = SAMTOOLS_FAIDX.out.fai.map{ it[1] } - } - } else if (params.fasta) { - genome = file(params.fasta, checkIfExists:true).getBaseName() - ch_fasta = Channel.of([[genome:genome], file(params.fasta, checkIfExists:true)]) - if (params.fasta_fai) { - fai = file(params.fasta_fai, checkIfExists:true) - } else { - SAMTOOLS_FAIDX(ch_fasta, Channel.of([[], []])) - ch_versions = ch_versions.mix(SAMTOOLS_FAIDX.out.versions.first()) - fai = SAMTOOLS_FAIDX.out.fai.map{ it[1] } - } - } - ch_ref_gen = ch_fasta.combine(fai) - - // - // Create map channel - // - ch_map = params.map ? - Channel.of([["map": params.map], params.map]) : - Channel.of([[],[]]) - - // - // Create channel from input file provided through params.input - // - ch_input = Channel - .fromSamplesheet("input") - .map { - meta, bam, bai -> - [ meta, bam, bai ] - } - - // - // Create channel for panel - // - if (params.panel) { - ch_panel = Channel - .fromSamplesheet("panel") - .map { - meta,vcf,index,sites,tsv,legend,phased -> - [ meta, vcf, index ] - } - } - - // - // Create channel from region input - // - if (params.input_region) { - if (params.input_region.endsWith(".csv")) { - println "Region file provided as input is a csv file" - ch_regions = Channel.fromSamplesheet("input_region") - .map{ chr, start, end -> [["chr": chr], chr + ":" + start + "-" + end]} - .map{ metaC, region -> [metaC + ["region": region], region]} - } else { - println "Region file provided is a single region" - GET_REGION ( - params.input_region, - ch_ref_gen - ) - ch_versions = ch_versions.mix(GET_REGION.out.versions.first()) - ch_regions = GET_REGION.out.regions - } - } - - emit: - input = ch_input // [ [meta], bam, bai ] - fasta = ch_ref_gen // [ [genome], fasta, fai ] - panel = ch_panel // [ [panel], panel ] - regions = ch_regions // [ [chr, region], region ] - map = ch_map // [ [map], map ] - versions = ch_versions -} - -/* -======================================================================================== - SUBWORKFLOW FOR PIPELINE COMPLETION -======================================================================================== -*/ - -workflow PIPELINE_COMPLETION { - - take: - email // string: email address - email_on_fail // string: email address sent on pipeline failure - plaintext_email // boolean: Send plain-text email instead of HTML - outdir // path: Path to output directory where results will be published - monochrome_logs // boolean: Disable ANSI colour codes in log output - hook_url // string: hook URL for notifications - multiqc_report // string: Path to MultiQC report - - main: - - summary_params = paramsSummaryMap(workflow, parameters_schema: "nextflow_schema.json") - - // - // Completion email and summary - // - workflow.onComplete { - if (email || email_on_fail) { - completionEmail(summary_params, email, email_on_fail, plaintext_email, outdir, monochrome_logs, multiqc_report.toList()) - } - - completionSummary(monochrome_logs) - - if (hook_url) { - imNotification(summary_params, hook_url) - } - } -} - -/* -======================================================================================== - FUNCTIONS -======================================================================================== -*/ -// -// Check and validate pipeline parameters -// -def validateInputParameters() { - genomeExistsError() - // Check that only genome or fasta is provided - assert params.genome == null || params.fasta == null, "Either --genome or --fasta must be provided" - assert !(params.genome == null && params.fasta == null), "Only one of --genome or --fasta must be provided" - - // Check that a step is provided - assert params.step, "A step must be provided" - - // Check that at least one tool is provided - assert params.tools, "No tools provided" -} - -// -// Validate channels from input samplesheet -// -def validateInputSamplesheet(input) { - def (meta, bam, bai) = input - // Check that individual IDs are unique - // no validation for the moment -} -// -// Get attribute from genome config file e.g. fasta -// -def getGenomeAttribute(attribute) { - if (params.genomes && params.genome && params.genomes.containsKey(params.genome)) { - if (params.genomes[ params.genome ].containsKey(attribute)) { - return params.genomes[ params.genome ][ attribute ] - } - } - return null -} - -// -// Exit pipeline if incorrect --genome key provided -// -def genomeExistsError() { - if (params.genomes && params.genome && !params.genomes.containsKey(params.genome)) { - def error_string = "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" + - " Genome '${params.genome}' not found in any config files provided to the pipeline.\n" + - " Currently, the available genome keys are:\n" + - " ${params.genomes.keySet().join(", ")}\n" + - "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" - error(error_string) - } -} - -// -// Generate methods description for MultiQC -// -def toolCitationText() { - // TODO nf-core: Optionally add in-text citation tools to this list. - // Can use ternary operators to dynamically construct based conditions, e.g. params["run_xyz"] ? "Tool (Foo et al. 2023)" : "", - // Uncomment function in methodsDescriptionText to render in MultiQC report - def citation_text = [ - "Tools used in the workflow included:", - "FastQC (Andrews 2010),", - "MultiQC (Ewels et al. 2016)", - "." - ].join(' ').trim() - - return citation_text -} - -def toolBibliographyText() { - // TODO nf-core: Optionally add bibliographic entries to this list. - // Can use ternary operators to dynamically construct based conditions, e.g. params["run_xyz"] ? "
  • Author (2023) Pub name, Journal, DOI
  • " : "", - // Uncomment function in methodsDescriptionText to render in MultiQC report - def reference_text = [ - "
  • Andrews S, (2010) FastQC, URL: https://www.bioinformatics.babraham.ac.uk/projects/fastqc/).
  • ", - "
  • Ewels, P., Magnusson, M., Lundin, S., & Käller, M. (2016). MultiQC: summarize analysis results for multiple tools and samples in a single report. Bioinformatics , 32(19), 3047–3048. doi: /10.1093/bioinformatics/btw354
  • " - ].join(' ').trim() - - return reference_text -} - -def methodsDescriptionText(mqc_methods_yaml) { - // Convert to a named map so can be used as with familar NXF ${workflow} variable syntax in the MultiQC YML file - def meta = [:] - meta.workflow = workflow.toMap() - meta["manifest_map"] = workflow.manifest.toMap() - - // Pipeline DOI - meta["doi_text"] = meta.manifest_map.doi ? "(doi: ${meta.manifest_map.doi})" : "" - meta["nodoi_text"] = meta.manifest_map.doi ? "": "
  • If available, make sure to update the text to include the Zenodo DOI of version of the pipeline used.
  • " - - // Tool references - meta["tool_citations"] = "" - meta["tool_bibliography"] = "" - - // TODO nf-core: Only uncomment below if logic in toolCitationText/toolBibliographyText has been filled! - // meta["tool_citations"] = toolCitationText().replaceAll(", \\.", ".").replaceAll("\\. \\.", ".").replaceAll(", \\.", ".") - // meta["tool_bibliography"] = toolBibliographyText() - - - def methods_text = mqc_methods_yaml.text - - def engine = new groovy.text.SimpleTemplateEngine() - def description_html = engine.createTemplate(methods_text).make(meta) - - return description_html.toString() -} +// +// Subworkflow with functionality specific to the nf-core/phaseimpute pipeline +// + +/* +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + IMPORT FUNCTIONS / MODULES / SUBWORKFLOWS +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +*/ + +include { UTILS_NFVALIDATION_PLUGIN } from '../../nf-core/utils_nfvalidation_plugin' +include { paramsSummaryMap } from 'plugin/nf-validation' +include { fromSamplesheet } from 'plugin/nf-validation' +include { UTILS_NEXTFLOW_PIPELINE } from '../../nf-core/utils_nextflow_pipeline' +include { completionEmail } from '../../nf-core/utils_nfcore_pipeline' +include { completionSummary } from '../../nf-core/utils_nfcore_pipeline' +include { dashedLine } from '../../nf-core/utils_nfcore_pipeline' +include { nfCoreLogo } from '../../nf-core/utils_nfcore_pipeline' +include { imNotification } from '../../nf-core/utils_nfcore_pipeline' +include { UTILS_NFCORE_PIPELINE } from '../../nf-core/utils_nfcore_pipeline' +include { workflowCitation } from '../../nf-core/utils_nfcore_pipeline' +include { GET_REGION } from '../get_region' +include { SAMTOOLS_FAIDX } from '../../../modules/nf-core/samtools/faidx' + +/* +======================================================================================== + SUBWORKFLOW TO INITIALISE PIPELINE +======================================================================================== +*/ + +workflow PIPELINE_INITIALISATION { + + take: + version // boolean: Display version and exit + help // boolean: Display help text + validate_params // boolean: Boolean whether to validate parameters against the schema at runtime + monochrome_logs // boolean: Do not use coloured log outputs + nextflow_cli_args // array: List of positional nextflow CLI args + outdir // string: The output directory where the results will be saved + input // string: Path to input samplesheet + + main: + + ch_versions = Channel.empty() + + // + // Print version and exit if required and dump pipeline parameters to JSON file + // + UTILS_NEXTFLOW_PIPELINE ( + version, + true, + outdir, + workflow.profile.tokenize(',').intersect(['conda', 'mamba']).size() >= 1 + ) + + // + // Validate parameters and generate parameter summary to stdout + // + pre_help_text = nfCoreLogo(monochrome_logs) + post_help_text = '\n' + workflowCitation() + '\n' + dashedLine(monochrome_logs) + def String workflow_command = "nextflow run ${workflow.manifest.name} -profile --input samplesheet.csv --outdir " + UTILS_NFVALIDATION_PLUGIN ( + help, + workflow_command, + pre_help_text, + post_help_text, + validate_params, + "nextflow_schema.json" + ) + + // + // Check config provided to the pipeline + // + UTILS_NFCORE_PIPELINE ( + nextflow_cli_args + ) + // + // Custom validation for pipeline parameters + // + validateInputParameters() + + // + // Create fasta channel + // + genome = params.genome ? params.genome : file(params.fasta, checkIfExists:true).getBaseName() + if (params.genome) { + genome = params.genome + ch_fasta = Channel.of([[genome:genome], getGenomeAttribute('fasta')]) + fai = getGenomeAttribute('fai') + if (fai == null) { + SAMTOOLS_FAIDX(ch_fasta, Channel.of([[], []])) + ch_versions = ch_versions.mix(SAMTOOLS_FAIDX.out.versions.first()) + fai = SAMTOOLS_FAIDX.out.fai.map{ it[1] } + } + } else if (params.fasta) { + genome = file(params.fasta, checkIfExists:true).getBaseName() + ch_fasta = Channel.of([[genome:genome], file(params.fasta, checkIfExists:true)]) + if (params.fasta_fai) { + fai = file(params.fasta_fai, checkIfExists:true) + } else { + SAMTOOLS_FAIDX(ch_fasta, Channel.of([[], []])) + ch_versions = ch_versions.mix(SAMTOOLS_FAIDX.out.versions.first()) + fai = SAMTOOLS_FAIDX.out.fai.map{ it[1] } + } + } + ch_ref_gen = ch_fasta.combine(fai) + + // + // Create map channel + // + ch_map = params.map ? + Channel.of([["map": params.map], params.map]) : + Channel.of([[],[]]) + + // + // Create channel from input file provided through params.input + // + ch_input = Channel + .fromSamplesheet("input") + .map { + meta, bam, bai -> + [ meta, bam, bai ] + } + + // + // Create channel for panel + // + if (params.panel) { + ch_panel = Channel + .fromSamplesheet("panel") + .map { + meta,vcf,index,sites,tsv,legend,phased -> + [ meta, vcf, index ] + } + } + + // + // Create channel from region input + // + if (params.input_region) { + if (params.input_region.endsWith(".csv")) { + println "Region file provided as input is a csv file" + ch_regions = Channel.fromSamplesheet("input_region") + .map{ chr, start, end -> [["chr": chr], chr + ":" + start + "-" + end]} + .map{ metaC, region -> [metaC + ["region": region], region]} + } else { + println "Region file provided is a single region" + GET_REGION ( + params.input_region, + ch_ref_gen + ) + ch_versions = ch_versions.mix(GET_REGION.out.versions.first()) + ch_regions = GET_REGION.out.regions + } + } + + emit: + input = ch_input // [ [meta], bam, bai ] + fasta = ch_ref_gen // [ [genome], fasta, fai ] + panel = ch_panel // [ [panel], panel ] + regions = ch_regions // [ [chr, region], region ] + map = ch_map // [ [map], map ] + versions = ch_versions +} + +/* +======================================================================================== + SUBWORKFLOW FOR PIPELINE COMPLETION +======================================================================================== +*/ + +workflow PIPELINE_COMPLETION { + + take: + email // string: email address + email_on_fail // string: email address sent on pipeline failure + plaintext_email // boolean: Send plain-text email instead of HTML + outdir // path: Path to output directory where results will be published + monochrome_logs // boolean: Disable ANSI colour codes in log output + hook_url // string: hook URL for notifications + multiqc_report // string: Path to MultiQC report + + main: + + summary_params = paramsSummaryMap(workflow, parameters_schema: "nextflow_schema.json") + + // + // Completion email and summary + // + workflow.onComplete { + if (email || email_on_fail) { + completionEmail(summary_params, email, email_on_fail, plaintext_email, outdir, monochrome_logs, multiqc_report.toList()) + } + + completionSummary(monochrome_logs) + + if (hook_url) { + imNotification(summary_params, hook_url) + } + } +} + +/* +======================================================================================== + FUNCTIONS +======================================================================================== +*/ +// +// Check and validate pipeline parameters +// +def validateInputParameters() { + genomeExistsError() + // Check that only genome or fasta is provided + assert params.genome == null || params.fasta == null, "Either --genome or --fasta must be provided" + assert !(params.genome == null && params.fasta == null), "Only one of --genome or --fasta must be provided" + + // Check that a step is provided + assert params.step, "A step must be provided" + + // Check that at least one tool is provided + assert params.tools, "No tools provided" +} + +// +// Validate channels from input samplesheet +// +def validateInputSamplesheet(input) { + def (meta, bam, bai) = input + // Check that individual IDs are unique + // no validation for the moment +} +// +// Get attribute from genome config file e.g. fasta +// +def getGenomeAttribute(attribute) { + if (params.genomes && params.genome && params.genomes.containsKey(params.genome)) { + if (params.genomes[ params.genome ].containsKey(attribute)) { + return params.genomes[ params.genome ][ attribute ] + } + } + return null +} + +// +// Exit pipeline if incorrect --genome key provided +// +def genomeExistsError() { + if (params.genomes && params.genome && !params.genomes.containsKey(params.genome)) { + def error_string = "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" + + " Genome '${params.genome}' not found in any config files provided to the pipeline.\n" + + " Currently, the available genome keys are:\n" + + " ${params.genomes.keySet().join(", ")}\n" + + "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" + error(error_string) + } +} + +// +// Generate methods description for MultiQC +// +def toolCitationText() { + // TODO nf-core: Optionally add in-text citation tools to this list. + // Can use ternary operators to dynamically construct based conditions, e.g. params["run_xyz"] ? "Tool (Foo et al. 2023)" : "", + // Uncomment function in methodsDescriptionText to render in MultiQC report + def citation_text = [ + "Tools used in the workflow included:", + "FastQC (Andrews 2010),", + "MultiQC (Ewels et al. 2016)", + "." + ].join(' ').trim() + + return citation_text +} + +def toolBibliographyText() { + // TODO nf-core: Optionally add bibliographic entries to this list. + // Can use ternary operators to dynamically construct based conditions, e.g. params["run_xyz"] ? "
  • Author (2023) Pub name, Journal, DOI
  • " : "", + // Uncomment function in methodsDescriptionText to render in MultiQC report + def reference_text = [ + "
  • Andrews S, (2010) FastQC, URL: https://www.bioinformatics.babraham.ac.uk/projects/fastqc/).
  • ", + "
  • Ewels, P., Magnusson, M., Lundin, S., & Käller, M. (2016). MultiQC: summarize analysis results for multiple tools and samples in a single report. Bioinformatics , 32(19), 3047–3048. doi: /10.1093/bioinformatics/btw354
  • " + ].join(' ').trim() + + return reference_text +} + +def methodsDescriptionText(mqc_methods_yaml) { + // Convert to a named map so can be used as with familar NXF ${workflow} variable syntax in the MultiQC YML file + def meta = [:] + meta.workflow = workflow.toMap() + meta["manifest_map"] = workflow.manifest.toMap() + + // Pipeline DOI + meta["doi_text"] = meta.manifest_map.doi ? "(doi: ${meta.manifest_map.doi})" : "" + meta["nodoi_text"] = meta.manifest_map.doi ? "": "
  • If available, make sure to update the text to include the Zenodo DOI of version of the pipeline used.
  • " + + // Tool references + meta["tool_citations"] = "" + meta["tool_bibliography"] = "" + + // TODO nf-core: Only uncomment below if logic in toolCitationText/toolBibliographyText has been filled! + // meta["tool_citations"] = toolCitationText().replaceAll(", \\.", ".").replaceAll("\\. \\.", ".").replaceAll(", \\.", ".") + // meta["tool_bibliography"] = toolBibliographyText() + + + def methods_text = mqc_methods_yaml.text + + def engine = new groovy.text.SimpleTemplateEngine() + def description_html = engine.createTemplate(methods_text).make(meta) + + return description_html.toString() +}