示例#1
0
 def save_cfg_dicomdir(self):
     """Function intended to save the DICOM directory once button is pressed"""
     self.cfg['folders']['dicom'] = self.working_dir
     Configuration.save_config(self.cfg['folders']["rootdir"], self.cfg)
     Output.msg_box(
         text="Folder changed in the configuration file to {}".format(
             self.working_dir),
         title='Changed folder')
示例#2
0
    def closeEvent(self, event):
        """saves the settings found here as a yaml file which may be loaded the next time as the configuration used"""

        self.cfg["preprocess"]["dcm2nii"][
            "OutputFileStruct"] = self.lineEditFilename.text()
        self.cfg["preprocess"]["dcm2nii"][
            "IncludeFiles"] = self.lineEditIncludeFiles.text()
        Configuration.save_config(self.cfg["folders"]["rootdir"], self.cfg)
        event.accept()
示例#3
0
    def closeEvent(self, event):
        """saves the settings found here as a yaml file which may be loaded the next time as the configuration used"""

        self.cfg["lead_detection"]["PaCER"][
            "metal_threshold"] = self.lineEditMetalThreshold.text()
        self.cfg["lead_detection"]["PaCER"][
            "snr_threshold"] = self.lineEditSNRThreshold.text()
        self.cfg["lead_detection"]["PaCER"]["lambda"] = int(
            self.lineEditLambda.text())

        Configuration.save_config(ROOTDIR, self.cfg)
        event.accept()
示例#4
0
    def redefineDefault(self):
        """redefines which template is set as default on the right list and in the cfg-file"""

        if not self.selected_subj_Gen:
            Output.msg_box(text="No template selected. Please indicate new default one.", title="No data selected")
            return
        elif len(self.selected_subj_Gen) > 1:
            Output.msg_box(text="Please select only one image as default.", title="Too many templates selected")
            return
        else:
            default_template = [FileOperations.return_full_filename(self.wdirTemplate, x) for x in self.selected_subj_Gen]
            self.cfg['folders']['default_template'] = default_template[0]
            Configuration.save_config(ROOTDIR, self.cfg)

        self.run_reload_files()
示例#5
0
    def run_reload_files(self):
        """Reloads files, e.g. after renaming them"""

        self.cfg = Configuration.load_config(self.cfg['folders']['rootdir'])
        self.availableTemplates.clear()
        itemsTab = set(FileOperations.list_files_in_folder(self.wdirTemplate))
        self.add_available_templates(self.availableTemplates, itemsTab)
示例#6
0
    def run_reload_files(self):
        """Reloads files, e.g. after renaming them"""
        self.cfg = Configuration.load_config(ROOTDIR)
        self.availableNiftiTab.clear()

        itemsChanged = FileOperations.list_folders(self.cfg['folders']['nifti'], prefix=self.cfg['folders']['prefix'])
        self.add_available_items(self.availableNiftiTab, itemsChanged)
示例#7
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
示例#8
0
    def change_workingdir(self):
        """A new window appears in which the working directory can be set; besides, data is stored in the preferences
        file so that they will be loaded automatically next time"""

        self.working_dir = QFileDialog.getExistingDirectory(
            self,
            directory=self.working_dir,
            caption='Change working directory')
        self.label_workingdir.setText('Working DIR: {}'.format(
            self.working_dir))
        self.mInput.clear()

        items = FileOperations.list_folders(self.working_dir, prefix='')
        self.addAvailableItems(items)
        if self.option_gui == 'dcm2niix':
            self.cfg['folders']['dicom'] = self.working_dir
            Configuration.save_config(self.cfg['folders']["rootdir"], self.cfg)
示例#9
0
    def closeEvent(self, event):
        """saves the settings found here as a yaml file which may be loaded the next time as the configuration used"""

        self.cfg["preprocess"]["ANTsN4"]["prefix"] = self.lineEditPrefix.text()
        self.cfg["preprocess"]["ANTsN4"]["shrink-factor"] = int(self.lineEditShrink.text())
        self.cfg["preprocess"]["ANTsN4"]["bspline-fitting"] = int(self.lineEditBSplineDist.text())
        self.cfg["preprocess"]["ANTsN4"]["convergence"][0] = int(self.lineEditConv1.text())
        self.cfg["preprocess"]["ANTsN4"]["convergence"][1] = int(self.lineEditConv2.text())
        self.cfg["preprocess"]["ANTsN4"]["convergence"][2] = int(self.lineEditConv3.text())
        self.cfg["preprocess"]["ANTsN4"]["convergence"][3] = int(self.lineEditConv4.text())
        self.cfg["preprocess"]["ANTsN4"]["threshold"] = float(self.lineEditTolerance.text())
        self.cfg["preprocess"]["ANTsN4"]["dti_prefix"] = self.lineEditDiffPrefix.text()

        self.cfg["preprocess"]["registration"]["prefix"] = self.lineEditPrefixRegistration.text()
        self.cfg["preprocess"]["registration"]["resample_spacing"] = self.lineResampleSpacing.text()

        self.cfg["preprocess"]["normalisation"]["sequences"] = self.lineEditNormalisationSequences.text()

        Configuration.save_config(ROOTDIR, self.cfg)
        event.accept()
示例#10
0
    def __init__(self, subject, inputfolder=''):
        self.cfg = Configuration.load_config(ROOTDIR)
        self.debug = False
        GetData()
        # TODO: new order with a) get 'static data' such as background, trajectory, lead_model, b) plot all results.
        # TODO: c) include some variable data (markers, rotation) and add some callback functions in form of arrows

        # Get static data, that is lead data, backgrounds and trajectories
        filename_leadmodel = os.path.join(inputfolder,
                                          'elecModels_' + subject + '.pkl')
        lead_data_raw, intensityProfiles, skelSkalms = self.load_leadModel(
            inputfolder, filename=filename_leadmodel)
        lead_data, sides = self.estimate_hemisphere(
            lead_data_raw)  # determines which side is used in lead_data
        lead_model, default_positions, default_coordinates = GetData.get_default_lead(
            lead_data_raw[0])  # all in [mm]

        # Get initial data for both leads
        marker, coordinates, trajectory, resize, emp_dist = [{}
                                                             for _ in range(5)]
        for hemisphere in sides:
            marker[hemisphere], coordinates[hemisphere], trajectory[hemisphere], resize[hemisphere] = \
                GetData.get_leadModel(self, lead_data[hemisphere], default_positions, default_coordinates, side=hemisphere)
            _, emp_dist[hemisphere] = GetData.resize_coordinates(
                self, coordinates[hemisphere], lead_data[hemisphere])
            _, lead_data[hemisphere]['trajectory'], _, marker_temp = \
                GetData.resolve_coordinates(self, marker[hemisphere], default_coordinates, default_positions,
                                            lead_data[hemisphere], resize_bool=resize[hemisphere],
                                            rszfactor=emp_dist[hemisphere]) # This part doesn't do anything meaningful!

        # Get data for xy-plane estimation/plot
        intensity_matrix, bounding_box, fitvolume = GetData.multiprocessing_xyplanes(
            self, lead_data, trajectory)

        # Start plotting the 'fixed parts', that is lead model (left) and CT intensitiy planes (middle)
        # fig, grid = self.create_figure()
        # fig, layout = self.create_figure_plotly()
        layout = self.create_figure_plotly()
        data = []
        data = self.plotCTintensitiesPlotLy(intensity_matrix['left'],
                                            fitvolume['left'], data)

        fig = go.Figure(data=data, layout=layout)
        fig.show()
        # https://community.plotly.com/t/moving-the-location-of-a-graph-point-interactively/7161/2 # TODO Next steps
        # CTintensitiesLeft = fig.add_subplot(grid[0:3,0], facecolor='None', projection='3d')
        # CTintensitiesLeft = self.plotCTintensitiesNEW(CTintensitiesLeft, intensity_matrix['left'],
        #                                              bounding_box['left'], fitvolume['left'], trajectory['left'])

        # CTintensitiesRight = fig.add_subplot(grid[0:,2:3], facecolor='None', projection='3d')

        self.interactive_plot(lead_data['right'], intensityProfiles,
                              skelSkalms)
示例#11
0
文件: GuiMain.py 项目: dpedrosac/cDBS
    def __init__(self, parent=None):
        super(TabContent, self).__init__()
        self.selected_subj_Gen = ''
        self.selected_subj_ANT = ''

        self.cfg = Configuration.load_config(ROOTDIR)
        if os.path.isdir(self.cfg['folders']['nifti']):
            self.niftidir = self.cfg['folders']['nifti']
        else:
            self.niftidir = os.getcwd()
        self.cfg['folders']['rootdir'] = ROOTDIR
        Configuration.save_config(ROOTDIR, self.cfg)

        # General layout for the tab view and initialisation of tabs
        self.layout = QVBoxLayout(self)
        self.tabs = QTabWidget()
        self.tabs.resize(150, 100)
        self.layout.addWidget(self.tabs)

        # Customize tabs
        # ==============================    Tab 1 - General   ==============================
        self.tab1 = GuiTabGeneral()
        self.tabs.addTab(self.tab1, "General")

        # ==============================    Tab 2 - Work on templates   ==============================
        self.tab2 = GuiTabTemplate()
        self.tabs.addTab(self.tab2, "Template")

        # ==============================    Tab 3 - ANTs routines   ==============================
        self.tab3 = GuiTabPreprocessANTs()
        self.tabs.addTab(self.tab3, "Preprocess Imaging (ANTsPy)")

        # ==============================    Tab 3 - Lead detection   ==============================
        self.tab4 = GuiTabDetectLeads()
        self.tabs.addTab(self.tab4, "Detect leads (Pacer)")

        # Add tabs to widget
        self.layout.addWidget(self.tabs)
        self.setLayout(self.layout)
示例#12
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
示例#13
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
示例#14
0
    def itk_snap_check(rootdir=''):
        """checks for common folders in different platforms in which ITK-snap may be saved. """

        rootdir = ROOTDIR if not rootdir else rootdir
        platform = sys.platform
        cfg = Configuration.load_config(ROOTDIR)         # TODO: include the version stored in dependencies.py
        if not cfg['folders']['path2itksnap']:
            if platform == 'linux':
                default_folders = ["/etc/bin/", "/usr/lib/snap-3.6.0", "/usr/lib/snap-3.6.0/ITK-SNAP",
                                   os.path.join(rootdir, 'ext', 'snap-3.6.0')]
            elif platform == 'macos' or platform == 'darwin':
                default_folders = ['/Applications/ITK-SNAP.app/']

            try:
                folder = [folder_id for folder_id in default_folders if os.path.isfile(os.path.join(folder_id, "ITK-SNAP"))]
            except KeyError:
                folder = QFileDialog.getExistingDirectory('Please indicate location of ITK-SNAP.')
        else:
            folder = cfg['folders']['path2itksnap']
        # Here a dialog is needed in case folder has many flags to folders with itk-snap

        return folder[0]
示例#15
0
    def __init__(self, _folderlist):
        self.logfile = True
        self.cfg = Configuration.load_config(ROOTDIR)
        self.DCM2NIIX_ROOT = os.path.join(ROOTDIR, 'ext', 'dcm2niix')

        if not os.path.isdir(self.cfg['folders']['dicom']):
            Output.msg_box(
                text="Please indicate a correct folder in the main GUI",
                title="Wrong folder")
        else:
            self.inputdir = self.cfg['folders']['dicom']

        subjlist = self.create_subjlist(_folderlist)

        if not os.path.isdir(self.DCM2NIIX_ROOT):
            Output.msg_box(
                text=
                "Extracting imaging data from DICOM-files not successful because of wrong "
                "folder for 'dcm2niix'.",
                title="Wrong folder!")
            return

        if not os.path.isdir(self.cfg['folders']['nifti']):
            print(
                "\nDirectory for output is invalid; assuming same base and creating folder named 'nifti' therein!"
            )
            self.outdir = os.path.join(
                os.path.split(self.inputdir)[0], 'nifti')
            if not os.path.isdir(self.outdir):
                os.mkdir(self.outdir)
        else:
            self.outdir = self.cfg['folders']['nifti']

        lastsubj = self.get_index_nifti_folders(
            self.outdir, prefix=self.cfg['folders']['prefix'])

        self.create_csv_subjlist(subjlist, int(lastsubj))
        self.convert_dcm2nii(subjlist, last_idx=int(lastsubj))
示例#16
0
    def save_cfg(self):
        """Function intended to save the DICOM directory once button is pressed"""

        self.cfg['folders']['dicom'] = self.dicomdir
        Configuration.save_config(self.cfg['folders']['rootdir'], self.cfg)
        Output.msg_box(text="Folder changed in configuration to {}".format(self.dicomdir), title="Changed folder")
示例#17
0
 def __init__(self):
     self.cfg = Configuration.load_config(ROOTDIR)
     self.verbose = True
示例#18
0
    def __init__(self, parent=None):
        super(GuiLeadDetection, self).__init__(parent=None)

        # Load configuration files and general settings
        self.cfg = Configuration.load_config(ROOTDIR)

        # General appearance of the GUI
        self.setFixedSize(800, 600)
        self.setWindowTitle(
            'Settings for Lead Detection using the different packages')
        self.show()

        # Create general layout
        self.layout_tot = QVBoxLayout(self)

        # ==============================    Create Content for Left Upper Box   ==============================
        self.optionboxPaCER = QGroupBox('PaCER')
        self.settings_list1 = QVBoxLayout(self.optionboxPaCER)

        self.labelMetalThreshold = QLabel('Metal threshold?\t\t')
        self.labelMetalThreshold.setToolTip(setToolTips.PaCER_MetalThreshold())
        self.lineEditMetalThreshold = QLineEdit()

        lay1 = QHBoxLayout()
        lay1.addWidget(self.labelMetalThreshold)
        lay1.addWidget(self.lineEditMetalThreshold)
        lay1.addStretch()

        self.labelSNRThreshold = QLabel('SNR threshold?\t\t')
        #self.labelSNRThreshold.setToolTip(setToolTips.PaCER_MetalThreshold())
        self.lineEditSNRThreshold = QLineEdit()

        lay2 = QHBoxLayout()
        lay2.addWidget(self.labelSNRThreshold)
        lay2.addWidget(self.lineEditSNRThreshold)
        lay2.addStretch()

        self.labelLambda = QLabel('Lambda?\t\t\t')
        self.labelLambda.setToolTip(setToolTips.PaCER_Lambda())
        self.lineEditLambda = QLineEdit()
        regex = QtCore.QRegExp('^[0-9]\d{1}$')
        validator1 = QtGui.QRegExpValidator(regex)
        self.lineEditLambda.setValidator(validator1)

        lay3 = QHBoxLayout()
        lay3.addWidget(self.labelLambda)
        lay3.addWidget(self.lineEditLambda)
        lay3.addStretch()

        self.labelProbMask = QLabel('Use probabilisitic mask?\t')
        self.labelProbMask.setToolTip(setToolTips.ProbabilisticMask())
        self.btngroup_ProbMask = QButtonGroup()
        self.rbtnProbMasky = QRadioButton('yes')
        self.rbtnProbMaskn = QRadioButton('no')
        self.rbtnProbMasky.toggled.connect(self.onClickedRBTN_ProbMask)
        self.rbtnProbMaskn.toggled.connect(self.onClickedRBTN_ProbMask)

        self.btngroup_ProbMask.addButton(self.rbtnProbMasky)
        self.btngroup_ProbMask.addButton(self.rbtnProbMaskn)
        lay4 = QHBoxLayout()
        lay4.addWidget(self.labelProbMask)
        lay4.addWidget(self.rbtnProbMasky)
        lay4.addWidget(self.rbtnProbMaskn)
        lay4.addStretch()

        self.labelDetectionMethod = QLabel('Detection method?\t')
        self.lineDetectionMethod = QComboBox()
        allowable_methods = ["peak", "peakWaveCenter", "contactAreaCenter"]
        [self.lineDetectionMethod.addItem(x) for x in allowable_methods]
        idx_method = self.lineDetectionMethod.findText(
            self.cfg["lead_detection"]["PaCER"]["detection_method"],
            QtCore.Qt.MatchFixedString)

        if idx_method >= 0:
            self.lineDetectionMethod.setCurrentIndex(idx_method)
        self.lineDetectionMethod.currentTextChanged.connect(
            self.comboChangedDetectionMethod)
        self.lineDetectionMethod.setDisabled(False)

        lay5 = QHBoxLayout()
        lay5.addWidget(self.labelDetectionMethod)
        lay5.addWidget(self.lineDetectionMethod)
        lay5.addStretch()

        self.labelLeadType = QLabel('Implanted lead?\t\t')
        self.lineLeadType = QComboBox()
        allowable_leads = [
            "Medtronic 3387", "Medtronic 3389", "Boston Vercise Directional",
            "Boston Vercise Nondirectional", "St Jude 6172", "St Jude 6173"
        ]
        [self.lineLeadType.addItem(x) for x in allowable_leads]
        idx_method = self.lineLeadType.findText(
            self.cfg["lead_detection"]["PaCER"]["lead_type"],
            QtCore.Qt.MatchFixedString)
        if idx_method >= 0:
            self.lineLeadType.setCurrentIndex(idx_method)
        self.lineLeadType.currentTextChanged.connect(self.comboChangedLeadType)
        self.lineLeadType.setDisabled(False)

        lay6 = QHBoxLayout()
        lay6.addWidget(self.labelLeadType)
        lay6.addWidget(self.lineLeadType)
        lay6.addStretch()

        self.labelTransformMatrix = QLabel('Use transformation matrix?\t')
        self.labelProbMask.setToolTip(setToolTips.ProbabilisticMask())
        self.btngroup_TransformMatrx = QButtonGroup()
        self.rbtnTransformMatrixy = QRadioButton('yes')
        self.rbtnTransformMatrixn = QRadioButton('no')
        self.rbtnProbMasky.toggled.connect(
            self.onClickedRBTN_TransformationMatrix)
        self.rbtnProbMaskn.toggled.connect(
            self.onClickedRBTN_TransformationMatrix)

        self.btngroup_TransformMatrx.addButton(self.rbtnTransformMatrixy)
        self.btngroup_TransformMatrx.addButton(self.rbtnTransformMatrixn)
        lay7 = QHBoxLayout()
        lay7.addWidget(self.labelTransformMatrix)
        lay7.addWidget(self.rbtnTransformMatrixy)
        lay7.addWidget(self.rbtnTransformMatrixn)
        lay7.addStretch()

        self.settings_list1.addLayout(lay1)
        self.settings_list1.addLayout(lay2)
        self.settings_list1.addLayout(lay3)
        self.settings_list1.addLayout(lay4)
        self.settings_list1.addLayout(lay5)
        self.settings_list1.addLayout(lay6)
        self.settings_list1.addLayout(lay7)
        self.settings_list1.addStretch()

        # ==============================    Create Content for Right Upper Box   ==============================
        # self.optionboxRegistration = QGroupBox('Other')
        # self.settings_list2 = QVBoxLayout(self.optionboxMarALAGO)
        # self.settings_list2.addLayout(lay1)

        # self.labelPrefixRegistration = QLabel('Registration prefix?\t')
        # self.labelPrefixRegistration.setToolTip(setToolTips.LabelPrefixBias())
        # self.lineEditPrefixRegistration = QLineEdit()

        # lay8 = QHBoxLayout()
        # lay8.addWidget(self.labelPrefixRegistration)
        # lay8.addWidget(self.lineEditPrefixRegistration)
        # lay8.addStretch()

        # self.settings_list2.addLayout(lay8)
        # self.settings_list2.addStretch(1)

        # Merge all upper boxes
        self.layout_upper = QHBoxLayout()
        self.layout_upper.addWidget(self.optionboxPaCER)
        # self.layout_upper.addWidget(self.optionboxMarALAGO)

        # ====================    Create Content for Buttons at the Bottom      ====================
        layout_bottom = QHBoxLayout()
        self.buttonsave = QPushButton('Save settings \nand return')
        self.buttonsave.clicked.connect(self.close)
        self.buttondefault = QPushButton('Load Default \nsettings')
        self.buttondefault.clicked.connect(self.load_default_settings)

        layout_bottom.addStretch(1)
        layout_bottom.addWidget(self.buttonsave)
        layout_bottom.addWidget(self.buttondefault)

        # ====================    Set Content of box and buttoms to General Layout     =======================
        self.layout_tot.addLayout(self.layout_upper)
        self.layout_tot.addLayout(layout_bottom)
        self.get_settings_from_config()
示例#19
0
    def __init__(self, parent=None):
        super(QWidget, self).__init__(parent=None)
        self.cfg = Configuration.load_config(ROOTDIR)

        # General appearance of the GUI
        self.setFixedSize(600, 400)
        self.setWindowTitle('Settings for converting DICOM to NIFTI files')
        self.show()

        # Create general layout
        self.layout = QVBoxLayout(self)

        # ==============================    Create Content for First Box   ==============================
        self.optionbox = QGroupBox('Settings for dcm2niix')
        self.settings_list = QVBoxLayout(self.optionbox)

        self.labelBIDS = QLabel('Do you want to create a BIDS sidecar?\t\t')
        self.labelBIDS.setToolTip(setToolTips.LabelBIDS())
        self.btngroup_BIDS = QButtonGroup()
        self.rbtnBIDSy = QRadioButton('yes')
        self.rbtnBIDSn = QRadioButton('no')
        self.rbtnBIDSy.toggled.connect(self.onClickedRBTN_BIDS)
        self.rbtnBIDSn.toggled.connect(self.onClickedRBTN_BIDS)

        self.btngroup_BIDS.addButton(self.rbtnBIDSy)
        self.btngroup_BIDS.addButton(self.rbtnBIDSn)
        lay1 = QHBoxLayout()
        lay1.addWidget(self.labelBIDS)
        lay1.addWidget(self.rbtnBIDSy)
        lay1.addWidget(self.rbtnBIDSn)
        lay1.addStretch()

        self.labelVerbosity = QLabel(
            'Please indicate the amount of \noutput from dcm2nii ("verbosity")\t\t\t'
        )
        self.labelVerbosity.setToolTip(setToolTips.LabelVerbosity())
        self.btngroup_verbosity = QButtonGroup()
        self.rbtnVerbosity0 = QRadioButton('0')
        self.rbtnVerbosity1 = QRadioButton('1')
        self.rbtnVerbosity2 = QRadioButton('2')
        self.rbtnVerbosity0.toggled.connect(self.onClickedRBTN_verbose)
        self.rbtnVerbosity1.toggled.connect(self.onClickedRBTN_verbose)
        self.rbtnVerbosity2.toggled.connect(self.onClickedRBTN_verbose)

        self.btngroup_verbosity.addButton(self.rbtnVerbosity0)
        self.btngroup_verbosity.addButton(self.rbtnVerbosity1)
        self.btngroup_verbosity.addButton(self.rbtnVerbosity2)

        lay2 = QHBoxLayout()
        lay2.addWidget(self.labelVerbosity)
        lay2.addWidget(self.rbtnVerbosity0)
        lay2.addWidget(self.rbtnVerbosity1)
        lay2.addWidget(self.rbtnVerbosity2)
        lay2.addStretch()

        self.labelCompression = QLabel(
            'Do you want dcm2niix to compress the \nresulting NIFTI files?\t\t\t\t'
        )
        self.labelCompression.setToolTip(setToolTips.CompressionDCM2NII())
        self.btngroup_Compression = QButtonGroup()
        self.rbtnCompressiony = QRadioButton('yes')
        self.rbtnCompressionn = QRadioButton('no')
        self.rbtnCompressiony.toggled.connect(self.onClickedRBTN_Compression)
        self.rbtnCompressionn.toggled.connect(self.onClickedRBTN_Compression)

        self.btngroup_Compression.addButton(self.rbtnCompressiony)
        self.btngroup_Compression.addButton(self.rbtnCompressionn)
        lay3 = QHBoxLayout()
        lay3.addWidget(self.labelCompression)
        lay3.addWidget(self.rbtnCompressiony)
        lay3.addWidget(self.rbtnCompressionn)
        lay3.addStretch()

        self.labelFilename = QLabel(
            'What should output filenames be like?\t\t')
        self.labelFilename.setToolTip(setToolTips.LabelFilenameDCM2NII())
        self.lineEditFilename = QLineEdit()
        regex = QtCore.QRegExp("[a-z-A-Z-0-9%_]+")
        validator1 = QtGui.QRegExpValidator(regex)
        self.lineEditFilename.setValidator(validator1)

        lay4 = QHBoxLayout()
        lay4.addWidget(self.labelFilename)
        lay4.addWidget(self.lineEditFilename)
        lay4.addStretch()

        self.labelIncludeFiles = QLabel(
            'Please indicate the sequences to keep?\t\t')
        self.labelIncludeFiles.setToolTip(setToolTips.includeFilesDCM2NII())
        self.lineEditIncludeFiles = QLineEdit()
        regex = QtCore.QRegExp("[a-z-A-Z-0-9,_]+")
        validator2 = QtGui.QRegExpValidator(regex)
        self.lineEditIncludeFiles.setValidator(validator2)

        lay5 = QHBoxLayout()
        lay5.addWidget(self.labelIncludeFiles)
        lay5.addWidget(self.lineEditIncludeFiles)
        lay5.addStretch()

        self.labelReorientCrop = QLabel(
            'Do you want dcm2niix to reorient \nand crop resulting NIFTI-files?\t\t\t'
        )
        self.labelReorientCrop.setToolTip(setToolTips.LabelReorientCrop())
        self.btngroup_ReorientCrop = QButtonGroup()
        self.rbtnReorientCropy = QRadioButton('yes')
        self.rbtnReorientCropn = QRadioButton('no')
        self.rbtnReorientCropy.toggled.connect(self.onClickedRBTN_ReorientCrop)
        self.rbtnReorientCropn.toggled.connect(self.onClickedRBTN_ReorientCrop)

        self.btngroup_ReorientCrop.addButton(self.rbtnReorientCropy)
        self.btngroup_ReorientCrop.addButton(self.rbtnReorientCropn)
        lay6 = QHBoxLayout()
        lay6.addWidget(self.labelReorientCrop)
        lay6.addWidget(self.rbtnReorientCropy)
        lay6.addWidget(self.rbtnReorientCropn)
        lay6.addStretch()

        self.settings_list.addLayout(lay1)
        self.settings_list.addLayout(lay2)
        self.settings_list.addLayout(lay3)
        self.settings_list.addLayout(lay4)
        self.settings_list.addLayout(lay5)
        self.settings_list.addLayout(lay6)

        # ====================    Create Content for Buttons at the Bottom      ====================
        layout_bottom = QHBoxLayout()
        self.buttonsave = QPushButton('Save settings \nand return')
        self.buttonsave.clicked.connect(self.close)
        self.buttondefault = QPushButton('Load Default \nsettings')
        self.buttondefault.clicked.connect(self.load_default_DCM2NIIsettings)

        layout_bottom.addStretch(1)
        layout_bottom.addWidget(self.buttonsave)
        layout_bottom.addWidget(self.buttondefault)

        # ====================    Set Content of box and buttoms to General Layout     =======================
        self.layout.addWidget(self.optionbox)
        self.layout.addLayout(layout_bottom)
        self.get_settings_from_config()
示例#20
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
示例#21
0
    def __init__(self, working_directory, _option_gui, parent=None):
        super(QWidget, self).__init__(parent)
        self.cfg = Configuration.load_config(ROOTDIR)
        self.option_gui = _option_gui

        # ============================    Different options available   ============================
        if self.option_gui == 'dcm2niix':
            working_dir = self.cfg['folders']['dicom']
            self.working_dir = working_dir if os.path.isdir(
                working_dir) else os.getcwd()
            options = {
                'folderbox_title': "Directory (DICOM-files)",
                'str_labelDir': 'DICOM DIR: {}'.format(self.working_dir),
                'runBTN_label': 'Run processing'
            }

        elif self.option_gui == 'displayNiftiFiles':
            if not working_directory:
                Output.msg_box(
                    text="Please provide a valid folder. Terminating this GUI.",
                    title="No folder provided")
                self.close()
                return
            else:
                self.working_dir = working_directory
            options = {
                'folderbox_title': "Directory (nifti-files)",
                'str_labelDir': 'subjects\' DIR: {}'.format(self.working_dir),
                'runBTN_label': 'View files'
            }
        else:
            Output.msg_box(
                text=
                "Please provide a valid option such as 'dcm2niix' or 'displayNiftiFiles'. "
                "Terminating the GUI",
                title="Wrong input as option")
            self.close()
            return

        # ============================    Start creating layout   ============================
        # Create general layout
        self.tot_layout = QVBoxLayout(self)
        self.mid_layout = QHBoxLayout(self)

        # ============================    Create upper of  GUI, i.e. working directory   ============================
        self.label_folderbox = QGroupBox(options["folderbox_title"])
        self.HBoxUpperTwoListGUI = QVBoxLayout(self.label_folderbox)
        self.label_workingdir = QLabel(options["str_labelDir"])
        self.HBoxUpperTwoListGUI.addWidget(self.label_workingdir)

        self.btn_workingdir = QPushButton('Change working \ndirectory')
        self.btn_workingdir.setFixedSize(150, 40)
        self.btn_workingdir.setDisabled(True)
        if self.option_gui == 'dcm2niix':
            self.btn_workingdir.setEnabled(True)
        self.btn_workingdir.clicked.connect(self.change_workingdir)

        self.btn_savedir = QPushButton('Save directory \nto config file')
        self.btn_savedir.setFixedSize(150, 40)
        self.btn_savedir.setDisabled(True)
        if self.option_gui == 'dcm2niix':
            self.btn_savedir.setEnabled(True)
            self.btn_savedir.setToolTip(
                Output.split_lines(setToolTips.saveDirButton()))
        self.btn_savedir.clicked.connect(self.save_cfg_dicomdir)

        hlay_upper = QHBoxLayout()
        hlay_upper.addWidget(self.btn_workingdir)
        hlay_upper.addWidget(self.btn_savedir)
        hlay_upper.addStretch(1)
        self.HBoxUpperTwoListGUI.addLayout(hlay_upper)

        # ====================    Create Content for Lists, i.e. input/output      ====================
        self.listboxInputGUITwoList = QGroupBox(
            'Available items in working directory')
        self.listboxInput = QVBoxLayout(self.listboxInputGUITwoList)
        self.mInput = QListWidget()
        self.listboxInput.addWidget(self.mInput)

        self.mButtonToAvailable = QPushButton("<<")
        self.mBtnMoveToAvailable = QPushButton(">")
        self.mBtnMoveToSelected = QPushButton("<")
        self.mButtonToSelected = QPushButton(">>")
        self.mBtnUp = QPushButton("Up")
        self.mBtnDown = QPushButton("Down")

        self.listboxOutputGUITwoLIst = QGroupBox('Items to process')
        self.listboxOutput = QVBoxLayout(self.listboxOutputGUITwoLIst)
        self.mOutput = QListWidget()
        self.listboxOutput.addWidget(self.mOutput)

        # First column (Left side)
        vlay = QVBoxLayout()
        vlay.addStretch()
        vlay.addWidget(self.mBtnMoveToAvailable)
        vlay.addWidget(self.mBtnMoveToSelected)
        vlay.addStretch()
        vlay.addWidget(self.mButtonToAvailable)
        vlay.addWidget(self.mButtonToSelected)
        vlay.addStretch()

        # Second column (Right side)
        vlay2 = QVBoxLayout()
        vlay2.addStretch()
        vlay2.addWidget(self.mBtnUp)
        vlay2.addWidget(self.mBtnDown)
        vlay2.addStretch()

        # ====================    Lower part of GUI, i.e. Preferences/Start estimation      ====================
        self.btn_preferences = QPushButton("Preferences")
        self.btn_preferences.setDisabled(True)
        self.btn_preferences.clicked.connect(self.settings_show)
        if self.option_gui == 'dcm2niix':
            self.btn_preferences.setEnabled(True)

        self.btn_run_command = QPushButton(options["runBTN_label"])
        if self.option_gui == 'dcm2niix':
            self.btn_run_command.setToolTip(setToolTips.run_dcm2niix())
        else:
            self.btn_run_command.setToolTip(
                setToolTips.run_CheckRegistration())
        self.btn_run_command.clicked.connect(self.start_process)

        hlay_bottom = QHBoxLayout()
        hlay_bottom.addStretch(1)
        hlay_bottom.addWidget(self.btn_preferences)
        hlay_bottom.addWidget(self.btn_run_command)
        hlay_bottom.addStretch()

        # ====================    Set all contents to general Layout     =======================
        self.mid_layout.addWidget(self.listboxInputGUITwoList)
        self.mid_layout.addLayout(vlay)
        self.mid_layout.addWidget(self.listboxOutputGUITwoLIst)
        self.mid_layout.addLayout(vlay2)

        self.tot_layout.addWidget(self.label_folderbox)
        self.tot_layout.addLayout(self.mid_layout)
        self.tot_layout.addLayout(hlay_bottom)

        try:
            self.mInput.clear()
            if self.option_gui == 'dcm2niix':
                items = FileOperations.list_folders(self.working_dir,
                                                    prefix='')
            else:
                items = FileOperations.list_files_in_folder(
                    inputdir=self.working_dir, contains='', suffix='nii')
            self.addAvailableItems(items)
        except FileExistsError:
            print('{} without any valid files/folders, continuing ...'.format(
                self.working_dir))

        self.update_buttons_status()
        self.connections()
示例#22
0
    def extractAxialSlices(single_lead,
                           CTimaging_trans,
                           CTimaging_orig,
                           extractradius=30,
                           offset=0,
                           levels=('level1', 'level2')):
        """ extracts intensities of axial slices of the CT. In order to get a consistent artefact
        at the marker, a transformation to the original data is necessary as this corresponds to a steeper angle"""

        cfg = Configuration.load_config(ROOTDIR)
        lead_settings = {
            'Boston Vercise Directional': {
                'markerposition': 10.25,
                'leadspacing': 2
            },
            'St Jude 6172': {
                'markerposition': 9,
                'leadspacing': 2
            },
            'St Jude 6173': {
                'markerposition': 12,
                'leadspacing': 3
            }
        }

        intensity, box, rot_contact_coordinates = [dict() for _ in range(3)
                                                   ]  # pre-allocate for later
        estimated_markers = dict([(k, r) for k, r in single_lead.items()
                                  if k.startswith('marker')])
        file_invMatrix = os.path.join(single_lead['filenameCTimaging'][0],
                                      'CT2template_1InvWarpMatrix.mat')

        # Convert the markers to the imaging of the original data with the transformation matrix
        marker_rawCT = dict()
        for marker, coordinates in estimated_markers.items():
            coords_temp = [int(round(c)) for c in coordinates]
            transformed = LeadProperties.transform_coordinates(
                coords_temp,
                from_imaging=CTimaging_trans,
                to_imaging=CTimaging_orig,
                file_invMatrix=file_invMatrix)
            marker_rawCT[marker] = np.array(
                transformed['points'])  # use points to account for distances

        unit_vector_rawCT = np.divide(
            (marker_rawCT['markers_tail'] - marker_rawCT['markers_head']),
            np.linalg.norm(marker_rawCT['markers_tail'] -
                           marker_rawCT['markers_head']))
        marker_raw_mm = np.round(
            marker_rawCT['markers_head'] + [0, 0, offset] +
            np.multiply(lead_settings[single_lead['model']]['markerposition'],
                        unit_vector_rawCT))
        marker_raw = ants.transform_physical_point_to_index(
            CTimaging_orig, point=marker_raw_mm)

        cfg = cfg['preprocess']['registration']
        filenameCT = '/'.join(
            re.split(r".{}run[0-9].".format(cfg['prefix']),
                     os.path.join(*single_lead['filenameCTimaging'])))
        intensity['marker'], box['marker'], _ = GetImaging.get_axialplanes(
            marker_raw,
            filenameCT,
            unit_vector_rawCT,
            window_size=extractradius)
        marker_coordinates = marker_raw

        # Loop through the directional leads in order to obtain all necessary coordinates
        for idx, l in enumerate(levels, start=1):
            rot_contact_coordinates[l] = np.round(
                marker_rawCT['markers_head'] + [0, 0, offset] + np.multiply(
                    unit_vector_rawCT, idx *
                    lead_settings[single_lead['model']]['leadspacing']))
            rot_contact_coordinates[
                l] = ants.transform_physical_point_to_index(
                    CTimaging_orig, point=rot_contact_coordinates[l])
            intensity[l], box[l], _ = GetImaging.get_axialplanes(
                rot_contact_coordinates[l],
                filenameCT,
                unit_vector_rawCT,
                window_size=extractradius)

        return intensity, box, marker_coordinates, rot_contact_coordinates
示例#23
0
    def AxialSlices_levelwise(single_lead,
                              CTimaging_trans,
                              CTimaging_orig,
                              extractradius=30,
                              x_offset=0,
                              part2lookfor='marker',
                              level_dist=1):
        """ extracts intensities of axial CT-slices (levelwise). In order to get consistent artefacts at the marker,
         transformations to original data (CTimaging_orig) are required as this corresponds to steeper angle"""

        # General settings and pre-allocation of space
        cfg = Configuration.load_config(ROOTDIR)['preprocess'][
            'registration']  # specific part of cfg, required later
        file_invMatrix = os.path.join(single_lead['filenameCTimaging'][0],
                                      'CT2template_1InvWarpMatrix.mat')
        filenameCT = '/'.join(
            re.split(r".{}run[0-9].".format(cfg['prefix']),
                     os.path.join(*single_lead['filenameCTimaging'])))

        # Convert estimated markers (cf. preprocLeadCT.py) to original imaging data w/ transformation matrix
        estimated_markers = dict([(k, r) for k, r in single_lead.items()
                                  if k.startswith('marker')])
        marker_origCT = dict(
        )  # next part inconsistent to orientation from ea_main_orient (cf. lines 108ff.)!!
        for marker, coordinates in estimated_markers.items():
            coords_temp = [int(round(c)) for c in coordinates]
            transformed = LeadProperties.transform_coordinates(
                coords_temp,
                from_imaging=CTimaging_trans,
                to_imaging=CTimaging_orig,
                file_invMatrix=file_invMatrix)
            marker_origCT[marker] = np.array(
                transformed['points'])  # use points to account for distances

        UnitVector_origCT = np.divide(
            (marker_origCT['markers_tail'] - marker_origCT['markers_head']),
            np.linalg.norm(marker_origCT['markers_tail'] -
                           marker_origCT['markers_head']))

        marker_origCTmm = np.round(
            marker_origCT['markers_head'] + [0, 0, x_offset] +
            np.multiply(lead_settings[single_lead['model']]['markerposition'],
                        UnitVector_origCT))
        marker_origCTvx = ants.transform_physical_point_to_index(
            CTimaging_orig, point=marker_origCTmm)

        # Extract intensities from axial slices which result from original imaging and markers in vx-coordinates
        if part2lookfor == 'marker':
            intensity, box, fitvolume = \
                Specific.get_axialplanes(marker_origCTvx, filenameCT, UnitVector_origCT, window_size=extractradius)
            coordinates_temp = marker_origCTvx
        else:  # extract from 'levels', i.e. directional contacts
            coordinates_temp = np.round(
                marker_origCT['markers_head'] + [0, 0, x_offset] + np.multiply(
                    UnitVector_origCT, level_dist *
                    lead_settings[single_lead['model']]['leadspacing']))
            coordinates_temp = ants.transform_physical_point_to_index(
                CTimaging_orig, point=coordinates_temp)
            intensity, box, fitvolume = Specific.get_axialplanes(
                coordinates_temp,
                filenameCT,
                UnitVector_origCT,
                window_size=extractradius)

        return intensity, box, fitvolume, coordinates_temp, UnitVector_origCT
示例#24
0
    def AxialSlices(single_lead,
                    CTimaging_trans,
                    CTimaging_orig,
                    extractradius=30,
                    offset=[0] * 3,
                    levels=('level1', 'level2')):
        """ extracts intensities of axial slices of the CT. In order to get a consistent artefact
        at the marker, a transformation to the original data is necessary as this corresponds to a steeper angle;
        NOTE THIS FUNCTION WAS REPLACED WITH THE MORE GENERIC axialSlices_levelwise FUNCTION BELOW!"""

        cfg = Configuration.load_config(ROOTDIR)['preprocess']['registration']

        intensity, box, fitvolume, rotContact_coords = [
            dict() for _ in range(4)
        ]  # pre-allocate for later
        estimated_markers = dict([(k, r) for k, r in single_lead.items()
                                  if k.startswith('marker')])
        file_invMatrix = os.path.join(single_lead['filenameCTimaging'][0],
                                      'CT2template_1InvWarpMatrix.mat')

        # Convert the estimated markers (cf. preprocLeadCT.py) to original imaging data w/ transformation matrix
        marker_origCT = dict(
        )  # next part inconsistent to orientation from ea_main_orient (cf. lines 108ff.)!!
        for marker, coordinates in estimated_markers.items():
            coords_temp = [int(round(c)) for c in coordinates]
            transformed = LeadProperties.transform_coordinates(
                coords_temp,
                from_imaging=CTimaging_trans,
                to_imaging=CTimaging_orig,
                file_invMatrix=file_invMatrix)
            marker_origCT[marker] = np.array(
                transformed['points'])  # use points to account for distances

        UnitVector_origCT = np.divide(
            (marker_origCT['markers_tail'] - marker_origCT['markers_head']),
            np.linalg.norm(marker_origCT['markers_tail'] -
                           marker_origCT['markers_head']))
        marker_origCTmm = np.round(
            marker_origCT['markers_head'] + [0, 0, offset[0]] +
            np.multiply(lead_settings[single_lead['model']]['markerposition'],
                        UnitVector_origCT))
        marker_origCTvx = ants.transform_physical_point_to_index(
            CTimaging_orig, point=marker_origCTmm)

        filenameCT = '/'.join(
            re.split(r".{}run[0-9].".format(cfg['prefix']),
                     os.path.join(*single_lead['filenameCTimaging'])))

        # Extract the intensities from axial slices which result from original imaging and markers in vx-coordinates
        intensity['marker'], box['marker'], fitvolume[
            'marker'] = Specific.get_axialplanes(marker_origCTvx,
                                                 filenameCT,
                                                 UnitVector_origCT,
                                                 window_size=extractradius)
        marker_coordinates = marker_origCTvx

        # Loop through directional levels to obtain necessary coordinates and rotation
        for idx, l in enumerate(levels, start=1):
            rotContact_coords[l] = np.round(
                marker_origCT['markers_head'] + [0, 0, offset[idx]] +
                np.multiply(
                    UnitVector_origCT, idx *
                    lead_settings[single_lead['model']]['leadspacing']))
            rotContact_coords[l] = ants.transform_physical_point_to_index(
                CTimaging_orig, point=rotContact_coords[l])
            intensity[l], box[l], fitvolume[l] = Specific.get_axialplanes(
                rotContact_coords[l],
                filenameCT,
                UnitVector_origCT,
                window_size=extractradius)

        return intensity, box, fitvolume, marker_coordinates, rotContact_coords, UnitVector_origCT
示例#25
0
 def __init__(self, _debug=False):
     self.cfg = Configuration.load_config(ROOTDIR)
     self.debug = _debug
示例#26
0
 def comboChangedDetectionMethod(self):
     self.cfg["lead_detection"]["PaCER"][
         "detection_method"] = self.lineDetectionMethod.currentText()
     Configuration.save_config(ROOTDIR, self.cfg)
示例#27
0
    def __init__(self, parent=None):
        super(QWidget, self).__init__(parent)

        # Load configuration files and general settings
        self.cfg = Configuration.load_config(ROOTDIR)
        if os.path.isdir(self.cfg['folders']['dicom']):
            self.dicomdir = self.cfg['folders']['dicom']
        else:
            self.dicomdir = FileOperations.set_wdir_in_config(self.cfg, foldername='dicom', init=True)

        self.cfg['folders']['dicom'] = self.dicomdir
        self.cfg['folders']['rootdir'] = ROOTDIR
        Configuration.save_config(ROOTDIR, self.cfg)

        # Create general layout
        self.tot_layout = QVBoxLayout(self)
        self.mid_layout = QHBoxLayout(self)

        # ============================    Create upper of  GUI, i.e. working directory   ============================
        self.folderboxDcm2nii = QGroupBox("Directory (DICOM-files)")
        self.HBoxUpperDcm2nii = QVBoxLayout(self.folderboxDcm2nii)
        self.label_dicomdir = QLabel('dicom DIR: {}'.format(self.dicomdir))
        self.HBoxUpperDcm2nii.addWidget(self.label_dicomdir)

        self.btn_dicomdir = QPushButton('Change working \ndirectory')
        self.btn_dicomdir.setFixedSize(150, 40)
        self.btn_dicomdir.clicked.connect(self.change_dicomdir)
        self.btn_savedir = QPushButton('Save directory \nto config file')
        self.btn_savedir.setFixedSize(150, 40)
        self.btn_savedir.setToolTip(Output.split_lines(setToolTips.saveDirButton()))
        self.btn_savedir.clicked.connect(self.save_cfg)

        hlay_upper = QHBoxLayout()
        hlay_upper.addWidget(self.btn_dicomdir)
        hlay_upper.addWidget(self.btn_savedir)
        hlay_upper.addStretch(1)
        self.HBoxUpperDcm2nii.addLayout(hlay_upper)

        # ====================    Create Content for Lists, i.e. input/output      ====================
        self.listboxInputDcm2nii = QGroupBox('Available subjects in working directory')
        self.listboxInput = QVBoxLayout(self.listboxInputDcm2nii)
        self.mInput = QListWidget()
        self.listboxInput.addWidget(self.mInput)

        self.mButtonToAvailable = QPushButton("<<")
        self.mBtnMoveToAvailable = QPushButton(">")
        self.mBtnMoveToSelected = QPushButton("<")
        self.mButtonToSelected = QPushButton(">>")
        self.mBtnUp = QPushButton("Up")
        self.mBtnDown = QPushButton("Down")

        self.listboxOutputDcm2nii = QGroupBox('Subjects to process')
        self.listboxOutput = QVBoxLayout(self.listboxOutputDcm2nii)
        self.mOutput = QListWidget()
        self.listboxOutput.addWidget(self.mOutput)

        # First column on the left side
        vlay = QVBoxLayout()
        vlay.addStretch()
        vlay.addWidget(self.mBtnMoveToAvailable)
        vlay.addWidget(self.mBtnMoveToSelected)
        vlay.addStretch()
        vlay.addWidget(self.mButtonToAvailable)
        vlay.addWidget(self.mButtonToSelected)
        vlay.addStretch()

        # Second column on the right side
        vlay2 = QVBoxLayout()
        vlay2.addStretch()
        vlay2.addWidget(self.mBtnUp)
        vlay2.addWidget(self.mBtnDown)
        vlay2.addStretch()

        # ====================    Lower part of GUI, i.e. Preferences/Start estimation      ====================
        self.btn_preferences = QPushButton("Preferences")
        self.btn_preferences.clicked.connect(self.settings_show)
        self.btn_run_dcm2niix = QPushButton("Run dcm2niix")
        self.btn_run_dcm2niix.setToolTip(setToolTips.run_dcm2niix())
        self.btn_run_dcm2niix.clicked.connect(self.start_converting)

        hlay_bottom = QHBoxLayout()
        hlay_bottom.addStretch(1)
        hlay_bottom.addWidget(self.btn_preferences)
        hlay_bottom.addWidget(self.btn_run_dcm2niix)
        hlay_bottom.addStretch()

        # ====================    Set all contents to general Layout     =======================
        self.mid_layout.addWidget(self.listboxInputDcm2nii)
        self.mid_layout.addLayout(vlay)
        self.mid_layout.addWidget(self.listboxOutputDcm2nii)
        self.mid_layout.addLayout(vlay2)

        self.tot_layout.addWidget(self.folderboxDcm2nii)
        self.tot_layout.addLayout(self.mid_layout)
        self.tot_layout.addLayout(hlay_bottom)

        try:
            self.mInput.clear()
            items = FileOperations.list_folders(inputdir=self.cfg['folders']['dicom'], prefix='', files2lookfor='')
            items = self.check_for_complete_input(list(items))
            self.add_available_subj(items)
        except FileExistsError:
            print('{} without any valid files/folders, continuing ...'.format(self.dicomdir))

        self.update_buttons_status()
        self.connections()
示例#28
0
import cc3d

import ants
import numpy as np
import scipy
import scipy.io as spio
from matplotlib import pyplot as plt
from scipy import ndimage
from skimage.measure import regionprops
from sklearn.decomposition import PCA

from dependencies import ROOTDIR
from utils.HelperFunctions import Output, Configuration, FileOperations, Imaging, MatlabEquivalent, LeadProperties

from utils.estimateLeadRotation import function_wrapper
cfg = Configuration.load_config(ROOTDIR)


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]]
示例#29
0
    def __init__(self, parent=None):
        super(GuiTabDetectLeads, self).__init__(parent)
        self.selected_subj_ANT = ''

        # General settings/variables/helper files needed at some point
        self.cfg = Configuration.load_config(ROOTDIR)
        if os.path.isdir(self.cfg['folders']['nifti']):
            self.niftidir = self.cfg['folders']['nifti']
        else:
            self.niftidir = FileOperations.set_wdir_in_config(
                self.cfg, foldername='nifti', init=True)

        self.cfg['folders']['nifti'] = self.niftidir
        self.cfg['folders']['rootdir'] = ROOTDIR
        Configuration.save_config(ROOTDIR, self.cfg)

        self.lay = QHBoxLayout(self)
        self.tab = QWidget()

        # Customize tab
        # ==============================    Tab 3 - Lead detection routines   ==============================
        self.tab.layout = QHBoxLayout()
        self.tab.setLayout(self.tab.layout)

        # ------------------------- Upper left part (Folder)  ------------------------- #
        self.FolderboxTab = QGroupBox("Directory")
        self.HBoxUpperLeftTab = QVBoxLayout(self.FolderboxTab)
        self.lblWdirTab = QLabel('wDIR: {}'.format(self.niftidir))
        self.HBoxUpperLeftTab.addWidget(self.lblWdirTab)

        self.btnChangeWdir = QPushButton('Change working directory')
        self.btnChangeWdir.clicked.connect(self.change_wdir)
        self.btnReloadFilesTab = QPushButton('Reload files')
        self.btnReloadFilesTab.clicked.connect(self.run_reload_files)

        self.HBoxUpperLeftTab.addWidget(self.btnChangeWdir)
        self.HBoxUpperLeftTab.addWidget(self.btnReloadFilesTab)

        # ------------------------- Middle left part (Settings)  ------------------------- #
        self.SettingsTabLeadDetect = QGroupBox("Preferences")
        self.HBoxMiddleLeftTabExt = QVBoxLayout(self.SettingsTabLeadDetect)

        self.btn_LeadDetectSettings = QPushButton('Settings \nLead detection')
        self.btn_LeadDetectSettings.clicked.connect(
            self.run_PreferencesLeadDetection)
        self.btn_LeadDetectSettings.setToolTip(setToolTips.ANTsSettings())

        self.HBoxMiddleLeftTabExt.addWidget(self.btn_LeadDetectSettings)

        # ------------------------- Middle left part (Processing)  ------------------------- #
        self.ActionsTabANTs = QGroupBox("Lead detection routines")
        self.HBoxMiddleLeftTab = QVBoxLayout(self.ActionsTabANTs)
        self.btn_LeadDetectPacer = QPushButton('PaCER algorithm')
        self.btn_LeadDetectPacer.clicked.connect(self.run_LeadDetectionPaCER)

        self.btn_RefineDetectedLeads = QPushButton('Refine detected leads')
        self.btn_RefineDetectedLeads.clicked.connect(self.run_ManualCorrection)

        self.HBoxMiddleLeftTab.addWidget(self.btn_LeadDetectPacer)
        self.HBoxMiddleLeftTab.addWidget(self.btn_RefineDetectedLeads)

        # ------------------------- Lower left part (Processing)  ------------------------- #
        self.QualityTabLeadDetect = QGroupBox(
            "Quality checks for Lead detection")
        self.HBoxLowerLeftTab = QVBoxLayout(self.QualityTabLeadDetect)
        self.btn_QC_LeadDetect = QPushButton(
            'Check lead detection \nin viewer')
        self.btn_QC_LeadDetect.setToolTip(setToolTips.compareNIFTIfiles())
        self.btn_QC_LeadDetect.clicked.connect(self.VisualiseLeadDetection)
        self.HBoxLowerLeftTab.addWidget(self.btn_QC_LeadDetect)

        # -------------------- Right part (Subject list)  ----------------------- #
        self.listbox = QGroupBox('Available subjects')
        self.HBoxUpperRightTab = QVBoxLayout(self.listbox)
        self.availableNiftiTab = QListWidget()
        self.availableNiftiTab.setSelectionMode(
            QAbstractItemView.ExtendedSelection)
        itemsTab = FileOperations.list_folders(
            self.niftidir, prefix=self.cfg['folders']['prefix'])
        self.add_available_items(self.availableNiftiTab, itemsTab, msg='no')
        self.availableNiftiTab.itemSelectionChanged.connect(
            self.change_list_item)

        self.HBoxUpperRightTab.addWidget(self.availableNiftiTab)

        # Combine all Boxes for Tab 2 Layout
        self.LeftboxTabANTs = QGroupBox()
        self.HBoxTabLeadDetectLeft = QVBoxLayout(self.LeftboxTabANTs)
        self.HBoxTabLeadDetectLeft.addWidget(self.FolderboxTab)
        self.HBoxTabLeadDetectLeft.addStretch(1)
        self.HBoxTabLeadDetectLeft.addWidget(self.SettingsTabLeadDetect)
        self.HBoxTabLeadDetectLeft.addWidget(self.ActionsTabANTs)
        self.HBoxTabLeadDetectLeft.addWidget(self.QualityTabLeadDetect)

        self.tab.layout.addWidget(self.LeftboxTabANTs)
        self.tab.layout.addWidget(self.listbox)

        self.lay.addWidget(self.tab)
示例#30
0
    def __init__(self, parent=None):
        super(GuiTabTemplate, self).__init__(parent)
        self.selected_subj_Gen = ''
        self.wdirTemplate = os.path.join(ROOTDIR, 'ext', 'templates')

        # General settings/variables/helper files needed needed at some point
        self.cfg = Configuration.load_config(ROOTDIR)
        if os.path.isdir(self.cfg['folders']['nifti']):
            self.niftidir = self.cfg['folders']['nifti']
        else:
            self.niftidir = FileOperations.set_wdir_in_config(self.cfg, foldername='nifti', init=True)
        self.cfg['folders']['rootdir'] = ROOTDIR
        Configuration.save_config(ROOTDIR, self.cfg)

        self.lay = QHBoxLayout(self)
        self.tab = QWidget()

        # Customize tab
        # ==============================    Tab 1 - General   ==============================
        self.tab.layout = QHBoxLayout()
        self.tab.setLayout(self.tab.layout)
        # ------------------------- Upper left part (Folder)  ------------------------- #
        self.FolderboxTab = QGroupBox("Directory (Templates)")
        self.HBoxUpperLeftTab = QVBoxLayout(self.FolderboxTab)

        self.dirTemplates = QLabel('wDIR: {}'.format(self.wdirTemplate))
        self.HBoxUpperLeftTab.addWidget(self.dirTemplates)

        self.btnChangeWdir = QPushButton('Change working directory')
        self.btnChangeWdir.setDisabled(True)

        self.btnReloadFilesTab = QPushButton('Reload files')
        self.btnReloadFilesTab.clicked.connect(self.run_reload_files)

        self.HBoxUpperLeftTab.addWidget(self.btnChangeWdir)
        self.HBoxUpperLeftTab.addWidget(self.btnReloadFilesTab)

        # ------------------------- Lower left part (Processing)  ------------------------- #
        self.ActionsTab = QGroupBox("Functions")
        self.HBoxLowerLeftTab = QVBoxLayout(self.ActionsTab)
        self.btn_new_default = QPushButton('Set new \ndefault')
        # self.btn_subj_details.setToolTip(setToolTips.subjectDetails()) TODO: new ToolTip needed
        self.btn_new_default.clicked.connect(self.redefineDefault)

        self.btn_viewer = QPushButton('View selected \nTemplate in viewer')
        # self.btn_viewer.setToolTip(setToolTips.displayFolderContent()) TODO: new ToolTip needed
        self.btn_viewer.clicked.connect(self.view_template)

        self.create_SST = QPushButton('Create Study-specific\ntemplate')
        # self.btn_renaming.setToolTip(setToolTips.renameFolders()) TODO: new ToolTip needed
        self.create_SST.clicked.connect(self.create_StudySpecificTemplate)

        self.HBoxLowerLeftTab.addWidget(self.btn_viewer)
        self.HBoxLowerLeftTab.addWidget(self.btn_new_default)
        self.HBoxLowerLeftTab.addWidget(self.create_SST)

        # -------------------- Right part (Subject list)  ----------------------- #
        self.listbox = QGroupBox('Available subjects')
        self.HBoxUpperRightTab = QVBoxLayout(self.listbox)
        self.availableTemplates = QListWidget()
        self.availableTemplates.setSelectionMode(QAbstractItemView.ExtendedSelection)
        self.availableTemplates.itemSelectionChanged.connect(self.change_list_item)
        itemsTab = set(FileOperations.list_files_in_folder(self.wdirTemplate))
        self.add_available_templates(self.availableTemplates, itemsTab)
        self.HBoxUpperRightTab.addWidget(self.availableTemplates)

        # Combine all Boxes for General Tab Layout
        self.LeftboxTab = QGroupBox()
        self.HBoxTabLeft = QVBoxLayout(self.LeftboxTab)
        self.HBoxTabLeft.addWidget(self.FolderboxTab)
        self.HBoxTabLeft.addStretch()
        self.HBoxTabLeft.addWidget(self.ActionsTab)

        self.tab.layout.addWidget(self.LeftboxTab)
        self.tab.layout.addWidget(self.listbox)

        self.lay.addWidget(self.tab)