def rotation_wrapper(subj, side): """function calling all necessary steps; i.e. this function when called when initiating script is used to gather all data, whereas for special functionality other modules can be called/used""" input_folder = cfg['folders']['nifti'] CTimaging_orig, CTimaging_trans, _ = PrepareData.general_data( subj, input_folder, side) rotation, UnitVector = PrepareData.lead_details( subj, input_folder, side, rotation=Configuration.rotation_dict_mod()) angles, intensities_angle, vector, peak, markerfft, valleys, finalpeak = \ [{k: [] for k in rotation['slices'].keys()} for _ in range(7)] # Pre-allocate data for lvl in rotation['slices'].keys(): angles[lvl], intensities_angle[lvl], vector[lvl], peak[lvl], markerfft[lvl], valleys[lvl], finalpeak[lvl] = \ PrepareData.get_intensities(lvl, rotation['slices'][lvl], CTimaging_trans) rotation['vector'] = vector rotation['markerfft'] = markerfft['marker'] rotContact_coords = dict([(k, r) for k, r in rotation['coordinates'].items() if k.startswith('level')]) rotation = PrepareData.rotation_estimate( UnitVector, angles['marker'], finalpeak['marker'], intensities_angle, rotContact_coords, valleys['marker'], CTimaging_orig, rotation) return rotation
def function_wrapper(subj, side, lead_data=''): """function calling all necessary steps; i.e. this function when called when initiating script is used to gather all data, whereas for special functionality other modules can be called/used. The steps are as follows: a) load_LeadData, b) get_CTimaging, c) axialSlices (cf. lead_details) per level, d) get_intensities, e) rotation_estimate """ input_folder = cfg['folders']['nifti'] # default NIFTI-folder if not lead_data: lead_data, _, _ = General.load_leadData(subj, input_folder=input_folder, side=side) if lead_data['model'] not in ('Boston Vercise Directional', 'St Jude 6172', 'St Jude 6173'): print("\n\t...Rotation not required given 'non-directional' leads") rotation = {'angle': -math.pi / 10} return rotation # rotation not necessary for non-directional leads CTimaging_orig, CTimaging_trans = General.get_CTimaging(lead_data) rotation, UnitVector = General.lead_details( subj, input_folder, side=side, x_offset=[0] * 3, level_names=['marker', 'level1', 'level2'], rotation=Configuration.rotation_dict_mod(), single_lead=lead_data, CTimaging_orig=CTimaging_orig, CTimaging_trans=CTimaging_trans) angles, intensities_angle, vector, peak, markerfft, valleys, finalpeak = \ [{k: [] for k in rotation['slices'].keys()} for _ in range(7)] # Pre-allocate data for lvl in rotation['slices'].keys(): angles[lvl], intensities_angle[lvl], vector[lvl], peak[lvl], markerfft[lvl], valleys[lvl], finalpeak[lvl] = \ General.get_intensities(lvl, rotation['slices'][lvl], CTimaging_trans) rotation['vector'] = vector rotation['markerfft'] = markerfft['marker'] rotContact_coords = dict([(k, r) for k, r in rotation['coordinates'].items() if k.startswith('level')]) rotation = General.rotation_estimate(UnitVector, angles['marker'], finalpeak['marker'], intensities_angle, rotContact_coords, valleys['marker'], CTimaging_orig, rotation) return rotation
def lead_details(subj, input_folder, side='right', x_offset=[0] * 3, level_names=['marker', 'level1', 'level2'], rotation='', single_lead='', CTimaging_orig='', CTimaging_trans=''): """wrapper to retrieve default data for coordinates, slices, fitvolumes and boxes which are sorted in a sequential fashion; enabling changes as desired at later stages""" # Pre-allocate space and get 'empty' rotation dictionary if no input was provided if not rotation: rotation = Configuration.rotation_dict_mod() if not single_lead: single_lead, _, _ = General.load_leadData( subj, input_folder=input_folder, side=side) if not CTimaging_orig or not CTimaging_trans: CTimaging_orig, CTimaging_trans = General.get_CTimaging( single_lead) slices, boxes, fitvolumes, marker_coord, directional_coord, UnitVector = [ dict() for _ in range(6) ] for idx, k in enumerate(level_names): slices[k], boxes[k], fitvolumes[k], directional_coord[k], UnitVector = \ Specific.AxialSlices_levelwise(single_lead, CTimaging_trans, CTimaging_orig, x_offset=x_offset[idx], extractradius=30, part2lookfor=k, level_dist=int(idx)) # according to original script, slices [artifact_marker, artifact_dirX] MUST be flipped. Rationale for this # is not quite clear; cf. https://github.com/netstim/leaddbs/blob/master/ea_orient_main.m lines 138ff. for k, v in slices.items(): slices[k] = np.fliplr(v) # Update and return rotation dictionary for further processing for level in level_names: rotation['coordinates'][level] = directional_coord[level] rotation['plot_box'][level] = boxes[level] rotation['slices'][level] = slices[level] rotation['fitvolumes'][level] = fitvolumes[level] return rotation, UnitVector
def PaCER_script(subjects, inputfolder=''): """wrapper script for all steps included in the PaCER algorithm""" print("\nLead detection of {} subject(s)".format(len(subjects))) inputfolder = cfg['folders']['nifti'] if not inputfolder else inputfolder # select default input folder LW = LeadWorks() # load the class including necessary functions # Look for data files containing CT imaging including the brainMask and load this into workspace available_files = FileOperations.get_filelist_as_tuple(inputdir=inputfolder, subjects=subjects) regex2lookfor = 'reg_' + 'run[0-9]', 'brainmask_' file_id_CTimaging = [file_tuple for file_tuple in available_files if re.search(r'\w.({}).'.format(regex2lookfor[0]), file_tuple[0], re.IGNORECASE) and file_tuple[0].endswith('.nii') and 'CT' in file_tuple[0]] file_id_brainMask = [file_tuple for file_tuple in available_files if re.search(r'\w.({}).'.format(regex2lookfor[1]), file_tuple[0], re.IGNORECASE) and file_tuple[0].endswith('.nii')] if any(t > 2 for t in [len(k) for k in file_id_CTimaging]): print("More than one files for imaging or brainmask available. Please double-check!") return if not file_id_brainMask: warnings.warn(message="\tNo brain mask was found, trying to obtain a mask using ANTSpyNET routines") regex2lookforT1 = cfg['preprocess']['normalisation']['prefix'] + 'run' file_id_T1 = [file_tuple for file_tuple in available_files if re.search(r'\w.({}).'.format(regex2lookforT1), file_tuple[0], re.IGNORECASE) and 't1' in file_tuple[0] and file_tuple[0].endswith('.nii')] if not file_id_T1: Output.msg_box(text='No T1-sequence imaging available. BrainMask extraction impossible.', title='T1 sequences missing")') return else: T1imaging = ants.image_read(file_id_T1[0][0]) file_id_brainMask = Imaging.create_brainmask(input_folder=inputfolder, subj=''.join(subjects), registered_images=T1imaging) file_id_brainMask = [file_id_brainMask] if type(file_id_brainMask) == tuple else file_id_brainMask fileID = list(FileOperations.inner_join(file_id_brainMask, file_id_CTimaging)) # joins all to single list metal_threshold = int(cfg['lead_detection']['PaCER']['metal_threshold']) elecModels, intensityProfiles, skelSkalms = LW.electrodeEstimation(fileID[0], threshold=metal_threshold) elecModels, skelSkalms, intensityProfiles, _ = \ LeadProperties.estimate_hemisphere(elecModels, intensityProfiles, skelSkalms) # returns hemisphere from coords. filename_save = os.path.join(os.path.join(inputfolder, subjects[0]), 'elecModels_' + subjects[0] + '.pkl') with open(filename_save, "wb") as f: pickle.dump(elecModels, f) pickle.dump(intensityProfiles, f) pickle.dump(skelSkalms, f) sides = ['left', 'right'] rotation_default, rotation_mod = [{k: [] for k in sides} for _ in range(2)] for s in sides: rotation_default[s] = function_wrapper(subj=subjects[0], side=s) rotation_mod[s] = Configuration.rotation_dict_mod() # creates an empty array to save modified data later filename_save = os.path.join(os.path.join(inputfolder, subjects[0]), 'rotation_' + subjects[0] + '.pkl') with open(filename_save, "wb") as f: pickle.dump(rotation_default, f) pickle.dump(rotation_mod, f) print("Finished with lead detection!") # TODO: it does not return to the empty command line. return