Raster Plot

332 views
Skip to first unread message

Peter Malonis

unread,
Feb 6, 2014, 4:47:01 PM2/6/14
to pyqt...@googlegroups.com
Hello,

I'm attempting to use pyqtgraph to create a raster plot, which is a plot of event times each represented by a vertical line. Here's an example:
an example of a matplotlib raster plot
The first thing I tried was to make a separate PlotDataItem for each line.  However, once the number of lines reaches around 1000, the plotting is extremely slow or doesn't work at all.  Then I tried making an ImageItem for the whole plot.  The problem with this is that the width of each line depends on the zoom, including whether lines appear at all.  I suppose I could create a class which adjusts the width of the lines in the image depending on the range of the view box, but I'm wondering if there's not a simpler way to do this, or if you have any advice in general.

I really appreciate your help and all the work you've put into this tool.

best,
Peter

Luke Campagnola

unread,
Feb 6, 2014, 7:01:09 PM2/6/14
to pyqt...@googlegroups.com
On Thu, Feb 6, 2014 at 4:47 PM, Peter Malonis <pjma...@gmail.com> wrote:
Hello,

I'm attempting to use pyqtgraph to create a raster plot, which is a plot of event times each represented by a vertical line. Here's an example:
an example of a matplotlib raster plot
The first thing I tried was to make a separate PlotDataItem for each line.  However, once the number of lines reaches around 1000, the plotting is extremely slow or doesn't work at all.  Then I tried making an ImageItem for the whole plot.  The problem with this is that the width of each line depends on the zoom, including whether lines appear at all.  I suppose I could create a class which adjusts the width of the lines in the image depending on the range of the view box, but I'm wondering if there's not a simpler way to do this, or if you have any advice in general.


Hi Peter,

I have two pointers for you: 
1) Use a single GraphItem to draw many disconnected line segments; you'll get much better performance.
2) Have a look at the VTickGroup item; it does almost what you need, but always maintains the vertical tick position relative to the view  boundaries (it is used for marking event times along a plot curve).

Peter Malonis

unread,
Feb 7, 2014, 2:25:15 PM2/7/14
to pyqt...@googlegroups.com
Thanks. The GraphItem works much better.


--
You received this message because you are subscribed to a topic in the Google Groups "pyqtgraph" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/pyqtgraph/O9kTFQ3IRjc/unsubscribe.
To unsubscribe from this group and all its topics, send an email to pyqtgraph+...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/pyqtgraph/CACZXET-XEuAuj4XO%2Bt1EgTe9WFBJn%2BPtA3nq583ZFiA4cbA-jA%40mail.gmail.com.

For more options, visit https://groups.google.com/groups/opt_out.

Chadwick Boulay

unread,
May 23, 2017, 9:18:05 AM5/23/17
to pyqtgraph
Hi, I know this post is old but I came across it recently because I was trying to make a neural raster plot.

For static plots, VTickGroup worked okay except it had a bug (I made a PR here). However, even with the bug fixed, this approach often caused the GUI to crash when I was trying to do online updating. I couldn't figure out why.

Instead, I opted to use a ScatterPlotItem with a custom symbol, where the symbol was just a QPainterPath with 2 vertically-separated points. This works really well for me and I can update it very quickly. Example code is below.

-Chad

import sys
import PyQt5
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *
from PyQt5.QtCore import *
import numpy as np
import pyqtgraph as pg


class MyGUI(QMainWindow):
   
def __init__(self):
       
super(MyGUI, self).__init__()
       
self.setup_ui()
       
self.show()

   
def __del__(self):
       
pass

    def setup_ui(self):
       
self.resize(800, 600)
       
self.setWindowTitle('Test Raster')
       
self.setCentralWidget(QWidget(self))  # This squeezes out docks.
        self.centralWidget().setLayout(QVBoxLayout())

        glw
= pg.GraphicsLayoutWidget()
        glw
.useOpenGL(True)
       
self.centralWidget().layout().addWidget(glw)

        vtick
= QPainterPath()
        vtick
.moveTo(0, -0.5)
        vtick
.lineTo(0, 0.5)

        p1
= glw.addPlot(row=0, col=0)
        p1
.setXRange(-0.05, 1.05)
        p1
.hideAxis('bottom')

        s1
= pg.ScatterPlotItem(pxMode=False)
        s1
.setSymbol(vtick)
        s1
.setSize(1)
        s1
.setPen(QColor(*np.random.randint(0, 255 + 1, 3).tolist()))
        p1
.addItem(s1)

        s2
= pg.ScatterPlotItem(pxMode=False, symbol=vtick, size=1,
                                pen=QColor(*np.random.randint(0, 255 + 1, 3).tolist()))
        p1
.addItem(s2)

       
self.spis = [s1, s2]

   
def update(self):
       
super(MyGUI, self).update()
       
for spi_ix in range(len(self.spis)):
           
self.spis[spi_ix].setData(np.random.rand(10), spi_ix + 0.5 + np.zeros((10,)))


if __name__ == '__main__':
    qapp
= QApplication(sys.argv)
    aw
= MyGUI()
    timer
= QTimer()
    timer
.timeout.connect(aw.update)
    timer
.start(1)

   
if (sys.flags.interactive != 1) or not hasattr(PyQt5.QtCore, 'PYQT_VERSION'):
       
QApplication.instance().exec_()


Luke Campagnola

unread,
May 24, 2017, 11:45:15 PM5/24/17
to pyqt...@googlegroups.com
Nice example, Chad! 
There's another possibility--you can draw the ticks as a single PlotCurveItem using connect='pairs'. I would guess that this is the fastest option, but the ticks would not be scale-invariant like they are with ScatterPlotItem (at least, not without a little extra code).

import pyqtgraph as pg
import numpy as np

x = np.cumsum(abs(np.random.normal(size=10000)))
x[1::2] = x[::2]
y = np.zeros(len(x))
y[1::2] = 1

plt = pg.plot()
c = pg.PlotCurveItem()
c.setData(x, y, connect='pairs', pen=(255, 255, 255, 100))
plt.addItem(c)


--
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/380a87fd-7c41-47b4-9edc-d1ac1efa1eda%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Chadwick Boulay

unread,
May 25, 2017, 2:11:42 PM5/25/17
to pyqtgraph
Scale invariance isn't a desirable feature in a neuronal raster plot.
I tried your method and it works well for me. Thank you.
To unsubscribe from this group and stop receiving emails from it, send an email to pyqtgraph+...@googlegroups.com.
Reply all
Reply to author
Forward
0 new messages