How to add a colorbar to GLViewWidget()

1,486 views
Skip to first unread message

Igor Shovkun

unread,
Nov 25, 2014, 3:17:16 PM11/25/14
to pyqt...@googlegroups.com
Hi everybody!
I am working on visualization of 3D data.  I have a GLViewWidget widget, and I added a GLMeshItem to plot the data computed on a mesh.
I have managed to plot and color it using pg.ColorMap. All I need now is to add a legend or gradient item, which would represent the correspondence between the color and values I have on the faces.
Any Ideas how I can do it?

Thanks,
Igor.

Luke Campagnola

unread,
Dec 1, 2014, 2:54:59 PM12/1/14
to pyqt...@googlegroups.com
On Tue, Nov 25, 2014 at 3:17 PM, Igor Shovkun <igs...@gmail.com> wrote:
I have managed to plot and color it using pg.ColorMap. All I need now is to add a legend or gradient item, which would represent the correspondence between the color and values I have on the faces.
Any Ideas how I can do it?

It's not pretty, but there is a way to overlay 2D and 3D views:
https://groups.google.com/d/msg/pyqtgraph/PfJvmjIF3Dg/QVG9xUGk-zgJ

Does that work for you?

Igor Shovkun

unread,
Dec 1, 2014, 5:19:09 PM12/1/14
to pyqt...@googlegroups.com
I have already handled this problem myself. In case somebody wonders, I show the code:

import numpy as np
import pyqtgraph.opengl as gl
from pyqtgraph.Qt import QtCore, QtGui
import pyqtgraph as pg
pg.setConfigOption("useWeave", False) # this line eliminates some strange output lines
from pyqtgraph.pgcollections import OrderedDict

Gradients = OrderedDict([
('bw', {'ticks': [(0.0, (0, 0, 0, 255)), (1, (255, 255, 255, 255))], 'mode': 'rgb'}),
    ('hot', {'ticks': [(0.3333, (185, 0, 0, 255)), (0.6666, (255, 220, 0, 255)), (1, (255, 255, 255, 255)), (0, (0, 0, 0, 255))], 'mode': 'rgb'}),
    ('jet', {'ticks': [(1, (166, 0, 0, 255)), (0.32247191011235954, (0, 255, 255, 255)), (0.11348314606741573, (0, 68, 255, 255)), (0.6797752808988764, (255, 255, 0, 255)), (0.902247191011236, (255, 0, 0, 255)), (0.0, (0, 0, 166, 255)), (0.5022471910112359, (0, 255, 0, 255))], 'mode': 'rgb'}),
    ('summer', {'ticks': [(1, (255, 255, 0, 255)), (0.0, (0, 170, 127, 255))], 'mode': 'rgb'} ),
    ('space', {'ticks': [(0.562, (75, 215, 227, 255)), (0.087, (255, 170, 0, 254)), (0.332, (0, 255, 0, 255)), (0.77, (85, 0, 255, 255)), (0.0, (255, 0, 0, 255)), (1.0, (255, 0, 127, 255))], 'mode': 'rgb'}),
    ('winter', {'ticks': [(1, (0, 255, 127, 255)), (0.0, (0, 0, 255, 255))], 'mode': 'rgb'})
])


class Plotter:
def __init__(self):
pg.mkQApp()
# self.WindowNumber = 0
self.plot = None
self.plots = []
self.windows = []
def surfMesh(self, vertexes, faces, faceValues, cmap = 'space', drawEdges=False, smooth=False):
'''
plots data for the triangular mesh
Arguments:
float numpyarray vertexes: x-y coordinates of the vertices constituting the mesh
note: doesn't work with 3D. need some changes

int numpyarray faces: each element represents numbers of verticis constituting a face

float numpyarray data

str cmap:
'space' - default cmap developed by me. kinda cool :-)
'thermal'
'''
nbplt = len(self.plots)
# impose color scheme
if cmap in Gradients:
GradiendMode = Gradients[cmap]
else: raise TypeError('Color Map is not defined.')

# compute normalized value for color calculation
nbv = len(vertexes) # number of vertexes
xmin = faceValues.min()
xmax = faceValues.max()
if xmax != xmin:
x = (faceValues - xmin)/(xmax - xmin)
else: x = np.ones(len(faceValues)) * xmin

# Main window containing other widgets
win = QtGui.QWidget()
win.setWindowTitle('isqt plot')
self.windows.append(win)
# leyout windget controlling layour of other widgets
layout = QtGui.QGridLayout()
win.setLayout(layout)
# Widget - righthand side of the window allocated for the colorbar
cb = pg.GraphicsLayoutWidget()
# values axis
ax = pg.AxisItem('left')
if xmax != xmin:  # here we handle arrays with all values the same
# ax.setRange(np.round(xmin,2), np.round(xmax,2)) # to round numbers on ticks - doesn't work
ax.setRange(xmin, xmax)
else:
ax.setRange(xmin, xmax + 0.0001)
cb.addItem(ax)
# Gradient Editor widget
gw = pg.GradientEditorItem(orientation='right')
# load predefined color gradient
gw.restoreState(GradiendMode)
# left side of the window for 3D data representation
view = gl.GLViewWidget()

# it's basically 
view.setSizePolicy(cb.sizePolicy())
# add 3D widget to the left (first column)
layout.addWidget(view, 0, 0)
# add colorbar to the right (second column)
layout.addWidget(cb, 0, 1)
# Do not allow 2nd column (colorbar) to stretch
layout.setColumnStretch(1, 0)
# minimal size of the colorbar
layout.setColumnMinimumWidth(1, 120)
# Allow 1st column (3D widget) to stretch
layout.setColumnStretch(0, 1)
# horizontal size set to be large to prompt colormap to a minimum size
view.sizeHint = lambda: pg.QtCore.QSize(1700, 800)
cb.sizeHint = lambda: pg.QtCore.QSize(100, 800)
# this is to remove empty space between
layout.setHorizontalSpacing (0)
# set initial size of the window
win.resize(800,800)
win.show()

cb.addItem(gw)
cm = gw.colorMap()
# colors = cm.map(x)
colors = cm.mapToFloat(x)

# create 3D array to pass it to plotting function
vetrs3D = np.zeros([nbv,3])
if vertexes.shape == (nbv,3): vetrs3D = vertexes
else: 
print 'Converting 2D to 3D'
vetrs3D[:,:2] = vertexes
# compute distance to set initial camera pozition
dst = max(vertexes[:,0].max() - vertexes[:,0].min(), vertexes[:,1].max() - vertexes[:,1].min())
view.setCameraPosition(distance=dst)

plt = gl.GLMeshItem(vertexes=vetrs3D, faces=faces, faceColors=colors, drawEdges=drawEdges, smooth=smooth)
view.addItem(plt)
self.plots.append(plt)

And an example of using this stuff is:

verts = np.array([
    [0, 0, 0],
    [2, 0, 0],
    [1, 2, 0],
    [1, 1, 1],
])
faces = np.array([
    [0, 1, 2],
    [0, 1, 3],
    [0, 2, 3],
    [1, 2, 3]
])
values = np.array([0.0,2.0,3,20.0])
plt = Plotter()
plt.surfMesh(vertexes=verts, faces=faces, faceValues=values)
plt.show()


There might be some excessive variables in this script, that is due to the fact, this is only a part of the class I implemented for my plotting needs.

--
You received this message because you are subscribed to a topic in the Google Groups "pyqtgraph" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/pyqtgraph/R-F_Co5XBJs/unsubscribe.
To unsubscribe from this group and all its topics, send an email to pyqtgraph+...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/pyqtgraph/CACZXET-sgjaHggE8On7a1baHR1sqtRS_xHv3FHfRUmKQr4gA0A%40mail.gmail.com.
For more options, visit https://groups.google.com/d/optout.



--

Best regards,

Igor.

 


Reply all
Reply to author
Forward
0 new messages