Some basic questions about line plot

3,221 views
Skip to first unread message

Phisatho

unread,
Jul 7, 2012, 12:19:55 PM7/7/12
to pyqt...@googlegroups.com
Hi Luke,
Thanks for the nice widget.

I am using pyqtgraph to plot some plain vanilla line plots. A couple of questions:

1) How can I control the line thickness of individual lines?
2) How can I prevent the user from panning or zooming out? (better still, allow zoom-in but allow zoom-out to the default scale only)
I noticed that item-2 can be done interactively via the pop-up menu, however, I want to do it programatically.

TIA

Luke Campagnola

unread,
Jul 7, 2012, 3:57:28 PM7/7/12
to pyqt...@googlegroups.com
On Sat, Jul 7, 2012 at 12:19 PM, Phisatho <phis...@gmail.com> wrote:
1) How can I control the line thickness of individual lines?

Many ways! Most of the information you need starts here: http://luke.campagnola.me/code/pyqtgraph/documentation/style.html

Two common examples:

    ## set pen on a single data set:
    plotline = plotWidget.plot(xData, yData)
    plotline.setPen(color=(255,0,0), width=3)

    ## set pen while calling a plot():
    plotWidget.plot(xData, yData, pen={'color': (255,0,0), 'width': 3})

 
2) How can I prevent the user from panning or zooming out? (better still, allow zoom-in but allow zoom-out to the default scale only)

HM. Can you describe the effect you are trying to achieve? Do you mean that zooming out with the mouse should be disabled entirely or that you should not be able to zoom out too far? You can achieve something like this by calling ViewBox.setMouseMode(ViewBox.RectMode). You can access the ViewBox by calling PlotItem.getViewBox() or PlotWidget.getPlotItem().getViewBox().

Otherwise, there are currently no limits on how far you can zoom out, although this is a feature I've imagined would be useful since it can be confusing if you accidentally zoom out too far or pan past the edge of the data. If you want to give it a try, the relevant code is in ViewBox.mouseDragEvent(); graphicsItems/ViewBox/ViewBox.py.

I noticed that item-2 can be done interactively via the pop-up menu, however, I want to do it programatically.

The method for this is ViewBox.autoRange(). This method can also be called on a PlotWidget or PlotItem (the documentation for both classes has a list of methods that are wrapped from ViewBox).


Luke

Phisatho

unread,
Jul 8, 2012, 11:19:43 AM7/8/12
to pyqt...@googlegroups.com
Thanks for the hints. mkpen is what I wanted.

On issue-2, setMouseEnabled(False, False) is helpful. It stops pan and zoom. However, I would have preferred to allow zoom-in from the default view ( say to a left-button drag rectangle) and zoom reset by say- right click.
The other issue is right click menu is still present. Is it possible to disable this menu?

Luke Campagnola

unread,
Jul 8, 2012, 2:42:50 PM7/8/12
to pyqt...@googlegroups.com
On Sun, Jul 8, 2012 at 11:19 AM, Phisatho <phis...@gmail.com> wrote:
On issue-2, setMouseEnabled(False, False) is helpful. It stops pan and zoom. However, I would have preferred to allow zoom-in from the default view ( say to a left-button drag rectangle) and zoom reset by say- right click.
The other issue is right click menu is still present. Is it possible to disable this menu?

The menu can be disabled with ViewBox.setMenuEnabled(False)

To get a right-click to auto-scale would require rewriting the mouse event handler for ViewBox. This is a pretty common request, though--many people want finer control over the mouse behavior. I think perhaps the best solution to this is just to make it as easy as possible to write ViewBox subclasses with custom mouse behavior. 

I'll ponder this some more; suggestions welcome.

Luke


Phisatho

unread,
Jul 9, 2012, 11:32:03 AM7/9/12
to pyqt...@googlegroups.com
You are a star!
Example -Customplot in version174 did exactly what I wanted.

Phisatho

unread,
Jul 9, 2012, 1:28:46 PM7/9/12
to pyqt...@googlegroups.com
Actually, I had to change
self.autoRange()
to
pw.setXRange()
pw.setYRange()
to attain what I wanted

Some more questions.
Does setXRange and YRange accept only integers?
I put
pw.setYRange(0, 0.03)
The axis scaled correctly, but the axis was labelled 0 to 30 instead of 0 to 0.03

How can I modify major division and minor division of grids and axis labels?

Is it possible to show a small image inside a plotwidget?




On Monday, July 9, 2012 7:32:03 PM UTC+4, Phisatho wrote:
You are a star!
Example -Customplot in version174 did exactly what I wanted.

On Sunday, July 8, 2012 10:42:50 PM UTC+4, Luke Campagnola wrote:

Luke Campagnola

unread,
Jul 9, 2012, 2:24:19 PM7/9/12
to pyqt...@googlegroups.com
On Mon, Jul 9, 2012 at 1:28 PM, Phisatho <phis...@gmail.com> wrote:
Some more questions.
Does setXRange and YRange accept only integers?

Floats are fine; see below.
 
I put
pw.setYRange(0, 0.03)
The axis scaled correctly, but the axis was labelled 0 to 30 instead of 0 to 0.03

This should only happen if the axis has units set. For example, if the axis units are 's', then the range you specified would appear as 0-30 ms on the axis.
If you do not have units set, then there is something else fishy going on and I'll need more information.

This behavior can be disabled with plotItem.getAxis('bottom').setScale(1)
(correction: there is a bug that prevents this working correctly; fix forthcoming)
 
How can I modify major division and minor division of grids and axis labels?

There are a few approaches to this:
1) create a subclass of AxisItem that overrides tickSpacing() 
2) create a subclass of AxisItem that overrides tickValues()
3) call AxisItem.setTicks(...) to explicitly set the list of ticks to be displayed

The AxisItem documentation has more information about these methods; please let me know if it is unclear and I'll update the docs.
I'm also happy to take suggestions about improving the API for controlling axes.


Is it possible to show a small image inside a plotwidget?


Like this:

img = pg.ImageItem(data, ...)
plotItem.addItem(img)
img.setRect(QtCore.QRectF(...))  ## determines the position and size of the image


Cheers,
Luke

Phisatho

unread,
Jul 10, 2012, 4:20:17 PM7/10/12
to pyqt...@googlegroups.com
Yeah, that is right.I used a unit - kg/kg. I did not notice that it changed to mkg/kg.
Set scale(1) solved the problem with the latest version

Now I notice an autoscale button at the left bottom corner. Is it newly introduced? or is it that I did not notice it? How can I hide it?

On tick spacing, I see that there is no settickspacing method. I am a bit struggling to subclass the AxisItem. (I am yet to get a grip on OOP)


On Monday, July 9, 2012 10:24:19 PM UTC+4, Luke Campagnola wrote:

Luke Campagnola

unread,
Jul 10, 2012, 4:59:44 PM7/10/12
to pyqt...@googlegroups.com
On Tue, Jul 10, 2012 at 4:20 PM, Phisatho <phis...@gmail.com> wrote:
Now I notice an autoscale button at the left bottom corner. Is it newly introduced? or is it that I did not notice it? How can I hide it?

It is not new; you can use plotItem.hideButtons() 
(which I see is not documented.. I'll correct that)
 
On tick spacing, I see that there is no settickspacing method. I am a bit struggling to subclass the AxisItem. (I am yet to get a grip on OOP)

That's correct, there is no setTickSpacing method. I suppose I could add one.. 
The important thing to understand is that when the AxisItem is deciding what ticks it should draw (given the min/max range values), it first consults its own tickSpacing method to determine what the major/minor spacings should be.

Here's a simple example of an AxisItem subclass that always has major ticks spaced 10 units apart and minor ticks spaced 1 unit apart:

class FixedAxisItem(pg.AxisItem):
    def tickSpacing(self, minVal, maxVal, size):
        return [(10, 0), (1, 0)]

This axis class could then be placed into a PlotItem exactly as shown in the custom plot example.
You could also pretty easily implement your own setTickSpacing with this:

class FixedAxisItem(pg.AxisItem):
    def __init__(self, *args, **kwds):
        self.spacing = [10, 1]
        pg.AxisItem.__init__(self, *args, **kwds)
 
    def setTickSpacing(self, *spacing):
        self.spacing = spacing

    def tickSpacing(self, minVal, maxVal, size):
        return [(x, 0) for x in self.spacing]


Let me know if this doesn't make sense. I definitely recommend reading up on OOP as Qt inherently relies on it pretty heavily.

Luke






Phisatho

unread,
Jul 11, 2012, 4:14:55 PM7/11/12
to pyqt...@googlegroups.com
All solutions worked perfectly

Only thing is the image is displayed 90 deg rotated. I had to use np.rot90 thrice to straighten the image

On Wednesday, July 11, 2012 12:59:44 AM UTC+4, Luke Campagnola wrote:
Reply all
Reply to author
Forward
0 new messages