Beispiel #1
0
    def __init__(self):
        super().__init__()

        series = QLineSeries()

        for date, value in DATA:
            date_value = QDateTime(*date, 0, 0).toMSecsSinceEpoch()
            series.append(date_value, value)

        chart = QChart()
        chart.setTheme(QChart.ChartThemeDark)
        chart.setTitle("Line Chart with Date Example")
        chart.setAnimationOptions(QChart.SeriesAnimations)
        chart.addSeries(series)
        chart.legend().hide()

        axisX = QDateTimeAxis()
        axisX.setFormat("dd/MM/yyyy")
        axisX.setTitleText('Date')
        chart.addAxis(axisX, Qt.AlignBottom)
        series.attachAxis(axisX)

        axisY = QValueAxis()
        axisY.setTitleText('Value')
        chart.addAxis(axisY, Qt.AlignLeft)
        series.attachAxis(axisY)

        chart_view = QChartView()
        chart_view.setChart(chart)
        chart_view.setRenderHint(QPainter.Antialiasing)

        self.setCentralWidget(chart_view)
Beispiel #2
0
class ChartWidget:
    def __init__(self):
        self.model = QChart()
        self.view = QChartView()

        self.view.setChart(self.model)

        self.model.legend().setAlignment(Qt.AlignBottom)
        self.view.setRenderHint(QPainter.Antialiasing)

    def show(self):
        self.view.show()

    def exit(self):
        self.view.close()

    @property
    def title(self):
        return self.model.title()

    @title.setter
    def title(self, title):
        self.model.setTitle(title)

    def add_series(self, x_list, y_list, name):
        series = QLineSeries()
        series.setName(name)

        for x, y in zip(x_list, y_list):
            series.append(x, y)

        self.model.addSeries(series)
        self.model.createDefaultAxes()
    def __init__(self):
        super().__init__()

        series = QLineSeries()
        series.setPointsVisible(True)
        series.setPointLabelsVisible(True)
        series.setPointLabelsFormat("(@xPoint, @yPoint)")
        series.append(0, 6)
        series.append(2, 4)
        series.append(3, 8)
        series.append(7, 4)
        series.append(10, 5)

        chart = QChart()
        chart.setTitle("Line Chart Example")
        chart.setAnimationOptions(QChart.SeriesAnimations)
        chart.legend().hide()
        chart.addSeries(series)
        chart.createDefaultAxes()

        chart_view = QChartView()
        chart_view.setChart(chart)
        chart_view.setRenderHint(QPainter.Antialiasing)

        self.setCentralWidget(chart_view)
 def __init__(self, parent):
     super(ScoresWindow, self).__init__(parent)
     self.parent = parent
     mainLayout = QBoxLayout(QBoxLayout.TopToBottom)
     columnLayout = QBoxLayout(QBoxLayout.LeftToRight)
     column = [QBoxLayout(QBoxLayout.TopToBottom) for i in range(3)]
     for i in column: columnLayout.addLayout(i)
     self.cell = [QLabel() for i in range(9)]
     for i in range(9): column[i//3].addWidget(self.cell[i])
     chartView = QChartView()
     axisY = QValueAxis()
     axisY.setRange(-700,700)
     axisY.setLabelFormat("%d")
     self.chart = LineChart(((10,20,30,40,50,60,70,80),(0,-10,-20,-30,-40,50,-20,0)))
     self.chart.addAxis(axisY, Qt.AlignLeft)
     for i in self.chart.series:
         i.attachAxis(axisY)
     chartView.setChart(self.chart)
     self.level = QLabel()
     mainLayout.addLayout(columnLayout)
     mainLayout.addWidget(chartView)
     self.setLayout(mainLayout)
     self.setFixedSize(300,400)
     self.setModal(True)
     self.setStrings()
Beispiel #5
0
    def __init__(self, parent=None):
        super().__init__(parent)
        self.setWindowTitle("Demo12_1, QChart 基本绘图")
        self.resize(580, 420)
        chart = QChart()
        chart.setTitle("简单函数曲线")
        chartView = QChartView(self)
        chartView.setChart(chart)
        self.setCentralWidget(chartView)
        series0 = QLineSeries()
        series1 = QLineSeries()
        series0.setName("sin曲线")
        series1.setName("cos曲线")
        chart.addSeries(series0)
        chart.addSeries(series1)
        t = 0
        intv = 0.1
        pointCount = 100
        for i in range(pointCount):
            y1 = math.cos(t)
            series0.append(t, y1)
            y2 = 1.5 * math.sin(t + 20)
            series1.append(t, y2)
            t = t + intv
        axisX = QValueAxis()
        axisX.setRange(0, 10)
        axisX.setTitleText("time(secs)")
        axisY = QValueAxis()
        axisY.setRange(-2, 2)
        axisY.setTitleText("value")

        chart.setAxisX(axisX, series0)
        chart.setAxisY(axisY, series0)
        chart.setAxisX(axisX, series1)
        chart.setAxisY(axisY, series1)
Beispiel #6
0
    def __init__(self, chartViewParent: QtChart.QChartView, *preset):
        super().__init__()

        self.__chart = QtChart.QChart()
        self.__chart.legend().hide()
        self.__chart.setMinimumHeight(180)
        self.__chart.setMargins(QtCore.QMargins(0, 0, 0, 0))
        self.__series = QtChart.QPieSeries()
        self.__series.setHoleSize(0.58)
        self.__series.setPieSize(0.75)

        for i in range(8):
            ps = QtChart.QPieSlice(str(i), 1)
            ps.setExploded(True)
            ps.setExplodeDistanceFactor(RING_NORMAL)

            ps.clicked.connect(self.__slice_clicked)
            ps.hovered.connect(self.__slice_hovered)
            ps.doubleClicked.connect(self.__slice_dblclicked)

            self.__series.append(ps)

        self.__chart.addSeries(self.__series)

        chartViewParent.setRenderHint(QtGui.QPainter.Antialiasing, True)
        chartViewParent.setChart(self.__chart)

        self.__last_slice = self.__series.slices()[0]
Beispiel #7
0
    def __init__(
            self, api: CachedAPI, settings_filename: Optional[str] = None,
            *args: Any, **kwargs: Any) -> None:
        super().__init__(*args, **kwargs)
        self._api: CachedAPI = api
        # Set window's icon and title
        self.setWindowIcon(QIcon('img/icon.png'))
        self.setWindowTitle('Systemy kolejkowe')
        # Configure settings file and load saved application's settings:
        # window's size and position
        self._settings: IniSettings = IniSettings()
        self.resize(self._settings.value('window/size', QSize(750, 580), set_if_missing=True))
        self.move(self._settings.value('window/position', self.pos(), set_if_missing=True))
        # Create ComboBox object
        self._combo: ComboBox = ComboBox()
        # Create and setup chart and its view
        self._chart: QueueSystemChart = QueueSystemChart()
        chart_view = QChartView()
        chart_view.setChart(self._chart)
        chart_view.setRenderHint(QPainter.Antialiasing)
        # Create the table
        self._table: QueueSystemTable = QueueSystemTable()
        # Create the status bar for the window
        self._status: StatusConfigBar = StatusConfigBar()
        self._status.setSettings(self._settings)
        self.setStatusBar(self._status)
        # Create window's layout and place elements in it
        vbox_layout = QVBoxLayout()
        vbox_layout.addWidget(self._combo)
        vbox_layout.addWidget(chart_view)
        vbox_layout.addWidget(self._table)
        # Create central window's widget and apply layout to it
        main_widget = QWidget()
        main_widget.setLayout(vbox_layout)
        self.setCentralWidget(main_widget)
        # Create the timer
        self._timer: QTimer = QTimer()
        self._timer.setInterval(api.cooldown * 1000)
        # Create and setup required threads
        self._setup_threads()
        # Connect (cyclical) timer's timeout signal to a method starting cache
        # update
        self._timer.timeout.connect(self._threads['caching'].start)

        # Get list of available offices and display it in combo box
        office_list = sorted(api.get_office_list(), key=lambda x: x['name'])
        self._combo.setItems(
            [x['name'] for x in office_list], [x['key'] for x in office_list])
        # Insert placeholder value
        self._combo.insertItem(0, 'Wybierz urząd...', 'placeholder')
        self._combo.setCurrentIndex(0)
        # Connect combo box's index changing signal to appropriate callback
        # (responsible for resetting table names and reconnecting series with
        # them)
        self._combo.currentIndexChanged.connect(self._setup_widgets_content)
        if self._settings.value('check_box/restore_last_closed', value_type=bool):
            index = self._settings.value('combo_box/index', -1, value_type=int, set_if_missing=True)
            self._combo.setCurrentIndex(index + 1)
 def __init__(self, chart_data, *args, **kwargs):
     super(ShowChartPopup, self).__init__(*args, **kwargs)
     layout = QVBoxLayout(margin=0)
     chart = self._initial_chart(chart_data)
     chart_view = QChartView()
     chart_view.setChart(chart)
     chart_view.setRenderHint(QPainter.Antialiasing)  # 抗锯齿
     layout.addWidget(chart_view)
     self.resize(880, 380)
     self.setLayout(layout)
Beispiel #9
0
    def __init__(self, parent=None):
        super().__init__(parent)
        self.setWindowTitle("Demo12_1, QChart基本绘图")
        self.resize(580, 420)

        #创建chart和chartView
        chart = QChart()  #创建 Chart
        chart.setTitle("简单函数曲线")

        chartView = QChartView(self)  #创建 ChartView
        chartView.setChart(chart)  #Chart添加到ChartView
        self.setCentralWidget(chartView)

        #创建曲线序列
        series0 = QLineSeries()
        series1 = QLineSeries()
        series0.setName("Sin曲线")
        series1.setName("Cos曲线")
        chart.addSeries(series0)  #序列添加到图表
        chart.addSeries(series1)

        #序列添加数值
        t = 0
        intv = 0.1
        pointCount = 100
        for i in range(pointCount):
            y1 = math.cos(t)
            series0.append(t, y1)
            y2 = 1.5 * math.sin(t + 20)
            series1.append(t, y2)
            t = t + intv

##创建坐标轴
        axisX = QValueAxis()  #X 轴
        axisX.setRange(0, 10)  #设置坐标轴范围
        axisX.setTitleText("time(secs)")  #标题
        ##    axisX.setLabelFormat("%.1f")     #标签格式
        ##    axisX.setTickCount(11)           #主分隔个数
        ##    axisX.setMinorTickCount(4)
        ##    axisX.setGridLineVisible(false)

        axisY = QValueAxis()  #Y 轴
        axisY.setRange(-2, 2)
        axisY.setTitleText("value")
        ##    axisY.setTickCount(5)
        ##    axisY.setMinorTickCount(4)
        ##    axisY.setLabelFormat("%.2f")     #标签格式
        ##    axisY.setGridLineVisible(false)

        #为序列设置坐标轴
        chart.setAxisX(axisX, series0)  #为序列设置坐标轴
        chart.setAxisY(axisY, series0)

        chart.setAxisX(axisX, series1)  #为序列设置坐标轴
        chart.setAxisY(axisY, series1)
Beispiel #10
0
    def create_chart(self):
        # 创建折线视图窗口
        modelutil = ModelUtil()
        dataTable = modelutil.get_score(self.username)

        chart = QChartView(self)
        #获取显示器高宽
        screeRect = QApplication.desktop().screenGeometry()
        chart.setGeometry(QtCore.QRect(screeRect))
        chart.setRenderHint(QPainter.Antialiasing)  # 抗锯齿
        chart.raise_()

        # qfont=QFont()
        # qfont.setPointSize(34)
        # qfont.setPixelSize(45)

        chart._chart = QChart(title="考试成绩折线图")  # 创建折线视图
        # chart._chart.setFont(qfont)
        # chart.setStyleSheet(
        #                          "QChartView{border:2px}"
        #                          "QChartView{border-radius:10px}"
        #                          "QChartView{font-family:宋体}"
        #                          "QChartView{word-wrap:true}"
        #                          "QChartView{font-size:25px}"
        #                          "QChartView{padding:2px 2px}")
        # chart._chart.setFont(qfont)
        # chart._chart.setBackgroundVisible(visible=False)      # 背景色透明
        chart._chart.setBackgroundBrush(QBrush(QColor("#FFFFFF")))  # 改变图背景色

        #  图形项默认无法接收悬停事件,可以使用QGraphicsItem的setAcceptHoverEvents()函数使图形项可以接收悬停事件。
        chart._chart.setAcceptHoverEvents(True)
        # 4条折线的坐标值

        # 执行创建折线的函数
        self.create_series(dataTable, chart)

        chart._chart.createDefaultAxes()  # 创建默认的轴

        chart._chart.axisY().setTickCount(11)  # y1轴设置10个刻度
        chart._chart.axisY().setLabelFormat("%d")
        chart._chart.axisY().setRange(0, 100)  # 设置y1轴范围

        xnum = len(dataTable[0]) - 1
        chart._chart.axisX().setTickCount(xnum)  # X轴设置10个刻度
        # 执行定义X轴的函数
        # self.customAxisX(chart._chart)

        chart.setChart(chart._chart)
    def create_QChartView(self) -> QChartView:
        series = QLineSeries()
        series.append(0, 6)
        series.append(2, 4)
        series.append(3, 8)
        series.append(7, 4)
        series.append(10, 5)

        chart = QChart()
        chart.setTitle("Line Chart Example")
        chart.setAnimationOptions(QChart.SeriesAnimations)
        chart.legend().hide()
        chart.addSeries(series)
        chart.createDefaultAxes()

        chart_view = QChartView()
        chart_view.setChart(chart)
        chart_view.setRenderHint(QPainter.Antialiasing)

        return chart_view
Beispiel #12
0
    def __init__(self):
        super().__init__()

        series = QLineSeries()
        series.append(0, 6)
        series.append(2, 4)
        series.append(3, 8)
        series.append(7, 4)
        series.append(10, 5)

        chart = QChart()
        chart.setTitle("Dark Theme")
        chart.setTheme(QChart.ChartThemeDark)
        chart.setAnimationOptions(QChart.SeriesAnimations)
        chart.legend().hide()
        chart.addSeries(series)
        chart.createDefaultAxes()

        chart_view = QChartView()
        chart_view.setChart(chart)
        chart_view.setRenderHint(QPainter.Antialiasing)

        self.setCentralWidget(chart_view)
Beispiel #13
0
class Window(QMainWindow):
    def __init__(self):
        super().__init__()
        self._data_file_name = ""
        self._data = pd.DataFrame()
        self.initUI()

    def initUI(self):
        self.createMenu()
        centralWidget = QWidget(self)
        self.setCentralWidget(centralWidget)

        optionsLayout = QVBoxLayout()

        riskRateLabel = QLabel("Risk rate: ", centralWidget)
        self.riskRateLineEdit = QLineEdit(centralWidget)
        self.riskRateLineEdit.setText("0.0178")
        riskRateLayout = QHBoxLayout()
        riskRateLayout.addStretch(1)
        riskRateLayout.addWidget(riskRateLabel)
        riskRateLayout.addWidget(self.riskRateLineEdit)
        riskRateLayout.addStretch(1)

        portfolioNumLabel = QLabel("Portfolios: ", centralWidget)
        self.portfolioNumLineEdit = QLineEdit(centralWidget)
        self.portfolioNumLineEdit.setText("10000")
        portfolioNumLayout = QHBoxLayout()
        portfolioNumLayout.addStretch(1)
        portfolioNumLayout.addWidget(portfolioNumLabel)
        portfolioNumLayout.addWidget(self.portfolioNumLineEdit)
        portfolioNumLayout.addStretch(1)

        buttonLayout = QHBoxLayout()
        buttonLayout.addStretch(1)
        generateButton = QPushButton("Generate")
        generateButton.clicked.connect(self.onGenerateButtonClick)
        buttonLayout.addWidget(generateButton)
        buttonLayout.addStretch(1)

        randomMaxSharpeRatioLayout, self.randomMaxSharpeRatioLabel = self.createParameterLayout(
            "Max Sharpe Ratio (from random portfolio): ")
        randomMinVolatilityLayout, self.randomMinVolatilityLabel = self.createParameterLayout(
            "Min Volatility (from random portfolio): ")
        optimizedMaxSharpeRatioLayout, self.optimizedMaxSharpeRatioLabel = self.createParameterLayout(
            "Max Sharpe Ratio (optimized): ")
        optimizedMinVolatilityLayout, self.optimizedMinVolatilityLabel = self.createParameterLayout(
            "Min Volatility (optimized): ")

        self.sharpeChartView = QChartView(
            self.createChart([], [], "Max Sharpe Ratio Potfolio Allocation"))
        self.sharpeChartView.setRenderHint(QtGui.QPainter.Antialiasing)

        self.volatilityChartView = QChartView(
            self.createChart([], [], "Minimum Volatility Potfolio Allocation"))
        self.volatilityChartView.setRenderHint(QtGui.QPainter.Antialiasing)

        optionsLayout.addLayout(riskRateLayout)
        optionsLayout.addLayout(portfolioNumLayout)
        optionsLayout.addLayout(buttonLayout)
        optionsLayout.addLayout(randomMaxSharpeRatioLayout)
        optionsLayout.addLayout(optimizedMaxSharpeRatioLayout)
        optionsLayout.addWidget(self.sharpeChartView)
        optionsLayout.addLayout(randomMinVolatilityLayout)
        optionsLayout.addLayout(optimizedMinVolatilityLayout)
        optionsLayout.addWidget(self.volatilityChartView)

        tabs = QTabWidget()
        self.tableView = QTableView()
        self.tableView.horizontalHeader().setSectionResizeMode(
            QHeaderView.Stretch)

        self._stocksPlot = self.createPlot("Stocks prices", "Date",
                                           "Price in $")
        axis = DateAxisItem(orientation='bottom')
        axis.attachToPlotItem(self._stocksPlot.getPlotItem())

        self._dailyReturnsPlot = self.createPlot("Daily returns", "Date",
                                                 "Daily returns")
        axis = DateAxisItem(orientation='bottom')
        axis.attachToPlotItem(self._dailyReturnsPlot.getPlotItem())

        mptWidget = QWidget()
        mptLayout = QHBoxLayout()
        self._mptPlot = self.createPlot("Efficient Frontier",
                                        "Annualized Volatility",
                                        "Annualized Returns")
        mptLayout.addWidget(self._mptPlot, 50)
        mptLayout.addLayout(optionsLayout, 50)
        mptWidget.setLayout(mptLayout)

        tabs.addTab(self.tableView, "Data")
        tabs.addTab(self._stocksPlot, "Stocks")
        tabs.addTab(self._dailyReturnsPlot, "Daily Returns")
        tabs.addTab(mptWidget, "Portfolios")

        tabsLayout = QVBoxLayout()
        tabsLayout.addWidget(tabs)

        mainLayout = QHBoxLayout()
        mainLayout.addLayout(tabsLayout)

        centralWidget.setLayout(mainLayout)

        self.setGeometry(100, 100, 500, 500)
        self.setWindowTitle('Portfolio Optimizer')
        self.setWindowState(QtCore.Qt.WindowMaximized)

    def createMenu(self):
        openFileAct = QAction("Open file...", self)
        openFileAct.triggered.connect(self.onOpenFileMenuClick)

        exitAct = QAction("Exit", self)
        exitAct.triggered.connect(self.close)

        menubar = self.menuBar()
        fileMenu = menubar.addMenu("File")
        fileMenu.addAction(openFileAct)
        fileMenu.addAction(exitAct)

    def createChart(self, names, values, title):
        series = QPieSeries()
        for name, value in zip(names, values):
            series.append(name + " " + str(value) + "%", value)

        chart = QChart()
        chart.addSeries(series)
        chart.setAnimationOptions(QChart.SeriesAnimations)
        chart.setTitle(title)
        chart.legend().setVisible(True)

        return chart

    def createPlot(self, title, xlabel, ylabel):
        newPlot = pg.PlotWidget()
        newPlot.setBackground('w')
        newPlot.addLegend()
        newPlot.showGrid(x=True, y=True)
        newPlot.setTitle(title)
        newPlot.setLabel("bottom", xlabel)
        newPlot.setLabel("left", ylabel)
        return newPlot

    def createParameterLayout(self, text):
        parameterText = QLabel(text)
        parameterLabel = QLabel("")
        parameterLayout = QHBoxLayout()
        parameterLayout.addStretch(1)
        parameterLayout.addWidget(parameterText)
        parameterLayout.addWidget(parameterLabel)
        parameterLayout.addStretch(1)
        return parameterLayout, parameterLabel

    def onOpenFileMenuClick(self):
        file_dialog = QFileDialog(self)
        file_dialog.setNameFilter("Data files (*.csv)")
        if file_dialog.exec_() == QFileDialog.Accepted:
            self._data_file_name = file_dialog.selectedFiles()[0]
            self._data = portfolio.get_data(self._data_file_name)
            self.showStockData()
            self.plotStocksData()
            self.plotDailyReturn()

    def onGenerateButtonClick(self):
        risk_rate = float(self.riskRateLineEdit.text())
        num_portfolios = int(self.portfolioNumLineEdit.text())

        mean_returns = portfolio.calculate_mean_returns(self._data)
        cov_matrix = portfolio.calculate_cov_matrix(self._data, portfolio.DAYS)
        weights, returns, volatilities, sharps_ratios = portfolio.generate_random_portfolios(
            mean_returns, cov_matrix, risk_rate, num_portfolios)

        random_min_volatility_index = np.argmin(volatilities)
        random_min_volatility_x = volatilities[random_min_volatility_index]
        random_min_volatility_y = returns[random_min_volatility_index]
        random_min_volatility_point = (random_min_volatility_x,
                                       random_min_volatility_y)
        self.randomMinVolatilityLabel.setText(
            "return - " + str(round(random_min_volatility_y, 2)) +
            ", volatility - " + str(round(random_min_volatility_x, 2)))

        random_max_sharpe_ratio_index = np.argmax(sharps_ratios)
        random_max_sharpe_ratio_x = volatilities[random_max_sharpe_ratio_index]
        random_max_sharpe_ratio_y = returns[random_max_sharpe_ratio_index]
        random_max_sharpe_point = (random_max_sharpe_ratio_x,
                                   random_max_sharpe_ratio_y)
        self.randomMaxSharpeRatioLabel.setText(
            "return - " + str(round(random_max_sharpe_ratio_y, 2)) +
            ", volatility - " + str(round(random_max_sharpe_ratio_x, 2)))

        max_sharpe = portfolio.max_sharpe_ratio(mean_returns, cov_matrix,
                                                risk_rate)
        min_volatility = portfolio.min_volatility(mean_returns, cov_matrix)

        sharpe_vol = portfolio.calculate_volatility(max_sharpe.x, cov_matrix)
        sharpe_ret = portfolio.calculate_returns(max_sharpe.x, mean_returns)
        self.optimizedMaxSharpeRatioLabel.setText("return - " +
                                                  str(round(sharpe_ret, 2)) +
                                                  ", volatility - " +
                                                  str(round(sharpe_vol, 2)))

        volatility_vol = portfolio.calculate_volatility(
            min_volatility.x, cov_matrix)
        volatility_ret = portfolio.calculate_returns(min_volatility.x,
                                                     mean_returns)
        self.optimizedMinVolatilityLabel.setText(
            "return - " + str(round(volatility_ret, 2)) + ", volatility - " +
            str(round(volatility_vol, 2)))

        frontier_y = np.linspace(sharpe_ret, volatility_ret, 100)
        efficient_portfolios = portfolio.calculate_efficient_frontier(
            mean_returns, cov_matrix, frontier_y)
        frontier_x = [p['fun'] for p in efficient_portfolios]

        max_sharpe_ratio_allocation = pd.DataFrame(data=np.round(
            max_sharpe.x * 100, 2),
                                                   index=self._data.columns).T
        min_volatility_allocation = pd.DataFrame(data=np.round(
            min_volatility.x * 100, 2),
                                                 index=self._data.columns).T

        newSharpeChart = self.createChart(
            max_sharpe_ratio_allocation.columns.values,
            max_sharpe_ratio_allocation.to_numpy()[0].tolist(),
            "Max Sharpe Ratio Potfolio Allocation")
        self.sharpeChartView.setChart(newSharpeChart)

        newVolatilityChart = self.createChart(
            min_volatility_allocation.columns.values,
            min_volatility_allocation.to_numpy()[0].tolist(),
            "Minimum Volatility Potfolio Allocation")
        self.volatilityChartView.setChart(newVolatilityChart)

        self.plotBullet(volatilities, returns, random_min_volatility_point,
                        random_max_sharpe_point,
                        (volatility_vol, volatility_ret),
                        (sharpe_vol, sharpe_ret), (frontier_x, frontier_y))

    def showStockData(self):
        model = PandasModel(self._data)
        self.tableView.setModel(model)

    def plotStocksData(self):
        self._stocksPlot.clear()
        date_time_range = pd.to_datetime(self._data.index).astype(int) / 10**9
        for c in self._data.columns.values:
            self._stocksPlot.plot(date_time_range,
                                  self._data[c],
                                  name=c,
                                  pen=pg.mkPen(color=tuple(
                                      np.random.choice(range(256), size=3)),
                                               width=5))

    def plotDailyReturn(self):
        self._dailyReturnsPlot.clear()
        date_time_range = pd.to_datetime(self._data.index).astype(int) / 10**9
        changes = self._data.pct_change()
        for c in self._data.columns.values:
            self._dailyReturnsPlot.plot(date_time_range,
                                        changes[c].fillna(0),
                                        name=c,
                                        pen=pg.mkPen(color=tuple(
                                            np.random.choice(range(256),
                                                             size=3)),
                                                     width=5))

    def plotBullet(self, volatilities, returns, random_volatility_point,
                   random_sharpe_point, min_volatility_point,
                   max_sharpe_ratio_point, efficient_frontier):
        self._mptPlot.clear()
        self._mptPlot.plot(volatilities,
                           returns,
                           pen=None,
                           symbol='o',
                           name="Random Portfolios",
                           symbolPen=pg.mkPen(color=(0, 0, 255, 100), width=0),
                           symbolBrush=pg.mkBrush(color=(0, 0, 255, 100)))
        self._mptPlot.plot(efficient_frontier[0],
                           efficient_frontier[1],
                           pen=pg.mkPen(color=(0, 0, 0), width=5))

        self._mptPlot.plot([min_volatility_point[0]],
                           [min_volatility_point[1]],
                           name="Minimum Volatility",
                           pen=None,
                           symbol='star',
                           symbolPen=pg.mkPen(color=(255, 0, 0, 255), width=0),
                           symbolBrush=pg.mkBrush(color=(255, 0, 0, 255)),
                           symbolSize=20)

        self._mptPlot.plot([max_sharpe_ratio_point[0]],
                           [max_sharpe_ratio_point[1]],
                           name="Max Sharpe Ratio",
                           pen=None,
                           symbol='star',
                           symbolPen=pg.mkPen(color=(0, 255, 0, 255), width=0),
                           symbolBrush=pg.mkBrush(color=(0, 255, 0, 255)),
                           symbolSize=20)

        self._mptPlot.plot([random_volatility_point[0]],
                           [random_volatility_point[1]],
                           name="Minimum Volatility (from random generated)",
                           pen=None,
                           symbol='star',
                           symbolPen=pg.mkPen(color=(0, 0, 0, 255), width=2),
                           symbolBrush=pg.mkBrush(color=(255, 0, 0, 255)),
                           symbolSize=20)

        self._mptPlot.plot([random_sharpe_point[0]], [random_sharpe_point[1]],
                           name="Max Sharpe Ratio (from random generated)",
                           pen=None,
                           symbol='star',
                           symbolPen=pg.mkPen(color=(0, 0, 0, 255), width=2),
                           symbolBrush=pg.mkBrush(color=(0, 255, 0, 255)),
                           symbolSize=20)
Beispiel #14
0
class AmzHistoryChart(QWidget):
    """A chart that graphs the history of an AmazonListing's sales rank, price, and number of offers."""

    def __init__(self, parent=None):
        super(AmzHistoryChart, self).__init__(parent=parent)

        self.dbsession = Session()
        self.context_menu_actions = []
        self._avg_pointspan = 0
        self._max_points = 100
        self.source = None
        self.history = None

        layout = QVBoxLayout()
        layout.setContentsMargins(0, 0, 0, 0)
        self.setLayout(layout)

        # Set up the chart
        self.chart_view = QChartView(self)
        self.chart_view.setRenderHint(QPainter.Antialiasing)
        self.chart_view.setContextMenuPolicy(Qt.CustomContextMenu)
        self.chart_view.customContextMenuRequested.connect(self.context_menu)

        self.chart = QChart()
        self.chart.legend().hide()
        self.chart.setFlags(QGraphicsItem.ItemIsFocusable | QGraphicsItem.ItemIsSelectable)
        self.chart.installEventFilter(self)
        self.chart_view.setChart(self.chart)

        self.layout().addWidget(self.chart_view)

        # Create the axes
        rcolor = QColor(50, 130, 220)
        pcolor = QColor(0, 200, 0)
        ocolor = QColor(255, 175, 0)

        self.timeAxis = QDateTimeAxis()
        self.timeAxis.setFormat('M/dd hh:mm')
        self.timeAxis.setTitleText('Date/Time')
        self.chart.addAxis(self.timeAxis, Qt.AlignBottom)

        self.timeAxis.minChanged.connect(self.on_timeaxis_min_changed)

        self.rankAxis = QValueAxis()
        self.rankAxis.setLabelFormat('%\'i')
        self.rankAxis.setTitleText('Sales Rank')
        self.rankAxis.setLinePenColor(rcolor)
        self.rankAxis.setLabelsColor(rcolor)
        self.chart.addAxis(self.rankAxis, Qt.AlignLeft)

        self.priceAxis = QValueAxis()
        self.priceAxis.setLabelFormat('$%.2f')
        self.priceAxis.setTitleText('Price')
        self.priceAxis.setLinePenColor(pcolor)
        self.priceAxis.setLabelsColor(pcolor)
        self.chart.addAxis(self.priceAxis, Qt.AlignRight)

        # Create the series
        self.rankLine = QLineSeries()
        self.chart.addSeries(self.rankLine)
        self.rankLine.attachAxis(self.timeAxis)
        self.rankLine.attachAxis(self.rankAxis)
        self.rankLine.setColor(rcolor)

        self.priceLine = QLineSeries()
        self.chart.addSeries(self.priceLine)
        self.priceLine.attachAxis(self.timeAxis)
        self.priceLine.attachAxis(self.priceAxis)
        self.priceLine.setColor(pcolor)

        self.salesPoints = QScatterSeries()
        self.chart.addSeries(self.salesPoints)
        self.salesPoints.attachAxis(self.timeAxis)
        self.salesPoints.attachAxis(self.rankAxis)
        self.salesPoints.setColor(ocolor)

    def add_context_action(self, action):
        """Add an action to the chart's context menu."""
        self.context_menu_actions.append(action)

    def add_context_actions(self, actions):
        """Adds all action in an iterable."""
        self.context_menu_actions.extend(actions)

    def remove_context_action(self, action):
        """Removes an action from the chart's context menu."""
        self.context_menu_actions.remove(action)

    def context_menu(self, point):
        """Show a context menu on the chart."""
        menu = QMenu(self)
        menu.addActions(self.context_menu_actions)

        point = self.chart_view.viewport().mapToGlobal(point)
        menu.popup(point)

    def set_source(self, source):
        """Set the source listing for the graph."""
        self.source = source

        # Update the chart
        self.rankLine.clear()
        self.priceLine.clear()
        self.salesPoints.clear()
        self.history = None

        start_date = datetime.utcnow() - timedelta(days=5)
        self.load_history_from(start_date)

        self.reset_axes()

    def load_history_from(self, start_date=datetime.utcfromtimestamp(0)):
        """Load history data from start-present."""
        if not self.source:
            self._avg_pointspan = 0
            return

        # Get the earliest point already in the chart
        points = self.rankLine.pointsVector()

        if points:
            # The chart is drawn right-to-left, so the last point is the earliest point
            earliest_msecs = points[-1].x()
            earliest = datetime.fromtimestamp(earliest_msecs / 1000, timezone.utc)

            if earliest <= start_date:
                return

        else:
            earliest = datetime.now(timezone.utc)

        # Get the product history stats if we don't already have them
        if self.history is None:
            self.history = dbhelpers.ProductHistoryStats(self.dbsession, self.source.id)

        # Start adding points to the chart
        last_row = None
        for row in self.dbsession.query(AmzProductHistory).\
                                  filter(AmzProductHistory.amz_listing_id == self.source.id,
                                         AmzProductHistory.timestamp > start_date.replace(tzinfo=None),
                                         AmzProductHistory.timestamp < earliest.replace(tzinfo=None)).\
                                  order_by(AmzProductHistory.timestamp.desc()):

            # SqlAlchemy returns naive timestamps
            time = row.timestamp.replace(tzinfo=timezone.utc).timestamp() * 1000

            self.rankLine.append(time, row.salesrank or 0)
            self.priceLine.append(time, row.price or 0)

            if last_row:
                # It's possible for salesrank to be None
                try:
                    slope = (last_row.salesrank - row.salesrank) / (last_row.timestamp.timestamp() - row.timestamp.timestamp())
                    if slope < -0.3:
                        self.salesPoints.append(last_row.timestamp.replace(tzinfo=timezone.utc).timestamp() * 1000,
                                                last_row.salesrank)
                except (TypeError, AttributeError):
                    pass

            last_row = row

        # Calculate the average span between points
        spans = 0
        for p1, p2 in itertools.zip_longest(itertools.islice(points, 0, None, 2), itertools.islice(points, 1, None, 2)):
            if p1 and p2: spans += abs(p1.x() - p2.x())

        self._avg_pointspan = spans // 2

    def on_timeaxis_min_changed(self, min):
        """Respond to a change in the time axis' minimum value."""
        # toTime_t() converts to UTC automatically
        utc_min = datetime.fromtimestamp(min.toTime_t(), timezone.utc)
        self.load_history_from(start_date=utc_min - timedelta(days=1))

    def reset_axes(self):
        """Resets the chart axes."""
        r = self.rankLine.pointsVector()
        p = self.priceLine.pointsVector()

        # If there is only one data point, set the min and max to the day before and the day after
        if len(r) == 1:
            tmin = QDateTime.fromMSecsSinceEpoch(r[0].x(), Qt.LocalTime).addDays(-1)
            tmax = QDateTime.fromMSecsSinceEpoch(r[0].x(), Qt.LocalTime).addDays(+1)
        else:
            tmin = min(r, key=lambda pt: pt.x(), default=QPointF(QDateTime.currentDateTime().addDays(-1).toMSecsSinceEpoch(), 0)).x()
            tmax = max(r, key=lambda pt: pt.x(), default=QPointF(QDateTime.currentDateTime().addDays(+1).toMSecsSinceEpoch(), 0)).x()
            tmin = QDateTime.fromMSecsSinceEpoch(tmin, Qt.LocalTime)
            tmax = QDateTime.fromMSecsSinceEpoch(tmax, Qt.LocalTime)

        self.timeAxis.setMin(tmin)
        self.timeAxis.setMax(tmax)

        # Find the min and max values of the series
        min_point = lambda pts: min(pts, key=lambda pt: pt.y(), default=QPointF(0, 0))
        max_point = lambda pts: max(pts, key=lambda pt: pt.y(), default=QPointF(0, 0))

        rmin = min_point(r)
        rmax = max_point(r)
        pmin = min_point(p)
        pmax = max_point(p)

        # Scale the mins and maxes to 'friendly' values
        scalemin = lambda v, step: ((v - step / 2) // step) * step
        scalemax = lambda v, step: ((v + step / 2) // step + 1) * step

        # The the axis bounds

        rmin = max(scalemin(rmin.y(), 1000), 0)
        rmax = scalemax(rmax.y(), 1000)
        pmin = max(scalemin(pmin.y(), 5), 0)
        pmax = scalemax(pmax.y(), 5)

        self.rankAxis.setMin(rmin)
        self.rankAxis.setMax(rmax)
        self.priceAxis.setMin(pmin)
        self.priceAxis.setMax(pmax)

    def eventFilter(self, watched, event):
        """Intercept and handle mouse events."""
        if event.type() == QEvent.GraphicsSceneWheel and event.orientation() == Qt.Vertical:
            factor = 0.95 if event.delta() < 0 else 1.05
            self.chart.zoom(factor)
            return True

        if event.type() == QEvent.GraphicsSceneMouseDoubleClick:
            self.chart.zoomReset()
            self.reset_axes()
            return True

        if event.type() == QEvent.GraphicsSceneMouseMove:
            delta = event.pos() - event.lastPos()
            self.chart.scroll(-delta.x(), delta.y())
            return True

        return False
Beispiel #15
0
class OperatingTimeWindow(QMainWindow):
    def setupUI(self, mui):
        self.initUI(mui)
        self.mainUI(mui)
        self.configUI(mui)
        self.thresholdUI(mui)
        self.timeUI()
        self.timeFigureUI(mui)
        self.activetiyDetailUI(mui)

        self.draw_figure()
        ## value
        self.cycle_counter = 0

    def initUI(self, mui):
        self.gb_config = QGroupBox()
        self.gb_oprTime = QGroupBox()
        mui.gb_setThreshold = QGroupBox()
        self.gb_figTime = QGroupBox()
        self.gb_actDetail = QGroupBox()

    def mainUI(self, mui):
        self.setWindowTitle('Operating Time Calclation')
        self.setGeometry(1200, 50, 0, 0)
        main_frame = QWidget()

        sw_optForm = QStackedWidget()
        sw_optForm.addWidget(mui.gb_setThreshold)
        sw_optForm.addWidget(self.gb_figTime)
        sw_optForm.addWidget(self.gb_actDetail)
        combo_optForm = QComboBox()
        combo_optForm.addItem('1: Setting Threshold')
        combo_optForm.addItem('2: Operating Time Graph')
        combo_optForm.addItem('3: Activity Details')
        combo_optForm.currentIndexChanged.connect(sw_optForm.setCurrentIndex)

        vbox_main = QVBoxLayout()
        vbox_main.addWidget(self.gb_config)
        vbox_main.addWidget(self.gb_oprTime)
        vbox_main.addWidget(combo_optForm)
        vbox_main.addWidget(sw_optForm)
        main_frame.setLayout(vbox_main)
        self.setCentralWidget(main_frame)

    def configUI(self, mui):
        btn_readConfig = QPushButton('Read')
        btn_readConfig.clicked.connect(lambda: self.readConfig(mui))
        self.le_readConfig = QLineEdit()
        btn_saveConfig = QPushButton('Save')
        btn_saveConfig.clicked.connect(lambda: self.saveConfig(mui))
        self.le_saveConfig = QLineEdit()

        ### -1-
        hbox1 = QHBoxLayout()
        hbox1.addWidget(btn_readConfig)
        hbox1.addWidget(self.le_readConfig)
        ### -2-
        hbox2 = QHBoxLayout()
        hbox2.addWidget(btn_saveConfig)
        hbox2.addWidget(self.le_saveConfig)
        ### |-1-2-|
        vbox_gb_config = QVBoxLayout()
        vbox_gb_config.addLayout(hbox1)
        vbox_gb_config.addLayout(hbox2)

        self.gb_config.setSizePolicy(QSizePolicy.Expanding,
                                     QSizePolicy.Maximum)
        self.gb_config.setTitle("Config File")
        self.gb_config.setLayout(vbox_gb_config)

    def timeUI(self):
        ### Add Element
        stdOprTimeTextLabel = QLabel()
        stdOprTimeTextLabel.setText('Standard :')
        self.stdOprTimeSb = QDoubleSpinBox()
        self.stdOprTimeSb.setSingleStep(0.01)
        self.stdOprTimeSb.setSuffix(" [sec]")
        self.stdOprTimeSb.setValue(3.0)
        calcOprTimeTextLabel = QLabel()
        calcOprTimeTextLabel.setText('Calculation :')
        self.calcOprTimeLabel = QLabel()
        self.calcOprTimeLabel.setText('0.000')
        extTimeLabel = QLabel()
        extTimeLabel.setText("[sec]")
        self.fpsSb = QSpinBox()
        self.fpsSb.setValue(30)
        self.fpsSb.setPrefix("fps: ")
        self.fpsSb.setRange(1, 150)
        differenceTimeTextLabel = QLabel()
        differenceTimeTextLabel.setText('Difference :')
        self.differenceTimeLabel = QLabel()
        self.differenceTimeLabel.setText('x.xxx')
        self.cb_alarm = QCheckBox('Alarm Threshold:')
        self.dsb_alarmRange = QDoubleSpinBox()
        self.dsb_alarmRange.setRange(0, 10)
        self.dsb_alarmRange.setValue(3.0)
        self.dsb_alarmRange.setSingleStep(0.1)
        self.dsb_alarmRange.setSuffix(' [sec]')

        self.cb_saveOprTime = QCheckBox('Save:')
        self.le_filepath = QLineEdit()
        self.le_filepath.setText("CSV File")
        self.btn_save_fd = QPushButton('...')
        self.btn_save_fd.clicked.connect(self.setSaveTimeFilePath)
        self.btn_save_fd.setFixedWidth(30)

        ### -1-
        hbox1 = QHBoxLayout()
        hbox1.addWidget(stdOprTimeTextLabel)
        hbox1.addWidget(self.stdOprTimeSb)
        hbox1.addStretch(1)
        ### -2-
        hbox2 = QHBoxLayout()
        hbox2.addWidget(calcOprTimeTextLabel)
        hbox2.addWidget(self.calcOprTimeLabel)
        hbox2.addWidget(extTimeLabel)
        hbox2.addWidget(self.fpsSb)
        hbox2.addStretch(1)
        ### -3-
        hbox3 = QHBoxLayout()
        hbox3.addWidget(differenceTimeTextLabel)
        hbox3.addWidget(self.differenceTimeLabel)
        hbox3.addStretch(1)
        hbox3.addWidget(self.cb_alarm)
        hbox3.addWidget(self.dsb_alarmRange)
        ### -4-
        hbox4 = QHBoxLayout()
        hbox4.addWidget(self.cb_saveOprTime)
        hbox4.addWidget(self.le_filepath)
        hbox4.addWidget(self.btn_save_fd)

        ### |-1-2-3-4-|
        vbox_gb_oprTime = QVBoxLayout()
        vbox_gb_oprTime.addLayout(hbox1)
        vbox_gb_oprTime.addLayout(hbox2)
        vbox_gb_oprTime.addLayout(hbox3)
        vbox_gb_oprTime.addLayout(hbox4)

        self.gb_oprTime.setSizePolicy(QSizePolicy.Expanding,
                                      QSizePolicy.Maximum)
        self.gb_oprTime.setTitle("Operating Time")
        self.gb_oprTime.setLayout(vbox_gb_oprTime)

    def activetiyDetailUI(self, mui):

        series = QPieSeries()
        chart = QChart()
        chart.addSeries(series)
        #chart.setTitle("Activity Details")
        #chart.legend().hide()

        self.chartView = QChartView()
        self.chartView.setChart(chart)
        self.chartView.setRenderHint(QPainter.Antialiasing)
        self.chartView.setMinimumWidth(350)

        vbox_gb_actDetail = QVBoxLayout()
        vbox_gb_actDetail.addWidget(self.chartView)

        self.gb_actDetail.setSizePolicy(QSizePolicy.Expanding,
                                        QSizePolicy.Maximum)
        self.gb_actDetail.setLayout(vbox_gb_actDetail)

    def timeFigureUI(self, mui):
        fig = Figure((10, 5), dpi=100)
        self.canvas_time = FigureCanvas(fig)
        self.axes = fig.add_subplot(111)
        self.axes.clear()
        self.x_cycle = deque([])
        self.y_time = deque([])
        self.axes.bar(self.x_cycle, self.y_time)

        self.cb_registrationTime = QCheckBox('Registration')
        self.btn_initGraph = QPushButton('Init')
        self.btn_initGraph.clicked.connect(self.clearGraph)
        lbl_maxCount = QLabel('Num:')
        self.sb_maxCount = QSpinBox()
        self.sb_maxCount.setRange(1, 50)
        self.sb_maxCount.setValue(10)
        lbl_maxValue = QLabel('Val:')
        self.sb_maxValue = QSpinBox()
        self.sb_maxValue.setRange(1, 50)
        self.sb_maxValue.setValue(5)
        lbl_mean = QLabel('Mean:')
        self.le_mean = QLineEdit('')
        lbl_variance = QLabel('Variance:')
        self.le_variance = QLineEdit('')

        ### -1-
        hbox1 = QHBoxLayout()
        hbox1.addWidget(self.cb_registrationTime)
        hbox1.addStretch(1)
        hbox1.addWidget(lbl_maxCount)
        hbox1.addWidget(self.sb_maxCount)
        hbox1.addStretch(1)
        hbox1.addWidget(self.btn_initGraph)

        ### -2-
        hbox2 = QHBoxLayout()
        hbox2.addWidget(lbl_maxValue)
        hbox2.addWidget(self.sb_maxValue)
        hbox2.addWidget(lbl_mean)
        hbox2.addWidget(self.le_mean)
        hbox2.addWidget(lbl_variance)
        hbox2.addWidget(self.le_variance)

        ### |-1-2-|
        vbox_gb_figTime = QVBoxLayout()
        vbox_gb_figTime.addLayout(hbox1)
        vbox_gb_figTime.addWidget(self.canvas_time)
        vbox_gb_figTime.addLayout(hbox2)

        self.gb_figTime.setMinimumHeight(350)
        self.gb_figTime.setLayout(vbox_gb_figTime)

    def thresholdUI(self, mui):
        ### Add Element
        mui.cb_thX1_on = QCheckBox("X1")
        mui.cb_thX2_on = QCheckBox("X2")
        mui.cb_thY1_on = QCheckBox("Y1")
        mui.cb_thY2_on = QCheckBox("Y2")
        mui.cb_thZ1_on = QCheckBox("Z1")
        mui.cb_thZ2_on = QCheckBox("Z2")
        ## X
        mui.sld_thX1 = QSlider(Qt.Vertical)
        mui.sld_thX1.setRange(-50, 50)
        mui.sld_thX1.setValue(0)
        mui.sb_thX1 = QSpinBox()
        mui.sb_thX1.setRange(-50, 50)
        mui.sb_thX1.setValue(mui.sld_thX1.value())
        mui.sb_thX1.valueChanged.connect(mui.setSliderThresholdParameter)
        mui.sld_thX1.valueChanged.connect(mui.setSpinBoxGraphParameter)
        mui.sld_thX1.valueChanged.connect(mui.refreshGraphSlider)
        mui.sb_thX1Variance = QSpinBox()
        mui.sb_thX1Variance.setRange(0, 1000)
        mui.sb_thX1Variance.valueChanged.connect(mui.refreshGraphSpinBox)
        mui.sld_thX2 = QSlider(Qt.Vertical)
        mui.sld_thX2.setRange(-50, 50)
        mui.sld_thX2.setValue(0)
        mui.sb_thX2 = QSpinBox()
        mui.sb_thX2.setRange(-50, 50)
        mui.sb_thX2.setValue(mui.sld_thX1.value())
        mui.sb_thX2.valueChanged.connect(mui.setSliderThresholdParameter)
        mui.sld_thX2.valueChanged.connect(mui.setSpinBoxGraphParameter)
        mui.sld_thX2.valueChanged.connect(mui.refreshGraphSlider)
        mui.sb_thX2Variance = QSpinBox()
        mui.sb_thX2Variance.setRange(0, 1000)
        mui.sb_thX2Variance.valueChanged.connect(mui.refreshGraphSpinBox)
        ## Y
        mui.sld_thY1 = QSlider(Qt.Vertical)
        mui.sld_thY1.setRange(-50, 50)
        mui.sld_thY1.setValue(0)
        mui.sb_thY1 = QSpinBox()
        mui.sb_thY1.setRange(-50, 50)
        mui.sb_thY1.setValue(mui.sld_thY1.value())
        mui.sb_thY1.valueChanged.connect(mui.setSliderThresholdParameter)
        mui.sld_thY1.valueChanged.connect(mui.setSpinBoxGraphParameter)
        mui.sld_thY1.valueChanged.connect(mui.refreshGraphSlider)
        mui.sb_thY1Variance = QSpinBox()
        mui.sb_thY1Variance.setRange(0, 1000)
        mui.sb_thY1Variance.valueChanged.connect(mui.refreshGraphSpinBox)
        mui.sld_thY2 = QSlider(Qt.Vertical)
        mui.sld_thY2.setRange(-50, 50)
        mui.sld_thY2.setValue(0)
        mui.sb_thY2 = QSpinBox()
        mui.sb_thY2.setRange(-50, 50)
        mui.sb_thY2.setValue(mui.sld_thY1.value())
        mui.sb_thY2.valueChanged.connect(mui.setSliderThresholdParameter)
        mui.sld_thY2.valueChanged.connect(mui.setSpinBoxGraphParameter)
        mui.sld_thY2.valueChanged.connect(mui.refreshGraphSlider)
        mui.sb_thY2Variance = QSpinBox()
        mui.sb_thY2Variance.setRange(0, 1000)
        mui.sb_thY2Variance.valueChanged.connect(mui.refreshGraphSpinBox)
        ##Z
        mui.sld_thZ1 = QSlider(Qt.Vertical)
        mui.sld_thZ1.setRange(-50, 50)
        mui.sld_thZ1.setValue(0)
        mui.sb_thZ1 = QSpinBox()
        mui.sb_thZ1.setRange(-50, 50)
        mui.sb_thZ1.setValue(mui.sld_thZ1.value())
        mui.sb_thZ1.valueChanged.connect(mui.setSliderThresholdParameter)
        mui.sld_thZ1.valueChanged.connect(mui.setSpinBoxGraphParameter)
        mui.sld_thZ1.valueChanged.connect(mui.refreshGraphSlider)
        mui.sb_thZ1Variance = QSpinBox()
        mui.sb_thZ1Variance.setRange(0, 1000)
        mui.sb_thZ1Variance.valueChanged.connect(mui.refreshGraphSpinBox)
        mui.sld_thZ2 = QSlider(Qt.Vertical)
        mui.sld_thZ2.setRange(-50, 50)
        mui.sld_thZ2.setValue(0)
        mui.sb_thZ2 = QSpinBox()
        mui.sb_thZ2.setRange(-50, 50)
        mui.sb_thZ2.setValue(mui.sld_thZ2.value())
        mui.sb_thZ2.valueChanged.connect(mui.setSliderThresholdParameter)
        mui.sld_thZ2.valueChanged.connect(mui.setSpinBoxGraphParameter)
        mui.sld_thZ2.valueChanged.connect(mui.refreshGraphSlider)
        mui.sb_thZ2Variance = QSpinBox()
        mui.sb_thZ2Variance.setRange(0, 1000)
        mui.sb_thZ2Variance.valueChanged.connect(mui.refreshGraphSpinBox)

        #
        lbl_scaleX = QLabel('scale X:')
        lbl_scaleY = QLabel('scale Y:')
        lbl_scaleZ = QLabel('scale Z:')
        mui.sb_thX_scale = QDoubleSpinBox()
        mui.sb_thX_scale.setRange(0.01, 100)
        mui.sb_thX_scale.setValue(0.05)
        mui.sb_thX_scale.setSingleStep(0.01)
        mui.sb_thY_scale = QDoubleSpinBox()
        mui.sb_thY_scale.setRange(0.01, 100)
        mui.sb_thY_scale.setValue(0.05)
        mui.sb_thY_scale.setSingleStep(0.01)
        mui.sb_thZ_scale = QDoubleSpinBox()
        mui.sb_thZ_scale.setRange(0.01, 100)
        mui.sb_thZ_scale.setValue(0.05)
        mui.sb_thZ_scale.setSingleStep(0.01)

        ### -1-
        hbox1 = QHBoxLayout()
        hbox1.addWidget(lbl_scaleX)
        hbox1.addWidget(mui.sb_thX_scale)
        hbox1.addWidget(lbl_scaleY)
        hbox1.addWidget(mui.sb_thY_scale)
        hbox1.addWidget(lbl_scaleZ)
        hbox1.addWidget(mui.sb_thZ_scale)

        ### |1|
        vbox1 = QVBoxLayout()
        vbox1.addWidget(mui.cb_thX1_on)
        vbox1.addWidget(mui.sb_thX1)
        vbox1.addWidget(mui.sld_thX1)
        vbox1.addWidget(mui.sb_thX1Variance)
        vbox1_2 = QVBoxLayout()
        vbox1_2.addWidget(mui.cb_thX2_on)
        vbox1_2.addWidget(mui.sb_thX2)
        vbox1_2.addWidget(mui.sld_thX2)
        vbox1_2.addWidget(mui.sb_thX2Variance)
        ### |2|
        vbox2 = QVBoxLayout()
        vbox2.addWidget(mui.cb_thY1_on)
        vbox2.addWidget(mui.sb_thY1)
        vbox2.addWidget(mui.sld_thY1)
        vbox2.addWidget(mui.sb_thY1Variance)
        vbox2_2 = QVBoxLayout()
        vbox2_2.addWidget(mui.cb_thY2_on)
        vbox2_2.addWidget(mui.sb_thY2)
        vbox2_2.addWidget(mui.sld_thY2)
        vbox2_2.addWidget(mui.sb_thY2Variance)
        ### |3|
        vbox3 = QVBoxLayout()
        vbox3.addWidget(mui.cb_thZ1_on)
        vbox3.addWidget(mui.sb_thZ1)
        vbox3.addWidget(mui.sld_thZ1)
        vbox3.addWidget(mui.sb_thZ1Variance)
        vbox3_2 = QVBoxLayout()
        vbox3_2.addWidget(mui.cb_thZ2_on)
        vbox3_2.addWidget(mui.sb_thZ2)
        vbox3_2.addWidget(mui.sld_thZ2)
        vbox3_2.addWidget(mui.sb_thZ2Variance)
        ### -2|1|2|3|-
        hbox2 = QHBoxLayout()
        hbox2.addLayout(vbox1)
        hbox2.addLayout(vbox1_2)
        hbox2.addLayout(vbox2)
        hbox2.addLayout(vbox2_2)
        hbox2.addLayout(vbox3)
        hbox2.addLayout(vbox3_2)

        ### |-1-2-|
        vbox_gb_setThreshold = QVBoxLayout()
        vbox_gb_setThreshold.addLayout(hbox1)
        vbox_gb_setThreshold.addLayout(hbox2)

        mui.gb_setThreshold.setMinimumHeight(400)
        mui.gb_setThreshold.setLayout(vbox_gb_setThreshold)

    def readConfig(self, mui):
        filename = QFileDialog.getOpenFileName(self, 'Open file', '.')
        self.le_readConfig.setText(filename[0])
        if self.le_readConfig.text() == "":
            return -1

        config = ConfigParser()
        config.read(self.le_readConfig.text())

        ## set parameter
        self.stdOprTimeSb.setValue(
            float(config['timeUI']['StandartOperationTime']))
        self.fpsSb.setValue(int(config['timeUI']['FPS']))
        self.cb_saveOprTime.setChecked(
            "True" == (config['timeUI']['SaveOperationTime']))
        self.le_filepath.setText(config['timeUI']['SaveFilename'])
        mui.cb_thX1_on.setChecked(
            "True" == (config['thresholdUI']['UseThreshold_X1']))
        mui.cb_thX2_on.setChecked(
            "True" == (config['thresholdUI']['UseThreshold_X2']))
        mui.cb_thY1_on.setChecked(
            "True" == (config['thresholdUI']['UseThreshold_Y1']))
        mui.cb_thY2_on.setChecked(
            "True" == (config['thresholdUI']['UseThreshold_Y2']))
        mui.cb_thZ1_on.setChecked(
            "True" == (config['thresholdUI']['UseThreshold_Z1']))
        mui.cb_thZ2_on.setChecked(
            "True" == (config['thresholdUI']['UseThreshold_Z2']))
        mui.sb_thX_scale.setValue(
            float(config['thresholdUI']['Threshold_ScaleX']))
        mui.sb_thY_scale.setValue(
            float(config['thresholdUI']['Threshold_ScaleY']))
        mui.sb_thZ_scale.setValue(
            float(config['thresholdUI']['Threshold_ScaleZ']))
        mui.sb_thX1.setValue(int(config['thresholdUI']['Threshold_ValueX1']))
        mui.sb_thX2.setValue(int(config['thresholdUI']['Threshold_ValueX2']))
        mui.sb_thY1.setValue(int(config['thresholdUI']['Threshold_ValueY1']))
        mui.sb_thY2.setValue(int(config['thresholdUI']['Threshold_ValueY2']))
        mui.sb_thZ1.setValue(int(config['thresholdUI']['Threshold_ValueZ1']))
        mui.sb_thZ2.setValue(int(config['thresholdUI']['Threshold_ValueZ2']))
        mui.sb_thX1Variance.setValue(
            int(config['thresholdUI']['Threshold_VarianceX1']))
        mui.sb_thX2Variance.setValue(
            int(config['thresholdUI']['Threshold_VarianceX2']))
        mui.sb_thY1Variance.setValue(
            int(config['thresholdUI']['Threshold_VarianceY1']))
        mui.sb_thY2Variance.setValue(
            int(config['thresholdUI']['Threshold_VarianceY2']))
        mui.sb_thZ1Variance.setValue(
            int(config['thresholdUI']['Threshold_VarianceZ1']))
        mui.sb_thZ2Variance.setValue(
            int(config['thresholdUI']['Threshold_VarianceZ2']))
        mui.combo.setCurrentText(config['figureUI']['TargetSkeltonParts'])

    def saveConfig(self, mui):
        filename = QFileDialog.getSaveFileName(self, 'Save File', '.')
        self.le_saveConfig.setText(filename[0])
        if self.le_saveConfig.text() == "":
            return -1

        config = ConfigParser()
        config.optionxform = str
        config.add_section('timeUI')
        config.add_section('thresholdUI')
        config.add_section('figureUI')
        config.add_section('mainUI')
        config.set('timeUI', 'StandartOperationTime',
                   str(self.stdOprTimeSb.value()))
        config.set('timeUI', 'FPS', str(self.fpsSb.value()))
        config.set('timeUI', 'SaveOperationTime',
                   str(self.cb_saveOprTime.checkState()))
        config.set('timeUI', 'SaveFilename', str(self.le_filepath.text()))
        config.set('thresholdUI', 'UseThreshold_X1',
                   self.bool2string(mui.cb_thX1_on.checkState()))
        config.set('thresholdUI', 'UseThreshold_X2',
                   self.bool2string(mui.cb_thX2_on.checkState()))
        config.set('thresholdUI', 'UseThreshold_Y1',
                   self.bool2string(mui.cb_thY1_on.checkState()))
        config.set('thresholdUI', 'UseThreshold_Y2',
                   self.bool2string(mui.cb_thY2_on.checkState()))
        config.set('thresholdUI', 'UseThreshold_Z1',
                   self.bool2string(mui.cb_thZ1_on.checkState()))
        config.set('thresholdUI', 'UseThreshold_Z2',
                   self.bool2string(mui.cb_thZ2_on.checkState()))
        config.set('thresholdUI', 'Threshold_ScaleX',
                   str(mui.sb_thX_scale.value()))
        config.set('thresholdUI', 'Threshold_ScaleY',
                   str(mui.sb_thY_scale.value()))
        config.set('thresholdUI', 'Threshold_ScaleZ',
                   str(mui.sb_thZ_scale.value()))
        config.set('thresholdUI', 'Threshold_ValueX1',
                   str(mui.sb_thX1.value()))
        config.set('thresholdUI', 'Threshold_ValueX2',
                   str(mui.sb_thX2.value()))
        config.set('thresholdUI', 'Threshold_ValueY1',
                   str(mui.sb_thY1.value()))
        config.set('thresholdUI', 'Threshold_ValueY2',
                   str(mui.sb_thY2.value()))
        config.set('thresholdUI', 'Threshold_ValueZ1',
                   str(mui.sb_thZ1.value()))
        config.set('thresholdUI', 'Threshold_ValueZ2',
                   str(mui.sb_thZ2.value()))
        config.set('thresholdUI', 'Threshold_VarianceX1',
                   str(mui.sb_thX1Variance.value()))
        config.set('thresholdUI', 'Threshold_VarianceX2',
                   str(mui.sb_thX2Variance.value()))
        config.set('thresholdUI', 'Threshold_VarianceY1',
                   str(mui.sb_thY1Variance.value()))
        config.set('thresholdUI', 'Threshold_VarianceY2',
                   str(mui.sb_thY2Variance.value()))
        config.set('thresholdUI', 'Threshold_VarianceZ1',
                   str(mui.sb_thZ1Variance.value()))
        config.set('thresholdUI', 'Threshold_VarianceZ2',
                   str(mui.sb_thZ2Variance.value()))
        config.set('figureUI', 'TargetSkeltonParts',
                   str(mui.combo.currentText()))
        config.write(open(self.le_saveConfig.text(), 'w'))

    def drawChart(self, mui):
        series = QPieSeries()
        series.append("Main", mui.keyfunc.mainActivityFrame)
        series.append("Key", mui.keyfunc.keyActivityFrame)
        slice1 = series.slices()[0]
        #slice1.setExploded()
        slice1.setLabelVisible()
        slice1.setPen(QPen(QColor(40, 100, 240, 250), 2))
        slice1.setBrush(QColor(40, 100, 240, 200))
        slice2 = series.slices()[1]
        slice2.setLabelVisible()
        slice2.setPen(QPen(QColor(20, 150, 240, 250), 2))
        slice2.setBrush(QColor(20, 150, 240, 200))

        chart = QChart()
        chart.addSeries(series)
        #chart.setTitle("Activity Details")
        #chart.legend().hide()

        self.chartView.setChart(chart)

    def getCalclationTime(self, mui):
        if self.cb_registrationTime.checkState():
            self.setCalclationTimeGraph()
        self.calcDifferenceOperatingTime()
        if self.cb_saveOprTime.checkState():
            self.writeText(mui)

    def setCalclationTimeGraph(self):
        if (len(self.x_cycle) >= self.sb_maxCount.value()):
            self.x_cycle.popleft()
            self.y_time.popleft()
        self.cycle_counter += 1
        self.x_cycle.append(self.cycle_counter)
        self.y_time.append(float(self.calcOprTimeLabel.text()))
        self.le_mean.setText("{0:.2f}".format(np.array(self.y_time).mean()))
        self.le_variance.setText("{0:.2f}".format(
            self.calclVariance(np.array(self.y_time))))
        self.draw_figure()

    def draw_figure(self):
        self.axes.clear()
        self.axes.set_ylim([0, self.sb_maxValue.value()])
        self.axes.bar(self.x_cycle, self.y_time, color='#6060AA')
        self.canvas_time.draw()

    def clearGraph(self):
        self.cycle_counter = 0
        self.x_cycle = deque([])
        self.y_time = deque([])
        self.draw_figure()

    def calclVariance(self, val):
        variance = np.sum((val * val)) / len(val) - (val.mean() * val.mean())
        return variance

    def calcDifferenceOperatingTime(self):
        time = self.stdOprTimeSb.value() - float(self.calcOprTimeLabel.text())
        self.differenceTimeLabel.setText("{0:.2f}[sec]".format(time))
        if self.cb_alarm.checkState():
            if self.dsb_alarmRange.value() <= abs(time) and 0 < time:
                self.popupMessage(0, abs(time))
            elif self.dsb_alarmRange.value() <= abs(time) and 0 > time:
                self.popupMessage(1, abs(time))

    def popupMessage(self, signal, time):
        if signal == 0:
            QMessageBox.warning(
                self, 'Alarm Message',
                "標準作業時間({1:.2f}秒)と比較して{0:.2f}秒速いです".format(
                    time, self.stdOprTimeSb.value()), QMessageBox.Close)
        elif signal == 1:
            QMessageBox.warning(
                self, 'Alarm Message',
                "標準作業時間({1:.2f}秒)と比較して{0:.2f}秒遅いです".format(
                    time, self.stdOprTimeSb.value()), QMessageBox.Close)

    def writeText(self, mui):
        import csv
        import os.path
        writeItemname = True
        if os.path.isfile(self.le_filepath.text()):
            writeItemname = False
        with open(self.le_filepath.text(), 'a', newline="") as f:
            writer = csv.writer(f)
            if writeItemname:
                writer.writerow(
                    ['Filename', 'FPS', 'Calclation Time', 'Setting Time'])
            writer.writerow([
                mui.fnameQle.text(),
                self.fpsSb.value(),
                float(self.calcOprTimeLabel.text()),
                self.stdOprTimeSb.value()
            ])

    def setSaveTimeFilePath(self):
        filename = QFileDialog.getSaveFileName(self, 'Save File', '.')
        self.le_filepath.setText(filename[0])

    def bool2string(self, bool_val):
        if bool_val:
            return 'True'
        else:
            return 'False'
Beispiel #16
0
class MicroPythonGraphWidget(QWidget):
    """
    Class implementing the MicroPython graph widget.
    
    @signal dataFlood emitted to indicate, that too much data is received
    """
    dataFlood = pyqtSignal()

    def __init__(self, parent=None):
        """
        Constructor
        
        @param parent reference to the parent widget
        @type QWidget
        """
        super(MicroPythonGraphWidget, self).__init__(parent)

        self.__layout = QHBoxLayout()
        self.__layout.setContentsMargins(2, 2, 2, 2)
        self.setLayout(self.__layout)

        self.__chartView = QChartView(self)
        self.__chartView.setSizePolicy(QSizePolicy.Expanding,
                                       QSizePolicy.Expanding)
        self.__layout.addWidget(self.__chartView)

        self.__verticalLayout = QVBoxLayout()
        self.__verticalLayout.setContentsMargins(0, 0, 0, 0)
        self.__layout.addLayout(self.__verticalLayout)

        self.__saveButton = QToolButton(self)
        self.__saveButton.setIcon(UI.PixmapCache.getIcon("fileSave"))
        self.__saveButton.setToolTip(self.tr("Press to save the raw data"))
        self.__saveButton.clicked.connect(self.on_saveButton_clicked)
        self.__verticalLayout.addWidget(self.__saveButton)
        self.__verticalLayout.setAlignment(self.__saveButton, Qt.AlignHCenter)

        spacerItem = QSpacerItem(20, 20, QSizePolicy.Minimum,
                                 QSizePolicy.Expanding)
        self.__verticalLayout.addItem(spacerItem)

        label = QLabel(self.tr("max. X:"))
        self.__verticalLayout.addWidget(label)
        self.__verticalLayout.setAlignment(label, Qt.AlignHCenter)

        self.__maxX = 100
        self.__maxXSpinBox = QSpinBox()
        self.__maxXSpinBox.setMinimum(100)
        self.__maxXSpinBox.setMaximum(1000)
        self.__maxXSpinBox.setSingleStep(100)
        self.__maxXSpinBox.setToolTip(
            self.tr("Enter the maximum number of data points to be plotted."))
        self.__maxXSpinBox.setValue(self.__maxX)
        self.__maxXSpinBox.setAlignment(Qt.AlignRight)
        self.__verticalLayout.addWidget(self.__maxXSpinBox)

        # holds the data to be checked for plotable data
        self.__inputBuffer = []
        # holds the raw data
        self.__rawData = []
        self.__dirty = False

        self.__maxY = 1000
        self.__flooded = False  # flag indicating a data flood

        self.__data = [deque([0] * self.__maxX)]
        self.__series = [QLineSeries()]

        # Y-axis ranges
        self.__yRanges = [1, 5, 10, 25, 50, 100, 250, 500, 1000]

        # setup the chart
        self.__chart = QChart()
        self.__chart.legend().hide()
        self.__chart.addSeries(self.__series[0])
        self.__axisX = QValueAxis()
        self.__axisX.setRange(0, self.__maxX)
        self.__axisX.setLabelFormat("time")
        self.__axisY = QValueAxis()
        self.__axisY.setRange(-self.__maxY, self.__maxY)
        self.__axisY.setLabelFormat("%d")
        self.__chart.setAxisX(self.__axisX, self.__series[0])
        self.__chart.setAxisY(self.__axisY, self.__series[0])
        self.__chartView.setChart(self.__chart)
        self.__chartView.setRenderHint(QPainter.Antialiasing)

        self.__maxXSpinBox.valueChanged.connect(self.__handleMaxXChanged)

    @pyqtSlot(bytes)
    def processData(self, data):
        """
        Public slot to process the raw data.
        
        It takes raw bytes, checks the data for a valid tuple of ints or
        floats and adds the data to the graph. If the the length of the bytes
        data is greater than 1024 then a dataFlood signal is emitted to ensure
        eric can take action to remain responsive.
        
        @param data raw data received from the connected device via the main
            device widget
        @type bytes
        """
        # flooding guard
        if self.__flooded:
            return

        if len(data) > 1024:
            self.__flooded = True
            self.dataFlood.emit()
            return

        # disable the inputs while processing data
        self.__saveButton.setEnabled(False)
        self.__maxXSpinBox.setEnabled(False)

        data = data.replace(b"\r\n", b"\n").replace(b"\r", b"\n")
        self.__inputBuffer.append(data)

        # check if the data contains a Python tuple containing numbers (int
        # or float) on a single line
        inputBytes = b"".join(self.__inputBuffer)
        lines = inputBytes.splitlines(True)
        for line in lines:
            if not line.endswith(b"\n"):
                # incomplete line (last line); skip it
                break

            line = line.strip()
            if line.startswith(b"(") and line.endswith(b")"):
                # it may be a tuple we are interested in
                rawValues = [val.strip() for val in line[1:-1].split(b",")]
                values = []
                for raw in rawValues:
                    try:
                        values.append(int(raw))
                        # ok, it is an integer
                        continue
                    except ValueError:
                        # test for a float
                        pass
                    try:
                        values.append(float(raw))
                    except ValueError:
                        # it is not an int or float, ignore it
                        continue
                if values:
                    self.__addData(tuple(values))

        self.__inputBuffer = []
        if lines[-1] and not lines[-1].endswith(b"\n"):
            # Append any left over bytes for processing next time data is
            # received.
            self.__inputBuffer.append(lines[-1])

        # re-enable the inputs
        self.__saveButton.setEnabled(True)
        self.__maxXSpinBox.setEnabled(True)

    def __addData(self, values):
        """
        Private method to add a tuple of values to the graph.
        
        It ensures there are the required number of line series, adds the data
        to the line series and updates the range of the chart so the chart
        displays nicely.
        
        @param values tuple containing the data to be added
        @type tuple of int or float
        """
        # store incoming data to be able to dump it as CSV upon request
        self.__rawData.append(values)
        self.__dirty = True

        # check number of incoming values and adjust line series accordingly
        if len(values) != len(self.__series):
            valuesLen = len(values)
            seriesLen = len(self.__series)
            if valuesLen > seriesLen:
                # add a nwe line series
                for _index in range(valuesLen - seriesLen):
                    newSeries = QLineSeries()
                    self.__chart.addSeries(newSeries)
                    self.__chart.setAxisX(self.__axisX, newSeries)
                    self.__chart.setAxisY(self.__axisY, newSeries)
                    self.__series.append(newSeries)
                    self.__data.append(deque([0] * self.__maxX))
            else:
                # remove obsolete line series
                for oldSeries in self.__series[valuesLen:]:
                    self.__chart.removeSeries(oldSeries)
                self.__series = self.__series[:valuesLen]
                self.__data = self.__data[:valuesLen]

        # add the new values to the display and compute the maximum range
        maxRanges = []
        for index, value in enumerate(values):
            self.__data[index].appendleft(value)
            maxRanges.append(
                max([max(self.__data[index]),
                     abs(min(self.__data[index]))]))
            if len(self.__data[index]) > self.__maxX:
                self.__data[index].pop()

        # re-scale the y-axis
        maxYRange = max(maxRanges)
        yRange = bisect.bisect_left(self.__yRanges, maxYRange)
        if yRange < len(self.__yRanges):
            self.__maxY = self.__yRanges[yRange]
        elif maxYRange > self.__maxY:
            self.__maxY += self.__maxY
        elif maxYRange < self.__maxY / 2:
            self.__maxY /= 2
        self.__axisY.setRange(-self.__maxY, self.__maxY)

        # ensure that floats are used to label the y-axis if the range is small
        if self.__maxY <= 5:
            self.__axisY.setLabelFormat("%2.2f")
        else:
            self.__axisY.setLabelFormat("%d")

        # update the line series
        for index, series in enumerate(self.__series):
            series.clear()
            xyValues = []
            for x in range(self.__maxX):
                value = self.__data[index][self.__maxX - 1 - x]
                xyValues.append((x, value))
            for xy in xyValues:
                series.append(*xy)

    @pyqtSlot()
    def on_saveButton_clicked(self):
        """
        Private slot to save the raw data to a CSV file.
        """
        self.saveData()

    def hasData(self):
        """
        Public method to check, if the chart contains some valid data.
        
        @return flag indicating valid data
        @rtype bool
        """
        return len(self.__rawData) > 0

    def isDirty(self):
        """
        Public method to check, if the chart contains unsaved data.
        
        @return flag indicating unsaved data
        @rtype bool
        """
        return self.hasData() and self.__dirty

    def saveData(self):
        """
        Public method to save the dialog's raw data.
        
        @return flag indicating success
        @rtype bool
        """
        baseDir = (Preferences.getMultiProject("Workspace")
                   or os.path.expanduser("~"))
        dataDir = os.path.join(baseDir, "data_capture")

        if not os.path.exists(dataDir):
            os.makedirs(dataDir)

        # save the raw data as a CSV file
        fileName = "{0}.csv".format(time.strftime("%Y%m%d-%H%M%S"))
        fullPath = os.path.join(dataDir, fileName)
        try:
            csvFile = open(fullPath, "w")
            csvWriter = csv.writer(csvFile)
            csvWriter.writerows(self.__rawData)
            csvFile.close()

            self.__dirty = False
            return True
        except (IOError, OSError) as err:
            E5MessageBox.critical(
                self, self.tr("Save Chart Data"),
                self.tr("""<p>The chart data could not be saved into file"""
                        """ <b>{0}</b>.</p><p>Reason: {1}</p>""").format(
                            fullPath, str(err)))
            return False

    @pyqtSlot(int)
    def __handleMaxXChanged(self, value):
        """
        Private slot handling a change of the max. X spin box.
        
        @param value value of the spin box
        @type int
        """
        delta = value - self.__maxX
        if delta == 0:
            # nothing to change
            return
        elif delta > 0:
            # range must be increased
            for deq in self.__data:
                deq.extend([0] * delta)
        else:
            # range must be decreased
            data = []
            for deq in self.__data:
                data.append(deque(list(deq)[:value]))
            self.__data = data

        self.__maxX = value
        self.__axisX.setRange(0, self.__maxX)
class Ui_MainWindow(QtWidgets.QMainWindow):
    def setupUi(self):
        self.setObjectName("MainWindow")
        self.resize(850, 550)
        self.setWindowTitle("Rastrigin")
        self.centralwidget = QtWidgets.QWidget(self)
        self.centralwidget.setObjectName("centralwidget")

        self.frameChart = QChartView(self.centralwidget)
        self.frameChart.setGeometry(QtCore.QRect(10, 10, 620, 500))
        self.frameChart.setFrameShape(QtWidgets.QFrame.Box)
        self.frameChart.setFrameShadow(QtWidgets.QFrame.Sunken)
        self.frameChart.setRenderHint(QPainter.Antialiasing)
        self.frameChart.setObjectName("frameChart")

        self.genParams = QtWidgets.QGroupBox(self.centralwidget)
        self.genParams.setGeometry(QtCore.QRect(650, 10, 161, 110))
        self.genParams.setObjectName("genParams")
        self.genParams.setTitle("General parameters")

        self.label1 = QtWidgets.QLabel(self.genParams)
        self.label1.setGeometry(QtCore.QRect(10, 20, 61, 16))
        self.label1.setObjectName("label1")
        self.label1.setText("Population:")

        self.label2 = QtWidgets.QLabel(self.genParams)
        self.label2.setGeometry(QtCore.QRect(10, 50, 91, 16))
        self.label2.setObjectName("label2")
        self.label2.setText("No. generations:")

        self.label3 = QtWidgets.QLabel(self.genParams)
        self.label3.setGeometry(QtCore.QRect(10, 80, 81, 16))
        self.label3.setObjectName("label3")
        self.label3.setText("No. dimensions:")

        self.tbxPopulation = QtWidgets.QLineEdit(self.genParams)
        self.tbxPopulation.setGeometry(QtCore.QRect(100, 20, 51, 20))
        self.tbxPopulation.setObjectName("tbxPopulation")

        self.tbxGenerations = QtWidgets.QLineEdit(self.genParams)
        self.tbxGenerations.setGeometry(QtCore.QRect(100, 50, 51, 20))
        self.tbxGenerations.setObjectName("tbxGenerations")

        self.tbxDimensions = QtWidgets.QLineEdit(self.genParams)
        self.tbxDimensions.setGeometry(QtCore.QRect(100, 80, 51, 20))
        self.tbxDimensions.setObjectName("tbxDimensions")

        self.gaParams = QtWidgets.QGroupBox(self.centralwidget)
        self.gaParams.setGeometry(QtCore.QRect(650, 130, 191, 105))
        self.gaParams.setObjectName("gaParams")
        self.gaParams.setTitle("GA parameters")

        self.label4 = QtWidgets.QLabel(self.gaParams)
        self.label4.setGeometry(QtCore.QRect(10, 20, 61, 16))
        self.label4.setObjectName("label4")
        self.label4.setText("Mutation:")

        self.label5 = QtWidgets.QLabel(self.gaParams)
        self.label5.setGeometry(QtCore.QRect(10, 50, 91, 16))
        self.label5.setObjectName("label5")
        self.label5.setText("Elite members:")

        self.label9 = QtWidgets.QLabel(self.gaParams)
        self.label9.setGeometry(QtCore.QRect(10, 80, 61, 16))
        self.label9.setObjectName("label9")
        self.label9.setText("Max abs.:")

        self.tbxMutation = QtWidgets.QLineEdit(self.gaParams)
        self.tbxMutation.setGeometry(QtCore.QRect(100, 20, 51, 20))
        self.tbxMutation.setObjectName("tbxMutation")

        self.tbxElite = QtWidgets.QLineEdit(self.gaParams)
        self.tbxElite.setGeometry(QtCore.QRect(100, 50, 51, 20))
        self.tbxElite.setObjectName("tbxElite")

        self.tbxMaxAbs = QtWidgets.QLineEdit(self.gaParams)
        self.tbxMaxAbs.setGeometry(QtCore.QRect(100, 80, 51, 20))
        self.tbxMaxAbs.setObjectName("tbxMAxAbs")

        self.psoParams = QtWidgets.QGroupBox(self.centralwidget)
        self.psoParams.setGeometry(QtCore.QRect(650, 240, 161, 110))
        self.psoParams.setObjectName("psoParams")
        self.psoParams.setTitle("PSO parameters")

        self.label6 = QtWidgets.QLabel(self.psoParams)
        self.label6.setGeometry(QtCore.QRect(10, 20, 61, 16))
        self.label6.setObjectName("label6")
        self.label6.setText("Inertia factor:")

        self.label7 = QtWidgets.QLabel(self.psoParams)
        self.label7.setGeometry(QtCore.QRect(10, 50, 91, 16))
        self.label7.setObjectName("label7")
        self.label7.setText("Personal factor:")

        self.label8 = QtWidgets.QLabel(self.psoParams)
        self.label8.setGeometry(QtCore.QRect(10, 80, 81, 16))
        self.label8.setObjectName("label8")
        self.label8.setText("Social factor:")

        self.tbxInertia = QtWidgets.QLineEdit(self.psoParams)
        self.tbxInertia.setGeometry(QtCore.QRect(100, 20, 51, 20))
        self.tbxInertia.setObjectName("tbxInertia")

        self.tbxPersonal = QtWidgets.QLineEdit(self.psoParams)
        self.tbxPersonal.setGeometry(QtCore.QRect(100, 50, 51, 20))
        self.tbxPersonal.setObjectName("tbxPersonal")

        self.tbxSocial = QtWidgets.QLineEdit(self.psoParams)
        self.tbxSocial.setGeometry(QtCore.QRect(100, 80, 51, 20))
        self.tbxSocial.setObjectName("tbxSocial")

        self.cbxNoVis = QtWidgets.QCheckBox(self.centralwidget)
        self.cbxNoVis.setGeometry(QtCore.QRect(650, 350, 170, 17))
        self.cbxNoVis.setObjectName("cbxNoVis")
        self.cbxNoVis.setText("No visualization per generation")

        self.btnStartGA = QtWidgets.QPushButton(self.centralwidget)
        self.btnStartGA.setGeometry(QtCore.QRect(650, 370, 75, 23))
        self.btnStartGA.setObjectName("btnStartGA")
        self.btnStartGA.setText("Start GA")

        self.btnStartPSO = QtWidgets.QPushButton(self.centralwidget)
        self.btnStartPSO.setGeometry(QtCore.QRect(650, 400, 75, 23))
        self.btnStartPSO.setObjectName("btnStartPSO")
        self.btnStartPSO.setText("Start PSO")

        self.btnStop = QtWidgets.QPushButton(self.centralwidget)
        self.btnStop.setEnabled(False)
        self.btnStop.setGeometry(QtCore.QRect(740, 370, 75, 53))
        self.btnStop.setObjectName("btnStop")
        self.btnStop.setText("Stop")

        self.btnSaveChart = QtWidgets.QPushButton(self.centralwidget)
        self.btnSaveChart.setGeometry(QtCore.QRect(650, 450, 121, 41))
        self.btnSaveChart.setObjectName("btnSaveChart")
        self.btnSaveChart.setText("Save chart as image")

        self.btnSaveChartSeries = QtWidgets.QPushButton(self.centralwidget)
        self.btnSaveChartSeries.setGeometry(QtCore.QRect(650, 500, 121, 41))
        self.btnSaveChartSeries.setObjectName("btnSaveChartSeries")
        self.btnSaveChartSeries.setText("Save chart as series")

        self.setCentralWidget(self.centralwidget)
        QtCore.QMetaObject.connectSlotsByName(self)

        #Connect events
        self.btnStartGA.clicked.connect(self.btnStartGA_Click)
        self.btnStartPSO.clicked.connect(self.btnStartPSO_Click)
        self.btnStop.clicked.connect(self.btnStop_Click)
        self.btnSaveChart.clicked.connect(self.btnSaveChart_CLick)
        self.btnSaveChartSeries.clicked.connect(self.btnSaveChartSeries_Click)

        #Set default variables
        self.tbxGenerations.insert(str(NGEN))
        self.tbxPopulation.insert(str(POP_SIZE))
        self.tbxDimensions.insert(str(NO_DIMS))
        self.tbxMutation.insert(str(GA_MUTPB))
        self.tbxElite.insert(str(GA_NELT))
        self.tbxMaxAbs.insert(str(GA_MAX_ABS))
        self.tbxInertia.insert(str(PSO_INERTIA))
        self.tbxPersonal.insert(str(PSO_PERSONAL))
        self.tbxSocial.insert(str(PSO_SOCIAL))

    def btnStartGA_Click(self):

        global combination_series  # List of lists containing min_series of 5   results -- Added by Denis Lazor
        global parameter_name  # Name of parameter used for writing its data to .csv file -- Added by Denis Lazor
        global best_fit_values  # List containing best fitness values for every of 5 experiments per combination -- Added by Denis Lazor

        global DIM_SIZES
        global ELITE_SIZES
        global MAX_ABS_SIZES
        global MUTATION_SIZES

        # Checking if files are empty or not -- Added by Denis Lazor
        csv_contains_ga = os.stat("graphs_csv/original_ga.csv").st_size != 0

        # Clearing non empty files if we are trying to write to them -- Added by Denis Lazor
        if csv_contains_ga:
            clear_all_csv("ga")

        parameter_name = "original"
        n = 5000
        print("GA:\n")

        # Automation for all necessary combinations -- Added by Denis Lazor
        for d in DIM_SIZES:
            MUTATION_SIZES = [0.05, 0.1, 0.2]
            ELITE_SIZES = [4, 8, 16]
            MAX_ABS_SIZES = [0.4]

            for m in MUTATION_SIZES:
                for e in ELITE_SIZES:
                    for ma in MAX_ABS_SIZES:

                        for i in range(5):
                            # Set global variables
                            global stop_evolution
                            global q_min_series
                            global q_max_series
                            global q_avg_series
                            stop_evolution = False
                            q_min_series.clear()
                            q_max_series.clear()
                            q_avg_series.clear()

                            # Set global variables from information on UI
                            global NGEN
                            global POP_SIZE
                            global GA_MUTPB
                            global GA_NELT
                            global GA_MAX_ABS
                            NGEN = int(self.tbxGenerations.text())
                            POP_SIZE = int(self.tbxPopulation.text())
                            GA_MUTPB = m
                            GA_NELT = e
                            GA_MAX_ABS = ma

                            ####Initialize deap GA objects####

                            # Make creator that minimize. If it would be 1.0 instead od -1.0 than it would be maxmize
                            self.creator = creator
                            self.creator.create("FitnessMin",
                                                base.Fitness,
                                                weights=(-1.0, ))

                            # Create an individual (a blueprint for cromosomes) as a list with a specified fitness type
                            self.creator.create(
                                "Individual",
                                list,
                                fitness=self.creator.FitnessMin)

                            # Create base toolbox for finishing creation of a individual (cromosome)
                            self.toolbox = base.Toolbox()

                            # Define what type of data (number, gene) will it be in the cromosome
                            self.toolbox.register("attr_float", random.uniform,
                                                  F_MIN, F_MAX)
                            # Initialization procedure (initRepeat) for the cromosome. For the individual to be completed we need to run initRepeat for the amaout of genes the cromosome includes
                            self.toolbox.register("individual",
                                                  tools.initRepeat,
                                                  self.creator.Individual,
                                                  self.toolbox.attr_float,
                                                  n=NO_DIMS)

                            # Create a population of individuals (cromosomes). The population is then created by toolbox.population(n=300) where 'n' is the number of cromosomes in population
                            self.toolbox.register("population",
                                                  tools.initRepeat, list,
                                                  self.toolbox.individual)

                            # Register evaluation function
                            self.toolbox.register("evaluate", evaluateInd)

                            # Register what genetic operators to use
                            # Standard coding
                            self.toolbox.register(
                                "mate", tools.cxTwoPoint
                            )  # Use two point recombination
                            self.toolbox.register("mutate",
                                                  tools.mutGaussian,
                                                  mu=0,
                                                  sigma=GA_MAX_ABS,
                                                  indpb=0.5)

                            self.toolbox.register(
                                "select", tools.selTournament,
                                tournsize=3)  # Use tournament selection

                            ##################################

                            # Generate initial poplation. Will be a member variable so we can easely pass everything to new thread
                            self.pop = self.toolbox.population(n=POP_SIZE)

                            # Evaluate initial population, we map() the evaluation function to every individual and then assign their respective fitness, map runs evaluate function for each individual in pop
                            fitnesses = list(
                                map(self.toolbox.evaluate, self.pop))
                            for ind, fit in zip(self.pop, fitnesses):
                                ind.fitness.values = fit  # Assign calcualted fitness value to individuals

                            # Extracting all the fitnesses of all individuals in a population so we can monitor and evovlve the algorithm until it reaches 0 or max number of generation is reached
                            self.fits = [
                                ind.fitness.values[0] for ind in self.pop
                            ]

                            # Disable start and enable stop
                            self.btnStartGA.setEnabled(False)
                            self.btnStartPSO.setEnabled(False)
                            self.btnStop.setEnabled(False)
                            self.genParams.setEnabled(False)
                            self.gaParams.setEnabled(False)
                            self.psoParams.setEnabled(False)
                            self.cbxNoVis.setEnabled(False)

                            # Start evolution
                            self.evolveGA()

                        # Best fitness value -- Added by Denis Lazor

                        best_fit = np.array(min(best_fit_values))[0]
                        mean_fit = np.array(
                            min(best_fit_values,
                                key=lambda x: abs(x - statistics.mean(
                                    np.asarray(best_fit_values).flatten())))
                        )[0]

                        # Index of best fitness value -- Added by Denis Lazor
                        mean_fit_idx = best_fit_values.index(mean_fit)

                        write_to_file(combination_series[mean_fit_idx],
                                      parameter_name, "ga")

                        # First name will be "original", second one "max_abs" -- Added by Denis Lazor
                        parameter_name = "max_abs"

                        print_results_GA(POP_SIZE, m, e, ma, mean_fit,
                                         best_fit, NGEN, d)

                        # Clearing past lists  -- Added by Denis Lazor
                        combination_series = []
                        best_fit_values = []

                    # Reducing number of combinations and changing .csv file for writing -- Added by Denis Lazor
                    MAX_ABS_SIZES = MAX_ABS_SIZES[0:1]
                    parameter_name = "elites"

                ELITE_SIZES = ELITE_SIZES[0:1]
                parameter_name = "mutation"

            MUTATION_SIZES = MUTATION_SIZES[0:1]
            parameter_name = "original"

    def btnStartPSO_Click(self):
        global combination_series  # List of lists containing min_series of 5   results -- Added by Denis Lazor
        global parameter_name  # Name of parameter used for writing its data to .csv file -- Added by Denis Lazor
        global best_fit_values  # List containing best fitness values for every of 5 experiments per combination -- Added by Denis Lazor

        global DIM_SIZES
        global INERTIA_SIZES
        global PERSONAL_F_SIZES
        global SOCIAL_F_SIZES

        # Checking if files are empty or not -- Added by Denis Lazor
        csv_contains_pso = os.stat("graphs_csv/original_pso.csv").st_size != 0

        # Clearing non empty files if we are trying to write to them -- Added by Denis Lazor
        if csv_contains_pso:
            clear_all_csv("pso")

        n = 5000
        parameter_name = "original"
        print("PSO:\n")

        # Automation for all necessary combinations -- Added by Denis Lazor
        for d in DIM_SIZES:
            INERTIA_SIZES = [0.0, 0.37, 0.74]
            PERSONAL_F_SIZES = [0.5, 1.0, 1.5]
            SOCIAL_F_SIZES = [0.5, 1.0, 1.5]

            for in_f in INERTIA_SIZES:
                for pers_f in PERSONAL_F_SIZES:
                    for soc_f in SOCIAL_F_SIZES:

                        for i in range(5):
                            # Set global variables
                            global stop_evolution
                            global q_min_series
                            global q_max_series

                            global q_avg_series
                            stop_evolution = False
                            q_min_series.clear()
                            q_max_series.clear()
                            q_avg_series.clear()

                            # Set global variables from information on UI
                            global NGEN
                            global POP_SIZE
                            global PSO_INERTIA
                            global PSO_PERSONAL
                            global PSO_SOCIAL
                            NGEN = int(self.tbxGenerations.text())
                            POP_SIZE = int(self.tbxPopulation.text())
                            PSO_INERTIA = in_f
                            PSO_PERSONAL = pers_f
                            PSO_SOCIAL = soc_f

                            ####Initialize deap PSO objects####

                            # Make creator that minimize. If it would be 1.0 instead od -1.0 than it would be maxmize
                            self.creator = creator
                            self.creator.create("FitnessMin",
                                                base.Fitness,
                                                weights=(-1.0, ))

                            # Create an individual (a blueprint for cromosomes) as a list with a specified fitness type
                            self.creator.create(
                                "Particle",
                                list,
                                fitness=self.creator.FitnessMin,
                                speed=list,
                                best=None)

                            # Create base toolbox for finishing creation of a individual (particle) and population
                            self.toolbox = base.Toolbox()

                            # Particle initialization
                            self.toolbox.register("particle",
                                                  generateParticle,
                                                  cr=self.creator,
                                                  size=NO_DIMS,
                                                  min_val=F_MIN,
                                                  max_val=F_MAX)

                            # Create a population of individuals (particles). The population is then created by e.g. toolbox.population(n=300) where 'n' is the number of particles in population
                            self.toolbox.register("population",
                                                  tools.initRepeat, list,
                                                  self.toolbox.particle)

                            # Update function for each particle
                            self.toolbox.register("update", updateParticle)

                            # Evaluation function for each particle
                            self.toolbox.register("evaluate", evaluateInd)

                            ##################################

                            # Create population
                            self.pop = self.toolbox.population(n=POP_SIZE)

                            # Evaluate initial population, we map() the evaluation function to every individual and then assign their respective fitness, map runs emaluet function for each individual in pop
                            fitnesses = list(
                                map(self.toolbox.evaluate, self.pop))
                            for ind, fit in zip(self.pop, fitnesses):
                                ind.fitness.values = fit

                            # Extracting all the fitnesses of all individuals in a population so we can monitor and evovlve the algorithm until it reaches 0 or max number of generation is reached
                            self.fits = [
                                ind.fitness.values[0] for ind in self.pop
                            ]

                            # Extraction current best position
                            self.global_best_position = tools.selBest(
                                self.pop, 1)[0][:]

                            # Disable start and enable stop
                            self.btnStartGA.setEnabled(False)
                            self.btnStartPSO.setEnabled(False)
                            self.btnStop.setEnabled(False)
                            self.genParams.setEnabled(False)
                            self.gaParams.setEnabled(False)
                            self.psoParams.setEnabled(False)
                            self.cbxNoVis.setEnabled(False)

                            # Start evolution
                            self.evolvePSO()

                        # Best fitness value -- Added by Denis Lazor
                        best_fit = np.array(min(best_fit_values))[0]
                        mean_fit = np.array(
                            min(best_fit_values,
                                key=lambda x: abs(x - statistics.mean(
                                    np.asarray(best_fit_values).flatten())))
                        )[0]

                        # Index of best fitness value -- Added by Denis Lazor
                        mean_fit_idx = best_fit_values.index(mean_fit)

                        write_to_file(combination_series[mean_fit_idx],
                                      parameter_name, "pso")

                        # First name will be "original", second one "social_factor" -- Added by Denis Lazor
                        parameter_name = "social_factor"

                        print_results_PSO(POP_SIZE, in_f, pers_f, soc_f,
                                          mean_fit, best_fit, NGEN, d)

                        # Clearing past lists  -- Added by Denis Lazor
                        print(best_fit_values)
                        combination_series = []
                        best_fit_values = []

                    # Reducing number of combinations and changing .csv file for writing -- Added by Denis Lazor
                    SOCIAL_F_SIZES = SOCIAL_F_SIZES[0:1]
                    parameter_name = "personal_factor"

                PERSONAL_F_SIZES = PERSONAL_F_SIZES[0:1]
                parameter_name = "inertia"

            INERTIA_SIZES = INERTIA_SIZES[0:1]
            parameter_name = "original"

    def btnStop_Click(self):
        global stop_evolution
        stop_evolution = True
        #Disable stop and enable start
        self.btnStartGA.setEnabled(True)
        self.btnStartPSO.setEnabled(True)
        self.btnStop.setEnabled(False)
        self.genParams.setEnabled(True)
        self.gaParams.setEnabled(True)
        self.psoParams.setEnabled(True)
        self.cbxNoVis.setEnabled(True)

    #Function for GA evolution
    def evolveGA(self):
        global q_min_series
        global q_max_series
        global q_avg_series

        global combination_series
        global best_fit_values

        combination_current_series = [
        ]  # Clearing fitness values series -- Added by Denis Lazor

        # Variable for keeping track of the number of generations
        curr_g = 0

        # Begin the evolution till goal is reached or max number of generation is reached
        while min(self.fits) != 0 and curr_g < NGEN:
            #Check if evolution and thread need to stop
            if stop_evolution:
                break  #Break the evolution loop

            # A new generation
            curr_g = curr_g + 1
            # print("-- Generation %i --" % curr_g)

            # Select the next generation individuals
            #Select POP_SIZE - NELT number of individuals. Since recombination is between neigbours, not two naighbours should be the clone of the same individual
            offspring = []
            offspring.append(self.toolbox.select(
                self.pop, 1)[0])  #add first selected individual
            for i in range(
                    POP_SIZE - GA_NELT - 1
            ):  # -1 because the first seleceted individual is already added
                while True:
                    new_o = self.toolbox.select(self.pop, 1)[0]
                    if new_o != offspring[len(
                            offspring
                    ) - 1]:  #if it is different than the last inserted then add to offspring and break
                        offspring.append(new_o)
                        break

            # Clone the selected individuals because all of the changes are inplace
            offspring = list(map(self.toolbox.clone, offspring))

            # Apply crossover on the selected offspring
            for child1, child2 in zip(offspring[::2], offspring[1::2]):
                self.toolbox.mate(child1, child2)  #inplace recombination
                #Invalidate new children fitness values
                del child1.fitness.values
                del child2.fitness.values

            #Apply mutation on the offspring
            for mutant in offspring:
                if random.random() < GA_MUTPB:
                    self.toolbox.mutate(mutant)
                    del mutant.fitness.values

            #Add elite individuals #Is clonning needed?
            offspring.extend(
                list(map(self.toolbox.clone, tools.selBest(self.pop,
                                                           GA_NELT))))

            # Evaluate the individuals with an invalid fitness
            invalid_ind = [ind for ind in offspring if not ind.fitness.valid]
            fitnesses = map(self.toolbox.evaluate, invalid_ind)
            for ind, fit in zip(invalid_ind, fitnesses):
                ind.fitness.values = fit

            # print("  Evaluated %i individuals" % len(invalid_ind))

            #Replace population with offspring
            self.pop[:] = offspring

            # Gather all the fitnesses in one list and print the stats
            self.fits = [ind.fitness.values[0] for ind in self.pop]

            length = len(self.pop)
            mean = sum(self.fits) / length
            sum2 = sum(x * x for x in self.fits)
            std = abs(sum2 / length - mean**2)**0.5

            q_min_series.append(curr_g, min(self.fits))
            q_max_series.append(curr_g, max(self.fits))
            q_avg_series.append(curr_g, mean)

            combination_current_series.append(
                min(self.fits)
            )  # Saving min_series fitness values of an experiment -- Added by Denis Lazor

            # print("  Min %s" % q_min_series.at(q_min_series.count()-1).y())
            # print("  Max %s" % q_max_series.at(q_max_series.count()-1).y())
            # print("  Avg %s" % mean)
            # print("  Std %s" % std)
            #
            if self.cbxNoVis.isChecked():
                app.processEvents()
            else:
                self.chart = QChart()
                self.chart.addSeries(q_min_series)
                self.chart.addSeries(q_max_series)
                self.chart.addSeries(q_avg_series)
                self.chart.setTitle("Fitness value over time")
                self.chart.setAnimationOptions(QChart.NoAnimation)
                self.chart.createDefaultAxes()
                self.frameChart.setChart(self.chart)
                self.frameChart.repaint()
                app.processEvents()

        #Printing best individual
        best_ind = tools.selBest(self.pop, 1)[0]
        # print("Best individual is %s, %s" % (best_ind, best_ind.fitness.values))

        #Visulaize final solution
        if self.cbxNoVis.isChecked():
            self.chart = QChart()
            self.chart.addSeries(q_min_series)
            self.chart.addSeries(q_max_series)
            self.chart.addSeries(q_avg_series)
            self.chart.setTitle("Fitness value over time")
            self.chart.setAnimationOptions(QChart.NoAnimation)
            self.chart.createDefaultAxes()
            self.frameChart.setChart(self.chart)
            self.frameChart.repaint()

        #Disable stop and enable start
        self.btnStartGA.setEnabled(True)
        self.btnStartPSO.setEnabled(True)
        self.btnStop.setEnabled(False)
        self.genParams.setEnabled(True)
        self.gaParams.setEnabled(True)
        self.psoParams.setEnabled(True)
        self.cbxNoVis.setEnabled(True)
        app.processEvents()

        combination_series.append(combination_current_series
                                  )  # Saving 5 results -- Added by Denis Lazor
        best_fit_values.append(
            best_ind.fitness.values
        )  # Adding best fitness value of experiment -- Added by Denis Lazor

    #Function for GA evolution
    def evolvePSO(self):
        global q_min_series
        global q_max_series
        global q_avg_series

        global combination_series
        global best_fit_values

        combination_current_series = [
        ]  # Clearing fitness values series -- Added by Denis Lazor

        # Variable for keeping track of the number of generations
        curr_g = 0

        while min(self.fits) != 0.0 and curr_g < NGEN:
            #Check if evolution and thread need to stop
            if stop_evolution:
                break  #Break the evolution loop

            # A new generation
            curr_g = curr_g + 1
            # print("-- Generation %i --" % curr_g)

            #Update particle position and evaluate particle
            for particle in self.pop:
                #Update
                self.toolbox.update(particle, self.global_best_position,
                                    PSO_INERTIA, PSO_PERSONAL, PSO_SOCIAL)
                #Evaluate
                fit = self.toolbox.evaluate(particle)
                #Update best position
                if fit[0] < particle.fitness.values[0]:
                    particle.best = particle[:]
                #Update fitness
                particle.fitness.values = fit

            #Extracting all the fitnesses of all individuals in a population so we can monitor and evovlve the algorithm until it reaches 0 or max number of generation is reached
            self.fits = [ind.fitness.values[0] for ind in self.pop]

            #Extraction current best position
            self.global_best_position = tools.selBest(self.pop, 1)[0][:]

            #Stats
            length = len(self.pop)
            mean = sum(self.fits) / length
            sum2 = sum(x * x for x in self.fits)
            std = abs(sum2 / length - mean**2)**0.5

            q_min_series.append(curr_g, min(self.fits))
            q_max_series.append(curr_g, max(self.fits))
            q_avg_series.append(curr_g, mean)

            combination_current_series.append(
                min(self.fits)
            )  # Saving min_series fitness values of an experiment -- Added by Denis Lazor

            # print("  Min %s" % q_min_series.at(q_min_series.count()-1).y())
            # print("  Max %s" % q_max_series.at(q_max_series.count()-1).y())
            # print("  Avg %s" % mean)
            # print("  Std %s" % std)
            #
            if self.cbxNoVis.isChecked():
                app.processEvents()
            else:
                self.chart = QChart()
                self.chart.addSeries(q_min_series)
                self.chart.addSeries(q_max_series)
                self.chart.addSeries(q_avg_series)
                self.chart.setTitle("Fitness value over time")
                self.chart.setAnimationOptions(QChart.NoAnimation)
                self.chart.createDefaultAxes()
                self.frameChart.setChart(self.chart)
                self.frameChart.repaint()
                app.processEvents()

        #Printing best individual
        best_ind = tools.selBest(self.pop, 1)[0]
        # print("Best individual is %s, %s" % (best_ind, best_ind.fitness.values))

        #Visulaize final solution
        if self.cbxNoVis.isChecked():
            self.chart = QChart()
            self.chart.addSeries(q_min_series)
            self.chart.addSeries(q_max_series)
            self.chart.addSeries(q_avg_series)
            self.chart.setTitle("Fitness value over time")
            self.chart.setAnimationOptions(QChart.NoAnimation)
            self.chart.createDefaultAxes()
            self.frameChart.setChart(self.chart)
            self.frameChart.repaint()

        #Disable stop and enable start
        self.btnStartGA.setEnabled(True)
        self.btnStartPSO.setEnabled(True)
        self.btnStop.setEnabled(False)
        self.genParams.setEnabled(True)
        self.gaParams.setEnabled(True)
        self.psoParams.setEnabled(True)
        self.cbxNoVis.setEnabled(True)
        app.processEvents()

        combination_series.append(combination_current_series
                                  )  # Saving 5 results -- Added by Denis Lazor
        best_fit_values.append(
            best_ind.fitness.values
        )  # Adding best fitness value of experiment -- Added by Denis Lazor

    def btnSaveChart_CLick(self):
        p = self.frameChart.grab()
        filename, _ = QFileDialog.getSaveFileName(
            None, "Save series chart as a image", "", "Image Files (*.png)")
        p.save(filename, "PNG")
        print("Chart series image saved to: ", filename)

    def btnSaveChartSeries_Click(self):
        global q_min_series
        global q_max_series
        global q_avg_series
        filename, _ = QFileDialog.getSaveFileName(None,
                                                  "Save series to text file",
                                                  "",
                                                  "Text Files (*.txt, *.csv)")
        with open(filename, 'w') as dat:
            for i in range(q_min_series.count()):
                dat.write('%f,%f,%f\n' %
                          (q_min_series.at(i).y(), q_avg_series.at(i).y(),
                           q_max_series.at(i).y()))
        print("Chart series saved to: ", filename)
Beispiel #18
0
class MainChartWidget(QDialog):

    # w_type_charts = None
    # w_chart_line = None
    # w_chart_pie = None
    # w_chart_bar = None
    # w_chart = None
    #
    # v_layout_main = None
    # h_layout_middle = None
    #
    # selector = None

    signal_confirm_chart = pyqtSignal(QChart)

    def __init__(self):
        super(MainChartWidget, self).__init__()

        self.w_type_charts = None
        self.w_chart_line = None
        self.w_chart_pie = None
        self.w_chart_bar = None
        self.w_chart = None

        self.v_layout_main = None
        self.h_layout_middle = None

        self.selector = None
        self.init_ui()

    def init_ui(self):
        self.setFixedSize(700, 600)
        self.assemble()
        self.set_styles()
        self.aux = QPoint(200, 300)
        self.setWindowFlags(Qt.FramelessWindowHint)
        # self.setAttribute(Qt.WA_TranslucentBackground)

    def mousePressEvent(self, event):
        self.oldPos = event.globalPos()
        self._from_x = event.pos().x()
        self._from_y = event.pos().y()
        # self.start = event.pos()

    def mouseMoveEvent(self, event):
        delta = QPoint(event.globalPos() - self.oldPos)
        self.aux = QPoint(self.x() + delta.x(), self.y() + delta.y())
        self.move(self.aux)
        self.oldPos = event.globalPos()

        self._to_x = event.pos().x()
        self._to_y = event.pos().y()

        self.global_pos = event.globalPos()

        self._from_x = self._to_x
        self._from_y = self._to_y

    def set_styles(self):
        self.setStyleSheet("""
        MainChartWidget{
            border-radius: 4px;
            background:rgb(37,43,52,220);
            color: white;
        }
        QScrollArea{
                background-color:transparent;
                border-radius: 4px;
                border: 0px solid ;
                border-color: rgb(0,0,0,100)
            }

            QScrollBar:vertical{
                border:1px solid;
                border-color: rgb(197,197,199,100);
                width: 7px;
                margin: 0px 0px 0px 0px;
                background: rgb(234,234,234,100);

            }

            QScrollBar::handle:vertical  {
                background: rgba(14,65,148,100);
            }

            QScrollBar::add-line:vertical{
                height: 0px;
            }

            QScrollBar::sub-line:vertical{
                height: 0px;
            }
        """)

    def assemble(self):

        self.w_type_charts = TopBar(self)
        self.w_type_charts.signal_send_chart_selected.connect(
            self.set_chart_type)
        self.w_type_charts.setMinimumSize(650, 50)
        self.w_type_charts.setMaximumHeight(50)

        self.w_chart_line = LeftBarLineChart(self)
        self.w_chart_line.setMinimumSize(200, 300)
        self.w_chart_line.setMaximumWidth(200)

        self.w_chart_pie = LeftBarPieChart(self)
        self.w_chart_pie.hide()
        self.w_chart_pie.setMinimumSize(200, 300)
        self.w_chart_pie.setMaximumWidth(200)

        self.w_chart_bar = LeftBarBarChart(self)
        self.w_chart_bar.hide()
        self.w_chart_bar.setMinimumSize(200, 300)
        self.w_chart_bar.setMaximumWidth(200)

        self.w_chart = QChartView()
        self.w_chart.setChart(self.w_chart_line.chart)
        self.w_chart.setMinimumSize(400, 300)

        self.v_layout_main = QVBoxLayout()
        self.v_layout_main.setContentsMargins(20, 20, 20, 20)
        self.h_layout_middle = QHBoxLayout()
        self.v_layout_main.addWidget(self.w_type_charts)
        self.v_layout_main.addLayout(self.h_layout_middle)
        self.h_layout_middle.addWidget(self.w_chart_line)
        self.h_layout_middle.addWidget(self.w_chart_pie)
        self.h_layout_middle.addWidget(self.w_chart_bar)
        self.h_layout_middle.addWidget(self.w_chart)

        self.setLayout(self.v_layout_main)
        self.w_type_charts.btn_chart_line_clicked()

    @pyqtSlot(int)
    def set_chart_type(self, type):
        self.w_chart_line.hide()
        self.w_chart_pie.hide()
        self.w_chart_bar.hide()
        self.selector = type
        if type == EChart.LINE:
            self.w_chart_line.show()
            self.w_chart.setChart(self.w_chart_line.chart)
        elif type == EChart.PIE:
            self.w_chart_pie.show()
            self.w_chart.setChart(self.w_chart_pie.chart)
        elif type == EChart.BAR:
            self.w_chart_bar.show()
            self.w_chart.setChart(self.w_chart_bar.chart)

    def confirm_chart(self):
        self.signal_confirm_chart.emit(self.w_chart.chart())
        # KEYBOARD.close()

    def hide(self):
        # KEYBOARD.close()
        super(MainChartWidget, self).hide()
Beispiel #19
0
class Chart(QWidget):
    def __init__(self, ch0Name='ch0', ch1Name='ch1', ch2Name='ch2', ch3Name='ch3'):
        super(Chart, self).__init__()
        self.ch0Name = ch0Name
        self.ch1Name = ch1Name
        self.ch2Name = ch2Name
        self.ch3Name = ch3Name
        self.data = []
        self.initUI()

    def initUI(self):
        vbox = QVBoxLayout()
        vbox.addWidget(self.chartUI())
        vbox.addWidget(self.controlUI())

        self.setLayout(vbox)

    def chartUI(self):
        self.chart1 = QLineSeries()
        self.chart1.setName(self.ch0Name)
        self.chart1.setPen(QPen(Qt.red))
        self.chart2 = QLineSeries()
        self.chart2.setName(self.ch1Name)
        self.chart2.setPen(QPen(Qt.darkYellow))
        self.chart3 = QLineSeries()
        self.chart3.setName(self.ch2Name)
        self.chart3.setPen(QPen(Qt.green))
        self.chart4 = QLineSeries()
        self.chart4.setName(self.ch3Name)
        self.chart4.setPen(QPen(Qt.blue))

        self.chart = QChart()
        self.chart.addSeries(self.chart1)
        self.chart.addSeries(self.chart2)
        self.chart.addSeries(self.chart3)
        self.chart.addSeries(self.chart4)
        self.chart.setAnimationOptions(QChart.AllAnimations)
        self.chart.setTitle("laser data")

        self.axis_x = QValueAxis()
        self.axis_y = QValueAxis()
        self.axis_x.setTickCount(10)
        self.axis_y.setTickCount(10)
        self.axis_x.setLabelFormat('%d')
        self.axis_y.setLabelFormat('%d')

        self.axis_x.setRange(0, 1000)
        self.axis_y.setRange(100, 300)
        self.chart.setAxisX(self.axis_x, self.chart1)
        self.chart.setAxisY(self.axis_y, self.chart1)
        self.chart.setAxisX(self.axis_x, self.chart2)
        self.chart.setAxisY(self.axis_y, self.chart2)
        self.chart.setAxisX(self.axis_x, self.chart3)
        self.chart.setAxisY(self.axis_y, self.chart3)
        self.chart.setAxisX(self.axis_x, self.chart4)
        self.chart.setAxisY(self.axis_y, self.chart4)

        self.chartView = QChartView()
        self.chartView.setChart(self.chart)
        self.chartView.setRubberBand(QChartView.RectangleRubberBand)
        self.chartView.setRenderHint(QPainter.Antialiasing)

        return self.chartView

    def controlUI(self):
        self.autoRefreshCb = QCheckBox('自动刷新')
        self.autoRefreshCb.setChecked(True)
        self.ch0Enable = QCheckBox(self.ch0Name)
        self.ch1Enable = QCheckBox(self.ch1Name)
        self.ch2Enable = QCheckBox(self.ch2Name)
        self.ch3Enable = QCheckBox(self.ch3Name)
        self.ch0Enable.setChecked(True)
        self.ch1Enable.setChecked(True)
        self.ch2Enable.setChecked(True)
        self.ch3Enable.setChecked(True)
        hbox1 = QHBoxLayout()
        hbox1.addWidget(self.autoRefreshCb)
        hbox1.addWidget(self.ch0Enable)
        hbox1.addWidget(self.ch1Enable)
        hbox1.addWidget(self.ch2Enable)
        hbox1.addWidget(self.ch3Enable)

        self.xDataMinLabel = QLabel('x min:')
        self.xDataMaxLabel = QLabel('x max:')
        self.yDataMinLabel = QLabel('y min:')
        self.yDataMaxLabel = QLabel('y max:')

        self.xDataMinLine = QLineEdit()
        self.xDataMaxLine = QLineEdit()
        self.yDataMinLine = QLineEdit()
        self.yDataMaxLine = QLineEdit()
        self.setBtn = QPushButton('设置')

        hbox = QHBoxLayout()
        hbox.addWidget(self.xDataMinLabel)
        hbox.addWidget(self.xDataMinLine)
        hbox.addWidget(self.xDataMaxLabel)
        hbox.addWidget(self.xDataMaxLine)
        hbox.addWidget(self.yDataMinLabel)
        hbox.addWidget(self.yDataMinLine)
        hbox.addWidget(self.yDataMaxLabel)
        hbox.addWidget(self.yDataMaxLine)
        hbox.addWidget(self.setBtn)

        mainLayout = QVBoxLayout()
        mainLayout.addLayout(hbox1)
        mainLayout.addLayout(hbox)
        frame = QFrame()
        frame.setLayout(mainLayout)

        self.setBtn.clicked.connect(self.setAxisRange)
        self.ch0Enable.clicked.connect(self.changeCh)
        self.ch1Enable.clicked.connect(self.changeCh)
        self.ch2Enable.clicked.connect(self.changeCh)
        self.ch3Enable.clicked.connect(self.changeCh)
        return frame

    # @timethis
    def update(self):
        x0Data, y0Data, x1Data, y1Data, x2Data, y2Data, x3Data, y3Data = self.data
        self.chart1.clear()
        self.chart2.clear()
        self.chart3.clear()
        self.chart4.clear()
        try:
            for i in range(0, len(x0Data)):
                if self.ch0Enable.isChecked():
                    self.chart1.append(QPoint(x0Data[i], y0Data[i]))
            for i in range(0, len(x1Data)):
                if self.ch1Enable.isChecked():
                    self.chart2.append(QPoint(x1Data[i], y1Data[i]))
            for i in range(0, len(x2Data)):
                if self.ch2Enable.isChecked():
                    self.chart3.append(QPoint(x2Data[i], y2Data[i]))
            for i in range(0, len(x3Data)):
                if self.ch3Enable.isChecked():
                    self.chart4.append(QPoint(x3Data[i], y3Data[i]))
        except:
            logging.debug('y0Data is %s' % y0Data)
            logging.debug('y1Data is %s' % y1Data)
            logging.debug('y2Data is %s' % y2Data)
            logging.debug('y3Data is %s' % y3Data)
            self.chart1.clear()
            self.chart2.clear()
            self.chart3.clear()
            self.chart4.clear()
        # self.chartView.update()

        if self.autoRefreshCb.isChecked():
            self.fillAxisRange()
            self.setAxisRange()

    def fillAxisRange(self):
        x0Data, y0Data, x1Data, y1Data, x2Data, y2Data, x3Data, y3Data = self.data
        tmp = [min(x0Data), min(x1Data), min(x2Data), min(x3Data)]
        xDataMin = min(tmp)
        tmp = [max(x0Data), max(x1Data), max(x2Data), max(x3Data)]
        xDataMax = max(tmp)
        tmp = [min(y0Data), min(y1Data), min(y2Data), min(y3Data)]
        yDataMin = min(tmp)
        tmp = [max(y0Data), max(y1Data), max(y2Data), max(y3Data)]
        yDataMax = max(tmp)

        xDataAvr = (xDataMin + xDataMax) // 2
        yDataAvr = (yDataMin + yDataMax) // 2

        self.xDataMinLine.setText(str(xDataAvr - xDataAvr*6//5))
        self.xDataMaxLine.setText(str(xDataAvr + xDataAvr*6//5))
        self.yDataMinLine.setText(str(yDataAvr - yDataAvr*6//5))
        self.yDataMaxLine.setText(str(yDataAvr + yDataAvr*6//5))

    @pyqtSlot()
    def setAxisRange(self):
        if self.xDataMinLine.text() and self.xDataMaxLine.text() and \
            self.yDataMinLine.text() and self.yDataMaxLine.text():
            self.axis_x.setRange(int(self.xDataMinLine.text()), int(self.xDataMaxLine.text()))
            self.axis_y.setRange(int(self.yDataMinLine.text()), int(self.yDataMaxLine.text()))
        else:
            QMessageBox.warning(self, '警告', '缺少参数')

    @pyqtSlot()
    def changeCh(self):

        self.chart1.clear()
        self.chart2.clear()
        self.chart3.clear()
        self.chart4.clear()
        x0Data, y0Data, x1Data, y1Data, x2Data, y2Data, x3Data, y3Data = self.data

        for i in range(0, len(x0Data)):
            if self.ch0Enable.isChecked():
                self.chart1.append(QPoint(x0Data[i], y0Data[i]))
        for i in range(0, len(x1Data)):
            if self.ch1Enable.isChecked():
                self.chart2.append(QPoint(x1Data[i], y1Data[i]))
        for i in range(0, len(x2Data)):
            if self.ch2Enable.isChecked():
                self.chart3.append(QPoint(x2Data[i], y2Data[i]))
        for i in range(0, len(x3Data)):
            if self.ch3Enable.isChecked():
                self.chart4.append(QPoint(x3Data[i], y3Data[i]))
Beispiel #20
0
class Win(QMainWindow):
    def __init__(self, parent=None):
        super().__init__(parent=parent)
        self.setup_ui()

    def setup_ui(self):
        self.setWindowTitle("Torrent Companion")
        self.resize(1400, 800)
        self.hSplitter = QSplitter()
        self.tree = TreeWidget(parent=self.hSplitter)
        self.hSplitter.addWidget(self.tree)
        self.tables = QWidget(self.hSplitter)
        self.hLayout = QHBoxLayout(self.tables)
        self.tables.setLayout(self.hLayout)
        self.hSplitter.addWidget(self.tables)
        self.vSplitter = QSplitter(parent=self.tables)
        self.vSplitter.setOrientation(Qt.Vertical)
        self.hLayout.addWidget(self.vSplitter)
        self.staticTable = TableView(self.vSplitter)
        self.vSplitter.addWidget(self.staticTable)
        self.tabs = QTabWidget(parent=self.vSplitter)
        self.dataTable = TableView(self.tabs)
        self.tabs.addTab(self.dataTable, "data")
        self.hSplitter.setStretchFactor(1, 4)
        self.vSplitter.addWidget(self.tabs)
        self.vSplitter.setStretchFactor(1, 3)
        self.add_chart_tabs()
        self.setCentralWidget(self.hSplitter)
        self.menubar = MenuBar(parent=self)
        self.setMenuBar(self.menubar)
        statusbar = self.statusBar()
        statusbar.setObjectName(u"statusbar")
        QMetaObject.connectSlotsByName(self)

    def add_chart_tabs(self):
        self.ulChart = QChartView(parent=self.tabs)
        self.ratioChart = QChartView(parent=self.tabs)
        self.lineChart = QChartView(parent=self.tabs)
        self.ulChart.setRenderHint(QPainter.Antialiasing)
        self.ratioChart.setRenderHint(QPainter.Antialiasing)
        self.lineChart.setRenderHint(QPainter.Antialiasing)
        self.tabs.addTab(self.lineChart, "Line Chart")
        self.tabs.addTab(self.ratioChart, "Ratio Chart")
        self.tabs.addTab(self.ulChart, "Uploaded Chart")
        return

    def torrent_charts(self, upload_chart, ratio_chart, line_chart):
        self.ulChart.setChart(upload_chart)
        self.ratioChart.setChart(ratio_chart)
        self.lineChart.setChart(line_chart)
        return

    def open_settings(self):
        settings_menu = SettingsMenu(self, self.session, parent=self)
        settings_menu.show()

    def exit_window(self):
        self.destroy()
        self.session.end_session()

    def assign_session(self, session):
        self.session = session
        self.staticTable.assign(session, self)
        self.dataTable.assign(session, self)
        self.tree.assign(session, self)
        self.menubar.assign(session, self)
Beispiel #21
0
class DataEntryForm(QWidget):
    def __init__(self):
        super().__init__()
        self.items = 0
        self._data = {
            'Phone bill': 50,
            "Gas": 30,
            "Rent": 1850,
            "Car Payment": 420.0
        }

        #=============== left side ======================
        self.table = QTableWidget()
        self.table.setColumnCount(2)
        self.table.setHorizontalHeaderLabels(('Description', 'price'))
        self.table.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch)

        #============== Chart widget =================
        self.chartView = QChartView()
        self.chartView.setRenderHint(QPainter.Antialiasing)

        #=============== layout button and entry ================
        self.layoutRight = QVBoxLayout()
        self.lineEditDescription = QLineEdit()
        self.lineEditPrice = QLineEdit()
        self.buttonAdd = QPushButton("Add")
        self.buttonClear = QPushButton("Clear")
        self.buttonQuit = QPushButton("Quit")
        self.buttonPlot = QPushButton("Plot")

        self.buttonAdd.setEnabled(False)
        # self.buttonAdd.hide()

        self.layoutRight.setSpacing(10)
        self.layoutRight.addWidget(QLabel("Description"))
        self.layoutRight.addWidget(self.lineEditDescription)
        self.layoutRight.addWidget(QLabel("Price"))
        self.layoutRight.addWidget(self.lineEditPrice)
        self.layoutRight.addWidget(self.buttonAdd)
        self.layoutRight.addWidget(self.buttonPlot)
        self.layoutRight.addWidget(self.chartView)
        self.layoutRight.addWidget(self.buttonClear)
        self.layoutRight.addWidget(self.buttonQuit)

        #================= connect function to button =====================
        self.buttonAdd.clicked.connect(self.add_entry)
        self.buttonPlot.clicked.connect(self.graph_chart)
        self.buttonQuit.clicked.connect(lambda: app.quit())

        self.layout = QHBoxLayout()
        self.layout.addWidget(self.table, 50)
        self.layout.addLayout(self.layoutRight,
                              50)  # 50% proportional locaction

        self.setLayout(self.layout)

        self.lineEditDescription.textChanged[str].connect(self.check_disable)
        self.lineEditPrice.textChanged[str].connect(self.check_disable)
        self.fill_table()  # upload data into table

    def fill_table(self, data=None):
        data = self._data
        print(data)

        for desc, price in data.items():
            descItem = QTableWidgetItem(desc)
            priceItem = QTableWidgetItem("${0:.2f}".format(price))
            priceItem.setTextAlignment(Qt.AlignRight | Qt.AlignCenter)

            self.table.insertRow(self.items)
            self.table.setItem(self.items, 0,
                               descItem)  # setItem(row, column, value)
            self.table.setItem(self.items, 1, priceItem)
            self.items += 1

    def add_entry(self):
        desc = self.lineEditDescription.text()
        price = self.lineEditPrice.text()

        try:
            descItem = QTableWidgetItem(desc)
            priceItem = QTableWidgetItem('${0:.2f}'.format(float(price)))
            priceItem.setTextAlignment(Qt.AlignRight | Qt.AlignCenter)

            self.table.insertRow(self.items)
            self.table.setItem(self.items, 0, descItem)
            self.table.setItem(self.items, 1, priceItem)
            self.items += 1

            self.lineEditDescription.setText('')
            self.lineEditPrice.setText('')
        except ValueError:
            pass

    def check_disable(self):
        if self.lineEditDescription.text() and self.lineEditPrice.text():
            self.buttonAdd.setEnabled(True)
        else:
            self.buttonAdd.setEnabled(False)

    def graph_chart(self):
        series = QPieSeries()

        for i in range(self.table.rowCount()):
            text = self.table.item(i, 0).text()
            val = float(self.table.item(i, 1).text().replace('$', ''))
            series.append(text, val)

        chart = QChart()
        chart.addSeries(series)
        chart.legend().setAlignment(Qt.AlignTop)
        self.chartView.setChart(chart)
class MainInterface(QMainWindow):
    '''实现 GUI 以及其连接整个程序的功能

    @属性说明: 


    @方法说明: 


    @注意: 

    '''
    def __init__(self, parent=None):
        super().__init__(parent)  # 父类初始化
        self.ui = Ui_main_interface()  # 创建UI类
        self.ui.setupUi(self)
        self.showMaximized()  # 最大化界面
        self.setWindowTitle("疲劳检测")  # 界面标题
        self.time = QTimer()  # 创建定时器
        self._connect_slot()  # 初始化槽函数连接
        self.eye_data_chart_init()  # 初始化眼睛闭合数据折线图
        self._t = 0  # 用来计数
        self._perclos_threshold = 0.3  # 设置初始化阈值

    def _connect_slot(self):
        '''初始化信号与槽的连接

        @参数说明: 
            无

        @返回值: 
            无

        @注意: 
            无
        '''
        self.ui.btn_start.clicked.connect(self._display)
        self.time.timeout.connect(self.test)

    def paintEvent(self, evevt):
        """绘图软件背景图

        Qt里面默认事件处理函数,在界面需要重新绘制时触发
        此方法主要是绘制软件的背景图

        @参数说明: 
            evevt:Qt默认事件

        @返回值: 
            无

        @注意: 
            无
        """
        temp_painter = QPainter(self)
        # 创建背景图QPixmap()对象
        soft_background_image = QPixmap("resources/groud.jpg")
        # 绘制背景图
        temp_painter.drawPixmap(0, 0, self.width(), self.height(),
                                soft_background_image)
        # 执行父类的paintEvent()函数,以便父类执行其内建的一些操作
        super().paintEvent(evevt)

    def eye_data_chart_init(self):
        '''初始化左右眼闭合程度曲线图表

        @参数说明: 
            无

        @返回值: 
            无

        @注意: 
            无
        '''
        # 创建 chart 和 chartview
        self._chart = QChart()
        self._chart.setTitle("眼睛闭合程度值")  # 设置图表标题
        self._chartView = QChartView(self)
        self._chartView.setChart(self._chart)  # chart 添加到 chartview

        # 完成布局
        self.ui.horizontalLayout_2.addWidget(self._chartView)

        ## 创建曲线系列
        self._series0 = QLineSeries()
        self._series1 = QLineSeries()
        self._series0.setName("左眼曲线")  # 设置曲线名
        self._series1.setName("右眼曲线")
        self._chart.addSeries(self._series0)  # 序列添加到图表
        self._chart.addSeries(self._series1)

        # 创建坐标轴
        self._axis_x = QValueAxis()  # x 轴
        self._axis_x.setRange(0, 60)  # 设置 x 轴坐标范围
        self._axis_x.setTitleText("time(secs)")  # x 轴标题
        self._axis_y = QValueAxis()  # y 轴
        self._axis_y.setRange(0, 0.5)  # 设置 y 轴坐标范围
        self._axis_y.setTitleText("value")  # y 轴标题

        # 为序列设置坐标轴
        self._chart.setAxisX(self._axis_x, self._series0)
        self._chart.setAxisY(self._axis_y, self._series0)
        self._chart.setAxisX(self._axis_x, self._series1)
        self._chart.setAxisY(self._axis_y, self._series1)

    @pyqtSlot(bool)
    def _display(self, checked):
        '''

        @参数说明: 


        @返回值: 


        @注意: 

        '''
        if (checked == False):  # 当按键为 False 时,停止检查
            self.ui.le_eye_threshold.setEnabled(True)
            self.ui.btn_start.setText("启动")
            self.ui.lb_fatigue_detection.setText("检测停止")
            self.time.stop()
        else:
            threshold_str = self.ui.le_eye_threshold.text()  # 获得睁闭眼阈值
            threshold_str = re.match(r"\d\.\d\d$", threshold_str)  # 对睁闭眼阈值做限定
            if (threshold_str == None):
                message_title = "阈值格式错误"
                message_text = "请输入正确的阈值格式,格式为 x.xx (x 为数字)"
                QMessageBox.critical(self, message_title, message_text)
            else:
                self.ui.btn_start.setText("停止")
                self.ui.le_eye_threshold.setEnabled(False)
                model_path = r"E:\make_data\facial"  # 人脸关键模型路径
                opencv_facial_path = r"E:\Fatigue_Detection\model_data\facial_model\haarcascade_frontalface_default.xml"  # 人脸检测模型路径
                cap_index = eval(
                    self.ui.cmb_cap_index.currentText())  # 从 combabox 获取设想头索引
                # cap_file = r"C:\Users\LWL\Pictures\Camera Roll\WIN_20200503_07_51_19_Pro.mp4"
                self.facial_data = GetFacialData(
                    tf_model=model_path,
                    facial_model_file=opencv_facial_path,
                    cap_index=cap_index)  # 创建 GetFacialData 类
                self.time.start(1000)  # 设置每次检测的间隔时间
                self.ui.lb_fatigue_detection.setText("检测中")
                self._series0.clear()
                self._series1.clear()
                self._t = 0  # 重新开始计数
                self._perclos_threshold = eval(threshold_str.group())

    def test(self):
        ret, frame = self.facial_data.get_frame()
        if (ret == -1):
            message_title = "摄像头打开失败"
            message_text = "摄像头打开失败,请检测摄像头索引是否正确"
            self.time.stop()
            QMessageBox.critical(self, message_title, message_text)
        if (ret == -2):
            message_title = "获取帧失败"
            message_text = "从摄像头获取帧失败,请重启软件"
            self.time.stop()
            QMessageBox.critical(self, message_title, message_text)
        else:
            frame = cv2.medianBlur(frame, 5)
            ret, rect = self.facial_data.get_facial(frame)
            h, w = frame.shape[:2]
            if (ret == -1):
                frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
                temp_q_image = QImage(frame, w, h, QImage.Format_RGB888)
                #  在 lb_display 中显示图片
                self.ui.lb_display.setPixmap(QPixmap.fromImage(temp_q_image))
                self.ui.lb_facial_number.setText(str(rect))  # 显示当前检测人脸数
            else:
                self.ui.lb_facial_number.setText("1")  # 显示当前检测人脸数
                frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
                facial = frame[rect[2]:rect[3], rect[0]:rect[1]]

                image = cv2.cvtColor(facial, cv2.COLOR_RGB2GRAY)
                image_h, image_w = image.shape[:2]
                image = cv2.resize(image, (150, 150))
                image = np.reshape(image, [1, 150, 150, 1])
                image = image / 255.
                facial_keypoints = self.facial_data.get_result(image)
                facial_keypoints = (facial_keypoints[0] + 1) / 2
                facial_keypoints[::
                                 2] = facial_keypoints[::2] * image_w + rect[0]
                facial_keypoints[
                    1::2] = facial_keypoints[1::2] * image_h + rect[2]

                # 圈出人脸范围
                facial = cv2.rectangle(frame, (rect[0], rect[2]),
                                       (rect[1], rect[3]), (255, 0, 0), 1)

                # 将人脸多特征点标记到图片上
                for i in range(12):
                    facial = cv2.circle(frame,
                                        (int(facial_keypoints[2 * i]),
                                         int(facial_keypoints[2 * i + 1])), 2,
                                        (255, 0, 0), -1)  # 进行打点

                # 获得左右眼的闭合程度
                eye_process_data = result_process.eyes_process(
                    facial_keypoints)

                # 添加点到图表上
                self._series0.append(self._t, eye_process_data[0])
                self._series1.append(self._t, eye_process_data[1])

                # 在label上显示左右眼计算值
                self.ui.lb_left_eye_figure.setText(str(
                    eye_process_data[0]))  # 显示左眼的计算值
                self.ui.lb_right_eye_figure.setText(str(
                    eye_process_data[1]))  # 显示右眼的计算值

                temp_q_image = QImage(facial.data, w, h, QImage.Format_RGB888)
                #  在 lb_display 中显示图片
                self.ui.lb_display.setPixmap(QPixmap.fromImage(temp_q_image))

                self._t += 1  # 每个 1s 绘制点
                if (self._t > 60):
                    # 获取 series0 以及 series1 中所有的数据
                    left_eye_point = self._series0.pointsVector()
                    right_eye_point = self._series1.pointsVector()
                    # 使用正则表达式提取其中的计算数据
                    left_eye_data = np.array(
                        re.findall(r"\d+\.\d{2,5}", str(left_eye_point)))
                    right_eye_data = np.array(
                        re.findall(r"\d+\.\d{2,5}", str(right_eye_point)))
                    perclos_judge_result = result_process.perclos_judge(
                        left_eye_data, self._perclos_threshold)
                    # 对 perclos_judge 的结果进行输出
                    if (perclos_judge_result == -2):
                        self.ui.lb_fatigue_detection.setText("过度疲劳")
                        message_title = "过度疲劳警告提醒"
                        message_text = "为了你的人身安全,请停下手中工作,休息一段时间!"
                        QMessageBox.critical(self, message_title,
                                             message_text)  # 过度疲劳提醒
                    elif (perclos_judge_result == -1):
                        self.ui.lb_fatigue_detection.setText("疲劳状态")
                    else:
                        self.ui.lb_fatigue_detection.setText("状态良好")
                    # 清除所有的 series0 以及 series1 数据,重新绘图
                    self._series0.clear()
                    self._series1.clear()
                    self._t = 0  # 重新开始计数
class Ui_MainWindow(QtWidgets.QMainWindow):
    def openDetails(self):

        self.window = QtWidgets.QDialog()
        self.ui = Ui_Detail()
        self.ui.setupUi(self.window)
        self.window.show()
        if self.inputUlasan.toPlainText() != '':
            self.ui.setDetail(self.tmp_res[0], self.tmp_res[1],
                              self.tmp_res[2], self.tmp_res[3],
                              self.tmp_res[4], self.tmp_res[5])
            return

    def __init__(self, parent=None):
        super().__init__(parent)
        self.setObjectName("MainWindow")
        self.resize(1366, 768)
        self.setAutoFillBackground(False)

        self.ind = 0

        namaPantai = []
        npn = NamaPantai()
        namaPan = npn.nama_pantai()
        for i in range(len(namaPan)):
            namaPantai.append(namaPan[i])
        self.label_pantai = namaPantai

        self.label_pantai_sort = self.getLabelSort()[0]
        self.label_pantai_sort2 = self.getLabelSort()[1]
        self.label_pantai_sort3 = self.getLabelSort()[2]
        self.label_pantai_sort4 = self.getLabelSort()[3]
        self.centralwidget = QtWidgets.QWidget(self)
        self.centralwidget.setObjectName("centralwidget")
        self.tabWidget = QtWidgets.QTabWidget(self.centralwidget)
        self.tabWidget.setGeometry(QtCore.QRect(0, 0, 1366, 768))
        self.tabWidget.setObjectName("tabWidget")
        self.tab_Grafik = QtWidgets.QWidget()
        self.tab_Grafik.setObjectName("tab_Grafik")
        self.radioALL = QtWidgets.QRadioButton(self.tab_Grafik)
        self.radioALL.setGeometry(QtCore.QRect(850, 30, 100, 21))
        self.radioDT = QtWidgets.QRadioButton(self.tab_Grafik)
        self.radioDT.setGeometry(QtCore.QRect(950, 30, 100, 21))
        self.radioDT.setObjectName("radioDT")
        self.radioAK = QtWidgets.QRadioButton(self.tab_Grafik)
        self.radioAK.setGeometry(QtCore.QRect(1050, 30, 100, 21))
        self.radioAK.setObjectName("radioAK")
        self.radioKB = QtWidgets.QRadioButton(self.tab_Grafik)
        self.radioKB.setGeometry(QtCore.QRect(1150, 30, 100, 21))
        self.radioKB.setObjectName("radioKB")
        self.radioFS = QtWidgets.QRadioButton(self.tab_Grafik)
        self.radioFS.setGeometry(QtCore.QRect(1250, 30, 100, 21))
        self.radioFS.setObjectName("radioFS")

        self.step = 0.8
        self.verticalScrollBar = QtWidgets.QScrollBar(
            self.tab_Grafik,
            sliderMoved=self.onAxisSliderMoved,
            pageStep=self.step * 10)
        self.verticalScrollBar.setGeometry(QtCore.QRect(30, 620, 1300, 20))
        self.verticalScrollBar.setOrientation(QtCore.Qt.Horizontal)
        self.verticalScrollBar.setObjectName("verticalScrollBar")

        self.comboBox = QtWidgets.QComboBox(self.tab_Grafik)
        self.comboBox.setGeometry(QtCore.QRect(110, 30, 161, 21))
        self.comboBox.setObjectName("comboBox")
        self.comboBox.addItem("=Pilih=")
        self.tmp_res = None

        for i in range(len(namaPan)):
            self.comboBox.addItem(namaPan[i])
        self.label_6 = QtWidgets.QLabel(self.tab_Grafik)
        self.label_6.setGeometry(QtCore.QRect(40, 30, 81, 16))
        self.label_6.setObjectName("label_6")
        self.graphicsView = QChartView(self.tab_Grafik)
        self.graphicsView.setGeometry(QtCore.QRect(30, 70, 1300, 520))
        self.graphicsView.setObjectName("graphicsView")
        self.tabWidget.addTab(self.tab_Grafik, "")

        self.tab_Klasifikasi = QtWidgets.QWidget()
        self.tab_Klasifikasi.setObjectName("tab_Klasifikasi")
        self.label = QtWidgets.QLabel(self.tab_Klasifikasi)
        self.label.setGeometry(QtCore.QRect(450, 70, 381, 31))
        self.label.setObjectName("label")
        self.label_2 = QtWidgets.QLabel(self.tab_Klasifikasi)
        self.label_2.setGeometry(QtCore.QRect(170, 150, 131, 16))
        self.label_2.setObjectName("label_2")
        self.label_3 = QtWidgets.QLabel(self.tab_Klasifikasi)
        self.label_3.setGeometry(QtCore.QRect(170, 370, 200, 16))
        self.label_3.setObjectName("label_3")
        self.label_4 = QtWidgets.QLabel(self.tab_Klasifikasi)
        self.label_4.setGeometry(QtCore.QRect(850, 150, 71, 16))
        self.label_4.setObjectName("label_4")
        self.label_5 = QtWidgets.QLabel(self.tab_Klasifikasi)
        self.label_5.setGeometry(QtCore.QRect(850, 370, 71, 21))
        self.label_5.setObjectName("label_5")
        self.inputUlasan = QtWidgets.QPlainTextEdit(self.tab_Klasifikasi)
        self.inputUlasan.setGeometry(QtCore.QRect(170, 200, 500, 121))
        self.inputUlasan.setFont(QFont('Times', 15))
        self.inputUlasan.setObjectName("inputUlasan")
        self.hasilPreprocessing = QtWidgets.QPlainTextEdit(
            self.tab_Klasifikasi)
        self.hasilPreprocessing.setGeometry(QtCore.QRect(170, 420, 500, 121))
        self.hasilPreprocessing.setFont(QFont('Times', 15))
        self.hasilPreprocessing.setObjectName("hasilPreprocessing")
        self.hasilSentimen = QtWidgets.QPlainTextEdit(self.tab_Klasifikasi)
        self.hasilSentimen.setGeometry(QtCore.QRect(850, 200, 300, 121))
        self.hasilSentimen.setObjectName("hasilSentimen")
        self.hasilSentimen.setFont(QFont('Times', 15))
        self.hasilKategori = QtWidgets.QPlainTextEdit(self.tab_Klasifikasi)
        self.hasilKategori.setGeometry(QtCore.QRect(850, 420, 300, 121))
        self.hasilKategori.setObjectName("hasilKategori")
        self.hasilKategori.setFont(QFont('Times', 15))
        self.buttonPrediksi = QtWidgets.QPushButton(self.tab_Klasifikasi)
        self.buttonPrediksi.setGeometry(QtCore.QRect(170, 570, 111, 30))
        self.buttonPrediksi.setObjectName("buttonPrediksi")
        self.buttonDetail = QtWidgets.QPushButton(self.tab_Klasifikasi)
        self.buttonDetail.setGeometry(QtCore.QRect(350, 570, 111, 30))
        self.buttonDetail.setObjectName("buttonDetail")
        self.buttonClear = QtWidgets.QPushButton(self.tab_Klasifikasi)
        self.buttonClear.setGeometry(QtCore.QRect(1039, 570, 111, 30))
        self.buttonClear.setObjectName("buttonClear")
        self.tabWidget.addTab(self.tab_Klasifikasi, "")
        self.tab_Pengujian = QtWidgets.QWidget()
        self.tab_Pengujian.setObjectName("tab_Pengujian")
        self.graphicsView_sentimen = QChartView(self.tab_Pengujian)
        self.graphicsView_sentimen.setGeometry(QtCore.QRect(50, 100, 600, 560))
        self.graphicsView_sentimen.setObjectName("graphicsView")
        self.graphicsView_kategori = QChartView(self.tab_Pengujian)
        self.graphicsView_kategori.setGeometry(QtCore.QRect(
            700, 100, 600, 560))
        self.graphicsView_kategori.setObjectName("graphicsView")
        self.label_ujisentimen = QtWidgets.QLabel(self.tab_Pengujian)
        self.label_ujisentimen.setGeometry(QtCore.QRect(200, 50, 300, 31))
        self.label_ujisentimen.setObjectName("label_ujisentimen")
        self.label_ujiKategori = QtWidgets.QLabel(self.tab_Pengujian)
        self.label_ujiKategori.setGeometry(QtCore.QRect(850, 50, 300, 31))
        self.label_ujiKategori.setObjectName("label_ujiKategori")
        self.tabWidget.addTab(self.tab_Pengujian, "")
        self.setCentralWidget(self.centralwidget)
        self.statusbar = QtWidgets.QStatusBar(self)
        self.statusbar.setObjectName("statusbar")
        self.setStatusBar(self.statusbar)
        self.retranslateUi(self)
        QtCore.QMetaObject.connectSlotsByName(self)

        self.comboBox.activated.connect(self.selectionChange)
        self.ALL()
        self.buttonPrediksi.clicked.connect(self.on_click)
        self.buttonClear.clicked.connect(self.delete)
        self.buttonDetail.clicked.connect(self.openDetails)
        self.graphicsView_sentimen.setChart(self.grafik_uji_sentimen())
        self.graphicsView_kategori.setChart(self.grafik_uji_kategori())
        self.radioALL.setChecked(True)
        self.radioALL.toggled.connect(self.ALL)
        self.radioDT.toggled.connect(self.DT)
        self.radioAK.toggled.connect(self.AK)
        self.radioKB.toggled.connect(self.KB)
        self.radioFS.toggled.connect(self.FS)

    def retranslateUi(self, MainWindow):
        _translate = QtCore.QCoreApplication.translate
        MainWindow.setWindowTitle(_translate("MainWindow",
                                             "Analisis Sentimen"))
        self.buttonPrediksi.setText(_translate("MainWindow", "Prediksi"))
        self.buttonDetail.setText(_translate("MainWindow", "Detail"))
        self.buttonClear.setText(_translate("MainWindow", "Hapus"))
        self.radioALL.setText(_translate("MainWindow", "Kategori"))
        self.radioDT.setText(_translate("MainWindow", "Daya Tarik"))
        self.radioAK.setText(_translate("MainWindow", "Aksesbilitas"))
        self.radioKB.setText(_translate("MainWindow", "Kebersihan"))
        self.radioFS.setText(_translate("MainWindow", "Fasilitas"))
        self.label.setText(
            _translate(
                "MainWindow",
                "<html><head/><body><p align=\"center\"><span style=\" font-size:14pt; font-weight:600;\">KLASIFIKASI ULASAN GOOGLE MAPS</span></p></body></html>"
            ))
        self.label_2.setText(
            _translate(
                "MainWindow",
                "<html><head/><body><p align=\"center\"><span style=\" font-size:10pt; font-weight:600;\">Masukkan Ulasan :</span></p></body></html>"
            ))
        self.label_3.setText(
            _translate(
                "MainWindow",
                "<html><head/><body><p><span style=\" font-size:10pt; font-weight:600;\">Hasil Preprocessing :</span></p></body></html>"
            ))
        self.label_4.setText(
            _translate(
                "MainWindow",
                "<html><head/><body><p align=\"center\"><span style=\" font-size:10pt; font-weight:600;\">Sentimen :</span></p></body></html>"
            ))
        self.label_5.setText(
            _translate(
                "MainWindow",
                "<html><head/><body><p align=\"center\"><span style=\" font-size:10pt; font-weight:600;\">Kategori :</span></p></body></html>"
            ))
        self.label_ujisentimen.setText(
            _translate(
                "MainWindow",
                "<html><head/><body><p align=\"center\"><span style=\" font-size:12pt; font-weight:600;\">Grafik Pengujian Sentimen</span></p></body></html>"
            ))
        self.label_ujiKategori.setText(
            _translate(
                "MainWindow",
                "<html><head/><body><p align=\"center\"><span style=\" font-size:12pt; font-weight:600;\">Grafik Pengujian Kategori</span></p></body></html>"
            ))
        self.tabWidget.setTabText(self.tabWidget.indexOf(self.tab_Klasifikasi),
                                  _translate("MainWindow", "Klasifikasi"))
        self.comboBox.setItemText(0, _translate("MainWindow", "-Pilih-"))
        np = NamaPantai()
        hasil = np.nama_pantai()
        for i in range(len(hasil)):
            self.comboBox.setItemText(i + 1,
                                      _translate("MainWindow", hasil[i]))
        self.label_6.setText(
            _translate(
                "MainWindow",
                "<html><head/><body><p><span style=\" font-size:9pt;\">Pilih Pantai :</span></p></body></html>"
            ))
        self.tabWidget.setTabText(self.tabWidget.indexOf(self.tab_Grafik),
                                  _translate("MainWindow", "Grafik"))
        self.tabWidget.setTabText(self.tabWidget.indexOf(self.tab_Pengujian),
                                  _translate("MainWindow", "Pengujian"))

    def selectionChange(self):
        pilih_pantai = str(self.comboBox.currentText())
        if pilih_pantai == '-Pilih-':
            self.ALL()
            return
        gf = Grafik(pilih_pantai)
        hasil = gf.hasil_grafik()
        hasil_dayatarik = hasil[0]
        hasil_aksesbilitas = hasil[1]
        hasil_kebersihan = hasil[2]
        hasil_fasilitas = hasil[3]
        total_pantai = hasil[4]
        daya_tarik = (hasil_dayatarik / total_pantai) * 100
        aksesbilitas = (hasil_aksesbilitas / total_pantai) * 100
        kebersihan = (hasil_kebersihan / total_pantai) * 100
        fasilitas = (hasil_fasilitas / total_pantai) * 100
        nilai = {
            'Daya Tarik': daya_tarik,
            'Aksesbilitas': aksesbilitas,
            'Kebersihan': kebersihan,
            'Fasilitas': fasilitas
        }
        maks = max(nilai['Daya Tarik'], nilai['Aksesbilitas'],
                   nilai['Kebersihan'], nilai['Fasilitas'])
        for i in nilai:
            if maks == nilai[i]:
                print(i)
        set0 = QBarSet(pilih_pantai)
        set0 << daya_tarik << aksesbilitas << kebersihan << fasilitas
        series = QBarSeries()
        series.append(set0)
        series.setLabelsVisible(True)
        chart = QChart()
        chart.addSeries(series)
        chart.setTitle('Pantai ' + str(pilih_pantai))

        labelnya = ["Daya Tarik", "Aksesbilitas", "Kebersihan", "Fasilitas"]

        series = QPieSeries()
        series.append("dt", daya_tarik)
        series.append("ak", aksesbilitas)
        series.append("keb", kebersihan)
        series.append("fas", fasilitas)

        slice = QPieSlice()
        slice = series.slices()[0]
        slice.setExploded(False)
        slice.setLabelVisible(True)
        slice.setBrush(QtGui.QColor("blue"))

        slice = QPieSlice()
        slice = series.slices()[1]
        slice.setExploded(False)
        slice.setLabelVisible(True)
        slice.setBrush(QtGui.QColor("red"))

        slice = QPieSlice()
        slice = series.slices()[2]
        slice.setExploded(False)
        slice.setLabelVisible(True)
        slice.setBrush(QtGui.QColor("green"))

        slice = QPieSlice()
        slice = series.slices()[3]
        slice.setExploded(False)
        slice.setLabelVisible(True)
        slice.setBrush(QtGui.QColor("orange"))
        i = 0
        for slice in series.slices():
            slice.setLabel(labelnya[i] +
                           "  {:.1f}%".format(100 * slice.percentage()))
            i = i + 1

        chart = QChart()
        chart.legend().hide()
        chart.addSeries(series)
        chart.createDefaultAxes()
        chart.setAnimationOptions(QChart.SeriesAnimations)
        self.graphicsView.setChart(chart)

    def ALL(self):
        self.ind = 0
        set0 = QBarSet('Daya Tarik')
        set1 = QBarSet('Aksesbilitas')
        set2 = QBarSet('Kebersihan')
        set3 = QBarSet('Fasilitas')

        set0.setColor(QtGui.QColor("blue"))
        set1.setColor(QtGui.QColor("red"))
        set2.setColor(QtGui.QColor("green"))
        set3.setColor(QtGui.QColor("orange"))
        gf = Grafik_2()

        jml = gf.jumlah_per_pantai()
        jml_pantai = []
        for i in range(len(jml)):
            jml_pantai.append(jml[i])

        hasil = gf.hasil_dayatarik()
        for i in range(len(hasil)):
            set0.append((hasil[i] / jml_pantai[i]) * 100)

        hasil2 = gf.hasil_aksesbilitas()
        for i in range(len(hasil2)):
            set1.append((hasil2[i] / jml_pantai[i]) * 100)

        hasil3 = gf.hasil_kebersihan()
        for i in range(len(hasil3)):
            set2.append((hasil3[i] / jml_pantai[i]) * 100)

        hasil4 = gf.hasil_fasilitas()
        for i in range(len(hasil4)):
            set3.append((hasil4[i] / jml_pantai[i]) * 100)

        series = QBarSeries()
        series.append(set0)
        series.append(set1)
        series.append(set2)
        series.append(set3)
        series.setLabelsVisible(True)
        series.setLabelsPosition(QAbstractBarSeries.LabelsInsideEnd)
        series.setLabelsAngle(-90)

        self.chart = QChart()
        self.chart.addSeries(series)
        self.chart.setTitle('Grafik Prosentase Ulasan Pantai')
        self.chart.setAnimationOptions(QChart.SeriesAnimations)
        axisY = QValueAxis()
        axisY.setTitleText("Prosentase (%)")
        axisY.applyNiceNumbers()
        self.chart.addAxis(axisY, Qt.AlignLeft)
        series.attachAxis(axisY)
        self.chart.legend().setVisible(True)
        self.chart.legend().setAlignment(Qt.AlignBottom)
        self.chart.createDefaultAxes()
        self.graphicsView.setChart(self.chart)
        self.adjust_axes(0, 2)
        self.lims = np.array([0, 6])
        self.onAxisSliderMoved(self.verticalScrollBar.value())

    def getLabelSort(self):
        gf = Grafik_2()
        jml = gf.jumlah_per_pantai()
        jml_pantai = []
        for i in range(len(jml)):
            jml_pantai.append(jml[i])

        value = []
        value2 = []
        value3 = []
        value4 = []
        hasil = gf.hasil_dayatarik()
        for i in range(len(hasil)):
            value.append((hasil[i] / jml_pantai[i]) * 100)
        sorting = sorted(value, reverse=True)
        index = np.argsort(value)[::-1]
        label_sorting = []
        for i in index:
            label_sorting.append(self.label_pantai[i])

        hasil2 = gf.hasil_aksesbilitas()
        for i in range(len(hasil2)):
            value2.append((hasil2[i] / jml_pantai[i]) * 100)
        sorting2 = sorted(value2, reverse=True)
        index2 = np.argsort(value2)[::-1]
        label_sorting2 = []
        for i in index2:
            label_sorting2.append(self.label_pantai[i])

        hasil3 = gf.hasil_kebersihan()
        for i in range(len(hasil3)):
            value3.append((hasil3[i] / jml_pantai[i]) * 100)
        sorting3 = sorted(value3, reverse=True)
        index3 = np.argsort(value3)[::-1]
        label_sorting3 = []
        for i in index3:
            label_sorting3.append(self.label_pantai[i])

        hasil4 = gf.hasil_fasilitas()
        for i in range(len(hasil4)):
            value4.append((hasil4[i] / jml_pantai[i]) * 100)
        sorting4 = sorted(value4, reverse=True)
        index4 = np.argsort(value4)[::-1]
        label_sorting4 = []
        for i in index4:
            label_sorting4.append(self.label_pantai[i])
        return (label_sorting, label_sorting2, label_sorting3, label_sorting4)

    def adjust_axes(self, value_min, value_max):
        if value_max > 35:
            return
        self.chart.createDefaultAxes()
        self.chart.axisX().setRange(str(value_min), str(value_max))
        if self.ind == 0:
            for i in range(
                    value_min, value_max +
                    1 if value_max < 36 else len(self.label_pantai)):
                self.chart.axisX().replace(
                    str(i), self.label_pantai[i - 1 if i > 0 else i])
        if self.ind == 1:
            for i in range(
                    value_min, value_max +
                    1 if value_max < 36 else len(self.label_pantai_sort)):
                self.chart.axisX().replace(
                    str(i), self.label_pantai_sort[i - 1 if i > 0 else i])
        if self.ind == 2:
            for i in range(
                    value_min, value_max +
                    1 if value_max < 36 else len(self.label_pantai_sort2)):
                self.chart.axisX().replace(
                    str(i), self.label_pantai_sort2[i - 1 if i > 0 else i])
        if self.ind == 3:
            for i in range(
                    value_min, value_max +
                    1 if value_max < 36 else len(self.label_pantai_sort3)):
                self.chart.axisX().replace(
                    str(i), self.label_pantai_sort3[i - 1 if i > 0 else i])
        if self.ind == 4:
            for i in range(
                    value_min, value_max +
                    1 if value_max < 36 else len(self.label_pantai_sort4)):
                self.chart.axisX().replace(
                    str(i), self.label_pantai_sort4[i - 1 if i > 0 else i])

    @QtCore.pyqtSlot(int)
    def onAxisSliderMoved(self, value):
        r = value / ((1 + self.step) * 10)
        l1 = self.lims[0] + r * np.diff(self.lims)
        l2 = l1 + np.diff(self.lims) * self.step
        self.adjust_axes(math.floor(l1), math.ceil(l2))

    def DT(self):
        self.ind = 1
        gf = Grafik_2()
        jml = gf.jumlah_per_pantai()
        jml_pantai = []
        for i in range(len(jml)):
            jml_pantai.append(jml[i])

        value = []
        hasil = gf.hasil_dayatarik()
        for i in range(len(hasil)):
            value.append((hasil[i] / jml_pantai[i]) * 100)
        sorting = sorted(value, reverse=True)
        index = np.argsort(value)[::-1]
        label_sorting = []
        for i in index:
            label_sorting.append(self.label_pantai[i])

        set0 = QBarSet('Daya Tarik')
        set0.setColor(QtGui.QColor("blue"))
        for i in range(len(hasil)):
            set0.append(sorting)

        series = QBarSeries()
        series.append(set0)
        series.setLabelsVisible(True)
        series.setLabelsPosition(QAbstractBarSeries.LabelsInsideEnd)
        self.chart = QChart()
        self.chart.addSeries(series)
        self.chart.setTitle('Grafik Prosentase Ulasan Pantai')
        self.chart.setAnimationOptions(QChart.SeriesAnimations)
        axisX = QBarCategoryAxis()
        axisX.setLabelsAngle(-90)

        axisY = QValueAxis()
        axisY.setTitleText("Prosentase (%)")
        self.chart.addAxis(axisX, Qt.AlignBottom)
        self.chart.addAxis(axisY, Qt.AlignLeft)
        series.attachAxis(axisY)
        axisY.applyNiceNumbers()
        self.chart.legend().setVisible(True)
        self.chart.legend().setAlignment(Qt.AlignBottom)
        self.chart.createDefaultAxes()
        self.graphicsView.setChart(self.chart)
        self.lims = np.array([0, 10])
        self.onAxisSliderMoved(self.verticalScrollBar.value())

    def AK(self):
        self.ind = 2
        gf = Grafik_2()
        jml = gf.jumlah_per_pantai()
        jml_pantai = []
        for i in range(len(jml)):
            jml_pantai.append(jml[i])

        value = []
        hasil = gf.hasil_aksesbilitas()
        for i in range(len(hasil)):
            value.append((hasil[i] / jml_pantai[i]) * 100)
        sorting = sorted(value, reverse=True)

        set0 = QBarSet('Aksesbilitas')
        set0.setColor(QtGui.QColor("red"))
        for i in range(len(hasil)):
            set0.append(sorting)
        series = QBarSeries()
        series.append(set0)
        series.setLabelsVisible(True)
        series.setLabelsPosition(QAbstractBarSeries.LabelsInsideEnd)

        self.chart = QChart()
        self.chart.addSeries(series)
        self.chart.setTitle('Grafik Prosentase Ulasan Pantai')
        self.chart.setAnimationOptions(QChart.SeriesAnimations)

        axisY = QValueAxis()
        axisY.setTitleText("Prosentase (%)")
        axisY.applyNiceNumbers()
        self.chart.addAxis(axisY, Qt.AlignLeft)
        series.attachAxis(axisY)
        self.chart.legend().setVisible(True)
        self.chart.legend().setAlignment(Qt.AlignBottom)
        self.chart.createDefaultAxes()
        self.graphicsView.setChart(self.chart)
        self.adjust_axes(0, 2)
        self.lims = np.array([0, 10])
        self.onAxisSliderMoved(self.verticalScrollBar.value())

    def KB(self):
        self.ind = 3
        gf = Grafik_2()
        jml = gf.jumlah_per_pantai()
        jml_pantai = []
        for i in range(len(jml)):
            jml_pantai.append(jml[i])

        value = []
        hasil = gf.hasil_kebersihan()
        for i in range(len(hasil)):
            value.append((hasil[i] / jml_pantai[i]) * 100)
        sorting = sorted(value, reverse=True)

        set0 = QBarSet('Kebersihan')
        set0.setColor(QtGui.QColor("green"))
        for i in range(len(hasil)):
            set0.append(sorting)

        series = QBarSeries()
        series.append(set0)
        series.setLabelsVisible(True)
        series.setLabelsPosition(QAbstractBarSeries.LabelsInsideEnd)

        self.chart = QChart()
        self.chart.addSeries(series)
        self.chart.setTitle('Grafik Prosentase Ulasan Pantai')
        self.chart.setAnimationOptions(QChart.SeriesAnimations)

        axisY = QValueAxis()
        axisY.setTitleText("Prosentase (%)")
        axisY.applyNiceNumbers()
        self.chart.addAxis(axisY, Qt.AlignLeft)
        series.attachAxis(axisY)
        self.chart.legend().setVisible(True)
        self.chart.legend().setAlignment(Qt.AlignBottom)
        self.chart.createDefaultAxes()
        self.graphicsView.setChart(self.chart)
        self.adjust_axes(0, 2)
        self.lims = np.array([0, 10])
        self.onAxisSliderMoved(self.verticalScrollBar.value())

    def FS(self):
        self.ind = 4
        gf = Grafik_2()
        jml = gf.jumlah_per_pantai()
        jml_pantai = []
        for i in range(len(jml)):
            jml_pantai.append(jml[i])

        value = []
        hasil = gf.hasil_fasilitas()
        for i in range(len(hasil)):
            value.append((hasil[i] / jml_pantai[i]) * 100)
        sorting = sorted(value, reverse=True)

        set0 = QBarSet('Fasilitas')
        set0.setColor(QtGui.QColor("orange"))
        for i in range(len(hasil)):
            set0.append(sorting)

        series = QBarSeries()
        series.append(set0)
        series.setLabelsVisible(True)
        series.setLabelsPosition(QAbstractBarSeries.LabelsInsideEnd)

        self.chart = QChart()
        self.chart.addSeries(series)
        self.chart.setTitle('Grafik Prosentase Ulasan Pantai')
        self.chart.setAnimationOptions(QChart.SeriesAnimations)

        axisY = QValueAxis()
        axisY.setTitleText("Prosentase (%)")
        axisY.applyNiceNumbers()
        self.chart.addAxis(axisY, Qt.AlignLeft)
        series.attachAxis(axisY)
        self.chart.legend().setVisible(True)
        self.chart.legend().setAlignment(Qt.AlignBottom)
        self.chart.createDefaultAxes()
        self.graphicsView.setChart(self.chart)
        self.adjust_axes(0, 2)
        self.lims = np.array([0, 10])
        self.onAxisSliderMoved(self.verticalScrollBar.value())

    def on_click(self):
        textboxValue = self.inputUlasan.toPlainText()
        cf = Classification(textboxValue)
        hasil = cf.klasifikasi()
        hasil_sentimen = hasil[0]
        hasil_kategori = hasil[1]
        token = hasil[2]
        predict_sentimen_positif = hasil[3]
        predict_sentimen_negatif = hasil[4]

        predict_DayaTarik = hasil[5]
        predict_Aksesbilitas = hasil[6]
        predict_Kebersihan = hasil[7]
        predict_Fasilitas = hasil[8]
        if self.inputUlasan.toPlainText() != '':
            self.inputUlasan.setPlainText(textboxValue)
            self.hasilPreprocessing.setPlainText(token)
            self.hasilSentimen.setPlainText(hasil_sentimen)
            self.hasilKategori.setPlainText(hasil_kategori)
            self.tmp_res = (predict_sentimen_positif, predict_sentimen_negatif,
                            predict_DayaTarik, predict_Aksesbilitas,
                            predict_Kebersihan, predict_Fasilitas)

        return self.tmp_res

    def delete(self):
        self.inputUlasan.setPlainText("")
        self.hasilPreprocessing.setPlainText("")
        self.hasilSentimen.setPlainText("")
        self.hasilKategori.setPlainText("")

    def grafik_uji_sentimen(self):
        with open(
                'C:/Users/asus/Desktop/SKRIPSWEET BISMILLAH/MODUL PROGRAM/Modul Program Bismillah/Pengujian/hasil_uji_sentimen_kfold.json'
        ) as f:
            dataa = json.load(f)
        print(dataa)
        acc = dataa['acc']
        pres = dataa['presisi']
        rec = dataa['recall']
        set0 = QBarSet('Akurasi')
        set1 = QBarSet('Presisi')
        set2 = QBarSet('Recall')

        for i in range(len(acc)):
            set0.append(acc[i] * 100)

        for i in range(len(pres)):
            set1.append(pres[i] * 100)

        for i in range(len(rec)):
            set2.append(rec[i] * 100)

        series = QBarSeries()
        series.append(set0)
        series.append(set1)
        series.append(set2)

        set0.setColor(QtGui.QColor("navy"))
        set1.setColor(QtGui.QColor("yellow"))
        set2.setColor(QtGui.QColor("red"))

        chart = QChart()
        chart.addSeries(series)
        chart.setAnimationOptions(QChart.SeriesAnimations)
        label_pantai = ['K=1', 'K=2', 'K=3', 'K=4', 'K=5']
        axisX = QBarCategoryAxis()
        axisX.append(label_pantai)
        axisX.setLabelsAngle(0)
        axisY = QValueAxis()
        axisX.setTitleText("K-Fold Cross Validation")
        axisY.setTitleText("Prosentase (%)")
        axisY.setRange(0, max(set0))
        axisY.setMinorTickCount(5)
        chart.addAxis(axisX, Qt.AlignBottom)
        chart.addAxis(axisY, Qt.AlignLeft)
        chart.legend().setVisible(True)
        chart.legend().setAlignment(Qt.AlignBottom)
        return (chart)

    def grafik_uji_kategori(self):
        with open(
                'C:/Users/asus/Desktop/SKRIPSWEET BISMILLAH/MODUL PROGRAM/Modul Program Bismillah/Pengujian/hasil_uji_kategori_kfold.json'
        ) as f:
            dataa = json.load(f)
        print(dataa)
        acc = dataa['acc']
        pres = dataa['presisi']
        rec = dataa['recall']
        set0 = QBarSet('Akurasi')
        set1 = QBarSet('Presisi')
        set2 = QBarSet('Recall')

        for i in range(len(acc)):
            set0.append(acc[i] * 100)

        for i in range(len(pres)):
            set1.append(pres[i] * 100)

        for i in range(len(rec)):
            set2.append(rec[i] * 100)

        series = QBarSeries()
        series.append(set0)
        series.append(set1)
        series.append(set2)
        set0.setColor(QtGui.QColor("navy"))
        set1.setColor(QtGui.QColor("yellow"))
        set2.setColor(QtGui.QColor("red"))

        chart = QChart()
        chart.addSeries(series)
        chart.setAnimationOptions(QChart.SeriesAnimations)
        label_pantai = ['K=1', 'K=2', 'K=3', 'K=4', 'K=5']
        axisX = QBarCategoryAxis()
        axisX.append(label_pantai)
        axisX.setLabelsAngle(0)
        axisY = QValueAxis()
        axisX.setTitleText("K-Fold Cross Validation")
        axisY.setTitleText("Prosentase (%)")
        axisY.setRange(0, max(set0))
        axisY.setMinorTickCount(5)

        chart.addAxis(axisX, Qt.AlignBottom)
        chart.addAxis(axisY, Qt.AlignLeft)
        chart.legend().setVisible(True)
        chart.legend().setAlignment(Qt.AlignBottom)
        return (chart)
Beispiel #24
0
class DataEntryForm(QWidget):
    def __init__(self):
        super().__init__()
        self.items = 0

        self._data = {
            "Phone bill": 50.5,
            "Gas": 30.0,
            "Rent": 1850.0,
            "Car Payment": 420.0,
            "Comcast": 105.0,
            "Public transportation": 60.0,
            "Coffee": 90.5
        }

        # left side
        self.table = QTableWidget()
        self.table.setColumnCount(2)
        self.table.setHorizontalHeaderLabels(('Description', 'Price'))
        self.table.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch)

        self.layoutRight = QVBoxLayout()

        # chart widget
        self.chartView = QChartView()
        self.chartView.setRenderHint(QPainter.Antialiasing)

        self.lineEditDescription = QLineEdit()
        self.lineEditPrice = QLineEdit()
        self.buttonAdd = QPushButton('Add')
        self.buttonClear = QPushButton('Clear')
        self.buttonQuit = QPushButton('Quit')
        self.butotnPlot = QPushButton('Plot')

        self.buttonAdd.setEnabled(False)

        self.layoutRight.setSpacing(10)
        self.layoutRight.addWidget(QLabel('Description'))
        self.layoutRight.addWidget(self.lineEditDescription)
        self.layoutRight.addWidget(QLabel('Price'))
        self.layoutRight.addWidget(self.lineEditPrice)
        self.layoutRight.addWidget(self.buttonAdd)
        self.layoutRight.addWidget(self.butotnPlot)
        self.layoutRight.addWidget(self.chartView)
        self.layoutRight.addWidget(self.buttonClear)
        self.layoutRight.addWidget(self.buttonQuit)

        self.layout = QHBoxLayout()
        self.layout.addWidget(self.table, 50)
        self.layout.addLayout(self.layoutRight, 50)

        self.setLayout(self.layout)

        self.buttonQuit.clicked.connect(lambda: app.quit())
        self.buttonClear.clicked.connect(self.reset_table)
        self.butotnPlot.clicked.connect(self.graph_chart)
        self.buttonAdd.clicked.connect(self.add_entry)

        self.lineEditDescription.textChanged[str].connect(self.check_disable)
        self.lineEditPrice.textChanged[str].connect(self.check_disable)

        self.fill_table()

    def fill_table(self, data=None):
        if not data:
            data = self._data
        # 	print("data not :", data)
        # else:
        # 	print ("data :",data)

        for desc, price in data.items():
            descItem = QTableWidgetItem(desc)
            priceItem = QTableWidgetItem('${0:.2f}'.format(price))
            priceItem.setTextAlignment(Qt.AlignRight | Qt.AlignCenter)

            self.table.insertRow(self.items)
            self.table.setItem(self.items, 0, descItem)
            self.table.setItem(self.items, 1, priceItem)
            self.items += 1

    def add_entry(self):
        desc = self.lineEditDescription.text()
        price = self.lineEditPrice.text()

        try:
            descItem = QTableWidgetItem(desc)
            priceItem = QTableWidgetItem('${0:.2f}'.format(float(price)))
            priceItem.setTextAlignment(Qt.AlignRight | Qt.AlignCenter)

            self.table.insertRow(self.items)
            self.table.setItem(self.items, 0, descItem)
            self.table.setItem(self.items, 1, priceItem)
            self.items += 1

            self.lineEditDescription.setText('')
            self.lineEditPrice.setText('')
        except ValueError:
            pass

    def check_disable(self):
        if self.lineEditDescription.text() and self.lineEditPrice.text():
            self.buttonAdd.setEnabled(True)
        else:
            self.buttonAdd.setEnabled(False)

    def reset_table(self):
        self.table.setRowCount(0)
        self.items = 0

        chart = QChart()
        self.chartView.setChart(chart)

    def graph_chart(self):
        series = QPieSeries()

        for i in range(self.table.rowCount()):
            text = self.table.item(i, 0).text()
            val = float(self.table.item(i, 1).text().replace('$', ''))
            series.append(text, val)

        chart = QChart()
        chart.addSeries(series)
        chart.legend().setAlignment(Qt.AlignTop)
        self.chartView.setChart(chart)
Beispiel #25
0
class MainWindow(QMainWindow):
    def __init__(self, parent=None):
        super(MainWindow, self).__init__(parent)

        self.pixelRow = QLabel()
        self.pixelRow.setFixedSize(20, nbPixels)

        self.matrixDisplay = QTextEdit()
        self.matrixDisplay.setFixedSize(165, 180)

        self.valuesDisplay = QTextEdit()
        self.valuesDisplay.setFixedSize(50, nbPixels)

        # CHART
        self.serie = QLineSeries()

        self.chart = QChart()
        self.chart.addSeries(self.serie)
        self.chart.legend().hide()
        self.chart.layout().setContentsMargins(0, 0, 0, 0)

        self.xAxis = QValueAxis()
        self.xAxis.setTitleText("Height")
        self.xAxis.setLabelFormat("%d")
        self.xAxis.setRange(0, nbPixels)

        self.yAxis = QValueAxis()
        self.yAxis.setLabelFormat("%d")
        self.yAxis.setTitleText("Distance ")
        self.yAxis.setRange(0, couleurMax)

        self.chart.setAxisX(self.xAxis)
        self.chart.setAxisY(self.yAxis)

        self.serie.attachAxis(self.xAxis)
        self.serie.attachAxis(self.yAxis)

        self.chart.setTitle("Profile line")

        self.chartView = QChartView(self)
        self.chartView.setChart(self.chart)
        self.chartView.rotate(90)
        self.chartView.setGeometry(20, 195, 450, 400)
        #end CHART

        self.timer = QTimer(self)
        self.timer.setInterval(periode)
        self.timer.start
        self.timer.timeout.connect(self.refresh)

        self.startButton = QPushButton("START")
        self.startButton.setDefault(True)
        self.startButton.clicked.connect(self.startTimer)
        self.startButton.setFixedSize(100, 50)

        self.stopButton = QPushButton("STOP")
        self.stopButton.setDefault(True)
        self.stopButton.clicked.connect(self.stopTimer)
        self.stopButton.setFixedSize(100, 50)

        topLayout = QGridLayout()
        topLayout.addWidget(self.startButton, 0, 0)
        topLayout.addWidget(self.stopButton, 1, 0)
        topLayout.addWidget(self.matrixDisplay, 0, 1, 2, 1)

        mainLayout = QGridLayout()
        mainLayout.addLayout(topLayout, 0, 0)
        mainLayout.addWidget(self.pixelRow, 0, 1, 2, 1)
        mainLayout.addWidget(self.valuesDisplay, 0, 2, 2, 1)
        mainLayout.addWidget(self.chartView, 1, 0)

        mainwidget = QWidget()
        mainwidget.setLayout(mainLayout)
        self.setCentralWidget(mainwidget)

        self.setWindowTitle("Minecraft Depth Map")

    def startTimer(self):
        self.timer.start()

    def stopTimer(self):
        self.timer.stop()

    def refresh(self):
        self.serie.clear()
        self.valuesDisplay.clear()
        screen = app.primaryScreen()
        #grabWindow(wID, x, y, w, h)
        pix = QPixmap(
            screen.grabWindow(0,
                              int((screenW * 3) / 4) - 10,
                              int((screenH - nbPixels) / 2), 20, nbPixels))
        self.pixelRow.setPixmap(pix)
        img = QImage(pix.toImage())

        array = [0 for i in range(nbBlocsH)]

        for i in range(nbBlocsH):
            y = nbPixels - (i * (nbPixels / nbBlocsH) + (nbPixels /
                                                         (2 * nbBlocsH)))
            colorvalue = 255 - QColor(img.pixel(10, y)).black()
            self.valuesDisplay.append(str(colorvalue))
            self.valuesDisplay.append("\n")
            self.serie.append(y, colorvalue)

            #convert colors from 0->couleurMax to 0->nbBlocsD
            if colorvalue > couleurMax:
                colorvalue = nbBlocsD
            elif colorvalue < couleurMin:
                colorvalue = 0
            else:
                colorvalue = int(colorvalue / (couleurMax / nbBlocsD))
            array[i] = colorvalue

        self.convertToMatrix(array)

    def convertToMatrix(self, array):

        matrix = [[0 for j in range(nbBlocsD)] for i in range(nbBlocsH)]

        for i in range(nbBlocsH):
            if array[i] < nbBlocsD:
                matrix[i][array[i]] = 1
                if i < (nbBlocsH - 1):
                    if array[i + 1] > (array[i] + 1):
                        for j in range(array[i] + 1,
                                       min(nbBlocsD, array[i + 1])):
                            matrix[i][j] = 1
                if i > 0:
                    if array[i - 1] > (array[i] + 1):
                        for j in range(array[i] + 1,
                                       min(nbBlocsD, array[i - 1])):
                            matrix[i][j] = 1

        #test1Scalable.convertToHexa(motifF,nbBlocsD,nbBlocsH)  # es-ce bien la fonction a utiliser pour l'affichage ?
        self.displayMatrix(matrix)

    def displayMatrix(self, matrix):
        self.matrixDisplay.clear()
        for j in range(nbBlocsD - 1, -1, -1):
            line = ""
            for i in range(nbBlocsH):
                line = line + str(matrix[i][j]) + "  "
                #self.matrixDisplay.append( line)
                #self.matrixDisplay.append( str(matrix[i][j]) + "  ")
                #self.matrixDisplay.moveCursor( QTextCursor.EndOfLine )
            self.matrixDisplay.append(line)
Beispiel #26
0
class PieChart(QtWidgets.QWidget):
    def __init__(self):
        QtWidgets.QWidget.__init__(self)

        self.setObjectName("main")
        self.setStyleSheet("""
                    QWidget{
                        border:1px solid #148CD2;
                        border-radius:10px;
                    }
        """)
        self.create_piechart()

        timer = QTimer(self)
        timer.timeout.connect(self.redraw)
        timer.start(5 * 60 * 1000)  # update every 5 minutes

        layout = QHBoxLayout(self)
        layout.setContentsMargins(5, 5, 50, 5)
        layout.addWidget(self.chartview)

        self.setLayout(layout)
        self.setFixedSize(500, 400)

    def create_piechart(self):
        today = datetime.date.today()
        Day = selectday(today)
        catogeries = Day['allCategory']
        catogeries = dict(sorted(catogeries.items(), key=lambda x: -x[1])[:5])
        print(f"--------------------{catogeries}--------")
        series = QPieSeries()

        tot_val = 0
        for name, value in catogeries.items():
            tot_val += value

        tot_val = max(tot_val, 1)
        for name, value in catogeries.items():
            if value == 0:
                value = 0.2
            _slice = series.append(name, 100 * (value / tot_val))
            _slice.setLabelVisible(True)  # can be removed if unnecessary

        self.chart = QChart()
        self.chart.legend().hide()
        self.chart.addSeries(series)
        self.chart.createDefaultAxes()
        self.chart.setAnimationOptions(QChart.SeriesAnimations)
        self.chart.setTitle("Categories")

        self.chart.legend().setVisible(True)
        self.chart.legend().setAlignment(Qt.AlignBottom)

        self.chartview = QChartView(self.chart)
        self.chartview.setRenderHint(QPainter.Antialiasing)

    def redraw(self):
        # remove pieChart
        self.chart.removeAllSeries()

        today = datetime.date.today()
        Day = selectday(today)
        catogeries = Day['allCategory']
        catogeries = dict(sorted(catogeries.items(), key=lambda x: -x[1])[:5])
        print(f"--------------------{catogeries}--------")
        series = QPieSeries()

        tot_val = 0
        for name, value in catogeries.items():
            tot_val += value

        for name, value in catogeries.items():
            _slice = series.append(name, 100 * (value / tot_val))
            _slice.setLabelVisible(True)  # can be removed if unnecessary

        self.chart.addSeries(series)

        self.chartview.setChart((self.chart))
        self.chartview.setRenderHint(QPainter.Antialiasing)
        self.chartview.repaint()
class SetChartDetailPopup(QDialog):
    def __init__(self, table_id, *args, **kwargs):
        super(SetChartDetailPopup, self).__init__(*args, **kwargs)
        layout = QHBoxLayout(margin=2)
        # left_layout = QVBoxLayout()
        self.table_id = table_id
        self.table_data_frame = None  # 表格数据的pandas Data Frame对象
        # 图表参数设置的控件
        self.chart_parameter = QWidget(parent=self)
        parameter_layout = QVBoxLayout(margin=0)
        parameter_layout.addWidget(QLabel('参数设置', objectName='widgetTip'))
        # 图表名称
        chart_name_layout = QHBoxLayout()
        chart_name_layout.addWidget(QLabel('图表名称:', objectName='headTip'))
        self.chart_name = QLineEdit()
        chart_name_layout.addWidget(self.chart_name)
        parameter_layout.addLayout(chart_name_layout)
        # 图表类型
        chart_category_layout = QHBoxLayout()
        chart_category_layout.addWidget(QLabel('图表类型:', objectName='headTip'))
        self.chart_category_combo = QComboBox()
        self.chart_category_combo.addItems([u'折线图', u'柱形图'])
        chart_category_layout.addWidget(self.chart_category_combo)
        chart_category_layout.addStretch()
        parameter_layout.addLayout(chart_category_layout)
        # 选择X轴
        chart_xaxis_layout = QHBoxLayout()
        chart_xaxis_layout.addWidget(QLabel('X 轴列名:', objectName='headTip'))
        self.x_axis_combo = QComboBox(currentTextChanged=self.x_axis_changed)
        chart_xaxis_layout.addWidget(self.x_axis_combo)
        chart_xaxis_layout.addStretch()
        parameter_layout.addLayout(chart_xaxis_layout)
        # Y轴设置
        parameter_layout.addWidget(QLabel('Y 轴列名:', objectName='headTip'))
        yaxis_layout = QHBoxLayout()
        left_yaxis_layout = QVBoxLayout()
        self.column_header_list = QListWidget()
        self.column_header_list.setMaximumWidth(180)
        left_yaxis_layout.addWidget(self.column_header_list)
        yaxis_layout.addLayout(left_yaxis_layout)
        # 中间按钮
        middle_yasis_layout = QVBoxLayout()
        middle_yasis_layout.addWidget(
            QPushButton('左轴→', objectName='addAxis', clicked=self.add_y_left))
        middle_yasis_layout.addWidget(
            QPushButton('右轴→', objectName='addAxis', clicked=self.add_y_right))
        yaxis_layout.addLayout(middle_yasis_layout)
        # 右侧列头显示
        right_yaxis_layout = QVBoxLayout()
        self.right_top_list = QListWidget(
            doubleClicked=self.remove_toplist_item)
        self.right_top_list.setMaximumWidth(180)
        right_yaxis_layout.addWidget(self.right_top_list)
        self.right_bottom_list = QListWidget(
            doubleClicked=self.remove_bottomlist_item)
        self.right_bottom_list.setMaximumWidth(180)
        right_yaxis_layout.addWidget(self.right_bottom_list)
        yaxis_layout.addLayout(right_yaxis_layout)
        parameter_layout.addLayout(yaxis_layout)
        # 轴名称设置
        parameter_layout.addWidget(QLabel('轴名称设置:', objectName='headTip'),
                                   alignment=Qt.AlignLeft)
        # x轴
        bottom_xaxis_name_layout = QHBoxLayout()
        bottom_xaxis_name_layout.addWidget(QLabel('X 轴:'))
        self.bottom_x_label_edit = QLineEdit(placeholderText='请输入轴名称')
        bottom_xaxis_name_layout.addWidget(self.bottom_x_label_edit)
        parameter_layout.addLayout(bottom_xaxis_name_layout)
        # Y轴
        yaxis_name_layout = QHBoxLayout()
        yaxis_name_layout.addWidget(QLabel('左轴:'))
        self.left_y_label_edit = QLineEdit(placeholderText='请输入左轴名称')
        yaxis_name_layout.addWidget(self.left_y_label_edit)
        yaxis_name_layout.addWidget(QLabel('右轴:'))
        self.right_y_label_edit = QLineEdit(placeholderText='请输入右轴名称')
        yaxis_name_layout.addWidget(self.right_y_label_edit)
        parameter_layout.addLayout(yaxis_name_layout)
        # 数据范围
        parameter_layout.addWidget(QLabel('数据范围设置:', objectName='headTip'),
                                   alignment=Qt.AlignLeft)
        chart_scope_layout1 = QHBoxLayout()
        chart_scope_layout1.addWidget(QLabel('起始日期:'))
        self.scope_start_date = QDateEdit()
        self.scope_start_date.setCalendarPopup(True)
        self.scope_start_date.setEnabled(False)
        chart_scope_layout1.addWidget(self.scope_start_date)
        chart_scope_layout1.addWidget(QLabel('截止日期:'))
        self.scope_end_date = QDateEdit()
        self.scope_end_date.setCalendarPopup(True)
        self.scope_end_date.setEnabled(False)
        chart_scope_layout1.addWidget(self.scope_end_date)
        parameter_layout.addLayout(chart_scope_layout1)
        parameter_layout.addWidget(QPushButton(
            '画图预览', clicked=self.review_chart_clicked),
                                   alignment=Qt.AlignRight)
        self.chart_parameter.setMaximumWidth(350)
        self.chart_parameter.setLayout(parameter_layout)
        # 参数设置控件加入布局
        layout.addWidget(self.chart_parameter)
        # 预览控件
        self.review_widget = QWidget(parent=self)
        review_layout = QVBoxLayout(margin=0)
        review_layout.addWidget(QLabel('图表预览', objectName='widgetTip'))
        self.review_chart = QChartView()
        self.review_chart.setRenderHint(QPainter.Antialiasing)
        review_layout.addWidget(self.review_chart)
        # # 图例显示区
        # self.legend_view = QWidget(parent=self.review_widget)
        # legend_layout = QGridLayout()
        # self.legend_view.setLayout(legend_layout)
        # review_layout.addWidget(self.legend_view)
        # 确认设置
        commit_layout = QHBoxLayout()
        commit_layout.addStretch()
        self.current_start = QCheckBox('当前起始')
        commit_layout.addWidget(self.current_start)
        self.current_end = QCheckBox('当前截止')
        commit_layout.addWidget(self.current_end)
        commit_layout.addWidget(
            QPushButton('确认设置', clicked=self.commit_add_chart))
        review_layout.addLayout(commit_layout)
        # 表详情数据显示
        self.detail_trend_table = QTableWidget()
        self.detail_trend_table.setMaximumHeight(200)
        review_layout.addWidget(self.detail_trend_table)
        self.review_widget.setLayout(review_layout)
        layout.addWidget(self.review_widget)
        self.setLayout(layout)
        self.setMinimumWidth(950)
        self.setMaximumHeight(550)
        self.has_review_chart = False
        self.setStyleSheet("""
        #widgetTip{
            color: rgb(50,80,180);
            font-weight:bold
        }
        #headTip{
            font-weight:bold
        }
        #addAxis{
            max-width:40px
        }
        """)

    # x轴选择改变
    def x_axis_changed(self):
        self.column_header_list.clear()
        for header_index in range(
                self.detail_trend_table.horizontalHeader().count()):
            text = self.detail_trend_table.horizontalHeaderItem(
                header_index).text()
            if text == self.x_axis_combo.currentText():
                continue
            self.column_header_list.addItem(text)
        # 清空左轴和右轴的设置
        self.right_top_list.clear()
        self.right_bottom_list.clear()

    # 移除当前列表中的item
    def remove_toplist_item(self, index):
        row = self.right_top_list.currentRow()
        self.right_top_list.takeItem(row)

    def remove_bottomlist_item(self, index):
        row = self.right_bottom_list.currentRow()
        self.right_bottom_list.takeItem(row)

    # 加入左轴
    def add_y_left(self):
        text_in = list()
        for i in range(self.right_top_list.count()):
            text_in.append(self.right_top_list.item(i).text())
        item = self.column_header_list.currentItem()  # 获取item
        if item is not None:
            if item.text() not in text_in:
                self.right_top_list.addItem(item.text())

    # 加入右轴
    def add_y_right(self):
        text_in = list()
        for i in range(self.right_bottom_list.count()):
            text_in.append(self.right_bottom_list.item(i).text())
        item = self.column_header_list.currentItem()  # 获取item
        if item is not None:
            if item.text() not in text_in:
                self.right_bottom_list.addItem(item.text())

    # 预览数据
    def review_chart_clicked(self):
        try:
            chart_name = self.chart_name.text()
            chart_category = self.chart_category_combo.currentText()
            # 根据设置从表格中获取画图源数据
            x_axis = self.x_axis_combo.currentText()  # x轴
            left_y_axis = [
                self.right_top_list.item(i).text()
                for i in range(self.right_top_list.count())
            ]
            right_y_axis = [
                self.right_bottom_list.item(i).text()
                for i in range(self.right_bottom_list.count())
            ]
            # 根据表头将这些列名称换为索引
            x_axis_col = list()
            left_y_cols = list()
            right_y_cols = list()
            header_data = list()
            for header_index in range(
                    self.detail_trend_table.horizontalHeader().count()):
                text = self.detail_trend_table.horizontalHeaderItem(
                    header_index).text()
                header_data.append(text)
                if text == x_axis:
                    x_axis_col.append(header_index)
                for y_left in left_y_axis:
                    if y_left == text:
                        left_y_cols.append(header_index)
                for y_right in right_y_axis:
                    if y_right == text:
                        right_y_cols.append(header_index)
            # 判断是否选择了左轴
            if not left_y_cols:
                popup = InformationPopup(message='请至少选择一列左轴数据。', parent=self)
                if not popup.exec_():
                    popup.deleteLater()
                    del popup
                return
            # 根据设置画图
            start_date = self.scope_start_date.date().toString('yyyy-MM-dd')
            start_date = pd.to_datetime(start_date)
            end_date = self.scope_end_date.date().toString('yyyy-MM-dd')
            end_date = pd.to_datetime(end_date)
            df = self.table_data_frame.copy()
            final_df = df.loc[(df[0] >= start_date)
                              & (df[0] <= end_date)].copy()  # 根据时间范围取数
            # 根据类型进行画图
            if chart_category == u'折线图':  # 折线图
                chart = lines_stacked(name=chart_name,
                                      table_df=final_df,
                                      x_bottom_cols=x_axis_col,
                                      y_left_cols=left_y_cols,
                                      y_right_cols=right_y_cols,
                                      legend_labels=header_data,
                                      tick_count=12)
                # 设置图例
                # chart.legend().hide()
                # markers = chart.legend().markers()
                # print(markers)
                # row_index = 0
                # col_index = 0
                # for marker in chart.legend().markers():
                #     print(marker.series().name())
                #     # from PyQt5.QtChart import QLineSeries
                #     # QLineSeries.name()
                #     # 每条线设置一个label
                #     legend_label = QLabel(marker.series().name())
                #     self.legend_view.layout().addWidget(legend_label, row_index, col_index)
                #     col_index += 1
                #     if col_index >= 3:
                #         row_index += 1
                #         col_index = 0

            elif chart_category == u'柱形图':
                chart = bars_stacked(name=chart_name,
                                     table_df=final_df,
                                     x_bottom_cols=x_axis_col,
                                     y_left_cols=left_y_cols,
                                     y_right_cols=right_y_cols,
                                     legend_labels=header_data,
                                     tick_count=12)
            else:
                popup = InformationPopup(message='当前设置不适合作图或系统暂不支持作图。',
                                         parent=self)
                if not popup.exec_():
                    popup.deleteLater()
                    del popup
                return
            self.review_chart.setChart(chart)
            self.has_review_chart = True
        except Exception as e:
            popup = InformationPopup(message=str(e), parent=self)
            if not popup.exec_():
                popup.deleteLater()
                del popup

    # 确认添加本张图表
    def commit_add_chart(self):
        if not self.has_review_chart:
            info = InformationPopup(message='请先预览图表,再进行设置!', parent=self)
            if not info.exec_():
                info.deleteLater()
                del info
            return
        category_dict = {
            '折线图': 'line',
            '柱形图': 'bar',
        }
        chart_name = re.sub(r'\s+', '', self.chart_name.text())
        category = category_dict.get(self.chart_category_combo.currentText(),
                                     None)
        if not all([chart_name, category]):
            info = InformationPopup(message='请设置图表名称和图表类型!', parent=self)
            if not info.exec_():
                info.deleteLater()
                del info
            return
        # 根据设置从表格中获取数据把选择的列头变为索引
        x_axis = self.x_axis_combo.currentText()  # x轴
        left_y_axis = [
            self.right_top_list.item(i).text()
            for i in range(self.right_top_list.count())
        ]
        right_y_axis = [
            self.right_bottom_list.item(i).text()
            for i in range(self.right_bottom_list.count())
        ]
        # 根据表头将这些列名称换为索引
        x_axis_cols = list()
        left_y_cols = list()
        right_y_cols = list()
        for header_index in range(
                self.detail_trend_table.horizontalHeader().count()):
            text = self.detail_trend_table.horizontalHeaderItem(
                header_index).text()
            if text == x_axis:
                x_axis_cols.append(header_index)
            for y_left in left_y_axis:
                if y_left == text:
                    left_y_cols.append(header_index)
            for y_right in right_y_axis:
                if y_right == text:
                    right_y_cols.append(header_index)
        if not x_axis_cols:
            info = InformationPopup(message='请设置图表X轴!', parent=self)
            if not info.exec_():
                info.deleteLater()
                del info
            return
        if not left_y_cols:
            info = InformationPopup(message='至少左轴要有一列数据!', parent=self)
            if not info.exec_():
                info.deleteLater()
                del info
            return
        # 获取轴名称
        x_bottom_labels = re.split(r';', self.bottom_x_label_edit.text())
        y_left_labels = re.split(r';', self.left_y_label_edit.text())
        y_right_labels = re.split(r';', self.right_y_label_edit.text())
        chart_params = dict()
        chart_params['table_id'] = self.table_id
        chart_params['name'] = chart_name
        chart_params['category'] = category
        chart_params['x_bottom'] = x_axis_cols
        chart_params['x_bottom_label'] = x_bottom_labels
        chart_params['x_top'] = []
        chart_params['x_top_label'] = []
        chart_params['y_left'] = left_y_cols
        chart_params['y_left_label'] = y_left_labels
        chart_params['y_right'] = right_y_cols
        chart_params['y_right_label'] = y_right_labels
        chart_params['is_top'] = False
        if self.current_start.isChecked():
            # print('设置当前起始范围')
            chart_params['start'] = self.scope_start_date.date().toString(
                'yyyy-MM-dd')
        if self.current_end.isChecked():
            # print('设置当前截止')
            chart_params['end'] = self.scope_end_date.date().toString(
                'yyyy-MM-dd')
        # print(chart_params)
        # 上传数据
        try:
            r = requests.post(url=settings.SERVER_ADDR + 'trend/chart/?mc=' +
                              settings.app_dawn.value('machine'),
                              headers={
                                  'AUTHORIZATION':
                                  settings.app_dawn.value('AUTHORIZATION')
                              },
                              data=json.dumps(chart_params))
            response = json.loads(r.content.decode('utf-8'))
            if r.status_code != 201:
                raise ValueError(response['message'])
            message = response['message']
        except Exception as e:
            message = str(e)
        info = InformationPopup(message=message, parent=self)
        if not info.exec_():
            info.deleteLater()
            del info

    # 获取当前表的数据(预用来设置显示图的数据)
    def getCurrentTrendTable(self):
        try:
            r = requests.get(url=settings.SERVER_ADDR + 'trend/table/' +
                             str(self.table_id) + '/?look=1&mc=' +
                             settings.app_dawn.value('machine'))
            response = json.loads(r.content.decode('utf-8'))
            if r.status_code != 200:
                raise ValueError(response['message'])
        except Exception:
            pass
        else:
            column_headers = response['data']['header_data']
            column_headers.pop(0)
            self.x_axis_combo.addItems(column_headers)  # X轴选择
            for text in column_headers:
                if text in self.x_axis_combo.currentText():
                    continue
                self.column_header_list.addItem(text)  # 列头待选表
            # pandas处理数据
            self.table_data_frame = self.pd_handler_data(
                response['data']['table_data'])
            # 填充表格
            self.showTableData(column_headers, self.table_data_frame)

    # pandas 处理数据
    def pd_handler_data(self, table_data):
        # 转为DF
        table_df = pd.DataFrame(table_data)
        table_df.drop(columns=[0], inplace=True)  # 删除id列
        table_df.columns = [i for i in range(table_df.shape[1])]  # 重置列索引
        table_df[0] = pd.to_datetime(table_df[0])  # 第一列转为时间类型
        table_df.sort_values(by=0, inplace=True)  # 根据时间排序数据
        # 计算数据时间跨度大小显示在范围上
        min_x, max_x = table_df[0].min(), table_df[0].max(
        )  # 第一列时间数据(x轴)的最大值和最小值
        self.scope_start_date.setDateRange(QDate(min_x), QDate(max_x))
        self.scope_end_date.setDateRange(QDate(min_x), QDate(max_x))
        self.scope_start_date.setEnabled(True)
        self.scope_end_date.setEnabled(True)
        self.scope_end_date.setDate(self.scope_end_date.maximumDate())
        return table_df

    # 设置表格显示表数据内容
    def showTableData(self, headers, table_df):
        # 设置行列
        self.detail_trend_table.setRowCount(table_df.shape[0])
        col_count = len(headers)
        self.detail_trend_table.setColumnCount(col_count)
        self.detail_trend_table.setHorizontalHeaderLabels(headers)
        self.detail_trend_table.horizontalHeader().setSectionResizeMode(
            QHeaderView.ResizeToContents)
        for row, row_content in enumerate(table_df.values.tolist()):
            for col, value in enumerate(row_content):
                if col == 0:  # 时间类
                    value = value.strftime('%Y-%m-%d')
                item = QTableWidgetItem(value)
                item.setTextAlignment(Qt.AlignCenter)
                self.detail_trend_table.setItem(row, col, item)
class Ui_MainWindow(QtWidgets.QMainWindow):
    def setupUi(self):
        self.setObjectName("MainWindow")
        self.resize(600, 830)
        self.setWindowTitle("GA - Queens")
        self.centralwidget = QtWidgets.QWidget(self)
        self.centralwidget.setObjectName("centralwidget")
        self.frameWorld = MyQFrame(self.centralwidget)
        self.frameWorld.img = QPixmap(1000, 1000)
        self.frameWorld.setGeometry(QtCore.QRect(10, 10, 400, 400))
        self.frameWorld.setFrameShape(QtWidgets.QFrame.Box)
        self.frameWorld.setFrameShadow(QtWidgets.QFrame.Sunken)
        self.frameWorld.setObjectName("frameWorld")
        self.frameChart = QChartView(self.centralwidget)
        self.frameChart.setGeometry(QtCore.QRect(10, 420, 400, 400))
        self.frameChart.setFrameShape(QtWidgets.QFrame.Box)
        self.frameChart.setFrameShadow(QtWidgets.QFrame.Sunken)
        self.frameChart.setRenderHint(QPainter.Antialiasing)
        self.frameChart.setObjectName("frameChart")
        self.gaParams = QtWidgets.QGroupBox(self.centralwidget)
        self.gaParams.setGeometry(QtCore.QRect(430, 10, 161, 171))
        self.gaParams.setObjectName("gaParams")
        self.gaParams.setTitle("GA parameters")
        self.label1 = QtWidgets.QLabel(self.gaParams)
        self.label1.setGeometry(QtCore.QRect(10, 20, 61, 16))
        self.label1.setObjectName("label1")
        self.label1.setText("Population:")
        self.label2 = QtWidgets.QLabel(self.gaParams)
        self.label2.setGeometry(QtCore.QRect(10, 50, 47, 16))
        self.label2.setObjectName("label2")
        self.label2.setText("Mutation:")
        self.label3 = QtWidgets.QLabel(self.gaParams)
        self.label3.setGeometry(QtCore.QRect(10, 80, 81, 16))
        self.label3.setObjectName("label3")
        self.label3.setText("Elite members:")
        self.label4 = QtWidgets.QLabel(self.gaParams)
        self.label4.setGeometry(QtCore.QRect(10, 110, 91, 16))
        self.label4.setObjectName("label4")
        self.label4.setText("No. generations:")
        self.cbxPermutation = QtWidgets.QCheckBox(self.gaParams)
        self.cbxPermutation.setGeometry(QtCore.QRect(35, 140, 91, 17))
        self.cbxPermutation.setObjectName("cbxPermutation")
        self.cbxPermutation.setText("Permutation")
        self.tbxPopulation = QtWidgets.QLineEdit(self.gaParams)
        self.tbxPopulation.setGeometry(QtCore.QRect(100, 20, 51, 20))
        self.tbxPopulation.setObjectName("tbxPopulation")
        self.tbxMutation = QtWidgets.QLineEdit(self.gaParams)
        self.tbxMutation.setGeometry(QtCore.QRect(100, 50, 51, 20))
        self.tbxMutation.setObjectName("tbxMutation")
        self.tbxElite = QtWidgets.QLineEdit(self.gaParams)
        self.tbxElite.setGeometry(QtCore.QRect(100, 80, 51, 20))
        self.tbxElite.setObjectName("tbxElite")
        self.tbxGenerations = QtWidgets.QLineEdit(self.gaParams)
        self.tbxGenerations.setGeometry(QtCore.QRect(100, 110, 51, 20))
        self.tbxGenerations.setObjectName("tbxGenerations")
        self.label5 = QtWidgets.QLabel(self.centralwidget)
        self.label5.setGeometry(QtCore.QRect(440, 190, 61, 16))
        self.label5.setObjectName("label5")
        self.label5.setText("No. queens:")
        self.tbxNoQueens = QtWidgets.QLineEdit(self.centralwidget)
        self.tbxNoQueens.setGeometry(QtCore.QRect(510, 190, 51, 20))
        self.tbxNoQueens.setObjectName("tbxNoQueens")
        self.cbxNoVis = QtWidgets.QCheckBox(self.centralwidget)
        self.cbxNoVis.setGeometry(QtCore.QRect(420, 215, 170, 17))
        self.cbxNoVis.setObjectName("cbxNoVis")
        self.cbxNoVis.setText("No visualization per generation")
        self.btnStart = QtWidgets.QPushButton(self.centralwidget)
        self.btnStart.setGeometry(QtCore.QRect(430, 250, 75, 23))
        self.btnStart.setObjectName("btnStart")
        self.btnStart.setText("Start")
        self.btnStop = QtWidgets.QPushButton(self.centralwidget)
        self.btnStop.setEnabled(False)
        self.btnStop.setGeometry(QtCore.QRect(510, 250, 75, 23))
        self.btnStop.setObjectName("btnStop")
        self.btnStop.setText("Stop")
        self.btnSaveWorld = QtWidgets.QPushButton(self.centralwidget)
        self.btnSaveWorld.setGeometry(QtCore.QRect(430, 370, 121, 41))
        self.btnSaveWorld.setObjectName("btnSaveWorld")
        self.btnSaveWorld.setText("Save world as image")
        self.btnSaveChart = QtWidgets.QPushButton(self.centralwidget)
        self.btnSaveChart.setGeometry(QtCore.QRect(430, 730, 121, 41))
        self.btnSaveChart.setObjectName("btnSaveChart")
        self.btnSaveChart.setText("Save chart as image")
        self.btnSaveChartSeries = QtWidgets.QPushButton(self.centralwidget)
        self.btnSaveChartSeries.setGeometry(QtCore.QRect(430, 780, 121, 41))
        self.btnSaveChartSeries.setObjectName("btnSaveChartSeries")
        self.btnSaveChartSeries.setText("Save chart as series")
        self.setCentralWidget(self.centralwidget)
        QtCore.QMetaObject.connectSlotsByName(self)

        #Connect events
        self.btnStart.clicked.connect(self.btnStart_Click)
        self.btnStop.clicked.connect(self.btnStop_Click)
        self.btnSaveWorld.clicked.connect(self.btnSaveWorld_Click)
        self.btnSaveChart.clicked.connect(self.btnSaveChart_CLick)
        self.btnSaveChartSeries.clicked.connect(self.btnSaveChartSeries_Click)

        #Set default GA variables
        self.tbxNoQueens.insert(str(NO_QUEENS))
        self.tbxGenerations.insert(str(NGEN))
        self.tbxPopulation.insert(str(POP_SIZE))
        self.tbxMutation.insert(str(MUTPB))
        self.tbxElite.insert(str(NELT))

        self.new_image = QPixmap(1000, 1000)

    def btnStart_Click(self):

        global success  # Number of times when fitness function reached 0 -- Added by Denis Lazor
        global generations  # Number of times when fitness function reached 0 -- Added by Denis Lazor
        global combination_series  # List of lists containing min_series of 5 correct results -- Added by Denis Lazor
        global parameter_name  # Name of parameter used for writing its data to .csv file -- Added by Denis Lazor

        global ELITE_SIZES
        global BOARD_SIZES
        global POPULATION_SIZES
        global MUTATION_SIZES

        # Checking if files are empty or not -- Added by Denis Lazor
        csv_contains = os.stat("graphs_csv/original_.csv").st_size != 0
        csv_contains_permutation = os.stat(
            "graphs_csv/original_permutation.csv").st_size != 0
        permutation_checked = self.cbxPermutation.isChecked()

        # Clearing non empty files if we are trying to write to them -- Added by Denis Lazor
        if csv_contains_permutation and permutation_checked:
            clear_all_csv("p")
        if csv_contains and not permutation_checked:
            clear_all_csv("np")

        BOARD_SIZES = [12, 24]
        n = 5000
        # Automation for all necessary combinations -- Added by Denis Lazor
        for b in BOARD_SIZES:
            # Because we use slicing we need to restore parameters lists after changing board size
            POPULATION_SIZES = [50, 100, 200]
            MUTATION_SIZES = [0.04, 0.08, 0.16]
            ELITE_SIZES = [4, 8, 16]

            for p in POPULATION_SIZES:
                for m in MUTATION_SIZES:
                    for e in ELITE_SIZES:

                        success = 0
                        trials = 0  # Number of tries needed to find 5 'correct' results -- Added by Denis Lazor

                        while success < 5:  # Doing same combination till we get 5 'correct' results -- Added by Denis Lazor
                            trials = trials + 1

                            # Set global variables
                            global stop_evolution
                            global q_min_series
                            global q_max_series
                            global q_avg_series
                            stop_evolution = False
                            q_min_series.clear()
                            q_max_series.clear()
                            q_avg_series.clear()

                            # Set global variables from information on UI
                            global NO_QUEENS
                            global NGEN
                            global POP_SIZE
                            global MUTPB
                            global NELT
                            NO_QUEENS = b
                            NGEN = n
                            POP_SIZE = p
                            MUTPB = m
                            NELT = e

                            # Painting chess table
                            self.img = QPixmap(1000, 1000)
                            self.img.fill()
                            painter = QPainter(self.img)
                            painter.setPen(QPen(Qt.black, 10, Qt.SolidLine))
                            width = 1000 / NO_QUEENS
                            cur_width = 0
                            for i in range(
                                    NO_QUEENS + 1
                            ):  # +1 in order to draw the last line as well
                                painter.drawLine(cur_width, 0, cur_width, 1000)
                                painter.drawLine(0, cur_width, 1000, cur_width)
                                cur_width += width
                            painter.end()
                            self.frameWorld.img = self.img
                            # Redrawing frames
                            self.frameWorld.repaint()
                            app.processEvents()

                            ####Initialize deap GA objects####

                            # Make creator that minimize. If it would be 1.0 instead od -1.0 than it would be maxmize
                            creator.create("FitnessMin",
                                           base.Fitness,
                                           weights=(-1.0, ))

                            # Create an individual (a blueprint for cromosomes) as a list with a specified fitness type
                            creator.create("Individual",
                                           list,
                                           fitness=creator.FitnessMin)

                            # Create base toolbox for finishing creation of a individual (cromosome)
                            self.toolbox = base.Toolbox()

                            # Define what type of data (number, gene) will it be in the cromosome
                            if self.cbxPermutation.isChecked():
                                # Permutation coding
                                self.toolbox.register("indices", random.sample,
                                                      range(NO_QUEENS),
                                                      NO_QUEENS)
                                # initIterate requires that the generator of genes (such as random.sample) generates an iterable (a list) variable
                                self.toolbox.register("individual",
                                                      tools.initIterate,
                                                      creator.Individual,
                                                      self.toolbox.indices)
                            else:
                                # Standard coding
                                self.toolbox.register(
                                    "attr_int", random.randint, 0,
                                    NO_QUEENS - 1
                                )  # number in cromosome is from 0 till IND_SIZE - 1
                                # Initialization procedure (initRepeat) for the cromosome. For the individual to be completed we need to run initRepeat for the amaout of genes the cromosome includes
                                self.toolbox.register("individual",
                                                      tools.initRepeat,
                                                      creator.Individual,
                                                      self.toolbox.attr_int,
                                                      n=NO_QUEENS)

                            # Create a population of individuals (cromosomes). The population is then created by toolbox.population(n=300) where 'n' is the number of cromosomes in population
                            self.toolbox.register("population",
                                                  tools.initRepeat, list,
                                                  self.toolbox.individual)

                            # Register evaluation function
                            self.toolbox.register("evaluate", evaluateInd)

                            # Register what genetic operators to use
                            if self.cbxPermutation.isChecked():
                                # Permutation coding
                                self.toolbox.register(
                                    "mate",
                                    tools.cxUniformPartialyMatched,
                                    indpb=0.2
                                )  # Use uniform recombination for permutation coding
                                self.toolbox.register("mutate",
                                                      tools.mutShuffleIndexes,
                                                      indpb=0.2)
                            else:
                                # Standard coding
                                self.toolbox.register(
                                    "mate", tools.cxTwoPoint
                                )  # Use two point recombination
                                self.toolbox.register(
                                    "mutate",
                                    tools.mutUniformInt,
                                    low=0,
                                    up=NO_QUEENS - 1,
                                    indpb=0.2)  # 20% that the gene will change

                            self.toolbox.register(
                                "select", tools.selTournament,
                                tournsize=3)  # Use tournament selection

                            ##################################

                            # Generate initial poplation. Will be a member variable so we can easely pass everything to new thread
                            self.pop = self.toolbox.population(n=POP_SIZE)

                            # Evaluate initial population, we map() the evaluation function to every individual and then assign their respective fitness, map runs evaluate function for each individual in pop
                            fitnesses = list(
                                map(self.toolbox.evaluate, self.pop))
                            for ind, fit in zip(self.pop, fitnesses):
                                ind.fitness.values = fit  # Assign calcualted fitness value to individuals

                            # Extracting all the fitnesses of all individuals in a population so we can monitor and evovlve the algorithm until it reaches 0 or max number of generation is reached
                            self.fits = [
                                ind.fitness.values[0] for ind in self.pop
                            ]

                            self.fits

                            # Disable start and enable stop
                            self.btnStart.setEnabled(False)
                            self.btnStop.setEnabled(True)
                            self.gaParams.setEnabled(False)
                            self.tbxNoQueens.setEnabled(False)
                            self.cbxNoVis.setEnabled(False)

                            # Start evolution
                            self.evolve()

                        # Mean number of generations nedeed for finding 5 correct solutions -- Added by Denis Lazor
                        mean_gen = min(generations,
                                       key=lambda x: abs(x - statistics.mean(
                                           generations)))
                        # Index of mean_gen value -- Added by Denis Lazor
                        mean_idx = generations.index(mean_gen)

                        write_to_file(
                            combination_series[mean_idx], parameter_name,
                            permutation_checked
                        )  # First name will be "original", second one "elites" -- Added by Denis Lazor
                        parameter_name = "elites"

                        print_results(b, p, m, e, trials, generations,
                                      mean_gen, NGEN)

                        # Clearing past lists  -- Added by Denis Lazor
                        generations = []
                        combination_series = []

                    # Reducing number of combinations and changing .csv file for writing -- Added by Denis Lazor
                    ELITE_SIZES = ELITE_SIZES[0:1]
                    parameter_name = "mutation"
                MUTATION_SIZES = MUTATION_SIZES[0:1]
                parameter_name = "population"
            POPULATION_SIZES = POPULATION_SIZES[0:1]
            parameter_name = "original"

            n = 30000  # Increasing generation size for 24x24 board

    def btnStop_Click(self):
        global stop_evolution
        stop_evolution = True
        #Disable stop and enable start
        self.btnStop.setEnabled(False)
        self.btnStart.setEnabled(True)
        self.gaParams.setEnabled(True)
        self.tbxNoQueens.setEnabled(True)
        self.cbxNoVis.setEnabled(True)

    #Function for GA evolution
    def evolve(self):
        global q_min_series
        global q_max_series
        global q_avg_series
        global success
        global generations
        global combination_series
        global NO_QUEENS
        global NGEN
        global POP_SIZE
        global MUTPB
        global NELT

        combination_current_series = []

        # Variable for keeping track of the number of generations
        curr_g = 0

        # Begin the evolution till goal is reached or max number of generation is reached
        while min(self.fits) != 0 and curr_g < NGEN:
            #Check if evolution and thread need to stop
            if stop_evolution:
                break  #Break the evolution loop

            # A new generation
            curr_g = curr_g + 1
            #print("-- Generation %i --" % curr_g)

            # Select the next generation individuals
            #Select POP_SIZE - NELT number of individuals. Since recombination is between neigbours, not two naighbours should be the clone of the same individual
            offspring = []
            offspring.append(self.toolbox.select(
                self.pop, 1)[0])  #add first selected individual
            for i in range(
                    POP_SIZE - NELT - 1
            ):  # -1 because the first seleceted individual is already added
                while True:
                    new_o = self.toolbox.select(self.pop, 1)[0]
                    if new_o != offspring[len(
                            offspring
                    ) - 1]:  #if it is different than the last inserted then add to offspring and break
                        offspring.append(new_o)
                        break

            # Clone the selected individuals because all of the changes are inplace
            offspring = list(map(self.toolbox.clone, offspring))

            # Apply crossover on the selected offspring
            for child1, child2 in zip(offspring[::2], offspring[1::2]):
                self.toolbox.mate(child1, child2)  #inplace recombination
                #Invalidate new children fitness values
                del child1.fitness.values
                del child2.fitness.values

            #Apply mutation on the offspring
            for mutant in offspring:
                if random.random() < MUTPB:
                    self.toolbox.mutate(mutant)
                    del mutant.fitness.values

            #Add elite individuals #Is clonning needed?
            offspring.extend(
                list(map(self.toolbox.clone, tools.selBest(self.pop, NELT))))

            # Evaluate the individuals with an invalid fitness
            invalid_ind = [ind for ind in offspring if not ind.fitness.valid]
            fitnesses = map(self.toolbox.evaluate, invalid_ind)
            for ind, fit in zip(invalid_ind, fitnesses):
                ind.fitness.values = fit

            #print("  Evaluated %i individuals" % len(invalid_ind))

            #Replace population with offspring
            self.pop[:] = offspring

            # Gather all the fitnesses in one list and print the stats
            self.fits = [ind.fitness.values[0] for ind in self.pop]

            length = len(self.pop)
            mean = sum(self.fits) / length
            sum2 = sum(x * x for x in self.fits)
            std = abs(sum2 / length - mean**2)**0.5

            q_min_series.append(curr_g, min(self.fits))
            q_max_series.append(curr_g, max(self.fits))
            q_avg_series.append(curr_g, mean)

            combination_current_series.append(
                min(self.fits)
            )  # Saving min_series fitness values of an experiment -- Added by Denis Lazor

            # Checking if fitness value of 0 is reached -- Added by Denis Lazor
            for f in self.fits:
                if f == 0:
                    success = success + 1
                    generations.append(curr_g)
                    combination_series.append(combination_current_series)
                    break

            #print("  Min %s" % q_min_series.at(q_min_series.count()-1).y())
            #print("  Max %s" % q_max_series.at(q_max_series.count()-1).y())
            #print("  Avg %s" % mean)
            #print("  Std %s" % std)

            if self.cbxNoVis.isChecked():
                app.processEvents()
            else:
                #Draw queen positions of best individual on a image
                best_ind = tools.selBest(self.pop, 1)[0]
                self.updateWorldFrame(generateQueenImage(best_ind))

                self.chart = QChart()
                #self.chart.addSeries(q_min_series)
                #self.chart.addSeries(q_max_series)
                #q_avg_series.setName("Board: " + str(b) + " Population: " + str(p) + " Elite: " + str(e) + " Mutation:" + str(m*100) + "% " + "Generations:" + str(NGSEN))
                self.chart.addSeries(q_avg_series)
                self.chart.setTitle("QN: " + str(NO_QUEENS) + " POP: " +
                                    str(POP_SIZE) + " EL: " + str(NELT) +
                                    " MT: " + str(MUTPB * 100) + "% ")
                self.chart.setAnimationOptions(QChart.NoAnimation)
                self.chart.createDefaultAxes()
                self.frameChart.setChart(self.chart)

        #Printing best individual
        best_ind = tools.selBest(self.pop, 1)[0]
        #print("Best individual is %s, %s \n" % (best_ind, best_ind.fitness.values))

        #Visulaize final solution
        if self.cbxNoVis.isChecked():
            #Draw queen positions of best individual on a image
            best_ind = tools.selBest(self.pop, 1)[0]
            self.updateWorldFrame(generateQueenImage(best_ind))

            self.chart = QChart()
            #self.chart.addSeries(q_min_series)
            #self.chart.addSeries(q_max_series)
            self.chart.addSeries(q_avg_series)
            self.chart.setTitle("QN: " + str(NO_QUEENS) + " POP: " +
                                str(POP_SIZE) + " EL: " + str(NELT) + " MT: " +
                                str(MUTPB * 100) + "% ")
            self.chart.setAnimationOptions(QChart.NoAnimation)
            self.chart.createDefaultAxes()
            self.frameChart.setChart(self.chart)

        #Disable stop and enable start
        self.btnStop.setEnabled(False)
        self.btnStart.setEnabled(True)
        self.gaParams.setEnabled(True)
        self.tbxNoQueens.setEnabled(True)
        self.cbxNoVis.setEnabled(True)

    def updateWorldFrame(self, queens_img):
        #new_image = QPixmap(1000,1000)
        self.new_image.fill()  #White color is default
        painter = QPainter(self.new_image)
        #First draw the table
        painter.drawPixmap(self.new_image.rect(), self.img)
        #Then draw the queens
        painter.drawImage(self.new_image.rect(), queens_img)
        painter.end()
        #Set new image to the frame
        self.frameWorld.img = self.new_image
        #Redrawing frames
        self.frameWorld.repaint()
        self.frameChart.repaint()
        app.processEvents()

    def btnSaveWorld_Click(self):
        filename, _ = QFileDialog.getSaveFileName(None,
                                                  "Save world as a image", "",
                                                  "Image Files (*.png)")
        self.frameWorld.img.save(filename, "PNG")
        print("World image saved to: ", filename)

    def btnSaveChart_CLick(self):
        p = self.frameChart.grab()
        filename, _ = QFileDialog.getSaveFileName(
            None, "Save series chart as a image", "", "Image Files (*.png)")
        p.save(filename, "PNG")
        print("Chart series image saved to: ", filename)

    def btnSaveChartSeries_Click(self):
        global q_min_series
        global q_max_series
        global q_avg_series
        filename, _ = QFileDialog.getSaveFileName(None,
                                                  "Save series to text file",
                                                  "",
                                                  "Text Files (*.txt, *.csv)")
        with open(filename, 'w') as dat:
            for i in range(q_min_series.count()):
                dat.write('%f,%f,%f\n' %
                          (q_min_series.at(i).y(), q_avg_series.at(i).y(),
                           q_max_series.at(i).y()))
        print("Chart series saved to: ", filename)
Beispiel #29
0
class Demo(QWidget,QFont):
    def __init__(self):
        super(Demo,self).__init__()     #子类调用父类的方法
        self.BuildUI()                  #构造界面
        self.CreatChart()               #创建曲线
        self.connection()

##==============自定义功能函数============
    def BuildUI(self):   ##构造界面
        self.resize(800, 600)
        self.setFont(QFont("黑体", 10.5))  ##设置字体
        self.setWindowTitle("水工标准设计反应谱v1.1(Hs小毕)")  ##s设置窗口标题
        self.setWindowIcon(QIcon(':/fyp.ico'))

        # 定义控件
        #定义“输入”控件===========================
        self.label1 = QLabel("水工建筑物类型", self)
        # 标准设计反应谱最大值的代表值
        BEITA = ["土石坝", "重力坝", "拱坝", "水闸|进水塔|边坡|其他"]
        self.comboBox1 = QComboBox()
        self.comboBox1.addItems(BEITA)
        self.comboBox1.setCurrentIndex(1)  # 设置默认值
        self.label2 = QLabel("特征周期Tg(s)", self)
        self.line2 = QLineEdit()
        self.line2.setPlaceholderText("单位(s)")
        self.label3 = QLabel("加速度幅值A(g)", self)
        self.line3 = QLineEdit()
        self.line3.setPlaceholderText("单位(g)")
        self.groupbox_1 = QGroupBox('输入数据', self)
        self.v_layout = QVBoxLayout()
        self.v_layout.addWidget(self.label1)
        self.v_layout.addWidget(self.comboBox1)
        self.v_layout.addWidget(self.label2)
        self.v_layout.addWidget(self.line2)
        self.v_layout.addWidget(self.label3)
        self.v_layout.addWidget(self.line3)
        self.groupbox_1.setLayout(self.v_layout)

        #定义“生成”控件===========================
        self.v1_layout = QVBoxLayout()
        self.groupbox_2 = QGroupBox('生成曲线', self)
        self.button1 = QPushButton("生成曲线",self)
        self.v1_layout.addWidget(self.button1)
        self.groupbox_2.setLayout(self.v1_layout)

        #定义“输出单位”控件
        self.groupbox_3 = QGroupBox('输出单位', self)
        self.h_layout = QHBoxLayout()
        self.unit_g = QRadioButton('g', self)
        self.unit_g.setChecked(True)                #设置单位“g”为默认
        self.unit_m = QRadioButton('m/sec2', self)
        self.unit_mm = QRadioButton('mm/sec2', self)
        self.h_layout.addWidget(self.unit_g)
        self.h_layout.addWidget(self.unit_m)
        self.h_layout.addWidget(self.unit_mm)
        self.groupbox_3.setLayout(self.h_layout)
        #定义输出的列数
        self.groupbox_4 = QGroupBox('输出列数', self)
        self.h1_layout = QHBoxLayout()
        self.list2 = QRadioButton('时间|谱值')
        self.list2.setChecked(True)  # 设置时间|谱值为默认
        self.list1 = QRadioButton('谱值')
        self.h1_layout.addWidget(self.list2)
        self.h1_layout.addWidget(self.list1)
        self.groupbox_4.setLayout(self.h1_layout)
        #输出时间间隔
        self.groupbox_5 = QGroupBox('输出时间间隔(s)', self)
        self.v2_layout = QHBoxLayout()
        self.Dtime = QRadioButton('0.01')
        self.Dtime.setChecked(True)  # 设置0.01s为默认
        self.Dtime_Edit = QLineEdit()
        self.Dtime1 = QRadioButton(self.Dtime_Edit)
        self.v2_layout.addWidget(self.Dtime)
        self.v2_layout.addWidget(self.Dtime1)
        self.v2_layout.addWidget(self.Dtime_Edit)
        self.groupbox_5.setLayout(self.v2_layout)
        #定义输出的文件选择
        self.groupbox_6 = QGroupBox('输出文件', self)
        self.v3_layout = QVBoxLayout()
        self.h3_layout = QHBoxLayout()
        self.Enter = QPushButton('点击输出',self)
        self.out_line=QLineEdit()
        self.out_select=QPushButton('浏览',self)
        self.h3_layout.addWidget(self.out_line)
        self.h3_layout.addWidget(self.out_select)
        self.v3_layout.addLayout(self.h3_layout)
        self.v3_layout.addWidget(self.Enter)
        self.groupbox_6.setLayout(self.v3_layout)

        # 定义绘图控件===========================
        self.chartView = QChartView()  # 创建 ChartView
        self.v6_layout = QVBoxLayout()
        self.v6_layout.addWidget(self.groupbox_1)
        self.v6_layout.addWidget(self.groupbox_2)
        self.v6_layout.addWidget(self.groupbox_3)
        self.v6_layout.addWidget(self.groupbox_4)
        self.v6_layout.addWidget(self.groupbox_5)
        self.v6_layout.addWidget(self.groupbox_6)

        self.h4_layout = QHBoxLayout()
        self.h4_layout.addLayout(self.v6_layout)
        self.h4_layout.addWidget(self.chartView)
        self.setLayout(self.h4_layout)

    def CreatChart(self):
        self.chart = QChart()  # 创建 Chart
        self.chart.setTitle("反应谱曲线")
        self.chartView.setChart(self.chart)  # Chart添加到ChartView
        # 创建曲线序列
        self.series0 = QLineSeries()
        self.chart.addSeries(self.series0)  # 序列添加到图表
        self.chart.createDefaultAxes()
        ##创建坐标轴
        self.axisX = QValueAxis()  # X 轴
        self.axisX.setTitleText("T(s)")  # 标题
        self.axisX.setLabelFormat("%.1f")     #标签格式
        self.axisX.setTickCount(5)           #主分隔个数
        self.axisX.setMinorTickCount(4)
        self.axisY=QValueAxis()  # Y 轴
        self.axisY.setTitleText("Se/g")
        self.axisY.setTickCount(5)
        self.axisY.setMinorTickCount(4)
        self.axisY.setLabelFormat("%.2f")     #标签格式
        # 为序列设置坐标轴
        self.chart.setAxisX(self.axisX, self.series0)  # 为序列设置坐标轴
        self.chart.setAxisY(self.axisY, self.series0)

    def PrepareData(self):
        """
        定义绘图中的数据
        """
        # 序列添加数值
        Str_dict={"土石坝":1.6, "重力坝":2, "拱坝":2.5, "水闸|进水塔|边坡|其他":2.25}
        Str_list =self.comboBox1.currentText()
        BETA_Data = Str_dict[Str_list]
        # 特征周期
        TG = float(self.line2.text())
        # 加速度幅值
        PGA = float(self.line3.text())
        t = 0
        intv = 0.01
        pointCount = 301
        self.series0.clear()   #清楚数据========
        for T in range(pointCount):
            T= round(T * intv,2)
            if T <= 0.1:
                y1 = (BETA_Data-1)/(0.1-0)*T+1
            elif 0.1<T and T <= TG:
                y1= BETA_Data
            else:
                y1 = BETA_Data*(TG/T)**0.6
            y1 = y1 * PGA
            self.series0.append(T, y1)
        #设置坐标轴范围=========================
        self.axisX.setRange(0,3)
        self.axisY.setRange(0,BETA_Data*PGA+1)

    def outputfilename(self):
        """
        定义输出路径
        """
        dlg = QFileDialog()
        filt = "Srf Files(*.Srf);;Text Files (*.txt);;All Files (*)"
        fileName, _ =dlg.getSaveFileName(self, "另存为文件", ".",filt)
        self.out_line.setText(fileName)

    def Output_Data(self):
        """
        定义输出的数据
        """
        # 序列添加数值
        Str_dict={"土石坝":1.6, "重力坝":2, "拱坝":2.5, "水闸|进水塔|边坡|其他":2.25}
        Str_list =self.comboBox1.currentText()
        BETA_Data = Str_dict[Str_list]
        # 特征周期
        TG = float(self.line2.text())
        # 加速度幅值
        PGA = float(self.line3.text())
        # 输出单位
        if self.unit_g.isChecked()==True:
            UNIT = 1
        elif self.unit_g.isChecked()==True:
            UNIT = 9.81
        else:
            UNIT = 9810
        # 输出间隔
        if self.Dtime.isChecked()==True:
            intv = 0.01
        else:
            intv = float(self.Dtime_Edit.text())
        pointCount = 301
        fileNameout = QLineEdit.text(self.out_line)
        with open(fileNameout, 'w', encoding='gbk') as f_out:
            for T in range(pointCount):
                T = round(T * intv, 2)
                if T <= 0.1:
                    y1 = (BETA_Data - 1) / (0.1 - 0) * T + 1
                elif 0.1 < T and T <= TG:
                    y1 = BETA_Data
                else:
                    y1 = BETA_Data * (TG / T) ** 0.6
                y1 = y1 * PGA * UNIT
                if self.list2.isChecked()==True:
                    f_out.write(f"{T}\t\t{y1}\n")
                else:
                    f_out.write(f"{y1}\n")
    def connection(self):
        """
        槽函数
        """
        self.button1.clicked.connect(lambda: self.PrepareData())
        self.out_select.clicked.connect(lambda: self.outputfilename())
        self.Enter.clicked.connect(lambda: self.Output_Data())
Beispiel #30
0
class DataEntryForm(QWidget):
    def __init__(self):
        super().__init__()
        self.items = 0

        # Data
        self._data = {}

        # Left Side
        self.table = QTableWidget()
        self.table.setColumnCount(2)
        self.table.setHorizontalHeaderLabels(('Description', 'Price'))
        self.table.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch)

        self.layoutRight = QVBoxLayout()

        # Chart Widget
        self.chartView = QChartView()
        self.chartView.setRenderHint(QPainter.Antialiasing)

        self.lineEditDescription = QLineEdit()
        self.lineEditPrice = QLineEdit()
        self.buttonAdd = QPushButton('Add Expense')
        self.buttonClear = QPushButton('Clear All')
        self.buttonPlot = QPushButton('Pie Chart')

        self.buttonAdd.setEnabled(False)

        self.layoutRight.setSpacing(10)
        self.layoutRight.addWidget(QLabel('Description'))
        self.layoutRight.addWidget(self.lineEditDescription)
        self.layoutRight.addWidget(QLabel('Price'))
        self.layoutRight.addWidget(self.lineEditPrice)
        self.layoutRight.addWidget(self.buttonAdd)
        self.layoutRight.addWidget(self.buttonPlot)
        self.layoutRight.addWidget(self.chartView)
        self.layoutRight.addWidget(self.buttonClear)

        self.layout = QHBoxLayout()
        self.layout.addWidget(self.table, 50)
        self.layout.addLayout(self.layoutRight, 50)

        self.setLayout(self.layout)

        self.buttonClear.clicked.connect(self.reset_table)
        self.buttonPlot.clicked.connect(self.graph_chart)
        self.buttonAdd.clicked.connect(self.add_entry)

        self.lineEditDescription.textChanged[str].connect(self.check_disable)
        self.lineEditPrice.textChanged[str].connect(self.check_disable)

        self.fill_table()

    # Fill Table
    def fill_table(self, data=None):
        data = self._data if not data else data
        for desc, price in data.items():
            descItem = QTableWidgetItem(desc)
            priceItem = QTableWidgetItem('${0:.2f}'.format(price))
            priceItem.setTextAlignment(Qt.AlignRight | Qt.AlignCenter)
            self.table.insertRow(self.items)
            self.table.setItem(self.items, 0, descItem)
            self.table.setItem(self.items, 1, priceItem)
            self.items += 1

    # Add Entry
    def add_entry(self):
        desc = self.lineEditDescription.text()
        price = self.lineEditPrice.text()
        try:
            descItem = QTableWidgetItem(desc)
            priceItem = QTableWidgetItem('${0:.2f}'.format(float(price)))
            priceItem.setTextAlignment(Qt.AlignRight | Qt.AlignCenter)
            self.table.insertRow(self.items)
            self.table.setItem(self.items, 0, descItem)
            self.table.setItem(self.items, 1, priceItem)
            self.items += 1
            self.lineEditDescription.setText('')
            self.lineEditPrice.setText('')
        except ValueError:
            pass

    # Check If Buttons Are Disabled
    def check_disable(self):
        if self.lineEditDescription.text() and self.lineEditPrice.text():
            self.buttonAdd.setEnabled(True)
        else:
            self.buttonAdd.setEnabled(False)

    # Reset Table
    def reset_table(self):
        self.table.setRowCount(0)
        self.items = 0
        chart = QChart()
        self.chartView.setChart(chart)

    # Graph Data Chart
    def graph_chart(self):
        series = QPieSeries()
        for i in range(self.table.rowCount()):
            text = self.table.item(i, 0).text()
            val = float(self.table.item(i, 1).text().replace('$', ''))
            series.append(text, val)

        chart = QChart()
        chart.addSeries(series)
        chart.legend().setAlignment(Qt.AlignTop)
        self.chartView.setChart(chart)