class ChartView(QChartView,QChart): def __init__(self, *args, **kwargs): super(ChartView, self).__init__(*args, **kwargs) self.resize(800, 600) self.setRenderHint(QPainter.Antialiasing) # 抗锯齿 self.chart_init() self.timer_init() def timer_init(self): #使用QTimer,2秒触发一次,更新数据 self.timer = QTimer(self) self.timer.timeout.connect(self.drawLine) self.timer.start(100) def chart_init(self): self.chart = QChart() self.series = QScatterSeries() #设置曲线名称 self.series.setName("实时数据") self.series.setColor(QColor(255,0,0)) self.series.setMarkerSize(20.0) self.series.setPen(QPen(QtCore.Qt.PenStyle.NoPen)) #把曲线添加到QChart的实例中 self.chart.addSeries(self.series) #声明并初始化X轴,Y轴 self.dtaxisX = QDateTimeAxis() self.vlaxisY = QValueAxis() #设置坐标轴显示范围 self.dtaxisX.setMin(QDateTime.currentDateTime().addSecs(-300*1)) self.dtaxisX.setMax(QDateTime.currentDateTime().addSecs(0)) self.vlaxisY.setMin(0) self.vlaxisY.setMax(1500) #设置X轴时间样式 self.dtaxisX.setFormat("MM月dd hh:mm:ss") #设置坐标轴上的格点 self.dtaxisX.setTickCount(6) self.vlaxisY.setTickCount(11) #设置坐标轴名称 self.dtaxisX.setTitleText("时间") self.vlaxisY.setTitleText("量程") #设置网格不显示` #把坐标轴添加到chart中 self.chart.addAxis(self.dtaxisX,Qt.AlignBottom) self.chart.addAxis(self.vlaxisY,Qt.AlignLeft) #把曲线关联到坐标轴 self.series.attachAxis(self.dtaxisX) self.series.attachAxis(self.vlaxisY) self.setChart(self.chart) def drawLine(self): #获取当前时间 bjtime = QDateTime.currentDateTime() #更新X轴坐标 self.dtaxisX.setMin(QDateTime.currentDateTime().addSecs(-300*1)) self.dtaxisX.setMax(QDateTime.currentDateTime().addSecs(0)) #当曲线上的点超出X轴的范围时,移除最早的点 if(self.series.count()>149): self.series.removePoints(0,self.series.count()-149) #产生随即数 yint = random.randint(0,1500) #添加数据到曲线末端 self.series.append(bjtime.toMSecsSinceEpoch(),yint)
def update_particles(particles): animation_chart = QChart() reals = QScatterSeries() pen_reals = reals.pen() pen_reals.setBrush(QtGui.QColor("white")) reals.setMarkerSize(5) reals.setColor(QtGui.QColor("red")) reals.setPen(pen_reals) for particle in particles: reals.append(particle, 0) animation_chart.addSeries(reals) animation_chart.setBackgroundBrush(QtGui.QColor(41, 43, 47)) animation_chart.createDefaultAxes() animation_chart.legend().hide() animation_chart.setContentsMargins(-10, -10, -10, -10) animation_chart.layout().setContentsMargins(0, 0, 0, 0) animation_chart.axisX().setTickCount(17) animation_chart.axisY().setTickCount(3) animation_chart.axisX().setLabelsColor(QtGui.QColor("white")) animation_chart.axisX().setGridLineColor(QtGui.QColor("grey")) animation_chart.axisX().setRange(-4, 12) animation_chart.axisY().setRange(-1, 1) animation_chart.axisY().setLabelsColor(QtGui.QColor("white")) animation_chart.axisY().setGridLineColor(QtGui.QColor("grey")) form.widget_animation.setChart(animation_chart)
def addSeries(self, _x2idx: typing.Dict, _idx2x: list, _chart: QChart, _axis_x: QValueAxis, _axis_y: QValueAxis): series = QScatterSeries() series.setName(self.name) for x, y in zip(self.x_list, self.y_list): series.append(_x2idx[x], y) if self.color is not None: series.setColor(self.color) _chart.addSeries(series) _chart.setAxisX(_axis_x, series) _chart.setAxisY(_axis_y, series) if self.show_value: self.createShow()
def addSeries( self, _x2idx: typing.Dict, _idx2x: list, _chart: QChart, _axis_x: QValueAxis, _axis_y: QValueAxis ): series = QScatterSeries() series.setName(self.name) for x, y in zip(self.x_list, self.y_list): series.append(_x2idx[x], y) if self.color is not None: series.setColor(self.color) _chart.addSeries(series) _chart.setAxisX(_axis_x, series) _chart.setAxisY(_axis_y, series) if self.show_value: self.createShow()
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 Window(QMainWindow): def __init__(self, landmarkPoints, allPoints, threadEvent): super().__init__() self.title = "Lidar data points" #self.queue = queue self.color = Qt.darkRed self.lmrkPoints = landmarkPoints self.allPoints = allPoints self.event = threadEvent self.left = 500 self.top = 500 self.height = 480 self.width = 640 self.count = 0 self.time = 0 self.label = QLabel(self) self.lmrkBox = QCheckBox("Landmark points", self) self.ptsBox = QCheckBox("Data points", self) self.boxArea = QWidget() self.mainLayout = QGridLayout() self.mainLayout.addWidget(self.lmrkBox, 0, 0) self.mainLayout.addWidget(self.ptsBox, 1, 0) self.mainLayout.setVerticalSpacing(5) self.boxArea.setLayout(self.mainLayout) crote = QDockWidget("Hide", self) crote.setWidget(self.boxArea) self.addDockWidget(Qt.LeftDockWidgetArea, crote) dock = QDockWidget("", self) dock.setWidget(self.label) self.addDockWidget(Qt.LeftDockWidgetArea, dock) self.chart = QChart() self.config_axis() self.series = QScatterSeries(self.chart) self.allSeries = QScatterSeries(self.chart) self.config_series() #self.update() self.timer = QTimer(self) self.view = QChartView(self.chart) self.setCentralWidget( self.view ) # It is needed to create to view because the CentralWidget needs to be a QWidget, and a QChart is not so. self.initWindow() def config_series(self): self.series.setName("Landmark Points") self.allSeries.setName("Data Points") lmrkPen = self.series.pen() pen = self.allSeries.pen() lmrkPen.setWidthF(.2) pen.setWidthF(.2) self.series.setPen(lmrkPen) self.allSeries.setPen(pen) self.series.setColor(Qt.red) self.allSeries.setColor(Qt.blue) self.series.setMarkerShape(1) # 1 - rectangle; 0 - circle # for good visualization, the landmark points should be bigger than normal points self.series.setMarkerSize(8) self.allSeries.setMarkerSize(5) self.label.move(15, 15) def config_axis(self): self.xAxis = QValueAxis() self.yAxis = QValueAxis() self.xAxis.setRange(-XRANGE, XRANGE) self.xAxis.setTitleText("Eixo x") self.yAxis.setRange(-YRANGE, YRANGE) self.yAxis.setTitleText("Eixo y") self.chart.addAxis(self.xAxis, Qt.AlignBottom) self.chart.addAxis(self.yAxis, Qt.AlignLeft) def update(self): self.event.wait() start = time.time() self.label.setText("FPS: {:.2f}".format(1 / (time.time() - self.time))) self.time = time.time() if self.count == 0 and self.lmrkPoints != []: self.series.append(self.lmrkPoints[0][:]) self.allSeries.append(self.allPoints[0][:]) del self.lmrkPoints[:] del self.allPoints[:] self.count = 1 elif self.lmrkPoints != []: self.series.replace(self.lmrkPoints[0][:]) self.allSeries.replace(self.allPoints[0][:]) del self.lmrkPoints[:] del self.allPoints[:] end = time.time() self.event.clear() def hide_show_points(self): self.series.setVisible(not self.series.isVisible()) def hide_show_all_points(self): self.allSeries.setVisible(not self.allSeries.isVisible()) def initWindow(self): print("queue inside myWindow: {}".format(self.lmrkPoints)) self.setGeometry(self.left, self.top, self.width, self.height) self.setWindowTitle(self.title) self.chart.addSeries(self.series) self.chart.addSeries(self.allSeries) self.series.attachAxis(self.xAxis) self.series.attachAxis(self.yAxis) self.allSeries.attachAxis(self.xAxis) self.allSeries.attachAxis(self.yAxis) self.timer.timeout.connect(self.update) self.lmrkBox.stateChanged.connect(self.hide_show_points) self.ptsBox.stateChanged.connect(self.hide_show_all_points) self.timer.start(0) self.show()
def run_evolution(): range_a = float(str(form.input_a.text())) range_b = float(str(form.input_b.text())) precision = int(str(form.input_d.text())) generations_number = int(str(form.input_t.text())) app.setOverrideCursor(QtCore.Qt.WaitCursor) best_reals, best_binary, best_fxs, local_fxs, _, _ = evolution(range_a, range_b, precision, generations_number, form.checkBox.isChecked()) form.best_table.item(1,0).setText(str(best_reals[len(local_fxs)-1])) form.best_table.item(1,1).setText(''.join(map(str, best_binary[len(local_fxs)-1]))) form.best_table.item(1,2).setText(str(best_fxs[len(local_fxs)-1])) chart = QChart() bests = QLineSeries() pen_best = bests.pen() pen_best.setWidth(1) pen_best.setBrush(QtGui.QColor("red")) bests.setPen(pen_best) for i in range(0, len(local_fxs)): if len(local_fxs[i]) - 1 == 0: fxs = QScatterSeries() fxs.append(i + 0.99, local_fxs[i][0]) pen = fxs.pen() color = QtGui.QColor(random.randint(50,255), random.randint(50,255), random.randint(50,255)) fxs.setColor(color) pen.setColor(color) fxs.setPen(pen) fxs.setMarkerSize(5) else: fxs = QLineSeries() tick = 1 / (len(local_fxs[i]) - 1) for j in range(len(local_fxs[i])): fxs.append(i + j * tick, local_fxs[i][j]) pen = fxs.pen() pen.setWidth(1) pen.setBrush(QtGui.QColor(random.randint(50,255), random.randint(50,255), random.randint(50,255))) fxs.setPen(pen) bests.append(i+1, best_fxs[i]) chart.addSeries(fxs) chart.addSeries(bests) chart.setBackgroundBrush(QtGui.QColor(41, 43, 47)) chart.createDefaultAxes() chart.legend().hide() chart.setContentsMargins(-10, -10, -10, -10) chart.layout().setContentsMargins(0, 0, 0, 0) chart.axisX().setTickCount(11) chart.axisX().setLabelsColor(QtGui.QColor("white")) chart.axisX().setGridLineColor(QtGui.QColor("grey")) chart.axisX().setLabelFormat("%i") chart.axisY().setRange(-2,2) chart.axisY().setLabelsColor(QtGui.QColor("white")) chart.axisY().setGridLineColor(QtGui.QColor("grey")) form.widget.setChart(chart) with open('best_history.csv', 'w', newline='', encoding='utf8') as history_csvfile: history_writer = csv.writer( history_csvfile, delimiter=';', dialect=csv.excel) history_writer.writerow(['Parametry']) history_writer.writerow(['Precyzja: 10^-%d' % precision]) history_writer.writerow(['Iteracje: %d' % generations_number]) history_writer.writerow(['', 'real', 'bin', 'f(real)']) for index, generation in enumerate(range(generations_number)): history_writer.writerow([index, best_reals[generation], best_binary[generation], best_fxs[generation]]) app.restoreOverrideCursor()