Python pyqtgraph.plot() Examples

The following are 16 code examples of pyqtgraph.plot(). You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example. You may also want to check out all available functions/classes of the module pyqtgraph , or try the search function .
Example #1
Source File: PerformanceTest.py    From liblsl-Python with MIT License 6 votes vote down vote up
def update():
    markerGen.update()
    markerIn.update()
    betaGen.update(task=markerIn.task)  # Rate-limiting step. Will time.sleep as needed.
    signal, tvec = betaIn.update()

    if haspyqtgraph:
        plot = qwindow.getPlotItem()
        graphs = plot.listDataItems()
        if not graphs:
            # create graphs
            for i in range(signal.shape[1]):
                plot.plot(tvec, signal[:, i])
        else:
            # update graphs
            for i in range(signal.shape[1]):
                graphs[i].setData(signal[:, i], x=tvec) 
Example #2
Source File: test_pyqtgraph_benchmark.py    From pyrpl with GNU General Public License v3.0 6 votes vote down vote up
def update_plot(self):
        self.cycle += 1
        if self.cycle == 1:
            self.starttime = time.time()
        if self.cycle == self.cycles:
            self.endtime = time.time()
        if self.REDPITAYA:
            t = self.r.scope.times
            #y1 = self.r.scope.curve(ch=1, timeout=0)
            #y2 = self.r.scope.curve(ch=2, timeout=0)
            #self.r.scope.setup()
            y1 = self.r.scope._data_ch1_current
            y2 = self.r.scope._data_ch2_current
        else:
            t = self.t0 + (time.time()-self.starttime)
            phi = 2.0*np.pi*self.frequency*t
            y1 = np.sin(phi)
            y2 = np.cos(phi)
        if self.cycle == 1:
            self.c1 = self.plotWidget.plot(t, y1, pen='g')
            self.c2 = self.plotWidget.plot(t, y2, pen='r')
        else:
            self.c1.setData(t, y1)
            self.c2.setData(t, y2) 
Example #3
Source File: logic.py    From Calculator_pyqt with MIT License 6 votes vote down vote up
def clicked(self):
	l = float(self.edit1.text())
	r = float(self.edit2.text())
	s = float(self.edit3.text())
	x = np.arange(l,r,s)
	print(x)
	s = calculator_class.var
	print("In Second")
	print(s)
	y = eval(s)
	pg.setConfigOption('background', 'w')      # sets background white
    	pg.setConfigOption('foreground', 'k')      # sets axis color to black
	pw = pg.plot(x,y,pen = 'k')
	pw.setTitle('y = f(x)')
   	pw.setLabel('bottom', 'x -->')           	# x-label
    	pw.setLabel('left', 'y = f(x) -->')             # y-label 
Example #4
Source File: test_csv.py    From tf-pose with Apache License 2.0 5 votes vote down vote up
def test_CSVExporter():
    tempfilename = tempfile.NamedTemporaryFile(suffix='.csv').name
    print("using %s as a temporary file" % tempfilename)
    
    plt = pg.plot()
    y1 = [1,3,2,3,1,6,9,8,4,2]
    plt.plot(y=y1, name='myPlot')
    
    y2 = [3,4,6,1,2,4,2,3,5,3,5,1,3]
    x2 = pg.np.linspace(0, 1.0, len(y2))
    plt.plot(x=x2, y=y2)
    
    y3 = [1,5,2,3,4,6,1,2,4,2,3,5,3]
    x3 = pg.np.linspace(0, 1.0, len(y3)+1)
    plt.plot(x=x3, y=y3, stepMode=True)
    
    ex = pg.exporters.CSVExporter(plt.plotItem)
    ex.export(fileName=tempfilename)

    r = csv.reader(open(tempfilename, 'r'))
    lines = [line for line in r]
    header = lines.pop(0)
    assert header == ['myPlot_x', 'myPlot_y', 'x0001', 'y0001', 'x0002', 'y0002']
    
    i = 0
    for vals in lines:
        vals = list(map(str.strip, vals))
        assert (i >= len(y1) and vals[0] == '') or approxeq(float(vals[0]), i) 
        assert (i >= len(y1) and vals[1] == '') or approxeq(float(vals[1]), y1[i]) 
        
        assert (i >= len(x2) and vals[2] == '') or approxeq(float(vals[2]), x2[i])
        assert (i >= len(y2) and vals[3] == '') or approxeq(float(vals[3]), y2[i])
        
        assert (i >= len(x3) and vals[4] == '') or approxeq(float(vals[4]), x3[i])
        assert (i >= len(y3) and vals[5] == '') or approxeq(float(vals[5]), y3[i])
        i += 1

    os.unlink(tempfilename) 
Example #5
Source File: test_InfiniteLine.py    From tf-pose with Apache License 2.0 5 votes vote down vote up
def test_InfiniteLine():
    # Test basic InfiniteLine API
    plt = pg.plot()
    plt.setXRange(-10, 10)
    plt.setYRange(-10, 10)
    plt.resize(600, 600)
    
    # seemingly arbitrary requirements; might need longer wait time for some platforms..
    QtTest.QTest.qWaitForWindowShown(plt)
    QtTest.QTest.qWait(100)
    
    vline = plt.addLine(x=1)
    assert vline.angle == 90
    br = vline.mapToView(QtGui.QPolygonF(vline.boundingRect()))
    assert br.containsPoint(pg.Point(1, 5), QtCore.Qt.OddEvenFill)
    assert not br.containsPoint(pg.Point(5, 0), QtCore.Qt.OddEvenFill)
    hline = plt.addLine(y=0)
    assert hline.angle == 0
    assert hline.boundingRect().contains(pg.Point(5, 0))
    assert not hline.boundingRect().contains(pg.Point(0, 5))

    vline.setValue(2)
    assert vline.value() == 2
    vline.setPos(pg.Point(4, -5))
    assert vline.value() == 4
    
    oline = pg.InfiniteLine(angle=30)
    plt.addItem(oline)
    oline.setPos(pg.Point(1, -1))
    assert oline.angle == 30
    assert oline.pos() == pg.Point(1, -1)
    assert oline.value() == [1, -1]
    
    # test bounding rect for oblique line
    br = oline.mapToScene(oline.boundingRect())
    pos = oline.mapToScene(pg.Point(2, 0))
    assert br.containsPoint(pos, QtCore.Qt.OddEvenFill)
    px = pg.Point(-0.5, -1.0 / 3**0.5)
    assert br.containsPoint(pos + 5 * px, QtCore.Qt.OddEvenFill)
    assert not br.containsPoint(pos + 7 * px, QtCore.Qt.OddEvenFill) 
Example #6
Source File: test_csv.py    From soapy with GNU General Public License v3.0 5 votes vote down vote up
def test_CSVExporter():
    tempfilename = tempfile.NamedTemporaryFile(suffix='.csv').name
    print("using %s as a temporary file" % tempfilename)
    
    plt = pg.plot()
    y1 = [1,3,2,3,1,6,9,8,4,2]
    plt.plot(y=y1, name='myPlot')
    
    y2 = [3,4,6,1,2,4,2,3,5,3,5,1,3]
    x2 = pg.np.linspace(0, 1.0, len(y2))
    plt.plot(x=x2, y=y2)
    
    y3 = [1,5,2,3,4,6,1,2,4,2,3,5,3]
    x3 = pg.np.linspace(0, 1.0, len(y3)+1)
    plt.plot(x=x3, y=y3, stepMode=True)
    
    ex = pg.exporters.CSVExporter(plt.plotItem)
    ex.export(fileName=tempfilename)

    r = csv.reader(open(tempfilename, 'r'))
    lines = [line for line in r]
    header = lines.pop(0)
    assert header == ['myPlot_x', 'myPlot_y', 'x0001', 'y0001', 'x0002', 'y0002']
    
    i = 0
    for vals in lines:
        vals = list(map(str.strip, vals))
        assert (i >= len(y1) and vals[0] == '') or approxeq(float(vals[0]), i) 
        assert (i >= len(y1) and vals[1] == '') or approxeq(float(vals[1]), y1[i]) 
        
        assert (i >= len(x2) and vals[2] == '') or approxeq(float(vals[2]), x2[i])
        assert (i >= len(y2) and vals[3] == '') or approxeq(float(vals[3]), y2[i])
        
        assert (i >= len(x3) and vals[4] == '') or approxeq(float(vals[4]), x3[i])
        assert (i >= len(y3) and vals[5] == '') or approxeq(float(vals[5]), y3[i])
        i += 1

    os.unlink(tempfilename) 
Example #7
Source File: test_InfiniteLine.py    From soapy with GNU General Public License v3.0 5 votes vote down vote up
def test_InfiniteLine():
    # Test basic InfiniteLine API
    plt = pg.plot()
    plt.setXRange(-10, 10)
    plt.setYRange(-10, 10)
    plt.resize(600, 600)
    
    # seemingly arbitrary requirements; might need longer wait time for some platforms..
    QtTest.QTest.qWaitForWindowShown(plt)
    QtTest.QTest.qWait(100)
    
    vline = plt.addLine(x=1)
    assert vline.angle == 90
    br = vline.mapToView(QtGui.QPolygonF(vline.boundingRect()))
    assert br.containsPoint(pg.Point(1, 5), QtCore.Qt.OddEvenFill)
    assert not br.containsPoint(pg.Point(5, 0), QtCore.Qt.OddEvenFill)
    hline = plt.addLine(y=0)
    assert hline.angle == 0
    assert hline.boundingRect().contains(pg.Point(5, 0))
    assert not hline.boundingRect().contains(pg.Point(0, 5))

    vline.setValue(2)
    assert vline.value() == 2
    vline.setPos(pg.Point(4, -5))
    assert vline.value() == 4
    
    oline = pg.InfiniteLine(angle=30)
    plt.addItem(oline)
    oline.setPos(pg.Point(1, -1))
    assert oline.angle == 30
    assert oline.pos() == pg.Point(1, -1)
    assert oline.value() == [1, -1]
    
    # test bounding rect for oblique line
    br = oline.mapToScene(oline.boundingRect())
    pos = oline.mapToScene(pg.Point(2, 0))
    assert br.containsPoint(pos, QtCore.Qt.OddEvenFill)
    px = pg.Point(-0.5, -1.0 / 3**0.5)
    assert br.containsPoint(pos + 5 * px, QtCore.Qt.OddEvenFill)
    assert not br.containsPoint(pos + 7 * px, QtCore.Qt.OddEvenFill) 
Example #8
Source File: ReceiveAndPlot.py    From liblsl-Python with MIT License 5 votes vote down vote up
def pull_and_plot(self, plot_time: float, plt: pg.PlotItem):
        """Pull data from the inlet and add it to the plot.
        :param plot_time: lowest timestamp that's still visible in the plot
        :param plt: the plot the data should be shown on
        """
        # We don't know what to do with a generic inlet, so we skip it.
        pass 
Example #9
Source File: ReceiveAndPlot.py    From liblsl-Python with MIT License 5 votes vote down vote up
def pull_and_plot(self, plot_time, plt):
        # pull the data
        _, ts = self.inlet.pull_chunk(timeout=0.0,
                                      max_samples=self.buffer.shape[0],
                                      dest_obj=self.buffer)
        # ts will be empty if no samples were pulled, a list of timestamps otherwise
        if ts:
            ts = np.asarray(ts)
            y = self.buffer[0:ts.size, :]
            this_x = None
            old_offset = 0
            new_offset = 0
            for ch_ix in range(self.channel_count):
                # we don't pull an entire screen's worth of data, so we have to
                # trim the old data and append the new data to it
                old_x, old_y = self.curves[ch_ix].getData()
                # the timestamps are identical for all channels, so we need to do
                # this calculation only once
                if ch_ix == 0:
                    # find the index of the first sample that's still visible,
                    # i.e. newer than the left border of the plot
                    old_offset = old_x.searchsorted(plot_time)
                    # same for the new data, in case we pulled more data than
                    # can be shown at once
                    new_offset = ts.searchsorted(plot_time)
                    # append new timestamps to the trimmed old timestamps
                    this_x = np.hstack((old_x[old_offset:], ts[new_offset:]))
                # append new data to the trimmed old data
                this_y = np.hstack((old_y[old_offset:], y[new_offset:, ch_ix] - ch_ix))
                # replace the old data
                self.curves[ch_ix].setData(this_x, this_y) 
Example #10
Source File: test_pyqtgraph_benchmark.py    From pyrpl with GNU General Public License v3.0 5 votes vote down vote up
def setup(self):
        self.t0 = np.linspace(0, self.duration, self.N)
        self.plotWidget = pg.plot(title="Realtime plotting benchmark")
        self.cycle = 0
        self.starttime = time.time()  # not yet the actual starttime, but needed for timeout
        if self.REDPITAYA:
            self.r.scope.setup(trigger_source='immediately', duration=self.duration)
        self.timer = QtCore.QTimer()
        self.timer.setInterval(1000*self.dt)
        self.timer.timeout.connect(self.update_plot)
        self.timer.start() 
Example #11
Source File: test_csv.py    From qgisSpaceSyntaxToolkit with GNU General Public License v3.0 5 votes vote down vote up
def test_CSVExporter():
    tempfilename = tempfile.NamedTemporaryFile(suffix='.csv').name
    print("using %s as a temporary file" % tempfilename)
    
    plt = pg.plot()
    y1 = [1,3,2,3,1,6,9,8,4,2]
    plt.plot(y=y1, name='myPlot')
    
    y2 = [3,4,6,1,2,4,2,3,5,3,5,1,3]
    x2 = pg.np.linspace(0, 1.0, len(y2))
    plt.plot(x=x2, y=y2)
    
    y3 = [1,5,2,3,4,6,1,2,4,2,3,5,3]
    x3 = pg.np.linspace(0, 1.0, len(y3)+1)
    plt.plot(x=x3, y=y3, stepMode=True)
    
    ex = pg.exporters.CSVExporter(plt.plotItem)
    ex.export(fileName=tempfilename)

    r = csv.reader(open(tempfilename, 'r'))
    lines = [line for line in r]
    header = lines.pop(0)
    assert header == ['myPlot_x', 'myPlot_y', 'x0001', 'y0001', 'x0002', 'y0002']
    
    i = 0
    for vals in lines:
        vals = list(map(str.strip, vals))
        assert (i >= len(y1) and vals[0] == '') or approxeq(float(vals[0]), i) 
        assert (i >= len(y1) and vals[1] == '') or approxeq(float(vals[1]), y1[i]) 
        
        assert (i >= len(x2) and vals[2] == '') or approxeq(float(vals[2]), x2[i])
        assert (i >= len(y2) and vals[3] == '') or approxeq(float(vals[3]), y2[i])
        
        assert (i >= len(x3) and vals[4] == '') or approxeq(float(vals[4]), x3[i])
        assert (i >= len(y3) and vals[5] == '') or approxeq(float(vals[5]), y3[i])
        i += 1

    os.unlink(tempfilename) 
Example #12
Source File: hdf5.py    From tf-pose with Apache License 2.0 4 votes vote down vote up
def updateHDF5Plot(self):
        if self.hdf5 is None:
            self.setData([])
            return
        
        vb = self.getViewBox()
        if vb is None:
            return  # no ViewBox yet
        
        # Determine what data range must be read from HDF5
        xrange = vb.viewRange()[0]
        start = max(0,int(xrange[0])-1)
        stop = min(len(self.hdf5), int(xrange[1]+2))
        
        # Decide by how much we should downsample 
        ds = int((stop-start) / self.limit) + 1
        
        if ds == 1:
            # Small enough to display with no intervention.
            visible = self.hdf5[start:stop]
            scale = 1
        else:
            # Here convert data into a down-sampled array suitable for visualizing.
            # Must do this piecewise to limit memory usage.        
            samples = 1 + ((stop-start) // ds)
            visible = np.zeros(samples*2, dtype=self.hdf5.dtype)
            sourcePtr = start
            targetPtr = 0
            
            # read data in chunks of ~1M samples
            chunkSize = (1000000//ds) * ds
            while sourcePtr < stop-1: 
                chunk = self.hdf5[sourcePtr:min(stop,sourcePtr+chunkSize)]
                sourcePtr += len(chunk)
                
                # reshape chunk to be integral multiple of ds
                chunk = chunk[:(len(chunk)//ds) * ds].reshape(len(chunk)//ds, ds)
                
                # compute max and min
                chunkMax = chunk.max(axis=1)
                chunkMin = chunk.min(axis=1)
                
                # interleave min and max into plot data to preserve envelope shape
                visible[targetPtr:targetPtr+chunk.shape[0]*2:2] = chunkMin
                visible[1+targetPtr:1+targetPtr+chunk.shape[0]*2:2] = chunkMax
                targetPtr += chunk.shape[0]*2
            
            visible = visible[:targetPtr]
            scale = ds * 0.5
            
        self.setData(visible) # update the plot
        self.setPos(start, 0) # shift to match starting index
        self.resetTransform()
        self.scale(scale, 1)  # scale to match downsampling 
Example #13
Source File: test_InfiniteLine.py    From tf-pose with Apache License 2.0 4 votes vote down vote up
def test_mouseInteraction():
    plt = pg.plot()
    plt.scene().minDragTime = 0  # let us simulate mouse drags very quickly.
    vline = plt.addLine(x=0, movable=True)
    plt.addItem(vline)
    hline = plt.addLine(y=0, movable=True)
    hline2 = plt.addLine(y=-1, movable=False)
    plt.setXRange(-10, 10)
    plt.setYRange(-10, 10)
    
    # test horizontal drag
    pos = plt.plotItem.vb.mapViewToScene(pg.Point(0,5)).toPoint()
    pos2 = pos - QtCore.QPoint(200, 200)
    mouseMove(plt, pos)
    assert vline.mouseHovering is True and hline.mouseHovering is False
    mouseDrag(plt, pos, pos2, QtCore.Qt.LeftButton)
    px = vline.pixelLength(pg.Point(1, 0), ortho=True)
    assert abs(vline.value() - plt.plotItem.vb.mapSceneToView(pos2).x()) <= px

    # test missed drag
    pos = plt.plotItem.vb.mapViewToScene(pg.Point(5,0)).toPoint()
    pos = pos + QtCore.QPoint(0, 6)
    pos2 = pos + QtCore.QPoint(-20, -20)
    mouseMove(plt, pos)
    assert vline.mouseHovering is False and hline.mouseHovering is False
    mouseDrag(plt, pos, pos2, QtCore.Qt.LeftButton)
    assert hline.value() == 0

    # test vertical drag
    pos = plt.plotItem.vb.mapViewToScene(pg.Point(5,0)).toPoint()
    pos2 = pos - QtCore.QPoint(50, 50)
    mouseMove(plt, pos)
    assert vline.mouseHovering is False and hline.mouseHovering is True
    mouseDrag(plt, pos, pos2, QtCore.Qt.LeftButton)
    px = hline.pixelLength(pg.Point(1, 0), ortho=True)
    assert abs(hline.value() - plt.plotItem.vb.mapSceneToView(pos2).y()) <= px

    # test non-interactive line
    pos = plt.plotItem.vb.mapViewToScene(pg.Point(5,-1)).toPoint()
    pos2 = pos - QtCore.QPoint(50, 50)
    mouseMove(plt, pos)
    assert hline2.mouseHovering == False
    mouseDrag(plt, pos, pos2, QtCore.Qt.LeftButton)
    assert hline2.value() == -1 
Example #14
Source File: test_InfiniteLine.py    From soapy with GNU General Public License v3.0 4 votes vote down vote up
def test_mouseInteraction():
    plt = pg.plot()
    plt.scene().minDragTime = 0  # let us simulate mouse drags very quickly.
    vline = plt.addLine(x=0, movable=True)
    plt.addItem(vline)
    hline = plt.addLine(y=0, movable=True)
    hline2 = plt.addLine(y=-1, movable=False)
    plt.setXRange(-10, 10)
    plt.setYRange(-10, 10)
    
    # test horizontal drag
    pos = plt.plotItem.vb.mapViewToScene(pg.Point(0,5)).toPoint()
    pos2 = pos - QtCore.QPoint(200, 200)
    mouseMove(plt, pos)
    assert vline.mouseHovering is True and hline.mouseHovering is False
    mouseDrag(plt, pos, pos2, QtCore.Qt.LeftButton)
    px = vline.pixelLength(pg.Point(1, 0), ortho=True)
    assert abs(vline.value() - plt.plotItem.vb.mapSceneToView(pos2).x()) <= px

    # test missed drag
    pos = plt.plotItem.vb.mapViewToScene(pg.Point(5,0)).toPoint()
    pos = pos + QtCore.QPoint(0, 6)
    pos2 = pos + QtCore.QPoint(-20, -20)
    mouseMove(plt, pos)
    assert vline.mouseHovering is False and hline.mouseHovering is False
    mouseDrag(plt, pos, pos2, QtCore.Qt.LeftButton)
    assert hline.value() == 0

    # test vertical drag
    pos = plt.plotItem.vb.mapViewToScene(pg.Point(5,0)).toPoint()
    pos2 = pos - QtCore.QPoint(50, 50)
    mouseMove(plt, pos)
    assert vline.mouseHovering is False and hline.mouseHovering is True
    mouseDrag(plt, pos, pos2, QtCore.Qt.LeftButton)
    px = hline.pixelLength(pg.Point(1, 0), ortho=True)
    assert abs(hline.value() - plt.plotItem.vb.mapSceneToView(pos2).y()) <= px

    # test non-interactive line
    pos = plt.plotItem.vb.mapViewToScene(pg.Point(5,-1)).toPoint()
    pos2 = pos - QtCore.QPoint(50, 50)
    mouseMove(plt, pos)
    assert hline2.mouseHovering == False
    mouseDrag(plt, pos, pos2, QtCore.Qt.LeftButton)
    assert hline2.value() == -1 
Example #15
Source File: ReceiveAndPlot.py    From liblsl-Python with MIT License 4 votes vote down vote up
def main():
    # firstly resolve all streams that could be shown
    inlets: List[Inlet] = []
    print("looking for streams")
    streams = pylsl.resolve_streams()

    # Create the pyqtgraph window
    pw = pg.plot(title='LSL Plot')
    plt = pw.getPlotItem()
    plt.enableAutoRange(x=False, y=True)

    # iterate over found streams, creating specialized inlet objects that will
    # handle plotting the data
    for info in streams:
        if info.type() == 'Markers':
            if info.nominal_srate() != pylsl.IRREGULAR_RATE \
                    or info.channel_format() != pylsl.cf_string:
                print('Invalid marker stream ' + info.name())
            print('Adding marker inlet: ' + info.name())
            inlets.append(MarkerInlet(info))
        elif info.nominal_srate() != pylsl.IRREGULAR_RATE \
                and info.channel_format() != pylsl.cf_string:
            print('Adding data inlet: ' + info.name())
            inlets.append(DataInlet(info, plt))
        else:
            print('Don\'t know what to do with stream ' + info.name())

    def scroll():
        """Move the view so the data appears to scroll"""
        # We show data only up to a timepoint shortly before the current time
        # so new data doesn't suddenly appear in the middle of the plot
        fudge_factor = pull_interval * .002
        plot_time = pylsl.local_clock()
        pw.setXRange(plot_time - plot_duration + fudge_factor, plot_time - fudge_factor)

    def update():
        # Read data from the inlet. Use a timeout of 0.0 so we don't block GUI interaction.
        mintime = pylsl.local_clock() - plot_duration
        # call pull_and_plot for each inlet.
        # Special handling of inlet types (markers, continuous data) is done in
        # the different inlet classes.
        for inlet in inlets:
            inlet.pull_and_plot(mintime, plt)

    # create a timer that will move the view every update_interval ms
    update_timer = QtCore.QTimer()
    update_timer.timeout.connect(scroll)
    update_timer.start(update_interval)

    # create a timer that will pull and add new data occasionally
    pull_timer = QtCore.QTimer()
    pull_timer.timeout.connect(update)
    pull_timer.start(pull_interval)

    import sys

    # Start Qt event loop unless running in interactive mode or using pyside.
    if (sys.flags.interactive != 1) or not hasattr(QtCore, 'PYQT_VERSION'):
        QtGui.QApplication.instance().exec_() 
Example #16
Source File: hdf5.py    From qgisSpaceSyntaxToolkit with GNU General Public License v3.0 4 votes vote down vote up
def updateHDF5Plot(self):
        if self.hdf5 is None:
            self.setData([])
            return
        
        vb = self.getViewBox()
        if vb is None:
            return  # no ViewBox yet
        
        # Determine what data range must be read from HDF5
        xrange = vb.viewRange()[0]
        start = max(0,int(xrange[0])-1)
        stop = min(len(self.hdf5), int(xrange[1]+2))
        
        # Decide by how much we should downsample 
        ds = int((stop-start) / self.limit) + 1
        
        if ds == 1:
            # Small enough to display with no intervention.
            visible = self.hdf5[start:stop]
            scale = 1
        else:
            # Here convert data into a down-sampled array suitable for visualizing.
            # Must do this piecewise to limit memory usage.        
            samples = 1 + ((stop-start) // ds)
            visible = np.zeros(samples*2, dtype=self.hdf5.dtype)
            sourcePtr = start
            targetPtr = 0
            
            # read data in chunks of ~1M samples
            chunkSize = (1000000//ds) * ds
            while sourcePtr < stop-1: 
                chunk = self.hdf5[sourcePtr:min(stop,sourcePtr+chunkSize)]
                sourcePtr += len(chunk)
                
                # reshape chunk to be integral multiple of ds
                chunk = chunk[:(len(chunk)//ds) * ds].reshape(len(chunk)//ds, ds)
                
                # compute max and min
                chunkMax = chunk.max(axis=1)
                chunkMin = chunk.min(axis=1)
                
                # interleave min and max into plot data to preserve envelope shape
                visible[targetPtr:targetPtr+chunk.shape[0]*2:2] = chunkMin
                visible[1+targetPtr:1+targetPtr+chunk.shape[0]*2:2] = chunkMax
                targetPtr += chunk.shape[0]*2
            
            visible = visible[:targetPtr]
            scale = ds * 0.5
            
        self.setData(visible) # update the plot
        self.setPos(start, 0) # shift to match starting index
        self.resetTransform()
        self.scale(scale, 1)  # scale to match downsampling