process runModkitPileup { label "modkit" cpus 4 memory "16 GB" input: tuple val(alias), val(meta), path(alignment), path(alignment_index), val(alignment_stats), val(mod_codes) tuple path(reference), path(reference_index) output: tuple val(alias), path("${alias}.mods.bedmethyl.gz"), emit: bedmethyl publishDir "${params.out_dir}/${output_key}/mods", mode: 'copy' script: output_key = alias == "cohort" ? "cohort" : "samples/${alias}" // nodef String modified_bases_arg = "--modified-bases " + mod_codes .split(',') .join(' ') """ modkit pileup \ "${alignment}" \ "${alias}.mods.bedmethyl.gz" \ ${modified_bases_arg} \ --reference "${reference}" \ --threads ${task.cpus} \ --bgzf """ } process modkit_tobigwig { label "modkit" cpus 4 memory "2 GB" input: tuple path(reference), path(reference_index) tuple val(alias), path(bedmethyl), val(mod_codes) path mod_code_labels output: tuple val(alias), path("${alias}.mods.*.bw"), emit: bigwig publishDir "${params.out_dir}/${output_key}/mods", mode: 'copy' script: output_key = alias == "cohort" ? "cohort" : "samples/${alias}" // nodef String mod_code_args = mod_codes .split(',') .join(' ') """ for mod_code in ${mod_code_args}; do mod_code_value="\${mod_code#*:}" mod_label=\$(mod_code_label "\${mod_code}" "${mod_code_labels}") zcat "${bedmethyl}" | \ modkit bedmethyl tobigwig \ --sizes "${reference_index}" \ --nthreads ${task.cpus} \ --mod-codes "\${mod_code_value}" \ - \ "${alias}.mods.\${mod_label}.bw" done """ } process summariseModkitBedmethyl { label "wf_common" cpus 1 memory "2 GB" input: tuple val(alias), path(bedmethyl), val(mod_codes) path mod_code_labels output: tuple val(alias), path("${alias}.mods.summary.tsv"), emit: summary publishDir "${params.out_dir}/${output_key}/mods", mode: 'copy' script: output_key = alias == "cohort" ? "cohort" : "samples/${alias}" // nodef """ workflow-glue summarise_modkit_bedmethyl \ "${bedmethyl}" \ "${alias}" \ "${mod_codes}" \ "${mod_code_labels}" \ "${alias}.mods.summary.tsv" """ } process inferModkitBases { label "modkit" cpus 1 memory "4 GB" input: tuple val(alias), val(meta), path(alignment), path(alignment_index), val(alignment_stats) output: tuple val(alias), env(mod_codes) script: """ modkit modbam check-tags "${alignment}" --num-reads 10000 --mapped-only --out-dir check_tags infer_modkit_codes check_tags/modified_bases.tsv > mod_codes.txt if [ ! -s mod_codes.txt ]; then echo "Failed to infer modified base codes from ${alignment}" >&2 exit 1 fi read -r mod_codes < mod_codes.txt """ } workflow mods { take: xams ref_genome main: xams.branch { nomods: it[0].has_modbase_tags != true return it[0].alias mods: it[0].has_modbase_tags == true return [it[0].alias] + it // prepend alias for joining }.set{xams_with} // warn for samples without mods xams_with.nomods.subscribe { log.warn "Input ${it} does not contain modified base tags. Was a modified basecalling model selected when basecalling this data?" } // determine what mods to ask modkit pileup for sample_modcodes = params.mod_codes ? xams_with.mods.map { [it[0], params.mod_codes.trim()] } // cross all aliases with user mod_codes : inferModkitBases(xams_with.mods) // otherwise infer per-sample from modbam mod_samples = xams_with.mods.join(sample_modcodes) pileup = runModkitPileup(mod_samples, ref_genome) sample_summaries = summariseModkitBedmethyl( pileup.bedmethyl.join(sample_modcodes), file("$projectDir/data/mod_code_labels.tsv") ) sample_bigwigs = modkit_tobigwig( ref_genome, pileup.bedmethyl.join(sample_modcodes), file("$projectDir/data/mod_code_labels.tsv") ) emit: bedmethyl = pileup.bedmethyl summary = sample_summaries.summary bigwig = sample_bigwigs.bigwig }