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 wonder if someone can help me out. I am trying to convert the MultiplePlotAxes.py example in pyqtgraph so that the all the axes are on the right side and aligned. Here is my code which I have added an extra plot:

Demonstrates a way to put multiple axes around a single plot. (This will eventually become a built-in feature of PlotItem) #import initExample ## Add path to library (just for examples; you do not need this) import pyqtgraph as pg from pyqtgraph.Qt import QtCore, QtGui import numpy as np pg.mkQApp() pw = pg.PlotWidget() pw.show() pw.setWindowTitle('pyqtgraph example: MultiplePlotAxes') p1 = pw.plotItem p1.setLabels(left='axis 1') ## create a new ViewBox, link the right axis to its coordinate system p2 = pg.ViewBox() p1.showAxis('right') p1.scene().addItem(p2) p1.getAxis('right').linkToView(p2) p2.setXLink(p1) p1.getAxis('right').setLabel('axis2', color='#0000ff') ## create third ViewBox. ## this time we need to create a new axis as well. p3 = pg.ViewBox() ax3 = pg.AxisItem('right') p1.layout.addItem(ax3, 2, 3) p1.scene().addItem(p3) ax3.linkToView(p3) p3.setXLink(p1) ax3.setZValue(-10000) ax3.setLabel('axis 3', color='#ff0000') ## create forth ViewBox. ## this time we need to create a new axis as well. p4 = pg.ViewBox() ax4 = pg.AxisItem('right') p1.layout.addItem(ax4, 2, 4) p1.scene().addItem(p4) ax4.linkToView(p4) p4.setXLink(p1) ax4.setZValue(-10000) ax4.setLabel('axis 4', color='#2EFEF7') ## Handle view resizing def updateViews(): ## view has resized; update auxiliary views to match global p1, p2, p3, p4 p2.setGeometry(p1.vb.sceneBoundingRect()) p3.setGeometry(p1.vb.sceneBoundingRect()) p4.setGeometry(p1.vb.sceneBoundingRect()) ## need to re-update linked axes since this was called ## incorrectly while views had different shapes. ## (probably this should be handled in ViewBox.resizeEvent) p2.linkedViewChanged(p1.vb, p2.XAxis) p3.linkedViewChanged(p1.vb, p3.XAxis) p4.linkedViewChanged(p1.vb, p4.XAxis) updateViews() p1.vb.sigResized.connect(updateViews) p1.plot([1, 2, 4, 8, 16, 32]) p2.addItem(pg.PlotCurveItem([1, 2, 4, 9, 16, 32], pen='b')) p3.addItem(pg.PlotCurveItem([1, 2, 4, 7, 16, 32], pen='r')) p4.addItem(pg.PlotCurveItem([1, 3, 5, 7, 17, 32], pen='c')) ## 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_()

This produces the following picture which I have added a red arrow showing what I want to do.

Based on what I have been able to figure out I can do this using pg.GraphicsLayout(). However, the axisItem directly associated with plotItem and the created axisItems don't match because the one attached to the plotitem is smaller.

Here is a picture of what I believe is happening:

This is my problem as I want them to all align. In the attached code you can addItem(axes,2,1) to the right but it doesn't work on the left. Anyone know how I can do this?

Thanks in advance for any help you can provide.

I had this same issue, saw this post, was disappointed with the lack of an answer, but I finally did manage a fix so figured I would post here.

If you could post the code you have for the axis on the right, I could patch that up, but basically what I did was attach the bottom axis to a a row of its own.

self.main_pI = pg.PlotItem()
self.axis_bottom = self.main_pI.getAxis('bottom')
self.axis_bottom.setLabel('Time (seconds)', color='#ffffff')
self.layout.addItem(self.main_pI, row=1, col=2, rowspan=2)
self.layout.addItem(self.axis_bottom, row=3, col=2, rowspan=2)

I'm a noob at pyqtgraph so I'm sure I'm going to butcher this terminology, but I detach the 'bottom' axis, and reattach it to the layout, where it's on a row of its own.

Hope that helps.

What you suggests works and this makes them all the same size. However I was hoping to make them all the same size as the one attached to the original plot and not the other way around. The reason for this is when you look at a point and want to read it off the axis, it will be wrong. I tried to paste my extended example here but there is not enough room for it. – Mr RC Jul 5, 2017 at 18:27 In my implementation, all the subsequent axes are the size of the gray one (meaning they line up with the plot). Mr RC which posted another solution shows a similar thing, where they put the bottom axes into a a row that is 1 higher than that of the plot area, and the y-axes. – Ogi Moore Jul 6, 2017 at 23:09 Its fine. When you have a plot item and add an extra axis to the bottom or to the right it will line up correctly. However, it is not possible to say have 5 right axis inside a plot item. Instead you have to use a grid layout and in this situation the method I mention below works ok. – Mr RC Jul 11, 2017 at 10:04

I have figured something out that is not perfect but is pretty close. Using the suggestion above and adding an extra axis item to the bottom in the appropriate space and blanking it out I have come up with this. All lines line up but not perfectly with the y-axis but close enough to get away with it. Heres the difference

Original Heres the code:

from pyqtgraph.Qt import QtGui, QtCore
import pyqtgraph as pg
pg.mkQApp()
# Axis
a2 = pg.AxisItem("left")
a3 = pg.AxisItem("left")
a4 = pg.AxisItem("left")  
a5 = pg.AxisItem("left")
a6 = pg.AxisItem("left")
# ViewBoxes
v2 = pg.ViewBox()
v3 = pg.ViewBox()
v4 = pg.ViewBox()
v5 = pg.ViewBox()
v6 = pg.ViewBox()
# main view
pw = pg.GraphicsView()
pw.setWindowTitle('pyqtgraph example: multiple y-axis')
pw.show()
# layout
l = pg.GraphicsLayout()
pw.setCentralWidget(l)
# add axis to layout
## watch the col parameter here for the position
l.addItem(a2, row=1, col=5, rowspan=1, colspan=1)
l.addItem(a3, row=1, col=4, rowspan=1, colspan=1)
l.addItem(a4, row=1, col=3, rowspan=1, colspan=1)
l.addItem(a5, row=1, col=2, rowspan=1, colspan=1)
l.addItem(a6, row=1, col=1, rowspan=1, colspan=1)
# Blank axis used for aligning things
ax = pg.AxisItem(orientation='bottom')
ax.setPen('#000000')
pos = (2,2)
l.addItem(ax, *pos)
# plotitem and viewbox
## at least one plotitem is used whioch holds its own viewbox and left axis
pI = pg.PlotItem()
v1 = pI.vb  # reference to viewbox of the plotitem
l.addItem(pI, row=1, col=8, rowspan=2, colspan=1)  # add plotitem to layout
# split off 1st axis and put to side
pI.axis_left = pI.getAxis('left')
pos = (1,7)
l.addItem(pI.axis_left, *pos)
# add viewboxes to layout
l.scene().addItem(v2)
l.scene().addItem(v3)
l.scene().addItem(v4)
l.scene().addItem(v5)
l.scene().addItem(v6)
# link axis with viewboxes
a2.linkToView(v2)
a3.linkToView(v3)
a4.linkToView(v4)
a5.linkToView(v5)
a6.linkToView(v6)
# link viewboxes
v2.setXLink(v1)
v3.setXLink(v2)
v4.setXLink(v3)
v5.setXLink(v4)
v6.setXLink(v5)
# axes labels
pI.getAxis("left").setLabel('axis 1 in ViewBox of PlotItem', color='#FFFFFF')
a2.setLabel('axis 2 in Viewbox 2', color='#2E2EFE')
a3.setLabel('axis 3 in Viewbox 3', color='#2EFEF7')
a4.setLabel('axis 4 in Viewbox 4', color='#2EFE2E')
a5.setLabel('axis 5 in Viewbox 5', color='#FFFF00')
a6.setLabel('axis 6 in Viewbox 6', color='#FE2E64')
# slot: update view when resized
def updateViews():
    v2.setGeometry(v1.sceneBoundingRect())
    v3.setGeometry(v1.sceneBoundingRect())
    v4.setGeometry(v1.sceneBoundingRect())
    v5.setGeometry(v1.sceneBoundingRect())
    v6.setGeometry(v1.sceneBoundingRect())
# data
x = [1, 2, 3, 4, 5, 6]
y1 = [0, 4, 6, 8, 10, 4]
y2 = [0, 5, 7, 9, 11, 3]
y3 = [0, 1, 2, 3, 4, 12]
y4 = [0, 8, 0.3, 0.4, 2, 5]
y5 = [0, 1, 6, 4, 2, 1]
y6 = [0, 0.2, 0.3, 0.4, 0.5, 0.6]
# plot
v1.addItem(pg.PlotCurveItem(x, y1, pen='#FFFFFF'))
v2.addItem(pg.PlotCurveItem(x, y2, pen='#2E2EFE'))
v3.addItem(pg.PlotCurveItem(x, y3, pen='#2EFEF7'))
v4.addItem(pg.PlotCurveItem(x, y4, pen='#2EFE2E'))
v5.addItem(pg.PlotCurveItem(x, y5, pen='#FFFF00'))
v6.addItem(pg.PlotCurveItem(x, y6, pen='#FE2E64'))
# updates when resized
v1.sigResized.connect(updateViews)
# autorange once to fit views at start
v2.enableAutoRange(axis=pg.ViewBox.XYAxes, enable=True)
v3.enableAutoRange(axis=pg.ViewBox.XYAxes, enable=True)
v4.enableAutoRange(axis=pg.ViewBox.XYAxes, enable=True)
v5.enableAutoRange(axis=pg.ViewBox.XYAxes, enable=True)
v6.enableAutoRange(axis=pg.ViewBox.XYAxes, enable=True)
updateViews()
if __name__ == '__main__':
    import sys
    if (sys.flags.interactive != 1) or not hasattr(QtCore, 'PYQT_VERSION'):
        QtGui.QApplication.instance().exec_()

Hope it helps anyone who has the same problem in the future

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.