diff --git a/GraphicsScene/GraphicsScene.py b/GraphicsScene/GraphicsScene.py index 6ac5c5e2..a5f60059 100644 --- a/GraphicsScene/GraphicsScene.py +++ b/GraphicsScene/GraphicsScene.py @@ -73,7 +73,7 @@ class GraphicsScene(QtGui.QGraphicsScene): sigMouseHover = QtCore.Signal(object) ## emits a list of objects hovered over sigMouseMoved = QtCore.Signal(object) ## emits position of mouse on every move - sigMouseClicked = QtCore.Signal(object) ## emitted when MouseClickEvent is not accepted by any items under the click. + sigMouseClicked = QtCore.Signal(object) ## emitted when mouse is clicked. Check for event.isAccepted() to see whether the event has already been acted on. _addressCache = weakref.WeakValueDictionary() @@ -343,10 +343,11 @@ class GraphicsScene(QtGui.QGraphicsScene): if int(item.flags() & item.ItemIsFocusable) > 0: item.setFocus(QtCore.Qt.MouseFocusReason) break - if not ev.isAccepted() and ev.button() is QtCore.Qt.RightButton: + #if not ev.isAccepted() and ev.button() is QtCore.Qt.RightButton: #print "GraphicsScene emitting sigSceneContextMenu" - self.sigMouseClicked.emit(ev) - ev.accept() + #self.sigMouseClicked.emit(ev) + #ev.accept() + self.sigMouseClicked.emit(ev) return ev.isAccepted() #def claimEvent(self, item, button, eventType): diff --git a/SRTTransform3D.py b/SRTTransform3D.py index 89b8ab13..77583b5a 100644 --- a/SRTTransform3D.py +++ b/SRTTransform3D.py @@ -35,6 +35,7 @@ class SRTTransform3D(pg.Transform3D): 'angle': init._state['angle'], 'axis': Vector(0, 0, 1), } + self._state['scale'][2] = 1.0 self.update() elif isinstance(init, QtGui.QMatrix4x4): self.setFromMatrix(init) diff --git a/canvas/CanvasItem.py b/canvas/CanvasItem.py index a5e8d02c..81388cb6 100644 --- a/canvas/CanvasItem.py +++ b/canvas/CanvasItem.py @@ -205,6 +205,7 @@ class CanvasItem(QtCore.QObject): self.userTransform = self.userTransform * inv self.updateTransform() self.selectBoxFromUser() + self.sigTransformChangeFinished.emit(self) #if flip: #if tr['scale'][0] < 0 xor tr['scale'][1] < 0: #return diff --git a/functions.py b/functions.py index 3f5a01d9..23b2580c 100644 --- a/functions.py +++ b/functions.py @@ -991,7 +991,53 @@ def imageToArray(img, copy=False, transpose=True): else: return arr +def colorToAlpha(data, color): + """ + Given an RGBA image in *data*, convert *color* to be transparent. + *data* must be an array (w, h, 3 or 4) of ubyte values and *color* must be + an array (3) of ubyte values. + This is particularly useful for use with images that have a black or white background. + Algorithm is taken from Gimp's color-to-alpha function in plug-ins/common/colortoalpha.c + Credit: + /* + * Color To Alpha plug-in v1.0 by Seth Burgess, sjburges@gimp.org 1999/05/14 + * with algorithm by clahey + */ + + """ + data = data.astype(float) + if data.shape[-1] == 3: ## add alpha channel if needed + d2 = np.empty(data.shape[:2]+(4,), dtype=data.dtype) + d2[...,:3] = data + d2[...,3] = 255 + data = d2 + + color = color.astype(float) + alpha = np.zeros(data.shape[:2]+(3,), dtype=float) + output = data.copy() + + for i in [0,1,2]: + d = data[...,i] + c = color[i] + mask = d > c + alpha[...,i][mask] = (d[mask] - c) / (255. - c) + imask = d < c + alpha[...,i][imask] = (c - d[imask]) / c + + output[...,3] = alpha.max(axis=2) * 255. + + mask = output[...,3] >= 1.0 ## avoid zero division while processing alpha channel + correction = 255. / output[...,3][mask] ## increase value to compensate for decreased alpha + for i in [0,1,2]: + output[...,i][mask] = ((output[...,i][mask]-color[i]) * correction) + color[i] + output[...,3][mask] *= data[...,3][mask] / 255. ## combine computed and previous alpha values + + #raise Exception() + return np.clip(output, 0, 255).astype(np.ubyte) + + + #def isosurface(data, level): #""" #Generate isosurface from volumetric data using marching tetrahedra algorithm. diff --git a/graphicsItems/ViewBox/ViewBox.py b/graphicsItems/ViewBox/ViewBox.py index a1cfde89..8da539fb 100644 --- a/graphicsItems/ViewBox/ViewBox.py +++ b/graphicsItems/ViewBox/ViewBox.py @@ -1269,7 +1269,15 @@ class ViewBox(GraphicsWidget): for item in g.childItems(): item.setPen(fn.mkPen(color='y', width=3)) - item.setZValue(1000000) + g.setZValue(1000000) + + if children: + g.path = QtGui.QGraphicsPathItem(g.childrenShape()) + else: + g.path = QtGui.QGraphicsPathItem(g.shape()) + g.path.setParentItem(g) + g.path.setPen(fn.mkPen('g')) + g.path.setZValue(100) QtCore.QTimer.singleShot(timeout*1000, self.clearLocate) diff --git a/opengl/GLViewWidget.py b/opengl/GLViewWidget.py index 37d42072..d1c1d090 100644 --- a/opengl/GLViewWidget.py +++ b/opengl/GLViewWidget.py @@ -202,9 +202,9 @@ class GLViewWidget(QtOpenGL.QGLWidget): Pos may be a Vector or an (N,3) array of locations """ cam = self.cameraPosition() - if isinstance(pos, np.ndarray) and pos.ndim == 2: - cam = np.array(cam).reshape(1,3) - dist = ((pos-cam)**2).sum(axis=1)**0.5 + if isinstance(pos, np.ndarray): + cam = np.array(cam).reshape((1,)*(pos.ndim-1)+(3,)) + dist = ((pos-cam)**2).sum(axis=-1)**0.5 else: dist = (pos-cam).length() xDist = dist * 2. * np.tan(0.5 * self.opts['fov'] * np.pi / 180.) diff --git a/opengl/items/GLScatterPlotItem.py b/opengl/items/GLScatterPlotItem.py index d04a2ac7..e9bbde64 100644 --- a/opengl/items/GLScatterPlotItem.py +++ b/opengl/items/GLScatterPlotItem.py @@ -118,7 +118,10 @@ class GLScatterPlotItem(GLGraphicsItem): #glUniform1i(self.shader.uniform('texture'), 0) ## inform the shader which texture to use glEnableClientState(GL_VERTEX_ARRAY) try: - glVertexPointerf(self.pos) + pos = self.pos + #if pos.ndim > 2: + #pos = pos.reshape((reduce(lambda a,b: a*b, pos.shape[:-1]), pos.shape[-1])) + glVertexPointerf(pos) if isinstance(self.color, np.ndarray): glEnableClientState(GL_COLOR_ARRAY) @@ -131,19 +134,19 @@ class GLScatterPlotItem(GLGraphicsItem): if not self.pxMode or isinstance(self.size, np.ndarray): glEnableClientState(GL_NORMAL_ARRAY) - norm = np.empty(self.pos.shape) + norm = np.empty(pos.shape) if self.pxMode: - norm[:,0] = self.size + norm[...,0] = self.size else: - gpos = self.mapToView(self.pos.transpose()).transpose() + gpos = self.mapToView(pos.transpose()).transpose() pxSize = self.view().pixelSize(gpos) - norm[:,0] = self.size / pxSize + norm[...,0] = self.size / pxSize glNormalPointerf(norm) else: glNormal3f(self.size, 0, 0) ## vertex shader uses norm.x to determine point size #glPointSize(self.size) - glDrawArrays(GL_POINTS, 0, len(self.pos)) + glDrawArrays(GL_POINTS, 0, pos.size / pos.shape[-1]) finally: glDisableClientState(GL_NORMAL_ARRAY) glDisableClientState(GL_VERTEX_ARRAY)