Esempio n. 1
0
class ClusteringGui(QMainWindow):
    # ui
    layout: QVBoxLayout  # Main Layout in which everything else is contained
    browse_btn: QPushButton  # Load Dataset button
    k_selector: QSpinBox  # Selector for k value
    repetitions_selector: QSpinBox  # Select how many times K-Means is ran per dataset
    run_btn: QPushButton  # Run button
    step_btn: QPushButton  # Next button
    dimensions_label: QLabel  # Filled with vector dimensions found from dataset
    recommended_k_label: QLabel  # Filled with recommended K value as calculated using SSE / Elbow method
    plot_canvas: FigureCanvas  # Canvas containing matplotlib plot

    path: str  # Path of current loaded dataset
    kmeans: KMeans
    figure: plt.Figure
    elbow_chart: QWidget

    def __init__(self):
        self.kmeans = KMeans()
        super(ClusteringGui, self).__init__()
        uic.loadUi(main_interface_file, self)

        self.browse_btn = self.findChild(QPushButton, 'browse_button')
        self.browse_btn.clicked.connect(self.on_browse_click)
        self.k_selector = self.findChild(QSpinBox, 'k_val_selector')
        self.k_selector.valueChanged.connect(self.on_update_k)
        self.repetitions_selector = self.findChild(QSpinBox, 'k_repetitions_selector')
        self.repetitions_selector.valueChanged.connect(self.on_set_repetitions)
        self.run_btn = self.findChild(QPushButton, 'run_button')
        self.run_btn.clicked.connect(self.on_run_click)
        self.run_btn.setEnabled(False)
        self.step_btn = self.findChild(QPushButton, 'step_button')
        self.step_btn.clicked.connect(self.on_step_click)
        self.step_btn.setEnabled(False)
        self.elbow_btn = self.findChild(QPushButton, 'elbow_chart_button')
        self.elbow_btn.clicked.connect(self.on_show_elbow)
        self.elbow_btn.setEnabled(False)
        self.layout = self.findChild(QVBoxLayout, 'layout')
        self.dimensions_label = self.findChild(QLabel, 'dimensions_label')
        self.dimensions_label.setText("")

        self.show()

    @pyqtSlot()
    def on_browse_click(self):
        self.path, _ = QFileDialog.getOpenFileName(self, "Open Dataset", "", "CSV Files (*.csv)")
        try:
            self.kmeans.open_dataset(filepath=self.path)
            self.dimensions_label.setText("Dimensions: {}".format(self.kmeans.dimensions))
            self.add_matplotlib_canvas()
            self.setWindowTitle('K-Means Clustering: {}'.format(self.path))
            self.elbow_btn.setEnabled(True)
            self.run_btn.setEnabled(True)
            self.step_btn.setEnabled(True)
        except FileNotFoundError:
            print("Exception")
            error_dialog = QErrorMessage()
            error_dialog.showMessage("File Not Found, try again")
            error_dialog.exec()

    @pyqtSlot()
    def on_show_elbow(self):
        sse = []
        # Calculate SSE for values of K ranging from 1 to 10.
        for i in range(1,10):
            print("Calculating SSE for K =", i)
            self.kmeans.update_k(i)
            # Cluster and update centroids 3 times for each K value
            self.kmeans.cluster_points()
            self.kmeans.cluster_points()
            self.kmeans.cluster_points()
            sse.append(self.kmeans.calculate_sse())

        self.elbow_chart = ElbowChartGui()
        self.elbow_chart.plot(sse, self.path)

    # Handles K value being changed
    @pyqtSlot()
    def on_update_k(self):
        self.kmeans.update_k(self.k_selector.value())
        # If there's data being displayed, update it now
        if self.kmeans.data_displayed:
            self.update_matplotlib()

    @pyqtSlot()
    def on_run_click(self):
        self.kmeans.run()
        self.update_matplotlib()

    @pyqtSlot()
    def on_set_repetitions(self):
        self.kmeans.repetitions = self.repetitions_selector.value()

    # Handles 'Next' button being pressed
    @pyqtSlot()
    def on_step_click(self):
        self.kmeans.step()
        self.update_matplotlib()

    # Adds the matplotlib canvas to the UI
    def add_matplotlib_canvas(self):
        try:
            self.figure.clear()
        except AttributeError:
            self.figure = plt.figure()
            self.plot_canvas = FigureCanvas(self.figure)
            self.layout.addWidget(self.plot_canvas)

        ax = self.figure.add_subplot(1, 1, 1)

        x = [point[0] for point in self.kmeans.vectors]
        y = [point[1] for point in self.kmeans.vectors]
        ax.scatter(x, y, alpha=0.8)

        self.plot_canvas.draw()

    # Updates the matplotlib UI
    def update_matplotlib(self):
        self.figure.clear()

        ax = self.figure.add_subplot(1, 1, 1)

        for cluster in self.kmeans.clusters:
            x = [point[0] for point in cluster]
            y = [point[1] for point in cluster]
            ax.scatter(x, y, alpha=0.5)

        for centroid in self.kmeans.centroids:
            x, y = centroid[0], centroid[1]
            ax.scatter(x, y, c='k', alpha=0.8)

        self.plot_canvas.draw()