diff --git a/console/Console.py b/console/Console.py index 38c740c4..4d5b691a 100644 --- a/console/Console.py +++ b/console/Console.py @@ -217,6 +217,7 @@ class ConsoleWidget(QtGui.QWidget): for l in tb.split('\n'): lines.append(" "*indent + prefix + l) self.write('\n'.join(lines)) + self.exceptionHandler(*sys.exc_info()) def cmdSelected(self, item): index = -(self.ui.historyList.row(item)+1) @@ -314,6 +315,8 @@ class ConsoleWidget(QtGui.QWidget): def exceptionHandler(self, excType, exc, tb): if self.ui.catchNextExceptionBtn.isChecked(): self.ui.catchNextExceptionBtn.setChecked(False) + elif not self.ui.catchAllExceptionsBtn.isChecked(): + return self.ui.clearExceptionBtn.setEnabled(True) self.currentTraceback = tb diff --git a/examples/crosshair.py b/examples/crosshair.py index 13c70029..2d437215 100644 --- a/examples/crosshair.py +++ b/examples/crosshair.py @@ -1,5 +1,6 @@ import initExample ## Add path to library (just for examples; you do not need this) import numpy as np +import scipy.ndimage as ndi import pyqtgraph as pg from pyqtgraph.Qt import QtGui, QtCore from pyqtgraph.Point import Point @@ -11,22 +12,38 @@ label = pg.LabelItem(justify='right') win.addItem(label) p1 = win.addPlot(row=1, col=0) p2 = win.addPlot(row=2, col=0) + region = pg.LinearRegionItem() region.setZValue(10) p2.addItem(region) +#pg.dbg() +p1.setAutoVisible(y=True) + + #create numpy arrays #make the numbers large to show that the xrange shows data from 10000 to all the way 0 -data1 = 10000 + 3000 * np.random.random(size=10000) -data2 = 15000 + 3000 * np.random.random(size=10000) +data1 = 10000 + 15000 * ndi.gaussian_filter(np.random.random(size=10000), 10) + 3000 * np.random.random(size=10000) +data2 = 15000 + 15000 * ndi.gaussian_filter(np.random.random(size=10000), 10) + 3000 * np.random.random(size=10000) p1.plot(data1, pen="r") p1.plot(data2, pen="g") + p2.plot(data1, pen="w") def update(): - p1.setXRange(*region.getRegion()) + region.setZValue(10) + minX, maxX = region.getRegion() + p1.setXRange(minX, maxX, padding=0) + region.sigRegionChanged.connect(update) + +def updateRegion(window, viewRange): + rgn = viewRange[0] + region.setRegion(rgn) + +p1.sigRangeChanged.connect(updateRegion) + region.setRegion([1000, 2000]) #cross hair @@ -34,6 +51,8 @@ vLine = pg.InfiniteLine(angle=90, movable=False) hLine = pg.InfiniteLine(angle=0, movable=False) p1.addItem(vLine, ignoreBounds=True) p1.addItem(hLine, ignoreBounds=True) + + vb = p1.vb def mouseMoved(evt): @@ -45,6 +64,9 @@ def mouseMoved(evt): label.setText("x=%0.1f, y1=%0.1f, y2=%0.1f" % (mousePoint.x(), data1[index], data2[index])) vLine.setPos(mousePoint.x()) hLine.setPos(mousePoint.y()) + + + proxy = pg.SignalProxy(p1.scene().sigMouseMoved, rateLimit=60, slot=mouseMoved) #p1.scene().sigMouseMoved.connect(mouseMoved) @@ -52,4 +74,4 @@ proxy = pg.SignalProxy(p1.scene().sigMouseMoved, rateLimit=60, slot=mouseMoved) ## Start Qt event loop unless running in interactive mode or using pyside. import sys if (sys.flags.interactive != 1) or not hasattr(QtCore, 'PYQT_VERSION'): - app.exec_() \ No newline at end of file + app.exec_() diff --git a/functions.py b/functions.py index a7246d7b..73c7380d 100644 --- a/functions.py +++ b/functions.py @@ -116,7 +116,7 @@ def siEval(s): """ s = asUnicode(s) - m = re.match(r'(-?((\d+(\.\d*)?)|(\.\d+))([eE]-?\d+)?)\s*([u' + SI_PREFIXES + r']?)$', s) + m = re.match(r'(-?((\d+(\.\d*)?)|(\.\d+))([eE]-?\d+)?)\s*([u' + SI_PREFIXES + r']?).*$', s) if m is None: raise Exception("Can't convert string '%s' to number." % s) v = float(m.groups()[0]) diff --git a/graphicsItems/ViewBox/ViewBox.py b/graphicsItems/ViewBox/ViewBox.py index 2ec14a2c..9ddee54d 100644 --- a/graphicsItems/ViewBox/ViewBox.py +++ b/graphicsItems/ViewBox/ViewBox.py @@ -532,7 +532,7 @@ class ViewBox(GraphicsWidget): if type(fractionVisible[i]) is bool: fractionVisible[i] = 1.0 - childRect = None + childRange = None order = [0,1] if self.state['autoVisibleOnly'][0] is True: @@ -545,40 +545,48 @@ class ViewBox(GraphicsWidget): if self.state['autoVisibleOnly'][ax]: oRange = [None, None] oRange[ax] = targetRect[1-ax] - childRect = self.childrenBoundingRect(frac=fractionVisible, orthoRange=oRange) + childRange = self.childrenBounds(frac=fractionVisible, orthoRange=oRange) else: - if childRect is None: - childRect = self.childrenBoundingRect(frac=fractionVisible) - - if ax == 0: - ## Make corrections to X range + if childRange is None: + childRange = self.childrenBounds(frac=fractionVisible) + + ## Make corrections to range + xr = childRange[ax] + if xr is not None: if self.state['autoPan'][0]: - x = childRect.center().x() + x = sum(xr) * 0.5 + #x = childRect.center().x() w2 = (targetRect[0][1]-targetRect[0][0]) / 2. - childRect.setLeft(x-w2) - childRect.setRight(x+w2) + #childRect.setLeft(x-w2) + #childRect.setRight(x+w2) + childRange[ax] = [x-w2, x+w2] else: - wp = childRect.width() * 0.02 - childRect = childRect.adjusted(-wp, 0, wp, 0) + #wp = childRect.width() * 0.02 + wp = (xr[1] - xr[0]) * 0.02 + #childRect = childRect.adjusted(-wp, 0, wp, 0) + childRange[ax][0] -= wp + childRange[ax][1] += wp + #targetRect[ax][0] = childRect.left() + #targetRect[ax][1] = childRect.right() + targetRect[ax] = childRange[ax] + args['xRange' if ax == 0 else 'yRange'] = targetRect[ax] + #else: + ### Make corrections to Y range + #if self.state['autoPan'][1]: + #y = childRect.center().y() + #h2 = (targetRect[1][1]-targetRect[1][0]) / 2. + #childRect.setTop(y-h2) + #childRect.setBottom(y+h2) + #else: + #hp = childRect.height() * 0.02 + #childRect = childRect.adjusted(0, -hp, 0, hp) - targetRect[0][0] = childRect.left() - targetRect[0][1] = childRect.right() - args['xRange'] = targetRect[0] - else: - ## Make corrections to Y range - if self.state['autoPan'][1]: - y = childRect.center().y() - h2 = (targetRect[1][1]-targetRect[1][0]) / 2. - childRect.setTop(y-h2) - childRect.setBottom(y+h2) - else: - hp = childRect.height() * 0.02 - childRect = childRect.adjusted(0, -hp, 0, hp) - - targetRect[1][0] = childRect.top() - targetRect[1][1] = childRect.bottom() - args['yRange'] = targetRect[1] + #targetRect[1][0] = childRect.top() + #targetRect[1][1] = childRect.bottom() + #args['yRange'] = targetRect[1] + if len(args) == 0: + return args['padding'] = 0 args['disableAutoRange'] = False #self.setRange(xRange=targetRect[0], yRange=targetRect[1], padding=0, disableAutoRange=False) @@ -689,14 +697,14 @@ class ViewBox(GraphicsWidget): overlap = min(sg.bottom(), vg.bottom()) - max(sg.top(), vg.top()) if overlap < min(vg.height()/3, sg.height()/3): ## if less than 1/3 of views overlap, ## then just replicate the view - x1 = vr.top() - x2 = vr.bottom() + y1 = vr.top() + y2 = vr.bottom() else: ## views overlap; line them up upp = float(vr.height()) / vg.height() - x1 = vr.top() + (sg.y()-vg.y()) * upp - x2 = x1 + sg.height() * upp + y2 = vr.bottom() - (sg.y()-vg.y()) * upp + y1 = y2 - sg.height() * upp self.enableAutoRange(ViewBox.YAxis, False) - self.setYRange(x1, x2, padding=0) + self.setYRange(y1, y2, padding=0) finally: view.blockLink(False) @@ -984,8 +992,8 @@ class ViewBox(GraphicsWidget): return children - - def childrenBoundingRect(self, frac=None, orthoRange=(None,None)): + + def childrenBounds(self, frac=None, orthoRange=(None,None)): """Return the bounding range of all children. [[xmin, xmax], [ymin, ymax]] Values may be None if there are no specific bounds for an axis. @@ -1052,22 +1060,18 @@ class ViewBox(GraphicsWidget): if useY: if range[1] is not None: range[1] = [min(bounds.top(), range[1][0]), max(bounds.bottom(), range[1][1])] - #bounds.setTop(min(bounds.top(), chb.top())) - #bounds.setBottom(max(bounds.bottom(), chb.bottom())) else: range[1] = [bounds.top(), bounds.bottom()] - #bounds.setTop(chb.top()) - #bounds.setBottom(chb.bottom()) if useX: if range[0] is not None: range[0] = [min(bounds.left(), range[0][0]), max(bounds.right(), range[0][1])] - #bounds.setLeft(min(bounds.left(), chb.left())) - #bounds.setRight(max(bounds.right(), chb.right())) else: range[0] = [bounds.left(), bounds.right()] - #bounds.setLeft(chb.left()) - #bounds.setRight(chb.right()) + return range + + def childrenBoundingRect(self, *args, **kwds): + range = self.childrenBounds(*args, **kwds) tr = self.targetRange() if range[0] is None: range[0] = tr[0] diff --git a/numpy_fix.py b/numpy_fix.py index f345b58c..2fa8ef1f 100644 --- a/numpy_fix.py +++ b/numpy_fix.py @@ -5,15 +5,15 @@ try: ## (numpy trac issue #2084) if not hasattr(np, 'concatenate_orig'): np.concatenate_orig = np.concatenate - def concatenate(vals, **kwds): + def concatenate(vals, *args, **kwds): """Wrapper around numpy.concatenate (see pyqtgraph/numpy_fix.py)""" dtypes = [getattr(v, 'dtype', None) for v in vals] names = [getattr(dt, 'names', None) for dt in dtypes] if len(dtypes) < 2 or all([n is None for n in names]): - return np.concatenate_orig(vals, **kwds) + return np.concatenate_orig(vals, *args, **kwds) if any([dt != dtypes[0] for dt in dtypes[1:]]): raise TypeError("Cannot concatenate structured arrays of different dtype.") - return np.concatenate_orig(vals, **kwds) + return np.concatenate_orig(vals, *args, **kwds) np.concatenate = concatenate diff --git a/opengl/GLViewWidget.py b/opengl/GLViewWidget.py index e0465793..3e105491 100644 --- a/opengl/GLViewWidget.py +++ b/opengl/GLViewWidget.py @@ -109,11 +109,13 @@ class GLViewWidget(QtOpenGL.QGLWidget): import pyqtgraph.debug pyqtgraph.debug.printExc() msg = "Error while drawing item %s." % str(item) - ver = glGetString(GL_VERSION).split()[0] - if int(ver.split('.')[0]) < 2: - print(msg + " The original exception is printed above; however, pyqtgraph requires OpenGL version 2.0 or greater for many of its 3D features and your OpenGL version is %s. Installing updated display drivers may resolve this issue." % ver) - else: - print(msg) + ver = glGetString(GL_VERSION) + if ver is not None: + ver = ver.split()[0] + if int(ver.split('.')[0]) < 2: + print(msg + " The original exception is printed above; however, pyqtgraph requires OpenGL version 2.0 or greater for many of its 3D features and your OpenGL version is %s. Installing updated display drivers may resolve this issue." % ver) + else: + print(msg) finally: glPopAttrib()