Permalink
Browse files

lp:~luke-campagnola/pyqtgraph/dev/revision/132

  • Loading branch information...
1 parent c7a53a6 commit 06bcfe2c89a46fff670ff9ca7640354bb247363c @ibressler committed May 31, 2012
View
@@ -1,41 +1,41 @@
-from pyqtgraph.Qt import QtCore, QtGui
-
-class ThreadsafeTimer(QtCore.QObject):
- """
- Thread-safe replacement for QTimer.
- """
-
- timeout = QtCore.Signal()
- sigTimerStopRequested = QtCore.Signal()
- sigTimerStartRequested = QtCore.Signal(object)
-
- def __init__(self):
- QtCore.QObject.__init__(self)
- self.timer = QtCore.QTimer()
- self.timer.timeout.connect(self.timerFinished)
- self.timer.moveToThread(QtCore.QCoreApplication.instance().thread())
- self.moveToThread(QtCore.QCoreApplication.instance().thread())
- self.sigTimerStopRequested.connect(self.stop, QtCore.Qt.QueuedConnection)
- self.sigTimerStartRequested.connect(self.start, QtCore.Qt.QueuedConnection)
-
-
- def start(self, timeout):
- isGuiThread = QtCore.QThread.currentThread() == QtCore.QCoreApplication.instance().thread()
- if isGuiThread:
- #print "start timer", self, "from gui thread"
- self.timer.start(timeout)
- else:
- #print "start timer", self, "from remote thread"
- self.sigTimerStartRequested.emit(timeout)
-
- def stop(self):
- isGuiThread = QtCore.QThread.currentThread() == QtCore.QCoreApplication.instance().thread()
- if isGuiThread:
- #print "stop timer", self, "from gui thread"
- self.timer.stop()
- else:
- #print "stop timer", self, "from remote thread"
- self.sigTimerStopRequested.emit()
-
- def timerFinished(self):
+from pyqtgraph.Qt import QtCore, QtGui
+
+class ThreadsafeTimer(QtCore.QObject):
+ """
+ Thread-safe replacement for QTimer.
+ """
+
+ timeout = QtCore.Signal()
+ sigTimerStopRequested = QtCore.Signal()
+ sigTimerStartRequested = QtCore.Signal(object)
+
+ def __init__(self):
+ QtCore.QObject.__init__(self)
+ self.timer = QtCore.QTimer()
+ self.timer.timeout.connect(self.timerFinished)
+ self.timer.moveToThread(QtCore.QCoreApplication.instance().thread())
+ self.moveToThread(QtCore.QCoreApplication.instance().thread())
+ self.sigTimerStopRequested.connect(self.stop, QtCore.Qt.QueuedConnection)
+ self.sigTimerStartRequested.connect(self.start, QtCore.Qt.QueuedConnection)
+
+
+ def start(self, timeout):
+ isGuiThread = QtCore.QThread.currentThread() == QtCore.QCoreApplication.instance().thread()
+ if isGuiThread:
+ #print "start timer", self, "from gui thread"
+ self.timer.start(timeout)
+ else:
+ #print "start timer", self, "from remote thread"
+ self.sigTimerStartRequested.emit(timeout)
+
+ def stop(self):
+ isGuiThread = QtCore.QThread.currentThread() == QtCore.QCoreApplication.instance().thread()
+ if isGuiThread:
+ #print "stop timer", self, "from gui thread"
+ self.timer.stop()
+ else:
+ #print "stop timer", self, "from remote thread"
+ self.sigTimerStopRequested.emit()
+
+ def timerFinished(self):
self.timeout.emit()
View
0 examples/Arrow.py 100755 → 100644
No changes.
View
0 examples/GraphicsLayout.py 100755 → 100644
No changes.
View
0 examples/ScatterPlot.py 100755 → 100644
No changes.
View
0 examples/ViewBox.py 100755 → 100644
No changes.
View
@@ -59,6 +59,7 @@ def __init__(self, orientation, pen=None, linkView=None, parent=None, maxTickLen
self.textHeight = 18
self.tickLength = maxTickLength
+ self._tickLevels = None ## used to override the automatic ticking system with explicit ticks
self.scale = 1.0
self.autoScale = True
@@ -227,7 +228,8 @@ def setScale(self, scale=None):
self.update()
def setRange(self, mn, mx):
- """Set the range of values displayed by the axis"""
+ """Set the range of values displayed by the axis.
+ Usually this is handled automatically by linking the axis to a ViewBox with :func:`linkToView <pyqtgraph.AxisItem.linkToView>`"""
if mn in [np.nan, np.inf, -np.inf] or mx in [np.nan, np.inf, -np.inf]:
raise Exception("Not setting range to [%s, %s]" % (str(mn), str(mx)))
self.range = [mn, mx]
@@ -284,10 +286,28 @@ def paint(self, p, opt, widget):
self.drawPicture(painter)
finally:
painter.end()
+ p.setRenderHint(p.Antialiasing, False)
+ p.setRenderHint(p.TextAntialiasing, True)
self.picture.play(p)
+ def setTicks(self, ticks):
+ """Explicitly determine which ticks to display.
+ This overrides the behavior specified by tickSpacing(), tickValues(), and tickStrings()
+ The format for *ticks* looks like::
+ [
+ [ (majorTickValue1, majorTickString1), (majorTickValue2, majorTickString2), ... ],
+ [ (minorTickValue1, minorTickString1), (minorTickValue2, minorTickString2), ... ],
+ ...
+ ]
+
+ If *ticks* is None, then the default tick system will be used instead.
+ """
+ self._tickLevels = ticks
+ self.picture = None
+ self.update()
+
def tickSpacing(self, minVal, maxVal, size):
"""Return values describing the desired spacing and offset of ticks.
@@ -350,6 +370,7 @@ def tickValues(self, minVal, maxVal, size):
ticks = []
tickLevels = self.tickSpacing(minVal, maxVal, size)
+ allValues = []
for i in range(len(tickLevels)):
spacing, offset = tickLevels[i]
@@ -358,7 +379,10 @@ def tickValues(self, minVal, maxVal, size):
## determine number of ticks
num = int((maxVal-start) / spacing) + 1
- ticks.append((spacing, np.arange(num) * spacing + start))
+ values = np.arange(num) * spacing + start
+ values = filter(lambda x: x not in allValues, values) ## remove any ticks that were present in higher levels
+ allValues.extend(values)
+ ticks.append((spacing, values))
return ticks
def logTickValues(self, minVal, maxVal, size):
@@ -408,7 +432,6 @@ def drawPicture(self, p):
p.setRenderHint(p.TextAntialiasing, True)
prof = debug.Profiler("AxisItem.paint", disabled=True)
- p.setPen(self.pen)
#bounds = self.boundingRect()
bounds = self.mapRectFromParent(self.geometry())
@@ -446,6 +469,7 @@ def drawPicture(self, p):
#print tickStart, tickStop, span
## draw long line along axis
+ p.setPen(self.pen)
p.drawLine(*span)
p.translate(0.5,0) ## resolves some damn pixel ambiguity
@@ -455,8 +479,21 @@ def drawPicture(self, p):
if lengthInPixels == 0:
return
-
- tickLevels = self.tickValues(self.range[0], self.range[1], lengthInPixels)
+ if self._tickLevels is None:
+ tickLevels = self.tickValues(self.range[0], self.range[1], lengthInPixels)
+ tickStrings = None
+ else:
+ ## parse self.tickLevels into the formats returned by tickLevels() and tickStrings()
+ tickLevels = []
+ tickStrings = []
+ for level in self._tickLevels:
+ values = []
+ strings = []
+ tickLevels.append((None, values))
+ tickStrings.append(strings)
+ for val, strn in level:
+ values.append(val)
+ strings.append(strn)
textLevel = 1 ## draw text at this scale level
@@ -499,51 +536,56 @@ def drawPicture(self, p):
p.drawLine(Point(p1), Point(p2))
tickPositions[i].append(x)
prof.mark('draw ticks')
-
- ## determine level to draw text
- best = 0
+
+ ## Draw text until there is no more room (or no more text)
+ textRects = []
for i in range(len(tickLevels)):
- ## take a small sample of strings and measure their rendered text
- spacing, values = tickLevels[i]
- strings = self.tickStrings(values, self.scale, spacing)
- if len(strings) == 0:
- continue
- textRects = [p.boundingRect(QtCore.QRectF(0, 0, 100, 100), QtCore.Qt.AlignCenter, s) for s in strings]
- if axis == 0:
- textSize = np.max([r.height() for r in textRects])
+ ## Get the list of strings to display for this level
+ if tickStrings is None:
+ spacing, values = tickLevels[i]
+ strings = self.tickStrings(values, self.scale, spacing)
else:
- textSize = np.max([r.width() for r in textRects])
+ strings = tickStrings[i]
- ## If these strings are not too crowded, then this level is ok
- textFillRatio = float(textSize * len(values)) / lengthInPixels
- if textFillRatio < 0.7:
- best = i
+ if len(strings) == 0:
continue
- prof.mark('measure text')
-
- spacing, values = tickLevels[best]
- strings = self.tickStrings(values, self.scale, spacing)
- for j in range(len(strings)):
- vstr = strings[j]
- x = tickPositions[best][j]
- textRect = p.boundingRect(QtCore.QRectF(0, 0, 100, 100), QtCore.Qt.AlignCenter, vstr)
- height = textRect.height()
- self.textHeight = height
- if self.orientation == 'left':
- textFlags = QtCore.Qt.AlignRight|QtCore.Qt.AlignVCenter
- rect = QtCore.QRectF(tickStop-100, x-(height/2), 99-max(0,self.tickLength), height)
- elif self.orientation == 'right':
- textFlags = QtCore.Qt.AlignLeft|QtCore.Qt.AlignVCenter
- rect = QtCore.QRectF(tickStop+max(0,self.tickLength)+1, x-(height/2), 100-max(0,self.tickLength), height)
- elif self.orientation == 'top':
- textFlags = QtCore.Qt.AlignCenter|QtCore.Qt.AlignBottom
- rect = QtCore.QRectF(x-100, tickStop-max(0,self.tickLength)-height, 200, height)
- elif self.orientation == 'bottom':
- textFlags = QtCore.Qt.AlignCenter|QtCore.Qt.AlignTop
- rect = QtCore.QRectF(x-100, tickStop+max(0,self.tickLength), 200, height)
+
+ if i > 0: ## always draw top level
+ ## measure all text, make sure there's enough room
+ textRects.extend([p.boundingRect(QtCore.QRectF(0, 0, 100, 100), QtCore.Qt.AlignCenter, s) for s in strings])
+ if axis == 0:
+ textSize = np.sum([r.height() for r in textRects])
+ else:
+ textSize = np.sum([r.width() for r in textRects])
+
+ ## If the strings are too crowded, stop drawing text now
+ textFillRatio = float(textSize) / lengthInPixels
+ if textFillRatio > 0.7:
+ break
- p.setPen(QtGui.QPen(QtGui.QColor(150, 150, 150)))
- p.drawText(rect, textFlags, vstr)
+ #spacing, values = tickLevels[best]
+ #strings = self.tickStrings(values, self.scale, spacing)
+ for j in range(len(strings)):
+ vstr = strings[j]
+ x = tickPositions[i][j]
+ textRect = p.boundingRect(QtCore.QRectF(0, 0, 100, 100), QtCore.Qt.AlignCenter, vstr)
+ height = textRect.height()
+ self.textHeight = height
+ if self.orientation == 'left':
+ textFlags = QtCore.Qt.AlignRight|QtCore.Qt.AlignVCenter
+ rect = QtCore.QRectF(tickStop-100, x-(height/2), 99-max(0,self.tickLength), height)
+ elif self.orientation == 'right':
+ textFlags = QtCore.Qt.AlignLeft|QtCore.Qt.AlignVCenter
+ rect = QtCore.QRectF(tickStop+max(0,self.tickLength)+1, x-(height/2), 100-max(0,self.tickLength), height)
+ elif self.orientation == 'top':
+ textFlags = QtCore.Qt.AlignCenter|QtCore.Qt.AlignBottom
+ rect = QtCore.QRectF(x-100, tickStop-max(0,self.tickLength)-height, 200, height)
+ elif self.orientation == 'bottom':
+ textFlags = QtCore.Qt.AlignCenter|QtCore.Qt.AlignTop
+ rect = QtCore.QRectF(x-100, tickStop+max(0,self.tickLength), 200, height)
+
+ p.setPen(QtGui.QPen(QtGui.QColor(150, 150, 150)))
+ p.drawText(rect, textFlags, vstr)
prof.mark('draw text')
prof.finish()
@@ -16,11 +16,12 @@ def __init__(self, *args, **kargs):
GraphicsItem.__init__(self)
GraphicsScene.registerObject(self) ## workaround for pyqt bug in graphicsscene.items()
- def itemChange(self, change, value):
- ret = QtGui.QGraphicsWidget.itemChange(self, change, value)
- if change in [self.ItemParentHasChanged, self.ItemSceneHasChanged]:
- self._updateView()
- return ret
+## Removed because this causes segmentation faults. Don't know why.
+# def itemChange(self, change, value):
+# ret = QtGui.QGraphicsWidget.itemChange(self, change, value) ## segv occurs here
+# if change in [self.ItemParentHasChanged, self.ItemSceneHasChanged]:
+# self._updateView()
+# return ret
#def getMenu(self):
#pass
@@ -22,7 +22,7 @@ def __init__(self):
def viewRangeChanged(self):
- GraphicsObject.viewRangeChanged(self)
+ UIGraphicsItem.viewRangeChanged(self)
self.picture = None
#UIGraphicsItem.viewRangeChanged(self)
#self.update()
@@ -1,9 +1,4 @@
-try:
- import metaarray
- HAVE_METAARRAY = True
-except:
- HAVE_METAARRAY = False
-
+import pyqtgraph.metaarray as metaarray
from pyqtgraph.Qt import QtCore
from .GraphicsObject import GraphicsObject
from .PlotCurveItem import PlotCurveItem
@@ -493,9 +488,10 @@ def dataType(obj):
return 'empty'
if isSequence(obj):
first = obj[0]
- if isinstance(obj, np.ndarray):
- if HAVE_METAARRAY and isinstance(obj, metaarray.MetaArray):
- return 'MetaArray'
+
+ if isinstance(obj, metaarray.MetaArray):
+ return 'MetaArray'
+ elif isinstance(obj, np.ndarray):
if obj.ndim == 1:
if obj.dtype.names is None:
return 'listOfValues'
@@ -514,7 +510,7 @@ def dataType(obj):
def isSequence(obj):
- return isinstance(obj, list) or isinstance(obj, np.ndarray)
+ return isinstance(obj, list) or isinstance(obj, np.ndarray) or isinstance(obj, metaarray.MetaArray)
View
0 graphicsItems/ROI.py 100755 → 100644
No changes.
@@ -35,7 +35,7 @@
def makeSymbolPixmap(size, pen, brush, symbol):
## Render a spot with the given parameters to a pixmap
- penPxWidth = np.ceil(pen.width())
+ penPxWidth = max(np.ceil(pen.width()), 1)
image = QtGui.QImage(size+penPxWidth, size+penPxWidth, QtGui.QImage.Format_ARGB32_Premultiplied)
image.fill(0)
p = QtGui.QPainter(image)
@@ -355,17 +355,18 @@ def measureSpotSizes(self, dataSet):
## keep track of the maximum spot size and pixel size
width = 0
pxWidth = 0
- if self.opts['pxMode']:
- pxWidth += spot.size()
- else:
- width += spot.size()
pen = spot.pen()
- if pen.isCosmetic():
- pxWidth += pen.width() * 2
+ if self.opts['pxMode']:
+ pxWidth = spot.size() + pen.width()
else:
- width += pen.width() * 2
+ width = spot.size()
+ if pen.isCosmetic():
+ pxWidth += pen.width()
+ else:
+ width += pen.width()
self._maxSpotWidth = max(self._maxSpotWidth, width)
self._maxSpotPxWidth = max(self._maxSpotPxWidth, pxWidth)
+ self.bounds = [None, None]
def clear(self):
@@ -388,6 +389,7 @@ def dataBounds(self, ax, frac=1.0, orthoRange=None):
if frac >= 1.0 and self.bounds[ax] is not None:
return self.bounds[ax]
+ self.prepareGeometryChange()
if self.data is None or len(self.data) == 0:
return (None, None)
Oops, something went wrong.

0 comments on commit 06bcfe2

Please sign in to comment.