Traditional log10 mode for PlotDataItem (by adding "mapped data" stage) (#1992)

* make PlotDataItem aware of mapped data

* inf suppression, metadata storage and refactor of data structures

* cleanup, test, and documentation pass

* re-added prepareForPaint, added PlotDataset to sphinx index

* strip more print statements

* indicate (internal) PlotDataset documentation as orphaned to avoid sphinx error

* Do not export PlotDataset

* replacement example

* example comments
This commit is contained in:
Nils Nemitz 2021-10-07 14:40:38 +09:00 committed by GitHub
parent bc542ae1c4
commit 0cc3580687
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 504 additions and 427 deletions

View File

@ -1,38 +1,44 @@
# -*- coding: utf-8 -*-
"""
Test programmatically setting log transformation modes.
Demonstrate programmatic setting of log transformation modes.
"""
import initExample ## Add path to library (just for examples; you do not need this)
import numpy as np
from pyqtgraph.Qt import QtGui, QtCore
import pyqtgraph as pg
app = pg.mkQApp("Log Axis Example")
w = pg.GraphicsLayoutWidget(show=True)
w.setWindowTitle('pyqtgraph example: logAxis')
p1 = w.addPlot(0,0, title="X Semilog")
w.resize(800,800)
w.setWindowTitle('pyqtgraph example: Log Axis, or How to Recognise Different Types of Curves from Quite a Long Way Away')
p0 = w.addPlot(0,0, title="Linear")
p1 = w.addPlot(0,1, title="X Semilog")
p2 = w.addPlot(1,0, title="Y Semilog")
p3 = w.addPlot(2,0, title="XY Log")
p1.showGrid(True, True)
p2.showGrid(True, True)
p3.showGrid(True, True)
p3 = w.addPlot(1,1, title="XY Log")
# configure logarithmic axis scaling:
p1.setLogMode(True, False)
p2.setLogMode(False, True)
p3.setLogMode(True, True)
# 1000 points from 0.1 to 10, chosen to give a compatible range of values across curves:
x = np.logspace(-1, 1, 1000)
plotdata = ( # legend entry, color, and plotted equation:
('1 / 3x' , '#ff9d47', 1./(3*x) ),
('sqrt x' , '#b3cf00', 1/np.sqrt(x) ),
('exp. decay', '#00a0b5', 5 * np.exp(-x/1) ),
('-log x' , '#a54dff', - np.log10(x) )
)
p0.addLegend(offset=(-20,20)) # include legend only in top left plot
for p in (p0, p1, p2, p3): # draw identical numerical data in all four plots
p.showGrid(True, True) # turn on grid for all four plots
p.showAxes(True, size=(40,None)) # show a full frame, and reserve identical room for y labels
for name, color, y in plotdata: # draw all four curves as defined in plotdata
pen = pg.mkPen(color, width=2)
p.plot( x,y, pen=pen, name=name )
w.show()
y = np.random.normal(size=1000)
x = np.linspace(0, 1, 1000)
p1.plot(x, y)
p2.plot(x, y)
p3.plot(x, y)
#p.getAxis('bottom').setLogMode(True)
if __name__ == '__main__':
pg.exec()

View File

@ -1123,7 +1123,10 @@ def transformCoordinates(tr, coords, transpose=False):
m = m[:, :-1]
## map coordinates and return
mapped = (m*coords).sum(axis=1) ## apply scale/rotate
# nan or inf points will not plot, but should not generate warnings
with warnings.catch_warnings():
warnings.simplefilter("ignore", RuntimeWarning)
mapped = (m*coords).sum(axis=1) ## apply scale/rotate
mapped += translate
if transpose:
@ -2042,7 +2045,7 @@ def arrayToQPath(x, y, connect='all', finiteCheck=True):
only values with 1 will connect to the previous point. Def
finiteCheck : bool, default Ture
When false, the check for finite values will be skipped, which can
improve performance. If finite values are present in `x` or `y`,
improve performance. If nonfinite values are present in `x` or `y`,
an empty QPainterPath will be generated.
Returns

File diff suppressed because it is too large Load Diff

View File

@ -1468,6 +1468,10 @@ class ViewBox(GraphicsWidget):
bounds = QtCore.QRectF(range[0][0], range[1][0], range[0][1]-range[0][0], range[1][1]-range[1][0])
return bounds
def update(self, *args, **kwargs):
self.prepareForPaint()
GraphicsWidget.update(self, *args, **kwargs)
def updateViewRange(self, forceX=False, forceY=False):
## Update viewRange to match targetRange as closely as possible, given

View File

@ -1,5 +1,6 @@
# -*- coding: utf-8 -*-
import numpy as np
import warnings
import pyqtgraph as pg
from pyqtgraph.Qt import QtGui
@ -71,6 +72,31 @@ def test_setData():
pdi.setData([],[])
assert pdi.xData is None
assert pdi.yData is None
def test_nonfinite():
def _assert_equal_arrays(a1, a2):
assert a1.shape == a2.shape
for ( xtest, xgood ) in zip( a1, a2 ):
assert( (xtest == xgood) or (np.isnan(xtest) and np.isnan(xgood) ) )
x = np.array([-np.inf, 0.0, 1.0, 2.0 , np.nan, 4.0 , np.inf])
y = np.array([ 1.0, 0.0,-1.0, np.inf, 2.0 , np.nan, 0.0 ])
pdi = pg.PlotDataItem(x, y)
dataset = pdi.getDisplayDataset()
_assert_equal_arrays( dataset.x, x )
_assert_equal_arrays( dataset.y, y )
with warnings.catch_warnings():
warnings.simplefilter("ignore")
x_log = np.log10(x)
y_log = np.log10(y)
x_log[ ~np.isfinite(x_log) ] = np.nan
y_log[ ~np.isfinite(y_log) ] = np.nan
pdi.setLogMode(True, True)
dataset = pdi.getDisplayDataset()
_assert_equal_arrays( dataset.x, x_log )
_assert_equal_arrays( dataset.y, y_log )
def test_opts():
# test that curve and scatter plot properties get updated from PlotDataItem methods