Coverage for  / builds / tms-localization / papers / tmsloc_proto / scripts / 01_create_subject_structure.py: 99%

167 statements  

« prev     ^ index     » next       coverage.py v7.13.5, created at 2026-04-01 07:48 +0000

1#!/usr/bin/env python 

2 

3""" 

4Creates a template subject, i.e. the folder structure and the create_subject.py file. 

5 

6create_new_subject.py -f <path> 

7 

8-f ... path of new subject 

9""" 

10import os 

11import warnings 

12import argparse 

13import subprocess 

14 

15parser = argparse.ArgumentParser(description='Creates a new subject in path') 

16parser.add_argument('-f', '--fn_subject', help='path of new subject', required=True) 

17args = parser.parse_args() 

18 

19fn_subject = os.path.abspath(args.fn_subject) 

20subject_id = os.path.split(fn_subject)[1] 

21 

22if os.path.exists(fn_subject): 

23 print("Subject already exists... aborting") 

24 exit() 

25 

26os.makedirs(fn_subject) 

27os.makedirs(os.path.join(fn_subject, "exp")) 

28os.makedirs(os.path.join(fn_subject, "mesh")) 

29os.makedirs(os.path.join(fn_subject, "opt")) 

30os.makedirs(os.path.join(fn_subject, "mri", "0", "original", "dicom")) 

31os.makedirs(os.path.join(fn_subject, "mri", "0", "original", "nifti", "t1")) 

32os.makedirs(os.path.join(fn_subject, "mri", "0", "original", "nifti", "t2")) 

33os.makedirs(os.path.join(fn_subject, "mri", "0", "original", "nifti", "dti")) 

34os.makedirs(os.path.join(fn_subject, "results")) 

35 

36f = open(os.path.join(fn_subject, f"create_{subject_id}.py"), "w") 

37f.write("#!/usr/bin/env python\n") 

38f.write("import os\n") 

39f.write("import pynibs\n") 

40f.write("import numpy as np\n") 

41f.write("from inspect import getsourcefile\n") 

42f.write("\n") 

43f.write("subject_folder = os.path.split(os.path.abspath(getsourcefile(lambda: 0)))[0]\n") 

44f.write("\n") 

45f.write("# subject information\n") 

46f.write("###############################################################" 

47 "#########################################################\n") 

48f.write("subject_id = '{}'\n".format(subject_id)) 

49f.write("fn_subject_obj = subject_folder + f'{os.sep}{subject_id}.hdf5'\n") 

50f.write("\n") 

51f.write("# MRI information\n") 

52f.write("###############################################################" 

53 "#########################################################\n") 

54f.write("mri = [dict()]\n") 

55f.write("mri[0]['fn_mri_T1'] = subject_folder + f'{os.sep}mri{os.sep}0{os.sep}original{os.sep}nifti{os.sep}t1{os.sep}T1.nii'\n") 

56f.write("mri[0]['fn_mri_T2'] = subject_folder + f'{os.sep}mri{os.sep}0{os.sep}original{os.sep}nifti{os.sep}t2{os.sep}T2.nii'\n") 

57f.write("mri[0]['fn_mri_DTI'] = subject_folder + f'{os.sep}mri{os.sep}0{os.sep}original{os.sep}nifti{os.sep}dti{os.sep}DTI.nii'\n") 

58f.write("mri[0]['fn_mri_DTI_rev'] = subject_folder + f'{os.sep}mri{os.sep}0{os.sep}original{os.sep}nifti{os.sep}dti{os.sep}DTI_rev.nii'\n") 

59f.write("mri[0]['fn_mri_DTI_bvec'] = subject_folder + f'{os.sep}mri{os.sep}0{os.sep}original{os.sep}nifti{os.sep}dti{os.sep}DTI.bvec'\n") 

60f.write("mri[0]['fn_mri_DTI_bval'] = subject_folder + f'{os.sep}mri{os.sep}0{os.sep}original{os.sep}nifti{os.sep}dti{os.sep}DTI.bval'\n") 

61f.write("mri[0]['dti_readout_time'] = '0.0476258'\n") 

62f.write("mri[0]['dti_phase_direction'] = '-y'\n") 

63f.write("mri[0]['freesurfer_dir'] = subject_folder + '/mri/0/original/fs'\n") 

64f.write("mri[0]['dti_tensor_fn'] = None # if you want to provide your own, preprocessed tensor file, set it here\n") 

65f.write("\n") 

66f.write("# Mesh information\n") 

67f.write("################################################################" 

68 "########################################################\n") 

69f.write("mesh = dict()\n") 

70f.write("# Add one dict() for each mesh. See templates below.\n") 

71f.write("mesh['charm_4.1_refined_M1_fs'] = dict()\n") 

72f.write("mesh['charm_4.1_refined_M1_fs']['info'] = 'charm_4.1_refined_M1_fs'\n") 

73f.write("mesh['charm_4.1_refined_M1_fs']['approach'] = 'charm'\n") 

74f.write("mesh['charm_4.1_refined_M1_fs']['mesh_folder'] = os.path.join(subject_folder, 'mesh', 'charm_4.1_refined_M1_fs')\n") 

75f.write("mesh['charm_4.1_refined_M1_fs']['vertex_density'] = None\n") 

76f.write("mesh['charm_4.1_refined_M1_fs']['fn_mesh_msh'] = os.path.join(mesh['charm_4.1_refined_M1_fs']['mesh_folder'], f'm2m_{subject_id}', f'{subject_id}.msh')\n") 

77f.write("mesh['charm_4.1_refined_M1_fs']['fn_mesh_hdf5'] = os.path.join(mesh['charm_4.1_refined_M1_fs']['mesh_folder'], f'm2m_{subject_id}', f'{subject_id}.hdf5')\n") 

78f.write("mesh['charm_4.1_refined_M1_fs']['fn_tensor_vn'] = f'm2m_{subject_id}/DTI_coregT1_tensor.nii.gz'\n") 

79f.write("mesh['charm_4.1_refined_M1_fs']['mri_idx'] = 0\n") 

80f.write("mesh['charm_4.1_refined_M1_fs']['fn_mri_conform'] = f'm2m_{subject_id}/T1.nii.gz'\n") 

81f.write("mesh['charm_4.1_refined_M1_fs']['fn_lh_wm'] = None\n") 

82f.write("mesh['charm_4.1_refined_M1_fs']['fn_rh_wm'] = None\n") 

83f.write("mesh['charm_4.1_refined_M1_fs']['fn_lh_gm'] = None\n") 

84f.write("mesh['charm_4.1_refined_M1_fs']['fn_rh_gm'] = None\n") 

85f.write("mesh['charm_4.1_refined_M1_fs']['fn_lh_gm_curv'] = None\n") 

86f.write("mesh['charm_4.1_refined_M1_fs']['fn_rh_gm_curv'] = None\n") 

87f.write("mesh['charm_4.1_refined_M1_fs']['fn_lh_midlayer'] = f'm2m_{subject_id}/surfaces/lh.central.gii'\n") 

88f.write("mesh['charm_4.1_refined_M1_fs']['fn_rh_midlayer'] = f'm2m_{subject_id}/surfaces/rh.central.gii'\n") 

89f.write("mesh['charm_4.1_refined_M1_fs']['smooth_skin'] = .8\n") 

90f.write("mesh['charm_4.1_refined_M1_fs']['refinement_roi'] = 'midlayer_m1s1pmd'\n") 

91f.write("mesh['charm_4.1_refined_M1_fs']['refinemement_element_size'] = 0.75\n") 

92f.write("mesh['charm_4.1_refined_M1_fs']['use_fs'] = True # use freesurfer segmentation to improve head mesh\n") 

93 

94f.write("\n") 

95 

96f.write("# ROI information (first index: mesh, second index: roi)\n") 

97f.write("################################################################" 

98 "########################################################\n") 

99f.write("roi = dict()\n") 

100f.write("# Add one dict() for each roi per mesh. See templates below.\n") 

101f.write("\n") 

102f.write("roi['charm_4.1_refined_M1_fs'] = dict()\n") 

103f.write("roi['charm_4.1_refined_M1_fs']['midlayer_m1s1pmd'] = dict()\n") 

104f.write("roi['charm_4.1_refined_M1_fs']['midlayer_m1s1pmd']['type'] = 'surface'\n") 

105f.write("roi['charm_4.1_refined_M1_fs']['midlayer_m1s1pmd']['info'] = 'freesurfer PMd, M1 and somatosensory cortex'\n") 

106f.write("roi['charm_4.1_refined_M1_fs']['midlayer_m1s1pmd']['gm_surf_fname'] = mesh['charm_4.1_refined_M1_fs']['fn_lh_gm']\n") 

107f.write("roi['charm_4.1_refined_M1_fs']['midlayer_m1s1pmd']['wm_surf_fname'] = mesh['charm_4.1_refined_M1_fs']['fn_lh_wm']\n") 

108f.write("roi['charm_4.1_refined_M1_fs']['midlayer_m1s1pmd']['midlayer_surf_fname'] = mesh['charm_4.1_refined_M1_fs']['fn_lh_midlayer']\n") 

109f.write("roi['charm_4.1_refined_M1_fs']['midlayer_m1s1pmd']['refine'] = False\n") 

110f.write("roi['charm_4.1_refined_M1_fs']['midlayer_m1s1pmd']['delta'] = 0.5\n") 

111f.write("roi['charm_4.1_refined_M1_fs']['midlayer_m1s1pmd']['X_ROI'] = None\n") 

112f.write("roi['charm_4.1_refined_M1_fs']['midlayer_m1s1pmd']['Y_ROI'] = None\n") 

113f.write("roi['charm_4.1_refined_M1_fs']['midlayer_m1s1pmd']['Z_ROI'] = None\n") 

114f.write("roi['charm_4.1_refined_M1_fs']['midlayer_m1s1pmd']['layer'] = 3\n") 

115f.write("roi['charm_4.1_refined_M1_fs']['midlayer_m1s1pmd']['fn_mask'] = f'roi/midlayer_m1s1pmd/mask_{subject_id}m1pmdss.mgh'\n") 

116f.write("roi['charm_4.1_refined_M1_fs']['midlayer_m1s1pmd']['fn_mask_avg'] = 'tmsloc_proto/examppes/lefthandknob_M1S1PMd.overlay'\n") 

117warnings.warn("Adjust the fn_mask_avg path to your needs") 

118f.write("roi['charm_4.1_refined_M1_fs']['midlayer_m1s1pmd']['hemisphere'] = 'lh'\n") 

119 

120f.write("\n") 

121 

122f.write("# Experiment information\n") 

123f.write("###############################################################" 

124 "#########################################################\n") 

125f.write("exp = dict()\n") 

126f.write("# Add one dict() for each experiment. See templates below.\n") 

127f.write("\n") 

128f.write("# exp['TMS_Localite_template'] = dict()\n") 

129f.write("# exp['TMS_Localite_template']['info'] = ['TMS-MEP template Localite (MPI)']\n") 

130f.write("# exp['TMS_Localite_template']['date'] = ['XX{os.sep}XX{os.sep}20XX']\n") 

131f.write("# exp['TMS_Localite_template']['nnav_system'] = 'Localite'\n") 

132f.write("# exp['TMS_Localite_template']['fn_tms_nav'] = [[subject_folder + '...xml', subject_folder + '...xml']]\n") 

133f.write("# exp['TMS_Localite_template']['fn_data'] = [[subject_folder + '{os.sep}exp{os.sep}0{os.sep}mep{os.sep}...cfs']]\n") 

134f.write("# exp['TMS_Localite_template']['fn_intensity'] = None\n") 

135f.write("# exp['TMS_Localite_template']['mep_onsets'] = [[0]]\n") 

136f.write("# exp['TMS_Localite_template']['fn_exp_csv'] = [subject_folder + '{os.sep}exp{os.sep}0{os.sep}experiment.csv']\n") 

137f.write("# exp['TMS_Localite_template']['fn_exp_hdf5'] = [subject_folder + '{os.sep}exp{os.sep}0{os.sep}experiment.hdf5']\n") 

138f.write("# exp['TMS_Localite_template']['fn_coil'] = [['...{os.sep}MagStim_Alpha_Coil_70mm_Fig8.nii.gz']]\n") 

139f.write("# exp['TMS_Localite_template']['fn_mri_nii'] = [[subject_folder + '{os.sep}exp{os.sep}0{os.sep}..._conform.nii']]\n") 

140f.write("# exp['TMS_Localite_template']['cond'] = [['']]\n") 

141f.write("# exp['TMS_Localite_template']['channels'] = [['FDI', 'ADM', 'APB']]") 

142f.write("# exp['TMS_Localite_template']['tms_pulse_time'] = None\n") 

143f.write("# exp['TMS_Localite_template']['experimenter'] = ''\n") 

144f.write("# exp['TMS_Localite_template']['mep_fit_info'] = ['']\n") 

145f.write("# exp['TMS_Localite_template']['incidents'] = ['']\n") 

146f.write("# exp['TMS_Localite_template']['postproc'] = [dict()]\n") 

147f.write("# exp['TMS_Localite_template']['postproc'][0]['info'] = ' '\n") 

148f.write("# exp['TMS_Localite_template']['postproc'][0]['cmd'] = ' '\n") 

149f.write("\n") 

150f.write("# exp['TMS_ANT_template'] = dict()\n") 

151f.write("# exp['TMS_ANT_template']['info'] = ['TMS-MEP-EEG template (ANT)']\n") 

152f.write("# exp['TMS_ANT_template']['date'] = ['XX{os.sep}XX{os.sep}20XX']\n") 

153f.write("# exp['TMS_ANT_template']['nnav_system'] = 'Visor'\n") 

154f.write("# exp['TMS_ANT_template']['fn_data'] = [[subject_folder + '{os.sep}exp{os.sep}2{os.sep}...cnt']]\n") 

155f.write("# exp['TMS_ANT_template']['fn_exp_hdf5'] = [subject_folder + '{os.sep}exp{os.sep}2{os.sep}experiment.hdf5']\n") 

156f.write("# exp['TMS_ANT_template']['fn_coil'] = [['...{os.sep}MagStim_Alpha_Coil_70mm_Fig8.nii.gz']]\n") 

157f.write("# exp['TMS_ANT_template']['fn_mri_nii'] = [[subject_folder + '{os.sep}exp{os.sep}2{os.sep}..._conform.nii']]\n") 

158f.write("# exp['TMS_ANT_template']['fn_visor_cnt'] = [subject_folder + '{os.sep}exp{os.sep}2{os.sep}...pos.cnt']\n") 

159f.write("# exp['TMS_ANT_template']['fn_visor_calibration'] = [subject_folder + '{os.sep}exp{os.sep}2{os.sep}...calibration.xml']\n") 

160f.write("# exp['TMS_ANT_template']['fn_eeg_cnt'] = [subject_folder + '{os.sep}exp{os.sep}2{os.sep}eeg{os.sep}...cnt']\n") 

161f.write("# exp['TMS_ANT_template']['eeg_channels'] = ['all']\n") 

162f.write("# exp['TMS_ANT_template']['fn_emg_cnt'] = [subject_folder + '{os.sep}exp{os.sep}2{os.sep}emg{os.sep}...cnt']\n") 

163f.write("# exp['TMS_ANT_template']['emg_channels'] = [0]\n") 

164f.write("# exp['TMS_ANT_template']['emg_max_duration'] = [10]\n") 

165f.write("# exp['TMS_ANT_template']['eeg_max_duration'] = [10]\n") 

166f.write("# exp['TMS_ANT_template']['emg_trigger_value'] = ['4']\n") 

167f.write("# exp['TMS_ANT_template']['eeg_trigger_value'] = ['1']\n") 

168f.write("# exp['TMS_ANT_template']['cond'] = [['M1_random']]\n") 

169f.write("# exp['TMS_ANT_template']['tms_pulse_time'] = None\n") 

170f.write("# exp['TMS_ANT_template']['experimenter'] = ' '\n") 

171f.write("# exp['TMS_ANT_template']['mep_fit_info'] = [' ']\n") 

172f.write("# exp['TMS_ANT_template']['incidents'] = [' ']\n") 

173f.write("# exp['TMS_ANT_template']['fiducal_corr'] = [[0,0,0]] # x,y,z in mm\n") 

174f.write("\n") 

175f.write("# save subject information in .hdf5 file\n") 

176f.write("###############################################################" 

177 "#########################################################\n") 

178f.write("pynibs.save_subject_hdf5(fname=fn_subject_obj,\n") 

179f.write(" mri_dict=mri,\n") 

180f.write(" mesh_dict=mesh,\n") 

181f.write(" roi_dict=roi,\n") 

182f.write(" exp_dict=exp,\n") 

183f.write(" ps_dict=None,\n") 

184f.write(" subject_id=subject_id,\n") 

185f.write(" subject_folder=subject_folder)\n") 

186f.write("\n") 

187f.write("print(f'Created subject .hdf5 file: {fn_subject_obj}')\n") 

188f.close() 

189 

190fn = os.path.join(fn_subject, f'create_{subject_id}.py') 

191print(f"Created subject info file: {fn}\n. Edit this file to your needs and rerun 'python {fn}") 

192subprocess.Popen(f"python {fn}", shell=True) 

193