Collectives™ on Stack Overflow
Find centralized, trusted content and collaborate around the technologies you use most.
Learn more about Collectives
Teams
Q&A for work
Connect and share knowledge within a single location that is structured and easy to search.
Learn more about Teams
I'm playing around with python2.7 and pyqtgraph and I want to make a scrolling time plot with custom date-time labels on the x-axis. So when there is a new y-value, the graph is scrolling left and the new point is drawn on the right, with the current y-positon and the date and time of receipt on the x-axis. I tried to simulate it by pushing random ints to the y-axis and the current date and time to the x-axis.
I tested my code on windows and Mint18(virtualbox) and it seems to work pretty well, but when I port it to my raspberry(or beaglebone, same issue), the code shows a weird behaviour. The graph isn't moving, no lines are drawn. Nothing happens but the x-axis labels are set to the current date and time.
I tried to debug the issue but wasn't successful. My suspicion is the data type appended to the x-axis, which is happening in
self.data.append({'x': time.time(), 'y': np.random.randint(0, 100)})
x = [item['x'] for item in self.data]
y = [item['y'] for item in self.data]
self.curve.setData(x=x, y=y)
where time.time()
is passed to tickStrings(self, values, scale, spacing)
and return is a list of numpy.float64 timestamps.
In this case the plot doesn't work, but when I use
self.t = QTime()
self.t.start()
and in def update(self):
self.data.append({'x': self.t.elapsed()*1000, 'y': np.random.randint(0, 100)})
the passed data type to tickStrings(self, values, scale, spacing):
is int, and the graph is being plotted. But now the x-labels are the lapsed time since program start, which is not what I want.
But when I do something like
self.data.append({'x': self.t.elapsed()*1000000000000, 'y': np.random.randint(0, 100)})
the passed data type is long, but the graph is being plotted, which is quite confusing.
I also tried to pass a unix timestamp created from
UNIX_EPOCH = datetime.datetime(1970, 1, 1, 0, 0)
TS_MULT_us = 1e6
def now_timestamp(ts_mult=TS_MULT_us, epoch=UNIX_EPOCH):
return(int((datetime.datetime.utcnow() - epoch).total_seconds()*ts_mult))s
This also didn't work, so now I am stuck. I also am not sure if the problem is the data type, but I noticed that every time I append integers, the plot seems to work, but with long or floats this is not the case.
The raspberry terminal also doesn't throw any exceptions, so I tried print type(x), x
and print "updating"
.
After 2 iterations of
tickStrings()
update()
tickStrings()
is not called anymore, but only
update()
. It seems like a buffer or something is full and
self.data.append({'x': time.time(), 'y': np.random.randint(0, 100)})
cant append any values.
I am not sure how to proceed debugging this issue, maybe somebody has a hint for me.
Since the problem occurs only on embedded linux:
Is there a major difference on how python handles long and float data types on x64 and arm systems and could this be the problem?
Maybe there are some interesting logfiles I should check?
uname -a returns
Linux raspberrypi 4.14.58-v7+ #1130 SMP Thu Jul 26 14:30:50 BST 2018 armv7l GNU/Linux
Latest updates are installed, also the used pip packages are up to date.
Any help is appreciated, as well as any useful general comments, because I am a python greenhorn and still learning a lot.
import sys
import numpy as np
from pyqtgraph.Qt import QtGui, QtCore
import pyqtgraph as pg
from PyQt4.QtCore import QTime, QTimer, QDateTime
from collections import deque
import datetime
import time
from pytz import utc
class TimeAxisItem(pg.AxisItem):
#from https://gist.github.com/friendzis/4e98ebe2cf29c0c2c232
def __init__(self, *args, **kwargs):
#super().__init__(*args, **kwargs) port to python2.7
super(TimeAxisItem, self).__init__(*args, **kwargs)
def tickStrings(self, values, scale, spacing):
#return [time.strftime("%d.%m.%y \n %H:%M:%S", time.localtime(value)) for value in values]
#debug, short above
strns = []
for x in values:
#debug
print type(x), x
strns.append(time.strftime("%d.%m.%y \n %H:%M:%S", time.localtime(x)))
#strns.append(x.strftime("%d.%m.%y \n %H:%M:%S")) # time_t --> time.struct_time
except ValueError: # Windows can't handle dates before 1970
strns.append('')
return strns
class MyApplication(QtGui.QApplication):
def __init__(self, *args, **kwargs):
super(MyApplication, self).__init__(*args, **kwargs)
#debug
#self.t = QDateTime()
#self.t = QTime()
#self.t.start()
#deque fast performance container type alternative to classic lists
self.data = deque(maxlen=10)
self.win = pg.GraphicsWindow(title="Basic plotting examples")
self.win.resize(700,400)
self.plot = self.win.addPlot(title='Timed data', axisItems={'bottom': TimeAxisItem(orientation='bottom')})
self.curve = self.plot.plot()
self.tmr = QTimer()
self.tmr.timeout.connect(self.update)
self.tmr.start(1000)
def update(self):
#input x and y data here
print "updating"
#self.data.append({'x': self.t.elapsed()*1000000000000, 'y': np.random.randint(0, 100)})
#self.data.append({'x': self.t.elapsed()*1000, 'y': np.random.randint(0, 100)})
self.data.append({'x': time.time(), 'y': np.random.randint(0, 100)})
#debug
#print self.t.currentMSecsSinceEpoch()
#print type(self.t.elapsed()*1000)
x = [item['x'] for item in self.data]
y = [item['y'] for item in self.data]
self.curve.setData(x=x, y=y)
#print type(x)
#print x
#print y
def main():
app = MyApplication(sys.argv)
sys.exit(app.exec_())
if __name__ == '__main__':
main()
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.