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)
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()
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)
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]
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)
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)
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
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)
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)
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
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'
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)
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()
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]))
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)
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)
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)
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)
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)
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())
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)