Hi everyone!
I have a question regarding plotting two x axes in one PlotWidget. I've 
seen a few examples regarding multiple axes in one plot but to no avail. 
What I try to accomplish is the following:

I have a single line that I want plot in a PlotWidget and visualize that 
line using two differently scaled x axes. E.g. Let's say the bottom x axis 
to be in units of "Frames/Pictures taken" and the upper x axis to be in 
units of "Seconds". Hence, the mapping from one axis to the other should be 
strict and maintained when I zoom or pan the curve. In the 
"MultiplePlotAxes.py" example this is not the case since different datasets 
are plotted; zooming in only changes on y axis in that example. However, I 
need the two axes to zoom synchronized while maintaining the relationship 
between both x scales. Here is the code I pieced together not knowing what 
I'm really doing...:

# -*- coding: utf-8 -*-


import pyqtgraph as pg
from pyqtgraph.Qt import QtCore, QtGui


pg.mkQApp()

MainPlot = pg.PlotWidget()
MainPlot.show()
MainPlot.setWindowTitle('Dual x axis example, synchronized zoom on 
different axes')
AuxPlot = pg.ViewBox()


#AuxPlot.setXLink(MainPlot) #this line will cause the two x axes to display 
the same range which is not wanted in this example

AuxPlot.setYLink(MainPlot)  #this will synchronize zooming along the y axis

MainPlot.showAxis('top')
MainPlot.scene().addItem(AuxPlot)
AuxPlot.setGeometry(MainPlot.getPlotItem().vb.sceneBoundingRect())
MainPlot.getAxis('top').linkToView(AuxPlot)

##plot data
MainPlot.plot([0,1,2,3],[0,1,2,3], pen="w")
AuxPlot.addItem(pg.PlotCurveItem([-1,0,1,2],[0,1,2,3], pen="b")) #this data 
is scaled differently along the x axis while y is the same as in MainPlot

## This commented section was taken from another user's example but 
##only one x axis zooms while the other is unaffected

def updateViews():
    ## view has resized; update auxiliary views to match
    global MainPlot, AuxPlot
    AuxPlot.setGeometry(MainPlot.getPlotItem().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)
    AuxPlot.linkedViewChanged(MainPlot.getPlotItem().vb, AuxPlot.YAxis)

updateViews()
MainPlot.getPlotItem().sigRangeChanged.connect(updateViews)

##end of other user's example

## 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_()

I included a snippet from another user (See post here: 
https://groups.google.com/forum/#!topic/pyqtgraph/7wQeFe2iVUw) but I don't 
understand what it is really doing (especially the line

AuxPlot.linkedViewChanged(MainPlot.getPlotItem().vb, AuxPlot.YAxis)

I then tried to manually set the viewed range by calculating the upper x 
axis range from the currently displayed lower x axis. This gives me 
synchronized zooming/panning but now there is a small offset between the 
two x axes (I think because there are in principle two datasets being 
displayed). Here is that code using manual setting the range of the upper x 
axis:

# -*- coding: utf-8 -*-


import pyqtgraph as pg
from pyqtgraph.Qt import QtCore, QtGui


pg.mkQApp()

MainPlot = pg.PlotWidget()
MainPlot.show()
MainPlot.setWindowTitle('Dual x axis example, synchronized zoom on 
different axes')
AuxPlot = pg.ViewBox()
Shift = 1


#AuxPlot.setXLink(MainPlot) #this line will cause the two x axes to display 
the same range which is not wanted in this example

AuxPlot.setYLink(MainPlot)  #this will synchronize zooming along the y axis

MainPlot.showAxis('top')
MainPlot.scene().addItem(AuxPlot)
AuxPlot.setGeometry(MainPlot.getPlotItem().vb.sceneBoundingRect())
MainPlot.getAxis('top').linkToView(AuxPlot)

##plot data
MainPlot.plot([0,1,2,3],[0,1,2,3], pen="w")
AuxPlot.addItem(pg.PlotCurveItem([-1,0,1,2],[0,1,2,3], pen="b")) #this data 
is scaled differently along the x axis while y is the same as in MainPlot

## This commented section was taken from another user's example but 
##only one x axis zooms while the other is unaffected; modified to
##manually set XRange; doesnt work as both x axes are not aligned correctly

def updateViews():
    ## view has resized; update auxiliary views to match
    global MainPlot, AuxPlot
    AuxPlot.setGeometry(MainPlot.getPlotItem().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)
    AuxPlot.linkedViewChanged(MainPlot.getPlotItem().vb, AuxPlot.YAxis)
    MainPlotXMin, MainPlotXMax = MainPlot.viewRange()[0]
    
    AuxPlotXMin = (MainPlotXMin)-Shift
    AuxPlotXMax = (MainPlotXMax)-Shift
    AuxPlot.setRange(xRange=[AuxPlotXMin,AuxPlotXMax])
    
    print("MainPlotXMin: ",MainPlotXMin)
    print("(MainPlotXMin)-Shift: ",(MainPlotXMin)-Shift)

updateViews()
MainPlot.getPlotItem().sigRangeChanged.connect(updateViews)

##end of other user's example (modified)

## 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_()

What is the correct way of displaying two x axes which represent the same 
single curve in two different "units" in one plot? I am new to this and 
can't get my head around all the different objects (PlotItem, ViewBox 
etc...). Is there a simple way like telling pyqtgraph to plot one dataset 
and then give it scaling factors describing the mapping to the second x 
axis? 

Thanks for your help and time, Chris 

-- 
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/fa10a8af-d3d9-4bf8-9bca-d08bf02f30fe%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to