Question

I'm creating a Nyquist plot in PyQwt. It currently works, except I need to flip the y-axis - the convention has zero at the bottom and increasing negative numbers as you go up.

I know how you would do this in C++, but cannot figure out how to do it in Python. I don't fully understand how Qt/Qwt translates into PyQt/PyQwt. According to http://qwt.sourceforge.net/class_qwt_scale_engine.html, there's an attribute Inverted to set. In C++, this would look like:

ui.plotWidget->axisScaleEngine(QwtPlot::yLeft)->setAttribute(QwtScaleEngine::Inverted, true);

I can't figure out a way to do this, I've tried several approaches in my main window's __init__(self):

self.ui.qwtPlot.setAxisTitle(Qwt.QwtPlot.yLeft, 'Imaginary Impedance')
self.ui.qwtPlot.setAxisScaleEngine(Qwt.QwtPlot.yLeft, Qwt.QwtScaleEngine.Inverted))
# TypeError: QwtPlot.setAxisScaleEngine(): argument 2 has unexpected type 'Attribute'
self.ui.qwtPlot.setAxisScaleEngine(Qwt.QwtPlot.yLeft,   Qwt.QwtScaleEngine.setAttribute(Inverted))
# NameError: global name 'Inverted' is not defined
self.ui.qwtPlot.setAxisScaleEngine(Qwt.QwtPlot.yLeft, Qwt.QwtScaleEngine.setAttribute(Qwt.QwtScaleEngine.Inverted)
# TypeError: QwtScaleEngine.setAttribute(): first argument of unbound method must have type 'QwtScaleEngine'

I also tried defining a new class, as was done in http://sourceforge.net/p/pyqwt/patches/1/ , as in:

class InvertedAxisEngine(Qwt.QwtScaleEngine):
    def __init__(self):
        Qwt.QwtScaleEngine.__init__(self)
        self.setAttribute(Qwt.QwtScaleEngine.Inverted)
# back in Window.__init__(self)
self.ui.qwtPlot.setAxisScaleEngine(Qwt.QwtPlot.yLeft, InvertedAxisEngine)
#TypeError: QwtPlot.setAxisScaleEngine(): argument 2 has unexpected type 'PyQt4.QtCore.pyqtWrapperType'
self.ui.qwtPlot.setAxisScaleEngine(Qwt.QwtPlot.yLeft, InvertedAxisEngine())
# NotImplementedError: QwtScaleEngine.divideScale() is abstract and must be overridden
#NotImplementedError: QwtScaleEngine.transformation() is abstract and must be overridden

I get the feeling I'm making this too complicated.

EDIT - Comment below inspired a couple of things, like adding =True to Inverted (nope, no keyword arguments, and I also tried this, which goes make to the the unexpected type (wrapper).

self.ui.inverted_engine = Qwt.QwtScaleEngine
self.ui.inverted_engine.Inverted = True        
self.ui.qwtPlot.setAxisScaleEngine(Qwt.QwtPlot.yLeft, self.ui.inverted_engine)

I have no interpreter prompt access while the GUI runs, but I added a print dir(Qwt.QwtScaleEngine) to the init, and it certainly exists: ['Attribute', 'Floating', 'IncludeReference', 'Inverted', 'NoAttribute', 'Symmetric', '__class__',....

Was it helpful?

Solution

I finally figured this out after examining the code at http://orange.biolab.si/svn/orange/externals/trunk/install-scripts/mac/bundle/Orange.app/Contents/Frameworks/Python.framework/Versions/2.6/lib/python2.6/site-packages/PyQt4/Qwt5/qplt.py . I think there's probably also a way to do this using setAxisScaleEngine(), but this works.

    QMainWindow.__init__(self)
    self.ui = Ui_MainWindow()
    self.ui.setupUi(self)
    self.ui.qwtPlot.setAxisTitle(Qwt.QwtPlot.yLeft, 'Imaginary Impedance (ohms)')
    self.ui.qwtPlot.setCanvasBackground(Qt.white)
    engine = self.ui.qwtPlot.axisScaleEngine(Qwt.QwtPlot.yLeft)
    Qwt.QwtScaleEngine.setAttribute(engine, Qwt.QwtScaleEngine.Inverted)
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top