@@ -202,8 +202,6 @@ def isclose(a, b, rel_tol=1e-9, abs_tol=0.0):
202202 dst_val = numpy .asarray (dst )
203203 dst_val = dst_val .astype ("int" )
204204
205- reg = list (convert_lut .REGION )
206-
207205 # Check that each label of original volume (old_label) has a matching transformation in the csv file
208206 for i in range (old_labels .size ):
209207 index = numpy .argwhere (src_val == old_labels [i ])
@@ -212,15 +210,12 @@ def isclose(a, b, rel_tol=1e-9, abs_tol=0.0):
212210 raise Exception (
213211 f"Could not find label { old_labels [i ]} on conversion table. Add it manually in CSV file to correct error"
214212 )
215- # else:
216- # cprint(str(old_labels[i]) + " has been found on conversion table")
217213
218214 # Instantiation of final volume, with same dtype as original volume
219215 new_volume = numpy .zeros (volume .shape , dtype = volume .dtype )
220216 # Computing the transformation
221217 for i in range (len (src )):
222218 new_volume [volume == src_val [i ]] = dst_val [i ]
223- # cprint("Region " + reg[i] + " transformed")
224219 # Get unique list of new label
225220 new_labels = numpy .unique (new_volume )
226221 new_labels = new_labels .astype ("int" )
@@ -235,7 +230,6 @@ def isclose(a, b, rel_tol=1e-9, abs_tol=0.0):
235230 current_path = os .path .abspath (current_path )
236231 nib .save (myNifti , current_path )
237232 list_of_regions .append (current_path )
238- # cprint("Label " + str(new_labels[i]) + " created in " + current_path)
239233 allsum = allsum + region_volume
240234
241235 # The sum of a voxel location across the fourth dimension should be 1
@@ -248,61 +242,66 @@ def isclose(a, b, rel_tol=1e-9, abs_tol=0.0):
248242 return list_of_regions
249243
250244
251- def runApplyInverseDeformationField_SPM_standalone (
252- target , deformation_field , img , matscript_folder
253- ):
245+ def runApplyInverseDeformationField_SPM_standalone (target , deformation_field , img ):
254246 """
255247 This function does the exact same job as runApplyInverseDeformationField but with SPM standalone. We directly create
256248 a batch file that SPM standalone can run. This function does not check whether SPM standalone must be used. Previous
257249 check when building the pipeline ensures that all the env vars exists ($SPMSTANDALONE_HOME and $MCR_HOME)
258250 """
259251 import os
260- import platform
261252 import subprocess
262253 from os .path import abspath , basename , exists , join
254+ from textwrap import dedent
255+
256+ from clinica .utils .check_dependency import get_spm_standalone_home
257+ from clinica .utils .spm import _get_real_spm_standalone_file
263258
264259 prefix = "subject_space_"
265260
266261 # Write SPM batch command directly in a script that is readable by SPM standalone
267262 script_location = abspath ("./m_script.m" )
268- script_file = open (script_location , "w+" )
269- script_file .write (
270- "jobs{1}.spm.util.defs.comp{1}.inv.comp{1}.def = {'"
271- + deformation_field
272- + "'};\n "
263+ script_file = dedent (
264+ """
265+ spm('Defaults', 'fMRI');
266+ spm_jobman('initcfg');
267+
268+ jobs{{1}}.spm.util.defs.comp{{1}}.inv.comp{{1}}.def = {{'{deformation_field}'}};
269+ jobs{{1}}.spm.util.defs.comp{{1}}.inv.space = {{'{target}'}};
270+ jobs{{1}}.spm.util.defs.out{{1}}.pull.fnames = {{'{img}'}};
271+ jobs{{1}}.spm.util.defs.out{{1}}.pull.savedir.saveusr = {{'{output_dir}'}};
272+ jobs{{1}}.spm.util.defs.out{{1}}.pull.interp = 4;
273+ jobs{{1}}.spm.util.defs.out{{1}}.pull.mask = 1;
274+ jobs{{1}}.spm.util.defs.out{{1}}.pull.fwhm = [0 0 0];
275+ jobs{{1}}.spm.util.defs.out{{1}}.pull.prefix = '{prefix}';
276+
277+ spm_jobman('run', jobs);
278+ """
273279 )
274- script_file .write ("jobs{1}.spm.util.defs.comp{1}.inv.space = {'" + target + "'};\n " )
275- script_file .write ("jobs{1}.spm.util.defs.out{1}.pull.fnames = {'" + img + "'};\n " )
276- script_file .write (
277- "jobs{1}.spm.util.defs.out{1}.pull.savedir.saveusr = {'"
278- + abspath (os .getcwd ())
279- + "'};\n "
280+
281+ script_file = script_file .format (
282+ deformation_field = deformation_field ,
283+ target = target ,
284+ img = img ,
285+ output_dir = abspath (os .getcwd ()),
286+ prefix = prefix ,
280287 )
281- script_file .write ("jobs{1}.spm.util.defs.out{1}.pull.interp = 4;\n " )
282- script_file .write ("jobs{1}.spm.util.defs.out{1}.pull.mask = 1;\n " )
283- script_file .write ("jobs{1}.spm.util.defs.out{1}.pull.fwhm = [0 0 0];\n " )
284- script_file .write ("jobs{1}.spm.util.defs.out{1}.pull.prefix = '" + prefix + "';\n " )
285- script_file .close ()
286-
287- # Generate command line to run
288- # SPM standalone must be run directly from its root folder
289- if platform .system () == "Darwin" :
290- # Mac OS
291- cmdline = f"cd $SPMSTANDALONE_HOME && ./run_spm12.sh $MCR_HOME batch { script_location } "
292- elif platform .system () == "Linux" :
293- # Linux OS
294- cmdline = f"$SPMSTANDALONE_HOME/run_spm12.sh $MCR_HOME batch { script_location } "
295- else :
296- raise SystemError ("Only support Mac OS and Linux" )
288+
289+ with open (script_location , "w" , encoding = "utf-8" ) as f :
290+ f .write (script_file )
291+
292+ # TODO : This might not even be needed with cmd line setting done prior
293+ spm_file = _get_real_spm_standalone_file (get_spm_standalone_home ())
294+ cmdline = f"$SPMSTANDALONE_HOME/{ spm_file } $MCR_HOME batch { script_location } "
295+
297296 subprocess_run = subprocess .run (
298297 cmdline ,
299298 shell = True ,
300299 stdout = subprocess .DEVNULL ,
301300 stderr = subprocess .DEVNULL ,
302301 )
303- if subprocess_run .returncode != 0 :
302+ if code := subprocess_run .returncode != 0 :
304303 raise ValueError (
305- "runApplyInverseDeformationField_SPM_standalone failed, returned non-zero code"
304+ f "runApplyInverseDeformationField_SPM_standalone failed, returned non-zero code with { code } "
306305 )
307306
308307 output_file = join (abspath ("./" ), prefix + basename (img ))
@@ -317,40 +316,6 @@ def runApplyInverseDeformationField_SPM_standalone(
317316 return output_file
318317
319318
320- def runApplyInverseDeformationField (target , deformation_field , img , matscript_folder ):
321- import os
322- import sys
323-
324- from nipype .interfaces .matlab import MatlabCommand , get_matlab_command
325-
326- prefix = "subject_space_"
327-
328- MatlabCommand .set_default_matlab_cmd (get_matlab_command ())
329- matlab = MatlabCommand ()
330- if sys .platform .startswith ("linux" ):
331- matlab .inputs .args = "-nosoftwareopengl"
332-
333- matlab .inputs .paths = matscript_folder
334- matlab .inputs .script = """
335- applyInverseDeformationField('%s', '%s', '%s', './', '%s')
336- """ % (
337- target ,
338- deformation_field ,
339- img ,
340- prefix ,
341- )
342- matlab .inputs .single_comp_thread = False
343- matlab .inputs .logfile = os .path .join ("./" , "matlab_output.log" )
344- matlab .run ()
345-
346- output_file = os .path .join (os .path .abspath ("./" ), prefix + os .path .basename (img ))
347- if not os .path .exists (output_file ):
348- raise IOError (
349- f"Something went wrong, please check { os .path .abspath (matlab .inputs .logfile )} for more information"
350- )
351- return output_file
352-
353-
354319def suvr_normalization (pet_path , mask ):
355320 """suvr_normalization is a way of getting suvr from your pet image, based on the segmentation performed by
356321 gtmsegmentation. The Standard Uptake Value ratio is computed by dividing the whole PET volume by the mean value
@@ -789,16 +754,13 @@ def get_mid_surface(in_surfaces):
789754
790755
791756def reformat_surfname (hemi , left_surface , right_surface ):
792- res = None
793757 if hemi == "lh" :
794- res = left_surface
795- elif hemi == "rh" :
796- res = right_surface
797- else :
798- raise Exception (
799- "First input of this reformat_surfname function must be either lh or rh"
800- )
801- return res
758+ return left_surface
759+ if hemi == "rh" :
760+ return right_surface
761+ raise ValueError (
762+ f"First input of this reformat_surfname function must be either lh or rh. Here it is : { hemi } "
763+ )
802764
803765
804766def produce_tsv (pet , atlas_files ):
@@ -890,7 +852,6 @@ def get_wf(
890852 acq_label : str ,
891853 csv_segmentation ,
892854 suvr_reference_region : str ,
893- matscript_folder_inverse_deformation ,
894855 destrieux_left ,
895856 destrieux_right ,
896857 desikan_left ,
@@ -912,7 +873,6 @@ def get_wf(
912873 acq_label (string):
913874 csv_segmentation (string): Path to the CSV for the segmentation (problems encountered while using __file__)
914875 suvr_reference_region (string): Label of the SUVR reference region
915- matscript_folder_inverse_deformation (string): Path to the current folder containing the matlab script used to call the spm function for the inverse deformation
916876 destrieux_left (string):
917877 destrieux_right (string):
918878 desikan_left (string):
@@ -1037,23 +997,14 @@ def get_wf(
1037997 name = "normalize_to_MNI" ,
1038998 )
1039999
1040- if using_spm_standalone :
1041- fun_apply_inverse_deformation = (
1042- utils .runApplyInverseDeformationField_SPM_standalone
1043- )
1044- else :
1045- fun_apply_inverse_deformation = utils .runApplyInverseDeformationField
10461000 apply_inverse_deformation = pe .Node (
10471001 niu .Function (
1048- input_names = ["target" , "deformation_field" , "img" , "matscript_folder" ],
1002+ input_names = ["target" , "deformation_field" , "img" ],
10491003 output_names = ["freesurfer_space_eroded_mask" ],
1050- function = fun_apply_inverse_deformation ,
1004+ function = utils . runApplyInverseDeformationField_SPM_standalone ,
10511005 ),
10521006 name = "applyInverseDeformation" ,
10531007 )
1054- apply_inverse_deformation .inputs .matscript_folder = (
1055- matscript_folder_inverse_deformation
1056- )
10571008
10581009 pons_normalization = pe .Node (
10591010 niu .Function (
@@ -1222,7 +1173,6 @@ def get_wf(
12221173 name = "inputnode" ,
12231174 mandatory_inputs = True ,
12241175 )
1225-
12261176 inputnode .inputs .orig_nu = orig_nu
12271177 inputnode .inputs .pet = pet
12281178 inputnode .inputs .psf = pvc_psf_tsv
0 commit comments