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/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/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.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..5bfc7eb 100644 --- a/nextflow_schema.json +++ b/nextflow_schema.json @@ -419,7 +419,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 +427,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 +483,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", @@ -543,6 +549,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/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 4935ce2..02cfe42 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 { @@ -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() ) {