From f997b3079b7b723ff3ee7f65b100620ee1cb4eb5 Mon Sep 17 00:00:00 2001 From: Luke Campagnola Date: Fri, 6 Sep 2013 15:36:36 -0400 Subject: [PATCH] Added GLBarGraphItem example GLMeshItem accepts ShaderProgram or name of predefined program Added missing documentation to GLGraphicsItem minor edits --- examples/GLBarGraphItem.py | 47 +++++++++++++++++++++++++++ pyqtgraph/PlotData.py | 1 + pyqtgraph/multiprocess/remoteproxy.py | 6 +++- pyqtgraph/opengl/GLGraphicsItem.py | 23 +++++++++++++ pyqtgraph/opengl/MeshData.py | 6 ++-- pyqtgraph/opengl/items/GLMeshItem.py | 6 +++- 6 files changed, 84 insertions(+), 5 deletions(-) create mode 100644 examples/GLBarGraphItem.py diff --git a/examples/GLBarGraphItem.py b/examples/GLBarGraphItem.py new file mode 100644 index 00000000..d14eba87 --- /dev/null +++ b/examples/GLBarGraphItem.py @@ -0,0 +1,47 @@ +# -*- coding: utf-8 -*- +""" +Demonstrate use of GLLinePlotItem to draw cross-sections of a surface. + +""" +## Add path to library (just for examples; you do not need this) +import initExample + +from pyqtgraph.Qt import QtCore, QtGui +import pyqtgraph.opengl as gl +import pyqtgraph as pg +import numpy as np + +app = QtGui.QApplication([]) +w = gl.GLViewWidget() +w.opts['distance'] = 40 +w.show() +w.setWindowTitle('pyqtgraph example: GLBarGraphItem') + +gx = gl.GLGridItem() +gx.rotate(90, 0, 1, 0) +gx.translate(-10, 0, 10) +w.addItem(gx) +gy = gl.GLGridItem() +gy.rotate(90, 1, 0, 0) +gy.translate(0, -10, 10) +w.addItem(gy) +gz = gl.GLGridItem() +gz.translate(0, 0, 0) +w.addItem(gz) + +# regular grid of starting positions +pos = np.mgrid[0:10, 0:10, 0:1].reshape(3,10,10).transpose(1,2,0) +# fixed widths, random heights +size = np.empty((10,10,3)) +size[...,0:2] = 0.4 +size[...,2] = np.random.normal(size=(10,10)) + +bg = gl.GLBarGraphItem(pos, size) +w.addItem(bg) + + +## Start Qt event loop unless running in interactive mode. +if __name__ == '__main__': + import sys + if (sys.flags.interactive != 1) or not hasattr(QtCore, 'PYQT_VERSION'): + QtGui.QApplication.instance().exec_() diff --git a/pyqtgraph/PlotData.py b/pyqtgraph/PlotData.py index 0bf13ca8..e5faadda 100644 --- a/pyqtgraph/PlotData.py +++ b/pyqtgraph/PlotData.py @@ -15,6 +15,7 @@ class PlotData(object): - removal of nan/inf values - option for single value shared by entire column - cached downsampling + - cached min / max / hasnan / isuniform """ def __init__(self): self.fields = {} diff --git a/pyqtgraph/multiprocess/remoteproxy.py b/pyqtgraph/multiprocess/remoteproxy.py index f33ebc83..e4c3f34f 100644 --- a/pyqtgraph/multiprocess/remoteproxy.py +++ b/pyqtgraph/multiprocess/remoteproxy.py @@ -205,7 +205,11 @@ class RemoteEventHandler(object): fnkwds[k] = np.fromstring(byteData[ind], dtype=dtype).reshape(shape) if len(fnkwds) == 0: ## need to do this because some functions do not allow keyword arguments. - result = obj(*fnargs) + try: + result = obj(*fnargs) + except: + print("Failed to call object %s: %d, %s" % (obj, len(fnargs), fnargs[1:])) + raise else: result = obj(*fnargs, **fnkwds) diff --git a/pyqtgraph/opengl/GLGraphicsItem.py b/pyqtgraph/opengl/GLGraphicsItem.py index 59bc4449..9680fba7 100644 --- a/pyqtgraph/opengl/GLGraphicsItem.py +++ b/pyqtgraph/opengl/GLGraphicsItem.py @@ -40,6 +40,7 @@ class GLGraphicsItem(QtCore.QObject): self.__glOpts = {} def setParentItem(self, item): + """Set this item's parent in the scenegraph hierarchy.""" if self.__parent is not None: self.__parent.__children.remove(self) if item is not None: @@ -98,9 +99,11 @@ class GLGraphicsItem(QtCore.QObject): def parentItem(self): + """Return a this item's parent in the scenegraph hierarchy.""" return self.__parent def childItems(self): + """Return a list of this item's children in the scenegraph hierarchy.""" return list(self.__children) def _setView(self, v): @@ -124,10 +127,15 @@ class GLGraphicsItem(QtCore.QObject): return self.__depthValue def setTransform(self, tr): + """Set the local transform for this object. + Must be a :class:`Transform3D ` instance. This transform + determines how the local coordinate system of the item is mapped to the coordinate + system of its parent.""" self.__transform = Transform3D(tr) self.update() def resetTransform(self): + """Reset this item's transform to an identity transformation.""" self.__transform.setToIdentity() self.update() @@ -148,9 +156,12 @@ class GLGraphicsItem(QtCore.QObject): self.setTransform(tr * self.transform()) def transform(self): + """Return this item's transform object.""" return self.__transform def viewTransform(self): + """Return the transform mapping this item's local coordinate system to the + view coordinate system.""" tr = self.__transform p = self while True: @@ -190,16 +201,24 @@ class GLGraphicsItem(QtCore.QObject): def hide(self): + """Hide this item. + This is equivalent to setVisible(False).""" self.setVisible(False) def show(self): + """Make this item visible if it was previously hidden. + This is equivalent to setVisible(True).""" self.setVisible(True) def setVisible(self, vis): + """Set the visibility of this item.""" self.__visible = vis self.update() def visible(self): + """Return True if the item is currently set to be visible. + Note that this does not guarantee that the item actually appears in the + view, as it may be obscured or outside of the current view area.""" return self.__visible @@ -237,6 +256,10 @@ class GLGraphicsItem(QtCore.QObject): self.setupGLState() def update(self): + """ + Indicates that this item needs to be redrawn, and schedules an update + with the view it is displayed in. + """ v = self.view() if v is None: return diff --git a/pyqtgraph/opengl/MeshData.py b/pyqtgraph/opengl/MeshData.py index 12a9b83b..71e566c9 100644 --- a/pyqtgraph/opengl/MeshData.py +++ b/pyqtgraph/opengl/MeshData.py @@ -247,9 +247,9 @@ class MeshData(object): return self._faceNormals elif indexed == 'faces': if self._faceNormalsIndexedByFaces is None: - norms = np.empty((self._faceNormals.shape[0], 3, 3)) - norms[:] = self._faceNormals[:,np.newaxis,:] - self._faceNormalsIndexedByFaces = norms + norms = np.empty((self._faceNormals.shape[0], 3, 3)) + norms[:] = self._faceNormals[:,np.newaxis,:] + self._faceNormalsIndexedByFaces = norms return self._faceNormalsIndexedByFaces else: raise Exception("Invalid indexing mode. Accepts: None, 'faces'") diff --git a/pyqtgraph/opengl/items/GLMeshItem.py b/pyqtgraph/opengl/items/GLMeshItem.py index 66d54361..5b245e64 100644 --- a/pyqtgraph/opengl/items/GLMeshItem.py +++ b/pyqtgraph/opengl/items/GLMeshItem.py @@ -69,7 +69,11 @@ class GLMeshItem(GLGraphicsItem): self.update() def shader(self): - return shaders.getShaderProgram(self.opts['shader']) + shader = self.opts['shader'] + if isinstance(shader, shaders.ShaderProgram): + return shader + else: + return shaders.getShaderProgram(shader) def setColor(self, c): """Set the default color to use when no vertex or face colors are specified."""