From 1795bf88f1cb3bfa9e11578e49e99f103b0a3a38 Mon Sep 17 00:00:00 2001 From: Omer Ali Date: Wed, 3 Sep 2025 11:55:37 +0200 Subject: [PATCH 01/22] feat:adding metric module --- conf/modules.config | 8 ++++ modules/local/metrics/metrics.nf | 40 ++++++++++++++++++++ workflows/main.nf | 64 ++++++++++++++++++++++++++++---- 3 files changed, 104 insertions(+), 8 deletions(-) create mode 100644 modules/local/metrics/metrics.nf diff --git a/conf/modules.config b/conf/modules.config index 12e22b0..263d5e3 100644 --- a/conf/modules.config +++ b/conf/modules.config @@ -36,5 +36,13 @@ process { saveAs: { filename -> filename.equals('versions.yml') ? null : filename } ] } + withName:ALL_METRICS_PLOTTING { + ext.args = '--create_plots False' + publishDir = [ path: params.metrics_plotting_all_runs_output_directory, mode: 'copy', overwrite: true ] + } + withName:LAST_N_METRICS_PLOTTING { + ext.args = '' + publishDir = [ path: params.metrics_plotting_output_directory, mode: 'copy', overwrite: true ] + } } diff --git a/modules/local/metrics/metrics.nf b/modules/local/metrics/metrics.nf new file mode 100644 index 0000000..492511b --- /dev/null +++ b/modules/local/metrics/metrics.nf @@ -0,0 +1,40 @@ +process METRICS_PLOTTING { + tag "${run_ids.size()}_runs" + label 'process_low' + + container "${docker_image_id}" + containerOptions = "-v ${params.local_mounting_dir}:/inpred/data -v \$(pwd):/workdir" + + input: + val run_ids + val final_output_dir + val docker_image_id + output: + path "intermediate_metrics_files/master_metrics_table.tsv" , emit: 'tsv' + path "TSO500_run_metrics.pdf" , emit: 'pdf', optional: true + when: + task.ext.when == null || task.ext.when + + script: + def argument_list = run_ids.collect { run_id -> + "-m ${params.local_mounting_dir}/in/analysis_results/${run_id}_TSO_500_LocalApp_results/Results/MetricsOutput.tsv " + + "-r ${params.local_mounting_dir}/in/sequences/decoy_RunCompletionStatus.xml " + + "-l ${run_id}" + }.join(' ') + + """ + bash /inpred/user_scripts/process_metrics_files.sh \\ + ${argument_list} \\ + -o \$(pwd) \\ + -s ${params.local_mounting_dir} \\ + ${task.ext.args ?: ''} + + """ + + stub: + """ + mkdir -p ${final_output_dir} + touch ${final_output_dir}/TSO500_metrics_plots.pdf + touch ${final_output_dir}/master_metrics_table.tsv + """ +} diff --git a/workflows/main.nf b/workflows/main.nf index 912662f..1b499a9 100644 --- a/workflows/main.nf +++ b/workflows/main.nf @@ -4,14 +4,16 @@ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ -include { GATHER } from '../modules/local/local_app/local_app' -include { LOCAL_APP as LOCAL_APP_DEMULTIPLEX } from '../modules/local/local_app/local_app' -include { LOCAL_APP as LOCAL_APP_TSO500 } from '../modules/local/local_app/local_app' -include { LOCAL_APP_PREPPER } from '../modules/local/local_app_prepper/local_app_prepper' -include { paramsSummaryMap } from 'plugin/nf-schema' -include { samplesheetToList } from 'plugin/nf-schema' -include { softwareVersionsToYAML } from '../subworkflows/nf-core/utils_nfcore_pipeline' -include { validateParameters } from 'plugin/nf-schema' +include { GATHER } from '../modules/local/local_app/local_app' +include { LOCAL_APP as LOCAL_APP_DEMULTIPLEX } from '../modules/local/local_app/local_app' +include { LOCAL_APP as LOCAL_APP_TSO500 } from '../modules/local/local_app/local_app' +include { LOCAL_APP_PREPPER } from '../modules/local/local_app_prepper/local_app_prepper' +include { paramsSummaryMap } from 'plugin/nf-schema' +include { samplesheetToList } from 'plugin/nf-schema' +include { softwareVersionsToYAML } from '../subworkflows/nf-core/utils_nfcore_pipeline' +include { validateParameters } from 'plugin/nf-schema' +include { METRICS_PLOTTING as ALL_METRICS_PLOTTING } from '../modules/local/ous_metrics/ous_metrics.nf' +include { METRICS_PLOTTING as LAST_N_METRICS_PLOTTING } from '../modules/local/ous_metrics/ous_metrics.nf' /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -87,6 +89,49 @@ workflow MAIN { ) versions = versions.mix(GATHER.out.versions.first()) + // MODULE: Run metrics plotting workflow + // we will create a chennel to handle run Ids in a cleaner way + // we wi need metrics files, status files and run ids + def csv_file = file(params.mp_run_ids_csv_file) + if (!csv_file.exists()) { + exit 1, "Error: CSV file '${params.mp_run_ids_csv_file}' not found!" + } + + def mp_run_ids = csv_file.readLines() + .collect { it.trim().replaceAll('"','') } + .findAll { it } + + log.info "Total run IDs parsed: ${mp_run_ids.size()}" + + params.mp_run_ids = mp_run_ids + + // Ensure output directories exist + new File(params.metrics_plotting_all_runs_output_directory).mkdirs() + new File(params.metrics_plotting_output_directory).mkdirs() + + // Determine how many recent runs to plot + min_val = Math.min(params.n_runs, mp_run_ids.size()) + + if (min_val > 0) { + // All runs: no plots + ALL_METRICS_PLOTTING( + mp_run_ids, + params.metrics_plotting_all_runs_output_directory, + params.docker_image_id + ) + + // Last N runs: allow plots + def last_n_run_ids = mp_run_ids.subList(mp_run_ids.size() - min_val, mp_run_ids.size()) + + LAST_N_METRICS_PLOTTING( + last_n_run_ids, + params.metrics_plotting_output_directory, + params.docker_image_id + ) + } else { + log.info "No runs specified for metrics plotting." + } + // collate and save software versions softwareVersionsToYAML(versions) .collectFile( @@ -95,7 +140,10 @@ workflow MAIN { sort: true, newLine: true ).set { ch_collated_versions } + + + emit: versions = versions From 24c694fac44952a5be192ad9fb0090e4f745540f Mon Sep 17 00:00:00 2001 From: Omer Ali <79196757+Omer0191@users.noreply.github.com> Date: Tue, 9 Sep 2025 23:17:41 +0200 Subject: [PATCH 02/22] Update main.nf by changing header file ous_metrics folder in the header is change to metrics to make it more general --- workflows/main.nf | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/workflows/main.nf b/workflows/main.nf index 1b499a9..ac5eef7 100644 --- a/workflows/main.nf +++ b/workflows/main.nf @@ -12,8 +12,8 @@ include { paramsSummaryMap } from 'plugin/nf-schema' include { samplesheetToList } from 'plugin/nf-schema' include { softwareVersionsToYAML } from '../subworkflows/nf-core/utils_nfcore_pipeline' include { validateParameters } from 'plugin/nf-schema' -include { METRICS_PLOTTING as ALL_METRICS_PLOTTING } from '../modules/local/ous_metrics/ous_metrics.nf' -include { METRICS_PLOTTING as LAST_N_METRICS_PLOTTING } from '../modules/local/ous_metrics/ous_metrics.nf' +include { METRICS_PLOTTING as ALL_METRICS_PLOTTING } from '../modules/local/metrics/metrics.nf' +include { METRICS_PLOTTING as LAST_N_METRICS_PLOTTING } from '../modules/local/metrics/metrics.nf' /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ From 16a84459d1d7a2cca2c1d189e4eb2b74a6d01bab Mon Sep 17 00:00:00 2001 From: Martin Rippin Date: Mon, 22 Sep 2025 12:44:30 +0200 Subject: [PATCH 03/22] feat: change input channel, rm hard-coded paths, set specific image --- modules/local/metrics/metrics.nf | 37 ++++++++++++++------------------ 1 file changed, 16 insertions(+), 21 deletions(-) diff --git a/modules/local/metrics/metrics.nf b/modules/local/metrics/metrics.nf index 492511b..488b254 100644 --- a/modules/local/metrics/metrics.nf +++ b/modules/local/metrics/metrics.nf @@ -1,40 +1,35 @@ process METRICS_PLOTTING { - tag "${run_ids.size()}_runs" + tag "${id.size()}_runs" label 'process_low' - container "${docker_image_id}" - containerOptions = "-v ${params.local_mounting_dir}:/inpred/data -v \$(pwd):/workdir" + container "inpred/tsoppi_main:latest" // is this version v0.3.2? + containerOptions = "-v \$(pwd):/workdir" input: - val run_ids - val final_output_dir - val docker_image_id + tuple val(id), path(tsv, stageAs: "?/*"), path(xml, stageAs: "?/*") // stage file with index as folder name + output: - path "intermediate_metrics_files/master_metrics_table.tsv" , emit: 'tsv' + path "intermediate_metrics_files/master_metrics_table.tsv", emit: 'tsv' path "TSO500_run_metrics.pdf" , emit: 'pdf', optional: true + when: task.ext.when == null || task.ext.when script: - def argument_list = run_ids.collect { run_id -> - "-m ${params.local_mounting_dir}/in/analysis_results/${run_id}_TSO_500_LocalApp_results/Results/MetricsOutput.tsv " + - "-r ${params.local_mounting_dir}/in/sequences/decoy_RunCompletionStatus.xml " + - "-l ${run_id}" - }.join(' ') - + def args = task.ext.args ?: '' + for (int i = 0; i < id.size(); i++) { + args = args + " -m ${tsv[i]} -r ${xml[i]} -l ${id[i]}" + } """ bash /inpred/user_scripts/process_metrics_files.sh \\ - ${argument_list} \\ - -o \$(pwd) \\ - -s ${params.local_mounting_dir} \\ - ${task.ext.args ?: ''} - + --output_directory \$(pwd) \\ + --host_system_mounting_directory \$(pwd) \\ + $args """ stub: """ - mkdir -p ${final_output_dir} - touch ${final_output_dir}/TSO500_metrics_plots.pdf - touch ${final_output_dir}/master_metrics_table.tsv + mkdir intermediate_metrics_files + touch TSO500_run_metrics.pdf intermediate_metrics_files/master_metrics_table.tsv """ } From fdb92780506458af614eb6393a213cee121f6800 Mon Sep 17 00:00:00 2001 From: Martin Rippin Date: Mon, 22 Sep 2025 12:48:00 +0200 Subject: [PATCH 04/22] feat: add new workflow parameters and set stub defaults --- conf/modules.config | 8 ++++---- conf/test_stub.config | 11 ++++++++--- nextflow.config | 9 +++++++-- nextflow_schema.json | 38 ++++++++++++++++++++++++++++++++++++++ 4 files changed, 57 insertions(+), 9 deletions(-) diff --git a/conf/modules.config b/conf/modules.config index 263d5e3..0a3068a 100644 --- a/conf/modules.config +++ b/conf/modules.config @@ -36,13 +36,13 @@ process { saveAs: { filename -> filename.equals('versions.yml') ? null : filename } ] } - withName:ALL_METRICS_PLOTTING { + withName:ALL_METRICS_PLOTTING { ext.args = '--create_plots False' - publishDir = [ path: params.metrics_plotting_all_runs_output_directory, mode: 'copy', overwrite: true ] + publishDir = [ path: params.metrics_plotting_all_runs_output_dir, mode: 'copy', overwrite: true ] } - withName:LAST_N_METRICS_PLOTTING { + withName:LAST_N_METRICS_PLOTTING { ext.args = '' - publishDir = [ path: params.metrics_plotting_output_directory, mode: 'copy', overwrite: true ] + publishDir = [ path: params.metrics_plotting_n_runs_output_dir, mode: 'copy', overwrite: true ] } } diff --git a/conf/test_stub.config b/conf/test_stub.config index 429b4f4..2092027 100644 --- a/conf/test_stub.config +++ b/conf/test_stub.config @@ -23,7 +23,12 @@ params { config_profile_description = 'Simply stubbing the tasks in the pipeline instead of running them' // Input data - input = 'assets/example.samplesheet.csv' - outdir = 'test_stub' - tso500_resource_folder = 'assets/example.tso500_resource_folder' + input = 'assets/example.samplesheet.csv' + outdir = 'test_stub' + tso500_resource_folder = 'assets/example.tso500_resource_folder' + localapp_root_output_dir = 'assets' + //decoy_run_completion_status_xml = 'assets/decoy_RunCompletionStatus.xml' + seq_data_root_output_dir = 'assets' + metrics_plotting_all_runs_output_dir = 'test_stub/metrics_plotting_all_runs' + metrics_plotting_n_runs_output_dir = 'test_stub/metrics_plotting_n_runs' } diff --git a/nextflow.config b/nextflow.config index 24f5d86..140c560 100644 --- a/nextflow.config +++ b/nextflow.config @@ -10,8 +10,13 @@ params { // Input options - input = null - tso500_resource_folder = null + input = null + tso500_resource_folder = null + localapp_root_output_dir = null + decoy_run_completion_status_xml = null + seq_data_root_output_dir = null + metrics_plotting_all_runs_output_dir = null + metrics_plotting_n_runs_output_dir = null // Boilerplate options outdir = null diff --git a/nextflow_schema.json b/nextflow_schema.json index fcbeeaf..30361bf 100644 --- a/nextflow_schema.json +++ b/nextflow_schema.json @@ -29,6 +29,18 @@ "description": "The output directory where the results will be saved. You have to use absolute paths to storage on Cloud infrastructure.", "fa_icon": "fas fa-folder-open" }, + "metrics_plotting_all_runs_output_dir": { + "type": "string", + "format": "directory-path", + "description": "The output directory where the results will be saved. You have to use absolute paths to storage on Cloud infrastructure.", + "fa_icon": "fas fa-folder-open" + }, + "metrics_plotting_n_runs_output_dir": { + "type": "string", + "format": "directory-path", + "description": "The output directory where the results will be saved. You have to use absolute paths to storage on Cloud infrastructure.", + "fa_icon": "fas fa-folder-open" + }, "tso500_resource_folder": { "type": "string", "format": "directory-path", @@ -36,6 +48,32 @@ "description": "Path to directory where all reference files, required by the TSO500 LocalApp, are stored.", "help_text": "The resource directory is usually obtained together with the LocalApp image.", "fa_icon": "fas fa-folder-open" + }, + "localapp_root_output_dir": { + "type": "string", + "format": "directory-path", + "exists": true, + "description": "Path to root directory where all TSO500 LocalApp results are stored.", + "help_text": "The root directory is usually contains all run results generated by LocalApp (all dirs called _LocalApp should be contained, might even be subdirectories).", + "fa_icon": "fas fa-folder-open" + }, + "decoy_run_completion_status_xml": { + "type": "string", + "format": "file-path", + "exists": true, + "mimetype": "text/xml", + "pattern": "RunCompletionStatus.xml$", + "description": "Path to xml file containing acting as decoy if sequencing was done on NovaSeq.", + "help_text": "The decoy file can be used for any run that did not produce a RunCompletionStatus.xml.", + "fa_icon": "fas fa-file-xml" + }, + "seq_data_root_output_dir": { + "type": "string", + "format": "directory-path", + "exists": true, + "description": "Path to root directory where all TSO500 sequencing data results are stored.", + "help_text": "The root directory is usually contains all results generated by the sequencing runs.", + "fa_icon": "fas fa-folder-open" } } }, From 84f64e3ee0af0662d587ab01172d21354e300bd3 Mon Sep 17 00:00:00 2001 From: Martin Rippin Date: Mon, 22 Sep 2025 12:49:31 +0200 Subject: [PATCH 05/22] feat: add metrics module to workflow and construct input channel --- workflows/main.nf | 82 +++++++++++++++++++++++------------------------ 1 file changed, 40 insertions(+), 42 deletions(-) diff --git a/workflows/main.nf b/workflows/main.nf index 1b499a9..6b57ff7 100644 --- a/workflows/main.nf +++ b/workflows/main.nf @@ -12,8 +12,8 @@ include { paramsSummaryMap } from 'plugin/nf-schema' include { samplesheetToList } from 'plugin/nf-schema' include { softwareVersionsToYAML } from '../subworkflows/nf-core/utils_nfcore_pipeline' include { validateParameters } from 'plugin/nf-schema' -include { METRICS_PLOTTING as ALL_METRICS_PLOTTING } from '../modules/local/ous_metrics/ous_metrics.nf' -include { METRICS_PLOTTING as LAST_N_METRICS_PLOTTING } from '../modules/local/ous_metrics/ous_metrics.nf' +include { METRICS_PLOTTING as ALL_METRICS_PLOTTING } from '../modules/local/metrics/metrics.nf' +include { METRICS_PLOTTING as LAST_N_METRICS_PLOTTING } from '../modules/local/metrics/metrics.nf' /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -89,48 +89,50 @@ workflow MAIN { ) versions = versions.mix(GATHER.out.versions.first()) - // MODULE: Run metrics plotting workflow - // we will create a chennel to handle run Ids in a cleaner way - // we wi need metrics files, status files and run ids - def csv_file = file(params.mp_run_ids_csv_file) - if (!csv_file.exists()) { - exit 1, "Error: CSV file '${params.mp_run_ids_csv_file}' not found!" + // glob all MetricsOutput.tsv files and join with RunCompletionStatus.xml files for process_metrics_files + metrics_output_tsv = channel.fromPath("${params.localapp_root_output_dir}/**_LocalApp_results/Results/MetricsOutput.tsv") // Channel: [ tsv ] + .map { file -> + def run_id = (file.toString() =~ /(\d{6}_\D{1,3}\d{5,6}(_RUO)?_\d{4}_\w{10})(_TSO_500)?_LocalApp_results/)[0][1] + return [ run_id, file ] + } // Channel: [ [ run_id, tsv ] ] + if (params.decoy_run_completion_status_xml) { + metrics_input_ch = metrics_output_tsv + .map { run_id, file -> + return [ run_id, file, params.decoy_run_completion_status_xml ] + } // Channel: [ [ run_id, tsv, xml ] ] + .collect(flat: false) // Channel: [ [ [ run_id, tsv, xml ], [ run_id, tsv, xml ], ... ] ] + .transpose() // Channel: [ [ run_id, run_id, ... ], [ tsv, tsv, ... ], [ xml, xml, ... ] ] + } else { + run_completion_status_xml = channel.fromPath("${params.seq_data_root_output_dir}/*/RunCompletionStatus.xml") + .map { file -> + def run_id = (file.toString() =~ /(\d{6}_\D{1,3}\d{5,6}(_RUO)?_\d{4}_\w{10})/)[0][1] + return [ run_id, file ] + } // Channel: [ [ run_id, xml ] ] + metrics_input_ch = metrics_output_tsv.join(run_completion_status_xml) + .view() + .collect(flat: false) + .transpose() + .collect(flat: false) } - def mp_run_ids = csv_file.readLines() - .collect { it.trim().replaceAll('"','') } - .findAll { it } - - log.info "Total run IDs parsed: ${mp_run_ids.size()}" + // MODULE: Run metrics plotting + ALL_METRICS_PLOTTING(metrics_input_ch) - params.mp_run_ids = mp_run_ids + //// Determine how many recent runs to plot + //min_val = Math.min(params.n_runs, mp_run_ids.size()) - // Ensure output directories exist - new File(params.metrics_plotting_all_runs_output_directory).mkdirs() - new File(params.metrics_plotting_output_directory).mkdirs() + //if (min_val > 0) { + // // All runs: no plots + // ALL_METRICS_PLOTTING( + // mp_run_ids, + // ) - // Determine how many recent runs to plot - min_val = Math.min(params.n_runs, mp_run_ids.size()) + // // Last N runs: allow plots + // def last_n_run_ids = mp_run_ids.subList(mp_run_ids.size() - min_val, mp_run_ids.size()) - if (min_val > 0) { - // All runs: no plots - ALL_METRICS_PLOTTING( - mp_run_ids, - params.metrics_plotting_all_runs_output_directory, - params.docker_image_id - ) - - // Last N runs: allow plots - def last_n_run_ids = mp_run_ids.subList(mp_run_ids.size() - min_val, mp_run_ids.size()) - - LAST_N_METRICS_PLOTTING( - last_n_run_ids, - params.metrics_plotting_output_directory, - params.docker_image_id - ) - } else { - log.info "No runs specified for metrics plotting." - } + // LAST_N_METRICS_PLOTTING( + // last_n_run_ids, + // ) // collate and save software versions softwareVersionsToYAML(versions) @@ -140,10 +142,6 @@ workflow MAIN { sort: true, newLine: true ).set { ch_collated_versions } - - - - emit: versions = versions From bafe432e2689895a977f79b1a7cc13bf510f5a5a Mon Sep 17 00:00:00 2001 From: Martin Rippin Date: Mon, 22 Sep 2025 15:35:03 +0200 Subject: [PATCH 06/22] feat: rename nf file to main.nf and use specific version --- .../local_app_prepper/{local_app_prepper.nf => main.nf} | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) rename modules/local/local_app_prepper/{local_app_prepper.nf => main.nf} (92%) diff --git a/modules/local/local_app_prepper/local_app_prepper.nf b/modules/local/local_app_prepper/main.nf similarity index 92% rename from modules/local/local_app_prepper/local_app_prepper.nf rename to modules/local/local_app_prepper/main.nf index 4e3b05e..867e4ba 100644 --- a/modules/local/local_app_prepper/local_app_prepper.nf +++ b/modules/local/local_app_prepper/main.nf @@ -2,7 +2,7 @@ process LOCAL_APP_PREPPER { tag "$id" label 'process_low' - container "inpred/local_app_prepper:latest" + container "inpred/local_app_prepper:1.0.0" input: tuple val(id), path(runfolder), val(sample_list) @@ -25,7 +25,7 @@ process LOCAL_APP_PREPPER { cat <<-END_VERSIONS > versions.yml "${task.process}": - local_app_prepper: latest + local_app_prepper: 1.0.0 python: \$(python --version | sed 's/Python //g') END_VERSIONS """ @@ -33,6 +33,7 @@ process LOCAL_APP_PREPPER { stub: """ touch demultiplex.json gather.json tso500_IPH0001-D01-T01-A1.json tso500_IPH0001-D01-N01-A1.json + cat <<-END_VERSIONS > versions.yml "${task.process}": local_app_prepper: stub From 1a0d5dc8af2615dc4a52fa807d3869fc9de1fee6 Mon Sep 17 00:00:00 2001 From: Martin Rippin Date: Mon, 22 Sep 2025 15:41:21 +0200 Subject: [PATCH 07/22] feat: local_app to acadia_500_wdl_workflow: rename nf file to main.nf --- .../local_app.nf => acadia_500_wdl_workflow/main.nf} | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) rename modules/local/{local_app/local_app.nf => acadia_500_wdl_workflow/main.nf} (98%) diff --git a/modules/local/local_app/local_app.nf b/modules/local/acadia_500_wdl_workflow/main.nf similarity index 98% rename from modules/local/local_app/local_app.nf rename to modules/local/acadia_500_wdl_workflow/main.nf index 5f3a91b..31e5abf 100644 --- a/modules/local/local_app/local_app.nf +++ b/modules/local/acadia_500_wdl_workflow/main.nf @@ -1,4 +1,4 @@ -process LOCAL_APP { +process TSO500_WORKFLOW { tag "$id" label 'process_medium' @@ -46,6 +46,7 @@ process LOCAL_APP { output = 'localapp_' + id """ mkdir $output + cat <<-END_VERSIONS > versions.yml "${task.process}": cromwell: stub @@ -55,7 +56,7 @@ process LOCAL_APP { """ } -process GATHER { +process GATHER_RESULTS_WORKFLOW { tag "$id" label 'process_medium' @@ -101,6 +102,7 @@ process GATHER { """ touch inputs.json mkdir cromwell-executions cromwell-workflow-logs Results + cat <<-END_VERSIONS > versions.yml "${task.process}": cromwell: stub From 2f0f6a66dd50dd34aebca402cb928b04b5ca3f90 Mon Sep 17 00:00:00 2001 From: Martin Rippin Date: Wed, 24 Sep 2025 13:51:34 +0200 Subject: [PATCH 08/22] feat: rename process_metrics_files and handle absolute path requirement --- modules/local/metrics/metrics.nf | 35 --------------- modules/local/process_metrics_files/main.nf | 48 +++++++++++++++++++++ 2 files changed, 48 insertions(+), 35 deletions(-) delete mode 100644 modules/local/metrics/metrics.nf create mode 100644 modules/local/process_metrics_files/main.nf diff --git a/modules/local/metrics/metrics.nf b/modules/local/metrics/metrics.nf deleted file mode 100644 index 488b254..0000000 --- a/modules/local/metrics/metrics.nf +++ /dev/null @@ -1,35 +0,0 @@ -process METRICS_PLOTTING { - tag "${id.size()}_runs" - label 'process_low' - - container "inpred/tsoppi_main:latest" // is this version v0.3.2? - containerOptions = "-v \$(pwd):/workdir" - - input: - tuple val(id), path(tsv, stageAs: "?/*"), path(xml, stageAs: "?/*") // stage file with index as folder name - - output: - path "intermediate_metrics_files/master_metrics_table.tsv", emit: 'tsv' - path "TSO500_run_metrics.pdf" , emit: 'pdf', optional: true - - when: - task.ext.when == null || task.ext.when - - script: - def args = task.ext.args ?: '' - for (int i = 0; i < id.size(); i++) { - args = args + " -m ${tsv[i]} -r ${xml[i]} -l ${id[i]}" - } - """ - bash /inpred/user_scripts/process_metrics_files.sh \\ - --output_directory \$(pwd) \\ - --host_system_mounting_directory \$(pwd) \\ - $args - """ - - stub: - """ - mkdir intermediate_metrics_files - touch TSO500_run_metrics.pdf intermediate_metrics_files/master_metrics_table.tsv - """ -} diff --git a/modules/local/process_metrics_files/main.nf b/modules/local/process_metrics_files/main.nf new file mode 100644 index 0000000..1000746 --- /dev/null +++ b/modules/local/process_metrics_files/main.nf @@ -0,0 +1,48 @@ +process PROCESS_METRICS_FILES { + tag "${id.size()}_runs" + label 'process_low' + + container "inpred/tsoppi_main:latest" // is this version v0.3.2? + containerOptions = "-v \$(pwd):/workdir -v \$(pwd):/inpred/data" + + input: + tuple val(id), path(tsv, stageAs: "?/*"), path(xml, stageAs: "?/*") // stage file with index as folder name + + output: + path "intermediate_metrics_files/master_metrics_table.tsv" , emit: 'tsv' + path "TSO500_run_metrics.pdf" , emit: 'pdf', optional: true + path 'versions.yml' , emit: versions + + when: + task.ext.when == null || task.ext.when + + script: + def args = task.ext.args ?: '' + for (int i = 0; i < id.size(); i++) { + args = args + " -m \$(pwd)/${tsv[i]} -r \$(pwd)/${xml[i]} -l ${id[i]}" // due to tsoppi container replacing absolute input mount paths we need to create absolute paths for staged files + } + """ + bash /inpred/user_scripts/process_metrics_files.sh \\ + --output_directory \$(pwd) \\ + --host_system_mounting_directory \$(pwd) \\ + $args + + cat <<-END_VERSIONS > versions.yml + "${task.process}": + process_metrics_files: \$(bash /inpred/user_scripts/process_metrics_files.sh --version | grep process_metrics_files.py | awk '{print \$2}') + python: \$(python --version | sed 's/Python //g') + END_VERSIONS + """ + + stub: + """ + mkdir intermediate_metrics_files + touch TSO500_run_metrics.pdf intermediate_metrics_files/master_metrics_table.tsv + + cat <<-END_VERSIONS > versions.yml + "${task.process}": + process_metrics_files: stub + python: stub + END_VERSIONS + """ +} From 6a655f6c6fb98bf5f6a48db8fc11e94743f7d4a0 Mon Sep 17 00:00:00 2001 From: Martin Rippin Date: Wed, 24 Sep 2025 15:01:39 +0200 Subject: [PATCH 09/22] feat: rename input to nxf_samplesheet --- assets/schema_input.json | 4 ++-- conf/test_stub.config | 2 +- main.nf | 4 ++-- nextflow.config | 9 +++---- nextflow_schema.json | 24 +++++++++---------- .../local/utils_nfcore_full_pipeline/main.nf | 6 ++--- 6 files changed, 25 insertions(+), 24 deletions(-) diff --git a/assets/schema_input.json b/assets/schema_input.json index 72a4d1d..b617efe 100644 --- a/assets/schema_input.json +++ b/assets/schema_input.json @@ -1,7 +1,7 @@ { "$schema": "https://json-schema.org/draft/2020-12/schema", - "title": "inpred/tso500_nxf_workflow - params.input schema", - "description": "Schema for the file provided with params.input (ideally a samplesheet)", + "title": "inpred/tso500_nxf_workflow - params.nxf_samplesheet schema", + "description": "Schema for the file provided with params.nxf_samplesheet", "type": "array", "items": { "type": "object", diff --git a/conf/test_stub.config b/conf/test_stub.config index 2092027..3eee7fc 100644 --- a/conf/test_stub.config +++ b/conf/test_stub.config @@ -23,7 +23,7 @@ params { config_profile_description = 'Simply stubbing the tasks in the pipeline instead of running them' // Input data - input = 'assets/example.samplesheet.csv' + nxf_samplesheet = 'assets/stub_data/nxf_samplesheet.csv' outdir = 'test_stub' tso500_resource_folder = 'assets/example.tso500_resource_folder' localapp_root_output_dir = 'assets' diff --git a/main.nf b/main.nf index d539f42..b6d675b 100644 --- a/main.nf +++ b/main.nf @@ -21,7 +21,7 @@ include { PIPELINE_COMPLETION } from './subworkflows/local/utils_nfcore_full workflow TSO500_PIPELINE { take: - samplesheet // channel: samplesheet read in from --input + samplesheet // channel: samplesheet read in from --nxf_samplesheet main: @@ -50,7 +50,7 @@ workflow { params.monochrome_logs, args, params.outdir, - params.input + params.nxf_samplesheet ) // diff --git a/nextflow.config b/nextflow.config index 140c560..ef91eb6 100644 --- a/nextflow.config +++ b/nextflow.config @@ -10,10 +10,11 @@ params { // Input options - input = null - tso500_resource_folder = null - localapp_root_output_dir = null decoy_run_completion_status_xml = null + nxf_samplesheet = null + process_metrics_files_n = 10 + tso500_resources_directory = null + localapp_root_output_dir = null seq_data_root_output_dir = null metrics_plotting_all_runs_output_dir = null metrics_plotting_n_runs_output_dir = null @@ -150,7 +151,7 @@ validation { monochromeLogs = params.monochrome_logs help { enabled = true - command = "nextflow run InPreD/tso500_nxf_workflow -profile --input samplesheet.csv --outdir " + command = "nextflow run InPreD/tso500_nxf_workflow -profile --nxf_samplesheet samplesheet.csv --outdir " fullParameter = "help_full" showHiddenParameter = "show_hidden" } diff --git a/nextflow_schema.json b/nextflow_schema.json index 30361bf..d360ffe 100644 --- a/nextflow_schema.json +++ b/nextflow_schema.json @@ -10,9 +10,19 @@ "type": "object", "fa_icon": "fas fa-terminal", "description": "Define where the pipeline should find input data and save output data.", - "required": ["input", "outdir", "tso500_resource_folder"], + "required": ["nxf_samplesheet", "process_metrics_files_n", "outdir", "tso500_resources_directory"], "properties": { - "input": { + "decoy_run_completion_status_xml": { + "type": "string", + "format": "file-path", + "exists": true, + "mimetype": "text/xml", + "pattern": "RunCompletionStatus.xml$", + "description": "Path to xml file containing acting as decoy if sequencing was done on NovaSeq.", + "help_text": "The decoy file can be used for any run that did not produce a RunCompletionStatus.xml.", + "fa_icon": "fas fa-file-xml" + }, + "nxf_samplesheet": { "type": "string", "format": "file-path", "exists": true, @@ -57,16 +67,6 @@ "help_text": "The root directory is usually contains all run results generated by LocalApp (all dirs called _LocalApp should be contained, might even be subdirectories).", "fa_icon": "fas fa-folder-open" }, - "decoy_run_completion_status_xml": { - "type": "string", - "format": "file-path", - "exists": true, - "mimetype": "text/xml", - "pattern": "RunCompletionStatus.xml$", - "description": "Path to xml file containing acting as decoy if sequencing was done on NovaSeq.", - "help_text": "The decoy file can be used for any run that did not produce a RunCompletionStatus.xml.", - "fa_icon": "fas fa-file-xml" - }, "seq_data_root_output_dir": { "type": "string", "format": "directory-path", diff --git a/subworkflows/local/utils_nfcore_full_pipeline/main.nf b/subworkflows/local/utils_nfcore_full_pipeline/main.nf index 6881361..67bf686 100644 --- a/subworkflows/local/utils_nfcore_full_pipeline/main.nf +++ b/subworkflows/local/utils_nfcore_full_pipeline/main.nf @@ -29,7 +29,7 @@ workflow PIPELINE_INITIALISATION { 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 + nxf_samplesheet // string: Path to input samplesheet main: @@ -62,11 +62,11 @@ workflow PIPELINE_INITIALISATION { ) // - // Create channel from input file provided through params.input + // Create channel from input file provided through params.nxf_samplesheet // Channel - .fromList(samplesheetToList(params.input, "${projectDir}/assets/schema_input.json")) + .fromList(samplesheetToList(params.nxf_samplesheet, "${projectDir}/assets/schema_input.json")) .set { ch_samplesheet } emit: From e525e24de32a38ae367842a673073861734152c8 Mon Sep 17 00:00:00 2001 From: Martin Rippin Date: Wed, 24 Sep 2025 15:52:33 +0200 Subject: [PATCH 10/22] feat: rename input variables to be more descriptive/consistent --- conf/test_stub.config | 16 +++++++------- nextflow.config | 16 +++++++------- nextflow_schema.json | 51 ++++++++++++++++++++++++++++--------------- 3 files changed, 49 insertions(+), 34 deletions(-) diff --git a/conf/test_stub.config b/conf/test_stub.config index 3eee7fc..9551fd5 100644 --- a/conf/test_stub.config +++ b/conf/test_stub.config @@ -23,12 +23,12 @@ params { config_profile_description = 'Simply stubbing the tasks in the pipeline instead of running them' // Input data - nxf_samplesheet = 'assets/stub_data/nxf_samplesheet.csv' - outdir = 'test_stub' - tso500_resource_folder = 'assets/example.tso500_resource_folder' - localapp_root_output_dir = 'assets' - //decoy_run_completion_status_xml = 'assets/decoy_RunCompletionStatus.xml' - seq_data_root_output_dir = 'assets' - metrics_plotting_all_runs_output_dir = 'test_stub/metrics_plotting_all_runs' - metrics_plotting_n_runs_output_dir = 'test_stub/metrics_plotting_n_runs' + //decoy_run_completion_status_xml = 'assets/stub_data/decoy_RunCompletionStatus.xml' + metrics_plots_all_output_directory = 'metrics_plots_NODE_all' + metrics_plots_latest_output_directory = 'metrics_plots_NODE_latest' + nxf_samplesheet = 'assets/stub_data/nxf_samplesheet.csv' + outdir = 'test_stub' + raw_data_root_directory = 'assets/stub_data/raw_data_root_directory' + tso500_resources_directory = 'assets/stub_data/resources' + tso500_root_output_directory = 'assets/stub_data/tso500_root_output_directory' } diff --git a/nextflow.config b/nextflow.config index ef91eb6..44157ae 100644 --- a/nextflow.config +++ b/nextflow.config @@ -10,14 +10,14 @@ params { // Input options - decoy_run_completion_status_xml = null - nxf_samplesheet = null - process_metrics_files_n = 10 - tso500_resources_directory = null - localapp_root_output_dir = null - seq_data_root_output_dir = null - metrics_plotting_all_runs_output_dir = null - metrics_plotting_n_runs_output_dir = null + decoy_run_completion_status_xml = null + metrics_plots_all_output_directory = null + metrics_plots_latest_output_directory = null + nxf_samplesheet = null + process_metrics_files_n = 10 + raw_data_root_directory = null + tso500_resources_directory = null + tso500_root_output_directory = null // Boilerplate options outdir = null diff --git a/nextflow_schema.json b/nextflow_schema.json index d360ffe..12ecfca 100644 --- a/nextflow_schema.json +++ b/nextflow_schema.json @@ -10,7 +10,16 @@ "type": "object", "fa_icon": "fas fa-terminal", "description": "Define where the pipeline should find input data and save output data.", - "required": ["nxf_samplesheet", "process_metrics_files_n", "outdir", "tso500_resources_directory"], + "required": [ + "metrics_plots_all_output_directory", + "metrics_plots_latest_output_directory", + "nxf_samplesheet", + "process_metrics_files_n", + "outdir", + "raw_data_root_directory", + "tso500_resources_directory", + "tso500_root_output_directory" + ], "properties": { "decoy_run_completion_status_xml": { "type": "string", @@ -22,6 +31,18 @@ "help_text": "The decoy file can be used for any run that did not produce a RunCompletionStatus.xml.", "fa_icon": "fas fa-file-xml" }, + "metrics_plots_all_output_directory": { + "type": "string", + "format": "directory-path", + "description": "The output directory where the results from process_metrics_files (all runs) should be saved", + "fa_icon": "fas fa-folder-open" + }, + "metrics_plots_latest_output_directory": { + "type": "string", + "format": "directory-path", + "description": "The output directory where the results from process_metrics_files (last n runs) should be saved", + "fa_icon": "fas fa-folder-open" + }, "nxf_samplesheet": { "type": "string", "format": "file-path", @@ -39,19 +60,21 @@ "description": "The output directory where the results will be saved. You have to use absolute paths to storage on Cloud infrastructure.", "fa_icon": "fas fa-folder-open" }, - "metrics_plotting_all_runs_output_dir": { - "type": "string", - "format": "directory-path", - "description": "The output directory where the results will be saved. You have to use absolute paths to storage on Cloud infrastructure.", - "fa_icon": "fas fa-folder-open" + "process_metrics_files_n": { + "type": "integer", + "description": "Number of sequencing runs to consider.", + "help_text": "Specify the number of sequencing runs to include.", + "fa_icon": "fas fa-hashtag" }, - "metrics_plotting_n_runs_output_dir": { + "raw_data_root_directory": { "type": "string", "format": "directory-path", - "description": "The output directory where the results will be saved. You have to use absolute paths to storage on Cloud infrastructure.", + "exists": true, + "description": "Path to root directory where all TSO500 sequencing data results are stored.", + "help_text": "The root directory is usually contains all results generated by the sequencing runs.", "fa_icon": "fas fa-folder-open" }, - "tso500_resource_folder": { + "tso500_resources_directory": { "type": "string", "format": "directory-path", "exists": true, @@ -59,21 +82,13 @@ "help_text": "The resource directory is usually obtained together with the LocalApp image.", "fa_icon": "fas fa-folder-open" }, - "localapp_root_output_dir": { + "tso500_root_output_directory": { "type": "string", "format": "directory-path", "exists": true, "description": "Path to root directory where all TSO500 LocalApp results are stored.", "help_text": "The root directory is usually contains all run results generated by LocalApp (all dirs called _LocalApp should be contained, might even be subdirectories).", "fa_icon": "fas fa-folder-open" - }, - "seq_data_root_output_dir": { - "type": "string", - "format": "directory-path", - "exists": true, - "description": "Path to root directory where all TSO500 sequencing data results are stored.", - "help_text": "The root directory is usually contains all results generated by the sequencing runs.", - "fa_icon": "fas fa-folder-open" } } }, From 5387b489adda5cd4d184f0bd0fc4e68cc321400f Mon Sep 17 00:00:00 2001 From: Martin Rippin Date: Wed, 24 Sep 2025 15:53:55 +0200 Subject: [PATCH 11/22] feat: improve formatting in modules.config and attempt to follow more realworld setup --- conf/modules.config | 40 ++++++++++++++++++++++++++++------------ 1 file changed, 28 insertions(+), 12 deletions(-) diff --git a/conf/modules.config b/conf/modules.config index 0a3068a..2c4d21b 100644 --- a/conf/modules.config +++ b/conf/modules.config @@ -17,32 +17,48 @@ process { mode: params.publish_dir_mode ] - withName: LOCAL_APP_DEMULTIPLEX { + withName: GATHER_RESULTS_WORKFLOW { publishDir = [ - enabled: false + path: { "${params.tso500_root_output_directory}/${id}_TSO_500_LocalApp_results" }, + mode: params.publish_dir_mode, + saveAs: { filename -> filename.equals('versions.yml') ? null : filename } ] } - withName: LOCAL_APP_TSO500 { + withName: LOCAL_APP_PREPPER { publishDir = [ - enabled: false + path: { "${params.tso500_root_output_directory}/${id}_pipeline_info" }, + mode: params.publish_dir_mode, + saveAs: { filename -> filename.equals('versions.yml') ? null : filename } ] } - withName: LOCAL_APP_PREPPER { + withName: PROCESS_METRICS_FILES_ALL { + ext.args = '--create_plots False' publishDir = [ - path: { "${params.outdir}/pipeline_info" }, + path: { "${params.tso500_root_output_directory}/${params.metrics_plots_all_output_directory}" }, mode: params.publish_dir_mode, saveAs: { filename -> filename.equals('versions.yml') ? null : filename } ] } - withName:ALL_METRICS_PLOTTING { - ext.args = '--create_plots False' - publishDir = [ path: params.metrics_plotting_all_runs_output_dir, mode: 'copy', overwrite: true ] + + withName: PROCESS_METRICS_FILES_N { + publishDir = [ + path: { "${params.tso500_root_output_directory}/${params.metrics_plots_latest_output_directory}" }, + mode: params.publish_dir_mode, + saveAs: { filename -> filename.equals('versions.yml') ? null : filename } + ] } - withName:LAST_N_METRICS_PLOTTING { - ext.args = '' - publishDir = [ path: params.metrics_plotting_n_runs_output_dir, mode: 'copy', overwrite: true ] + withName: TSO500_DEMULTIPLEX_WORKFLOW { + publishDir = [ + enabled: false + ] + } + + withName: TSO500_WORKFLOW { + publishDir = [ + enabled: false + ] } } From 10ca12c4ef09d0f1dcf8391b1b32bf41de4324f7 Mon Sep 17 00:00:00 2001 From: Martin Rippin Date: Wed, 24 Sep 2025 15:54:50 +0200 Subject: [PATCH 12/22] feat: replace old var names, improve channel logic, add metrics latest module call, add channel comments --- workflows/main.nf | 210 ++++++++++++++++++++++++++++------------------ 1 file changed, 127 insertions(+), 83 deletions(-) diff --git a/workflows/main.nf b/workflows/main.nf index 6b57ff7..5f641cc 100644 --- a/workflows/main.nf +++ b/workflows/main.nf @@ -4,16 +4,16 @@ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ -include { GATHER } from '../modules/local/local_app/local_app' -include { LOCAL_APP as LOCAL_APP_DEMULTIPLEX } from '../modules/local/local_app/local_app' -include { LOCAL_APP as LOCAL_APP_TSO500 } from '../modules/local/local_app/local_app' -include { LOCAL_APP_PREPPER } from '../modules/local/local_app_prepper/local_app_prepper' -include { paramsSummaryMap } from 'plugin/nf-schema' -include { samplesheetToList } from 'plugin/nf-schema' -include { softwareVersionsToYAML } from '../subworkflows/nf-core/utils_nfcore_pipeline' -include { validateParameters } from 'plugin/nf-schema' -include { METRICS_PLOTTING as ALL_METRICS_PLOTTING } from '../modules/local/metrics/metrics.nf' -include { METRICS_PLOTTING as LAST_N_METRICS_PLOTTING } from '../modules/local/metrics/metrics.nf' +include { GATHER_RESULTS_WORKFLOW } from '../modules/local/acadia_500_wdl_workflow/main' +include { TSO500_WORKFLOW as TSO500_WORKFLOW_DEMULTIPLEX } from '../modules/local/acadia_500_wdl_workflow/main' +include { TSO500_WORKFLOW } from '../modules/local/acadia_500_wdl_workflow/main' +include { LOCAL_APP_PREPPER } from '../modules/local/local_app_prepper/main' +include { PROCESS_METRICS_FILES as PROCESS_METRICS_FILES_ALL } from '../modules/local/process_metrics_files/main' +include { PROCESS_METRICS_FILES as PROCESS_METRICS_FILES_N } from '../modules/local/process_metrics_files/main' +include { softwareVersionsToYAML } from '../subworkflows/nf-core/utils_nfcore_pipeline' +include { paramsSummaryMap } from 'plugin/nf-schema' +include { samplesheetToList } from 'plugin/nf-schema' +include { validateParameters } from 'plugin/nf-schema' /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -31,108 +31,152 @@ workflow MAIN { // empty channel to store all software versions versions = Channel.empty() - // channel holding information about run id, path to the run folder and a list of sample ids - local_app_prepper_input = samplesheet - .map{ it -> return [ it[6], it[7], it[1] ] } - .groupTuple( by: [ 0, 1 ] ) + /* + MODULE: LocalApp prepper + */ - // channel holding information about run id, path to run folder and samplesheet - run_folders = samplesheet - .map{ it -> return [ it[6], it[7], it[8], [] ] } - .unique() + // prepare channel from samplesheet holding information about run id, path to the run folder and a list of sample ids + local_app_prepper_input = samplesheet // Channel: [ [ dataset_id, sample_id, molecule, sample_type, tumor_site, tumor_content, run_id, run, samplesheet, barcode ] ] + .map{ it -> return [ it[6], it[7], it[1] ] } // Channel: [ [ run_id, run, sample_id ] ] + .groupTuple( by: [ 0, 1 ] ) // Channel: [ [ run_id, run, [ sample_id, sample_id, ... ] ] ] - // MODULE: Prepare inputs.json for LocalApp + // run process LOCAL_APP_PREPPER ( local_app_prepper_input ) + + // add versions to versions channel versions = versions.mix(LOCAL_APP_PREPPER.out.versions.first()) + /* + MODULE: TSO500 demultiplex workflow (LocalApp) + */ + + // prepare channel from samplesheet holding information about run id, path to run folder and samplesheet + run_folders = samplesheet // Channel: [ [ dataset_id, sample_id, molecule, sample_type, tumor_site, tumor_content, run_id, run, samplesheet, barcode ] ] + .map{ it -> return [ it[6], it[7], it[8], [] ] } // Channel: [ [ run_id, run, samplesheet, [] ] ] + .unique() // Channel: [ [ run_id, run, samplesheet, [] ] ] + // attach the json to the correct run folder information - local_app_demultiplex_input = run_folders.join(LOCAL_APP_PREPPER.out.demultiplex) + tso500_workflow_demultiplex_input = run_folders // Channel: [ [ run_id, run, samplesheet, [] ] ] + .join(LOCAL_APP_PREPPER.out.demultiplex) // Channel: [ [ run_id, run, samplesheet, [], json ] ] - // MODULE: Run LocalApp demultiplex workflow - LOCAL_APP_DEMULTIPLEX ( - local_app_demultiplex_input, - file(params.tso500_resource_folder) + // run process + TSO500_WORKFLOW_DEMULTIPLEX ( + tso500_workflow_demultiplex_input, + file(params.tso500_resources_directory) ) - versions = versions.mix(LOCAL_APP_DEMULTIPLEX.out.versions.first()) - - // construct a channel for each sample - local_app_tso500_input = run_folders - .join(LOCAL_APP_DEMULTIPLEX.out.results) - .combine(LOCAL_APP_PREPPER.out.tso500.transpose(), by: 0) - .map{ it -> return [ get_sample_id(it[5]), it[1], it[2], it[4], it[5] ] } - - // MODULE: Run LocalApp TSO500 workflow - LOCAL_APP_TSO500 ( - local_app_tso500_input, - file(params.tso500_resource_folder) + + // add versions to versions channel + versions = versions.mix(TSO500_WORKFLOW_DEMULTIPLEX.out.versions.first()) + + /* + MODULE: TSO500 workflow (LocalApp) + */ + + // prepare channel for each sample + tso500_workflow_input = run_folders // Channel: [ [ run_id, run, samplesheet, [] ] ] + .join(TSO500_WORKFLOW_DEMULTIPLEX.out.results) // Channel: [ [ run_id, run, samplesheet, [], results ] ] + .combine(LOCAL_APP_PREPPER.out.tso500.transpose(), by: 0) // Channel: [ [ run_id, run, samplesheet, [], results, json ] ] + .map{ it -> return [ get_sample_id(it[5]), it[1], it[2], it[4], it[5] ] } // Channel: [ [ sample_id, run, samplesheet, results, json ] ] + + // run process + TSO500_WORKFLOW ( + tso500_workflow_input, + file(params.tso500_resources_directory) ) - versions = versions.mix(LOCAL_APP_TSO500.out.versions.first()) - - // merge all local app output folders in tuple and construct input channel for gather - gather_inputfolders = LOCAL_APP_PREPPER.out.tso500.transpose() - .map{ it -> return [ get_sample_id(it[1]), it[0] ] } - .join(LOCAL_APP_TSO500.out.results) - .map{ it -> return [ it[1], it[2] ] } - .concat(LOCAL_APP_DEMULTIPLEX.out.results) - .groupTuple() - gather_input = run_folders - .map{ it -> return [ it[0], it[1], it[2] ] } - .join(gather_inputfolders) - .join(LOCAL_APP_PREPPER.out.gather) - - // MODULE: Run LocalApp Gather workflow - GATHER ( - gather_input, - file(params.tso500_resource_folder) + + // add versions to versions channel + versions = versions.mix(TSO500_WORKFLOW.out.versions.first()) + + /* + MODULE: Gather results workflow (LocalApp) + */ + + // merge all LocalApp output directories in tuple + results_directories = LOCAL_APP_PREPPER.out.tso500 // Channel: [ run_id, [ json ] ] + .transpose() // Channel: [ [ run_id, json ] ] + .map{ it -> return [ get_sample_id(it[1]), it[0] ] } // Channel: [ [ sample_id, run_id ] ] + .join(TSO500_WORKFLOW.out.results) // Channel: [ [ sample_id, run_id, results ] ] + .map{ it -> return [ it[1], it[2] ] } // Channel: [ [ run_id, results ] ] + .concat(TSO500_WORKFLOW_DEMULTIPLEX.out.results) // Channel: [ [ run_id, results ] ] + .groupTuple() // Channel: [ [ run_id, [ results, results, ... ] ] ] + + // prepare channel holding run directories, results directories and gather json + gather_results_workflow_input = run_folders // Channel: [ [ run_id, run, samplesheet, [] ] ] + .map{ it -> return [ it[0], it[1], it[2] ] } // Channel: [ [ run_id, run, samplesheet ] ] + .join(results_directories) // Channel: [ [ run_id, run, samplesheet, [ results, results, ... ] ] ] + .join(LOCAL_APP_PREPPER.out.gather) // Channel: [ [ run_id, run, samplesheet, [ results, results, ... ], json ] ] + + // run process + GATHER_RESULTS_WORKFLOW ( + gather_results_workflow_input, + file(params.tso500_resources_directory) ) - versions = versions.mix(GATHER.out.versions.first()) - // glob all MetricsOutput.tsv files and join with RunCompletionStatus.xml files for process_metrics_files - metrics_output_tsv = channel.fromPath("${params.localapp_root_output_dir}/**_LocalApp_results/Results/MetricsOutput.tsv") // Channel: [ tsv ] + // add versions to versions channel + versions = versions.mix(GATHER_RESULTS_WORKFLOW.out.versions.first()) + + /* + MODULE: Process metrics files (All runs) + */ + + // gather all relevant MetricsOutput.tsv files + metrics_output_tsv = channel.fromPath("${params.tso500_root_output_directory}/**_LocalApp_results/Results/MetricsOutput.tsv") // Channel: [ tsv ] .map { file -> def run_id = (file.toString() =~ /(\d{6}_\D{1,3}\d{5,6}(_RUO)?_\d{4}_\w{10})(_TSO_500)?_LocalApp_results/)[0][1] return [ run_id, file ] } // Channel: [ [ run_id, tsv ] ] + + // join with (decoy) RunCompletionStatus.xml with MetricsOutput.tsv if (params.decoy_run_completion_status_xml) { - metrics_input_ch = metrics_output_tsv - .map { run_id, file -> - return [ run_id, file, params.decoy_run_completion_status_xml ] - } // Channel: [ [ run_id, tsv, xml ] ] - .collect(flat: false) // Channel: [ [ [ run_id, tsv, xml ], [ run_id, tsv, xml ], ... ] ] - .transpose() // Channel: [ [ run_id, run_id, ... ], [ tsv, tsv, ... ], [ xml, xml, ... ] ] + metrics_output_tsv_run_completion_status_xml = metrics_output_tsv // Channel: [ [ run_id, tsv ] ] + .map { run_id, file -> return [ run_id, file, params.decoy_run_completion_status_xml ] } // Channel: [ [ run_id, tsv, xml ] ] } else { - run_completion_status_xml = channel.fromPath("${params.seq_data_root_output_dir}/*/RunCompletionStatus.xml") + run_completion_status_xml = channel.fromPath("${params.raw_data_root_output_directory}/*/RunCompletionStatus.xml") // Channel: [ xml ] .map { file -> def run_id = (file.toString() =~ /(\d{6}_\D{1,3}\d{5,6}(_RUO)?_\d{4}_\w{10})/)[0][1] return [ run_id, file ] } // Channel: [ [ run_id, xml ] ] - metrics_input_ch = metrics_output_tsv.join(run_completion_status_xml) - .view() - .collect(flat: false) - .transpose() - .collect(flat: false) + metrics_output_tsv_run_completion_status_xml = metrics_output_tsv // Channel: [ [ run_id, tsv ] ] + .join(run_completion_status_xml) // Channel: [ [ run_id, tsv, xml ] ] } - // MODULE: Run metrics plotting - ALL_METRICS_PLOTTING(metrics_input_ch) + // sort MetricsOutput.tsv and RunCompletionStatus.xml by run_id descending + metrics_output_tsv_run_completion_status_xml_sorted = metrics_output_tsv_run_completion_status_xml + .toSortedList{ a, b -> b[0] <=> a[0] } // Channel: [ [ [ run_id, tsv, xml ], [ run_id, tsv, xml ], ... ] ] sorted by run_id descending + + // prepare channel holding list of run_ids, list of MetricsOutput.tsv files and list of RunCompletionStatus.xml files + process_metrics_files_all_input = metrics_output_tsv_run_completion_status_xml_sorted // Channel: [ [ run_id, tsv, xml ], [run_id, tsv, xml], ... ] + .transpose() // Channel: [ [ run_id, run_id, ... ], [ tsv, tsv, ... ], [ xml, xml, ... ] ] + .collect(flat: false) // Channel: [ [ [ run_id, run_id, ... ], [ tsv, tsv, ... ], [ xml, xml, ... ] ] ] - //// Determine how many recent runs to plot - //min_val = Math.min(params.n_runs, mp_run_ids.size()) + // run process + PROCESS_METRICS_FILES_ALL(process_metrics_files_all_input) - //if (min_val > 0) { - // // All runs: no plots - // ALL_METRICS_PLOTTING( - // mp_run_ids, - // ) + // add versions to versions channel + versions = versions.mix(PROCESS_METRICS_FILES_ALL.out.versions.first()) + + /* + MODULE: Process metrics files (Last N runs) + */ + + // calculate index in metrics tuples + idx = params.process_metrics_files_n - 1 + metrics_output_tsv.count().map{ it -> + if( it < params.process_metrics_files_n ) { + idx = it - 1 // the scope in here is weird as it is the same as in the next mapping function so idx is set correctly but printing idx outside will show the original value + } + } + // select last n runs + process_metrics_files_n_input = process_metrics_files_all_input // Channel: [ [ [ run_id, run_id, ... ], [ tsv, tsv, ... ], [ xml, xml, ... ] ] ] + .map { it -> return [ it[0][0..idx], it[1][0..idx], it[2][0..idx] ] } // Channel: [ [ [ run_id, run_id, ... ], [ tsv, tsv, ... ], [ xml, xml, ... ] ] ] select last n items - // // Last N runs: allow plots - // def last_n_run_ids = mp_run_ids.subList(mp_run_ids.size() - min_val, mp_run_ids.size()) + // run process + PROCESS_METRICS_FILES_N(process_metrics_files_n_input) - // LAST_N_METRICS_PLOTTING( - // last_n_run_ids, - // ) + // add versions to versions channel + versions = versions.mix(PROCESS_METRICS_FILES_N.out.versions.first()) // collate and save software versions softwareVersionsToYAML(versions) From 35b73bb4b53458a9e0068c188bc75930024583d3 Mon Sep 17 00:00:00 2001 From: Martin Rippin Date: Wed, 24 Sep 2025 15:55:47 +0200 Subject: [PATCH 13/22] test: add mock data for stubbing --- assets/example.samplesheet.csv | 3 --- .../.gitkeep => stub_data/decoy_RunCompletionStatus.xml} | 0 assets/stub_data/nxf_samplesheet.csv | 3 +++ .../200101_NS500643_0001_AHG5MGBGYM/RunCompletionStatus.xml} | 0 .../200102_NS500643_0002_AHG5MGBGYM/RunCompletionStatus.xml | 0 .../200103_NS500643_0003_AHG5MGBGYM/RunCompletionStatus.xml | 0 assets/stub_data/resources/.gitkeep | 0 .../Results/MetricsOutput.tsv | 0 .../Results/MetricsOutput.tsv | 0 9 files changed, 3 insertions(+), 3 deletions(-) delete mode 100644 assets/example.samplesheet.csv rename assets/{200501_NS500643_0793_AHG5MGBGYM/.gitkeep => stub_data/decoy_RunCompletionStatus.xml} (100%) create mode 100644 assets/stub_data/nxf_samplesheet.csv rename assets/{example.tso500_resource_folder/.gitkeep => stub_data/raw_data_root_directory/200101_NS500643_0001_AHG5MGBGYM/RunCompletionStatus.xml} (100%) create mode 100644 assets/stub_data/raw_data_root_directory/200102_NS500643_0002_AHG5MGBGYM/RunCompletionStatus.xml create mode 100644 assets/stub_data/raw_data_root_directory/200103_NS500643_0003_AHG5MGBGYM/RunCompletionStatus.xml create mode 100644 assets/stub_data/resources/.gitkeep create mode 100644 assets/stub_data/tso500_root_output_directory/200101_NS500643_0001_AHG5MGBGYM/200101_NS500643_0001_AHG5MGBGYM_LocalApp_results/Results/MetricsOutput.tsv create mode 100644 assets/stub_data/tso500_root_output_directory/200102_NS500643_0002_AHG5MGBGYM_TSO_500_LocalApp_results/Results/MetricsOutput.tsv diff --git a/assets/example.samplesheet.csv b/assets/example.samplesheet.csv deleted file mode 100644 index b21bc58..0000000 --- a/assets/example.samplesheet.csv +++ /dev/null @@ -1,3 +0,0 @@ -dataset_id,sample_id,molecule,sample_type,tumor_site,tumor_content,run_id,path_to_run,path_to_samplesheet,barcode -IPH0001,IPH0001-D01-T01-A19,dna,tumor,10,50,200501_NS500643_0793_AHG5MGBGYM,assets/200501_NS500643_0793_AHG5MGBGYM,,UDP0029 -IPH0001,IPH0001-D01-N01-A19,dna,normal,XX,0,200501_NS500643_0793_AHG5MGBGYM,assets/200501_NS500643_0793_AHG5MGBGYM,,UDP0030 diff --git a/assets/200501_NS500643_0793_AHG5MGBGYM/.gitkeep b/assets/stub_data/decoy_RunCompletionStatus.xml similarity index 100% rename from assets/200501_NS500643_0793_AHG5MGBGYM/.gitkeep rename to assets/stub_data/decoy_RunCompletionStatus.xml diff --git a/assets/stub_data/nxf_samplesheet.csv b/assets/stub_data/nxf_samplesheet.csv new file mode 100644 index 0000000..224d1d3 --- /dev/null +++ b/assets/stub_data/nxf_samplesheet.csv @@ -0,0 +1,3 @@ +dataset_id,sample_id,molecule,sample_type,tumor_site,tumor_content,run_id,path_to_run,path_to_samplesheet,barcode +IPH0001,IPH0001-D01-T01-A19,dna,tumor,10,50,200103_NS500643_0003_AHG5MGBGYM,assets/stub_data/raw_data_root_directory/200103_NS500643_0003_AHG5MGBGYM,,UDP0029 +IPH0001,IPH0001-D01-N01-A19,dna,normal,XX,0,200103_NS500643_0003_AHG5MGBGYM,assets/stub_data/raw_data_root_directory/200103_NS500643_0003_AHG5MGBGYM,,UDP0030 diff --git a/assets/example.tso500_resource_folder/.gitkeep b/assets/stub_data/raw_data_root_directory/200101_NS500643_0001_AHG5MGBGYM/RunCompletionStatus.xml similarity index 100% rename from assets/example.tso500_resource_folder/.gitkeep rename to assets/stub_data/raw_data_root_directory/200101_NS500643_0001_AHG5MGBGYM/RunCompletionStatus.xml diff --git a/assets/stub_data/raw_data_root_directory/200102_NS500643_0002_AHG5MGBGYM/RunCompletionStatus.xml b/assets/stub_data/raw_data_root_directory/200102_NS500643_0002_AHG5MGBGYM/RunCompletionStatus.xml new file mode 100644 index 0000000..e69de29 diff --git a/assets/stub_data/raw_data_root_directory/200103_NS500643_0003_AHG5MGBGYM/RunCompletionStatus.xml b/assets/stub_data/raw_data_root_directory/200103_NS500643_0003_AHG5MGBGYM/RunCompletionStatus.xml new file mode 100644 index 0000000..e69de29 diff --git a/assets/stub_data/resources/.gitkeep b/assets/stub_data/resources/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/assets/stub_data/tso500_root_output_directory/200101_NS500643_0001_AHG5MGBGYM/200101_NS500643_0001_AHG5MGBGYM_LocalApp_results/Results/MetricsOutput.tsv b/assets/stub_data/tso500_root_output_directory/200101_NS500643_0001_AHG5MGBGYM/200101_NS500643_0001_AHG5MGBGYM_LocalApp_results/Results/MetricsOutput.tsv new file mode 100644 index 0000000..e69de29 diff --git a/assets/stub_data/tso500_root_output_directory/200102_NS500643_0002_AHG5MGBGYM_TSO_500_LocalApp_results/Results/MetricsOutput.tsv b/assets/stub_data/tso500_root_output_directory/200102_NS500643_0002_AHG5MGBGYM_TSO_500_LocalApp_results/Results/MetricsOutput.tsv new file mode 100644 index 0000000..e69de29 From af2675611fffe2bbbf93b1f864a286d7ec9fbf3b Mon Sep 17 00:00:00 2001 From: Martin Rippin Date: Wed, 24 Sep 2025 15:59:25 +0200 Subject: [PATCH 14/22] chore: include new workflow output in gitignore --- .gitignore | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.gitignore b/.gitignore index deba4a3..d3a21ee 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,8 @@ .nextflow* +assets/stub_data/tso500_root_output_directory/200103_NS500643_0003_AHG5MGBGYM_pipeline_info +assets/stub_data/tso500_root_output_directory/200103_NS500643_0003_AHG5MGBGYM_TSO_500_LocalApp_results +assets/stub_data/tso500_root_output_directory/metrics_plots_NODE_all +assets/stub_data/tso500_root_output_directory/metrics_plots_NODE_latest nohup.out null test_stub From 96d25a5a3c51adb25c7c5b3007b1b52f43cc2c79 Mon Sep 17 00:00:00 2001 From: Martin Rippin Date: Wed, 24 Sep 2025 15:59:43 +0200 Subject: [PATCH 15/22] fix: correct raw_data_root_directory var name --- workflows/main.nf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/workflows/main.nf b/workflows/main.nf index 5f641cc..0fc6218 100644 --- a/workflows/main.nf +++ b/workflows/main.nf @@ -133,7 +133,7 @@ workflow MAIN { metrics_output_tsv_run_completion_status_xml = metrics_output_tsv // Channel: [ [ run_id, tsv ] ] .map { run_id, file -> return [ run_id, file, params.decoy_run_completion_status_xml ] } // Channel: [ [ run_id, tsv, xml ] ] } else { - run_completion_status_xml = channel.fromPath("${params.raw_data_root_output_directory}/*/RunCompletionStatus.xml") // Channel: [ xml ] + run_completion_status_xml = channel.fromPath("${params.raw_data_root_directory}/*/RunCompletionStatus.xml") // Channel: [ xml ] .map { file -> def run_id = (file.toString() =~ /(\d{6}_\D{1,3}\d{5,6}(_RUO)?_\d{4}_\w{10})/)[0][1] return [ run_id, file ] From c14122972b4aee9ba60bf2ce7a8f913d72be2156 Mon Sep 17 00:00:00 2001 From: Martin Rippin Date: Wed, 24 Sep 2025 16:01:06 +0200 Subject: [PATCH 16/22] chore: editorconfig linting --- modules/local/process_metrics_files/main.nf | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/modules/local/process_metrics_files/main.nf b/modules/local/process_metrics_files/main.nf index 1000746..b652186 100644 --- a/modules/local/process_metrics_files/main.nf +++ b/modules/local/process_metrics_files/main.nf @@ -23,9 +23,9 @@ process PROCESS_METRICS_FILES { } """ bash /inpred/user_scripts/process_metrics_files.sh \\ - --output_directory \$(pwd) \\ - --host_system_mounting_directory \$(pwd) \\ - $args + --output_directory \$(pwd) \\ + --host_system_mounting_directory \$(pwd) \\ + $args cat <<-END_VERSIONS > versions.yml "${task.process}": From 69bfbe9985781269c3e41683812ba7f73f065437 Mon Sep 17 00:00:00 2001 From: Martin Rippin Date: Wed, 24 Sep 2025 16:02:57 +0200 Subject: [PATCH 17/22] fix: use correct process name for TSO500_WORKFLOW_DEMULTIPLEX --- conf/modules.config | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/conf/modules.config b/conf/modules.config index 2c4d21b..c424d24 100644 --- a/conf/modules.config +++ b/conf/modules.config @@ -50,7 +50,7 @@ process { ] } - withName: TSO500_DEMULTIPLEX_WORKFLOW { + withName: TSO500_WORKFLOW_DEMULTIPLEX { publishDir = [ enabled: false ] From dae526b5e3d2ba035899822e364736db8291c0c4 Mon Sep 17 00:00:00 2001 From: Martin Rippin Date: Mon, 29 Sep 2025 09:38:04 +0200 Subject: [PATCH 18/22] feat: use version tag for TSOPPI image instead of latest --- modules/local/process_metrics_files/main.nf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/local/process_metrics_files/main.nf b/modules/local/process_metrics_files/main.nf index b652186..5c85e05 100644 --- a/modules/local/process_metrics_files/main.nf +++ b/modules/local/process_metrics_files/main.nf @@ -2,7 +2,7 @@ process PROCESS_METRICS_FILES { tag "${id.size()}_runs" label 'process_low' - container "inpred/tsoppi_main:latest" // is this version v0.3.2? + container "inpred/tsoppi_main:v0.3.2" containerOptions = "-v \$(pwd):/workdir -v \$(pwd):/inpred/data" input: From cd37890625aeac7f9c8ca524abd5c2d4e4c8f71a Mon Sep 17 00:00:00 2001 From: Martin Rippin Date: Mon, 29 Sep 2025 09:43:39 +0200 Subject: [PATCH 19/22] chore: update helptext for process_metrics_files_n --- nextflow_schema.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nextflow_schema.json b/nextflow_schema.json index 12ecfca..80e642c 100644 --- a/nextflow_schema.json +++ b/nextflow_schema.json @@ -63,7 +63,7 @@ "process_metrics_files_n": { "type": "integer", "description": "Number of sequencing runs to consider.", - "help_text": "Specify the number of sequencing runs to include.", + "help_text": "Specify the number of sequencing runs to include in plotting of the latest n metrics. For examples, process_metrics_files_n = 10 will create a pdf file containing metrics plotted for last 10 sequencing runs.", "fa_icon": "fas fa-hashtag" }, "raw_data_root_directory": { From 52da8380fbcb7a9003871dd521856fe6b99c17be Mon Sep 17 00:00:00 2001 From: Martin Rippin Date: Fri, 3 Oct 2025 14:26:16 +0200 Subject: [PATCH 20/22] chore: turn off schema_lint --- .nf-core.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.nf-core.yml b/.nf-core.yml index a44986f..16bd97d 100644 --- a/.nf-core.yml +++ b/.nf-core.yml @@ -59,6 +59,7 @@ lint: multiqc_config: false nextflow_config: false pipeline_name_conventions: false + schema_lint: false readme: - nextflow_badge From 549eb71d685699225abc23a3aee059c99294c77a Mon Sep 17 00:00:00 2001 From: jaimicore Date: Thu, 16 Oct 2025 10:41:51 +0200 Subject: [PATCH 21/22] fix: updated version taken from Omer branch --- .devcontainer/Dockerfile | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.devcontainer/Dockerfile b/.devcontainer/Dockerfile index 079bdb4..c95db53 100644 --- a/.devcontainer/Dockerfile +++ b/.devcontainer/Dockerfile @@ -17,7 +17,7 @@ RUN apt-get update \ && apt-get install -y --no-install-recommends \ fish=3.3.1+ds-3 \ fuse-overlayfs=1.7.1-1 \ - openssh-server=1:8.9p1-3ubuntu0.11 \ + openssh-server=1:8.9p1-3ubuntu0.13 \ silversearcher-ag=2.2.0+git20200805-1 \ && echo "LC_ALL=en_US.UTF-8" > /etc/default/locale \ && locale-gen en_US.UTF-8 \ @@ -25,8 +25,8 @@ RUN apt-get update \ && rm -Rf /usr/share/doc && rm -Rf /usr/share/man \ && rm -rf /var/lib/apt/lists/* # convert gitpod to local user -RUN groupmod -n ${USERNAME} -g ${USER_GID} gitpod \ - && usermod -md /home/${USERNAME} -l ${USERNAME} -u ${USER_UID} -s /usr/bin/fish -aG docker gitpod \ +RUN groupmod -n ${USERNAME} -g ${USER_GID:-1000} gitpod \ + && usermod -md /home/${USERNAME} -l ${USERNAME} -u ${USER_UID:-1000} -s /usr/bin/fish -aG docker gitpod \ && echo ${USERNAME} ALL=\(root\) NOPASSWD:ALL > /etc/sudoers.d/${USERNAME} \ && chmod 0440 /etc/sudoers.d/${USERNAME} \ && find / -uid 33333 -not -path "/proc/*" -exec chown ${USERNAME}:${USERNAME} {} + @@ -35,4 +35,4 @@ ENV HOME=/home/${USERNAME} \ USER ${USERNAME} RUN git config --global pull.rebase false \ && git config --global user.email "${MAIL}" \ - && git config --global user.name "${FULLNAME}" + && git config --global user.name "${FULLNAME}" \ No newline at end of file From 4fab7b05dcfae114b63174fbdb99ae3e68c3a3ce Mon Sep 17 00:00:00 2001 From: Jean-Marc Costanzi Date: Fri, 24 Apr 2026 16:11:46 +0200 Subject: [PATCH 22/22] feat: add_variant_summary nextflow module --- modules/local/add_variant_summary/main.nf | 44 +++++++++++++++++++++++ 1 file changed, 44 insertions(+) create mode 100644 modules/local/add_variant_summary/main.nf diff --git a/modules/local/add_variant_summary/main.nf b/modules/local/add_variant_summary/main.nf new file mode 100644 index 0000000..5646591 --- /dev/null +++ b/modules/local/add_variant_summary/main.nf @@ -0,0 +1,44 @@ +process ADD_VARIANT_SUMMARY { + tag "$run_id" + label 'process_low' + + container "inpred/tsoppi_main:v0.3.2" + containerOptions "-v \$(pwd):/inpred/data" + + input: + tuple val(run_id), path(analysis_results_dir) + + output: + path "${run_id}_variant_summary.tsv", emit: tsv + path 'versions.yml' , emit: versions + + when: + task.ext.when == null || task.ext.when + + script: + def args = task.ext.args ?: '' + """ + python ${params.user_scripts_dir}/summarize_run_variants.py \\ + -r \$(pwd)/${analysis_results_dir} \\ + -o \$(pwd)/${run_id}_variant_summary.tsv \\ + -s \$(pwd) \\ + $args + + cat <<-END_VERSIONS > versions.yml + "${task.process}": + summarize_run_variants: \$(python ${params.user_scripts_dir}/summarize_run_variants.py --version 2>&1 | grep -oP 'version \\K[0-9.:-]+' || echo "0.3.2:22-06-07") + python: \$(python --version | sed 's/Python //g') + END_VERSIONS + """ + + stub: + """ + touch ${run_id}_variant_summary.tsv + + cat <<-END_VERSIONS > versions.yml + "${task.process}": + summarize_run_variants: stub + python: stub + END_VERSIONS + """ +}