Matplotlib-style transforms on PyQtGraph PlotItems

200 views
Skip to first unread message

Brad Buran

unread,
Nov 8, 2017, 12:44:09 PM11/8/17
to pyqtgraph
I'm updating some code that was written in Chaco to use PyQtGraph instead. I'm working with relatively low-level primitives from PyQtGraph to maximize my control over the various components. For example, I am creating a GraphicsLayout, inserting a ViewBox and then adding the PlotCurveItem to the ViewBox.

One thing I would like to accomplish in a single ViewBox is to have multiple PlotCurveItems. However, each curve needs to be offset vertically relative to the axes coordinates. For example, if I have three plots, the plots would be spaced equally along the vertical axis. However, when I use the mouse wheel to scale the Y-axis, it should scale the plot (but not the position of the plot).

This is easy to accomplish in Matplotlib using their transform system. For example, I would do:

import matplotlib as mp
import pylab as pl
import numpy as np

ax
= pl.gca()

x
= np.arange(100)
y
= np.random.uniform(-1, 1, size=100)

offset_transform
= mp.transforms.Affine2D().translate(0, 0.25)
new_transform
= ax.transLimits + offset_transform + ax.transAxes
ax
.plot(x, y, 'ro-', transform=new_transform)

offset_transform
= mp.transforms.Affine2D().translate(0, 0.5)
new_transform
= ax.transLimits + offset_transform + ax.transAxes
ax
.plot(x, y, 'go-', transform=new_transform)

offset_transform
= mp.transforms.Affine2D().translate(0, 0.75)
new_transform
= ax.transLimits + offset_transform + ax.transAxes
ax
.plot(x, y, 'bo-', transform=new_transform)

#ax.axis(ymin=0, ymax=5)
pl
.show()

Does PyQtGraph have a similar system?

Luke Campagnola

unread,
Nov 9, 2017, 11:46:11 AM11/9/17
to pyqt...@googlegroups.com
PyQtGraph's coordinate system is inherited from Qt's GraphicsView (http://doc.qt.io/qt-4.8/graphicsview.html). Basically, it uses a scenegraph where each item in the scene is assigned a 2D matrix transform, and the final transform used to draw each item is generated on-demand by multiplying the item's transform with the transforms of its parents. This system is efficient but not very flexible (and it's maybe the thing I dislike the most about using Qt GraphicsView).

So the PyQtGraph equivalent just involves manually updating the position of each curve whenever the view range has changed:

import pyqtgraph as pg
import numpy as np

plt = pg.plot()
curves = [plt.plot(np.random.normal(size=100)) for i in range(5)]

# Don't try to scale the y-axis automatically
plt.enableAutoRange(x=True, y=False)
plt.setYRange(-30, 30)

def updateCurves():
    # Set a good y position for each curve 
    vb = plt.plotItem.vb
    height = vb.height()
    for i,curve in enumerate(curves):
        y = vb.mapToView(pg.Point(0, (i+1) * height / (len(curves)+1))).y()
        curve.setPos(0, y)

plt.plotItem.vb.sigRangeChanged.connect(updateCurves)
updateCurves()


Luke


--
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 pyqtgraph+unsubscribe@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/pyqtgraph/b0fee28f-de2c-4bcc-8670-7175b98ac34c%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply all
Reply to author
Forward
0 new messages