updating surface plot as fast as possible

554 views
Skip to first unread message

Mostafa

unread,
Apr 22, 2019, 11:57:59 PM4/22/19
to pyqtgraph
Hello, 

My eventual goal is to have a surface like the one that Matlab has for plotting a 2D array of size N by M. For my application, M and N are not greater than 256, so the greatest matrix I have has less than 100K entries. However, I could not find a remedy for the slow updating of the GLSurfacePlotItem. Basically, as the human eye perception is limited, the frame update speed should be around 25-30 frame per second. Besides, the surface plot is much far away from the nice representation in Matlab where the plot has x and y axes with an option to add a colorbar to show the color code values. There should be tricks to speed up the process similar to the suggestion for 2D plot to disable autoscale in order to update the graph much faster. 

Any idea? 

Best regards, 
Mostafa 
 

Patrick

unread,
Apr 23, 2019, 11:44:41 PM4/23/19
to pyqtgraph
Hi,

I don't use the 3D capabilities of pyqtgraph, but the example under 3D Graphics/Surface Plot (https://github.com/pyqtgraph/pyqtgraph/blob/develop/examples/GLSurfacePlot.py) has an animated 3D surface that looks to be rendering at 100+ FPS on my machine. Does that help? Otherwise if you can post a minimum working example then we might be able to suggest some ideas.

Patrick

Mostafa

unread,
Apr 26, 2019, 11:25:42 AM4/26/19
to pyqtgraph
Hi Partick, 

It works well when we set the following parameters for the GLSurfacePlotItem

computeNormals=False, smooth=False

However, I have a problem with the colorMap since the default mapping seems to be for data which is in [-1,1]. I have to change the mapping for an arbitrary data range since in general, I do not know the range but I can retrieve it when the code runs. I looked to the documentation for the colorMap but I barely understood how to define it and set in GLSurfacePlotItem. Besides, I want to add x,y axes which are fixed and they are necessary for getting meaning to the surface plot. Any recommendations will be appreciated. 

Best, 
Mostafa 

Patrick

unread,
Apr 27, 2019, 2:47:44 AM4/27/19
to pyqtgraph
Hi,

Yeah, the GL stuff doesn't use the same colour maps as the 2D images. I can't see any documentation on the shaders (http://www.pyqtgraph.org/documentation/3dgraphics/glmeshitem.html) that are used to colour the surface. Looking at the code under shaders.py does help though. For the "heightColor" shader, the 9 numbers in the array that are used (as in the Surface Plot example) are variables used in a formula to compute the RGB colour.

From comment in code:
## colors fragments by z-value.
## This is useful for coloring surface plots by height.
## This shader uses a uniform called "colorMap" to determine how to map the colors:
##    red   = pow(z * colorMap[0] + colorMap[1], colorMap[2])
##    green = pow(z * colorMap[3] + colorMap[4], colorMap[5])
##    blue  = pow(z * colorMap[6] + colorMap[7], colorMap[8])
## (set the values like this: shader['uniformMap'] = array([...])

I assume the output RGB values are expressed as a range from 0 to 1. So to tweak the example to work with ranges from say zmin to zmax, I think something like:

p4.shader()['colorMap'] = np.array([0.2*(zmax - zmin), 2 - zmin, 0.5, 0.2*(zmax - zmin), 1 - zmin, 1, 0.2*(zmax - zmin), 0 - zmin, 2])


Patrick

Mostafa

unread,
May 1, 2019, 1:05:04 PM5/1/19
to pyqtgraph
Hi Patrick,

I used the following code for updating the shader colors: 

self.p1.shader()['colorMap'] = np.array([.01/zmax,  # red 1
0, # red 2
0.01, # red 3
0.01/zmax, # green 1
0, # green 2
.05, # green 3
1/zmax, # blue 1
-zmin, # blue 2
1]) # blue 3

 
Thank you for your help. The library is great and it is very fast. However, I still do not know how to add x and y axes? In VisPy, there is an example for plotting the axes, but I could not find a similar one in PyQtGraph. Do you have an example of this? 

Best regards, 
Mostafa 

Patrick

unread,
May 1, 2019, 8:44:52 PM5/1/19
to pyqtgraph
Hi,

I don't think there is a pre-built axis item for 3D. You might be able to build one yourself by extending the GLGridItem and draw labels at the ends of the grid lines. You can at least make a "box" using three grids with something like (modifying GLSurfacePlot.py example):


## Add a grid to the view
gxz
= gl.GLGridItem()
gxz
.scale(2,2,1)
gxz
.translate(0, 0, -20)
gxz
.setDepthValue(10) # draw grid after surfaces since they may be translucent
w
.addItem(gxz)

gxy
= gl.GLGridItem()
gxy
.scale(2,2,1)
gxy
.translate(0, 0, -20)
gxy
.rotate(90, 10, 0, 0)
gxy
.setDepthValue(10)
w
.addItem(gxy)

gyz
= gl.GLGridItem()
gyz
.scale(2,2,1)
gyz
.translate(0, 0, -20)
gyz
.rotate(90, 0, 10, 0)
gyz
.setDepthValue(10)
w
.addItem(gyz)


There was some discussion here about drawing labels on the 3D plots: https://groups.google.com/forum/#!topic/pyqtgraph/FNxcMh3M6nc


Patrick
Reply all
Reply to author
Forward
0 new messages