Exemple #1
0
    def __init__(self):
        super(FeatureExtractionForm, self).__init__()
        self.ui = Ui_FeatureExtraction()
        self._root_folder = ''
        self._patterns = 0
        self._image_patten_list = []
        self._roi_patten_list = []
        self.radiomics_params = RadiomicsParamsConfig('RadiomicsParams.yaml')

        self.ui.setupUi(self)
        self.ui.tableFilePattern.setColumnCount(4)
        self.ui.tableFilePattern.setHorizontalHeaderLabels(
            ["Type", "Name", "Include", "Exclude"])
        self.ui.tableFilePattern.setEditTriggers(
            QAbstractItemView.NoEditTriggers)
        self.ui.tableFilePattern.setSelectionBehavior(
            QAbstractItemView.SelectRows)

        self.ui.buttonBrowseSourceFolder.clicked.connect(
            self.BrowseSourceFolder)
        self.ui.buttonAddOne.clicked.connect(self.AddOnePattern)
        self.ui.buttonRemoveOne.clicked.connect(self.RemoveOnePattern)
        self.ui.buttonRun.clicked.connect(self.Run)
        self.ui.UseExistConfigcheckBox.clicked.connect(self.UseExitingConfig)
        self.ui.ConfigPushButton.clicked.connect(
            self.BrowseRadiomicsFeatureCofigFile)
        self.ui.CofnigLineEdit.setText(
            r'D:\research\exampleMR_NoResampling.yaml')
        self.ui.CofnigLineEdit.setEnabled(False)
        self.ui.ConfigPushButton.setEnabled(False)
Exemple #2
0
    def __init__(self):
        super(FeatureExtractionForm, self).__init__()
        self.ui = Ui_FeatureExtraction()
        self._root_folder = ''
        self._patterns = 0
        self._image_patten_list = []
        self._roi_patten_list = []
        self.radiomics_params = RadiomicsParamsConfig('RadiomicsParams.yaml')

        self.ui.setupUi(self)
        self.ui.tableFilePattern.setColumnCount(4)
        self.ui.tableFilePattern.setHorizontalHeaderLabels(["Type", "Name", "Include", "Exclude"])
        self.ui.tableFilePattern.setEditTriggers(QAbstractItemView.NoEditTriggers)
        self.ui.tableFilePattern.setSelectionBehavior(QAbstractItemView.SelectRows)

        self.ui.buttonBrowseSourceFolder.clicked.connect(self.BrowseSourceFolder)
        self.ui.buttonAddOne.clicked.connect(self.AddOnePattern)
        self.ui.buttonRemoveOne.clicked.connect(self.RemoveOnePattern)
        self.ui.buttonRun.clicked.connect(self.Run)
Exemple #3
0
class FeatureExtractionForm(QWidget):
    close_signal = QtCore.pyqtSignal(bool)

    def __init__(self):
        super(FeatureExtractionForm, self).__init__()
        self.ui = Ui_FeatureExtraction()
        self._root_folder = ''
        self._patterns = 0
        self._image_patten_list = []
        self._roi_patten_list = []
        self.radiomics_params = RadiomicsParamsConfig('RadiomicsParams.yaml')

        self.ui.setupUi(self)
        self.ui.tableFilePattern.setColumnCount(4)
        self.ui.tableFilePattern.setHorizontalHeaderLabels(["Type", "Name", "Include", "Exclude"])
        self.ui.tableFilePattern.setEditTriggers(QAbstractItemView.NoEditTriggers)
        self.ui.tableFilePattern.setSelectionBehavior(QAbstractItemView.SelectRows)

        self.ui.buttonBrowseSourceFolder.clicked.connect(self.BrowseSourceFolder)
        self.ui.buttonAddOne.clicked.connect(self.AddOnePattern)
        self.ui.buttonRemoveOne.clicked.connect(self.RemoveOnePattern)
        self.ui.buttonRun.clicked.connect(self.Run)

    def closeEvent(self, event):
        self.close_signal.emit(True)
        event.accept()

    def BrowseSourceFolder(self):
        dlg = QFileDialog()
        dlg.setFileMode(QFileDialog.DirectoryOnly)
        dlg.setOption(QFileDialog.ShowDirsOnly)
        if dlg.exec_():
            self._root_folder = dlg.selectedFiles()[0]
            self.ui.lineEditSourceFolder.setText(self._root_folder)

    def _PatternNameExist(self, one_name):
        exist_name_list = [item['name'] for item in self._image_patten_list]
        if one_name in exist_name_list:
            return True
        else:
            return False

    def AddOnePattern(self):
        message = QMessageBox()
        if self.ui.lineEditkeyInclude.text() == '':
            message.about(self, 'Include can not be empty',
                                'Include patterns are used to identify the file')
            return
        if self.ui.lineEditkeyShowName.text() == '':
            message.about(self, 'ShowName can not be empty',
                          'ShowName patterns are used to add pre-name in the feature matrix')
            return

        one_pattern = {'name': self.ui.lineEditkeyShowName.text().split(','),
                       'include': self.ui.lineEditkeyInclude.text().split(','),
                       'exclude': self.ui.lineEditkeyExclude.text().split(',')}
        if self.ui.radioImagePattern.isChecked() and self._PatternNameExist(one_pattern['name']):
            message.about(self, '', 'Same image pattern exists')
            return
        elif self.ui.radioRoiPattern.isChecked() and self._roi_patten_list:
            message.about(self, '', 'There should only one ROI pattern')
            return

        self.ui.tableFilePattern.insertRow(self._patterns)
        if self.ui.radioImagePattern.isChecked():
            self.ui.tableFilePattern.setItem(self._patterns, 0, QTableWidgetItem('Image'))
            self._image_patten_list.append(one_pattern)
        elif self.ui.radioRoiPattern.isChecked():
            self.ui.tableFilePattern.setItem(self._patterns, 0, QTableWidgetItem('ROI'))
            self._roi_patten_list.append(one_pattern)
        self.ui.tableFilePattern.setItem(self._patterns, 1, QTableWidgetItem(','.join(one_pattern['name'])))
        self.ui.tableFilePattern.setItem(self._patterns, 2, QTableWidgetItem(','.join(one_pattern['include'])))
        self.ui.tableFilePattern.setItem(self._patterns, 3, QTableWidgetItem(','.join(one_pattern['exclude'])))

        self._patterns += 1

    def RemoveOnePattern(self):
        if not self.ui.tableFilePattern.selectedIndexes():
            return None
        index = self.ui.tableFilePattern.selectedIndexes()[0].row()

        image_type = self.ui.tableFilePattern.item(index, 0).text()
        if image_type == 'Image':
            one_pattern = {'name': self.ui.tableFilePattern.item(index, 1).text().split(','),
                           'include': self.ui.tableFilePattern.item(index, 2).text().split(','),
                           'exclude': self.ui.tableFilePattern.item(index, 3).text().split(',')}
            self._image_patten_list.remove(one_pattern)
        elif image_type == 'ROI':
            self._roi_patten_list = []

        self._patterns -= 1
        self.ui.tableFilePattern.removeRow(index)

    def _GetImageAndRoiMatcher(self):
        series_matchers = {}
        for one_pattern in self._image_patten_list:
            series_matchers[one_pattern['name'][0]] = SeriesStringMatcher(include_key=one_pattern['include'],
                                                                       exclude_key=one_pattern['exclude'])
        roi_matcher = SeriesStringMatcher(include_key=self._roi_patten_list[0]['include'],
                                          exclude_key=self._roi_patten_list[0]['exclude'])
        return series_matchers, roi_matcher

    def _CheckFiles(self):
        if len(self._roi_patten_list) == 0:
            self._missing_message += 'Must have 1 Roi Pattern. \n'
            return False
        if len(self._image_patten_list) == 0:
            self._missing_message += 'Must have at least 1 Image Pattern. \n'
            return False

        all_match = True
        series_matchers, roi_matcher = self._GetImageAndRoiMatcher()

        for case_name in os.listdir(self._root_folder):
            case_folder = os.path.join(self._root_folder, case_name)
            if not os.path.isdir(case_folder):
                continue
            series_list = os.listdir(case_folder)

            # Match series according to patterns
            for key, one_series_matcher in series_matchers.items():
                result = one_series_matcher.Match(series_list)
                if len(result) != 1:
                    self._missing_message += '{} does not match {}\n'.format(case_name, key)
                    all_match = False
            result = roi_matcher.Match(series_list)
            if len(result) != 1:
                self._missing_message += '{} does not match ROI\n'.format(case_name)
                all_match = False

        return all_match

    def _UpdateImageClassesFeature(self, update_data, image_types):
        image_types_ctrl = {self.ui.checkBoxOriginal, self.ui.checkBoxWavelet, self.ui.checkBoxSquare,
                            self.ui.checkBoxSquareRoot, self.ui.checkBoxLoG, self.ui.checkBoxLogarithm,
                            self.ui.checkBoxExponential, self.ui.checkBoxGradient, self.ui.checkBoxLocalBinaryPattern2D,
                            self.ui.checkBoxLocalBinaryPattern3D}
        if update_data:
            for ctrl in image_types_ctrl:
                if ctrl.isChecked():
                    image_types.append(ctrl.text())
        else:
            for ctrl in image_types_ctrl:
                ctrl.setChecked(ctrl.text() in image_types)

    def _UpdateFeatureClasses(self, update_data, feature_classes):
        feature_classes_ctrl = {self.ui.checkBoxFirstOrderStatistics, self.ui.checkBoxShapeBased2D,
                                self.ui.checkBoxGLCM, self.ui.checkBoxGLRLM, self.ui.checkBoxGLSZM,
                                self.ui.checkBoxGLDM, self.ui.checkBoxNGTDM}
        if update_data:
            for ctrl in feature_classes_ctrl:
                if ctrl.isChecked():
                    feature_classes.append(ctrl.text())
        else:
            for ctrl in feature_classes_ctrl:
                ctrl.setChecked(ctrl.text() in feature_classes)

    def Run(self):
        try:
            def UpdateRadiomicsConfig():
                image_types = list()
                self._UpdateImageClassesFeature(True, image_types)
                feature_classes = list()
                self._UpdateFeatureClasses(True, feature_classes)
                self.radiomics_params.SetImageClasses(image_types)
                self.radiomics_params.SetFeatureClasses(feature_classes)
                self.radiomics_params.SaveConfig()

            dlg = QFileDialog()
            file_name, _ = dlg.getSaveFileName(self, 'Save CSV feature files', 'features.csv',
                                               filter="CSV files (*.csv)")
            if not file_name:
                return None

            self.ui.plainTextOutput.setPlainText('Checking Files ...')
            QApplication.processEvents()

            self._missing_message = ''
            if not self._CheckFiles():
                self.ui.plainTextOutput.appendPlainText(self._missing_message)
                self.ui.plainTextOutput.appendPlainText("Please Check the Data")
                QApplication.processEvents()
                return

            self.ui.plainTextOutput.appendPlainText('Done')
            QApplication.processEvents()

            UpdateRadiomicsConfig()
            extractor = MyFeatureExtractor('RadiomicsParams.yaml')

            series_matchers, roi_matcher = self._GetImageAndRoiMatcher()
            name_list, matcher_list = [], []
            for name, matcher in series_matchers.items():
                name_list.append(name)
                matcher_list.append(matcher)

            total_cases = len([temp for temp in os.listdir(self._root_folder) if
                               os.path.isdir(os.path.join(self._root_folder, temp))])
            self.ui.plainTextOutput.appendPlainText("\n\nTotal {} cases are processed:\n".format(total_cases))

            for index, case_name in extractor.Execute(self._root_folder,
                                                      image_matcher_list=matcher_list,
                                                      roi_matcher=roi_matcher,
                                                      show_name_list=name_list,
                                                      store_path=file_name):
                self.ui.plainTextOutput.appendPlainText('{} Done ({}/{})\n'.format(case_name, index, total_cases))
                QApplication.processEvents()

        except Exception as e:
            print(e.__str__())