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
« prev ^ index » next coverage.py v7.13.5, created at 2026-04-01 07:48 +0000
1#!/usr/bin/env python
3"""
4Creates a template subject, i.e. the folder structure and the create_subject.py file.
6create_new_subject.py -f <path>
8-f ... path of new subject
9"""
10import os
11import warnings
12import argparse
13import subprocess
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()
19fn_subject = os.path.abspath(args.fn_subject)
20subject_id = os.path.split(fn_subject)[1]
22if os.path.exists(fn_subject):
23 print("Subject already exists... aborting")
24 exit()
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"))
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")
94f.write("\n")
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")
120f.write("\n")
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()
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)