To answer my own question - this is a rather well known issue, as it turns
out. Datetime axes use a UNIX Timestamp, which is a number of seconds since
the beginning of an epoch. This can be a float, where the fractional part
would represent fractions of a second. Pandas uses nanosecond precision by
design, so the decimal point is shifted to the left by 9 positions. I ended
up using Numpy's datetime64[s] instead.
On Saturday, May 23, 2020 at 10:44:55 PM UTC+2, mks wrote:
>
> Hello,
>
> First of all, let me thank you for sharing PyQtGraph. It's amazing. I'm
> very grateful.
>
> I am still learning it, I am especially interested in writing my own
> GraphicsItems. I was following the "Custom Graphics" example, which plots
> Candlesticks. In the example, the input data's x is a float. That works
> fine for the sake of example, but in real world it would almost always be a
> Timestamp/Datetime/equivalent. I was working on adopting this example to
> pandas Timestamp and I hit a roadblock. Upon closer look it seems that
> pandas Timestamp's nanosecond-precision is an issue, i.e. if I use the
> float value of the timestamp, the picture's boundingRect is calculated
> incorrectly. However, if I reduce precision to seconds by dividing the
> float by 10**9, it works fine. That leads me to believe there is some kind
> of overflow error somewhere along the way. I am not sure how to approach
> this. Simply dividing by 10**9 is an ok workaround for now, but it seems
> hacky to me. Below please find example code with two classes:
> "CandlestickItemWorking" and "CandlestickNotWorking". You can switch
> between them by commenting/uncommenting lines 77/78 to reproduce.
>
> Happy to hear your thoughts, perhaps it's a beginner's mistake on my part.
>
> Kind Regards,
> mks
>
> """
> Demonstrate creation of a custom graphic (a candlestick plot)
>
> """
> import initExample ## Add path to library (just for examples; you do not
> need this)
>
> import pyqtgraph as pg
> from pyqtgraph import QtCore, QtGui
> import pandas as pd
>
>
> class CandlestickItemWorking(pg.GraphicsObject):
> def __init__(self, data):
> pg.GraphicsObject.__init__(self)
> self.data = data ## data must have fields: time, open, close, min,
> max
> self.generatePicture()
>
> def generatePicture(self):
> self.picture = QtGui.QPicture()
> p = QtGui.QPainter(self.picture)
> p.setPen(pg.mkPen('w'))
> w = (self.data[1][0] - self.data[0][0]).value / (3. * 10**9)
>
> for (t, open, close, min, max) in self.data:
> p.drawLine(QtCore.QPointF(t.value / 10**9, min),
> QtCore.QPointF(t.value / 10**9, max))
> if open > close:
> p.setBrush(pg.mkBrush('r'))
> else:
> p.setBrush(pg.mkBrush('g'))
> p.drawRect(QtCore.QRectF(t.value/10**9 - w, open, w * 2, close -
> open))
> p.end()
>
> def paint(self, p, *args):
> p.drawPicture(0, 0, self.picture)
>
> def boundingRect(self):
> return QtCore.QRectF(self.picture.boundingRect())
>
>
> class CandlestickItemNotWorking(pg.GraphicsObject):
> def __init__(self, data):
> pg.GraphicsObject.__init__(self)
> self.data = data
> self.generatePicture()
>
> def generatePicture(self):
> self.picture = QtGui.QPicture()
> p = QtGui.QPainter(self.picture)
> p.setPen(pg.mkPen('w'))
> w = (self.data[1][0] - self.data[0][0]).value / 3.
>
> for (t, open, close, min, max) in self.data:
> p.drawLine(QtCore.QPointF(t.value, min), QtCore.QPointF(t.value,
> max))
> if open > close:
> p.setBrush(pg.mkBrush('r'))
> else:
> p.setBrush(pg.mkBrush('g'))
> p.drawRect(QtCore.QRectF(t.value - w, open, w * 2, close - open))
> p.end()
>
> def paint(self, p, *args):
> p.drawPicture(0, 0, self.picture)
>
> def boundingRect(self):
> return QtCore.QRectF(self.picture.boundingRect())
>
>
> data = [ ## fields are (time, open, close, min, max).
> (pd.Timestamp('2020-03-01 00:00:00'), 10, 13, 5, 15),
> (pd.Timestamp('2020-03-01 00:01:00'), 13, 17, 9, 20),
> (pd.Timestamp('2020-03-01 00:02:00'), 17, 14, 11, 23),
> (pd.Timestamp('2020-03-01 00:03:00'), 14, 15, 5, 19),
> (pd.Timestamp('2020-03-01 00:04:00'), 15, 9, 8, 22),
> (pd.Timestamp('2020-03-01 00:05:00'), 9, 15, 8, 16),
> ]
>
> item = CandlestickItemWorking(data)
> # item = CandlestickItemNotWorking(data)
> plt = pg.plot()
> plt.addItem(item)
> plt.setWindowTitle('pyqtgraph example: customGraphicsItem')
>
> ## Start Qt event loop unless running in interactive mode or using pyside.
> if __name__ == '__main__':
> import sys
>
> if (sys.flags.interactive != 1) or not hasattr(QtCore, 'PYQT_VERSION'):
> QtGui.QApplication.instance().exec_()
>
>
--
You received this message because you are subscribed to the Google Groups
"pyqtgraph" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
To view this discussion on the web visit
https://groups.google.com/d/msgid/pyqtgraph/50f2cca4-56e9-45fa-bb27-077ef583e77bo%40googlegroups.com.