示例#1
0
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
示例#2
0
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
示例#3
0
    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
示例#4
0
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