def __init__(self, parent, dataModel):
        super(QWidget, self).__init__(parent)
        self.dataModel = dataModel
        self.layout = QHBoxLayout(self)
        self.supported = []
        self.unsupported = []

        self.moduleOperationGroup = QGroupBox("Classification Operation")
        self.moduleOperationLayout = QVBoxLayout()
        self.moduleOperationGroup.setLayout(self.moduleOperationLayout)

        self.dataTypeCheck = PandasDatatypeCheck()

        self.selectLabelDropDown = QComboBox()
        self.selectLabelDropDown.currentIndexChanged.connect(
            self.label_selection_changed)

        self.buttonOperationLayout = QHBoxLayout()
        self.startOperationButton = QPushButton("Start")
        self.stopOperationButton = QPushButton("Stop")
        self.buttonOperationLayout.addWidget(self.startOperationButton)
        self.buttonOperationLayout.addWidget(self.stopOperationButton)

        self.startOperationButton.clicked.connect(self.start_operation)
        self.stopOperationButton.clicked.connect(self.stop_operation)

        self.moduleOperationLayout.addWidget(self.selectLabelDropDown)
        self.moduleOperationLayout.addLayout(self.buttonOperationLayout)

        self.startOperationButton.setEnabled(False)
        self.stopOperationButton.setEnabled(False)

        self.layout.addWidget(self.moduleOperationGroup)
        self.setLayout(self.layout)
    def __init__(self, parent, data_model, model_results, screen_height, screen_width):
        super(QWidget, self).__init__(parent)
        self.data = None
        self.dataModel = data_model

        self.dataTypeCheck = PandasDatatypeCheck()

        self.layout = QVBoxLayout()
        self.layout.setSpacing(0)

        self.actionLayout = QHBoxLayout()
        self.actionLayout.setSpacing(0)

        self.selectLabelDropDown = QComboBox()
        self.selectLabelDropDown.currentIndexChanged.connect(self.labelSelectionChanged)
        self.actionLayout.addWidget(self.selectLabelDropDown)

        self.graphLayout = QGridLayout(self)
        self.graphLayout.setSpacing(0)

        self.widthWidget = 4

        pg.setConfigOption('background', 'w')
        pg.setConfigOption('foreground', 'k')

        self.visualizationWidgets = []

        self.layout.addLayout(self.actionLayout)
        self.layout.addLayout(self.graphLayout)

        self.setLayout(self.layout)
    def __init__(self, parent, data_model, parent_history):
        super(QDialog, self).__init__(parent)
        self.dataModel = data_model
        self.data = None
        self.dataTypeCheck = PandasDatatypeCheck()
        self.isUndoConfirmed = False

        self.dataHistory = DataHistory()
        self.parentHistory = parent_history

        self.layout = QVBoxLayout()
        self.btnLayout = QHBoxLayout()

        self.addInstanceButton = QPushButton("Add Instance")
        self.undoButton = QPushButton("Undo")
        self.saveButton = QPushButton("Save")
        self.cancelButton = QPushButton("Cancel")

        self.addInstanceButton.clicked.connect(self._add_instance)
        self.undoButton.clicked.connect(self._undo_confirmation)
        self.saveButton.clicked.connect(self.on_ok)
        self.cancelButton.clicked.connect(self.on_cancel)

        self.btnLayout.addWidget(self.addInstanceButton)
        self.btnLayout.addWidget(self.undoButton)
        self.btnLayout.addWidget(self.saveButton)
        self.btnLayout.addWidget(self.cancelButton)

        self.undoButton.setEnabled(False)

        self.dataAttributeTable = PandasTableView({}, 0, 0)
        self.dataAttributeTable.setSelectionBehavior(QAbstractItemView.SelectItems)
        self.dataAttributeTable.setEditTriggers(QAbstractItemView.DoubleClicked)
        self.dataAttributeTable.setSelectionBehavior(QAbstractItemView.SelectRows)
        self.dataAttributeTable.setContextMenuPolicy(Qt.CustomContextMenu)

        self.dataAttributeTable.customContextMenuRequested.connect(self.showContextMenu)
        self.dataAttributeTable.cellChanged.connect(self._data_changed)

        self.layout.addWidget(self.dataAttributeTable)
        self.layout.addLayout(self.btnLayout)

        self.setMinimumSize(600, 400)
        self.setWindowTitle("Maleo Editor")
        self.setLayout(self.layout)
Example #4
0
    def __init__(self, parent, dataModel, classifierResults, screenHeight,
                 screenWidth):
        super(QWidget, self).__init__(parent)
        self.dataModel = dataModel
        self.module = None

        self.layout = QVBoxLayout(self)
        self.layout.setSpacing(0)

        self.classifierWidget = ClusteringWidget(self)
        self.dataTypeCheck = PandasDatatypeCheck()

        self.testLayout = QHBoxLayout()
        self.testLayout.setSpacing(0)

        self.leftTestLayout = QVBoxLayout()
        self.leftTestLayout.setSpacing(0)
        self.testOptionWidget = TestOptionWidget(self)
        self.moduleOperationWidget = ModuleOperationWidget(
            self, self.dataModel)
        self.resultListWidget = ResultListWidget(self)
        self.leftTestLayout.addWidget(self.testOptionWidget, stretch=40)
        self.leftTestLayout.addWidget(self.moduleOperationWidget, stretch=20)
        self.leftTestLayout.addWidget(self.resultListWidget, stretch=40)

        self.rightTestLayout = QVBoxLayout()
        self.rightTestLayout.setSpacing(0)
        self.classifierOutputWidget = ClusteringOutputWidget(self)
        self.rightTestLayout.addWidget(self.classifierOutputWidget)

        self.testLayout.addLayout(self.leftTestLayout, stretch=20)
        self.testLayout.addLayout(self.rightTestLayout, stretch=80)

        self.layout.addWidget(self.classifierWidget, stretch=10)
        self.layout.addLayout(self.testLayout, stretch=90)
        self.setLayout(self.layout)
class DatasetEditor(QDialog):
    def __init__(self, parent, data_model, parent_history):
        super(QDialog, self).__init__(parent)
        self.dataModel = data_model
        self.data = None
        self.dataTypeCheck = PandasDatatypeCheck()
        self.isUndoConfirmed = False

        self.dataHistory = DataHistory()
        self.parentHistory = parent_history

        self.layout = QVBoxLayout()
        self.btnLayout = QHBoxLayout()

        self.addInstanceButton = QPushButton("Add Instance")
        self.undoButton = QPushButton("Undo")
        self.saveButton = QPushButton("Save")
        self.cancelButton = QPushButton("Cancel")

        self.addInstanceButton.clicked.connect(self._add_instance)
        self.undoButton.clicked.connect(self._undo_confirmation)
        self.saveButton.clicked.connect(self.on_ok)
        self.cancelButton.clicked.connect(self.on_cancel)

        self.btnLayout.addWidget(self.addInstanceButton)
        self.btnLayout.addWidget(self.undoButton)
        self.btnLayout.addWidget(self.saveButton)
        self.btnLayout.addWidget(self.cancelButton)

        self.undoButton.setEnabled(False)

        self.dataAttributeTable = PandasTableView({}, 0, 0)
        self.dataAttributeTable.setSelectionBehavior(QAbstractItemView.SelectItems)
        self.dataAttributeTable.setEditTriggers(QAbstractItemView.DoubleClicked)
        self.dataAttributeTable.setSelectionBehavior(QAbstractItemView.SelectRows)
        self.dataAttributeTable.setContextMenuPolicy(Qt.CustomContextMenu)

        self.dataAttributeTable.customContextMenuRequested.connect(self.showContextMenu)
        self.dataAttributeTable.cellChanged.connect(self._data_changed)

        self.layout.addWidget(self.dataAttributeTable)
        self.layout.addLayout(self.btnLayout)

        self.setMinimumSize(600, 400)
        self.setWindowTitle("Maleo Editor")
        self.setLayout(self.layout)

    def showContextMenu(self, pos):
        menu = QMenu()
        clear_action = menu.addAction("Undo")
        add_instance = menu.addAction("Add Instance")
        delete_instance = menu.addAction("Delete Selected Instance")
        delete_all_instance = menu.addAction("Delete ALL Selected Instance")

        if self.dataHistory.is_past_empty():
            clear_action.setEnabled(False)
        else:
            clear_action.setEnabled(True)

        action = menu.exec_(self.mapToGlobal(pos))

        if action == clear_action:
            self._undo_confirmation()
        elif action == add_instance:
            self._add_instance()
        elif action == delete_instance:
            self._delete_instances(False)
        elif action == delete_all_instance:
            self._delete_instances(True)

    def _delete_instances(self, is_all):
        selected_rows = self.dataAttributeTable.selectionModel().selectedRows()
        num_deleted_row = 0
        for selected_row in selected_rows:
            row = selected_row.row()
            self.dataHistory.append_data({"row": row, "col": "all_deletion", "value": self.data.copy()})

            self.data.drop(index=row - num_deleted_row, axis=0, inplace=True)
            self.data.reset_index(inplace=True, drop=True)
            self.dataAttributeTable.deleteRow(row - num_deleted_row)

            num_deleted_row += 1
            if not is_all:
                break
        self.update_status()

    def _undo_confirmation(self):
        if self.isUndoConfirmed:
            self._undo_operation()
        else:
            dlg = QMessageBox()
            dlg.setIcon(QMessageBox.Question)
            dlg.setWindowTitle("Confirmation")
            dlg.setText("Are you sure you want to undo the last action ? This action cannot be undone.")
            dlg.setStandardButtons(QMessageBox.Yes | QMessageBox.No)
            dlg.setDefaultButton(QMessageBox.No)
            button_yes = dlg.button(QMessageBox.Yes)
            button_yes.setText("Yes")
            button_no = dlg.button(QMessageBox.No)
            button_no.setText("No")
            dlg.exec_()

            if dlg.clickedButton() == button_yes:
                self.isUndoConfirmed = True
                self._undo_operation()

    def load_data(self):
        self.data = self.dataModel.get_copy()
        try:
            self._show_table()
        except Exception as e:
            self.parent().parent().dialog_critical("Error exception !"+str(e))

    def update_status(self):
        if self.dataHistory.is_past_empty():
            self.undoButton.setEnabled(False)
        else:
            self.undoButton.setEnabled(True)

    def _undo_operation(self):
        data = self.dataHistory.pop_past()
        self.update_status()
        self._setTableItemData(data["row"], data["col"], data["value"])

    def _setTableItemData(self, row, col, value):
        if col == "all_insertion":
            self.data.drop(index=row, axis=0, inplace=True)
            self.data.reset_index(inplace=True, drop=True)

            self.dataAttributeTable.cellChanged.disconnect()
            self.dataAttributeTable.deleteRow(row)
            self.dataAttributeTable.cellChanged.connect(self._data_changed)
        elif col == "all_deletion":
            self.data = value
            self._show_table()
        else:
            self.data.iat[row, col] = value
            self.dataAttributeTable.cellChanged.disconnect()
            self.dataAttributeTable.setItemData(row, col, value)
            self.dataAttributeTable.cellChanged.connect(self._data_changed)

    def _show_table(self):
        if not self.dataModel.is_empty():
            self._draw_table(self.data, self.data.shape[0], self.data.shape[1])
        else:
            self._draw_table({}, 0, 0)

    def _draw_table(self, data, row, col):
        self.dataAttributeTable.updateParameter(col, row)
        self.dataAttributeTable.cellChanged.disconnect()
        self.dataAttributeTable.updateData(data)
        self.dataAttributeTable.cellChanged.connect(self._data_changed)
        self.dataAttributeTable.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch)

    def _append_table_row(self, new_row):
        row_count = self.dataAttributeTable.rowCount()
        self.dataHistory.append_data({"row": row_count, "col": "all_insertion", "value": None})
        self.update_status()

        self.data = self.data.append(new_row, ignore_index=True)
        self.dataAttributeTable.cellChanged.disconnect()
        self.dataAttributeTable.appendRow(new_row)
        self.dataAttributeTable.cellChanged.connect(self._data_changed)

    def _data_changed(self, row, col):
        changed_column = self.data.iloc[:, col]
        self.dataTypeCheck.setDataType(changed_column)
        self.dataType = self.dataTypeCheck.getDataType()

        item = self.dataAttributeTable.item(row, col).text()
        try:
            if self.dataType == self.dataTypeCheck.getType().Numeric:
                if nconvert.is_num(item):
                    self.dataHistory.append_data({"row": row, "col": col, "value": self.data.iat[row, col].copy()})
                    self.data.iat[row, col] = nconvert.str_to_num(item)
                    self.update_status()
                else:
                    self.parent().parent().dialog_critical("Cannot update numeric column by nominal value !")
                    self.dataAttributeTable.setItemData(row, col, self.data.iat[row, col])

            elif self.dataType == self.dataTypeCheck.getType().Nominal:
                if not nconvert.is_num(item):
                    self.dataHistory.append_data({"row": row, "col": col, "value": self.data.iat[row, col]})
                    self.data.iat[row, col] = item
                    self.update_status()
                else:
                    self.parent().parent().dialog_critical("Cannot update nominal column by numeric value !")
                    self.dataAttributeTable.setItemData(row, col, self.data.iat[row, col])

            else:
                self.parent().parent().dialog_critical("Column datatype is unknown !")
                print("This col item is unknown")
        except Exception as e:
            self.parent().parent().dialog_critical("Error exception !\n"+str(e))

    def _add_instance(self):
        new_row = {}
        for column in self.data.columns:
            changed_column = self.data.loc[:, column]
            self.dataTypeCheck.setDataType(changed_column)
            self.dataType = self.dataTypeCheck.getDataType()

            if self.dataType == self.dataTypeCheck.getType().Numeric:
                new_row[column] = 0
            elif self.dataType == self.dataTypeCheck.getType().Nominal:
                new_row[column] = ""
            else:
                new_row[column] = ""
        self._append_table_row(new_row)

    def on_ok(self):
        self.parentHistory.append_data(self.dataModel.get_copy())
        self.dataModel.set_data(self.data)
        self.parent().parent().data_loaded()
        self.close()

    def on_cancel(self):
        self.close()
class ModuleOperationWidget(QWidget):
    def __init__(self, parent, dataModel):
        super(QWidget, self).__init__(parent)
        self.dataModel = dataModel
        self.layout = QHBoxLayout(self)
        self.supported = []
        self.unsupported = []

        self.moduleOperationGroup = QGroupBox("Classification Operation")
        self.moduleOperationLayout = QVBoxLayout()
        self.moduleOperationGroup.setLayout(self.moduleOperationLayout)

        self.dataTypeCheck = PandasDatatypeCheck()

        self.selectLabelDropDown = QComboBox()
        self.selectLabelDropDown.currentIndexChanged.connect(
            self.label_selection_changed)

        self.buttonOperationLayout = QHBoxLayout()
        self.startOperationButton = QPushButton("Start")
        self.stopOperationButton = QPushButton("Stop")
        self.buttonOperationLayout.addWidget(self.startOperationButton)
        self.buttonOperationLayout.addWidget(self.stopOperationButton)

        self.startOperationButton.clicked.connect(self.start_operation)
        self.stopOperationButton.clicked.connect(self.stop_operation)

        self.moduleOperationLayout.addWidget(self.selectLabelDropDown)
        self.moduleOperationLayout.addLayout(self.buttonOperationLayout)

        self.startOperationButton.setEnabled(False)
        self.stopOperationButton.setEnabled(False)

        self.layout.addWidget(self.moduleOperationGroup)
        self.setLayout(self.layout)

    def start_operation(self):
        self.selectLabelDropDown.setEnabled(False)
        self.startOperationButton.setEnabled(False)
        self.stopOperationButton.setEnabled(True)
        self.parent().start_operation()

    def stop_operation(self):
        self.selectLabelDropDown.setEnabled(True)
        self.startOperationButton.setEnabled(True)
        self.stopOperationButton.setEnabled(False)
        self.parent().stop_operation()

    def update_supported_operation_type(self, supported, unsupported):
        self.supported = supported
        self.unsupported = unsupported
        if self.selectLabelDropDown.currentIndex() < len(
                self.headerIndex) and self.selectLabelDropDown.currentIndex(
                ) >= 0:
            self.label_selection_changed(
                self.selectLabelDropDown.currentIndex())

    def label_selection_changed(self, i):
        self.stopOperationButton.setEnabled(False)
        self.startOperationButton.setEnabled(False)
        if i >= 0 and i < len(self.headerIndex):
            if str(self.headerIndex[i]["data_type"]) in self.supported:
                self.startOperationButton.setEnabled(True)
                self.parent().set_label(i)

    def set_label_drop_down(self):
        self.data = self.dataModel.get_data()
        self.selectLabelDropDown.clear()
        self.headers = list(self.data.columns)
        self.headerIndex = {}
        for index in range(len(self.headers)):
            label_data = self.data.iloc[:, index]
            self.dataTypeCheck.setDataType(label_data)
            dataType = self.dataTypeCheck.getDataType()

            self.headerIndex[index] = {
                "name": self.headers[index],
                "data_type": dataType
            }

            self.selectLabelDropDown.addItem("(" + str(dataType) + ") " +
                                             self.headers[index])
class VisualizationTab(QWidget):
    def __init__(self, parent, data_model, model_results, screen_height, screen_width):
        super(QWidget, self).__init__(parent)
        self.data = None
        self.dataModel = data_model

        self.dataTypeCheck = PandasDatatypeCheck()

        self.layout = QVBoxLayout()
        self.layout.setSpacing(0)

        self.actionLayout = QHBoxLayout()
        self.actionLayout.setSpacing(0)

        self.selectLabelDropDown = QComboBox()
        self.selectLabelDropDown.currentIndexChanged.connect(self.labelSelectionChanged)
        self.actionLayout.addWidget(self.selectLabelDropDown)

        self.graphLayout = QGridLayout(self)
        self.graphLayout.setSpacing(0)

        self.widthWidget = 4

        pg.setConfigOption('background', 'w')
        pg.setConfigOption('foreground', 'k')

        self.visualizationWidgets = []

        self.layout.addLayout(self.actionLayout)
        self.layout.addLayout(self.graphLayout)

        self.setLayout(self.layout)

    def set_label_drop_down(self):
        self.selectLabelDropDown.clear()
        self.headers = list(self.data.columns)
        for index in range(len(self.headers)):
            label_data = self.data.iloc[:, index]
            self.dataTypeCheck.setDataType(label_data)
            dataType = self.dataTypeCheck.getDataType()

            self.selectLabelDropDown.addItem("("+str(dataType)+") "+self.headers[index])

    def labelSelectionChanged(self, i):
        self.labels = self.data.iloc[:, i]

    def load_data(self):
        self.data = self.dataModel.get_data()
        if not self.dataModel.is_empty():
            try:
                self.set_label_drop_down()
                self.plot()
            except Exception as e:
                self.dialog_critical("Error exception "+str(e))
        else:
            self.dialog_critical("Data is empty !")

    def plot(self):
        for widget in self.visualizationWidgets:
            self.graphLayout.removeWidget(widget)
            widget.deleteLater()
            widget = None
        self.visualizationWidgets = []

        row = 0
        col = 0
        for column in self.data:
            plot = pg.PlotWidget()

            value = self.data[column].value_counts()
            x = [i for i in value.keys()]
            y = [j for i, j in value.items()]
            if np.array(x).dtype.char == 'U':
                x = [i for i in range(len(x))]

            bar = pg.BarGraphItem(x=x, height=y, width=0.1, brush='b', pen=pg.mkPen('b', width=1))

            plot.addItem(bar)
            plot.setTitle(column)
            # plot.set_label('left', 'Value')
            # plot.set_label('bottom', 'Range')

            self.visualizationWidgets.append(plot)
            self.graphLayout.addWidget(plot, row, col)

            col += 1
            if col == 4:
                col = 0
                row += 1

    def dialog_critical(self, message):
        dlg = QMessageBox(self)
        dlg.setText(message)
        dlg.setIcon(QMessageBox.Critical)
        dlg.show()