我正在制作一个滚动图,它将绘制实时传感器数据,在x轴上显示时间。我对tickStrings
的行为有点困惑。
我的代码基于下面的示例(来自这里)。当绘制的点数增加时,x轴字符串的数目会发生变化--有时会增加,有时会减少。它稳定一旦德克是完整的长度和‘滚动’开始。
是否有可能保持滴答字串之间的间距与绘图点的数目相同?我想,可能会使用一种方法,在添加新数据时替换空白的勾选字符串,但不知道如何做到这一点。
编辑:我希望实现的一个例子是这里。
import sys
import numpy as np
import datetime
from PyQt5.QtCore import QTime, QTimer
from pyqtgraph.Qt import QtGui
import pyqtgraph as pg
from collections import deque
import time
class TimeAxisItem(pg.AxisItem):
def __init__(self, *args, **kwargs):
super(TimeAxisItem, self).__init__(*args, **kwargs)
def tickStrings(self, values, scale, spacing):
return [int2dt(value).strftime("%H:%M:%S") for value in values]
def int2dt(ts):
return(datetime.datetime.fromtimestamp(ts))
class MyApplication(QtGui.QApplication):
def __init__(self, *args, **kwargs):
super(MyApplication, self).__init__(*args, **kwargs)
self.t = QTime()
self.t.start()
maxlen = 100
self.data_x = deque(maxlen=maxlen)
self.data_y = deque(maxlen=maxlen)
self.win = pg.GraphicsLayoutWidget()
self.win.resize(1000,600)
self.plot = self.win.addPlot(title='Scrolling real-time plot', axisItems={'bottom': TimeAxisItem(
orientation='bottom')})
self.curve = self.plot.plot()
self.tmr = QTimer()
self.tmr.timeout.connect(self.update)
self.tmr.start(1000)
self.y = 100
self.win.show()
def update(self):
x = int(time.time())
self.y = self.y + np.random.uniform(-1, 1)
self.data_x.append(x)
self.data_y.append(self.y)
time.sleep(2)
print(self.data_x)
print(self.data_y)
self.curve.setData(x=list(self.data_x), y=list(self.data_y))
def main():
app = MyApplication(sys.argv)
sys.exit(app.exec_())
if __name__ == '__main__':
main()
发布于 2022-02-06 08:45:26
由于问题被更新了更多的细节,这里有更具体的答案。我保留先前的答案,以帮助某人,以防有固定数量的蜱显示。
要准确地处理您想要的内容,首先需要将滴答频率设置为每秒1次。这可以通过设置self.setTickSpacing(levels=[(1, 0)])
来完成。在您的示例中,您有一分钟的更新时间,在这种情况下,您需要使用self.setTickSpacing(levels=[(60, 0)])
。
问题的第二部分是蜱的旋转-90度。旋转不是AxisItem实现的一部分。因此,我们必须重新实现drawPicture方法。完成滴答的旋转和平移。此外,为了有足够的高度,我们必须设置self.fixedHeight = 150
以适应长的滴答线。
定间距是通过设置X轴的固定范围来实现的。为了达到滚动效果,我们必须在不附加任何数据的情况下隐藏第一滴滴。这是用ticks = [(1.0, ticks[0][1][self.hide_ticks:])]
行完成的。
值得注意的是,我的解决方案适合你的具体情况。否则,必须使用fixedHeight和drawPicture方法的旋转部分。另外,队列的maxlen
必须降低到10,这样就不会重叠。
这是完整的代码:
import datetime
import sys
import time
from collections import deque
import numpy as np
import pyqtgraph as pg
from PyQt5.QtCore import QTime, QTimer
from pyqtgraph import debug as debug
from pyqtgraph.Qt import QtGui
class TimeAxisItem(pg.AxisItem):
hide_ticks = 0
def __init__(self, *args, **kwargs):
super(TimeAxisItem, self).__init__(*args, **kwargs)
# Paint tick every 1 second
self.setTickSpacing(levels=[(1, 0)])
# Paint tick every 1 minute
# self.setTickSpacing(levels=[(60, 0)])
# Set fixed tick height
self.fixedHeight = 150
def tickStrings(self, values, scale, spacing):
return [int2dt(value).strftime("%Y-%m-%d %H:%M:%S") for value in values]
def drawPicture(self, p, axisSpec, tickSpecs, textSpecs):
profiler = debug.Profiler()
p.setRenderHint(p.RenderHint.Antialiasing, False)
p.setRenderHint(p.RenderHint.TextAntialiasing, True)
## draw long line along axis
pen, p1, p2 = axisSpec
p.setPen(pen)
p.drawLine(p1, p2)
# p.translate(0.5,0) ## resolves some damn pixel ambiguity
## draw ticks
for pen, p1, p2 in tickSpecs:
p.setPen(pen)
p.drawLine(p1, p2)
profiler('draw ticks')
# Draw all text
if self.style['tickFont'] is not None:
p.setFont(self.style['tickFont'])
p.setPen(self.textPen())
bounding = self.boundingRect().toAlignedRect()
p.setClipRect(bounding)
for rect, flags, text in textSpecs:
p.save() # save the painter state
p.translate(rect.center()) # move coordinate system to center of text rect
p.rotate(-90) # rotate text
p.translate(-rect.center()) # revert coordinate system
p.translate(-65, 0) # Move rotated tick down by 65 pixels
p.drawText(rect, int(flags), text)
p.restore() # restore the painter state
profiler('draw text')
def tickValues(self, minVal, maxVal, size):
if minVal == 0:
return []
else:
ticks = super().tickValues(minVal, maxVal, size)
ticks = [(1.0, ticks[0][1][self.hide_ticks:])]
return ticks
def int2dt(ts):
return (datetime.datetime.fromtimestamp(ts))
class MyApplication(QtGui.QApplication):
def __init__(self, *args, **kwargs):
super(MyApplication, self).__init__(*args, **kwargs)
self.t = QTime()
self.t.start()
maxlen = 10
self.data_x = deque(maxlen=maxlen)
self.data_y = deque(maxlen=maxlen)
self.win = pg.GraphicsLayoutWidget()
self.win.resize(1000, 600)
self.axis_x = TimeAxisItem(orientation='bottom')
self.plot = self.win.addPlot(title='Scrolling real-time plot', axisItems={'bottom': self.axis_x})
self.curve = self.plot.plot()
self.tmr = QTimer()
self.tmr.timeout.connect(self.update)
self.tmr.start(1000)
self.y = 100
self.win.show()
def update(self):
x = int(time.time())
self.y = self.y + np.random.uniform(-1, 1)
self.data_x.append(x)
self.data_y.append(self.y)
time.sleep(1)
# Set fixed range
self.plot.setXRange(self.data_x[0] - self.data_x.maxlen + len(self.data_x),
self.data_x[0] + len(self.data_x) - 1, padding=0)
# Hide ticks without data attached to it, to achieve scrolling effect
self.axis_x.hide_ticks = self.data_x.maxlen - len(self.data_x)
self.curve.setData(x=list(self.data_x), y=list(self.data_y))
def main():
app = MyApplication(sys.argv)
sys.exit(app.exec_())
if __name__ == '__main__':
main()
发布于 2022-02-02 12:00:41
要设置固定数量的刻度,还必须重写tickValues
方法。此方法生成滴答值,tickStrings
方法给出这些值的字符串表示--在您的情况下转换为人类可读的时间。
下面是您可以在代码中使用的TimeAxisItem示例:
class TimeAxisItem(pg.AxisItem):
nticks = 6
def __init__(self, *args, **kwargs):
super(TimeAxisItem, self).__init__(*args, **kwargs)
def tickStrings(self, values, scale, spacing):
return [int2dt(value).strftime("%H:%M:%S") for value in values]
def tickValues(self, minVal, maxVal, size):
if self.nticks is not None:
ticks = np.linspace(ceil(minVal), ceil(maxVal), num=self.nticks, endpoint=False)
return [((1.0, 0), ticks)]
else:
return super().tickValues(minVal, maxVal, size)
您可以看到,如果nticks不是空的,我们就从minVal和maxVal之间的值生成n个滴答。Pyqtgraph在称为levels
的范围内生成蜱。对于我们的情况,使用范围(1.0,0)就足够了,也就是说,滴答之间的距离是1秒,偏移量为0。
您可以根据需要使用setTickSpacing定义多个范围。例如,每小时、每分钟、每5秒都有滴答声,您可以将其设置为setTickSpacing(levels=[(3600, 0), (60, 0), (5, 0)])
。
如果Δx小于60秒,这将产生每5秒的滴答。如果Δx小于1小时,则每分钟进行勾选。然后每隔一小时滴答一次。
这是理解蜱是如何工作的关键知识。
https://stackoverflow.com/questions/70920246
复制相似问题