Как эффективно получить QLineSeries из Qchart в массивный массив?
Я пытаюсь получить QLineSeries
из QChart
с pointsVector()
метод. Тем не менее, я потратил немало времени, чтобы получить эти LineSeries.
Для примера в этом коде:
from PyQt5.QtGui import *
from PyQt5.QtCore import *
from PyQt5.QtChart import *
from PyQt5.QtWidgets import *
import sys
import numpy as np
from scipy import signal
import time
def series_to_polyline(xdata, ydata):
"""Convert series data to QPolygon(F) polyline
This code is derived from PythonQwt's function named
`qwt.plot_curve.series_to_polyline`"""
size = len(xdata)
polyline = QPolygonF(size)
pointer = polyline.data()
dtype, tinfo = np.float, np.finfo # integers: = np.int, np.iinfo
pointer.setsize(2*polyline.size()*tinfo(dtype).dtype.itemsize)
memory = np.frombuffer(pointer, dtype)
memory[:(size-1)*2+1:2] = xdata
memory[1:(size-1)*2+2:2] = ydata
return polyline
class pltlfp(QChartView):
axischanged = pyqtSignal(float ,float ,float ,float)
axisXchanged = pyqtSignal(float ,float , int)
def __init__(self, parent=None):
super(pltlfp, self).__init__(parent=parent)
self.ncurves = 0
self.chart = QChart()
self.chart.legend().hide()
self.setChart(self.chart)
self.setRubberBand(QChartView.RectangleRubberBand)
self.setRenderHint(QPainter.Antialiasing)
self.chart.layout().setContentsMargins(0, 0, 0, 0)
self.chart.setBackgroundRoundness(0)
self.chart.setAnimationEasingCurve(QEasingCurve.Linear)
print(self.chart.margins())
self.chart.setMargins(QMargins())
self.axisXlim = []
self.axisYlim = []
self.pos = QPoint()
self.begin = QPoint()
self.end= QPoint()
def emitaxischangesignal(self,pressed = 0 ):
self.axisXchanged.emit(self.chart.axisX().min(),self.chart.axisX().max(),pressed)
def mouseDoubleClickEvent(self,event):
if (event.buttons() == Qt.LeftButton):
# self.chart.zoomReset()
self.setAxisinit()
self.emitaxischangesignal()
def mouseMoveEvent(self,event):
if (event.buttons() == Qt.RightButton):
x = self.pos.x()-event.pos().x()
y = event.pos().y()-self.pos.y()
self.chart.scroll(x,y)
self.pos = event.pos()
self.emitaxischangesignal()
if (event.buttons() == Qt.LeftButton):
super(pltlfp, self).mouseMoveEvent(event)
# self.emitaxischangesignal()
def mousePressEvent(self,event):
if (event.button() == Qt.MidButton):
self.emitaxischangesignal(1)
if (event.button() == Qt.RightButton):
self.pos = event.pos()
if (event.button() == Qt.LeftButton):
super(pltlfp, self).mousePressEvent(event)
def mouseReleaseEvent(self, event):
if (event.button() == Qt.LeftButton):
super(pltlfp, self).mouseReleaseEvent(event)
self.emitaxischangesignal()
# self.chart.zoomIn(QRectF(self.begin,self.end))
def set_title(self, title,xlabel=None,ylabel=None):
self.chart.setTitle(title)
self.chart.axisX().setTitleText(xlabel)
self.chart.axisY().setTitleText(ylabel)
def setneewaxis(self, x=[0,10], y=[0,10]):
self.chart.axisX().setRange(x[0],x[1])
self.chart.axisY().setRange(y[0],y[1])
def add_data(self, xdata, ydata, color=None):
curve = QLineSeries()
pen = curve.pen()
if color is not None:
pen.setColor(color)
pen.setWidthF(.1)
curve.setPen(pen)
curve.setUseOpenGL(True)
curve.append(series_to_polyline(xdata, ydata))
self.chart.addSeries(curve)
self.chart.createDefaultAxes()
self.axisXlim = [self.chart.axisX().min(),self.chart.axisX().max()]
self.axisYlim = [self.chart.axisY().min(),self.chart.axisY().max()]
self.ncurves += 1
def replace_data(self, nb, xdata, ydata, color=None):
self.chart.removeSeries(self.chart.series()[nb])
self.add_data( xdata, ydata, color=color)
def get_axis_data(self, nb):
t0 = time.time()
L = self.chart.series()[nb]
print(1,time.time()-t0)
t0 = time.time()
data = L.pointsVector()
print(2,time.time()-t0)
t0 = time.time()
data = np.array([np.array([data[d].x(), data[d].y()]) for d in range(len(data))])
print(3,time.time()-t0)
t0 = time.time()
dataX = data[:,0]
print(4,time.time()-t0)
t0 = time.time()
dataY = data[:,1]
print(5,time.time()-t0)
t0 = time.time()
axisXlim = [self.chart.axisX().min(),self.chart.axisX().max()]
print(6,time.time()-t0)
t0 = time.time()
idxstart=np.where(dataX>=axisXlim[0])[0][0]
print(7,time.time()-t0)
t0 = time.time()
idxend = np.where(dataX<=axisXlim[1])[0][-1]
print(8,time.time()-t0)
t0 = time.time()
dataY=dataY[idxstart:idxend]
print(9,time.time()-t0)
t0 = time.time()
dataX=dataX[idxstart:idxend]
print(10,time.time()-t0)
t0 = time.time()
return dataX,dataY
def setAxis(self, xstart =0,xend =0, ystart =0, yend =0, ):
self.chart.axisX().setRange(xstart,xend )
# self.chart.axisY().setRange(ystart,yend)
def setAxisinit(self):
self.chart.axisX().setRange(self.axisXlim[0],self.axisXlim[1])
self.chart.axisY().setRange(self.axisYlim[0],self.axisYlim[1])
class SurfViewer(QMainWindow):
def __init__(self, parent=None,sig_dict=None, t=None):
super(SurfViewer, self).__init__()
self.parent = parent
self.centralWidget= QWidget()
self.setCentralWidget(self.centralWidget)
# self.setFixedWidth(800)
# self.setFixedHeight(800)
#tab Model selection
self.maplt1 = pltlfp()
self.maplt1.add_data(t,sig_dict['ydata1'], color=Qt.red)
self.maplt1.set_title("","Time [s]","ydata1")
self.Vlayout = QVBoxLayout()
self.Vlayout.addWidget(self.maplt1)
self.centralWidget.setLayout(self.Vlayout)
self.maplt1.axisXchanged.connect(self.signal_setaxis)
@pyqtSlot(float ,float , int)
def signal_setaxis(self, xstart,xend, pressed ):
self.maplt1.setAxis(xstart,xend)
if pressed == 1:
dataX,dataY = self.maplt1.get_axis_data(0)
def main():
app = QApplication(sys.argv)
Fs = 100 * 1024
npoints = 5 * Fs
xdata1 = np.linspace(0., 5., npoints)
ydata1 = np.sin(xdata1*2*3.1416*30)
sig_dict = {'ydata1':ydata1 }
ex = SurfViewer(app,sig_dict,xdata1)
ex.setWindowTitle('window')
ex.show()
sys.exit(app.exec_( ))
if __name__ == '__main__':
main()
Где я строю кривую с большим количеством точек. Я реализовал метод в pltlfp
имя класса get_axis_data(self, nb)
где я восстанавливаю LineSerie, который является сюжетом в этом классе. В этом методе я провел все время, делая data = L.pointsVector()
а также data = np.array([np.array([data[d].x(), data[d].y()]) for d in range(len(data))])
Вот что я получаю из печати, которую я сделал в get_axis_data(self, nb)
метод:
1 0.0
2 0.6440367698669434
3 1.9921140670776367
4 0.0
5 0.0
6 0.0
7 0.004000186920166016
8 0.0030002593994140625
9 0.0
10 0.0
Total time 2.64315128326416
Я ищу несколько хороших советов, чтобы сократить это время. Для .pointsVector()
Отмечу, что могу сделать лучше, но для другого это возможно.
Обновить
Я немного улучшил это
def get_axis_data(self, nb):
L = self.chart.series()[nb]
t0 = time.time()
data = L.pointsVector()
print(2,time.time()-t0)
t0 = time.time()
a = np.array([ [d.x(), d.y()] for d in data])
print(3,time.time()-t0)
t0 = time.time()
dataX = a[:,0]
dataY = a[:,1]
axisXlim = [self.chart.axisX().min(),self.chart.axisX().max()]
idxstart=np.where(dataX>=axisXlim[0])[0][0]
idxend = np.where(dataX<=axisXlim[1])[0][-1]
dataY=dataY[idxstart:idxend]
dataX=dataX[idxstart:idxend]
return dataX,dataY
что дает мне:
2 0.7390422821044922
3 0.9980571269989014
Но это все еще долго.