From dc0a3952ca9943f6c1c94ed9b8c3510062f3589f Mon Sep 17 00:00:00 2001 From: mblesac2 Date: Mon, 8 Nov 2021 14:54:18 +0000 Subject: [PATCH 01/16] Implementation of 5tt algorithm for neonatal data. Co-authored-by: Manuel Blesa Cabez Co-authored-by: Paola Galdi --- lib/mrtrix3/_5ttgen/neonatal.py | 138 ++++++++++++++++++++++++++++++++ 1 file changed, 138 insertions(+) create mode 100755 lib/mrtrix3/_5ttgen/neonatal.py diff --git a/lib/mrtrix3/_5ttgen/neonatal.py b/lib/mrtrix3/_5ttgen/neonatal.py new file mode 100755 index 0000000000..bc561315e8 --- /dev/null +++ b/lib/mrtrix3/_5ttgen/neonatal.py @@ -0,0 +1,138 @@ +# Copyright (c) 2008-2020 the MRtrix3 contributors. +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# Covered Software is provided under this License on an "as is" +# basis, without warranty of any kind, either expressed, implied, or +# statutory, including, without limitation, warranties that the +# Covered Software is free of defects, merchantable, fit for a +# particular purpose or non-infringing. +# See the Mozilla Public License v. 2.0 for more details. +# +# For more details, see http://www.mrtrix.org/. + +import math, os +from distutils.spawn import find_executable +from mrtrix3 import MRtrixError +from mrtrix3 import app, image, path, run, utils + + + +def usage(base_parser, subparsers): #pylint: disable=unused-variable + parser = subparsers.add_parser('neonatal', parents=[base_parser]) + parser.set_author('Manuel Blesa (manuel.blesa@ed.ac.uk), Paola Galdi (paola.galdi@ed.ac.uk) and Robert E. Smith (robert.smith@florey.edu.au)') + parser.set_synopsis('Use ANTs commands and the M-CRIB atlas to generate the 5TT image of a neonatal subject based on a T1-weighted or T2-weighted image') + parser.add_citation('Blesa, M.; Galdi, P.; Cox, S.R.; Sullivan, G.; Stoye, D.Q.; Lamb, G.L.; Quigley, A.J.; Thrippleton, M.J.; Escudero, J.; Bastin, M.E.; Smith, K.M. & Boardman. J.P. Hierarchical complexity of the macro-scale neonatal brain. Cerebral Cortex, 2021, 4, 2071-2084', is_external=True) + parser.add_citation('Avants, B.; Epstein, C.; Grossman, M. & Gee, J. Symmetric diffeomorphic image registration with cross-correlation: evaluating automated labeling of elderly and neurodegenerative brain. 2008, Medical Image Analysis, 41, 12-26', is_external=True) + parser.add_citation('Wang, H.; Suh, J.W.; Das, S.R.; Pluta, J.B.; Craige, C. & Yushkevich, P.A. Multi-atlas segmentation with joint label fusion. IEEE Trans Pattern Anal Mach Intell., 2013, 35, 611–623.', is_external=True) + parser.add_citation('Alexander, B.; Murray, A.L.; Loh, W.Y.; Matthews, L.G.; Adamson, C.; Beare, R.; Chen, J.; Kelly, C.E.; Rees, S.; Warfield, S.K.; Anderson, P.J.; Doyle, L.W.; Spittle, A.J.; Cheong, J.L.Y; Seal, M.L. & Thompson, D.K. A new neonatal cortical and subcortical brain atlas: the Melbourne Children’s Regional Infant Brain (m-crib) atlas. NeuroImage, 2017, 852, 147-841.', is_external=True) + parser.add_argument('input', help='The input structural image') + parser.add_argument('modality', choices = ["t1", "t2"], help='Specify the modality of the input image, either "t1" or "t2"') + parser.add_argument('output', help='The output 5TT image') + options = parser.add_argument_group('Options specific to the \'neonatal\' algorithm') + options.add_argument('-mask', type=str, help='Manually provide a brain mask, MANDATORY', required=True) + options.add_argument('-parcellation', type=str, help='Name of the hard segmentation') + options.add_argument('-mcrib_path', type=str, help='Provide the path of the M-CRIB atlas. This can be also specified in the config file as MCRIBpath') + options.add_argument('-quick', action="store_true", help='Specify the use of quick registration parameters') + options.add_argument('-ants_parallel', default=0, type=int, help='Control for parallel computation for antsJointLabelFusion (default 0) -- 0 == run serially, 1 == SGE qsub, 2 == use PEXEC (localhost), 3 == Apple XGrid, 4 == PBS qsub, 5 == SLURM.') + + + +def check_output_paths(): #pylint: disable=unused-variable + app.check_output_path(app.ARGS.output) + + + +def get_inputs(): #pylint: disable=unused-variable + from mrtrix3 import CONFIG, MRtrixError #pylint: disable=no-name-in-module, import-outside-toplevel + if app.ARGS.mcrib_path: + mpath = app.ARGS.mcrib_path + elif 'MCRIBpath' in CONFIG: + mpath = CONFIG.get('MCRIBpath') + else: + raise MRtrixError('The MCRIB atlas path needs to be specified either in the config file or with the option -mcrib_path') + image.check_3d_nonunity(path.from_user(app.ARGS.input, False)) + run.command('mrconvert ' + path.from_user(app.ARGS.input) + ' ' + path.to_scratch('input_raw.mif')) + run.command('mrconvert ' + path.from_user(app.ARGS.mask) + ' ' + path.to_scratch('mask.mif') + ' -datatype bit -strides -1,+2,+3') + atlaslist = ["01", "02", "03", "04", "05", "06", "07", "08", "09", "10"] + if app.ARGS.modality=="t1": + for x in atlaslist: + run.command('mrconvert ' + path.from_user(mpath) + '/M-CRIB_P' + x + '_T1_registered_to_T2.nii.gz ' + path.to_scratch('template_' + x + '.mif')) + run.command('mrconvert ' + path.from_user(mpath) + '/M-CRIB_orig_P' + x + '_parc.nii.gz ' + path.to_scratch('template_labels_' + x + '.mif')) + else: + for x in atlaslist: + run.command('mrconvert ' + path.from_user(mpath) + '/M-CRIB_P' + x + '_T2.nii.gz ' + path.to_scratch('template_' + x + '.mif')) + run.command('mrconvert ' + path.from_user(mpath) + '/M-CRIB_orig_P' + x + '_parc.nii.gz ' + path.to_scratch('template_labels_' + x + '.mif')) + + + +def execute(): #pylint: disable=unused-variable + if not find_executable('antsJointLabelFusion.sh'): + raise MRtrixError('Could not find ANTS script antsJointLabelFusion.sh; please check installation') + + run.command('mrcalc input_raw.mif mask.mif -mul input.mif') + run.command('mrconvert input.mif input.nii') + run.command('mrconvert mask.mif mask.nii -datatype bit') + atlaslist = ["01", "02", "03", "04", "05", "06", "07", "08", "09", "10"] + for x in atlaslist: + run.command('mrthreshold template_' + x + '.mif mask_template_' + x + '.mif -abs 0.5') + run.command('mrhistmatch -mask_input mask_template_' + x + '.mif -mask_target mask.mif scale template_' + x + '.mif input.mif template_hist_' + x + '.mif ') + run.command('mrconvert template_hist_' + x + '.mif template_hist_' + x + '.nii') + run.command('mrconvert mask_template_' + x + '.mif mask_template_' + x + '.nii') + run.command('mrconvert template_labels_' + x + '.mif template_labels_' + x + '.nii') + + ants_options = '-q {} -c {} -k 1'.format(1 if app.ARGS.quick else 0, app.ARGS.ants_parallel) + print(ants_options) + if app.ARGS.ants_parallel == 2: + ants_options += ' -j {}'.format(2 if app.ARGS.nthreads is None else app.ARGS.nthreads) + + + + run.command('antsJointLabelFusion.sh -d 3 -t input.nii -p posterior%04d.nii.gz -g template_hist_01.nii -l template_labels_01.nii -g template_hist_02.nii -l template_labels_02.nii -g template_hist_03.nii -l template_labels_03.nii -g template_hist_04.nii -l template_labels_04.nii -g template_hist_05.nii -l template_labels_05.nii -g template_hist_06.nii -l template_labels_06.nii -g template_hist_07.nii -l template_labels_07.nii -g template_hist_08.nii -l template_labels_08.nii -g template_hist_09.nii -l template_labels_09.nii -g template_hist_10.nii -l template_labels_10.nii -o input_parcellation_ ' + ants_options) + + run.command('antsJointFusion -d 3 -t input.nii --verbose 1 -g input_parcellation_template_hist_01_0_Warped.nii.gz -l input_parcellation_template_hist_01_0_WarpedLabels.nii.gz -g input_parcellation_template_hist_02_1_Warped.nii.gz -l input_parcellation_template_hist_02_1_WarpedLabels.nii.gz -g input_parcellation_template_hist_03_2_Warped.nii.gz -l input_parcellation_template_hist_03_2_WarpedLabels.nii.gz -g input_parcellation_template_hist_04_3_Warped.nii.gz -l input_parcellation_template_hist_04_3_WarpedLabels.nii.gz -g input_parcellation_template_hist_05_4_Warped.nii.gz -l input_parcellation_template_hist_05_4_WarpedLabels.nii.gz -g input_parcellation_template_hist_06_5_Warped.nii.gz -l input_parcellation_template_hist_06_5_WarpedLabels.nii.gz -g input_parcellation_template_hist_07_6_Warped.nii.gz -l input_parcellation_template_hist_07_6_WarpedLabels.nii.gz -g input_parcellation_template_hist_08_7_Warped.nii.gz -l input_parcellation_template_hist_08_7_WarpedLabels.nii.gz -g input_parcellation_template_hist_09_8_Warped.nii.gz -l input_parcellation_template_hist_09_8_WarpedLabels.nii.gz -g input_parcellation_template_hist_10_9_Warped.nii.gz -l input_parcellation_template_hist_10_9_WarpedLabels.nii.gz -o [input_parcellation_Labels.nii.gz,input_parcellation_Intensity.nii.gz,posterior%04d.nii.gz]') + + # Combine the tissue images into the 5TT format within the script itself + + if app.ARGS.sgm_amyg_hipp: + #WM + run.command('mrmath posterior0002.nii.gz posterior0041.nii.gz posterior0192.nii.gz posterior0170.nii.gz posterior0075.nii.gz posterior0076.nii.gz posterior0090.nii.gz sum WM.nii.gz') + #subcortical GM + run.command('mrmath posterior0091.nii.gz posterior0093.nii.gz posterior0017.nii.gz posterior0018.nii.gz posterior0053.nii.gz posterior0054.nii.gz posterior0009.nii.gz posterior0011.nii.gz posterior0012.nii.gz posterior0013.nii.gz posterior0026.nii.gz posterior0048.nii.gz posterior0050.nii.gz posterior0051.nii.gz posterior0052.nii.gz posterior0058.nii.gz sum sGM.nii.gz') + #CSF + run.command('mrmath posterior0014.nii.gz posterior0015.nii.gz posterior0024.nii.gz posterior0043.nii.gz posterior0004.nii.gz sum CSF.nii.gz') + #GM + run.command('mrmath posterior1000.nii.gz posterior1001.nii.gz posterior1002.nii.gz posterior1003.nii.gz posterior1005.nii.gz posterior1006.nii.gz posterior1007.nii.gz posterior1008.nii.gz posterior1009.nii.gz posterior1010.nii.gz posterior1011.nii.gz posterior1012.nii.gz posterior1013.nii.gz posterior1014.nii.gz posterior1015.nii.gz posterior1016.nii.gz posterior1017.nii.gz posterior1018.nii.gz posterior1019.nii.gz posterior1020.nii.gz posterior1021.nii.gz posterior1022.nii.gz posterior1023.nii.gz posterior1024.nii.gz posterior1025.nii.gz posterior1026.nii.gz posterior1027.nii.gz posterior1028.nii.gz posterior1029.nii.gz posterior1030.nii.gz posterior1031.nii.gz posterior1031.nii.gz posterior1032.nii.gz posterior1033.nii.gz posterior1034.nii.gz posterior1035.nii.gz posterior2000.nii.gz posterior2001.nii.gz posterior2002.nii.gz posterior2003.nii.gz posterior2005.nii.gz posterior2006.nii.gz posterior2007.nii.gz posterior2008.nii.gz posterior2009.nii.gz posterior2010.nii.gz posterior2011.nii.gz posterior2012.nii.gz posterior2013.nii.gz posterior2014.nii.gz posterior2015.nii.gz posterior2016.nii.gz posterior2017.nii.gz posterior2018.nii.gz posterior2019.nii.gz posterior2020.nii.gz posterior2021.nii.gz posterior2022.nii.gz posterior2023.nii.gz posterior2024.nii.gz posterior2025.nii.gz posterior2026.nii.gz posterior2027.nii.gz posterior2028.nii.gz posterior2029.nii.gz posterior2030.nii.gz posterior2031.nii.gz posterior2031.nii.gz posterior2032.nii.gz posterior2033.nii.gz posterior2034.nii.gz posterior2035.nii.gz sum GM.nii.gz') + else: + #WM + run.command('mrmath posterior0002.nii.gz posterior0041.nii.gz posterior0192.nii.gz posterior0170.nii.gz posterior0075.nii.gz posterior0076.nii.gz posterior0090.nii.gz sum WM.nii.gz') + #subcortical GM + run.command('mrmath posterior0091.nii.gz posterior0093.nii.gz posterior0009.nii.gz posterior0011.nii.gz posterior0012.nii.gz posterior0013.nii.gz posterior0026.nii.gz posterior0048.nii.gz posterior0050.nii.gz posterior0051.nii.gz posterior0052.nii.gz posterior0058.nii.gz sum sGM.nii.gz') + #CSF + run.command('mrmath posterior0014.nii.gz posterior0015.nii.gz posterior0024.nii.gz posterior0043.nii.gz posterior0004.nii.gz sum CSF.nii.gz') + #GM + run.command('mrmath posterior0017.nii.gz posterior0018.nii.gz posterior0053.nii.gz posterior0054.nii.gz posterior1000.nii.gz posterior1001.nii.gz posterior1002.nii.gz posterior1003.nii.gz posterior1005.nii.gz posterior1006.nii.gz posterior1007.nii.gz posterior1008.nii.gz posterior1009.nii.gz posterior1010.nii.gz posterior1011.nii.gz posterior1012.nii.gz posterior1013.nii.gz posterior1014.nii.gz posterior1015.nii.gz posterior1016.nii.gz posterior1017.nii.gz posterior1018.nii.gz posterior1019.nii.gz posterior1020.nii.gz posterior1021.nii.gz posterior1022.nii.gz posterior1023.nii.gz posterior1024.nii.gz posterior1025.nii.gz posterior1026.nii.gz posterior1027.nii.gz posterior1028.nii.gz posterior1029.nii.gz posterior1030.nii.gz posterior1031.nii.gz posterior1031.nii.gz posterior1032.nii.gz posterior1033.nii.gz posterior1034.nii.gz posterior1035.nii.gz posterior2000.nii.gz posterior2001.nii.gz posterior2002.nii.gz posterior2003.nii.gz posterior2005.nii.gz posterior2006.nii.gz posterior2007.nii.gz posterior2008.nii.gz posterior2009.nii.gz posterior2010.nii.gz posterior2011.nii.gz posterior2012.nii.gz posterior2013.nii.gz posterior2014.nii.gz posterior2015.nii.gz posterior2016.nii.gz posterior2017.nii.gz posterior2018.nii.gz posterior2019.nii.gz posterior2020.nii.gz posterior2021.nii.gz posterior2022.nii.gz posterior2023.nii.gz posterior2024.nii.gz posterior2025.nii.gz posterior2026.nii.gz posterior2027.nii.gz posterior2028.nii.gz posterior2029.nii.gz posterior2030.nii.gz posterior2031.nii.gz posterior2031.nii.gz posterior2032.nii.gz posterior2033.nii.gz posterior2034.nii.gz posterior2035.nii.gz sum GM.nii.gz') + + + #Force normalization + run.command('mrcalc mask.nii WM.nii.gz WM.nii.gz GM.nii.gz sGM.nii.gz CSF.nii.gz -add -add -add -divide 0 -if wm.mif') + run.command('mrcalc mask.nii GM.nii.gz WM.nii.gz GM.nii.gz sGM.nii.gz CSF.nii.gz -add -add -add -divide 0 -if cgm.mif') + run.command('mrcalc mask.nii sGM.nii.gz WM.nii.gz GM.nii.gz sGM.nii.gz CSF.nii.gz -add -add -add -divide 0 -if sgm.mif') + run.command('mrcalc mask.nii CSF.nii.gz WM.nii.gz GM.nii.gz sGM.nii.gz CSF.nii.gz -add -add -add -divide 0 -if csf.mif') + + run.command('mrcalc csf.mif 0 -mul path.mif') + + run.command('mrcat cgm.mif sgm.mif wm.mif csf.mif path.mif - -axis 3 | mrconvert - combined_precrop.mif -strides +2,+3,+4,+1') + + # Crop to reduce file size (improves caching of image data during tracking) + if app.ARGS.nocrop: + run.function(os.rename, 'combined_precrop.mif', 'result.mif') + else: + run.command('mrmath combined_precrop.mif sum - -axis 3 | mrthreshold - - -abs 0.5 | mrgrid combined_precrop.mif crop result.mif -mask -') + + run.command('mrconvert result.mif ' + path.from_user(app.ARGS.output), mrconvert_keyval=path.from_user(app.ARGS.input, False), force=app.FORCE_OVERWRITE) + + if app.ARGS.parcellation: + run.command('mrconvert input_parcellation_Labels.nii.gz ' + path.from_user(app.ARGS.parcellation), mrconvert_keyval=path.from_user(app.ARGS.input, False), force=app.FORCE_OVERWRITE) From e5284131de619d59e7b31acca6de4aaf19e9f078 Mon Sep 17 00:00:00 2001 From: mblesac2 Date: Tue, 9 Nov 2021 18:08:16 +0000 Subject: [PATCH 02/16] Update of the neonatal 5tt algorithm to include the dHCP option Co-authored-by: Manuel Blesa Co-authored-by: Paola Galdi --- lib/mrtrix3/_5ttgen/neonatal.py | 116 ++++++++++++++++++++++++++------ 1 file changed, 95 insertions(+), 21 deletions(-) mode change 100755 => 100644 lib/mrtrix3/_5ttgen/neonatal.py diff --git a/lib/mrtrix3/_5ttgen/neonatal.py b/lib/mrtrix3/_5ttgen/neonatal.py old mode 100755 new mode 100644 index bc561315e8..08e20cd3c9 --- a/lib/mrtrix3/_5ttgen/neonatal.py +++ b/lib/mrtrix3/_5ttgen/neonatal.py @@ -28,13 +28,15 @@ def usage(base_parser, subparsers): #pylint: disable=unused-variable parser.add_citation('Avants, B.; Epstein, C.; Grossman, M. & Gee, J. Symmetric diffeomorphic image registration with cross-correlation: evaluating automated labeling of elderly and neurodegenerative brain. 2008, Medical Image Analysis, 41, 12-26', is_external=True) parser.add_citation('Wang, H.; Suh, J.W.; Das, S.R.; Pluta, J.B.; Craige, C. & Yushkevich, P.A. Multi-atlas segmentation with joint label fusion. IEEE Trans Pattern Anal Mach Intell., 2013, 35, 611–623.', is_external=True) parser.add_citation('Alexander, B.; Murray, A.L.; Loh, W.Y.; Matthews, L.G.; Adamson, C.; Beare, R.; Chen, J.; Kelly, C.E.; Rees, S.; Warfield, S.K.; Anderson, P.J.; Doyle, L.W.; Spittle, A.J.; Cheong, J.L.Y; Seal, M.L. & Thompson, D.K. A new neonatal cortical and subcortical brain atlas: the Melbourne Children’s Regional Infant Brain (m-crib) atlas. NeuroImage, 2017, 852, 147-841.', is_external=True) + parser.add_citation('Makropoulos, A., Robinson, E.C., Schuh, A., Wright, R., Fitzgibbon, S., Bozek, J., Counsell, S.J., Steinweg, J., Vecchiato, K., Passerat-Palmbach, J., Lenz, G., Mortari, F., Tenev, T., Duff, E.P., Bastiani, M., Cordero-Grande, L., Hughes, E., Tusor, N., Tournier, J.D., Hutter, J., Price, A.N., Teixeira, R.P.A.G., Murgasova, M., Victor, S., Kelly, C., Rutherford, M.A., Smith, S.M., Edwards, A.D., Hajnal, J.V., Jenkinson, M. & Rueckert, D. The developing human connectome project: A minimal processing pipeline for neonatal cortical surface reconstruction. NeuroImage, 2018, 173, 88-112.', condition='If -dhcp_path option is used') parser.add_argument('input', help='The input structural image') parser.add_argument('modality', choices = ["t1", "t2"], help='Specify the modality of the input image, either "t1" or "t2"') parser.add_argument('output', help='The output 5TT image') options = parser.add_argument_group('Options specific to the \'neonatal\' algorithm') options.add_argument('-mask', type=str, help='Manually provide a brain mask, MANDATORY', required=True) - options.add_argument('-parcellation', type=str, help='Name of the hard segmentation') + options.add_argument('-dhcp_path', type=str, help='Provide the path of the tissue provability maps (posteriors/) obtained by the dHCP pipeline. You need to run the dHCP pipeline with the flag -additional enabled. This option requires modality to be "t2". We encourage tu use this option when possible') options.add_argument('-mcrib_path', type=str, help='Provide the path of the M-CRIB atlas. This can be also specified in the config file as MCRIBpath') + options.add_argument('-parcellation', type=str, help='Name of the hard segmentation') options.add_argument('-quick', action="store_true", help='Specify the use of quick registration parameters') options.add_argument('-ants_parallel', default=0, type=int, help='Control for parallel computation for antsJointLabelFusion (default 0) -- 0 == run serially, 1 == SGE qsub, 2 == use PEXEC (localhost), 3 == Apple XGrid, 4 == PBS qsub, 5 == SLURM.') @@ -47,6 +49,9 @@ def check_output_paths(): #pylint: disable=unused-variable def get_inputs(): #pylint: disable=unused-variable from mrtrix3 import CONFIG, MRtrixError #pylint: disable=no-name-in-module, import-outside-toplevel + if app.ARGS.dhcp_path: + if app.ARGS.modality=="t1": + raise MRtrixError('Modality has to be "t2" for the dHCP option to work') if app.ARGS.mcrib_path: mpath = app.ARGS.mcrib_path elif 'MCRIBpath' in CONFIG: @@ -65,6 +70,9 @@ def get_inputs(): #pylint: disable=unused-variable for x in atlaslist: run.command('mrconvert ' + path.from_user(mpath) + '/M-CRIB_P' + x + '_T2.nii.gz ' + path.to_scratch('template_' + x + '.mif')) run.command('mrconvert ' + path.from_user(mpath) + '/M-CRIB_orig_P' + x + '_parc.nii.gz ' + path.to_scratch('template_labels_' + x + '.mif')) + if app.ARGS.dhcp_path: + for i in range(1,88): + run.command('mrconvert ' + path.from_user(app.ARGS.dhcp_path) + '/*_drawem_seg' + str(i) + '.nii.gz ' + path.to_scratch('label_' + str(i) + '.mif'), shell=True) @@ -87,33 +95,99 @@ def execute(): #pylint: disable=unused-variable print(ants_options) if app.ARGS.ants_parallel == 2: ants_options += ' -j {}'.format(2 if app.ARGS.nthreads is None else app.ARGS.nthreads) - - - + run.command('antsJointLabelFusion.sh -d 3 -t input.nii -p posterior%04d.nii.gz -g template_hist_01.nii -l template_labels_01.nii -g template_hist_02.nii -l template_labels_02.nii -g template_hist_03.nii -l template_labels_03.nii -g template_hist_04.nii -l template_labels_04.nii -g template_hist_05.nii -l template_labels_05.nii -g template_hist_06.nii -l template_labels_06.nii -g template_hist_07.nii -l template_labels_07.nii -g template_hist_08.nii -l template_labels_08.nii -g template_hist_09.nii -l template_labels_09.nii -g template_hist_10.nii -l template_labels_10.nii -o input_parcellation_ ' + ants_options) run.command('antsJointFusion -d 3 -t input.nii --verbose 1 -g input_parcellation_template_hist_01_0_Warped.nii.gz -l input_parcellation_template_hist_01_0_WarpedLabels.nii.gz -g input_parcellation_template_hist_02_1_Warped.nii.gz -l input_parcellation_template_hist_02_1_WarpedLabels.nii.gz -g input_parcellation_template_hist_03_2_Warped.nii.gz -l input_parcellation_template_hist_03_2_WarpedLabels.nii.gz -g input_parcellation_template_hist_04_3_Warped.nii.gz -l input_parcellation_template_hist_04_3_WarpedLabels.nii.gz -g input_parcellation_template_hist_05_4_Warped.nii.gz -l input_parcellation_template_hist_05_4_WarpedLabels.nii.gz -g input_parcellation_template_hist_06_5_Warped.nii.gz -l input_parcellation_template_hist_06_5_WarpedLabels.nii.gz -g input_parcellation_template_hist_07_6_Warped.nii.gz -l input_parcellation_template_hist_07_6_WarpedLabels.nii.gz -g input_parcellation_template_hist_08_7_Warped.nii.gz -l input_parcellation_template_hist_08_7_WarpedLabels.nii.gz -g input_parcellation_template_hist_09_8_Warped.nii.gz -l input_parcellation_template_hist_09_8_WarpedLabels.nii.gz -g input_parcellation_template_hist_10_9_Warped.nii.gz -l input_parcellation_template_hist_10_9_WarpedLabels.nii.gz -o [input_parcellation_Labels.nii.gz,input_parcellation_Intensity.nii.gz,posterior%04d.nii.gz]') # Combine the tissue images into the 5TT format within the script itself + if app.ARGS.dhcp_path: + if app.ARGS.sgm_amyg_hipp: + #WM + run.command('mrmath label_5.mif label_6.mif label_7.mif label_8.mif label_9.mif label_10.mif label_11.mif label_12.mif label_13.mif label_14.mif label_15.mif label_16.mif label_20.mif label_21.mif label_22.mif label_23.mif label_24.mif label_25.mif label_26.mif label_27.mif label_28.mif label_29.mif label_30.mif label_31.mif label_32.mif label_33.mif label_34.mif label_35.mif label_36.mif label_37.mif label_38.mif label_39.mif sum Pmap-GM.mif') + #CSF + run.command('mrmath label_49.mif label_50.mif label_83.mif sum Pmap-CSF.mif') + #GM + run.command('mrmath label_19.mif label_51.mif label_52.mif label_53.mif label_54.mif label_55.mif label_56.mif label_57.mif label_58.mif label_59.mif label_60.mif label_61.mif label_62.mif label_63.mif label_64.mif label_65.mif label_66.mif label_67.mif label_68.mif label_69.mif label_70.mif label_71.mif label_72.mif label_73.mif label_74.mif label_75.mif label_76.mif label_77.mif label_78.mif label_79.mif label_80.mif label_81.mif label_82.mif label_85.mif label_48.mif label_40.mif label_41.mif label_42.mif label_43.mif label_44.mif label_45.mif label_46.mif label_47.mif label_86.mif label_87.mif sum Pmap-WM.mif') + #sGM + run.command('mrmath label_1.mif label_2.mif label_3.mif label_4.mif label_17.mif label_18.mif sum Pmap-subGM.mif') + + #extract sGM from M-CRIB + run.command('mrcalc input_parcellation_Labels.nii.gz 48 -eq sub1.mif') + run.command('mrcalc input_parcellation_Labels.nii.gz 50 -eq sub2.mif') + run.command('mrcalc input_parcellation_Labels.nii.gz 51 -eq sub3.mif') + run.command('mrcalc input_parcellation_Labels.nii.gz 52 -eq sub4.mif') + run.command('mrcalc input_parcellation_Labels.nii.gz 9 -eq sub5.mif') + run.command('mrcalc input_parcellation_Labels.nii.gz 11 -eq sub6.mif') + run.command('mrcalc input_parcellation_Labels.nii.gz 12 -eq sub7.mif') + run.command('mrcalc input_parcellation_Labels.nii.gz 13 -eq sub8.mif') + run.command('mrcalc input_parcellation_Labels.nii.gz 26 -eq sub9.mif') + run.command('mrcalc input_parcellation_Labels.nii.gz 58 -eq sub10.mif') + run.command('mrmath sub1.mif sub2.mif sub3.mif sub4.mif sub5.mif sub6.mif sub7.mif sub8.mif sub9.mif sub10.mif sum sub_all.mif') + + #refine the WM + run.command('mrthreshold -abs 0.5 -invert sub_all.mif sub_all_inverted.mif') + run.command('mrcalc Pmap-WM.mif sub_all_inverted.mif -mult Pmap-WM-corr.mif') + + #normalize 0-1 and combine + run.command('mrcalc Pmap-GM.mif 100 -div GM.nii.gz') + run.command('mrcalc Pmap-subGM.mif 100 -div Pmap-0002_pre.mif') + run.command('mrcalc Pmap-0002_pre.mif sub_all.mif -add sGM.nii.gz') + run.command('mrcalc Pmap-WM-corr.mif 100 -div WM.nii.gz') + run.command('mrcalc Pmap-CSF.mif 100 -div CSF.nii.gz') + else: + #WM + run.command('mrmath label_1.mif label_2.mif label_3.mif label_4.mif label_5.mif label_6.mif label_7.mif label_8.mif label_9.mif label_10.mif label_11.mif label_12.mif label_13.mif label_14.mif label_15.mif label_16.mif label_20.mif label_21.mif label_22.mif label_23.mif label_24.mif label_25.mif label_26.mif label_27.mif label_28.mif label_29.mif label_30.mif label_31.mif label_32.mif label_33.mif label_34.mif label_35.mif label_36.mif label_37.mif label_38.mif label_39.mif sum Pmap-GM.mif') + #CSF + run.command('mrmath label_49.mif label_50.mif label_83.mif sum Pmap-CSF.mif') + #GM + run.command('mrmath label_19.mif label_51.mif label_52.mif label_53.mif label_54.mif label_55.mif label_56.mif label_57.mif label_58.mif label_59.mif label_60.mif label_61.mif label_62.mif label_63.mif label_64.mif label_65.mif label_66.mif label_67.mif label_68.mif label_69.mif label_70.mif label_71.mif label_72.mif label_73.mif label_74.mif label_75.mif label_76.mif label_77.mif label_78.mif label_79.mif label_80.mif label_81.mif label_82.mif label_85.mif label_48.mif label_40.mif label_41.mif label_42.mif label_43.mif label_44.mif label_45.mif label_46.mif label_47.mif label_86.mif label_87.mif sum Pmap-WM.mif') + #sGM + run.command('mrmath label_17.mif label_18.mif sum Pmap-subGM.mif') + + #extract sGM from M-CRIB + run.command('mrcalc input_parcellation_Labels.nii.gz 48 -eq sub1.mif') + run.command('mrcalc input_parcellation_Labels.nii.gz 50 -eq sub2.mif') + run.command('mrcalc input_parcellation_Labels.nii.gz 51 -eq sub3.mif') + run.command('mrcalc input_parcellation_Labels.nii.gz 52 -eq sub4.mif') + run.command('mrcalc input_parcellation_Labels.nii.gz 9 -eq sub5.mif') + run.command('mrcalc input_parcellation_Labels.nii.gz 11 -eq sub6.mif') + run.command('mrcalc input_parcellation_Labels.nii.gz 12 -eq sub7.mif') + run.command('mrcalc input_parcellation_Labels.nii.gz 13 -eq sub8.mif') + run.command('mrcalc input_parcellation_Labels.nii.gz 26 -eq sub9.mif') + run.command('mrcalc input_parcellation_Labels.nii.gz 58 -eq sub10.mif') + run.command('mrmath sub1.mif sub2.mif sub3.mif sub4.mif sub5.mif sub6.mif sub7.mif sub8.mif sub9.mif sub10.mif sum sub_all.mif') + + #refine the WM + run.command('mrthreshold -abs 0.5 -invert sub_all.mif sub_all_inverted.mif') + run.command('mrcalc Pmap-WM.mif sub_all_inverted.mif -mult Pmap-WM-corr.mif') + + #normalize 0-1 and combine + run.command('mrcalc Pmap-GM.mif 100 -div GM.nii.gz') + run.command('mrcalc Pmap-subGM.mif 100 -div Pmap-0002_pre.mif') + run.command('mrcalc Pmap-0002_pre.mif sub_all.mif -add sGM.nii.gz') + run.command('mrcalc Pmap-WM-corr.mif 100 -div WM.nii.gz') + run.command('mrcalc Pmap-CSF.mif 100 -div CSF.nii.gz') - if app.ARGS.sgm_amyg_hipp: - #WM - run.command('mrmath posterior0002.nii.gz posterior0041.nii.gz posterior0192.nii.gz posterior0170.nii.gz posterior0075.nii.gz posterior0076.nii.gz posterior0090.nii.gz sum WM.nii.gz') - #subcortical GM - run.command('mrmath posterior0091.nii.gz posterior0093.nii.gz posterior0017.nii.gz posterior0018.nii.gz posterior0053.nii.gz posterior0054.nii.gz posterior0009.nii.gz posterior0011.nii.gz posterior0012.nii.gz posterior0013.nii.gz posterior0026.nii.gz posterior0048.nii.gz posterior0050.nii.gz posterior0051.nii.gz posterior0052.nii.gz posterior0058.nii.gz sum sGM.nii.gz') - #CSF - run.command('mrmath posterior0014.nii.gz posterior0015.nii.gz posterior0024.nii.gz posterior0043.nii.gz posterior0004.nii.gz sum CSF.nii.gz') - #GM - run.command('mrmath posterior1000.nii.gz posterior1001.nii.gz posterior1002.nii.gz posterior1003.nii.gz posterior1005.nii.gz posterior1006.nii.gz posterior1007.nii.gz posterior1008.nii.gz posterior1009.nii.gz posterior1010.nii.gz posterior1011.nii.gz posterior1012.nii.gz posterior1013.nii.gz posterior1014.nii.gz posterior1015.nii.gz posterior1016.nii.gz posterior1017.nii.gz posterior1018.nii.gz posterior1019.nii.gz posterior1020.nii.gz posterior1021.nii.gz posterior1022.nii.gz posterior1023.nii.gz posterior1024.nii.gz posterior1025.nii.gz posterior1026.nii.gz posterior1027.nii.gz posterior1028.nii.gz posterior1029.nii.gz posterior1030.nii.gz posterior1031.nii.gz posterior1031.nii.gz posterior1032.nii.gz posterior1033.nii.gz posterior1034.nii.gz posterior1035.nii.gz posterior2000.nii.gz posterior2001.nii.gz posterior2002.nii.gz posterior2003.nii.gz posterior2005.nii.gz posterior2006.nii.gz posterior2007.nii.gz posterior2008.nii.gz posterior2009.nii.gz posterior2010.nii.gz posterior2011.nii.gz posterior2012.nii.gz posterior2013.nii.gz posterior2014.nii.gz posterior2015.nii.gz posterior2016.nii.gz posterior2017.nii.gz posterior2018.nii.gz posterior2019.nii.gz posterior2020.nii.gz posterior2021.nii.gz posterior2022.nii.gz posterior2023.nii.gz posterior2024.nii.gz posterior2025.nii.gz posterior2026.nii.gz posterior2027.nii.gz posterior2028.nii.gz posterior2029.nii.gz posterior2030.nii.gz posterior2031.nii.gz posterior2031.nii.gz posterior2032.nii.gz posterior2033.nii.gz posterior2034.nii.gz posterior2035.nii.gz sum GM.nii.gz') else: - #WM - run.command('mrmath posterior0002.nii.gz posterior0041.nii.gz posterior0192.nii.gz posterior0170.nii.gz posterior0075.nii.gz posterior0076.nii.gz posterior0090.nii.gz sum WM.nii.gz') - #subcortical GM - run.command('mrmath posterior0091.nii.gz posterior0093.nii.gz posterior0009.nii.gz posterior0011.nii.gz posterior0012.nii.gz posterior0013.nii.gz posterior0026.nii.gz posterior0048.nii.gz posterior0050.nii.gz posterior0051.nii.gz posterior0052.nii.gz posterior0058.nii.gz sum sGM.nii.gz') - #CSF - run.command('mrmath posterior0014.nii.gz posterior0015.nii.gz posterior0024.nii.gz posterior0043.nii.gz posterior0004.nii.gz sum CSF.nii.gz') - #GM - run.command('mrmath posterior0017.nii.gz posterior0018.nii.gz posterior0053.nii.gz posterior0054.nii.gz posterior1000.nii.gz posterior1001.nii.gz posterior1002.nii.gz posterior1003.nii.gz posterior1005.nii.gz posterior1006.nii.gz posterior1007.nii.gz posterior1008.nii.gz posterior1009.nii.gz posterior1010.nii.gz posterior1011.nii.gz posterior1012.nii.gz posterior1013.nii.gz posterior1014.nii.gz posterior1015.nii.gz posterior1016.nii.gz posterior1017.nii.gz posterior1018.nii.gz posterior1019.nii.gz posterior1020.nii.gz posterior1021.nii.gz posterior1022.nii.gz posterior1023.nii.gz posterior1024.nii.gz posterior1025.nii.gz posterior1026.nii.gz posterior1027.nii.gz posterior1028.nii.gz posterior1029.nii.gz posterior1030.nii.gz posterior1031.nii.gz posterior1031.nii.gz posterior1032.nii.gz posterior1033.nii.gz posterior1034.nii.gz posterior1035.nii.gz posterior2000.nii.gz posterior2001.nii.gz posterior2002.nii.gz posterior2003.nii.gz posterior2005.nii.gz posterior2006.nii.gz posterior2007.nii.gz posterior2008.nii.gz posterior2009.nii.gz posterior2010.nii.gz posterior2011.nii.gz posterior2012.nii.gz posterior2013.nii.gz posterior2014.nii.gz posterior2015.nii.gz posterior2016.nii.gz posterior2017.nii.gz posterior2018.nii.gz posterior2019.nii.gz posterior2020.nii.gz posterior2021.nii.gz posterior2022.nii.gz posterior2023.nii.gz posterior2024.nii.gz posterior2025.nii.gz posterior2026.nii.gz posterior2027.nii.gz posterior2028.nii.gz posterior2029.nii.gz posterior2030.nii.gz posterior2031.nii.gz posterior2031.nii.gz posterior2032.nii.gz posterior2033.nii.gz posterior2034.nii.gz posterior2035.nii.gz sum GM.nii.gz') + if app.ARGS.sgm_amyg_hipp: + #WM + run.command('mrmath posterior0002.nii.gz posterior0041.nii.gz posterior0192.nii.gz posterior0170.nii.gz posterior0075.nii.gz posterior0076.nii.gz posterior0090.nii.gz sum WM.nii.gz') + #subcortical GM + run.command('mrmath posterior0091.nii.gz posterior0093.nii.gz posterior0017.nii.gz posterior0018.nii.gz posterior0053.nii.gz posterior0054.nii.gz posterior0009.nii.gz posterior0011.nii.gz posterior0012.nii.gz posterior0013.nii.gz posterior0026.nii.gz posterior0048.nii.gz posterior0050.nii.gz posterior0051.nii.gz posterior0052.nii.gz posterior0058.nii.gz sum sGM.nii.gz') + #CSF + run.command('mrmath posterior0014.nii.gz posterior0015.nii.gz posterior0024.nii.gz posterior0043.nii.gz posterior0004.nii.gz sum CSF.nii.gz') + #GM + run.command('mrmath posterior1000.nii.gz posterior1001.nii.gz posterior1002.nii.gz posterior1003.nii.gz posterior1005.nii.gz posterior1006.nii.gz posterior1007.nii.gz posterior1008.nii.gz posterior1009.nii.gz posterior1010.nii.gz posterior1011.nii.gz posterior1012.nii.gz posterior1013.nii.gz posterior1014.nii.gz posterior1015.nii.gz posterior1016.nii.gz posterior1017.nii.gz posterior1018.nii.gz posterior1019.nii.gz posterior1020.nii.gz posterior1021.nii.gz posterior1022.nii.gz posterior1023.nii.gz posterior1024.nii.gz posterior1025.nii.gz posterior1026.nii.gz posterior1027.nii.gz posterior1028.nii.gz posterior1029.nii.gz posterior1030.nii.gz posterior1031.nii.gz posterior1031.nii.gz posterior1032.nii.gz posterior1033.nii.gz posterior1034.nii.gz posterior1035.nii.gz posterior2000.nii.gz posterior2001.nii.gz posterior2002.nii.gz posterior2003.nii.gz posterior2005.nii.gz posterior2006.nii.gz posterior2007.nii.gz posterior2008.nii.gz posterior2009.nii.gz posterior2010.nii.gz posterior2011.nii.gz posterior2012.nii.gz posterior2013.nii.gz posterior2014.nii.gz posterior2015.nii.gz posterior2016.nii.gz posterior2017.nii.gz posterior2018.nii.gz posterior2019.nii.gz posterior2020.nii.gz posterior2021.nii.gz posterior2022.nii.gz posterior2023.nii.gz posterior2024.nii.gz posterior2025.nii.gz posterior2026.nii.gz posterior2027.nii.gz posterior2028.nii.gz posterior2029.nii.gz posterior2030.nii.gz posterior2031.nii.gz posterior2031.nii.gz posterior2032.nii.gz posterior2033.nii.gz posterior2034.nii.gz posterior2035.nii.gz sum GM.nii.gz') + else: + #WM + run.command('mrmath posterior0002.nii.gz posterior0041.nii.gz posterior0192.nii.gz posterior0170.nii.gz posterior0075.nii.gz posterior0076.nii.gz posterior0090.nii.gz sum WM.nii.gz') + #subcortical GM + run.command('mrmath posterior0091.nii.gz posterior0093.nii.gz posterior0009.nii.gz posterior0011.nii.gz posterior0012.nii.gz posterior0013.nii.gz posterior0026.nii.gz posterior0048.nii.gz posterior0050.nii.gz posterior0051.nii.gz posterior0052.nii.gz posterior0058.nii.gz sum sGM.nii.gz') + #CSF + run.command('mrmath posterior0014.nii.gz posterior0015.nii.gz posterior0024.nii.gz posterior0043.nii.gz posterior0004.nii.gz sum CSF.nii.gz') + #GM + run.command('mrmath posterior0017.nii.gz posterior0018.nii.gz posterior0053.nii.gz posterior0054.nii.gz posterior1000.nii.gz posterior1001.nii.gz posterior1002.nii.gz posterior1003.nii.gz posterior1005.nii.gz posterior1006.nii.gz posterior1007.nii.gz posterior1008.nii.gz posterior1009.nii.gz posterior1010.nii.gz posterior1011.nii.gz posterior1012.nii.gz posterior1013.nii.gz posterior1014.nii.gz posterior1015.nii.gz posterior1016.nii.gz posterior1017.nii.gz posterior1018.nii.gz posterior1019.nii.gz posterior1020.nii.gz posterior1021.nii.gz posterior1022.nii.gz posterior1023.nii.gz posterior1024.nii.gz posterior1025.nii.gz posterior1026.nii.gz posterior1027.nii.gz posterior1028.nii.gz posterior1029.nii.gz posterior1030.nii.gz posterior1031.nii.gz posterior1031.nii.gz posterior1032.nii.gz posterior1033.nii.gz posterior1034.nii.gz posterior1035.nii.gz posterior2000.nii.gz posterior2001.nii.gz posterior2002.nii.gz posterior2003.nii.gz posterior2005.nii.gz posterior2006.nii.gz posterior2007.nii.gz posterior2008.nii.gz posterior2009.nii.gz posterior2010.nii.gz posterior2011.nii.gz posterior2012.nii.gz posterior2013.nii.gz posterior2014.nii.gz posterior2015.nii.gz posterior2016.nii.gz posterior2017.nii.gz posterior2018.nii.gz posterior2019.nii.gz posterior2020.nii.gz posterior2021.nii.gz posterior2022.nii.gz posterior2023.nii.gz posterior2024.nii.gz posterior2025.nii.gz posterior2026.nii.gz posterior2027.nii.gz posterior2028.nii.gz posterior2029.nii.gz posterior2030.nii.gz posterior2031.nii.gz posterior2031.nii.gz posterior2032.nii.gz posterior2033.nii.gz posterior2034.nii.gz posterior2035.nii.gz sum GM.nii.gz') #Force normalization From 98802a57ce92cf55312f4b92cd5485a904b428f3 Mon Sep 17 00:00:00 2001 From: Robert Smith Date: Mon, 15 Nov 2021 19:11:56 +1100 Subject: [PATCH 03/16] 5ttgen neonatal: Proposed code cleanup --- lib/mrtrix3/_5ttgen/neonatal.py | 232 ++++++++++++++------------------ 1 file changed, 99 insertions(+), 133 deletions(-) diff --git a/lib/mrtrix3/_5ttgen/neonatal.py b/lib/mrtrix3/_5ttgen/neonatal.py index 08e20cd3c9..04c53c1d39 100644 --- a/lib/mrtrix3/_5ttgen/neonatal.py +++ b/lib/mrtrix3/_5ttgen/neonatal.py @@ -13,30 +13,46 @@ # # For more details, see http://www.mrtrix.org/. -import math, os +import glob, math, os from distutils.spawn import find_executable -from mrtrix3 import MRtrixError +from mrtrix3 import CONFIG, MRtrixError from mrtrix3 import app, image, path, run, utils +DHCP_CGM = list(range(5, 40)) +DHCP_SGM = [17, 18] +DHCP_WM = [19] + range(40, 49) + range(51, 83) + range(85, 88) +DHCP_CSF = [49, 50, 83] +DHCP_AMYG_HIPP = list(range(1, 5)) + +MCRIB_CGM = list(range(1000, 1036) + range(2000, 2036)) +MCRIB_SGM = [9, 11, 12, 13, 26, 48, 50, 51, 52, 58] +MCRIB_WM = [2, 41, 75, 76, 90, 170, 192] +MCRIB_CSF = [4, 14, 15, 24, 43] +MCRIB_AMYG_HIPP = [17, 18, 53, 54] +MCRIB_CEREBELLAR = [91, 93] + + + def usage(base_parser, subparsers): #pylint: disable=unused-variable parser = subparsers.add_parser('neonatal', parents=[base_parser]) parser.set_author('Manuel Blesa (manuel.blesa@ed.ac.uk), Paola Galdi (paola.galdi@ed.ac.uk) and Robert E. Smith (robert.smith@florey.edu.au)') parser.set_synopsis('Use ANTs commands and the M-CRIB atlas to generate the 5TT image of a neonatal subject based on a T1-weighted or T2-weighted image') + parser.add_description('When the -dhcp_path option is used, derivation of the 5TT image will be principally based on the segmentation already performed in the dHCP pipeline. The M-CRIB atlas will only be used to introduce additional sub-cortical grey matter parcels into the tissue segmentation. For this operation to be applicable, the dHCP pipeline must have been executed with the -additional command-line flag, and the modality of the input image must be T2-weighted. Use of this mode of operation is generally encouraged.') parser.add_citation('Blesa, M.; Galdi, P.; Cox, S.R.; Sullivan, G.; Stoye, D.Q.; Lamb, G.L.; Quigley, A.J.; Thrippleton, M.J.; Escudero, J.; Bastin, M.E.; Smith, K.M. & Boardman. J.P. Hierarchical complexity of the macro-scale neonatal brain. Cerebral Cortex, 2021, 4, 2071-2084', is_external=True) parser.add_citation('Avants, B.; Epstein, C.; Grossman, M. & Gee, J. Symmetric diffeomorphic image registration with cross-correlation: evaluating automated labeling of elderly and neurodegenerative brain. 2008, Medical Image Analysis, 41, 12-26', is_external=True) parser.add_citation('Wang, H.; Suh, J.W.; Das, S.R.; Pluta, J.B.; Craige, C. & Yushkevich, P.A. Multi-atlas segmentation with joint label fusion. IEEE Trans Pattern Anal Mach Intell., 2013, 35, 611–623.', is_external=True) parser.add_citation('Alexander, B.; Murray, A.L.; Loh, W.Y.; Matthews, L.G.; Adamson, C.; Beare, R.; Chen, J.; Kelly, C.E.; Rees, S.; Warfield, S.K.; Anderson, P.J.; Doyle, L.W.; Spittle, A.J.; Cheong, J.L.Y; Seal, M.L. & Thompson, D.K. A new neonatal cortical and subcortical brain atlas: the Melbourne Children’s Regional Infant Brain (m-crib) atlas. NeuroImage, 2017, 852, 147-841.', is_external=True) parser.add_citation('Makropoulos, A., Robinson, E.C., Schuh, A., Wright, R., Fitzgibbon, S., Bozek, J., Counsell, S.J., Steinweg, J., Vecchiato, K., Passerat-Palmbach, J., Lenz, G., Mortari, F., Tenev, T., Duff, E.P., Bastiani, M., Cordero-Grande, L., Hughes, E., Tusor, N., Tournier, J.D., Hutter, J., Price, A.N., Teixeira, R.P.A.G., Murgasova, M., Victor, S., Kelly, C., Rutherford, M.A., Smith, S.M., Edwards, A.D., Hajnal, J.V., Jenkinson, M. & Rueckert, D. The developing human connectome project: A minimal processing pipeline for neonatal cortical surface reconstruction. NeuroImage, 2018, 173, 88-112.', condition='If -dhcp_path option is used') parser.add_argument('input', help='The input structural image') - parser.add_argument('modality', choices = ["t1", "t2"], help='Specify the modality of the input image, either "t1" or "t2"') + parser.add_argument('modality', choices=["t1w", "t2w"], help='Specify the modality of the input image, either "t1w" or "t2w"') parser.add_argument('output', help='The output 5TT image') options = parser.add_argument_group('Options specific to the \'neonatal\' algorithm') options.add_argument('-mask', type=str, help='Manually provide a brain mask, MANDATORY', required=True) - options.add_argument('-dhcp_path', type=str, help='Provide the path of the tissue provability maps (posteriors/) obtained by the dHCP pipeline. You need to run the dHCP pipeline with the flag -additional enabled. This option requires modality to be "t2". We encourage tu use this option when possible') - options.add_argument('-mcrib_path', type=str, help='Provide the path of the M-CRIB atlas. This can be also specified in the config file as MCRIBpath') - options.add_argument('-parcellation', type=str, help='Name of the hard segmentation') + options.add_argument('-dhcp_path', type=str, help='Provide the path of the tissue probability maps (posteriors/) obtained by the dHCP pipeline (see Description)') + options.add_argument('-mcrib_path', type=str, help='Provide the path of the M-CRIB atlas (note: this can alternatively be specified in the MRtrix config file as "MCRIBPath")') + options.add_argument('-parcellation', type=str, help='Additionally export the M-CRIB parcellation warped to the subject data') options.add_argument('-quick', action="store_true", help='Specify the use of quick registration parameters') options.add_argument('-ants_parallel', default=0, type=int, help='Control for parallel computation for antsJointLabelFusion (default 0) -- 0 == run serially, 1 == SGE qsub, 2 == use PEXEC (localhost), 3 == Apple XGrid, 4 == PBS qsub, 5 == SLURM.') @@ -48,31 +64,32 @@ def check_output_paths(): #pylint: disable=unused-variable def get_inputs(): #pylint: disable=unused-variable - from mrtrix3 import CONFIG, MRtrixError #pylint: disable=no-name-in-module, import-outside-toplevel if app.ARGS.dhcp_path: - if app.ARGS.modality=="t1": - raise MRtrixError('Modality has to be "t2" for the dHCP option to work') + if app.ARGS.modality == "t1w": + raise MRtrixError('Modality has to be "t2w" for the dHCP option to work') if app.ARGS.mcrib_path: - mpath = app.ARGS.mcrib_path - elif 'MCRIBpath' in CONFIG: - mpath = CONFIG.get('MCRIBpath') + mcrib_dir = os.path.abspath(path.from_user(app.ARGS.mcrib_path, False)) + elif 'MCRIBPath' in CONFIG: + mcrib_dir = CONFIG.get('MCRIBPath') else: - raise MRtrixError('The MCRIB atlas path needs to be specified either in the config file or with the option -mcrib_path') + raise MRtrixError('The MCRIB atlas path needs to be specified either in the config file ("MCRIBPath") or with the command-line option -mcrib_path') image.check_3d_nonunity(path.from_user(app.ARGS.input, False)) run.command('mrconvert ' + path.from_user(app.ARGS.input) + ' ' + path.to_scratch('input_raw.mif')) run.command('mrconvert ' + path.from_user(app.ARGS.mask) + ' ' + path.to_scratch('mask.mif') + ' -datatype bit -strides -1,+2,+3') - atlaslist = ["01", "02", "03", "04", "05", "06", "07", "08", "09", "10"] - if app.ARGS.modality=="t1": - for x in atlaslist: - run.command('mrconvert ' + path.from_user(mpath) + '/M-CRIB_P' + x + '_T1_registered_to_T2.nii.gz ' + path.to_scratch('template_' + x + '.mif')) - run.command('mrconvert ' + path.from_user(mpath) + '/M-CRIB_orig_P' + x + '_parc.nii.gz ' + path.to_scratch('template_labels_' + x + '.mif')) - else: - for x in atlaslist: - run.command('mrconvert ' + path.from_user(mpath) + '/M-CRIB_P' + x + '_T2.nii.gz ' + path.to_scratch('template_' + x + '.mif')) - run.command('mrconvert ' + path.from_user(mpath) + '/M-CRIB_orig_P' + x + '_parc.nii.gz ' + path.to_scratch('template_labels_' + x + '.mif')) + mcrib_import = utils.RunList('Importing M-CRIB data to scratch directory', 20) + for i in range(1, 11): + mcrib_import.command(['mrconvert', os.path.join(mcrib_dir, ('M-CRIB_P%02d_' % i) + ('T1_registered_to_T2' if app.ARGS.modality == 't1w' else 'T2') + '.nii.gz'), path.to_scratch('template_%02d.mif' % i)]) + mcrib_import.command(['mrconvert', os.path.join(mcrib_dir, 'M-CRIB_orig_P%02d_parc.nii.gz' % i), path.to_scratch('template_labels_%02d.mif' % i, False)]) if app.ARGS.dhcp_path: - for i in range(1,88): - run.command('mrconvert ' + path.from_user(app.ARGS.dhcp_path) + '/*_drawem_seg' + str(i) + '.nii.gz ' + path.to_scratch('label_' + str(i) + '.mif'), shell=True) + dhcp_dir = os.path.abspath(path.from_user(app.ARGS.dhcp_path, False)) + dhcp_import = utils.RunList('Importing dHCP data to scratch directory', 87) + for i in range(1, 88): + images = glob.glob(os.path.join(dhcp_dir, '*_drawem_seg%d.nii.gz' % i)) + if not images: + raise MRtrixError('Unable to find dHCP image for parcel %d in location "' % i + dhcp_dir + '"') + if len(images) > 1: + raise MRtrixError('Multiple dHCP images found for parcel %d in location "' % i + dhcp_dir + '"') + dhcp_import.command(['mrconvert', images[0], path.to_scratch('label_%d.mif' % i, False)]) @@ -83,122 +100,71 @@ def execute(): #pylint: disable=unused-variable run.command('mrcalc input_raw.mif mask.mif -mul input.mif') run.command('mrconvert input.mif input.nii') run.command('mrconvert mask.mif mask.nii -datatype bit') - atlaslist = ["01", "02", "03", "04", "05", "06", "07", "08", "09", "10"] - for x in atlaslist: - run.command('mrthreshold template_' + x + '.mif mask_template_' + x + '.mif -abs 0.5') - run.command('mrhistmatch -mask_input mask_template_' + x + '.mif -mask_target mask.mif scale template_' + x + '.mif input.mif template_hist_' + x + '.mif ') - run.command('mrconvert template_hist_' + x + '.mif template_hist_' + x + '.nii') - run.command('mrconvert mask_template_' + x + '.mif mask_template_' + x + '.nii') - run.command('mrconvert template_labels_' + x + '.mif template_labels_' + x + '.nii') - - ants_options = '-q {} -c {} -k 1'.format(1 if app.ARGS.quick else 0, app.ARGS.ants_parallel) - print(ants_options) + + histmatch = utils.RunList('Histogram-matching template images to input image', 50) + for i in range(1, 11): + s = '%02d' % i + histmatch.command('mrthreshold template_%s.mif mask_template_%s.mif -abs 0.5' % (s, s)) + histmatch.command('mrhistmatch -mask_input mask_template_%s.mif -mask_target mask.mif scale template_%s.mif input.mif template_hist_%s.mif' % (s, s, s)) + histmatch.command('mrconvert template_hist_%s.mif template_hist_%s.nii' % (s, s)) + histmatch.command('mrconvert mask_template_%s.mif mask_template_%s.nii' % (s, s)) + histmatch.command('mrconvert template_labels_%s.mif template_labels_%s.nii' % (s, s)) + + ants_options = ' -q {} -c {} -k 1'.format(1 if app.ARGS.quick else 0, app.ARGS.ants_parallel) if app.ARGS.ants_parallel == 2: ants_options += ' -j {}'.format(2 if app.ARGS.nthreads is None else app.ARGS.nthreads) - - run.command('antsJointLabelFusion.sh -d 3 -t input.nii -p posterior%04d.nii.gz -g template_hist_01.nii -l template_labels_01.nii -g template_hist_02.nii -l template_labels_02.nii -g template_hist_03.nii -l template_labels_03.nii -g template_hist_04.nii -l template_labels_04.nii -g template_hist_05.nii -l template_labels_05.nii -g template_hist_06.nii -l template_labels_06.nii -g template_hist_07.nii -l template_labels_07.nii -g template_hist_08.nii -l template_labels_08.nii -g template_hist_09.nii -l template_labels_09.nii -g template_hist_10.nii -l template_labels_10.nii -o input_parcellation_ ' + ants_options) + app.debug('ANTs command-line options for JointLabelFusion: "' + ants_options + '"') - run.command('antsJointFusion -d 3 -t input.nii --verbose 1 -g input_parcellation_template_hist_01_0_Warped.nii.gz -l input_parcellation_template_hist_01_0_WarpedLabels.nii.gz -g input_parcellation_template_hist_02_1_Warped.nii.gz -l input_parcellation_template_hist_02_1_WarpedLabels.nii.gz -g input_parcellation_template_hist_03_2_Warped.nii.gz -l input_parcellation_template_hist_03_2_WarpedLabels.nii.gz -g input_parcellation_template_hist_04_3_Warped.nii.gz -l input_parcellation_template_hist_04_3_WarpedLabels.nii.gz -g input_parcellation_template_hist_05_4_Warped.nii.gz -l input_parcellation_template_hist_05_4_WarpedLabels.nii.gz -g input_parcellation_template_hist_06_5_Warped.nii.gz -l input_parcellation_template_hist_06_5_WarpedLabels.nii.gz -g input_parcellation_template_hist_07_6_Warped.nii.gz -l input_parcellation_template_hist_07_6_WarpedLabels.nii.gz -g input_parcellation_template_hist_08_7_Warped.nii.gz -l input_parcellation_template_hist_08_7_WarpedLabels.nii.gz -g input_parcellation_template_hist_09_8_Warped.nii.gz -l input_parcellation_template_hist_09_8_WarpedLabels.nii.gz -g input_parcellation_template_hist_10_9_Warped.nii.gz -l input_parcellation_template_hist_10_9_WarpedLabels.nii.gz -o [input_parcellation_Labels.nii.gz,input_parcellation_Intensity.nii.gz,posterior%04d.nii.gz]') + run.command('antsJointLabelFusion.sh -d 3 -t input.nii -p posterior%04d.nii.gz ' + + ' '.join('-g template_hist_%02d.nii -l template_labels_%02d.nii' % (i, i) for i in range(1, 11)) + + ' -o input_parcellation_' + + ants_options) + + run.command('antsJointFusion -d 3 -t input.nii --verbose 1 ' + + ' '.join('-g input_parcellation_template_hist_%02d_%d_Warped.nii.gz -l input_parcellation_template_hist_%02d_%d_WarpedLabels.nii.gz' % (i, i-1) for i in range(1, 11)) + + ' -o [input_parcellation_Labels.nii.gz,input_parcellation_Intensity.nii.gz,posterior%04d.nii.gz]') - # Combine the tissue images into the 5TT format within the script itself if app.ARGS.dhcp_path: - if app.ARGS.sgm_amyg_hipp: - #WM - run.command('mrmath label_5.mif label_6.mif label_7.mif label_8.mif label_9.mif label_10.mif label_11.mif label_12.mif label_13.mif label_14.mif label_15.mif label_16.mif label_20.mif label_21.mif label_22.mif label_23.mif label_24.mif label_25.mif label_26.mif label_27.mif label_28.mif label_29.mif label_30.mif label_31.mif label_32.mif label_33.mif label_34.mif label_35.mif label_36.mif label_37.mif label_38.mif label_39.mif sum Pmap-GM.mif') - #CSF - run.command('mrmath label_49.mif label_50.mif label_83.mif sum Pmap-CSF.mif') - #GM - run.command('mrmath label_19.mif label_51.mif label_52.mif label_53.mif label_54.mif label_55.mif label_56.mif label_57.mif label_58.mif label_59.mif label_60.mif label_61.mif label_62.mif label_63.mif label_64.mif label_65.mif label_66.mif label_67.mif label_68.mif label_69.mif label_70.mif label_71.mif label_72.mif label_73.mif label_74.mif label_75.mif label_76.mif label_77.mif label_78.mif label_79.mif label_80.mif label_81.mif label_82.mif label_85.mif label_48.mif label_40.mif label_41.mif label_42.mif label_43.mif label_44.mif label_45.mif label_46.mif label_47.mif label_86.mif label_87.mif sum Pmap-WM.mif') - #sGM - run.command('mrmath label_1.mif label_2.mif label_3.mif label_4.mif label_17.mif label_18.mif sum Pmap-subGM.mif') - - #extract sGM from M-CRIB - run.command('mrcalc input_parcellation_Labels.nii.gz 48 -eq sub1.mif') - run.command('mrcalc input_parcellation_Labels.nii.gz 50 -eq sub2.mif') - run.command('mrcalc input_parcellation_Labels.nii.gz 51 -eq sub3.mif') - run.command('mrcalc input_parcellation_Labels.nii.gz 52 -eq sub4.mif') - run.command('mrcalc input_parcellation_Labels.nii.gz 9 -eq sub5.mif') - run.command('mrcalc input_parcellation_Labels.nii.gz 11 -eq sub6.mif') - run.command('mrcalc input_parcellation_Labels.nii.gz 12 -eq sub7.mif') - run.command('mrcalc input_parcellation_Labels.nii.gz 13 -eq sub8.mif') - run.command('mrcalc input_parcellation_Labels.nii.gz 26 -eq sub9.mif') - run.command('mrcalc input_parcellation_Labels.nii.gz 58 -eq sub10.mif') - run.command('mrmath sub1.mif sub2.mif sub3.mif sub4.mif sub5.mif sub6.mif sub7.mif sub8.mif sub9.mif sub10.mif sum sub_all.mif') - - #refine the WM - run.command('mrthreshold -abs 0.5 -invert sub_all.mif sub_all_inverted.mif') - run.command('mrcalc Pmap-WM.mif sub_all_inverted.mif -mult Pmap-WM-corr.mif') - - #normalize 0-1 and combine - run.command('mrcalc Pmap-GM.mif 100 -div GM.nii.gz') - run.command('mrcalc Pmap-subGM.mif 100 -div Pmap-0002_pre.mif') - run.command('mrcalc Pmap-0002_pre.mif sub_all.mif -add sGM.nii.gz') - run.command('mrcalc Pmap-WM-corr.mif 100 -div WM.nii.gz') - run.command('mrcalc Pmap-CSF.mif 100 -div CSF.nii.gz') - else: - #WM - run.command('mrmath label_1.mif label_2.mif label_3.mif label_4.mif label_5.mif label_6.mif label_7.mif label_8.mif label_9.mif label_10.mif label_11.mif label_12.mif label_13.mif label_14.mif label_15.mif label_16.mif label_20.mif label_21.mif label_22.mif label_23.mif label_24.mif label_25.mif label_26.mif label_27.mif label_28.mif label_29.mif label_30.mif label_31.mif label_32.mif label_33.mif label_34.mif label_35.mif label_36.mif label_37.mif label_38.mif label_39.mif sum Pmap-GM.mif') - #CSF - run.command('mrmath label_49.mif label_50.mif label_83.mif sum Pmap-CSF.mif') - #GM - run.command('mrmath label_19.mif label_51.mif label_52.mif label_53.mif label_54.mif label_55.mif label_56.mif label_57.mif label_58.mif label_59.mif label_60.mif label_61.mif label_62.mif label_63.mif label_64.mif label_65.mif label_66.mif label_67.mif label_68.mif label_69.mif label_70.mif label_71.mif label_72.mif label_73.mif label_74.mif label_75.mif label_76.mif label_77.mif label_78.mif label_79.mif label_80.mif label_81.mif label_82.mif label_85.mif label_48.mif label_40.mif label_41.mif label_42.mif label_43.mif label_44.mif label_45.mif label_46.mif label_47.mif label_86.mif label_87.mif sum Pmap-WM.mif') - #sGM - run.command('mrmath label_17.mif label_18.mif sum Pmap-subGM.mif') - - #extract sGM from M-CRIB - run.command('mrcalc input_parcellation_Labels.nii.gz 48 -eq sub1.mif') - run.command('mrcalc input_parcellation_Labels.nii.gz 50 -eq sub2.mif') - run.command('mrcalc input_parcellation_Labels.nii.gz 51 -eq sub3.mif') - run.command('mrcalc input_parcellation_Labels.nii.gz 52 -eq sub4.mif') - run.command('mrcalc input_parcellation_Labels.nii.gz 9 -eq sub5.mif') - run.command('mrcalc input_parcellation_Labels.nii.gz 11 -eq sub6.mif') - run.command('mrcalc input_parcellation_Labels.nii.gz 12 -eq sub7.mif') - run.command('mrcalc input_parcellation_Labels.nii.gz 13 -eq sub8.mif') - run.command('mrcalc input_parcellation_Labels.nii.gz 26 -eq sub9.mif') - run.command('mrcalc input_parcellation_Labels.nii.gz 58 -eq sub10.mif') - run.command('mrmath sub1.mif sub2.mif sub3.mif sub4.mif sub5.mif sub6.mif sub7.mif sub8.mif sub9.mif sub10.mif sum sub_all.mif') - - #refine the WM - run.command('mrthreshold -abs 0.5 -invert sub_all.mif sub_all_inverted.mif') - run.command('mrcalc Pmap-WM.mif sub_all_inverted.mif -mult Pmap-WM-corr.mif') - - #normalize 0-1 and combine - run.command('mrcalc Pmap-GM.mif 100 -div GM.nii.gz') - run.command('mrcalc Pmap-subGM.mif 100 -div Pmap-0002_pre.mif') - run.command('mrcalc Pmap-0002_pre.mif sub_all.mif -add sGM.nii.gz') - run.command('mrcalc Pmap-WM-corr.mif 100 -div WM.nii.gz') - run.command('mrcalc Pmap-CSF.mif 100 -div CSF.nii.gz') + + for tissue, indices in { 'cGM': DHCP_CGM + ([] if app.ARGS.sgm_amyg_hipp else DHCP_AMYG_HIPP), + 'sGM': DHCP_SGM + (DHCP_AMYG_HIPP if app.ARGS.sgm_amyg_hipp else []), + 'WM' : DHCP_WM, + 'CSF': DHCP_CSF }: + run.command(['mrmath', ['label_%d.mif' % i for i in indices], 'sum', 'Pmap-' + tissue + '.mif']) + + # Uncompress just once, since we need to read multiple times + run.command('mrconvert input_parcellation_Labels.nii.gz input_parcellation_Labels.nii') + + #extract sGM from M-CRIB + run.command('mrcalc ' + ' '.join('input_parcellation_Labels.nii ' + str(i) + ' -eq' for i in MCRIB_SGM) + ' ' + ' '.join(['-add'] * (len(MCRIB_SGM) - 1)) + ' sGM_mcrib.mif') + + #refine the WM + run.command('mrcalc sGM_mcrib.mif 0.5 -lt Pmap-WM.mif -mult Pmap-WM-corr.mif') + + #normalize 0-1 and combine + run.command('mrcalc Pmap-cGM.mif 0.01 -mult GM.nii.gz') + run.command('mrcalc Pmap-sGM.mif 0.01 -mult sGM_mcrib.mif -add sGM.nii.gz') + run.command('mrcalc Pmap-WM-corr.mif 0.01 -mult WM.nii.gz') + run.command('mrcalc Pmap-CSF.mif 0.01 -mult CSF.nii.gz') else: - if app.ARGS.sgm_amyg_hipp: - #WM - run.command('mrmath posterior0002.nii.gz posterior0041.nii.gz posterior0192.nii.gz posterior0170.nii.gz posterior0075.nii.gz posterior0076.nii.gz posterior0090.nii.gz sum WM.nii.gz') - #subcortical GM - run.command('mrmath posterior0091.nii.gz posterior0093.nii.gz posterior0017.nii.gz posterior0018.nii.gz posterior0053.nii.gz posterior0054.nii.gz posterior0009.nii.gz posterior0011.nii.gz posterior0012.nii.gz posterior0013.nii.gz posterior0026.nii.gz posterior0048.nii.gz posterior0050.nii.gz posterior0051.nii.gz posterior0052.nii.gz posterior0058.nii.gz sum sGM.nii.gz') - #CSF - run.command('mrmath posterior0014.nii.gz posterior0015.nii.gz posterior0024.nii.gz posterior0043.nii.gz posterior0004.nii.gz sum CSF.nii.gz') - #GM - run.command('mrmath posterior1000.nii.gz posterior1001.nii.gz posterior1002.nii.gz posterior1003.nii.gz posterior1005.nii.gz posterior1006.nii.gz posterior1007.nii.gz posterior1008.nii.gz posterior1009.nii.gz posterior1010.nii.gz posterior1011.nii.gz posterior1012.nii.gz posterior1013.nii.gz posterior1014.nii.gz posterior1015.nii.gz posterior1016.nii.gz posterior1017.nii.gz posterior1018.nii.gz posterior1019.nii.gz posterior1020.nii.gz posterior1021.nii.gz posterior1022.nii.gz posterior1023.nii.gz posterior1024.nii.gz posterior1025.nii.gz posterior1026.nii.gz posterior1027.nii.gz posterior1028.nii.gz posterior1029.nii.gz posterior1030.nii.gz posterior1031.nii.gz posterior1031.nii.gz posterior1032.nii.gz posterior1033.nii.gz posterior1034.nii.gz posterior1035.nii.gz posterior2000.nii.gz posterior2001.nii.gz posterior2002.nii.gz posterior2003.nii.gz posterior2005.nii.gz posterior2006.nii.gz posterior2007.nii.gz posterior2008.nii.gz posterior2009.nii.gz posterior2010.nii.gz posterior2011.nii.gz posterior2012.nii.gz posterior2013.nii.gz posterior2014.nii.gz posterior2015.nii.gz posterior2016.nii.gz posterior2017.nii.gz posterior2018.nii.gz posterior2019.nii.gz posterior2020.nii.gz posterior2021.nii.gz posterior2022.nii.gz posterior2023.nii.gz posterior2024.nii.gz posterior2025.nii.gz posterior2026.nii.gz posterior2027.nii.gz posterior2028.nii.gz posterior2029.nii.gz posterior2030.nii.gz posterior2031.nii.gz posterior2031.nii.gz posterior2032.nii.gz posterior2033.nii.gz posterior2034.nii.gz posterior2035.nii.gz sum GM.nii.gz') - else: - #WM - run.command('mrmath posterior0002.nii.gz posterior0041.nii.gz posterior0192.nii.gz posterior0170.nii.gz posterior0075.nii.gz posterior0076.nii.gz posterior0090.nii.gz sum WM.nii.gz') - #subcortical GM - run.command('mrmath posterior0091.nii.gz posterior0093.nii.gz posterior0009.nii.gz posterior0011.nii.gz posterior0012.nii.gz posterior0013.nii.gz posterior0026.nii.gz posterior0048.nii.gz posterior0050.nii.gz posterior0051.nii.gz posterior0052.nii.gz posterior0058.nii.gz sum sGM.nii.gz') - #CSF - run.command('mrmath posterior0014.nii.gz posterior0015.nii.gz posterior0024.nii.gz posterior0043.nii.gz posterior0004.nii.gz sum CSF.nii.gz') - #GM - run.command('mrmath posterior0017.nii.gz posterior0018.nii.gz posterior0053.nii.gz posterior0054.nii.gz posterior1000.nii.gz posterior1001.nii.gz posterior1002.nii.gz posterior1003.nii.gz posterior1005.nii.gz posterior1006.nii.gz posterior1007.nii.gz posterior1008.nii.gz posterior1009.nii.gz posterior1010.nii.gz posterior1011.nii.gz posterior1012.nii.gz posterior1013.nii.gz posterior1014.nii.gz posterior1015.nii.gz posterior1016.nii.gz posterior1017.nii.gz posterior1018.nii.gz posterior1019.nii.gz posterior1020.nii.gz posterior1021.nii.gz posterior1022.nii.gz posterior1023.nii.gz posterior1024.nii.gz posterior1025.nii.gz posterior1026.nii.gz posterior1027.nii.gz posterior1028.nii.gz posterior1029.nii.gz posterior1030.nii.gz posterior1031.nii.gz posterior1031.nii.gz posterior1032.nii.gz posterior1033.nii.gz posterior1034.nii.gz posterior1035.nii.gz posterior2000.nii.gz posterior2001.nii.gz posterior2002.nii.gz posterior2003.nii.gz posterior2005.nii.gz posterior2006.nii.gz posterior2007.nii.gz posterior2008.nii.gz posterior2009.nii.gz posterior2010.nii.gz posterior2011.nii.gz posterior2012.nii.gz posterior2013.nii.gz posterior2014.nii.gz posterior2015.nii.gz posterior2016.nii.gz posterior2017.nii.gz posterior2018.nii.gz posterior2019.nii.gz posterior2020.nii.gz posterior2021.nii.gz posterior2022.nii.gz posterior2023.nii.gz posterior2024.nii.gz posterior2025.nii.gz posterior2026.nii.gz posterior2027.nii.gz posterior2028.nii.gz posterior2029.nii.gz posterior2030.nii.gz posterior2031.nii.gz posterior2031.nii.gz posterior2032.nii.gz posterior2033.nii.gz posterior2034.nii.gz posterior2035.nii.gz sum GM.nii.gz') - - - #Force normalization - run.command('mrcalc mask.nii WM.nii.gz WM.nii.gz GM.nii.gz sGM.nii.gz CSF.nii.gz -add -add -add -divide 0 -if wm.mif') - run.command('mrcalc mask.nii GM.nii.gz WM.nii.gz GM.nii.gz sGM.nii.gz CSF.nii.gz -add -add -add -divide 0 -if cgm.mif') - run.command('mrcalc mask.nii sGM.nii.gz WM.nii.gz GM.nii.gz sGM.nii.gz CSF.nii.gz -add -add -add -divide 0 -if sgm.mif') - run.command('mrcalc mask.nii CSF.nii.gz WM.nii.gz GM.nii.gz sGM.nii.gz CSF.nii.gz -add -add -add -divide 0 -if csf.mif') - - run.command('mrcalc csf.mif 0 -mul path.mif') - - run.command('mrcat cgm.mif sgm.mif wm.mif csf.mif path.mif - -axis 3 | mrconvert - combined_precrop.mif -strides +2,+3,+4,+1') + + for tissue, indices in { 'cGM': MCRIB_CGM + ([] if app.ARGS.sgm_amyg_hipp else MCRIB_AMYG_HIPP), + 'sGM': MCRIB_SGM + MCRIB_CEREBELLAR + (MCRIB_AMYG_HIPP if app.ARGS.sgm_amyg_hipp else []), + 'WM' : MCRIB_WM, + 'CSF': MCRIB_CSF }: + run.command(['mrmath', ['posterior%04d.nii.gz' % i for i in indices], 'sum', tissue + '.mif']) + + #Force normalization + run.command('mrmath WM.mif cGM.mif sGM.mif CSF.mif sum tissue_sum.mif') + run.command('mrcalc mask.nii cGM.mif tissue_sum.mif -divide 0 -if cgm_norm.mif') + run.command('mrcalc mask.nii sGM.mif tissue_sum.mif -divide 0 -if sgm_norm.mif') + run.command('mrcalc mask.nii WM.mif tissue_sum.mif -divide 0 -if wm_norm.mif') + run.command('mrcalc mask.nii CSF.mif tissue_sum.mif -divide 0 -if csf_norm.mif') + + run.command('mrcalc csf_norm.mif 0 -mul path.mif') + + run.command('mrcat cgm_norm.mif sgm_norm.mif wm_norm.mif csf_norm.mif path.mif - -axis 3 | mrconvert - combined_precrop.mif -strides +2,+3,+4,+1') # Crop to reduce file size (improves caching of image data during tracking) if app.ARGS.nocrop: From f65a3947aa49b9375cae1f82d1cca0d15fc577f4 Mon Sep 17 00:00:00 2001 From: mblesac2 Date: Tue, 16 Nov 2021 13:41:03 +0000 Subject: [PATCH 04/16] Fix syntax errors Co-authored-by: Manuel Blesa Co-authored-by: Paola Galdi --- lib/mrtrix3/_5ttgen/neonatal.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/mrtrix3/_5ttgen/neonatal.py b/lib/mrtrix3/_5ttgen/neonatal.py index 04c53c1d39..b4408c69e2 100644 --- a/lib/mrtrix3/_5ttgen/neonatal.py +++ b/lib/mrtrix3/_5ttgen/neonatal.py @@ -22,11 +22,11 @@ DHCP_CGM = list(range(5, 40)) DHCP_SGM = [17, 18] -DHCP_WM = [19] + range(40, 49) + range(51, 83) + range(85, 88) +DHCP_WM = [19] + list(range(40, 49)) + list(range(51, 83)) + list(range(85, 88)) DHCP_CSF = [49, 50, 83] DHCP_AMYG_HIPP = list(range(1, 5)) -MCRIB_CGM = list(range(1000, 1036) + range(2000, 2036)) +MCRIB_CGM = list(range(1000, 1004)) + list(range(1005,1036)) + list(range(2000, 2004)) + list(range(2005,2036)) MCRIB_SGM = [9, 11, 12, 13, 26, 48, 50, 51, 52, 58] MCRIB_WM = [2, 41, 75, 76, 90, 170, 192] MCRIB_CSF = [4, 14, 15, 24, 43] @@ -121,7 +121,7 @@ def execute(): #pylint: disable=unused-variable + ants_options) run.command('antsJointFusion -d 3 -t input.nii --verbose 1 ' - + ' '.join('-g input_parcellation_template_hist_%02d_%d_Warped.nii.gz -l input_parcellation_template_hist_%02d_%d_WarpedLabels.nii.gz' % (i, i-1) for i in range(1, 11)) + + ' '.join('-g input_parcellation_template_hist_%02d_%d_Warped.nii.gz -l input_parcellation_template_hist_%02d_%d_WarpedLabels.nii.gz' % (i, i-1, i, i-1) for i in range(1, 11)) + ' -o [input_parcellation_Labels.nii.gz,input_parcellation_Intensity.nii.gz,posterior%04d.nii.gz]') if app.ARGS.dhcp_path: @@ -152,7 +152,7 @@ def execute(): #pylint: disable=unused-variable for tissue, indices in { 'cGM': MCRIB_CGM + ([] if app.ARGS.sgm_amyg_hipp else MCRIB_AMYG_HIPP), 'sGM': MCRIB_SGM + MCRIB_CEREBELLAR + (MCRIB_AMYG_HIPP if app.ARGS.sgm_amyg_hipp else []), 'WM' : MCRIB_WM, - 'CSF': MCRIB_CSF }: + 'CSF': MCRIB_CSF }.items(): run.command(['mrmath', ['posterior%04d.nii.gz' % i for i in indices], 'sum', tissue + '.mif']) #Force normalization From a7f31886539c485b75bcb3e0fbd1d23afd406507 Mon Sep 17 00:00:00 2001 From: mblesac2 Date: Tue, 16 Nov 2021 14:05:43 +0000 Subject: [PATCH 05/16] Remove histogram matching Co-authored-by: Manuel Blesa Co-authored-by: Paola Galdi --- lib/mrtrix3/_5ttgen/neonatal.py | 17 ++++------------- 1 file changed, 4 insertions(+), 13 deletions(-) diff --git a/lib/mrtrix3/_5ttgen/neonatal.py b/lib/mrtrix3/_5ttgen/neonatal.py index b4408c69e2..11649ea747 100644 --- a/lib/mrtrix3/_5ttgen/neonatal.py +++ b/lib/mrtrix3/_5ttgen/neonatal.py @@ -78,8 +78,8 @@ def get_inputs(): #pylint: disable=unused-variable run.command('mrconvert ' + path.from_user(app.ARGS.mask) + ' ' + path.to_scratch('mask.mif') + ' -datatype bit -strides -1,+2,+3') mcrib_import = utils.RunList('Importing M-CRIB data to scratch directory', 20) for i in range(1, 11): - mcrib_import.command(['mrconvert', os.path.join(mcrib_dir, ('M-CRIB_P%02d_' % i) + ('T1_registered_to_T2' if app.ARGS.modality == 't1w' else 'T2') + '.nii.gz'), path.to_scratch('template_%02d.mif' % i)]) - mcrib_import.command(['mrconvert', os.path.join(mcrib_dir, 'M-CRIB_orig_P%02d_parc.nii.gz' % i), path.to_scratch('template_labels_%02d.mif' % i, False)]) + mcrib_import.command(['mrconvert', os.path.join(mcrib_dir, ('M-CRIB_P%02d_' % i) + ('T1_registered_to_T2' if app.ARGS.modality == 't1w' else 'T2') + '.nii.gz'), path.to_scratch('template_%02d.nii' % i)]) + mcrib_import.command(['mrconvert', os.path.join(mcrib_dir, 'M-CRIB_orig_P%02d_parc.nii.gz' % i), path.to_scratch('template_labels_%02d.nii' % i, False)]) if app.ARGS.dhcp_path: dhcp_dir = os.path.abspath(path.from_user(app.ARGS.dhcp_path, False)) dhcp_import = utils.RunList('Importing dHCP data to scratch directory', 87) @@ -101,27 +101,18 @@ def execute(): #pylint: disable=unused-variable run.command('mrconvert input.mif input.nii') run.command('mrconvert mask.mif mask.nii -datatype bit') - histmatch = utils.RunList('Histogram-matching template images to input image', 50) - for i in range(1, 11): - s = '%02d' % i - histmatch.command('mrthreshold template_%s.mif mask_template_%s.mif -abs 0.5' % (s, s)) - histmatch.command('mrhistmatch -mask_input mask_template_%s.mif -mask_target mask.mif scale template_%s.mif input.mif template_hist_%s.mif' % (s, s, s)) - histmatch.command('mrconvert template_hist_%s.mif template_hist_%s.nii' % (s, s)) - histmatch.command('mrconvert mask_template_%s.mif mask_template_%s.nii' % (s, s)) - histmatch.command('mrconvert template_labels_%s.mif template_labels_%s.nii' % (s, s)) - ants_options = ' -q {} -c {} -k 1'.format(1 if app.ARGS.quick else 0, app.ARGS.ants_parallel) if app.ARGS.ants_parallel == 2: ants_options += ' -j {}'.format(2 if app.ARGS.nthreads is None else app.ARGS.nthreads) app.debug('ANTs command-line options for JointLabelFusion: "' + ants_options + '"') run.command('antsJointLabelFusion.sh -d 3 -t input.nii -p posterior%04d.nii.gz ' - + ' '.join('-g template_hist_%02d.nii -l template_labels_%02d.nii' % (i, i) for i in range(1, 11)) + + ' '.join('-g template_%02d.nii -l template_labels_%02d.nii' % (i, i) for i in range(1, 11)) + ' -o input_parcellation_' + ants_options) run.command('antsJointFusion -d 3 -t input.nii --verbose 1 ' - + ' '.join('-g input_parcellation_template_hist_%02d_%d_Warped.nii.gz -l input_parcellation_template_hist_%02d_%d_WarpedLabels.nii.gz' % (i, i-1, i, i-1) for i in range(1, 11)) + + ' '.join('-g input_parcellation_template_%02d_%d_Warped.nii.gz -l input_parcellation_template_%02d_%d_WarpedLabels.nii.gz' % (i, i-1, i, i-1) for i in range(1, 11)) + ' -o [input_parcellation_Labels.nii.gz,input_parcellation_Intensity.nii.gz,posterior%04d.nii.gz]') if app.ARGS.dhcp_path: From 246cfca259a9cf41413f6906350e245a1ba6f650 Mon Sep 17 00:00:00 2001 From: mblesac2 Date: Tue, 16 Nov 2021 15:59:14 +0000 Subject: [PATCH 06/16] Neonatal algorithm split in two: neonatal_mcrib and neonatal_dhcp Co-authored-by: Manuel Blesa Co-authored-by: Paola Galdi --- .../_5ttgen/{neonatal.py => neonatal_dhcp.py} | 63 ++++----- lib/mrtrix3/_5ttgen/neonatal_mcrib.py | 121 ++++++++++++++++++ 2 files changed, 143 insertions(+), 41 deletions(-) rename lib/mrtrix3/_5ttgen/{neonatal.py => neonatal_dhcp.py} (73%) create mode 100644 lib/mrtrix3/_5ttgen/neonatal_mcrib.py diff --git a/lib/mrtrix3/_5ttgen/neonatal.py b/lib/mrtrix3/_5ttgen/neonatal_dhcp.py similarity index 73% rename from lib/mrtrix3/_5ttgen/neonatal.py rename to lib/mrtrix3/_5ttgen/neonatal_dhcp.py index 11649ea747..aef3233604 100644 --- a/lib/mrtrix3/_5ttgen/neonatal.py +++ b/lib/mrtrix3/_5ttgen/neonatal_dhcp.py @@ -20,37 +20,31 @@ -DHCP_CGM = list(range(5, 40)) +DHCP_CGM = list(range(5, 17)) + list(range(20,40)) DHCP_SGM = [17, 18] DHCP_WM = [19] + list(range(40, 49)) + list(range(51, 83)) + list(range(85, 88)) DHCP_CSF = [49, 50, 83] DHCP_AMYG_HIPP = list(range(1, 5)) -MCRIB_CGM = list(range(1000, 1004)) + list(range(1005,1036)) + list(range(2000, 2004)) + list(range(2005,2036)) MCRIB_SGM = [9, 11, 12, 13, 26, 48, 50, 51, 52, 58] -MCRIB_WM = [2, 41, 75, 76, 90, 170, 192] -MCRIB_CSF = [4, 14, 15, 24, 43] -MCRIB_AMYG_HIPP = [17, 18, 53, 54] -MCRIB_CEREBELLAR = [91, 93] def usage(base_parser, subparsers): #pylint: disable=unused-variable - parser = subparsers.add_parser('neonatal', parents=[base_parser]) + parser = subparsers.add_parser('neonatal_dhcp', parents=[base_parser]) parser.set_author('Manuel Blesa (manuel.blesa@ed.ac.uk), Paola Galdi (paola.galdi@ed.ac.uk) and Robert E. Smith (robert.smith@florey.edu.au)') - parser.set_synopsis('Use ANTs commands and the M-CRIB atlas to generate the 5TT image of a neonatal subject based on a T1-weighted or T2-weighted image') - parser.add_description('When the -dhcp_path option is used, derivation of the 5TT image will be principally based on the segmentation already performed in the dHCP pipeline. The M-CRIB atlas will only be used to introduce additional sub-cortical grey matter parcels into the tissue segmentation. For this operation to be applicable, the dHCP pipeline must have been executed with the -additional command-line flag, and the modality of the input image must be T2-weighted. Use of this mode of operation is generally encouraged.') + parser.set_synopsis('Use ANTs commands, the output of the dHCP pipeline and the M-CRIB atlas to generate the 5TT image of a neonatal subject based on a T2-weighted image') + parser.add_description('Derivation of the 5TT image is principally based on the segmentation already performed in the dHCP pipeline. The M-CRIB atlas will only be used to introduce additional sub-cortical grey matter parcels into the tissue segmentation. For this operation to be applicable, the dHCP pipeline must have been executed with the -additional command-line flag, and the modality of the input image must be T2-weighted.') parser.add_citation('Blesa, M.; Galdi, P.; Cox, S.R.; Sullivan, G.; Stoye, D.Q.; Lamb, G.L.; Quigley, A.J.; Thrippleton, M.J.; Escudero, J.; Bastin, M.E.; Smith, K.M. & Boardman. J.P. Hierarchical complexity of the macro-scale neonatal brain. Cerebral Cortex, 2021, 4, 2071-2084', is_external=True) parser.add_citation('Avants, B.; Epstein, C.; Grossman, M. & Gee, J. Symmetric diffeomorphic image registration with cross-correlation: evaluating automated labeling of elderly and neurodegenerative brain. 2008, Medical Image Analysis, 41, 12-26', is_external=True) parser.add_citation('Wang, H.; Suh, J.W.; Das, S.R.; Pluta, J.B.; Craige, C. & Yushkevich, P.A. Multi-atlas segmentation with joint label fusion. IEEE Trans Pattern Anal Mach Intell., 2013, 35, 611–623.', is_external=True) parser.add_citation('Alexander, B.; Murray, A.L.; Loh, W.Y.; Matthews, L.G.; Adamson, C.; Beare, R.; Chen, J.; Kelly, C.E.; Rees, S.; Warfield, S.K.; Anderson, P.J.; Doyle, L.W.; Spittle, A.J.; Cheong, J.L.Y; Seal, M.L. & Thompson, D.K. A new neonatal cortical and subcortical brain atlas: the Melbourne Children’s Regional Infant Brain (m-crib) atlas. NeuroImage, 2017, 852, 147-841.', is_external=True) - parser.add_citation('Makropoulos, A., Robinson, E.C., Schuh, A., Wright, R., Fitzgibbon, S., Bozek, J., Counsell, S.J., Steinweg, J., Vecchiato, K., Passerat-Palmbach, J., Lenz, G., Mortari, F., Tenev, T., Duff, E.P., Bastiani, M., Cordero-Grande, L., Hughes, E., Tusor, N., Tournier, J.D., Hutter, J., Price, A.N., Teixeira, R.P.A.G., Murgasova, M., Victor, S., Kelly, C., Rutherford, M.A., Smith, S.M., Edwards, A.D., Hajnal, J.V., Jenkinson, M. & Rueckert, D. The developing human connectome project: A minimal processing pipeline for neonatal cortical surface reconstruction. NeuroImage, 2018, 173, 88-112.', condition='If -dhcp_path option is used') + parser.add_citation('Makropoulos, A., Robinson, E.C., Schuh, A., Wright, R., Fitzgibbon, S., Bozek, J., Counsell, S.J., Steinweg, J., Vecchiato, K., Passerat-Palmbach, J., Lenz, G., Mortari, F., Tenev, T., Duff, E.P., Bastiani, M., Cordero-Grande, L., Hughes, E., Tusor, N., Tournier, J.D., Hutter, J., Price, A.N., Teixeira, R.P.A.G., Murgasova, M., Victor, S., Kelly, C., Rutherford, M.A., Smith, S.M., Edwards, A.D., Hajnal, J.V., Jenkinson, M. & Rueckert, D. The developing human connectome project: A minimal processing pipeline for neonatal cortical surface reconstruction. NeuroImage, 2018, 173, 88-112.') parser.add_argument('input', help='The input structural image') - parser.add_argument('modality', choices=["t1w", "t2w"], help='Specify the modality of the input image, either "t1w" or "t2w"') parser.add_argument('output', help='The output 5TT image') - options = parser.add_argument_group('Options specific to the \'neonatal\' algorithm') + options = parser.add_argument_group('Options specific to the \'neonatal_dhcp\' algorithm') options.add_argument('-mask', type=str, help='Manually provide a brain mask, MANDATORY', required=True) - options.add_argument('-dhcp_path', type=str, help='Provide the path of the tissue probability maps (posteriors/) obtained by the dHCP pipeline (see Description)') + options.add_argument('-dhcp_path', type=str, help='Provide the path of the tissue probability maps (posteriors/) obtained by the dHCP pipeline (see Description), MANDATORY', required=True) options.add_argument('-mcrib_path', type=str, help='Provide the path of the M-CRIB atlas (note: this can alternatively be specified in the MRtrix config file as "MCRIBPath")') options.add_argument('-parcellation', type=str, help='Additionally export the M-CRIB parcellation warped to the subject data') options.add_argument('-quick', action="store_true", help='Specify the use of quick registration parameters') @@ -64,9 +58,6 @@ def check_output_paths(): #pylint: disable=unused-variable def get_inputs(): #pylint: disable=unused-variable - if app.ARGS.dhcp_path: - if app.ARGS.modality == "t1w": - raise MRtrixError('Modality has to be "t2w" for the dHCP option to work') if app.ARGS.mcrib_path: mcrib_dir = os.path.abspath(path.from_user(app.ARGS.mcrib_path, False)) elif 'MCRIBPath' in CONFIG: @@ -78,7 +69,7 @@ def get_inputs(): #pylint: disable=unused-variable run.command('mrconvert ' + path.from_user(app.ARGS.mask) + ' ' + path.to_scratch('mask.mif') + ' -datatype bit -strides -1,+2,+3') mcrib_import = utils.RunList('Importing M-CRIB data to scratch directory', 20) for i in range(1, 11): - mcrib_import.command(['mrconvert', os.path.join(mcrib_dir, ('M-CRIB_P%02d_' % i) + ('T1_registered_to_T2' if app.ARGS.modality == 't1w' else 'T2') + '.nii.gz'), path.to_scratch('template_%02d.nii' % i)]) + mcrib_import.command(['mrconvert', os.path.join(mcrib_dir, 'M-CRIB_P%02d_T2.nii.gz' % i), path.to_scratch('template_%02d.nii' % i)]) mcrib_import.command(['mrconvert', os.path.join(mcrib_dir, 'M-CRIB_orig_P%02d_parc.nii.gz' % i), path.to_scratch('template_labels_%02d.nii' % i, False)]) if app.ARGS.dhcp_path: dhcp_dir = os.path.abspath(path.from_user(app.ARGS.dhcp_path, False)) @@ -115,36 +106,26 @@ def execute(): #pylint: disable=unused-variable + ' '.join('-g input_parcellation_template_%02d_%d_Warped.nii.gz -l input_parcellation_template_%02d_%d_WarpedLabels.nii.gz' % (i, i-1, i, i-1) for i in range(1, 11)) + ' -o [input_parcellation_Labels.nii.gz,input_parcellation_Intensity.nii.gz,posterior%04d.nii.gz]') - if app.ARGS.dhcp_path: - - for tissue, indices in { 'cGM': DHCP_CGM + ([] if app.ARGS.sgm_amyg_hipp else DHCP_AMYG_HIPP), + for tissue, indices in { 'cGM': DHCP_CGM + ([] if app.ARGS.sgm_amyg_hipp else DHCP_AMYG_HIPP), 'sGM': DHCP_SGM + (DHCP_AMYG_HIPP if app.ARGS.sgm_amyg_hipp else []), 'WM' : DHCP_WM, - 'CSF': DHCP_CSF }: - run.command(['mrmath', ['label_%d.mif' % i for i in indices], 'sum', 'Pmap-' + tissue + '.mif']) + 'CSF': DHCP_CSF }.items(): + run.command(['mrmath', ['label_%d.mif' % i for i in indices], 'sum', 'Pmap-' + tissue + '.mif']) - # Uncompress just once, since we need to read multiple times - run.command('mrconvert input_parcellation_Labels.nii.gz input_parcellation_Labels.nii') + # Uncompress just once, since we need to read multiple times + run.command('mrconvert input_parcellation_Labels.nii.gz input_parcellation_Labels.nii') - #extract sGM from M-CRIB - run.command('mrcalc ' + ' '.join('input_parcellation_Labels.nii ' + str(i) + ' -eq' for i in MCRIB_SGM) + ' ' + ' '.join(['-add'] * (len(MCRIB_SGM) - 1)) + ' sGM_mcrib.mif') + #extract sGM from M-CRIB + run.command('mrcalc ' + ' '.join('input_parcellation_Labels.nii ' + str(i) + ' -eq' for i in MCRIB_SGM) + ' ' + ' '.join(['-add'] * (len(MCRIB_SGM) - 1)) + ' sGM_mcrib.mif') - #refine the WM - run.command('mrcalc sGM_mcrib.mif 0.5 -lt Pmap-WM.mif -mult Pmap-WM-corr.mif') - - #normalize 0-1 and combine - run.command('mrcalc Pmap-cGM.mif 0.01 -mult GM.nii.gz') - run.command('mrcalc Pmap-sGM.mif 0.01 -mult sGM_mcrib.mif -add sGM.nii.gz') - run.command('mrcalc Pmap-WM-corr.mif 0.01 -mult WM.nii.gz') - run.command('mrcalc Pmap-CSF.mif 0.01 -mult CSF.nii.gz') - - else: + #refine the WM + run.command('mrcalc sGM_mcrib.mif 0.5 -lt Pmap-WM.mif -mult Pmap-WM-corr.mif') - for tissue, indices in { 'cGM': MCRIB_CGM + ([] if app.ARGS.sgm_amyg_hipp else MCRIB_AMYG_HIPP), - 'sGM': MCRIB_SGM + MCRIB_CEREBELLAR + (MCRIB_AMYG_HIPP if app.ARGS.sgm_amyg_hipp else []), - 'WM' : MCRIB_WM, - 'CSF': MCRIB_CSF }.items(): - run.command(['mrmath', ['posterior%04d.nii.gz' % i for i in indices], 'sum', tissue + '.mif']) + #normalize 0-1 and combine + run.command('mrcalc Pmap-cGM.mif 0.01 -mult cGM.mif') + run.command('mrcalc Pmap-sGM.mif 0.01 -mult sGM_mcrib.mif -add sGM.mif') + run.command('mrcalc Pmap-WM-corr.mif 0.01 -mult WM.mif') + run.command('mrcalc Pmap-CSF.mif 0.01 -mult CSF.mif') #Force normalization run.command('mrmath WM.mif cGM.mif sGM.mif CSF.mif sum tissue_sum.mif') diff --git a/lib/mrtrix3/_5ttgen/neonatal_mcrib.py b/lib/mrtrix3/_5ttgen/neonatal_mcrib.py new file mode 100644 index 0000000000..f17ef7b02f --- /dev/null +++ b/lib/mrtrix3/_5ttgen/neonatal_mcrib.py @@ -0,0 +1,121 @@ +# Copyright (c) 2008-2020 the MRtrix3 contributors. +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# Covered Software is provided under this License on an "as is" +# basis, without warranty of any kind, either expressed, implied, or +# statutory, including, without limitation, warranties that the +# Covered Software is free of defects, merchantable, fit for a +# particular purpose or non-infringing. +# See the Mozilla Public License v. 2.0 for more details. +# +# For more details, see http://www.mrtrix.org/. + +import glob, math, os +from distutils.spawn import find_executable +from mrtrix3 import CONFIG, MRtrixError +from mrtrix3 import app, image, path, run, utils + + +MCRIB_CGM = list(range(1000, 1004)) + list(range(1005,1036)) + list(range(2000, 2004)) + list(range(2005,2036)) +MCRIB_SGM = [9, 11, 12, 13, 26, 48, 50, 51, 52, 58] +MCRIB_WM = [2, 41, 75, 76, 90, 170, 192] +MCRIB_CSF = [4, 14, 15, 24, 43] +MCRIB_AMYG_HIPP = [17, 18, 53, 54] +MCRIB_CEREBELLAR = [91, 93] + + +def usage(base_parser, subparsers): #pylint: disable=unused-variable + parser = subparsers.add_parser('neonatal_mcrib', parents=[base_parser]) + parser.set_author('Manuel Blesa (manuel.blesa@ed.ac.uk), Paola Galdi (paola.galdi@ed.ac.uk) and Robert E. Smith (robert.smith@florey.edu.au)') + parser.set_synopsis('Use ANTs commands and the M-CRIB atlas to generate the 5TT image of a neonatal subject based on a T1-weighted or T2-weighted image') + parser.add_description('This command creates the 5TT file for human neonatal subjects. The M-CRIB atlas is used to idenity the different tissues.') + parser.add_citation('Blesa, M.; Galdi, P.; Cox, S.R.; Sullivan, G.; Stoye, D.Q.; Lamb, G.L.; Quigley, A.J.; Thrippleton, M.J.; Escudero, J.; Bastin, M.E.; Smith, K.M. & Boardman. J.P. Hierarchical complexity of the macro-scale neonatal brain. Cerebral Cortex, 2021, 4, 2071-2084', is_external=True) + parser.add_citation('Avants, B.; Epstein, C.; Grossman, M. & Gee, J. Symmetric diffeomorphic image registration with cross-correlation: evaluating automated labeling of elderly and neurodegenerative brain. 2008, Medical Image Analysis, 41, 12-26', is_external=True) + parser.add_citation('Wang, H.; Suh, J.W.; Das, S.R.; Pluta, J.B.; Craige, C. & Yushkevich, P.A. Multi-atlas segmentation with joint label fusion. IEEE Trans Pattern Anal Mach Intell., 2013, 35, 611–623.', is_external=True) + parser.add_citation('Alexander, B.; Murray, A.L.; Loh, W.Y.; Matthews, L.G.; Adamson, C.; Beare, R.; Chen, J.; Kelly, C.E.; Rees, S.; Warfield, S.K.; Anderson, P.J.; Doyle, L.W.; Spittle, A.J.; Cheong, J.L.Y; Seal, M.L. & Thompson, D.K. A new neonatal cortical and subcortical brain atlas: the Melbourne Children’s Regional Infant Brain (m-crib) atlas. NeuroImage, 2017, 852, 147-841.', is_external=True) + parser.add_argument('input', help='The input structural image') + parser.add_argument('modality', choices=["t1w", "t2w"], help='Specify the modality of the input image, either "t1w" or "t2w"') + parser.add_argument('output', help='The output 5TT image') + options = parser.add_argument_group('Options specific to the \'neonatal_mcrib\' algorithm') + options.add_argument('-mask', type=str, help='Manually provide a brain mask, MANDATORY', required=True) + options.add_argument('-mcrib_path', type=str, help='Provide the path of the M-CRIB atlas (note: this can alternatively be specified in the MRtrix config file as "MCRIBPath")') + options.add_argument('-parcellation', type=str, help='Additionally export the M-CRIB parcellation warped to the subject data') + options.add_argument('-quick', action="store_true", help='Specify the use of quick registration parameters') + options.add_argument('-ants_parallel', default=0, type=int, help='Control for parallel computation for antsJointLabelFusion (default 0) -- 0 == run serially, 1 == SGE qsub, 2 == use PEXEC (localhost), 3 == Apple XGrid, 4 == PBS qsub, 5 == SLURM.') + + + +def check_output_paths(): #pylint: disable=unused-variable + app.check_output_path(app.ARGS.output) + + + +def get_inputs(): #pylint: disable=unused-variable + if app.ARGS.mcrib_path: + mcrib_dir = os.path.abspath(path.from_user(app.ARGS.mcrib_path, False)) + elif 'MCRIBPath' in CONFIG: + mcrib_dir = CONFIG.get('MCRIBPath') + else: + raise MRtrixError('The MCRIB atlas path needs to be specified either in the config file ("MCRIBPath") or with the command-line option -mcrib_path') + image.check_3d_nonunity(path.from_user(app.ARGS.input, False)) + run.command('mrconvert ' + path.from_user(app.ARGS.input) + ' ' + path.to_scratch('input_raw.mif')) + run.command('mrconvert ' + path.from_user(app.ARGS.mask) + ' ' + path.to_scratch('mask.mif') + ' -datatype bit -strides -1,+2,+3') + mcrib_import = utils.RunList('Importing M-CRIB data to scratch directory', 20) + for i in range(1, 11): + mcrib_import.command(['mrconvert', os.path.join(mcrib_dir, ('M-CRIB_P%02d_' % i) + ('T1_registered_to_T2' if app.ARGS.modality == 't1w' else 'T2') + '.nii.gz'), path.to_scratch('template_%02d.nii' % i)]) + mcrib_import.command(['mrconvert', os.path.join(mcrib_dir, 'M-CRIB_orig_P%02d_parc.nii.gz' % i), path.to_scratch('template_labels_%02d.nii' % i, False)]) + + +def execute(): #pylint: disable=unused-variable + if not find_executable('antsJointLabelFusion.sh'): + raise MRtrixError('Could not find ANTS script antsJointLabelFusion.sh; please check installation') + + run.command('mrcalc input_raw.mif mask.mif -mul input.mif') + run.command('mrconvert input.mif input.nii') + run.command('mrconvert mask.mif mask.nii -datatype bit') + + ants_options = ' -q {} -c {} -k 1'.format(1 if app.ARGS.quick else 0, app.ARGS.ants_parallel) + if app.ARGS.ants_parallel == 2: + ants_options += ' -j {}'.format(2 if app.ARGS.nthreads is None else app.ARGS.nthreads) + app.debug('ANTs command-line options for JointLabelFusion: "' + ants_options + '"') + + run.command('antsJointLabelFusion.sh -d 3 -t input.nii -p posterior%04d.nii.gz ' + + ' '.join('-g template_%02d.nii -l template_labels_%02d.nii' % (i, i) for i in range(1, 11)) + + ' -o input_parcellation_' + + ants_options) + + run.command('antsJointFusion -d 3 -t input.nii --verbose 1 ' + + ' '.join('-g input_parcellation_template_%02d_%d_Warped.nii.gz -l input_parcellation_template_%02d_%d_WarpedLabels.nii.gz' % (i, i-1, i, i-1) for i in range(1, 11)) + + ' -o [input_parcellation_Labels.nii.gz,input_parcellation_Intensity.nii.gz,posterior%04d.nii.gz]') + + + for tissue, indices in { 'cGM': MCRIB_CGM + ([] if app.ARGS.sgm_amyg_hipp else MCRIB_AMYG_HIPP), + 'sGM': MCRIB_SGM + MCRIB_CEREBELLAR + (MCRIB_AMYG_HIPP if app.ARGS.sgm_amyg_hipp else []), + 'WM' : MCRIB_WM, + 'CSF': MCRIB_CSF }.items(): + run.command(['mrmath', ['posterior%04d.nii.gz' % i for i in indices], 'sum', tissue + '.mif']) + + #Force normalization + run.command('mrmath WM.mif cGM.mif sGM.mif CSF.mif sum tissue_sum.mif') + run.command('mrcalc mask.nii cGM.mif tissue_sum.mif -divide 0 -if cgm_norm.mif') + run.command('mrcalc mask.nii sGM.mif tissue_sum.mif -divide 0 -if sgm_norm.mif') + run.command('mrcalc mask.nii WM.mif tissue_sum.mif -divide 0 -if wm_norm.mif') + run.command('mrcalc mask.nii CSF.mif tissue_sum.mif -divide 0 -if csf_norm.mif') + + run.command('mrcalc csf_norm.mif 0 -mul path.mif') + + run.command('mrcat cgm_norm.mif sgm_norm.mif wm_norm.mif csf_norm.mif path.mif - -axis 3 | mrconvert - combined_precrop.mif -strides +2,+3,+4,+1') + + # Crop to reduce file size (improves caching of image data during tracking) + if app.ARGS.nocrop: + run.function(os.rename, 'combined_precrop.mif', 'result.mif') + else: + run.command('mrmath combined_precrop.mif sum - -axis 3 | mrthreshold - - -abs 0.5 | mrgrid combined_precrop.mif crop result.mif -mask -') + + run.command('mrconvert result.mif ' + path.from_user(app.ARGS.output), mrconvert_keyval=path.from_user(app.ARGS.input, False), force=app.FORCE_OVERWRITE) + + if app.ARGS.parcellation: + run.command('mrconvert input_parcellation_Labels.nii.gz ' + path.from_user(app.ARGS.parcellation), mrconvert_keyval=path.from_user(app.ARGS.input, False), force=app.FORCE_OVERWRITE) From db20d6a88dea3e93a677bca33955c42341417880 Mon Sep 17 00:00:00 2001 From: mblesac2 Date: Tue, 23 Nov 2021 11:55:57 +0000 Subject: [PATCH 07/16] Renaming algorithms and modification of the dhcp (using path as an input) Manuel Blesa Paola Galdi --- .../_5ttgen/{neonatal_dhcp.py => dhcp.py} | 74 ++++++++++++------- .../_5ttgen/{neonatal_mcrib.py => mcrib.py} | 6 +- 2 files changed, 51 insertions(+), 29 deletions(-) rename lib/mrtrix3/_5ttgen/{neonatal_dhcp.py => dhcp.py} (72%) rename lib/mrtrix3/_5ttgen/{neonatal_mcrib.py => mcrib.py} (98%) diff --git a/lib/mrtrix3/_5ttgen/neonatal_dhcp.py b/lib/mrtrix3/_5ttgen/dhcp.py similarity index 72% rename from lib/mrtrix3/_5ttgen/neonatal_dhcp.py rename to lib/mrtrix3/_5ttgen/dhcp.py index aef3233604..603e63f29b 100644 --- a/lib/mrtrix3/_5ttgen/neonatal_dhcp.py +++ b/lib/mrtrix3/_5ttgen/dhcp.py @@ -31,20 +31,18 @@ def usage(base_parser, subparsers): #pylint: disable=unused-variable - parser = subparsers.add_parser('neonatal_dhcp', parents=[base_parser]) + parser = subparsers.add_parser('dhcp', parents=[base_parser]) parser.set_author('Manuel Blesa (manuel.blesa@ed.ac.uk), Paola Galdi (paola.galdi@ed.ac.uk) and Robert E. Smith (robert.smith@florey.edu.au)') parser.set_synopsis('Use ANTs commands, the output of the dHCP pipeline and the M-CRIB atlas to generate the 5TT image of a neonatal subject based on a T2-weighted image') - parser.add_description('Derivation of the 5TT image is principally based on the segmentation already performed in the dHCP pipeline. The M-CRIB atlas will only be used to introduce additional sub-cortical grey matter parcels into the tissue segmentation. For this operation to be applicable, the dHCP pipeline must have been executed with the -additional command-line flag, and the modality of the input image must be T2-weighted.') + parser.add_description('Derivation of the 5TT image is principally based on the segmentation already performed in the dHCP pipeline. The M-CRIB atlas will only be used to introduce additional sub-cortical grey matter parcels into the tissue segmentation. For this operation to be applicable, the dHCP pipeline must have been executed with the -additional command-line flag.') parser.add_citation('Blesa, M.; Galdi, P.; Cox, S.R.; Sullivan, G.; Stoye, D.Q.; Lamb, G.L.; Quigley, A.J.; Thrippleton, M.J.; Escudero, J.; Bastin, M.E.; Smith, K.M. & Boardman. J.P. Hierarchical complexity of the macro-scale neonatal brain. Cerebral Cortex, 2021, 4, 2071-2084', is_external=True) parser.add_citation('Avants, B.; Epstein, C.; Grossman, M. & Gee, J. Symmetric diffeomorphic image registration with cross-correlation: evaluating automated labeling of elderly and neurodegenerative brain. 2008, Medical Image Analysis, 41, 12-26', is_external=True) parser.add_citation('Wang, H.; Suh, J.W.; Das, S.R.; Pluta, J.B.; Craige, C. & Yushkevich, P.A. Multi-atlas segmentation with joint label fusion. IEEE Trans Pattern Anal Mach Intell., 2013, 35, 611–623.', is_external=True) parser.add_citation('Alexander, B.; Murray, A.L.; Loh, W.Y.; Matthews, L.G.; Adamson, C.; Beare, R.; Chen, J.; Kelly, C.E.; Rees, S.; Warfield, S.K.; Anderson, P.J.; Doyle, L.W.; Spittle, A.J.; Cheong, J.L.Y; Seal, M.L. & Thompson, D.K. A new neonatal cortical and subcortical brain atlas: the Melbourne Children’s Regional Infant Brain (m-crib) atlas. NeuroImage, 2017, 852, 147-841.', is_external=True) parser.add_citation('Makropoulos, A., Robinson, E.C., Schuh, A., Wright, R., Fitzgibbon, S., Bozek, J., Counsell, S.J., Steinweg, J., Vecchiato, K., Passerat-Palmbach, J., Lenz, G., Mortari, F., Tenev, T., Duff, E.P., Bastiani, M., Cordero-Grande, L., Hughes, E., Tusor, N., Tournier, J.D., Hutter, J., Price, A.N., Teixeira, R.P.A.G., Murgasova, M., Victor, S., Kelly, C., Rutherford, M.A., Smith, S.M., Edwards, A.D., Hajnal, J.V., Jenkinson, M. & Rueckert, D. The developing human connectome project: A minimal processing pipeline for neonatal cortical surface reconstruction. NeuroImage, 2018, 173, 88-112.') - parser.add_argument('input', help='The input structural image') + parser.add_argument('input', help='The input path of the derivates folder (anat/) obtained from the dHCP pipeline') parser.add_argument('output', help='The output 5TT image') - options = parser.add_argument_group('Options specific to the \'neonatal_dhcp\' algorithm') - options.add_argument('-mask', type=str, help='Manually provide a brain mask, MANDATORY', required=True) - options.add_argument('-dhcp_path', type=str, help='Provide the path of the tissue probability maps (posteriors/) obtained by the dHCP pipeline (see Description), MANDATORY', required=True) + options = parser.add_argument_group('Options specific to the \'dhcp\' algorithm') options.add_argument('-mcrib_path', type=str, help='Provide the path of the M-CRIB atlas (note: this can alternatively be specified in the MRtrix config file as "MCRIBPath")') options.add_argument('-parcellation', type=str, help='Additionally export the M-CRIB parcellation warped to the subject data') options.add_argument('-quick', action="store_true", help='Specify the use of quick registration parameters') @@ -64,23 +62,37 @@ def get_inputs(): #pylint: disable=unused-variable mcrib_dir = CONFIG.get('MCRIBPath') else: raise MRtrixError('The MCRIB atlas path needs to be specified either in the config file ("MCRIBPath") or with the command-line option -mcrib_path') - image.check_3d_nonunity(path.from_user(app.ARGS.input, False)) - run.command('mrconvert ' + path.from_user(app.ARGS.input) + ' ' + path.to_scratch('input_raw.mif')) - run.command('mrconvert ' + path.from_user(app.ARGS.mask) + ' ' + path.to_scratch('mask.mif') + ' -datatype bit -strides -1,+2,+3') + + dhcp_dir = os.path.abspath(path.from_user(app.ARGS.input, False)) + + if os.path.isfile(glob.glob(os.path.join(dhcp_dir, '*_T2w_restore.nii.gz'))[0]): + run.command('mrconvert ' + glob.glob(os.path.join(dhcp_dir, '*_T2w_restore.nii.gz'))[0] + ' ' + path.to_scratch('input_raw.mif')) + elif os.path.isfile(glob.glob(os.path.join(dhcp_dir, '*restore_T2w.nii.gz'))[0]): + run.command('mrconvert ' + glob.glob(os.path.join(dhcp_dir, '*_restore_T2w.nii.gz'))[0] + ' ' + path.to_scratch('input_raw.mif')) + else: + raise MRtrixError('Could not find a T2w image in the dHCP folder; please check that the file exists') + + if os.path.isfile(glob.glob(os.path.join(dhcp_dir, '*_brainmask_drawem.nii.gz'))[0]): + run.command('mrconvert ' + glob.glob(os.path.join(dhcp_dir, '*_brainmask_drawem.nii.gz'))[0] + ' ' + path.to_scratch('mask.mif') + ' -datatype bit -strides -1,+2,+3') + elif os.path.isfile(glob.glob(os.path.join(dhcp_dir, '*-brain_mask.nii.gz'))[0]): + run.command('mrconvert ' + glob.glob(os.path.join(dhcp_dir, '*-brain_mask.nii.gz'))[0] + ' ' + path.to_scratch('mask.mif') + ' -datatype bit -strides -1,+2,+3') + else: + raise MRtrixError('Could not find a brain mask in the dHCP folder; please check that the file exists') + mcrib_import = utils.RunList('Importing M-CRIB data to scratch directory', 20) for i in range(1, 11): mcrib_import.command(['mrconvert', os.path.join(mcrib_dir, 'M-CRIB_P%02d_T2.nii.gz' % i), path.to_scratch('template_%02d.nii' % i)]) mcrib_import.command(['mrconvert', os.path.join(mcrib_dir, 'M-CRIB_orig_P%02d_parc.nii.gz' % i), path.to_scratch('template_labels_%02d.nii' % i, False)]) - if app.ARGS.dhcp_path: - dhcp_dir = os.path.abspath(path.from_user(app.ARGS.dhcp_path, False)) - dhcp_import = utils.RunList('Importing dHCP data to scratch directory', 87) - for i in range(1, 88): - images = glob.glob(os.path.join(dhcp_dir, '*_drawem_seg%d.nii.gz' % i)) - if not images: - raise MRtrixError('Unable to find dHCP image for parcel %d in location "' % i + dhcp_dir + '"') - if len(images) > 1: - raise MRtrixError('Multiple dHCP images found for parcel %d in location "' % i + dhcp_dir + '"') - dhcp_import.command(['mrconvert', images[0], path.to_scratch('label_%d.mif' % i, False)]) + + dhcp_import = utils.RunList('Importing dHCP data to scratch directory', 87) + dhcp_dir_posteriors = os.path.join(dhcp_dir, 'posteriors/') + for i in range(1, 88): + images = glob.glob(os.path.join(dhcp_dir_posteriors, '*_drawem_seg%d.nii.gz' % i)) + if not images: + raise MRtrixError('Unable to find dHCP image for parcel %d in location "' % i + dhcp_dir_posteriors + '"') + if len(images) > 1: + raise MRtrixError('Multiple dHCP images found for parcel %d in location "' % i + dhcp_dir_posteriors + '"') + dhcp_import.command(['mrconvert', images[0], path.to_scratch('label_%d.mif' % i, False)]) @@ -102,9 +114,9 @@ def execute(): #pylint: disable=unused-variable + ' -o input_parcellation_' + ants_options) - run.command('antsJointFusion -d 3 -t input.nii --verbose 1 ' - + ' '.join('-g input_parcellation_template_%02d_%d_Warped.nii.gz -l input_parcellation_template_%02d_%d_WarpedLabels.nii.gz' % (i, i-1, i, i-1) for i in range(1, 11)) - + ' -o [input_parcellation_Labels.nii.gz,input_parcellation_Intensity.nii.gz,posterior%04d.nii.gz]') +# run.command('antsJointFusion -d 3 -t input.nii --verbose 1 ' +# + ' '.join('-g input_parcellation_template_%02d_%d_Warped.nii.gz -l input_parcellation_template_%02d_%d_WarpedLabels.nii.gz' % (i, i-1, i, i-1) for i in range(1, 11)) +# + ' -o [input_parcellation_Labels.nii.gz,input_parcellation_Intensity.nii.gz,posterior%04d.nii.gz]') for tissue, indices in { 'cGM': DHCP_CGM + ([] if app.ARGS.sgm_amyg_hipp else DHCP_AMYG_HIPP), 'sGM': DHCP_SGM + (DHCP_AMYG_HIPP if app.ARGS.sgm_amyg_hipp else []), @@ -123,10 +135,14 @@ def execute(): #pylint: disable=unused-variable #normalize 0-1 and combine run.command('mrcalc Pmap-cGM.mif 0.01 -mult cGM.mif') - run.command('mrcalc Pmap-sGM.mif 0.01 -mult sGM_mcrib.mif -add sGM.mif') + run.command('mrcalc Pmap-sGM.mif 0.01 -mult sGM_mcrib.mif -add sGM_uncorrected.mif') run.command('mrcalc Pmap-WM-corr.mif 0.01 -mult WM.mif') run.command('mrcalc Pmap-CSF.mif 0.01 -mult CSF.mif') + #impose CSF of dHCP over sGM, every voxel with CSF > 0.5 will be removed from the sGM, to avoid issues later on at the normalization + run.command('mrthreshold CSF.mif -abs 0.5 -invert CSF_filter.mif') + run.command('mrcalc sGM_uncorrected.mif CSF_filter.mif -mult sGM.mif') + #Force normalization run.command('mrmath WM.mif cGM.mif sGM.mif CSF.mif sum tissue_sum.mif') run.command('mrcalc mask.nii cGM.mif tissue_sum.mif -divide 0 -if cgm_norm.mif') @@ -144,7 +160,13 @@ def execute(): #pylint: disable=unused-variable else: run.command('mrmath combined_precrop.mif sum - -axis 3 | mrthreshold - - -abs 0.5 | mrgrid combined_precrop.mif crop result.mif -mask -') - run.command('mrconvert result.mif ' + path.from_user(app.ARGS.output), mrconvert_keyval=path.from_user(app.ARGS.input, False), force=app.FORCE_OVERWRITE) - + dhcp_dir = os.path.abspath(path.from_user(app.ARGS.input, False)) + if os.path.isfile(glob.glob(os.path.join(dhcp_dir, '*_T2w_restore.nii.gz'))[0]): + file = glob.glob(os.path.join(dhcp_dir, '*_T2w_restore.nii.gz'))[0] + else: + file = glob.glob(os.path.join(dhcp_dir, '*_restore_T2w.nii.gz'))[0] + + run.command('mrconvert result.mif ' + path.from_user(app.ARGS.output), mrconvert_keyval=path.from_user(file, False), force=app.FORCE_OVERWRITE) if app.ARGS.parcellation: - run.command('mrconvert input_parcellation_Labels.nii.gz ' + path.from_user(app.ARGS.parcellation), mrconvert_keyval=path.from_user(app.ARGS.input, False), force=app.FORCE_OVERWRITE) + run.command('mrconvert input_parcellation_Labels.nii.gz ' + path.from_user(app.ARGS.parcellation), mrconvert_keyval=path.from_user(file, False), force=app.FORCE_OVERWRITE) + diff --git a/lib/mrtrix3/_5ttgen/neonatal_mcrib.py b/lib/mrtrix3/_5ttgen/mcrib.py similarity index 98% rename from lib/mrtrix3/_5ttgen/neonatal_mcrib.py rename to lib/mrtrix3/_5ttgen/mcrib.py index f17ef7b02f..c0246b31cc 100644 --- a/lib/mrtrix3/_5ttgen/neonatal_mcrib.py +++ b/lib/mrtrix3/_5ttgen/mcrib.py @@ -18,7 +18,7 @@ from mrtrix3 import CONFIG, MRtrixError from mrtrix3 import app, image, path, run, utils - +# Labels 1004 and 2004 are not present in the M-CRIB atlas MCRIB_CGM = list(range(1000, 1004)) + list(range(1005,1036)) + list(range(2000, 2004)) + list(range(2005,2036)) MCRIB_SGM = [9, 11, 12, 13, 26, 48, 50, 51, 52, 58] MCRIB_WM = [2, 41, 75, 76, 90, 170, 192] @@ -28,7 +28,7 @@ def usage(base_parser, subparsers): #pylint: disable=unused-variable - parser = subparsers.add_parser('neonatal_mcrib', parents=[base_parser]) + parser = subparsers.add_parser('mcrib', parents=[base_parser]) parser.set_author('Manuel Blesa (manuel.blesa@ed.ac.uk), Paola Galdi (paola.galdi@ed.ac.uk) and Robert E. Smith (robert.smith@florey.edu.au)') parser.set_synopsis('Use ANTs commands and the M-CRIB atlas to generate the 5TT image of a neonatal subject based on a T1-weighted or T2-weighted image') parser.add_description('This command creates the 5TT file for human neonatal subjects. The M-CRIB atlas is used to idenity the different tissues.') @@ -39,7 +39,7 @@ def usage(base_parser, subparsers): #pylint: disable=unused-variable parser.add_argument('input', help='The input structural image') parser.add_argument('modality', choices=["t1w", "t2w"], help='Specify the modality of the input image, either "t1w" or "t2w"') parser.add_argument('output', help='The output 5TT image') - options = parser.add_argument_group('Options specific to the \'neonatal_mcrib\' algorithm') + options = parser.add_argument_group('Options specific to the \'mcrib\' algorithm') options.add_argument('-mask', type=str, help='Manually provide a brain mask, MANDATORY', required=True) options.add_argument('-mcrib_path', type=str, help='Provide the path of the M-CRIB atlas (note: this can alternatively be specified in the MRtrix config file as "MCRIBPath")') options.add_argument('-parcellation', type=str, help='Additionally export the M-CRIB parcellation warped to the subject data') From 7438c0d22c5a6d9c0372a94601da9c9bc7396a41 Mon Sep 17 00:00:00 2001 From: mblesac2 Date: Fri, 26 Nov 2021 17:41:19 +0000 Subject: [PATCH 08/16] Addition of the option to use hard of soft segmentations to both neonatal algorithms Co-authored-by: Manuel Blesa Co-authored-by: Paola Galdi --- lib/mrtrix3/_5ttgen/dhcp.py | 101 ++++++++++++++++++++++------------- lib/mrtrix3/_5ttgen/mcrib.py | 13 +++-- 2 files changed, 73 insertions(+), 41 deletions(-) diff --git a/lib/mrtrix3/_5ttgen/dhcp.py b/lib/mrtrix3/_5ttgen/dhcp.py index 603e63f29b..0f631e1311 100644 --- a/lib/mrtrix3/_5ttgen/dhcp.py +++ b/lib/mrtrix3/_5ttgen/dhcp.py @@ -31,10 +31,10 @@ def usage(base_parser, subparsers): #pylint: disable=unused-variable - parser = subparsers.add_parser('dhcp', parents=[base_parser]) + parser = subparsers.add_parser('dhcp_binary', parents=[base_parser]) parser.set_author('Manuel Blesa (manuel.blesa@ed.ac.uk), Paola Galdi (paola.galdi@ed.ac.uk) and Robert E. Smith (robert.smith@florey.edu.au)') parser.set_synopsis('Use ANTs commands, the output of the dHCP pipeline and the M-CRIB atlas to generate the 5TT image of a neonatal subject based on a T2-weighted image') - parser.add_description('Derivation of the 5TT image is principally based on the segmentation already performed in the dHCP pipeline. The M-CRIB atlas will only be used to introduce additional sub-cortical grey matter parcels into the tissue segmentation. For this operation to be applicable, the dHCP pipeline must have been executed with the -additional command-line flag.') + parser.add_description('Derivation of the 5TT image is principally based on the segmentation already performed in the dHCP pipeline. The M-CRIB atlas will only be used to introduce additional sub-cortical grey matter parcels into the tissue segmentation. By default, the algorithm will use the tissue probability maps obtained from the dHCP. However, if the pipeline was executed without the -additional command-line flag, the algorithm will use the hard segmentation.') parser.add_citation('Blesa, M.; Galdi, P.; Cox, S.R.; Sullivan, G.; Stoye, D.Q.; Lamb, G.L.; Quigley, A.J.; Thrippleton, M.J.; Escudero, J.; Bastin, M.E.; Smith, K.M. & Boardman. J.P. Hierarchical complexity of the macro-scale neonatal brain. Cerebral Cortex, 2021, 4, 2071-2084', is_external=True) parser.add_citation('Avants, B.; Epstein, C.; Grossman, M. & Gee, J. Symmetric diffeomorphic image registration with cross-correlation: evaluating automated labeling of elderly and neurodegenerative brain. 2008, Medical Image Analysis, 41, 12-26', is_external=True) parser.add_citation('Wang, H.; Suh, J.W.; Das, S.R.; Pluta, J.B.; Craige, C. & Yushkevich, P.A. Multi-atlas segmentation with joint label fusion. IEEE Trans Pattern Anal Mach Intell., 2013, 35, 611–623.', is_external=True) @@ -42,10 +42,11 @@ def usage(base_parser, subparsers): #pylint: disable=unused-variable parser.add_citation('Makropoulos, A., Robinson, E.C., Schuh, A., Wright, R., Fitzgibbon, S., Bozek, J., Counsell, S.J., Steinweg, J., Vecchiato, K., Passerat-Palmbach, J., Lenz, G., Mortari, F., Tenev, T., Duff, E.P., Bastiani, M., Cordero-Grande, L., Hughes, E., Tusor, N., Tournier, J.D., Hutter, J., Price, A.N., Teixeira, R.P.A.G., Murgasova, M., Victor, S., Kelly, C., Rutherford, M.A., Smith, S.M., Edwards, A.D., Hajnal, J.V., Jenkinson, M. & Rueckert, D. The developing human connectome project: A minimal processing pipeline for neonatal cortical surface reconstruction. NeuroImage, 2018, 173, 88-112.') parser.add_argument('input', help='The input path of the derivates folder (anat/) obtained from the dHCP pipeline') parser.add_argument('output', help='The output 5TT image') - options = parser.add_argument_group('Options specific to the \'dhcp\' algorithm') + options = parser.add_argument_group('Options specific to the \'dhcp_binary\' algorithm') options.add_argument('-mcrib_path', type=str, help='Provide the path of the M-CRIB atlas (note: this can alternatively be specified in the MRtrix config file as "MCRIBPath")') options.add_argument('-parcellation', type=str, help='Additionally export the M-CRIB parcellation warped to the subject data') options.add_argument('-quick', action="store_true", help='Specify the use of quick registration parameters') + options.add_argument('-hard_segmentation', action="store_true", help='Specify the use of hard segmentation instead of the soft segmentation to generate the 5TT') options.add_argument('-ants_parallel', default=0, type=int, help='Control for parallel computation for antsJointLabelFusion (default 0) -- 0 == run serially, 1 == SGE qsub, 2 == use PEXEC (localhost), 3 == Apple XGrid, 4 == PBS qsub, 5 == SLURM.') @@ -65,17 +66,15 @@ def get_inputs(): #pylint: disable=unused-variable dhcp_dir = os.path.abspath(path.from_user(app.ARGS.input, False)) - if os.path.isfile(glob.glob(os.path.join(dhcp_dir, '*_T2w_restore.nii.gz'))[0]): - run.command('mrconvert ' + glob.glob(os.path.join(dhcp_dir, '*_T2w_restore.nii.gz'))[0] + ' ' + path.to_scratch('input_raw.mif')) - elif os.path.isfile(glob.glob(os.path.join(dhcp_dir, '*restore_T2w.nii.gz'))[0]): - run.command('mrconvert ' + glob.glob(os.path.join(dhcp_dir, '*_restore_T2w.nii.gz'))[0] + ' ' + path.to_scratch('input_raw.mif')) + T2_file = glob.glob(os.path.join(dhcp_dir, '*_T2w_restore.nii.gz')) + glob.glob(os.path.join(dhcp_dir, '*restore_T2w.nii.gz')) + if T2_file: + run.command('mrconvert ' + T2_file[0] + ' ' + path.to_scratch('input_raw.mif')) else: raise MRtrixError('Could not find a T2w image in the dHCP folder; please check that the file exists') - if os.path.isfile(glob.glob(os.path.join(dhcp_dir, '*_brainmask_drawem.nii.gz'))[0]): - run.command('mrconvert ' + glob.glob(os.path.join(dhcp_dir, '*_brainmask_drawem.nii.gz'))[0] + ' ' + path.to_scratch('mask.mif') + ' -datatype bit -strides -1,+2,+3') - elif os.path.isfile(glob.glob(os.path.join(dhcp_dir, '*-brain_mask.nii.gz'))[0]): - run.command('mrconvert ' + glob.glob(os.path.join(dhcp_dir, '*-brain_mask.nii.gz'))[0] + ' ' + path.to_scratch('mask.mif') + ' -datatype bit -strides -1,+2,+3') + MASK_file = glob.glob(os.path.join(dhcp_dir, '*_brainmask_drawem.nii.gz')) + glob.glob(os.path.join(dhcp_dir, '**-brain_mask.nii.gz')) + if MASK_file: + run.command('mrconvert ' + MASK_file[0] + ' ' + path.to_scratch('mask.mif') + ' -datatype bit -strides -1,+2,+3') else: raise MRtrixError('Could not find a brain mask in the dHCP folder; please check that the file exists') @@ -86,13 +85,26 @@ def get_inputs(): #pylint: disable=unused-variable dhcp_import = utils.RunList('Importing dHCP data to scratch directory', 87) dhcp_dir_posteriors = os.path.join(dhcp_dir, 'posteriors/') - for i in range(1, 88): - images = glob.glob(os.path.join(dhcp_dir_posteriors, '*_drawem_seg%d.nii.gz' % i)) - if not images: - raise MRtrixError('Unable to find dHCP image for parcel %d in location "' % i + dhcp_dir_posteriors + '"') - if len(images) > 1: - raise MRtrixError('Multiple dHCP images found for parcel %d in location "' % i + dhcp_dir_posteriors + '"') - dhcp_import.command(['mrconvert', images[0], path.to_scratch('label_%d.mif' % i, False)]) + use_hard_segmentation = False + if app.ARGS.hard_segmentation: + use_hard_segmentation = True + elif not dhcp_dir_posteriors: + app.warn('No tissue posteriors found (-additional flag not used in the dHCP pipeline); output will be hard segmentation') + use_hard_segmentation = True + if use_hard_segmentation: + Labels = glob.glob(os.path.join(dhcp_dir, '*_drawem_all_labels.nii.gz')) + glob.glob(os.path.join(dhcp_dir, '*-drawem87*.nii.gz')) + if Labels: + dhcp_import.command('mrconvert ' + Labels[0] + ' ' + path.to_scratch('all_labels_dHCP.mif') + ' -strides -1,+2,+3') + else: + raise MRtrixError('Could not find a binary segmentation in the dHCP folder; please check that the file exists') + else: + for i in range(1, 88): + images = glob.glob(os.path.join(dhcp_dir_posteriors, '*_drawem_seg%d.nii.gz' % i)) + if not images: + raise MRtrixError('Unable to find dHCP image for parcel %d in location "' % i + dhcp_dir_posteriors + '"') + if len(images) > 1: + raise MRtrixError('Multiple dHCP images found for parcel %d in location "' % i + dhcp_dir_posteriors + '"') + dhcp_import.command(['mrconvert', images[0], path.to_scratch('label_%d.mif' % i, False)]) @@ -100,10 +112,19 @@ def execute(): #pylint: disable=unused-variable if not find_executable('antsJointLabelFusion.sh'): raise MRtrixError('Could not find ANTS script antsJointLabelFusion.sh; please check installation') + dhcp_dir = os.path.abspath(path.from_user(app.ARGS.input, False)) + dhcp_dir_posteriors = os.path.join(dhcp_dir, 'posteriors/') run.command('mrcalc input_raw.mif mask.mif -mul input.mif') run.command('mrconvert input.mif input.nii') run.command('mrconvert mask.mif mask.nii -datatype bit') + use_hard_segmentation = False + if app.ARGS.hard_segmentation: + use_hard_segmentation = True + elif not dhcp_dir_posteriors: + app.warn('No tissue posteriors found (-additional flag not used in the dHCP pipeline); output will be hard segmentation') + use_hard_segmentation = True + ants_options = ' -q {} -c {} -k 1'.format(1 if app.ARGS.quick else 0, app.ARGS.ants_parallel) if app.ARGS.ants_parallel == 2: ants_options += ' -j {}'.format(2 if app.ARGS.nthreads is None else app.ARGS.nthreads) @@ -114,26 +135,37 @@ def execute(): #pylint: disable=unused-variable + ' -o input_parcellation_' + ants_options) -# run.command('antsJointFusion -d 3 -t input.nii --verbose 1 ' -# + ' '.join('-g input_parcellation_template_%02d_%d_Warped.nii.gz -l input_parcellation_template_%02d_%d_WarpedLabels.nii.gz' % (i, i-1, i, i-1) for i in range(1, 11)) -# + ' -o [input_parcellation_Labels.nii.gz,input_parcellation_Intensity.nii.gz,posterior%04d.nii.gz]') + run.command('antsJointFusion -d 3 -t input.nii --verbose 1 ' + + ' '.join('-g input_parcellation_template_%02d_%d_Warped.nii.gz -l input_parcellation_template_%02d_%d_WarpedLabels.nii.gz' % (i, i-1, i, i-1) for i in range(1, 11)) + + ' -o [input_parcellation_Labels.nii.gz,input_parcellation_Intensity.nii.gz,posterior%04d.nii.gz]') - for tissue, indices in { 'cGM': DHCP_CGM + ([] if app.ARGS.sgm_amyg_hipp else DHCP_AMYG_HIPP), + if use_hard_segmentation: + for tissue, indices in { 'cGM': DHCP_CGM + ([] if app.ARGS.sgm_amyg_hipp else DHCP_AMYG_HIPP), 'sGM': DHCP_SGM + (DHCP_AMYG_HIPP if app.ARGS.sgm_amyg_hipp else []), 'WM' : DHCP_WM, 'CSF': DHCP_CSF }.items(): - run.command(['mrmath', ['label_%d.mif' % i for i in indices], 'sum', 'Pmap-' + tissue + '.mif']) - + run.command('mrcalc ' + ' '.join('all_labels_dHCP.mif ' + str(i) + ' -eq' for i in indices) + ' ' + ' '.join(['-add'] * (len(indices) - 1)) + ' Pmap-' + tissue + '.mif') # Uncompress just once, since we need to read multiple times - run.command('mrconvert input_parcellation_Labels.nii.gz input_parcellation_Labels.nii') - + run.command('mrconvert input_parcellation_Labels.nii.gz input_parcellation_Labels.nii') #extract sGM from M-CRIB - run.command('mrcalc ' + ' '.join('input_parcellation_Labels.nii ' + str(i) + ' -eq' for i in MCRIB_SGM) + ' ' + ' '.join(['-add'] * (len(MCRIB_SGM) - 1)) + ' sGM_mcrib.mif') - + run.command('mrcalc ' + ' '.join('input_parcellation_Labels.nii ' + str(i) + ' -eq' for i in MCRIB_SGM) + ' ' + ' '.join(['-add'] * (len(MCRIB_SGM) - 1)) + ' sGM_mcrib.mif') + #refine the WM + run.command('mrcalc sGM_mcrib.mif 0.5 -lt Pmap-WM.mif -mult Pmap-WM-corr.mif') + else: + for tissue, indices in { 'cGM': DHCP_CGM + ([] if app.ARGS.sgm_amyg_hipp else DHCP_AMYG_HIPP), + 'sGM': DHCP_SGM + (DHCP_AMYG_HIPP if app.ARGS.sgm_amyg_hipp else []), + 'WM' : DHCP_WM, + 'CSF': DHCP_CSF }.items(): + run.command(['mrmath', ['label_%d.mif' % i for i in indices], 'sum', 'Pmap-' + tissue + '.mif']) + # Uncompress just once, since we need to read multiple times + run.command('mrconvert input_parcellation_Labels.nii.gz input_parcellation_Labels.nii') + #extract sGM from M-CRIB + run.command(['mrmath', ['posterior%04d.nii.gz' % i for i in MCRIB_SGM], 'sum', 'sGM_mcrib.mif']) #refine the WM - run.command('mrcalc sGM_mcrib.mif 0.5 -lt Pmap-WM.mif -mult Pmap-WM-corr.mif') + run.command('mrcalc sGM_mcrib.mif 0.1 -lt Pmap-WM.mif -mult Pmap-WM-corr.mif') #normalize 0-1 and combine + run.command('mrcalc Pmap-cGM.mif 0.01 -mult cGM.mif') run.command('mrcalc Pmap-sGM.mif 0.01 -mult sGM_mcrib.mif -add sGM_uncorrected.mif') run.command('mrcalc Pmap-WM-corr.mif 0.01 -mult WM.mif') @@ -160,13 +192,8 @@ def execute(): #pylint: disable=unused-variable else: run.command('mrmath combined_precrop.mif sum - -axis 3 | mrthreshold - - -abs 0.5 | mrgrid combined_precrop.mif crop result.mif -mask -') - dhcp_dir = os.path.abspath(path.from_user(app.ARGS.input, False)) - if os.path.isfile(glob.glob(os.path.join(dhcp_dir, '*_T2w_restore.nii.gz'))[0]): - file = glob.glob(os.path.join(dhcp_dir, '*_T2w_restore.nii.gz'))[0] - else: - file = glob.glob(os.path.join(dhcp_dir, '*_restore_T2w.nii.gz'))[0] - - run.command('mrconvert result.mif ' + path.from_user(app.ARGS.output), mrconvert_keyval=path.from_user(file, False), force=app.FORCE_OVERWRITE) + T2_file = glob.glob(os.path.join(dhcp_dir, '*_T2w_restore.nii.gz')) + glob.glob(os.path.join(dhcp_dir, '*restore_T2w.nii.gz')) + run.command('mrconvert result.mif ' + path.from_user(app.ARGS.output), mrconvert_keyval=path.from_user(T2_file[0], False), force=app.FORCE_OVERWRITE) if app.ARGS.parcellation: - run.command('mrconvert input_parcellation_Labels.nii.gz ' + path.from_user(app.ARGS.parcellation), mrconvert_keyval=path.from_user(file, False), force=app.FORCE_OVERWRITE) + run.command('mrconvert input_parcellation_Labels.nii.gz ' + path.from_user(app.ARGS.parcellation), mrconvert_keyval=path.from_user(T2_file[0], False), force=app.FORCE_OVERWRITE) diff --git a/lib/mrtrix3/_5ttgen/mcrib.py b/lib/mrtrix3/_5ttgen/mcrib.py index c0246b31cc..5aa9d3f673 100644 --- a/lib/mrtrix3/_5ttgen/mcrib.py +++ b/lib/mrtrix3/_5ttgen/mcrib.py @@ -28,7 +28,7 @@ def usage(base_parser, subparsers): #pylint: disable=unused-variable - parser = subparsers.add_parser('mcrib', parents=[base_parser]) + parser = subparsers.add_parser('mcrib_binary', parents=[base_parser]) parser.set_author('Manuel Blesa (manuel.blesa@ed.ac.uk), Paola Galdi (paola.galdi@ed.ac.uk) and Robert E. Smith (robert.smith@florey.edu.au)') parser.set_synopsis('Use ANTs commands and the M-CRIB atlas to generate the 5TT image of a neonatal subject based on a T1-weighted or T2-weighted image') parser.add_description('This command creates the 5TT file for human neonatal subjects. The M-CRIB atlas is used to idenity the different tissues.') @@ -39,11 +39,12 @@ def usage(base_parser, subparsers): #pylint: disable=unused-variable parser.add_argument('input', help='The input structural image') parser.add_argument('modality', choices=["t1w", "t2w"], help='Specify the modality of the input image, either "t1w" or "t2w"') parser.add_argument('output', help='The output 5TT image') - options = parser.add_argument_group('Options specific to the \'mcrib\' algorithm') + options = parser.add_argument_group('Options specific to the \'mcrib_binary\' algorithm') options.add_argument('-mask', type=str, help='Manually provide a brain mask, MANDATORY', required=True) options.add_argument('-mcrib_path', type=str, help='Provide the path of the M-CRIB atlas (note: this can alternatively be specified in the MRtrix config file as "MCRIBPath")') options.add_argument('-parcellation', type=str, help='Additionally export the M-CRIB parcellation warped to the subject data') options.add_argument('-quick', action="store_true", help='Specify the use of quick registration parameters') + options.add_argument('-hard_segmentation', action="store_true", help='Specify the use of hard segmentation instead of the soft segmentation to generate the 5TT (NOTE: use of this option in this segmentation algorithm is not recommended)') options.add_argument('-ants_parallel', default=0, type=int, help='Control for parallel computation for antsJointLabelFusion (default 0) -- 0 == run serially, 1 == SGE qsub, 2 == use PEXEC (localhost), 3 == Apple XGrid, 4 == PBS qsub, 5 == SLURM.') @@ -91,12 +92,16 @@ def execute(): #pylint: disable=unused-variable + ' '.join('-g input_parcellation_template_%02d_%d_Warped.nii.gz -l input_parcellation_template_%02d_%d_WarpedLabels.nii.gz' % (i, i-1, i, i-1) for i in range(1, 11)) + ' -o [input_parcellation_Labels.nii.gz,input_parcellation_Intensity.nii.gz,posterior%04d.nii.gz]') - for tissue, indices in { 'cGM': MCRIB_CGM + ([] if app.ARGS.sgm_amyg_hipp else MCRIB_AMYG_HIPP), 'sGM': MCRIB_SGM + MCRIB_CEREBELLAR + (MCRIB_AMYG_HIPP if app.ARGS.sgm_amyg_hipp else []), 'WM' : MCRIB_WM, 'CSF': MCRIB_CSF }.items(): - run.command(['mrmath', ['posterior%04d.nii.gz' % i for i in indices], 'sum', tissue + '.mif']) + + if app.ARGS.hard_segmentation: + run.command('mrcalc ' + ' '.join('input_parcellation_Labels.nii.gz ' + str(i) + ' -eq' for i in indices) + ' ' + ' '.join(['-add'] * (len(indices) - 1)) + ' ' + tissue + '.mif') + else: + run.command(['mrmath', ['posterior%04d.nii.gz' % i for i in indices], 'sum', tissue + '.mif']) + #Force normalization run.command('mrmath WM.mif cGM.mif sGM.mif CSF.mif sum tissue_sum.mif') From 9260baf63d474533b0abc07bda6e8e9f6fe2ce67 Mon Sep 17 00:00:00 2001 From: Robert Smith Date: Mon, 29 Nov 2021 10:57:17 +1100 Subject: [PATCH 09/16] 5ttgen dhcp: Code cleanup - Ensure that input files are unique and unambiguous. - Remove redundant logic across get_inputs() and execute() regarding use of hard segmentation. - Simplify logic of primary conversion loop. - Generate sub-cortical grey matter image from M-CRIB only once, rather than once per tissue; this should facilitate code execution without using the -force option. --- lib/mrtrix3/_5ttgen/dhcp.py | 66 ++++++++++++++++--------------------- 1 file changed, 28 insertions(+), 38 deletions(-) diff --git a/lib/mrtrix3/_5ttgen/dhcp.py b/lib/mrtrix3/_5ttgen/dhcp.py index 0f631e1311..98cd6c0596 100644 --- a/lib/mrtrix3/_5ttgen/dhcp.py +++ b/lib/mrtrix3/_5ttgen/dhcp.py @@ -67,16 +67,18 @@ def get_inputs(): #pylint: disable=unused-variable dhcp_dir = os.path.abspath(path.from_user(app.ARGS.input, False)) T2_file = glob.glob(os.path.join(dhcp_dir, '*_T2w_restore.nii.gz')) + glob.glob(os.path.join(dhcp_dir, '*restore_T2w.nii.gz')) - if T2_file: - run.command('mrconvert ' + T2_file[0] + ' ' + path.to_scratch('input_raw.mif')) - else: + if not T2_file: raise MRtrixError('Could not find a T2w image in the dHCP folder; please check that the file exists') + if len(T2_file) > 1: + raise MRtrixError('Multiple candidate T2w images in the dHCP folder; please check directory contents') + run.command('mrconvert ' + T2_file[0] + ' ' + path.to_scratch('input_raw.mif')) MASK_file = glob.glob(os.path.join(dhcp_dir, '*_brainmask_drawem.nii.gz')) + glob.glob(os.path.join(dhcp_dir, '**-brain_mask.nii.gz')) - if MASK_file: - run.command('mrconvert ' + MASK_file[0] + ' ' + path.to_scratch('mask.mif') + ' -datatype bit -strides -1,+2,+3') - else: + if not MASK_file: raise MRtrixError('Could not find a brain mask in the dHCP folder; please check that the file exists') + if len(MASK_file) > 1: + raise MRtrixError('Multiple candidate brain mask image in the dHCP folder; please check directory contents') + run.command('mrconvert ' + MASK_file[0] + ' ' + path.to_scratch('mask.mif') + ' -datatype bit -strides -1,+2,+3') mcrib_import = utils.RunList('Importing M-CRIB data to scratch directory', 20) for i in range(1, 11): @@ -93,10 +95,11 @@ def get_inputs(): #pylint: disable=unused-variable use_hard_segmentation = True if use_hard_segmentation: Labels = glob.glob(os.path.join(dhcp_dir, '*_drawem_all_labels.nii.gz')) + glob.glob(os.path.join(dhcp_dir, '*-drawem87*.nii.gz')) - if Labels: - dhcp_import.command('mrconvert ' + Labels[0] + ' ' + path.to_scratch('all_labels_dHCP.mif') + ' -strides -1,+2,+3') - else: + if not Labels: raise MRtrixError('Could not find a binary segmentation in the dHCP folder; please check that the file exists') + if len(Labels) > 1: + raise MRtrixError('Multiple candidate binary segmentations in the dHCP folder; please check directory contents') + dhcp_import.command('mrconvert ' + Labels[0] + ' ' + path.to_scratch('all_labels_dHCP.mif') + ' -strides -1,+2,+3') else: for i in range(1, 88): images = glob.glob(os.path.join(dhcp_dir_posteriors, '*_drawem_seg%d.nii.gz' % i)) @@ -112,19 +115,10 @@ def execute(): #pylint: disable=unused-variable if not find_executable('antsJointLabelFusion.sh'): raise MRtrixError('Could not find ANTS script antsJointLabelFusion.sh; please check installation') - dhcp_dir = os.path.abspath(path.from_user(app.ARGS.input, False)) - dhcp_dir_posteriors = os.path.join(dhcp_dir, 'posteriors/') run.command('mrcalc input_raw.mif mask.mif -mul input.mif') run.command('mrconvert input.mif input.nii') run.command('mrconvert mask.mif mask.nii -datatype bit') - use_hard_segmentation = False - if app.ARGS.hard_segmentation: - use_hard_segmentation = True - elif not dhcp_dir_posteriors: - app.warn('No tissue posteriors found (-additional flag not used in the dHCP pipeline); output will be hard segmentation') - use_hard_segmentation = True - ants_options = ' -q {} -c {} -k 1'.format(1 if app.ARGS.quick else 0, app.ARGS.ants_parallel) if app.ARGS.ants_parallel == 2: ants_options += ' -j {}'.format(2 if app.ARGS.nthreads is None else app.ARGS.nthreads) @@ -139,33 +133,28 @@ def execute(): #pylint: disable=unused-variable + ' '.join('-g input_parcellation_template_%02d_%d_Warped.nii.gz -l input_parcellation_template_%02d_%d_WarpedLabels.nii.gz' % (i, i-1, i, i-1) for i in range(1, 11)) + ' -o [input_parcellation_Labels.nii.gz,input_parcellation_Intensity.nii.gz,posterior%04d.nii.gz]') + use_hard_segmentation = os.path.isfile('all_labels_dHCP.mif') if use_hard_segmentation: - for tissue, indices in { 'cGM': DHCP_CGM + ([] if app.ARGS.sgm_amyg_hipp else DHCP_AMYG_HIPP), - 'sGM': DHCP_SGM + (DHCP_AMYG_HIPP if app.ARGS.sgm_amyg_hipp else []), - 'WM' : DHCP_WM, - 'CSF': DHCP_CSF }.items(): - run.command('mrcalc ' + ' '.join('all_labels_dHCP.mif ' + str(i) + ' -eq' for i in indices) + ' ' + ' '.join(['-add'] * (len(indices) - 1)) + ' Pmap-' + tissue + '.mif') - # Uncompress just once, since we need to read multiple times + # Uncompress just once, since we need to read multiple times in the following command run.command('mrconvert input_parcellation_Labels.nii.gz input_parcellation_Labels.nii') - #extract sGM from M-CRIB + #extract sGM from M-CRIB run.command('mrcalc ' + ' '.join('input_parcellation_Labels.nii ' + str(i) + ' -eq' for i in MCRIB_SGM) + ' ' + ' '.join(['-add'] * (len(MCRIB_SGM) - 1)) + ' sGM_mcrib.mif') - #refine the WM - run.command('mrcalc sGM_mcrib.mif 0.5 -lt Pmap-WM.mif -mult Pmap-WM-corr.mif') else: - for tissue, indices in { 'cGM': DHCP_CGM + ([] if app.ARGS.sgm_amyg_hipp else DHCP_AMYG_HIPP), - 'sGM': DHCP_SGM + (DHCP_AMYG_HIPP if app.ARGS.sgm_amyg_hipp else []), - 'WM' : DHCP_WM, - 'CSF': DHCP_CSF }.items(): - run.command(['mrmath', ['label_%d.mif' % i for i in indices], 'sum', 'Pmap-' + tissue + '.mif']) - # Uncompress just once, since we need to read multiple times - run.command('mrconvert input_parcellation_Labels.nii.gz input_parcellation_Labels.nii') - #extract sGM from M-CRIB + #extract sGM from M-CRIB run.command(['mrmath', ['posterior%04d.nii.gz' % i for i in MCRIB_SGM], 'sum', 'sGM_mcrib.mif']) - #refine the WM - run.command('mrcalc sGM_mcrib.mif 0.1 -lt Pmap-WM.mif -mult Pmap-WM-corr.mif') + + for tissue, indices in { 'cGM': DHCP_CGM + ([] if app.ARGS.sgm_amyg_hipp else DHCP_AMYG_HIPP), + 'sGM': DHCP_SGM + (DHCP_AMYG_HIPP if app.ARGS.sgm_amyg_hipp else []), + 'WM' : DHCP_WM, + 'CSF': DHCP_CSF }.items(): + if use_hard_segmentation: + run.command('mrcalc ' + ' '.join('all_labels_dHCP.mif ' + str(i) + ' -eq' for i in indices) + ' ' + ' '.join(['-add'] * (len(indices) - 1)) + ' Pmap-' + tissue + '.mif') + else: + run.command(['mrmath', ['label_%d.mif' % i for i in indices], 'sum', 'Pmap-' + tissue + '.mif']) + #refine the WM + run.command('mrcalc sGM_mcrib.mif ' + ('0.5' if use_hard_segmentation else '0.1') + ' -lt Pmap-WM.mif -mult Pmap-WM-corr.mif') #normalize 0-1 and combine - run.command('mrcalc Pmap-cGM.mif 0.01 -mult cGM.mif') run.command('mrcalc Pmap-sGM.mif 0.01 -mult sGM_mcrib.mif -add sGM_uncorrected.mif') run.command('mrcalc Pmap-WM-corr.mif 0.01 -mult WM.mif') @@ -192,6 +181,7 @@ def execute(): #pylint: disable=unused-variable else: run.command('mrmath combined_precrop.mif sum - -axis 3 | mrthreshold - - -abs 0.5 | mrgrid combined_precrop.mif crop result.mif -mask -') + dhcp_dir = os.path.abspath(path.from_user(app.ARGS.input, False)) T2_file = glob.glob(os.path.join(dhcp_dir, '*_T2w_restore.nii.gz')) + glob.glob(os.path.join(dhcp_dir, '*restore_T2w.nii.gz')) run.command('mrconvert result.mif ' + path.from_user(app.ARGS.output), mrconvert_keyval=path.from_user(T2_file[0], False), force=app.FORCE_OVERWRITE) if app.ARGS.parcellation: From fe7fe1357520fdaf2e53ce27913e6b6e900fab30 Mon Sep 17 00:00:00 2001 From: Robert Smith Date: Tue, 30 Nov 2021 09:36:02 +1100 Subject: [PATCH 10/16] 5ttgen: Revert names of new algorithms --- lib/mrtrix3/_5ttgen/dhcp.py | 4 ++-- lib/mrtrix3/_5ttgen/mcrib.py | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/mrtrix3/_5ttgen/dhcp.py b/lib/mrtrix3/_5ttgen/dhcp.py index 98cd6c0596..4148aa6bed 100644 --- a/lib/mrtrix3/_5ttgen/dhcp.py +++ b/lib/mrtrix3/_5ttgen/dhcp.py @@ -31,7 +31,7 @@ def usage(base_parser, subparsers): #pylint: disable=unused-variable - parser = subparsers.add_parser('dhcp_binary', parents=[base_parser]) + parser = subparsers.add_parser('dhcp', parents=[base_parser]) parser.set_author('Manuel Blesa (manuel.blesa@ed.ac.uk), Paola Galdi (paola.galdi@ed.ac.uk) and Robert E. Smith (robert.smith@florey.edu.au)') parser.set_synopsis('Use ANTs commands, the output of the dHCP pipeline and the M-CRIB atlas to generate the 5TT image of a neonatal subject based on a T2-weighted image') parser.add_description('Derivation of the 5TT image is principally based on the segmentation already performed in the dHCP pipeline. The M-CRIB atlas will only be used to introduce additional sub-cortical grey matter parcels into the tissue segmentation. By default, the algorithm will use the tissue probability maps obtained from the dHCP. However, if the pipeline was executed without the -additional command-line flag, the algorithm will use the hard segmentation.') @@ -42,7 +42,7 @@ def usage(base_parser, subparsers): #pylint: disable=unused-variable parser.add_citation('Makropoulos, A., Robinson, E.C., Schuh, A., Wright, R., Fitzgibbon, S., Bozek, J., Counsell, S.J., Steinweg, J., Vecchiato, K., Passerat-Palmbach, J., Lenz, G., Mortari, F., Tenev, T., Duff, E.P., Bastiani, M., Cordero-Grande, L., Hughes, E., Tusor, N., Tournier, J.D., Hutter, J., Price, A.N., Teixeira, R.P.A.G., Murgasova, M., Victor, S., Kelly, C., Rutherford, M.A., Smith, S.M., Edwards, A.D., Hajnal, J.V., Jenkinson, M. & Rueckert, D. The developing human connectome project: A minimal processing pipeline for neonatal cortical surface reconstruction. NeuroImage, 2018, 173, 88-112.') parser.add_argument('input', help='The input path of the derivates folder (anat/) obtained from the dHCP pipeline') parser.add_argument('output', help='The output 5TT image') - options = parser.add_argument_group('Options specific to the \'dhcp_binary\' algorithm') + options = parser.add_argument_group('Options specific to the \'dhcp\' algorithm') options.add_argument('-mcrib_path', type=str, help='Provide the path of the M-CRIB atlas (note: this can alternatively be specified in the MRtrix config file as "MCRIBPath")') options.add_argument('-parcellation', type=str, help='Additionally export the M-CRIB parcellation warped to the subject data') options.add_argument('-quick', action="store_true", help='Specify the use of quick registration parameters') diff --git a/lib/mrtrix3/_5ttgen/mcrib.py b/lib/mrtrix3/_5ttgen/mcrib.py index 5aa9d3f673..a6a803468a 100644 --- a/lib/mrtrix3/_5ttgen/mcrib.py +++ b/lib/mrtrix3/_5ttgen/mcrib.py @@ -28,7 +28,7 @@ def usage(base_parser, subparsers): #pylint: disable=unused-variable - parser = subparsers.add_parser('mcrib_binary', parents=[base_parser]) + parser = subparsers.add_parser('mcrib', parents=[base_parser]) parser.set_author('Manuel Blesa (manuel.blesa@ed.ac.uk), Paola Galdi (paola.galdi@ed.ac.uk) and Robert E. Smith (robert.smith@florey.edu.au)') parser.set_synopsis('Use ANTs commands and the M-CRIB atlas to generate the 5TT image of a neonatal subject based on a T1-weighted or T2-weighted image') parser.add_description('This command creates the 5TT file for human neonatal subjects. The M-CRIB atlas is used to idenity the different tissues.') @@ -39,7 +39,7 @@ def usage(base_parser, subparsers): #pylint: disable=unused-variable parser.add_argument('input', help='The input structural image') parser.add_argument('modality', choices=["t1w", "t2w"], help='Specify the modality of the input image, either "t1w" or "t2w"') parser.add_argument('output', help='The output 5TT image') - options = parser.add_argument_group('Options specific to the \'mcrib_binary\' algorithm') + options = parser.add_argument_group('Options specific to the \'mcrib\' algorithm') options.add_argument('-mask', type=str, help='Manually provide a brain mask, MANDATORY', required=True) options.add_argument('-mcrib_path', type=str, help='Provide the path of the M-CRIB atlas (note: this can alternatively be specified in the MRtrix config file as "MCRIBPath")') options.add_argument('-parcellation', type=str, help='Additionally export the M-CRIB parcellation warped to the subject data') From 1bbb5938d9928452e3b99b89694d09f4f6511e0c Mon Sep 17 00:00:00 2001 From: Robert Smith Date: Tue, 30 Nov 2021 10:06:09 +1100 Subject: [PATCH 11/16] 5ttgen: pylint fixes for new algorithms --- lib/mrtrix3/_5ttgen/dhcp.py | 39 ++++++++++++++++++------------------ lib/mrtrix3/_5ttgen/mcrib.py | 6 +++--- 2 files changed, 22 insertions(+), 23 deletions(-) diff --git a/lib/mrtrix3/_5ttgen/dhcp.py b/lib/mrtrix3/_5ttgen/dhcp.py index 4148aa6bed..8e4c549ad9 100644 --- a/lib/mrtrix3/_5ttgen/dhcp.py +++ b/lib/mrtrix3/_5ttgen/dhcp.py @@ -13,10 +13,10 @@ # # For more details, see http://www.mrtrix.org/. -import glob, math, os +import glob, os from distutils.spawn import find_executable from mrtrix3 import CONFIG, MRtrixError -from mrtrix3 import app, image, path, run, utils +from mrtrix3 import app, path, run, utils @@ -39,7 +39,7 @@ def usage(base_parser, subparsers): #pylint: disable=unused-variable parser.add_citation('Avants, B.; Epstein, C.; Grossman, M. & Gee, J. Symmetric diffeomorphic image registration with cross-correlation: evaluating automated labeling of elderly and neurodegenerative brain. 2008, Medical Image Analysis, 41, 12-26', is_external=True) parser.add_citation('Wang, H.; Suh, J.W.; Das, S.R.; Pluta, J.B.; Craige, C. & Yushkevich, P.A. Multi-atlas segmentation with joint label fusion. IEEE Trans Pattern Anal Mach Intell., 2013, 35, 611–623.', is_external=True) parser.add_citation('Alexander, B.; Murray, A.L.; Loh, W.Y.; Matthews, L.G.; Adamson, C.; Beare, R.; Chen, J.; Kelly, C.E.; Rees, S.; Warfield, S.K.; Anderson, P.J.; Doyle, L.W.; Spittle, A.J.; Cheong, J.L.Y; Seal, M.L. & Thompson, D.K. A new neonatal cortical and subcortical brain atlas: the Melbourne Children’s Regional Infant Brain (m-crib) atlas. NeuroImage, 2017, 852, 147-841.', is_external=True) - parser.add_citation('Makropoulos, A., Robinson, E.C., Schuh, A., Wright, R., Fitzgibbon, S., Bozek, J., Counsell, S.J., Steinweg, J., Vecchiato, K., Passerat-Palmbach, J., Lenz, G., Mortari, F., Tenev, T., Duff, E.P., Bastiani, M., Cordero-Grande, L., Hughes, E., Tusor, N., Tournier, J.D., Hutter, J., Price, A.N., Teixeira, R.P.A.G., Murgasova, M., Victor, S., Kelly, C., Rutherford, M.A., Smith, S.M., Edwards, A.D., Hajnal, J.V., Jenkinson, M. & Rueckert, D. The developing human connectome project: A minimal processing pipeline for neonatal cortical surface reconstruction. NeuroImage, 2018, 173, 88-112.') + parser.add_citation('Makropoulos, A., Robinson, E.C., Schuh, A., Wright, R., Fitzgibbon, S., Bozek, J., Counsell, S.J., Steinweg, J., Vecchiato, K., Passerat-Palmbach, J., Lenz, G., Mortari, F., Tenev, T., Duff, E.P., Bastiani, M., Cordero-Grande, L., Hughes, E., Tusor, N., Tournier, J.D., Hutter, J., Price, A.N., Teixeira, R.P.A.G., Murgasova, M., Victor, S., Kelly, C., Rutherford, M.A., Smith, S.M., Edwards, A.D., Hajnal, J.V., Jenkinson, M. & Rueckert, D. The developing human connectome project: A minimal processing pipeline for neonatal cortical surface reconstruction. NeuroImage, 2018, 173, 88-112.') parser.add_argument('input', help='The input path of the derivates folder (anat/) obtained from the dHCP pipeline') parser.add_argument('output', help='The output 5TT image') options = parser.add_argument_group('Options specific to the \'dhcp\' algorithm') @@ -66,19 +66,19 @@ def get_inputs(): #pylint: disable=unused-variable dhcp_dir = os.path.abspath(path.from_user(app.ARGS.input, False)) - T2_file = glob.glob(os.path.join(dhcp_dir, '*_T2w_restore.nii.gz')) + glob.glob(os.path.join(dhcp_dir, '*restore_T2w.nii.gz')) - if not T2_file: + t2w_file = glob.glob(os.path.join(dhcp_dir, '*_T2w_restore.nii.gz')) + glob.glob(os.path.join(dhcp_dir, '*restore_T2w.nii.gz')) + if not t2w_file: raise MRtrixError('Could not find a T2w image in the dHCP folder; please check that the file exists') - if len(T2_file) > 1: + if len(t2w_file) > 1: raise MRtrixError('Multiple candidate T2w images in the dHCP folder; please check directory contents') - run.command('mrconvert ' + T2_file[0] + ' ' + path.to_scratch('input_raw.mif')) + run.command('mrconvert ' + t2w_file[0] + ' ' + path.to_scratch('input_raw.mif')) - MASK_file = glob.glob(os.path.join(dhcp_dir, '*_brainmask_drawem.nii.gz')) + glob.glob(os.path.join(dhcp_dir, '**-brain_mask.nii.gz')) - if not MASK_file: + mask_file = glob.glob(os.path.join(dhcp_dir, '*_brainmask_drawem.nii.gz')) + glob.glob(os.path.join(dhcp_dir, '**-brain_mask.nii.gz')) + if not mask_file: raise MRtrixError('Could not find a brain mask in the dHCP folder; please check that the file exists') - if len(MASK_file) > 1: + if len(mask_file) > 1: raise MRtrixError('Multiple candidate brain mask image in the dHCP folder; please check directory contents') - run.command('mrconvert ' + MASK_file[0] + ' ' + path.to_scratch('mask.mif') + ' -datatype bit -strides -1,+2,+3') + run.command('mrconvert ' + mask_file[0] + ' ' + path.to_scratch('mask.mif') + ' -datatype bit -strides -1,+2,+3') mcrib_import = utils.RunList('Importing M-CRIB data to scratch directory', 20) for i in range(1, 11): @@ -94,12 +94,12 @@ def get_inputs(): #pylint: disable=unused-variable app.warn('No tissue posteriors found (-additional flag not used in the dHCP pipeline); output will be hard segmentation') use_hard_segmentation = True if use_hard_segmentation: - Labels = glob.glob(os.path.join(dhcp_dir, '*_drawem_all_labels.nii.gz')) + glob.glob(os.path.join(dhcp_dir, '*-drawem87*.nii.gz')) - if not Labels: + labels = glob.glob(os.path.join(dhcp_dir, '*_drawem_all_labels.nii.gz')) + glob.glob(os.path.join(dhcp_dir, '*-drawem87*.nii.gz')) + if not labels: raise MRtrixError('Could not find a binary segmentation in the dHCP folder; please check that the file exists') - if len(Labels) > 1: + if len(labels) > 1: raise MRtrixError('Multiple candidate binary segmentations in the dHCP folder; please check directory contents') - dhcp_import.command('mrconvert ' + Labels[0] + ' ' + path.to_scratch('all_labels_dHCP.mif') + ' -strides -1,+2,+3') + dhcp_import.command('mrconvert ' + labels[0] + ' ' + path.to_scratch('all_labels_dHCP.mif') + ' -strides -1,+2,+3') else: for i in range(1, 88): images = glob.glob(os.path.join(dhcp_dir_posteriors, '*_drawem_seg%d.nii.gz' % i)) @@ -128,7 +128,7 @@ def execute(): #pylint: disable=unused-variable + ' '.join('-g template_%02d.nii -l template_labels_%02d.nii' % (i, i) for i in range(1, 11)) + ' -o input_parcellation_' + ants_options) - + run.command('antsJointFusion -d 3 -t input.nii --verbose 1 ' + ' '.join('-g input_parcellation_template_%02d_%d_Warped.nii.gz -l input_parcellation_template_%02d_%d_WarpedLabels.nii.gz' % (i, i-1, i, i-1) for i in range(1, 11)) + ' -o [input_parcellation_Labels.nii.gz,input_parcellation_Intensity.nii.gz,posterior%04d.nii.gz]') @@ -182,8 +182,7 @@ def execute(): #pylint: disable=unused-variable run.command('mrmath combined_precrop.mif sum - -axis 3 | mrthreshold - - -abs 0.5 | mrgrid combined_precrop.mif crop result.mif -mask -') dhcp_dir = os.path.abspath(path.from_user(app.ARGS.input, False)) - T2_file = glob.glob(os.path.join(dhcp_dir, '*_T2w_restore.nii.gz')) + glob.glob(os.path.join(dhcp_dir, '*restore_T2w.nii.gz')) - run.command('mrconvert result.mif ' + path.from_user(app.ARGS.output), mrconvert_keyval=path.from_user(T2_file[0], False), force=app.FORCE_OVERWRITE) + t2w_file = glob.glob(os.path.join(dhcp_dir, '*_T2w_restore.nii.gz')) + glob.glob(os.path.join(dhcp_dir, '*restore_T2w.nii.gz')) + run.command('mrconvert result.mif ' + path.from_user(app.ARGS.output), mrconvert_keyval=path.from_user(t2w_file[0], False), force=app.FORCE_OVERWRITE) if app.ARGS.parcellation: - run.command('mrconvert input_parcellation_Labels.nii.gz ' + path.from_user(app.ARGS.parcellation), mrconvert_keyval=path.from_user(T2_file[0], False), force=app.FORCE_OVERWRITE) - + run.command('mrconvert input_parcellation_Labels.nii.gz ' + path.from_user(app.ARGS.parcellation), mrconvert_keyval=path.from_user(t2w_file[0], False), force=app.FORCE_OVERWRITE) diff --git a/lib/mrtrix3/_5ttgen/mcrib.py b/lib/mrtrix3/_5ttgen/mcrib.py index a6a803468a..3ad42fdc99 100644 --- a/lib/mrtrix3/_5ttgen/mcrib.py +++ b/lib/mrtrix3/_5ttgen/mcrib.py @@ -13,7 +13,7 @@ # # For more details, see http://www.mrtrix.org/. -import glob, math, os +import os from distutils.spawn import find_executable from mrtrix3 import CONFIG, MRtrixError from mrtrix3 import app, image, path, run, utils @@ -87,7 +87,7 @@ def execute(): #pylint: disable=unused-variable + ' '.join('-g template_%02d.nii -l template_labels_%02d.nii' % (i, i) for i in range(1, 11)) + ' -o input_parcellation_' + ants_options) - + run.command('antsJointFusion -d 3 -t input.nii --verbose 1 ' + ' '.join('-g input_parcellation_template_%02d_%d_Warped.nii.gz -l input_parcellation_template_%02d_%d_WarpedLabels.nii.gz' % (i, i-1, i, i-1) for i in range(1, 11)) + ' -o [input_parcellation_Labels.nii.gz,input_parcellation_Intensity.nii.gz,posterior%04d.nii.gz]') @@ -121,6 +121,6 @@ def execute(): #pylint: disable=unused-variable run.command('mrmath combined_precrop.mif sum - -axis 3 | mrthreshold - - -abs 0.5 | mrgrid combined_precrop.mif crop result.mif -mask -') run.command('mrconvert result.mif ' + path.from_user(app.ARGS.output), mrconvert_keyval=path.from_user(app.ARGS.input, False), force=app.FORCE_OVERWRITE) - + if app.ARGS.parcellation: run.command('mrconvert input_parcellation_Labels.nii.gz ' + path.from_user(app.ARGS.parcellation), mrconvert_keyval=path.from_user(app.ARGS.input, False), force=app.FORCE_OVERWRITE) From c48e69a07eb50d38393fbbeefabc67639a277b38 Mon Sep 17 00:00:00 2001 From: pgaldi Date: Thu, 2 Dec 2021 15:48:21 +0000 Subject: [PATCH 12/16] removed EN-DASH from reference --- lib/mrtrix3/_5ttgen/dhcp.py | 2 +- lib/mrtrix3/_5ttgen/mcrib.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/mrtrix3/_5ttgen/dhcp.py b/lib/mrtrix3/_5ttgen/dhcp.py index 8e4c549ad9..87b2f168dc 100644 --- a/lib/mrtrix3/_5ttgen/dhcp.py +++ b/lib/mrtrix3/_5ttgen/dhcp.py @@ -37,7 +37,7 @@ def usage(base_parser, subparsers): #pylint: disable=unused-variable parser.add_description('Derivation of the 5TT image is principally based on the segmentation already performed in the dHCP pipeline. The M-CRIB atlas will only be used to introduce additional sub-cortical grey matter parcels into the tissue segmentation. By default, the algorithm will use the tissue probability maps obtained from the dHCP. However, if the pipeline was executed without the -additional command-line flag, the algorithm will use the hard segmentation.') parser.add_citation('Blesa, M.; Galdi, P.; Cox, S.R.; Sullivan, G.; Stoye, D.Q.; Lamb, G.L.; Quigley, A.J.; Thrippleton, M.J.; Escudero, J.; Bastin, M.E.; Smith, K.M. & Boardman. J.P. Hierarchical complexity of the macro-scale neonatal brain. Cerebral Cortex, 2021, 4, 2071-2084', is_external=True) parser.add_citation('Avants, B.; Epstein, C.; Grossman, M. & Gee, J. Symmetric diffeomorphic image registration with cross-correlation: evaluating automated labeling of elderly and neurodegenerative brain. 2008, Medical Image Analysis, 41, 12-26', is_external=True) - parser.add_citation('Wang, H.; Suh, J.W.; Das, S.R.; Pluta, J.B.; Craige, C. & Yushkevich, P.A. Multi-atlas segmentation with joint label fusion. IEEE Trans Pattern Anal Mach Intell., 2013, 35, 611–623.', is_external=True) + parser.add_citation('Wang, H.; Suh, J.W.; Das, S.R.; Pluta, J.B.; Craige, C. & Yushkevich, P.A. Multi-atlas segmentation with joint label fusion. IEEE Trans Pattern Anal Mach Intell., 2013, 35, 611-623.', is_external=True) parser.add_citation('Alexander, B.; Murray, A.L.; Loh, W.Y.; Matthews, L.G.; Adamson, C.; Beare, R.; Chen, J.; Kelly, C.E.; Rees, S.; Warfield, S.K.; Anderson, P.J.; Doyle, L.W.; Spittle, A.J.; Cheong, J.L.Y; Seal, M.L. & Thompson, D.K. A new neonatal cortical and subcortical brain atlas: the Melbourne Children’s Regional Infant Brain (m-crib) atlas. NeuroImage, 2017, 852, 147-841.', is_external=True) parser.add_citation('Makropoulos, A., Robinson, E.C., Schuh, A., Wright, R., Fitzgibbon, S., Bozek, J., Counsell, S.J., Steinweg, J., Vecchiato, K., Passerat-Palmbach, J., Lenz, G., Mortari, F., Tenev, T., Duff, E.P., Bastiani, M., Cordero-Grande, L., Hughes, E., Tusor, N., Tournier, J.D., Hutter, J., Price, A.N., Teixeira, R.P.A.G., Murgasova, M., Victor, S., Kelly, C., Rutherford, M.A., Smith, S.M., Edwards, A.D., Hajnal, J.V., Jenkinson, M. & Rueckert, D. The developing human connectome project: A minimal processing pipeline for neonatal cortical surface reconstruction. NeuroImage, 2018, 173, 88-112.') parser.add_argument('input', help='The input path of the derivates folder (anat/) obtained from the dHCP pipeline') diff --git a/lib/mrtrix3/_5ttgen/mcrib.py b/lib/mrtrix3/_5ttgen/mcrib.py index 3ad42fdc99..05c8a1acae 100644 --- a/lib/mrtrix3/_5ttgen/mcrib.py +++ b/lib/mrtrix3/_5ttgen/mcrib.py @@ -34,7 +34,7 @@ def usage(base_parser, subparsers): #pylint: disable=unused-variable parser.add_description('This command creates the 5TT file for human neonatal subjects. The M-CRIB atlas is used to idenity the different tissues.') parser.add_citation('Blesa, M.; Galdi, P.; Cox, S.R.; Sullivan, G.; Stoye, D.Q.; Lamb, G.L.; Quigley, A.J.; Thrippleton, M.J.; Escudero, J.; Bastin, M.E.; Smith, K.M. & Boardman. J.P. Hierarchical complexity of the macro-scale neonatal brain. Cerebral Cortex, 2021, 4, 2071-2084', is_external=True) parser.add_citation('Avants, B.; Epstein, C.; Grossman, M. & Gee, J. Symmetric diffeomorphic image registration with cross-correlation: evaluating automated labeling of elderly and neurodegenerative brain. 2008, Medical Image Analysis, 41, 12-26', is_external=True) - parser.add_citation('Wang, H.; Suh, J.W.; Das, S.R.; Pluta, J.B.; Craige, C. & Yushkevich, P.A. Multi-atlas segmentation with joint label fusion. IEEE Trans Pattern Anal Mach Intell., 2013, 35, 611–623.', is_external=True) + parser.add_citation('Wang, H.; Suh, J.W.; Das, S.R.; Pluta, J.B.; Craige, C. & Yushkevich, P.A. Multi-atlas segmentation with joint label fusion. IEEE Trans Pattern Anal Mach Intell., 2013, 35, 611-623.', is_external=True) parser.add_citation('Alexander, B.; Murray, A.L.; Loh, W.Y.; Matthews, L.G.; Adamson, C.; Beare, R.; Chen, J.; Kelly, C.E.; Rees, S.; Warfield, S.K.; Anderson, P.J.; Doyle, L.W.; Spittle, A.J.; Cheong, J.L.Y; Seal, M.L. & Thompson, D.K. A new neonatal cortical and subcortical brain atlas: the Melbourne Children’s Regional Infant Brain (m-crib) atlas. NeuroImage, 2017, 852, 147-841.', is_external=True) parser.add_argument('input', help='The input structural image') parser.add_argument('modality', choices=["t1w", "t2w"], help='Specify the modality of the input image, either "t1w" or "t2w"') From dc594199d31efdd5a507020316dbcffefdde857e Mon Sep 17 00:00:00 2001 From: pgaldi Date: Fri, 3 Dec 2021 10:20:58 +0000 Subject: [PATCH 13/16] removed unicode char from refs --- lib/mrtrix3/_5ttgen/dhcp.py | 2 +- lib/mrtrix3/_5ttgen/mcrib.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/mrtrix3/_5ttgen/dhcp.py b/lib/mrtrix3/_5ttgen/dhcp.py index 87b2f168dc..da151dcd45 100644 --- a/lib/mrtrix3/_5ttgen/dhcp.py +++ b/lib/mrtrix3/_5ttgen/dhcp.py @@ -38,7 +38,7 @@ def usage(base_parser, subparsers): #pylint: disable=unused-variable parser.add_citation('Blesa, M.; Galdi, P.; Cox, S.R.; Sullivan, G.; Stoye, D.Q.; Lamb, G.L.; Quigley, A.J.; Thrippleton, M.J.; Escudero, J.; Bastin, M.E.; Smith, K.M. & Boardman. J.P. Hierarchical complexity of the macro-scale neonatal brain. Cerebral Cortex, 2021, 4, 2071-2084', is_external=True) parser.add_citation('Avants, B.; Epstein, C.; Grossman, M. & Gee, J. Symmetric diffeomorphic image registration with cross-correlation: evaluating automated labeling of elderly and neurodegenerative brain. 2008, Medical Image Analysis, 41, 12-26', is_external=True) parser.add_citation('Wang, H.; Suh, J.W.; Das, S.R.; Pluta, J.B.; Craige, C. & Yushkevich, P.A. Multi-atlas segmentation with joint label fusion. IEEE Trans Pattern Anal Mach Intell., 2013, 35, 611-623.', is_external=True) - parser.add_citation('Alexander, B.; Murray, A.L.; Loh, W.Y.; Matthews, L.G.; Adamson, C.; Beare, R.; Chen, J.; Kelly, C.E.; Rees, S.; Warfield, S.K.; Anderson, P.J.; Doyle, L.W.; Spittle, A.J.; Cheong, J.L.Y; Seal, M.L. & Thompson, D.K. A new neonatal cortical and subcortical brain atlas: the Melbourne Children’s Regional Infant Brain (m-crib) atlas. NeuroImage, 2017, 852, 147-841.', is_external=True) + parser.add_citation('Alexander, B.; Murray, A.L.; Loh, W.Y.; Matthews, L.G.; Adamson, C.; Beare, R.; Chen, J.; Kelly, C.E.; Rees, S.; Warfield, S.K.; Anderson, P.J.; Doyle, L.W.; Spittle, A.J.; Cheong, J.L.Y; Seal, M.L. & Thompson, D.K. A new neonatal cortical and subcortical brain atlas: the Melbourne Children\'s Regional Infant Brain (m-crib) atlas. NeuroImage, 2017, 852, 147-841.', is_external=True) parser.add_citation('Makropoulos, A., Robinson, E.C., Schuh, A., Wright, R., Fitzgibbon, S., Bozek, J., Counsell, S.J., Steinweg, J., Vecchiato, K., Passerat-Palmbach, J., Lenz, G., Mortari, F., Tenev, T., Duff, E.P., Bastiani, M., Cordero-Grande, L., Hughes, E., Tusor, N., Tournier, J.D., Hutter, J., Price, A.N., Teixeira, R.P.A.G., Murgasova, M., Victor, S., Kelly, C., Rutherford, M.A., Smith, S.M., Edwards, A.D., Hajnal, J.V., Jenkinson, M. & Rueckert, D. The developing human connectome project: A minimal processing pipeline for neonatal cortical surface reconstruction. NeuroImage, 2018, 173, 88-112.') parser.add_argument('input', help='The input path of the derivates folder (anat/) obtained from the dHCP pipeline') parser.add_argument('output', help='The output 5TT image') diff --git a/lib/mrtrix3/_5ttgen/mcrib.py b/lib/mrtrix3/_5ttgen/mcrib.py index 05c8a1acae..7417126161 100644 --- a/lib/mrtrix3/_5ttgen/mcrib.py +++ b/lib/mrtrix3/_5ttgen/mcrib.py @@ -35,7 +35,7 @@ def usage(base_parser, subparsers): #pylint: disable=unused-variable parser.add_citation('Blesa, M.; Galdi, P.; Cox, S.R.; Sullivan, G.; Stoye, D.Q.; Lamb, G.L.; Quigley, A.J.; Thrippleton, M.J.; Escudero, J.; Bastin, M.E.; Smith, K.M. & Boardman. J.P. Hierarchical complexity of the macro-scale neonatal brain. Cerebral Cortex, 2021, 4, 2071-2084', is_external=True) parser.add_citation('Avants, B.; Epstein, C.; Grossman, M. & Gee, J. Symmetric diffeomorphic image registration with cross-correlation: evaluating automated labeling of elderly and neurodegenerative brain. 2008, Medical Image Analysis, 41, 12-26', is_external=True) parser.add_citation('Wang, H.; Suh, J.W.; Das, S.R.; Pluta, J.B.; Craige, C. & Yushkevich, P.A. Multi-atlas segmentation with joint label fusion. IEEE Trans Pattern Anal Mach Intell., 2013, 35, 611-623.', is_external=True) - parser.add_citation('Alexander, B.; Murray, A.L.; Loh, W.Y.; Matthews, L.G.; Adamson, C.; Beare, R.; Chen, J.; Kelly, C.E.; Rees, S.; Warfield, S.K.; Anderson, P.J.; Doyle, L.W.; Spittle, A.J.; Cheong, J.L.Y; Seal, M.L. & Thompson, D.K. A new neonatal cortical and subcortical brain atlas: the Melbourne Children’s Regional Infant Brain (m-crib) atlas. NeuroImage, 2017, 852, 147-841.', is_external=True) + parser.add_citation('Alexander, B.; Murray, A.L.; Loh, W.Y.; Matthews, L.G.; Adamson, C.; Beare, R.; Chen, J.; Kelly, C.E.; Rees, S.; Warfield, S.K.; Anderson, P.J.; Doyle, L.W.; Spittle, A.J.; Cheong, J.L.Y; Seal, M.L. & Thompson, D.K. A new neonatal cortical and subcortical brain atlas: the Melbourne Children\'s Regional Infant Brain (m-crib) atlas. NeuroImage, 2017, 852, 147-841.', is_external=True) parser.add_argument('input', help='The input structural image') parser.add_argument('modality', choices=["t1w", "t2w"], help='Specify the modality of the input image, either "t1w" or "t2w"') parser.add_argument('output', help='The output 5TT image') From 4757b772f28fb7cedd18ce4bd8b720b19d13059e Mon Sep 17 00:00:00 2001 From: pgaldi Date: Fri, 3 Dec 2021 10:25:48 +0000 Subject: [PATCH 14/16] updated docs with new 5ttgen commands --- docs/reference/commands/5ttgen.rst | 231 ++++++++++++++++++++++++++++- 1 file changed, 230 insertions(+), 1 deletion(-) diff --git a/docs/reference/commands/5ttgen.rst b/docs/reference/commands/5ttgen.rst index 06746097bf..2fc2b86c6d 100644 --- a/docs/reference/commands/5ttgen.rst +++ b/docs/reference/commands/5ttgen.rst @@ -15,7 +15,7 @@ Usage 5ttgen algorithm [ options ] ... -- *algorithm*: Select the algorithm to be used to complete the script operation; additional details and options become available once an algorithm is nominated. Options are: freesurfer, fsl, gif, hsvs +- *algorithm*: Select the algorithm to be used to complete the script operation; additional details and options become available once an algorithm is nominated. Options are: dhcp, freesurfer, fsl, gif, hsvs, mcrib Description ----------- @@ -90,6 +90,120 @@ See the Mozilla Public License v. 2.0 for more details. For more details, see http://www.mrtrix.org/. +.. _5ttgen_dhcp: + +5ttgen dhcp +=========== + +Synopsis +-------- + +Use ANTs commands, the output of the dHCP pipeline and the M-CRIB atlas to generate the 5TT image of a neonatal subject based on a T2-weighted image + +Usage +----- + +:: + + 5ttgen dhcp input output [ options ] + +- *input*: The input path of the derivates folder (anat/) obtained from the dHCP pipeline +- *output*: The output 5TT image + +Description +----------- + +Derivation of the 5TT image is principally based on the segmentation already performed in the dHCP pipeline. The M-CRIB atlas will only be used to introduce additional sub-cortical grey matter parcels into the tissue segmentation. By default, the algorithm will use the tissue probability maps obtained from the dHCP. However, if the pipeline was executed without the -additional command-line flag, the algorithm will use the hard segmentation. + +Options +------- + +Options specific to the 'dhcp' algorithm +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +- **-mcrib_path** Provide the path of the M-CRIB atlas (note: this can alternatively be specified in the MRtrix config file as "MCRIBPath") + +- **-parcellation** Additionally export the M-CRIB parcellation warped to the subject data + +- **-quick** Specify the use of quick registration parameters + +- **-hard_segmentation** Specify the use of hard segmentation instead of the soft segmentation to generate the 5TT + +- **-ants_parallel** Control for parallel computation for antsJointLabelFusion (default 0) -- 0 == run serially, 1 == SGE qsub, 2 == use PEXEC (localhost), 3 == Apple XGrid, 4 == PBS qsub, 5 == SLURM. + +Options common to all 5ttgen algorithms +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +- **-nocrop** Do NOT crop the resulting 5TT image to reduce its size (keep the same dimensions as the input image) + +- **-sgm_amyg_hipp** Represent the amygdalae and hippocampi as sub-cortical grey matter in the 5TT image + +Additional standard options for Python scripts +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +- **-nocleanup** do not delete intermediate files during script execution, and do not delete scratch directory at script completion. + +- **-scratch /path/to/scratch/** manually specify the path in which to generate the scratch directory. + +- **-continue ** continue the script from a previous execution; must provide the scratch directory path, and the name of the last successfully-generated file. + +Standard options +^^^^^^^^^^^^^^^^ + +- **-info** display information messages. + +- **-quiet** do not display information messages or progress status. Alternatively, this can be achieved by setting the MRTRIX_QUIET environment variable to a non-empty string. + +- **-debug** display debugging messages. + +- **-force** force overwrite of output files. + +- **-nthreads number** use this number of threads in multi-threaded applications (set to 0 to disable multi-threading). + +- **-config key value** *(multiple uses permitted)* temporarily set the value of an MRtrix config file entry. + +- **-help** display this information page and exit. + +- **-version** display version information and exit. + +References +^^^^^^^^^^ + +* Smith, R. E.; Tournier, J.-D.; Calamante, F. & Connelly, A. Anatomically-constrained tractography: Improved diffusion MRI streamlines tractography through effective use of anatomical information. NeuroImage, 2012, 62, 1924-1938 + +* Blesa, M.; Galdi, P.; Cox, S.R.; Sullivan, G.; Stoye, D.Q.; Lamb, G.L.; Quigley, A.J.; Thrippleton, M.J.; Escudero, J.; Bastin, M.E.; Smith, K.M. & Boardman. J.P. Hierarchical complexity of the macro-scale neonatal brain. Cerebral Cortex, 2021, 4, 2071-2084 + +* Avants, B.; Epstein, C.; Grossman, M. & Gee, J. Symmetric diffeomorphic image registration with cross-correlation: evaluating automated labeling of elderly and neurodegenerative brain. 2008, Medical Image Analysis, 41, 12-26 + +* Wang, H.; Suh, J.W.; Das, S.R.; Pluta, J.B.; Craige, C. & Yushkevich, P.A. Multi-atlas segmentation with joint label fusion. IEEE Trans Pattern Anal Mach Intell., 2013, 35, 611-623. + +* Alexander, B.; Murray, A.L.; Loh, W.Y.; Matthews, L.G.; Adamson, C.; Beare, R.; Chen, J.; Kelly, C.E.; Rees, S.; Warfield, S.K.; Anderson, P.J.; Doyle, L.W.; Spittle, A.J.; Cheong, J.L.Y; Seal, M.L. & Thompson, D.K. A new neonatal cortical and subcortical brain atlas: the Melbourne Children's Regional Infant Brain (m-crib) atlas. NeuroImage, 2017, 852, 147-841. + +* Makropoulos, A., Robinson, E.C., Schuh, A., Wright, R., Fitzgibbon, S., Bozek, J., Counsell, S.J., Steinweg, J., Vecchiato, K., Passerat-Palmbach, J., Lenz, G., Mortari, F., Tenev, T., Duff, E.P., Bastiani, M., Cordero-Grande, L., Hughes, E., Tusor, N., Tournier, J.D., Hutter, J., Price, A.N., Teixeira, R.P.A.G., Murgasova, M., Victor, S., Kelly, C., Rutherford, M.A., Smith, S.M., Edwards, A.D., Hajnal, J.V., Jenkinson, M. & Rueckert, D. The developing human connectome project: A minimal processing pipeline for neonatal cortical surface reconstruction. NeuroImage, 2018, 173, 88-112. + +Tournier, J.-D.; Smith, R. E.; Raffelt, D.; Tabbara, R.; Dhollander, T.; Pietsch, M.; Christiaens, D.; Jeurissen, B.; Yeh, C.-H. & Connelly, A. MRtrix3: A fast, flexible and open software framework for medical image processing and visualisation. NeuroImage, 2019, 202, 116137 + +-------------- + + + +**Author:** Manuel Blesa (manuel.blesa@ed.ac.uk), Paola Galdi (paola.galdi@ed.ac.uk) and Robert E. Smith (robert.smith@florey.edu.au) + +**Copyright:** Copyright (c) 2008-2021 the MRtrix3 contributors. + +This Source Code Form is subject to the terms of the Mozilla Public +License, v. 2.0. If a copy of the MPL was not distributed with this +file, You can obtain one at http://mozilla.org/MPL/2.0/. + +Covered Software is provided under this License on an "as is" +basis, without warranty of any kind, either expressed, implied, or +statutory, including, without limitation, warranties that the +Covered Software is free of defects, merchantable, fit for a +particular purpose or non-infringing. +See the Mozilla Public License v. 2.0 for more details. + +For more details, see http://www.mrtrix.org/. + .. _5ttgen_freesurfer: 5ttgen freesurfer @@ -476,3 +590,118 @@ See the Mozilla Public License v. 2.0 for more details. For more details, see http://www.mrtrix.org/. +.. _5ttgen_mcrib: + +5ttgen mcrib +============ + +Synopsis +-------- + +Use ANTs commands and the M-CRIB atlas to generate the 5TT image of a neonatal subject based on a T1-weighted or T2-weighted image + +Usage +----- + +:: + + 5ttgen mcrib input modality output [ options ] + +- *input*: The input structural image +- *modality*: Specify the modality of the input image, either "t1w" or "t2w" +- *output*: The output 5TT image + +Description +----------- + +This command creates the 5TT file for human neonatal subjects. The M-CRIB atlas is used to idenity the different tissues. + +Options +------- + +Options specific to the 'mcrib' algorithm +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +- **-mask** Manually provide a brain mask, MANDATORY + +- **-mcrib_path** Provide the path of the M-CRIB atlas (note: this can alternatively be specified in the MRtrix config file as "MCRIBPath") + +- **-parcellation** Additionally export the M-CRIB parcellation warped to the subject data + +- **-quick** Specify the use of quick registration parameters + +- **-hard_segmentation** Specify the use of hard segmentation instead of the soft segmentation to generate the 5TT (NOTE: use of this option in this segmentation algorithm is not recommended) + +- **-ants_parallel** Control for parallel computation for antsJointLabelFusion (default 0) -- 0 == run serially, 1 == SGE qsub, 2 == use PEXEC (localhost), 3 == Apple XGrid, 4 == PBS qsub, 5 == SLURM. + +Options common to all 5ttgen algorithms +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +- **-nocrop** Do NOT crop the resulting 5TT image to reduce its size (keep the same dimensions as the input image) + +- **-sgm_amyg_hipp** Represent the amygdalae and hippocampi as sub-cortical grey matter in the 5TT image + +Additional standard options for Python scripts +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +- **-nocleanup** do not delete intermediate files during script execution, and do not delete scratch directory at script completion. + +- **-scratch /path/to/scratch/** manually specify the path in which to generate the scratch directory. + +- **-continue ** continue the script from a previous execution; must provide the scratch directory path, and the name of the last successfully-generated file. + +Standard options +^^^^^^^^^^^^^^^^ + +- **-info** display information messages. + +- **-quiet** do not display information messages or progress status. Alternatively, this can be achieved by setting the MRTRIX_QUIET environment variable to a non-empty string. + +- **-debug** display debugging messages. + +- **-force** force overwrite of output files. + +- **-nthreads number** use this number of threads in multi-threaded applications (set to 0 to disable multi-threading). + +- **-config key value** *(multiple uses permitted)* temporarily set the value of an MRtrix config file entry. + +- **-help** display this information page and exit. + +- **-version** display version information and exit. + +References +^^^^^^^^^^ + +* Smith, R. E.; Tournier, J.-D.; Calamante, F. & Connelly, A. Anatomically-constrained tractography: Improved diffusion MRI streamlines tractography through effective use of anatomical information. NeuroImage, 2012, 62, 1924-1938 + +* Blesa, M.; Galdi, P.; Cox, S.R.; Sullivan, G.; Stoye, D.Q.; Lamb, G.L.; Quigley, A.J.; Thrippleton, M.J.; Escudero, J.; Bastin, M.E.; Smith, K.M. & Boardman. J.P. Hierarchical complexity of the macro-scale neonatal brain. Cerebral Cortex, 2021, 4, 2071-2084 + +* Avants, B.; Epstein, C.; Grossman, M. & Gee, J. Symmetric diffeomorphic image registration with cross-correlation: evaluating automated labeling of elderly and neurodegenerative brain. 2008, Medical Image Analysis, 41, 12-26 + +* Wang, H.; Suh, J.W.; Das, S.R.; Pluta, J.B.; Craige, C. & Yushkevich, P.A. Multi-atlas segmentation with joint label fusion. IEEE Trans Pattern Anal Mach Intell., 2013, 35, 611-623. + +* Alexander, B.; Murray, A.L.; Loh, W.Y.; Matthews, L.G.; Adamson, C.; Beare, R.; Chen, J.; Kelly, C.E.; Rees, S.; Warfield, S.K.; Anderson, P.J.; Doyle, L.W.; Spittle, A.J.; Cheong, J.L.Y; Seal, M.L. & Thompson, D.K. A new neonatal cortical and subcortical brain atlas: the Melbourne Children's Regional Infant Brain (m-crib) atlas. NeuroImage, 2017, 852, 147-841. + +Tournier, J.-D.; Smith, R. E.; Raffelt, D.; Tabbara, R.; Dhollander, T.; Pietsch, M.; Christiaens, D.; Jeurissen, B.; Yeh, C.-H. & Connelly, A. MRtrix3: A fast, flexible and open software framework for medical image processing and visualisation. NeuroImage, 2019, 202, 116137 + +-------------- + + + +**Author:** Manuel Blesa (manuel.blesa@ed.ac.uk), Paola Galdi (paola.galdi@ed.ac.uk) and Robert E. Smith (robert.smith@florey.edu.au) + +**Copyright:** Copyright (c) 2008-2021 the MRtrix3 contributors. + +This Source Code Form is subject to the terms of the Mozilla Public +License, v. 2.0. If a copy of the MPL was not distributed with this +file, You can obtain one at http://mozilla.org/MPL/2.0/. + +Covered Software is provided under this License on an "as is" +basis, without warranty of any kind, either expressed, implied, or +statutory, including, without limitation, warranties that the +Covered Software is free of defects, merchantable, fit for a +particular purpose or non-infringing. +See the Mozilla Public License v. 2.0 for more details. + +For more details, see http://www.mrtrix.org/. + From cbe4f95f2e0b4e0ab28c72e09693946397319813 Mon Sep 17 00:00:00 2001 From: MRtrixBot Date: Mon, 6 Dec 2021 09:08:00 +1100 Subject: [PATCH 15/16] 5ttgen: Update copyrights --- lib/mrtrix3/_5ttgen/dhcp.py | 2 +- lib/mrtrix3/_5ttgen/mcrib.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/mrtrix3/_5ttgen/dhcp.py b/lib/mrtrix3/_5ttgen/dhcp.py index da151dcd45..92308daa16 100644 --- a/lib/mrtrix3/_5ttgen/dhcp.py +++ b/lib/mrtrix3/_5ttgen/dhcp.py @@ -1,4 +1,4 @@ -# Copyright (c) 2008-2020 the MRtrix3 contributors. +# Copyright (c) 2008-2021 the MRtrix3 contributors. # # This Source Code Form is subject to the terms of the Mozilla Public # License, v. 2.0. If a copy of the MPL was not distributed with this diff --git a/lib/mrtrix3/_5ttgen/mcrib.py b/lib/mrtrix3/_5ttgen/mcrib.py index 7417126161..c029b3f2f5 100644 --- a/lib/mrtrix3/_5ttgen/mcrib.py +++ b/lib/mrtrix3/_5ttgen/mcrib.py @@ -1,4 +1,4 @@ -# Copyright (c) 2008-2020 the MRtrix3 contributors. +# Copyright (c) 2008-2021 the MRtrix3 contributors. # # This Source Code Form is subject to the terms of the Mozilla Public # License, v. 2.0. If a copy of the MPL was not distributed with this From 67584216490d61ef3e23079b7f960d3c8b237b35 Mon Sep 17 00:00:00 2001 From: mblesac Date: Wed, 15 Jun 2022 16:12:08 +0100 Subject: [PATCH 16/16] Update dhcp.py --- lib/mrtrix3/_5ttgen/dhcp.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/lib/mrtrix3/_5ttgen/dhcp.py b/lib/mrtrix3/_5ttgen/dhcp.py index 92308daa16..0b24d12b88 100644 --- a/lib/mrtrix3/_5ttgen/dhcp.py +++ b/lib/mrtrix3/_5ttgen/dhcp.py @@ -151,8 +151,9 @@ def execute(): #pylint: disable=unused-variable run.command('mrcalc ' + ' '.join('all_labels_dHCP.mif ' + str(i) + ' -eq' for i in indices) + ' ' + ' '.join(['-add'] * (len(indices) - 1)) + ' Pmap-' + tissue + '.mif') else: run.command(['mrmath', ['label_%d.mif' % i for i in indices], 'sum', 'Pmap-' + tissue + '.mif']) - #refine the WM - run.command('mrcalc sGM_mcrib.mif ' + ('0.5' if use_hard_segmentation else '0.1') + ' -lt Pmap-WM.mif -mult Pmap-WM-corr.mif') + + #refine the WM + run.command('mrcalc sGM_mcrib.mif ' + ('0.5' if use_hard_segmentation else '0.1') + ' -lt Pmap-WM.mif -mult Pmap-WM-corr.mif') #normalize 0-1 and combine run.command('mrcalc Pmap-cGM.mif 0.01 -mult cGM.mif')