2021-04-29 04:35:27 +00:00
|
|
|
# -*- coding: utf-8 -*-
|
2017-02-06 07:13:00 +00:00
|
|
|
import numpy as np
|
|
|
|
import pyqtgraph as pg
|
2021-03-23 18:54:15 +00:00
|
|
|
from pyqtgraph.Qt import QtGui
|
2017-02-06 07:13:00 +00:00
|
|
|
|
|
|
|
pg.mkQApp()
|
|
|
|
|
|
|
|
|
2021-04-29 04:35:27 +00:00
|
|
|
def test_bool():
|
|
|
|
truths = np.random.randint(0, 2, size=(100,)).astype(bool)
|
|
|
|
pdi = pg.PlotDataItem(truths)
|
|
|
|
bounds = pdi.dataBounds(1)
|
|
|
|
assert isinstance(bounds[0], np.uint8)
|
|
|
|
assert isinstance(bounds[1], np.uint8)
|
|
|
|
xdata, ydata = pdi.getData()
|
|
|
|
assert ydata.dtype == np.uint8
|
|
|
|
|
|
|
|
|
2017-02-06 07:13:00 +00:00
|
|
|
def test_fft():
|
|
|
|
f = 20.
|
|
|
|
x = np.linspace(0, 1, 1000)
|
|
|
|
y = np.sin(2 * np.pi * f * x)
|
|
|
|
pd = pg.PlotDataItem(x, y)
|
2016-12-15 14:26:19 +00:00
|
|
|
pd.setFftMode(True)
|
2017-02-06 07:13:00 +00:00
|
|
|
x, y = pd.getData()
|
|
|
|
assert abs(x[np.argmax(y)] - f) < 0.03
|
2016-12-15 14:26:19 +00:00
|
|
|
|
2017-02-06 07:13:00 +00:00
|
|
|
x = np.linspace(0, 1, 1001)
|
|
|
|
y = np.sin(2 * np.pi * f * x)
|
|
|
|
pd.setData(x, y)
|
|
|
|
x, y = pd.getData()
|
|
|
|
assert abs(x[np.argmax(y)]- f) < 0.03
|
2016-12-15 14:26:19 +00:00
|
|
|
|
2017-02-06 07:13:00 +00:00
|
|
|
pd.setLogMode(True, False)
|
|
|
|
x, y = pd.getData()
|
|
|
|
assert abs(x[np.argmax(y)] - np.log10(f)) < 0.01
|
2018-04-05 03:13:09 +00:00
|
|
|
|
|
|
|
def test_setData():
|
|
|
|
pdi = pg.PlotDataItem()
|
|
|
|
|
|
|
|
#test empty data
|
|
|
|
pdi.setData([])
|
|
|
|
|
|
|
|
#test y data
|
|
|
|
y = list(np.random.normal(size=100))
|
|
|
|
pdi.setData(y)
|
|
|
|
assert len(pdi.xData) == 100
|
|
|
|
assert len(pdi.yData) == 100
|
|
|
|
|
|
|
|
#test x, y data
|
|
|
|
y += list(np.random.normal(size=50))
|
|
|
|
x = np.linspace(5, 10, 150)
|
|
|
|
|
|
|
|
pdi.setData(x, y)
|
|
|
|
assert len(pdi.xData) == 150
|
|
|
|
assert len(pdi.yData) == 150
|
2020-11-18 17:31:28 +00:00
|
|
|
|
|
|
|
#test clear by empty call
|
|
|
|
pdi.setData()
|
|
|
|
assert pdi.xData is None
|
|
|
|
assert pdi.yData is None
|
2018-04-05 03:13:09 +00:00
|
|
|
|
|
|
|
#test dict of x, y list
|
|
|
|
y += list(np.random.normal(size=50))
|
|
|
|
x = list(np.linspace(5, 10, 200))
|
|
|
|
pdi.setData({'x': x, 'y': y})
|
|
|
|
assert len(pdi.xData) == 200
|
|
|
|
assert len(pdi.yData) == 200
|
2018-04-05 03:13:58 +00:00
|
|
|
|
2020-11-18 17:31:28 +00:00
|
|
|
#test clear by zero length arrays call
|
|
|
|
pdi.setData([],[])
|
|
|
|
assert pdi.xData is None
|
|
|
|
assert pdi.yData is None
|
|
|
|
|
2021-03-23 18:54:15 +00:00
|
|
|
def test_opts():
|
|
|
|
# test that curve and scatter plot properties get updated from PlotDataItem methods
|
|
|
|
y = list(np.random.normal(size=100))
|
|
|
|
x = np.linspace(5, 10, 100)
|
|
|
|
pdi = pg.PlotDataItem(x, y)
|
|
|
|
pen = QtGui.QPen( QtGui.QColor('#FF0000') )
|
|
|
|
pen2 = QtGui.QPen( QtGui.QColor('#FFFF00') )
|
|
|
|
brush = QtGui.QBrush( QtGui.QColor('#00FF00'))
|
|
|
|
brush2 = QtGui.QBrush( QtGui.QColor('#00FFFF'))
|
|
|
|
float_value = 1.0 + 20*np.random.random()
|
|
|
|
pen2.setWidth( int(float_value) )
|
|
|
|
pdi.setPen(pen)
|
|
|
|
assert pdi.curve.opts['pen'] == pen
|
|
|
|
pdi.setShadowPen(pen2)
|
|
|
|
assert pdi.curve.opts['shadowPen'] == pen2
|
|
|
|
pdi.setFillLevel( float_value )
|
|
|
|
assert pdi.curve.opts['fillLevel'] == float_value
|
|
|
|
pdi.setFillBrush(brush2)
|
|
|
|
assert pdi.curve.opts['brush'] == brush2
|
|
|
|
|
|
|
|
pdi.setSymbol('t')
|
|
|
|
assert pdi.scatter.opts['symbol'] == 't'
|
|
|
|
pdi.setSymbolPen(pen)
|
|
|
|
assert pdi.scatter.opts['pen'] == pen
|
|
|
|
pdi.setSymbolBrush(brush)
|
|
|
|
assert pdi.scatter.opts['brush'] == brush
|
|
|
|
pdi.setSymbolSize( float_value )
|
|
|
|
assert pdi.scatter.opts['size'] == float_value
|
|
|
|
|
2018-04-05 03:13:58 +00:00
|
|
|
def test_clear():
|
|
|
|
y = list(np.random.normal(size=100))
|
|
|
|
x = np.linspace(5, 10, 100)
|
|
|
|
pdi = pg.PlotDataItem(x, y)
|
|
|
|
pdi.clear()
|
|
|
|
|
2020-11-18 17:31:28 +00:00
|
|
|
assert pdi.xData is None
|
|
|
|
assert pdi.yData is None
|
2016-12-15 14:26:19 +00:00
|
|
|
|
|
|
|
def test_clear_in_step_mode():
|
|
|
|
w = pg.PlotWidget()
|
Add "left" and "right" step Modes (#1360)
* Add "lstep" and "rstep" step Modes
stepMode is currently either True or False. If it is True,
it requires the user to make len(x) = len(y)+1. This is
inconvenient because it makes it difficult to change the
stepMode on a given curve (just as one would change, e.g.,
its color).
This commit extends the current situation by introducing
two more step modes: "lstep" and "rstep", which do not require
passing an extra x value. In turn, this modes associate each
y value to either the left or the right boundary of the step.
For example, the "rstep" mode is handy when plotting "life"
digital signals in which x,y data pairs are appended as they
are read.
This commit does not modify the behaviour in case of stepMode=True
* Replace step mode names: lstep,rstep -> left,right
* Improve docs for stepMode
Reword docstring and add it to PlotDataItem class too
* Document left and right stepModes as added in v 0.12.0
TODO: confirm the exact version number to use here
* Add comments stress the need for "is True"
Some conditional statements in the code regarding stepMode are
done with "is True". This is actually required since other
possible values such as "left" also evaluate as true but should
not be caught.
* Deprecate boolean API for stepMode
Introduce stepMode="mid" as a replacement of stepMode=True,
but keeping full backwards compatibility with the old API.
Adapt docs, examples and tests accordingly.
* Raise ValueError on unsupported stepMode values
* Rename "mid" step mode to "center"
* Remove "added in 0.12.0" note
See https://github.com/pyqtgraph/pyqtgraph/pull/1360#discussion_r502746919
* Add deprecation warning when stepMode=True
Issue a DeprecationWarning if stepMode=True is being passed to the
constructor or setData() of PlotDataItem or PlotCurveItem.
Note: warnings module is imported locally so that it is esier to
remove once this check is no longer needed.
* Fix wrong syntax in last commit
Fix usage of "default" kwarg in dict.get()
2020-10-13 15:52:07 +00:00
|
|
|
c = pg.PlotDataItem([1,4,2,3], [5,7,6], stepMode="center")
|
2016-12-15 14:26:19 +00:00
|
|
|
w.addItem(c)
|
|
|
|
c.clear()
|
2019-06-24 13:49:32 +00:00
|
|
|
|
|
|
|
def test_clipping():
|
|
|
|
y = np.random.normal(size=150)
|
|
|
|
x = np.exp2(np.linspace(5, 10, 150)) # non-uniform spacing
|
|
|
|
|
|
|
|
w = pg.PlotWidget(autoRange=True, downsample=5)
|
|
|
|
c = pg.PlotDataItem(x, y)
|
|
|
|
w.addItem(c)
|
|
|
|
|
|
|
|
c.setClipToView(True)
|
2021-04-29 05:07:24 +00:00
|
|
|
for x_min in range(-200, 2**10 - 100, 100):
|
|
|
|
x_max = x_min + 100
|
|
|
|
w.setXRange(x_min, x_max, padding=0)
|
2019-06-24 13:49:32 +00:00
|
|
|
xDisp, _ = c.getData()
|
2021-04-29 05:07:24 +00:00
|
|
|
# vr = c.viewRect()
|
|
|
|
if len(xDisp) > 3: # check that all points except the first and last are on screen
|
|
|
|
assert( xDisp[ 1] >= x_min and xDisp[ 1] <= x_max )
|
|
|
|
assert( xDisp[-2] >= x_min and xDisp[-2] <= x_max )
|
|
|
|
|
|
|
|
c.setDownsampling(ds=1) # disable downsampling
|
|
|
|
for x_min in range(-200, 2**10 - 100, 100):
|
|
|
|
x_max = x_min + 100
|
|
|
|
w.setXRange(x_min, x_max, padding=0)
|
|
|
|
xDisp, _ = c.getData()
|
|
|
|
# vr = c.viewRect() # this tends to be out of data, so we check against the range that we set
|
|
|
|
if len(xDisp) > 3: # check that all points except the first and last are on screen
|
|
|
|
assert( xDisp[ 0] == x[ 0] or xDisp[ 0] < x_min ) # first point should be unchanged, or off-screen
|
|
|
|
assert( xDisp[ 1] >= x_min and xDisp[ 1] <= x_max )
|
|
|
|
assert( xDisp[-2] >= x_min and xDisp[-2] <= x_max )
|
|
|
|
assert( xDisp[-1] == x[-1] or xDisp[-1] > x_max ) # last point should be unchanged, or off-screen
|
|
|
|
|
|
|
|
c.setData(x=np.zeros_like(y), y=y) # test zero width data set:
|
|
|
|
# test center and expected number of remaining data points
|
|
|
|
for center, num in ((-100.,1), (100.,1), (0.,len(y)) ):
|
|
|
|
# when all elements are off-screen, only one will be kept
|
|
|
|
# when all elelemts are on-screen, all should be kept
|
|
|
|
# and the code should not crash for zero separation
|
|
|
|
w.setXRange( center-50, center+50, padding=0 )
|
|
|
|
xDisp, yDisp = c.getData()
|
|
|
|
assert len(xDisp) == num
|
|
|
|
assert len(yDisp) == num
|
2019-09-27 20:37:40 +00:00
|
|
|
|
|
|
|
w.close()
|