Search code examples
pythonlayoutdata-visualizationsubplotpyqtgraph

pyqtgraph subplot layout with 3D plot


I would like to draw a pyqtgraph subplot with the following layout:

+-----+-----+-----+-----+-----+
|     |     |     |     |     |
+-----+-----+-----+-----+-----+
|                             |
+-----------------------------+
|                             |
+-----------------------------+

3 rows, there are 5 columns only in the first row.
Following the suggestion from this answer, I wrote this piece of code:

from pyqtgraph.Qt import QtGui
import numpy as np
import pyqtgraph as pg
import pyqtgraph.opengl as gl
import matplotlib.pyplot as plt


cmap = plt.get_cmap('jet')

app = QtGui.QApplication([])
win = pg.GraphicsWindow()
layoutgb = QtGui.QGridLayout()
win.setLayout(layoutgb)

N = 11
M = 11

x = np.linspace(0, 10, N)
y = np.linspace(0, 10, M)

for i in range(5):

    glvw = gl.GLViewWidget()

    z = np.random.random((N, M))

    minZ = np.min(z)
    maxZ = np.max(z)
    colors = cmap((z - minZ)/(maxZ - minZ))
    
    surf = gl.GLSurfacePlotItem(x = x, 
                                y = y, 
                                z = z, 
                                colors = colors, 
                                drawEdges = True)

    glvw.addItem(surf)

    layoutgb.addWidget(glvw, 0, i)

p1 = pg.PlotWidget()
p1.plot([1, 2, 3, 4, 5], [1, 0, 2, 3, 1], pen ='r', name ='red')
layoutgb.addWidget(p1, 1, 0)

p2 = pg.PlotWidget()
p2.plot([1, 2, 3, 4, 5], [2, 1, 4, 1, 1], pen ='g', name ='green')
layoutgb.addWidget(p2, 2, 0)

glvw.sizeHint = lambda: pg.QtCore.QSize(100, 100)
p1.sizeHint = lambda: pg.QtCore.QSize(100, 100)
p2.sizeHint = lambda: pg.QtCore.QSize(100, 100)
glvw.setSizePolicy(p1.sizePolicy())

QtGui.QApplication.instance().exec_()

enter image description here

As you can see, the above code generates a subplot with two major issues:

  1. even if the code does generate 5 3D GLSurfacePlotItem, it draw 2 only
  2. PlotWidget p1 and p2 aren't stretched with the full window's width

I have no idea how to solve the first issue. Regarding the second one, I tryied to address it by following suggestions from this answer but I didn't get any results.

Any help would be helpful.


Solution

    1. even if the code does generate 5 3D GLSurfacePlotItem, it draw 2 only

    I solve this issue by changing QSize of gl.GLViewWidget:

    glvw.sizeHint = lambda: pg.QtCore.QSize(100, 500)
    
    1. PlotWidget p1 and p2 aren't stretched with the full window's width

    I solve this issue by specifying rowSpan and columnSpan parameters within addWidget method:

    layoutgb.addWidget(p1, 1, 0, 1, -1)
    ...
    layoutgb.addWidget(p2, 2, 0, 1, -1)
    

    Complete Code

    from pyqtgraph.Qt import QtGui#, QtCore
    import numpy as np
    import pyqtgraph as pg
    import pyqtgraph.opengl as gl
    import matplotlib.pyplot as plt
    
    
    cmap = plt.get_cmap('jet')
    
    app = QtGui.QApplication([])
    win = pg.GraphicsWindow()
    layoutgb = QtGui.QGridLayout()
    win.setLayout(layoutgb)
    
    N = 11
    M = 11
    
    x = np.linspace(0, 10, N)
    y = np.linspace(0, 10, M)
    
    for i in range(5):
    
        glvw = gl.GLViewWidget()
    
        z = np.random.random((N, M))
    
        minZ = np.min(z)
        maxZ = np.max(z)
        colors = cmap((z - minZ)/(maxZ - minZ))
        
        surf = gl.GLSurfacePlotItem(x = x, 
                                    y = y, 
                                    z = z, 
                                    colors = colors, 
                                    drawEdges = True)
    
        glvw.addItem(surf)
    
        layoutgb.addWidget(glvw, 0, i)
    
    p1 = pg.PlotWidget()
    p1.plot([1, 2, 3, 4, 5], [1, 0, 2, 3, 1], pen ='r', name ='red')
    layoutgb.addWidget(p1, 1, 0, 1, -1)
    
    p2 = pg.PlotWidget()
    p2.plot([1, 2, 3, 4, 5], [2, 1, 4, 1, 1], pen ='g', name ='green')
    layoutgb.addWidget(p2, 2, 0, 1, -1)
    
    glvw.sizeHint = lambda: pg.QtCore.QSize(100, 500)
    
    QtGui.QApplication.instance().exec_()
    

    enter image description here