Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 5 additions & 4 deletions conf/modules/preproc_dwi.config
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,8 @@ process {
withName: ".*:TRACTOFLOW:PREPROC_DWI:TOPUP_EDDY:PREPROC_TOPUP" {
ext.prefix_topup = params.prefix_topup
ext.default_config_topup = params.config_topup
ext.encoding = params.encoding_direction //FIXME : this is subject bound, pass through meta ?
ext.readout = params.readout //FIXME : this is subject bound, pass through meta ?
ext.encoding = params.encoding_direction
ext.readout = params.readout
ext.b0_thr_extract_b0 = params.b0_thr_extract_b0
}

Expand All @@ -46,8 +46,9 @@ process {
ext.dilate_b0_mask_prelim_brain_extraction = params.dilate_b0_mask_prelim_brain_extraction
ext.bet_prelim_f = params.bet_prelim_f
ext.b0_thr_extract_b0 = params.b0_thr_extract_b0
ext.encoding = params.encoding_direction //FIXME : this is subject bound, pass through meta ?
ext.readout = params.readout //FIXME : this is subject bound, pass through meta ?
ext.encoding = params.encoding_direction
ext.readout = params.readout
ext.extra_args = params.eddy_extra_args
ext.run_qc = true
publishDir = [
path: { meta.session ? "${params.outdir}/${meta.id}/${meta.session}/dwi/" : "${params.outdir}/${meta.id}/dwi/" },
Expand Down
10 changes: 5 additions & 5 deletions modules.json
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,7 @@
},
"preproc/eddy": {
"branch": "main",
"git_sha": "31193a9ea0839d2ce29898504812ffdb515b67dc",
"git_sha": "d8b76bf2572247daced80a770df4bd36204480c1",
"installed_by": ["topup_eddy"]
},
"preproc/gibbs": {
Expand All @@ -167,7 +167,7 @@
},
"preproc/topup": {
"branch": "main",
"git_sha": "cada787da3b1857454bcfbb49038d438b375b990",
"git_sha": "cd43a735aebf4742acb0186597917bbeb1da9860",
"installed_by": ["topup_eddy"]
},
"qc/multiqc": {
Expand Down Expand Up @@ -366,7 +366,7 @@
},
"preproc_dwi": {
"branch": "main",
"git_sha": "e08971ac9ff68fd7df4c52fa6a1bce1db8162a03",
"git_sha": "d50587b763e4dc6932b3f44e96688d5ff8f0d303",
"installed_by": ["tractoflow"]
},
"preproc_t1": {
Expand All @@ -386,12 +386,12 @@
},
"topup_eddy": {
"branch": "main",
"git_sha": "913afe95df67300a0e9434374a59b866449f277b",
"git_sha": "7755bea10e388c2f47412f99e383e41695662b21",
"installed_by": ["preproc_dwi"]
},
"tractoflow": {
"branch": "main",
"git_sha": "bd3302172e63f11c08db8ebb22f8653dfff21af7",
"git_sha": "d50587b763e4dc6932b3f44e96688d5ff8f0d303",
"installed_by": ["subworkflows"]
},
"tractometry": {
Expand Down
18 changes: 16 additions & 2 deletions modules/nf-neuro/preproc/eddy/main.nf
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ process PREPROC_EDDY {
tuple val(meta), path("*__dwi_eddy_corrected.bval") , emit: bval_corrected
tuple val(meta), path("*__dwi_eddy_corrected.bvec") , emit: bvec_corrected
tuple val(meta), path("*__b0_bet_mask.nii.gz") , emit: b0_mask
tuple val(meta), env("nan_percentage") , emit: nan_percentage
tuple val(meta), path("*__dwi_eddy_mqc.gif") , emit: dwi_eddy_mqc, optional:true
tuple val(meta), path("*__rev_dwi_eddy_mqc.gif") , emit: rev_dwi_eddy_mqc, optional:true
tuple val(meta), path("*__dwi_eddy_restricted_movement_rms.txt"), emit: eddy_fd_mqc, optional:true
Expand All @@ -26,8 +27,8 @@ process PREPROC_EDDY {
def bet_topup_before_eddy_f = task.ext.bet_topup_before_eddy_f ?: ""
def prefix_topup = task.ext.prefix_topup ? task.ext.prefix_topup : ""
def b0_thr_extract_b0 = task.ext.b0_thr_extract_b0 ? task.ext.b0_thr_extract_b0 : ""
def encoding = task.ext.encoding ? task.ext.encoding : ""
def readout = task.ext.readout ? task.ext.readout : ""
def encoding = meta.dir ?: (task.ext.encoding ?: "")
def readout = meta.readout ?: (task.ext.readout ?: "")
def dilate_b0_mask_prelim_brain_extraction = task.ext.dilate_b0_mask_prelim_brain_extraction ? task.ext.dilate_b0_mask_prelim_brain_extraction : ""
def eddy_cmd = task.ext.eddy_cmd ? task.ext.eddy_cmd : "eddy_cpu"
def bet_prelim_f = task.ext.bet_prelim_f ? task.ext.bet_prelim_f : ""
Expand All @@ -45,6 +46,8 @@ process PREPROC_EDDY {
export ANTS_RANDOM_SEED=${task.ext.ants_rng_seed ? task.ext.ants_rng_seed : "1234"}
export MRTRIX_RNG_SEED=${task.ext.mrtrix_rng_seed ? task.ext.mrtrix_rng_seed : "1234"}

nan_percentage=0

orig_bval=$bval
# Concatenate DWIs
number_rev_dwi=0
Expand Down Expand Up @@ -112,6 +115,16 @@ process PREPROC_EDDY {
# Rename framewise displacement file to include subject id
mv dwi_eddy_corrected.eddy_restricted_movement_rms ${prefix}__dwi_eddy_restricted_movement_rms.txt

nb_voxels=\$(mrstats ${prefix}__dwi_corrected.nii.gz -mask ${prefix}__b0_bet_mask.nii.gz -quiet -output count -allvolumes)
nb_nan=\$(mrcalc ${prefix}__dwi_corrected.nii.gz -isnan - | mrstats - -quiet -output count -ignorezero -allvolumes)
nan_percentage=\$(awk "BEGIN {print \${nb_nan} * 100 / \${nb_voxels}}")

if [[ \${nan_percentage} -gt 0 ]];
then
echo "Warning: \${nan_percentage}% of voxels in the brain mask are NaN after eddy correction."
mrcalc ${prefix}__dwi_corrected.nii.gz -finite ${prefix}__dwi_corrected.nii.gz 0.0 -if ${prefix}__dwi_corrected.nii.gz -force
fi

if $run_qc;
then
extract_dim=\$(mrinfo ${dwi} -size)
Expand Down Expand Up @@ -214,6 +227,7 @@ process PREPROC_EDDY {
touch ${prefix}__dwi_eddy_corrected.bvec
touch ${prefix}__b0_bet_mask.nii.gz
touch ${prefix}__dwi_eddy_restricted_movement_rms.txt
nan_percentage=1

cat <<-END_VERSIONS > versions.yml
"${task.process}":
Expand Down
10 changes: 10 additions & 0 deletions modules/nf-neuro/preproc/eddy/meta.yml
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,16 @@ output:
pattern: "*__b0_bet_mask.nii.gz"
ontologies:
- edam: http://edamontology.org/format_3989 # GZIP format
nan_percentage:
- - meta:
type: map
description: |
Groovy Map containing sample information
e.g. `[ id:'test', single_end:false ]`
- nan_percentage:
type: float
description: Percentage of NaN voxels in the brain mask after Eddy correction.
ontologies: []
dwi_eddy_mqc:
- - meta:
type: map
Expand Down
4 changes: 3 additions & 1 deletion modules/nf-neuro/preproc/eddy/tests/main.nf.test
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ nextflow_process {
"""
input[0] = LOAD_DATA.out.test_data_directory
.map{ test_data_directory -> [
[ id:'test', session:'ses-01' ], // meta map
[ id:'test', session:'ses-01', dir:'y', readout:0.062 ], // meta map
file("\${test_data_directory}/sub-01_dir-AP_dwi.nii.gz", checkIfExists: true),
file("\${test_data_directory}/sub-01_dir-AP_dwi.bval", checkIfExists: true),
file("\${test_data_directory}/sub-01_dir-AP_dwi.bvec", checkIfExists: true),
Expand All @@ -55,6 +55,7 @@ nextflow_process {
process.out.bval_corrected,
file(process.out.bvec_corrected.get(0).get(1)).name,
process.out.b0_mask,
process.out.nan_percentage,
file(process.out.dwi_eddy_mqc.get(0).get(1)).name,
file(process.out.rev_dwi_eddy_mqc.get(0).get(1)).name,
file(process.out.eddy_fd_mqc.get(0).get(1)).name,
Expand Down Expand Up @@ -91,6 +92,7 @@ nextflow_process {
process.out.bval_corrected,
file(process.out.bvec_corrected.get(0).get(1)).name,
process.out.b0_mask,
process.out.nan_percentage,
file(process.out.dwi_eddy_mqc.get(0).get(1)).name,
file(process.out.eddy_fd_mqc.get(0).get(1)).name,
process.out.versions
Expand Down
31 changes: 27 additions & 4 deletions modules/nf-neuro/preproc/eddy/tests/main.nf.test.snap
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,9 @@
[
{
"id": "test",
"session": "ses-01"
"session": "ses-01",
"dir": "y",
"readout": 0.062
},
"test_ses-01__dwi_eddy_corrected.bval:md5,4c61c53078316c31b4d5daf446a3d6ac"
]
Expand All @@ -16,11 +18,24 @@
[
{
"id": "test",
"session": "ses-01"
"session": "ses-01",
"dir": "y",
"readout": 0.062
},
"test_ses-01__b0_bet_mask.nii.gz:md5,884e1028fb86b5556e1caac18a8d6e1f"
]
],
[
[
{
"id": "test",
"session": "ses-01",
"dir": "y",
"readout": 0.062
},
"0"
]
],
"test_ses-01__dwi_eddy_mqc.gif",
"test_ses-01__rev_dwi_eddy_mqc.gif",
"test_ses-01__dwi_eddy_restricted_movement_rms.txt",
Expand All @@ -32,7 +47,7 @@
"nf-test": "0.9.3",
"nextflow": "25.10.2"
},
"timestamp": "2026-02-26T22:15:32.652065952"
"timestamp": "2026-05-05T11:37:36.006704402"
},
"eddy_light": {
"content": [
Expand All @@ -54,6 +69,14 @@
"test__b0_bet_mask.nii.gz:md5,884e1028fb86b5556e1caac18a8d6e1f"
]
],
[
[
{
"id": "test"
},
"0"
]
],
"test__dwi_eddy_mqc.gif",
"test__dwi_eddy_restricted_movement_rms.txt",
[
Expand All @@ -64,7 +87,7 @@
"nf-test": "0.9.3",
"nextflow": "25.10.2"
},
"timestamp": "2026-02-26T22:16:33.991059908"
"timestamp": "2026-05-05T11:39:42.9821212"
},
"eddy - stub-run": {
"content": [
Expand Down
4 changes: 2 additions & 2 deletions modules/nf-neuro/preproc/topup/main.nf
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,8 @@ process PREPROC_TOPUP {

def prefix_topup = task.ext.prefix_topup ?: ""
config_topup = config_topup ?: task.ext.default_config_topup
def encoding = task.ext.encoding ?: ""
def readout = task.ext.readout ?: ""
def encoding = meta.dir ?: (task.ext.encoding ?: "")
def readout = meta.readout ?: (task.ext.readout ?: "")
def b0_thr_extract_b0 = task.ext.b0_thr_extract_b0 ?: ""
def run_qc = task.ext.run_qc
def nthreads = task.ext.single_thread ? 1 : task.cpus
Expand Down
2 changes: 1 addition & 1 deletion modules/nf-neuro/preproc/topup/tests/main.nf.test
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ nextflow_process {
"""
input[0] = LOAD_DATA.out.test_data_directory
.map{ test_data_directory -> [
[ id:'test', single_end:false ], // meta map
[ id:'test', single_end:false, dir:'y', readout:0.062 ], // meta map
file("\${test_data_directory}/sub-01_dir-AP_dwi.nii.gz", checkIfExists: true),
file("\${test_data_directory}/sub-01_dir-AP_dwi.bval", checkIfExists: true),
file("\${test_data_directory}/sub-01_dir-AP_dwi.bvec", checkIfExists: true),
Expand Down
10 changes: 7 additions & 3 deletions modules/nf-neuro/preproc/topup/tests/main.nf.test.snap
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,9 @@
[
{
"id": "test",
"single_end": false
"single_end": false,
"dir": "y",
"readout": 0.062
},
"test__rev_b0_mean.nii.gz:md5,a0c63d7a8a234d85eeb63045ae2a8f60"
]
Expand All @@ -30,7 +32,9 @@
[
{
"id": "test",
"single_end": false
"single_end": false,
"dir": "y",
"readout": 0.062
},
"test__b0_mean.nii.gz:md5,f50e652bcdd1d45f7a4c592df7eb851a"
]
Expand All @@ -45,7 +49,7 @@
"nf-test": "0.9.3",
"nextflow": "25.10.2"
},
"timestamp": "2026-02-26T22:18:29.533803801"
"timestamp": "2026-05-05T07:41:24.661738077"
},
"topup - AP DWI | PA sbref": {
"content": [
Expand Down
6 changes: 6 additions & 0 deletions nextflow.config
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,8 @@ params {
bet_topup_before_eddy_f = 0.16
use_slice_drop_correction = true
bet_dwi_final_f = 0.16
eddy_nan_threshold = 0
eddy_extra_args = ""

//**DWI: N4 bias correction options**//
run_dwi_N4 = true
Expand Down Expand Up @@ -465,18 +467,22 @@ process.shell = [
nextflow.enable.configProcessNamesValidation = false

timeline {
overwrite = true
enabled = true
file = "${params.outdir}/pipeline_info/execution_timeline_${params.trace_report_suffix}.html"
}
report {
overwrite = true
enabled = true
file = "${params.outdir}/pipeline_info/execution_report_${params.trace_report_suffix}.html"
}
trace {
overwrite = true
enabled = true
file = "${params.outdir}/pipeline_info/execution_trace_${params.trace_report_suffix}.txt"
}
dag {
overwrite = true
enabled = true
file = "${params.outdir}/pipeline_info/pipeline_dag_${params.trace_report_suffix}.html"
}
Expand Down
7 changes: 7 additions & 0 deletions nextflow_schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -199,6 +199,13 @@
"help_text": "Run Gibbs correction.",
"default": true
},
"eddy_nan_threshold": {
"type": "number",
"default": 0,
"description": "Eddy nan threshold. If the number of voxels with NaN values after Eddy correction is above this threshold, the Eddy correction will be considered as failed and the uncorrected DWI will be used for the next steps.",
"help_text": "Eddy nan threshold. If the number of voxels with NaN values after Eddy correction is above this threshold, the Eddy correction will be considered as failed and the uncorrected DWI will be used for the next steps.",
"minimum": 0
},
"run_topup": {
"type": "boolean",
"default": true,
Expand Down
1 change: 1 addition & 0 deletions subworkflows/nf-neuro/preproc_dwi/main.nf
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,7 @@ workflow PREPROC_DWI {
ch_rev_b0,
ch_config_topup.ifEmpty( "b02b0.cnf" ),
[
"eddy_nan_threshold": options.eddy_nan_threshold,
"topup_eddy_run_topup": options.topup_eddy_run_topup,
"topup_eddy_run_eddy": options.topup_eddy_run_eddy
] )
Expand Down
4 changes: 4 additions & 0 deletions subworkflows/nf-neuro/preproc_dwi/meta.yml
Original file line number Diff line number Diff line change
Expand Up @@ -193,6 +193,10 @@ input:
type: boolean
description: Remove Gibbs artifacts using the mrdegibbs method from MRtrix3.
default: true
eddy_nan_threshold:
type: float
description: Threshold for the percentage of NaN voxels in the brain mask after Eddy correction to raise a warning.
default: 0
topup_eddy_run_topup:
type: boolean
description: Perform Topup correction using FSL's Topup.
Expand Down
1 change: 1 addition & 0 deletions subworkflows/nf-neuro/preproc_dwi/tests/main.nf.test
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ nextflow_workflow {
input[4] = channel.empty()
input[5] = channel.from( [] )
input[6] = [
"eddy_nan_threshold": 0,
"topup_eddy_run_topup": false,
"topup_eddy_run_eddy": false,
"preproc_dwi_run_denoising": false,
Expand Down
7 changes: 7 additions & 0 deletions subworkflows/nf-neuro/topup_eddy/main.nf
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,13 @@ workflow TOPUP_EDDY {

// ** RUN EDDY **//
PREPROC_EDDY ( ch_eddy_input )

PREPROC_EDDY.out.nan_percentage.subscribe { meta, nan_percentage ->
if (nan_percentage.toFloat() > options.eddy_nan_threshold) {
log.warn "Subject ${meta.id} has ${nan_percentage}% of voxels in the brain mask that are NaN after eddy correction."
}
}

ch_versions = ch_versions.mix(PREPROC_EDDY.out.versions.first())
ch_multiqc_files = ch_multiqc_files.mix(PREPROC_EDDY.out.dwi_eddy_mqc)
ch_multiqc_files = ch_multiqc_files.mix(PREPROC_EDDY.out.rev_dwi_eddy_mqc)
Expand Down
4 changes: 4 additions & 0 deletions subworkflows/nf-neuro/topup_eddy/meta.yml
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,10 @@ input:
description: Map of options for the topup_eddy subworkflow.
mandatory: false
entries:
eddy_nan_threshold:
type: integer
description: Threshold for the percentage of NaN voxels in the brain mask after Eddy correction to raise a warning.
default: 0
topup_eddy_run_topup:
type: boolean
description: Run FSL Topup for distorsion correction.
Expand Down
Loading
Loading