Various improvements
Make an example displaying more clearly the Item capability. Correct few bugs in the Item class. Improve overall comments.
This commit is contained in:
parent
3cbe65d46d
commit
d32d61a1e2
@ -21,40 +21,45 @@ view = win.addViewBox()
|
|||||||
|
|
||||||
|
|
||||||
## Create data
|
## Create data
|
||||||
x = np.array([[1,1,1,1],
|
|
||||||
[2,2,2,2],
|
# x and y being the coordinates of the polygons, they share the same shape
|
||||||
[3,3,3,3],
|
# However the shape can be different in both dimension
|
||||||
[4,4,4,4],
|
xn = 50 # nb points along x
|
||||||
[5,5,5,5]])
|
yn = 40 # nb points along y
|
||||||
y = np.array([[4,8,12,16],
|
x = np.repeat(np.arange(1, xn+1), yn).reshape(xn, yn)
|
||||||
[2,4,6,8],
|
y = np.tile(np.arange(1, yn+1), xn).reshape(xn, yn)
|
||||||
[3,6,9,12],
|
|
||||||
[5,10,15,20],
|
# z being the color of the polygons its shape must be decreased by one in each dimension
|
||||||
[6,12,18,24]])
|
z = np.exp(-(x*xn)**2/1000)[:-1,:-1]
|
||||||
z = np.array([[1,2,3],
|
|
||||||
[5,6,7],
|
|
||||||
[9,10,11],
|
|
||||||
[13,14,15]])
|
|
||||||
|
|
||||||
## Create image item
|
## Create image item
|
||||||
pcmi = pg.PColorMeshItem(x, y, z)
|
pcmi = pg.PColorMeshItem()
|
||||||
view.addItem(pcmi)
|
view.addItem(pcmi)
|
||||||
|
|
||||||
|
|
||||||
|
## Set the animation
|
||||||
|
fps = 25 # Frame per second of the animation
|
||||||
|
|
||||||
fps = 1
|
# Wave parameters
|
||||||
i = 0
|
wave_amplitude = 3
|
||||||
|
wave_speed = 0.3
|
||||||
|
wave_length = 10
|
||||||
|
color_speed = 0.3
|
||||||
|
|
||||||
|
i=0
|
||||||
def updateData():
|
def updateData():
|
||||||
global pcmi, x, y, z, i
|
global i
|
||||||
|
|
||||||
## Display the data
|
## Display the new data set
|
||||||
pcmi.setData(x-i, y, z)
|
new_x = x
|
||||||
|
new_y = y+wave_amplitude*np.cos(x/wave_length+i)
|
||||||
QtCore.QTimer.singleShot(fps*1000, updateData)
|
new_z = np.exp(-(x-np.cos(i*color_speed)*xn)**2/1000)[:-1,:-1]
|
||||||
i += 1
|
pcmi.setData(new_x,
|
||||||
print(i)
|
new_y,
|
||||||
|
new_z)
|
||||||
|
|
||||||
|
i += wave_speed
|
||||||
|
QtCore.QTimer.singleShot(1000/fps, updateData)
|
||||||
|
|
||||||
updateData()
|
updateData()
|
||||||
|
|
||||||
|
@ -23,66 +23,97 @@ class PColorMeshItem(GraphicsObject):
|
|||||||
"""
|
"""
|
||||||
**Bases:** :class:`GraphicsObject <pyqtgraph.GraphicsObject>`
|
**Bases:** :class:`GraphicsObject <pyqtgraph.GraphicsObject>`
|
||||||
|
|
||||||
TODO
|
Create a pseudocolor plot with convex polygons.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
sigImageChanged = QtCore.Signal()
|
sigImageChanged = QtCore.Signal()
|
||||||
sigRemoveRequested = QtCore.Signal(object) # self; emitted when 'remove' is selected from context menu
|
sigRemoveRequested = QtCore.Signal(object) # self; emitted when 'remove' is selected from context menu
|
||||||
|
|
||||||
|
|
||||||
def __init__(self, x=None, y=None, z=None, cmap='viridis'):
|
def __init__(self, x=None, y=None, z=None,
|
||||||
|
cmap='viridis'):
|
||||||
"""
|
"""
|
||||||
See :func:`setImage <pyqtgraph.ImageItem.setImage>` for all allowed initialization arguments.
|
|
||||||
|
|
||||||
|
Parameters
|
||||||
|
----------
|
||||||
|
x, y : np.ndarray
|
||||||
|
2D array containing the coordinates of the polygons
|
||||||
|
z : np.ndarray
|
||||||
|
2D array containing the value which will be maped into the polygons
|
||||||
|
colors.
|
||||||
|
cmap : str, default 'viridis
|
||||||
|
Colormap used to map the z value to colors.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
GraphicsObject.__init__(self)
|
GraphicsObject.__init__(self)
|
||||||
|
|
||||||
self.x = x
|
self.x = x
|
||||||
self.y = y
|
self.y = y
|
||||||
self.z = z
|
self.z = z
|
||||||
|
|
||||||
self.qpicture = None ## rendered image for display
|
self.qpicture = None ## rendered image for display
|
||||||
|
|
||||||
self.axisOrder = getConfigOption('imageAxisOrder')
|
self.axisOrder = getConfigOption('imageAxisOrder')
|
||||||
|
|
||||||
if cmap in list(Gradients.keys()):
|
if cmap in Gradients.keys():
|
||||||
self.cmap = cmap
|
self.cmap = cmap
|
||||||
else:
|
else:
|
||||||
raise NameError('Undefined colormap')
|
raise NameError('Undefined colormap')
|
||||||
|
|
||||||
|
# If some data have been sent we directly display it
|
||||||
if x is not None and y is not None and z is not None:
|
if x is not None and y is not None and z is not None:
|
||||||
self.setData(x, y, z)
|
self.setData(x, y, z)
|
||||||
|
|
||||||
|
|
||||||
def setData(self, x, y, z):
|
def setData(self, x, y, z):
|
||||||
## pre-computing a QPicture object allows paint() to run much more quickly,
|
|
||||||
## rather than re-drawing the shapes every time.
|
|
||||||
|
# We test of the view has changed
|
||||||
|
if np.any(self.x != x) or np.any(self.y != y) or np.any(self.z != z):
|
||||||
|
self.informViewBoundsChanged()
|
||||||
|
|
||||||
|
# Replace data
|
||||||
|
self.x = x
|
||||||
|
self.y = y
|
||||||
|
self.z = z
|
||||||
|
|
||||||
profile = debug.Profiler()
|
profile = debug.Profiler()
|
||||||
|
|
||||||
self.qpicture = QtGui.QPicture()
|
self.qpicture = QtGui.QPicture()
|
||||||
p = QtGui.QPainter(self.qpicture)
|
p = QtGui.QPainter(self.qpicture)
|
||||||
p.setPen(fn.mkPen('w'))
|
|
||||||
|
|
||||||
|
# We set the pen of all polygons once
|
||||||
|
p.setPen(QtGui.QColor(0, 0, 0, 0))
|
||||||
|
|
||||||
# Prepare colormap
|
## Prepare colormap
|
||||||
pos = [i[0] for i in Gradients[self.cmap]['ticks']]
|
# First we get the LookupTable
|
||||||
|
pos = [i[0] for i in Gradients[self.cmap]['ticks']]
|
||||||
color = [i[1] for i in Gradients[self.cmap]['ticks']]
|
color = [i[1] for i in Gradients[self.cmap]['ticks']]
|
||||||
cmap = ColorMap(pos, color)
|
cmap = ColorMap(pos, color)
|
||||||
lut = cmap.getLookupTable(0.0, 1.0, 256)
|
lut = cmap.getLookupTable(0.0, 1.0, 256)
|
||||||
norm = ((z - z.min())/z.max()*len(lut)).astype(int)
|
# Second we associate each z value, that we normalize, to the lut
|
||||||
|
norm = z - z.min()
|
||||||
|
norm = norm/norm.max()
|
||||||
|
norm = (norm*(len(lut)-1)).astype(int)
|
||||||
|
|
||||||
xfn = z.shape[0]
|
# Go through all the data and draw the polygons accordingly
|
||||||
yfn = z.shape[1]
|
for xi in range(z.shape[0]):
|
||||||
for xi in range(xfn):
|
for yi in range(z.shape[1]):
|
||||||
for yi in range(yfn):
|
|
||||||
|
|
||||||
|
# Set the color of the polygon first
|
||||||
|
# print(xi, yi, norm[xi][yi])
|
||||||
|
c = lut[norm[xi][yi]]
|
||||||
|
p.setBrush(QtGui.QColor(c[0], c[1], c[2]))
|
||||||
|
|
||||||
|
# DrawConvexPlygon is faster
|
||||||
p.drawConvexPolygon(QtCore.QPointF(x[xi][yi], y[xi][yi]),
|
p.drawConvexPolygon(QtCore.QPointF(x[xi][yi], y[xi][yi]),
|
||||||
QtCore.QPointF(x[xi+1][yi], y[xi+1][yi]),
|
QtCore.QPointF(x[xi+1][yi], y[xi+1][yi]),
|
||||||
QtCore.QPointF(x[xi+1][yi+1], y[xi+1][yi+1]),
|
QtCore.QPointF(x[xi+1][yi+1], y[xi+1][yi+1]),
|
||||||
QtCore.QPointF(x[xi][yi+1], y[xi][yi+1]))
|
QtCore.QPointF(x[xi][yi+1], y[xi][yi+1]))
|
||||||
|
|
||||||
c = lut[norm[xi][yi]]
|
|
||||||
p.setBrush(QtGui.QColor(c[0], c[1], c[2]))
|
|
||||||
p.end()
|
|
||||||
|
|
||||||
|
p.end()
|
||||||
self.update()
|
self.update()
|
||||||
|
|
||||||
|
|
||||||
@ -106,14 +137,14 @@ class PColorMeshItem(GraphicsObject):
|
|||||||
def width(self):
|
def width(self):
|
||||||
if self.x is None:
|
if self.x is None:
|
||||||
return None
|
return None
|
||||||
return len(self.x)
|
return np.max(self.x)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def height(self):
|
def height(self):
|
||||||
if self.y is None:
|
if self.y is None:
|
||||||
return None
|
return None
|
||||||
return len(self.y)
|
return np.max(self.y)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user