- Fixed issue with numpy.concatenate wrapper

- ConsoleWidget now correctly catches its own exceptions
- Fixed ViewBox auto-scaling bug
- Fixed functions.siEval not parsing units correctly
- Fixed bug caused when opengl GL_VERSION_STR is None
This commit is contained in:
Luke Campagnola 2012-10-09 20:40:48 -04:00
parent 844dbb20a5
commit 1d05656a73
6 changed files with 88 additions and 57 deletions

View File

@ -217,6 +217,7 @@ class ConsoleWidget(QtGui.QWidget):
for l in tb.split('\n'): for l in tb.split('\n'):
lines.append(" "*indent + prefix + l) lines.append(" "*indent + prefix + l)
self.write('\n'.join(lines)) self.write('\n'.join(lines))
self.exceptionHandler(*sys.exc_info())
def cmdSelected(self, item): def cmdSelected(self, item):
index = -(self.ui.historyList.row(item)+1) index = -(self.ui.historyList.row(item)+1)
@ -314,6 +315,8 @@ class ConsoleWidget(QtGui.QWidget):
def exceptionHandler(self, excType, exc, tb): def exceptionHandler(self, excType, exc, tb):
if self.ui.catchNextExceptionBtn.isChecked(): if self.ui.catchNextExceptionBtn.isChecked():
self.ui.catchNextExceptionBtn.setChecked(False) self.ui.catchNextExceptionBtn.setChecked(False)
elif not self.ui.catchAllExceptionsBtn.isChecked():
return
self.ui.clearExceptionBtn.setEnabled(True) self.ui.clearExceptionBtn.setEnabled(True)
self.currentTraceback = tb self.currentTraceback = tb

View File

@ -1,5 +1,6 @@
import initExample ## Add path to library (just for examples; you do not need this) import initExample ## Add path to library (just for examples; you do not need this)
import numpy as np import numpy as np
import scipy.ndimage as ndi
import pyqtgraph as pg import pyqtgraph as pg
from pyqtgraph.Qt import QtGui, QtCore from pyqtgraph.Qt import QtGui, QtCore
from pyqtgraph.Point import Point from pyqtgraph.Point import Point
@ -11,22 +12,38 @@ label = pg.LabelItem(justify='right')
win.addItem(label) win.addItem(label)
p1 = win.addPlot(row=1, col=0) p1 = win.addPlot(row=1, col=0)
p2 = win.addPlot(row=2, col=0) p2 = win.addPlot(row=2, col=0)
region = pg.LinearRegionItem() region = pg.LinearRegionItem()
region.setZValue(10) region.setZValue(10)
p2.addItem(region) p2.addItem(region)
#pg.dbg()
p1.setAutoVisible(y=True)
#create numpy arrays #create numpy arrays
#make the numbers large to show that the xrange shows data from 10000 to all the way 0 #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) data1 = 10000 + 15000 * ndi.gaussian_filter(np.random.random(size=10000), 10) + 3000 * np.random.random(size=10000)
data2 = 15000 + 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(data1, pen="r")
p1.plot(data2, pen="g") p1.plot(data2, pen="g")
p2.plot(data1, pen="w") p2.plot(data1, pen="w")
def update(): def update():
p1.setXRange(*region.getRegion()) region.setZValue(10)
minX, maxX = region.getRegion()
p1.setXRange(minX, maxX, padding=0)
region.sigRegionChanged.connect(update) region.sigRegionChanged.connect(update)
def updateRegion(window, viewRange):
rgn = viewRange[0]
region.setRegion(rgn)
p1.sigRangeChanged.connect(updateRegion)
region.setRegion([1000, 2000]) region.setRegion([1000, 2000])
#cross hair #cross hair
@ -34,6 +51,8 @@ vLine = pg.InfiniteLine(angle=90, movable=False)
hLine = pg.InfiniteLine(angle=0, movable=False) hLine = pg.InfiniteLine(angle=0, movable=False)
p1.addItem(vLine, ignoreBounds=True) p1.addItem(vLine, ignoreBounds=True)
p1.addItem(hLine, ignoreBounds=True) p1.addItem(hLine, ignoreBounds=True)
vb = p1.vb vb = p1.vb
def mouseMoved(evt): def mouseMoved(evt):
@ -45,6 +64,9 @@ def mouseMoved(evt):
label.setText("<span style='font-size: 12pt'>x=%0.1f, <span style='color: red'>y1=%0.1f</span>, <span style='color: green'>y2=%0.1f</span>" % (mousePoint.x(), data1[index], data2[index])) label.setText("<span style='font-size: 12pt'>x=%0.1f, <span style='color: red'>y1=%0.1f</span>, <span style='color: green'>y2=%0.1f</span>" % (mousePoint.x(), data1[index], data2[index]))
vLine.setPos(mousePoint.x()) vLine.setPos(mousePoint.x())
hLine.setPos(mousePoint.y()) hLine.setPos(mousePoint.y())
proxy = pg.SignalProxy(p1.scene().sigMouseMoved, rateLimit=60, slot=mouseMoved) proxy = pg.SignalProxy(p1.scene().sigMouseMoved, rateLimit=60, slot=mouseMoved)
#p1.scene().sigMouseMoved.connect(mouseMoved) #p1.scene().sigMouseMoved.connect(mouseMoved)

View File

@ -116,7 +116,7 @@ def siEval(s):
""" """
s = asUnicode(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: if m is None:
raise Exception("Can't convert string '%s' to number." % s) raise Exception("Can't convert string '%s' to number." % s)
v = float(m.groups()[0]) v = float(m.groups()[0])

View File

@ -532,7 +532,7 @@ class ViewBox(GraphicsWidget):
if type(fractionVisible[i]) is bool: if type(fractionVisible[i]) is bool:
fractionVisible[i] = 1.0 fractionVisible[i] = 1.0
childRect = None childRange = None
order = [0,1] order = [0,1]
if self.state['autoVisibleOnly'][0] is True: if self.state['autoVisibleOnly'][0] is True:
@ -545,40 +545,48 @@ class ViewBox(GraphicsWidget):
if self.state['autoVisibleOnly'][ax]: if self.state['autoVisibleOnly'][ax]:
oRange = [None, None] oRange = [None, None]
oRange[ax] = targetRect[1-ax] oRange[ax] = targetRect[1-ax]
childRect = self.childrenBoundingRect(frac=fractionVisible, orthoRange=oRange) childRange = self.childrenBounds(frac=fractionVisible, orthoRange=oRange)
else: else:
if childRect is None: if childRange is None:
childRect = self.childrenBoundingRect(frac=fractionVisible) childRange = self.childrenBounds(frac=fractionVisible)
if ax == 0: ## Make corrections to range
## Make corrections to X range xr = childRange[ax]
if xr is not None:
if self.state['autoPan'][0]: 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. w2 = (targetRect[0][1]-targetRect[0][0]) / 2.
childRect.setLeft(x-w2) #childRect.setLeft(x-w2)
childRect.setRight(x+w2) #childRect.setRight(x+w2)
childRange[ax] = [x-w2, x+w2]
else: else:
wp = childRect.width() * 0.02 #wp = childRect.width() * 0.02
childRect = childRect.adjusted(-wp, 0, wp, 0) 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[1][0] = childRect.top()
targetRect[0][1] = childRect.right() #targetRect[1][1] = childRect.bottom()
args['xRange'] = targetRect[0] #args['yRange'] = targetRect[1]
else: if len(args) == 0:
## Make corrections to Y range return
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]
args['padding'] = 0 args['padding'] = 0
args['disableAutoRange'] = False args['disableAutoRange'] = False
#self.setRange(xRange=targetRect[0], yRange=targetRect[1], padding=0, 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()) 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, if overlap < min(vg.height()/3, sg.height()/3): ## if less than 1/3 of views overlap,
## then just replicate the view ## then just replicate the view
x1 = vr.top() y1 = vr.top()
x2 = vr.bottom() y2 = vr.bottom()
else: ## views overlap; line them up else: ## views overlap; line them up
upp = float(vr.height()) / vg.height() upp = float(vr.height()) / vg.height()
x1 = vr.top() + (sg.y()-vg.y()) * upp y2 = vr.bottom() - (sg.y()-vg.y()) * upp
x2 = x1 + sg.height() * upp y1 = y2 - sg.height() * upp
self.enableAutoRange(ViewBox.YAxis, False) self.enableAutoRange(ViewBox.YAxis, False)
self.setYRange(x1, x2, padding=0) self.setYRange(y1, y2, padding=0)
finally: finally:
view.blockLink(False) view.blockLink(False)
@ -985,7 +993,7 @@ class ViewBox(GraphicsWidget):
def childrenBoundingRect(self, frac=None, orthoRange=(None,None)): def childrenBounds(self, frac=None, orthoRange=(None,None)):
"""Return the bounding range of all children. """Return the bounding range of all children.
[[xmin, xmax], [ymin, ymax]] [[xmin, xmax], [ymin, ymax]]
Values may be None if there are no specific bounds for an axis. Values may be None if there are no specific bounds for an axis.
@ -1052,22 +1060,18 @@ class ViewBox(GraphicsWidget):
if useY: if useY:
if range[1] is not None: if range[1] is not None:
range[1] = [min(bounds.top(), range[1][0]), max(bounds.bottom(), range[1][1])] 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: else:
range[1] = [bounds.top(), bounds.bottom()] range[1] = [bounds.top(), bounds.bottom()]
#bounds.setTop(chb.top())
#bounds.setBottom(chb.bottom())
if useX: if useX:
if range[0] is not None: if range[0] is not None:
range[0] = [min(bounds.left(), range[0][0]), max(bounds.right(), range[0][1])] 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: else:
range[0] = [bounds.left(), bounds.right()] 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() tr = self.targetRange()
if range[0] is None: if range[0] is None:
range[0] = tr[0] range[0] = tr[0]

View File

@ -5,15 +5,15 @@ try:
## (numpy trac issue #2084) ## (numpy trac issue #2084)
if not hasattr(np, 'concatenate_orig'): if not hasattr(np, 'concatenate_orig'):
np.concatenate_orig = np.concatenate np.concatenate_orig = np.concatenate
def concatenate(vals, **kwds): def concatenate(vals, *args, **kwds):
"""Wrapper around numpy.concatenate (see pyqtgraph/numpy_fix.py)""" """Wrapper around numpy.concatenate (see pyqtgraph/numpy_fix.py)"""
dtypes = [getattr(v, 'dtype', None) for v in vals] dtypes = [getattr(v, 'dtype', None) for v in vals]
names = [getattr(dt, 'names', None) for dt in dtypes] names = [getattr(dt, 'names', None) for dt in dtypes]
if len(dtypes) < 2 or all([n is None for n in names]): 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:]]): if any([dt != dtypes[0] for dt in dtypes[1:]]):
raise TypeError("Cannot concatenate structured arrays of different dtype.") 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 np.concatenate = concatenate

View File

@ -109,7 +109,9 @@ class GLViewWidget(QtOpenGL.QGLWidget):
import pyqtgraph.debug import pyqtgraph.debug
pyqtgraph.debug.printExc() pyqtgraph.debug.printExc()
msg = "Error while drawing item %s." % str(item) msg = "Error while drawing item %s." % str(item)
ver = glGetString(GL_VERSION).split()[0] ver = glGetString(GL_VERSION)
if ver is not None:
ver = ver.split()[0]
if int(ver.split('.')[0]) < 2: 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) 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: else: