From 7340fce916bc8f39f6bd522db51c080b642be4cc Mon Sep 17 00:00:00 2001 From: Anthony Gagnon <anthony.gagnon7@usherbrooke.ca> Date: Thu, 9 Jan 2025 19:52:47 +0000 Subject: [PATCH 1/2] added required parameters specifying dti and fodf shells for more reproducibility --- conf/modules.config | 6 ++++++ nextflow.config | 2 ++ nextflow_schema.json | 20 ++++++++++++++++--- subworkflows/nf-neuro/preproc_t1/main.nf | 1 + .../nf-neuro/preproc_t1/preproc_t1.diff | 3 ++- workflows/pediatric.nf | 2 +- 6 files changed, 29 insertions(+), 5 deletions(-) diff --git a/conf/modules.config b/conf/modules.config index 331f68e..818c61e 100644 --- a/conf/modules.config +++ b/conf/modules.config @@ -356,6 +356,8 @@ process { withName: 'NF_PEDIATRIC:PEDIATRIC:PREPROC_DWI:NORMALIZE_DWI' { ext.fa_mask_threshold = params.dwi_normalize_fa_mask_threshold ext.dwi_shell_tolerance = params.dwi_normalize_shell_tolerance + ext.dti_shells = params.dti_shells + ext.max_dti_shell_value = params.dti_max_shell_value publishDir = [ path: { "${params.outdir}/${meta.id}/dwi/"}, mode: params.publish_dir_mode, @@ -458,6 +460,7 @@ process { ext.dwi_shell_tolerance = params.dti_shell_tolerance ext.max_dti_shell_value = params.dti_max_shell_value ext.b0_thr_extract_b0 = params.dti_b0_threshold + ext.dti_shells = params.dti_shells // ** DTI metrics to output ** // ext.ad = true @@ -502,6 +505,8 @@ process { ext.dwi_shell_tolerance = params.frf_dwi_shell_tolerance ext.max_dti_shell_value = params.frf_max_dti_shell_value ext.min_fodf_shell_value = params.frf_min_fodf_shell_value + ext.fodf_shells = params.fodf_shells + ext.dti_shells = params.dti_shells ext.b0_thr_extract_b0 = params.frf_b0_threshold ext.set_method = params.frf_set_method ext.set_frf = params.frf_set_frf @@ -522,6 +527,7 @@ process { withName: 'NF_PEDIATRIC:PEDIATRIC:RECONST_FODF' { ext.dwi_shell_tolerance = params.fodf_shell_tolerance ext.min_fodf_shell_value = params.fodf_min_fodf_shell_value + ext.fodf_shells = params.fodf_shells ext.b0_thr_extract_b0 = params.fodf_b0_threshold ext.sh_order = params.fodf_sh_order ext.sh_basis = params.fodf_sh_basis diff --git a/nextflow.config b/nextflow.config index dd302d2..651e167 100644 --- a/nextflow.config +++ b/nextflow.config @@ -103,6 +103,7 @@ params { dti_shell_tolerance = 50 dti_max_shell_value = 1500 dti_b0_threshold = 20 + dti_shells = null // FRF frf_fa = 0.7 @@ -121,6 +122,7 @@ params { // FODF Metrics fodf_shell_tolerance = 50 fodf_min_fodf_shell_value = 100 + fodf_shells = null fodf_b0_threshold = 20 fodf_sh_order = 8 fodf_sh_basis = "descoteaux07" diff --git a/nextflow_schema.json b/nextflow_schema.json index 0f666b7..1d20aab 100644 --- a/nextflow_schema.json +++ b/nextflow_schema.json @@ -406,6 +406,7 @@ "fa_icon": "fas fa-brain", "description": "Options for DTI processing.", "help_text": "These options are used to configure the DTI processing steps in the pipeline. You can use these options to customise the behaviour of the DTI processing steps.", + "required": ["dti_shells"], "properties": { "dti_shell_tolerance": { "type": "integer", @@ -419,7 +420,7 @@ "description": "Maximum shell value used in the DTI processing step.", "fa_icon": "fas fa-brain", "default": 1500, - "hidden": false + "hidden": true }, "dti_b0_threshold": { "type": "integer", @@ -427,6 +428,12 @@ "fa_icon": "fas fa-brain", "default": 20, "hidden": true + }, + "dti_shells": { + "type": "string", + "description": "Shells used in the DTI processing step.", + "fa_icon": "fas fa-brain", + "hidden": false } } }, @@ -477,14 +484,14 @@ "description": "Maximum DTI shell value used.", "fa_icon": "fas fa-brain", "default": 1500, - "hidden": false + "hidden": true }, "frf_min_fodf_shell_value": { "type": "integer", "description": "Minimum FODF shell value used.", "fa_icon": "fas fa-brain", "default": 100, - "hidden": false + "hidden": true }, "frf_b0_threshold": { "type": "integer", @@ -530,6 +537,7 @@ "fa_icon": "fas fa-brain", "description": "Options for FODF processing.", "help_text": "These options are used to configure the FODF processing steps in the pipeline. You can use these options to customise the behaviour of the FODF processing steps.", + "required": ["fodf_shells"], "properties": { "fodf_shell_tolerance": { "type": "integer", @@ -543,6 +551,12 @@ "description": "Minimum FODF shell value used.", "fa_icon": "fas fa-brain", "default": 100, + "hidden": true + }, + "fodf_shells": { + "type": "string", + "description": "Shells used in the FODF processing step.", + "fa_icon": "fas fa-brain", "hidden": false }, "fodf_b0_threshold": { diff --git a/subworkflows/nf-neuro/preproc_t1/main.nf b/subworkflows/nf-neuro/preproc_t1/main.nf index 5ca4ec9..a77c95b 100644 --- a/subworkflows/nf-neuro/preproc_t1/main.nf +++ b/subworkflows/nf-neuro/preproc_t1/main.nf @@ -92,6 +92,7 @@ workflow PREPROC_T1 { ch_bet = IMAGE_RESAMPLE.out.image .join(ch_template) .join(ch_probability_map) + .map{ it + [[], []] } BETCROP_ANTSBET ( ch_bet ) ch_versions = ch_versions.mix(BETCROP_ANTSBET.out.versions.first()) diff --git a/subworkflows/nf-neuro/preproc_t1/preproc_t1.diff b/subworkflows/nf-neuro/preproc_t1/preproc_t1.diff index dc38d6a..7e25254 100644 --- a/subworkflows/nf-neuro/preproc_t1/preproc_t1.diff +++ b/subworkflows/nf-neuro/preproc_t1/preproc_t1.diff @@ -3,7 +3,7 @@ Changes in component 'nf-neuro/preproc_t1' Changes in 'preproc_t1/main.nf': --- subworkflows/nf-neuro/preproc_t1/main.nf +++ subworkflows/nf-neuro/preproc_t1/main.nf -@@ -88,9 +88,10 @@ +@@ -88,9 +88,11 @@ // The template and probability maps are mandatory if running antsBET. Since the // error message from nextflow when they are absent is either non-informative or // missing, we use ifEmpty to provide a more informative one. @@ -13,6 +13,7 @@ Changes in 'preproc_t1/main.nf': - .join(ch_probability_map.ifEmpty{ error("ANTS BET needs a tissue probability map") }) + .join(ch_template) + .join(ch_probability_map) ++ .map{ it + [[], []] } BETCROP_ANTSBET ( ch_bet ) ch_versions = ch_versions.mix(BETCROP_ANTSBET.out.versions.first()) diff --git a/workflows/pediatric.nf b/workflows/pediatric.nf index 4935ce2..c3097be 100644 --- a/workflows/pediatric.nf +++ b/workflows/pediatric.nf @@ -126,7 +126,7 @@ workflow PEDIATRIC { ch_template = Channel.fromPath(params.t1_bet_template, checkIfExists: true) ch_probability_map = Channel.fromPath(params.t1_bet_template_probability_map, checkIfExists: true) - .map{ it + [[], []] } + if ( params.t1_synthstrip_weights ) { ch_t1_weights = Channel.fromPath(params.t1_synthstrip_weights, checkIfExists: false) } else { From 8b8e8ab8191b8cad472d6c5854e4155bcde1cf02 Mon Sep 17 00:00:00 2001 From: Anthony Gagnon <anthony.gagnon7@usherbrooke.ca> Date: Thu, 9 Jan 2025 23:19:33 +0000 Subject: [PATCH 2/2] move checkup to workflow, update docs, and tests --- CHANGELOG.md | 4 +++ docs/usage.md | 4 +-- nextflow_schema.json | 2 -- tests/chained.nf.test | 12 +++++++ tests/multisubjects.nf.test | 6 ++++ tests/tracking.nf.test | 66 +++++++++++++++++++++++++++++++++++++ workflows/pediatric.nf | 3 ++ 7 files changed, 93 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8090e47..c12516f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] - [2025-01-08] +### `Added` + +- Required --dti_shells and --fodf_shells parameters. + ### `Changed` - Fastsurfer and freesurfer outputs are now in their own dedicated output folder. diff --git a/docs/usage.md b/docs/usage.md index 0bc6748..80b91d3 100644 --- a/docs/usage.md +++ b/docs/usage.md @@ -122,10 +122,10 @@ An [example samplesheet](../assets/samplesheet.csv) has been provided with the p The typical command for running the pipeline is as follows: ```bash -nextflow run scilus/nf-pediatric -r main --input ./samplesheet.csv --outdir ./results -profile docker +nextflow run scilus/nf-pediatric -r main --input ./samplesheet.csv --outdir ./results --dti_shells "0 1000" --fodf_shells "0 1000" -profile docker ``` -This will launch the pipeline with the `docker` configuration profile. See below for more information about profiles. +This will launch the pipeline with the `docker` configuration profile. There is only 4 parameters that need to be supplied at runtime: `--input`: for the path to your samplesheet, `--oudir`: path to the output directory, `--dti_shells`: if the tracking profile is selected, you need to identify which shell to use for DTI fitting (0 and 1000 were selected in the previous example), and `--fodf_shells`: if the tracking profile is selected, specify your shells as for the DTI parameter. See below for more information about profiles. Note that the pipeline will create the following files in your working directory: diff --git a/nextflow_schema.json b/nextflow_schema.json index 1d20aab..5bfc7eb 100644 --- a/nextflow_schema.json +++ b/nextflow_schema.json @@ -406,7 +406,6 @@ "fa_icon": "fas fa-brain", "description": "Options for DTI processing.", "help_text": "These options are used to configure the DTI processing steps in the pipeline. You can use these options to customise the behaviour of the DTI processing steps.", - "required": ["dti_shells"], "properties": { "dti_shell_tolerance": { "type": "integer", @@ -537,7 +536,6 @@ "fa_icon": "fas fa-brain", "description": "Options for FODF processing.", "help_text": "These options are used to configure the FODF processing steps in the pipeline. You can use these options to customise the behaviour of the FODF processing steps.", - "required": ["fodf_shells"], "properties": { "fodf_shell_tolerance": { "type": "integer", diff --git a/tests/chained.nf.test b/tests/chained.nf.test index 899de03..91bba83 100644 --- a/tests/chained.nf.test +++ b/tests/chained.nf.test @@ -53,6 +53,9 @@ nextflow_pipeline { params.connectomics = true params.tracking = true + params.dti_shells = "0 1000" + params.fodf_shells = "0 1000" + } } @@ -85,6 +88,9 @@ nextflow_pipeline { params.tracking = true params.freesurfer = true + params.dti_shells = "0 1000" + params.fodf_shells = "0 1000" + params.use_fastsurfer = true params.fs_license = "https://www.dropbox.com/scl/fi/0s8lp6lydyd0rxawxb4jm/license.txt?rlkey=hz54oc0d4sor69avqphtrjvgn&st=9e0yij97&dl=0" } @@ -122,6 +128,9 @@ nextflow_pipeline { params.connectomics = true params.tracking = true + params.dti_shells = "0 1000" + params.fodf_shells = "0 1000" + } } @@ -164,6 +173,9 @@ nextflow_pipeline { params.local_min_len = 15 params.local_fa_seeding_mask_threshold = 0.10 + params.dti_shells = "0 1000" + params.fodf_shells = "0 1000" + } } diff --git a/tests/multisubjects.nf.test b/tests/multisubjects.nf.test index 8ba466d..bd68f63 100644 --- a/tests/multisubjects.nf.test +++ b/tests/multisubjects.nf.test @@ -14,6 +14,9 @@ nextflow_pipeline { params.outdir = "$outputDir" params.use_fastsurfer = true + params.dti_shells = "0 1000" + params.fodf_shells = "0 1000" + params.connectomics = true params.tracking = true params.freesurfer = true @@ -55,6 +58,9 @@ nextflow_pipeline { params.tracking = true params.infant = true + params.dti_shells = "0 1000" + params.fodf_shells = "0 1000" + // ** Infant specific parameters ** // params.dwi_run_synthstrip = true params.dwi_normalize_fa_mask_threshold = 0.10 diff --git a/tests/tracking.nf.test b/tests/tracking.nf.test index 2f38145..fcdec83 100644 --- a/tests/tracking.nf.test +++ b/tests/tracking.nf.test @@ -13,6 +13,9 @@ nextflow_pipeline { params.input = "$projectDir/tests/data/samplesheet_testtracking.csv" params.outdir = "$outputDir" + params.dti_shells = "0 1000" + params.fodf_shells = "0 1000" + params.tracking = true } @@ -43,6 +46,9 @@ nextflow_pipeline { params.input = "$projectDir/tests/data/samplesheet_testtracking.csv" params.outdir = "$outputDir" + params.dti_shells = "0 1000" + params.fodf_shells = "0 1000" + params.tracking = true params.skip_dwi_preprocessing = true @@ -76,6 +82,9 @@ nextflow_pipeline { params.tracking = true + params.dti_shells = "0 1000" + params.fodf_shells = "0 1000" + } } @@ -85,6 +94,48 @@ nextflow_pipeline { } } + test("Tracking profile no dti shells - should fail") { + + when { + params { + + params.input = "$projectDir/tests/data/samplesheet_testtracking_norev.csv" + params.outdir = "$outputDir" + + params.tracking = true + + params.fodf_shells = "0 1000" + + } + } + + then { + assert workflow.failed + assert workflow.stdout.contains("Please provide the DTI shells using --dti_shells parameter") + } + } + + test("Tracking profile no fodf shells - should fail") { + + when { + params { + + params.input = "$projectDir/tests/data/samplesheet_testtracking_norev.csv" + params.outdir = "$outputDir" + + params.tracking = true + + params.dti_shells = "0 1000" + + } + } + + then { + assert workflow.failed + assert workflow.stdout.contains("Please provide the FODF shells using --fodf_shells parameter") + } + } + test("Tracking profile no dwi - should fail") { when { @@ -93,6 +144,9 @@ nextflow_pipeline { params.input = "$projectDir/tests/data/samplesheet_testtracking_nodwi.csv" params.outdir = "$outputDir" + params.dti_shells = "0 1000" + params.fodf_shells = "0 1000" + params.tracking = true } @@ -126,6 +180,9 @@ nextflow_pipeline { params.local_fa_seeding_mask_threshold = 0.10 params.run_local_tracking = true + params.dti_shells = "0 1000" + params.fodf_shells = "0 1000" + } } @@ -167,6 +224,9 @@ nextflow_pipeline { params.local_min_len = 15 params.local_fa_seeding_mask_threshold = 0.10 + params.dti_shells = "0 1000" + params.fodf_shells = "0 1000" + } } @@ -187,6 +247,9 @@ nextflow_pipeline { params.tracking = true params.infant = true + params.dti_shells = "0 1000" + params.fodf_shells = "0 1000" + // ** Infant specific parameters ** // params.dwi_run_synthstrip = true params.dwi_normalize_fa_mask_threshold = 0.10 @@ -217,6 +280,9 @@ nextflow_pipeline { params.tracking = true params.infant = true + params.dti_shells = "0 1000" + params.fodf_shells = "0 1000" + // ** Infant specific parameters ** // params.dwi_run_synthstrip = true params.dwi_normalize_fa_mask_threshold = 0.10 diff --git a/workflows/pediatric.nf b/workflows/pediatric.nf index c3097be..02cfe42 100644 --- a/workflows/pediatric.nf +++ b/workflows/pediatric.nf @@ -152,6 +152,9 @@ workflow PEDIATRIC { // if ( params.tracking ) { + if ( !params.dti_shells ) { error "Please provide the DTI shells using --dti_shells parameter" } + if ( !params.fodf_shells ) { error "Please provide the FODF shells using --fodf_shells parameter" } + /* Load topup config if provided */ if ( params.dwi_susceptibility_config_file ) { if ( file(params.dwi_susceptibility_config_file).exists() ) {