Major merge with dev branch; this branch is ready to become stable after
a few rounds of bugfixes.
This commit is contained in:
commit
bc7e927ba7
@ -1,452 +0,0 @@
|
|||||||
# -*- coding: utf-8 -*-
|
|
||||||
from PyQt4 import QtGui, QtCore
|
|
||||||
import weakref
|
|
||||||
|
|
||||||
class TickSlider(QtGui.QGraphicsView):
|
|
||||||
def __init__(self, parent=None, orientation='bottom', allowAdd=True, **kargs):
|
|
||||||
QtGui.QGraphicsView.__init__(self, parent)
|
|
||||||
#self.orientation = orientation
|
|
||||||
self.allowAdd = allowAdd
|
|
||||||
self.setVerticalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff)
|
|
||||||
self.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff)
|
|
||||||
self.setTransformationAnchor(QtGui.QGraphicsView.NoAnchor)
|
|
||||||
self.setResizeAnchor(QtGui.QGraphicsView.AnchorViewCenter)
|
|
||||||
self.setRenderHints(QtGui.QPainter.Antialiasing | QtGui.QPainter.TextAntialiasing)
|
|
||||||
self.length = 100
|
|
||||||
self.tickSize = 15
|
|
||||||
self.orientations = {
|
|
||||||
'left': (270, 1, -1),
|
|
||||||
'right': (270, 1, 1),
|
|
||||||
'top': (0, 1, -1),
|
|
||||||
'bottom': (0, 1, 1)
|
|
||||||
}
|
|
||||||
|
|
||||||
self.scene = QtGui.QGraphicsScene()
|
|
||||||
self.setScene(self.scene)
|
|
||||||
|
|
||||||
self.ticks = {}
|
|
||||||
self.maxDim = 20
|
|
||||||
self.setOrientation(orientation)
|
|
||||||
self.setFrameStyle(QtGui.QFrame.NoFrame | QtGui.QFrame.Plain)
|
|
||||||
self.setBackgroundRole(QtGui.QPalette.NoRole)
|
|
||||||
self.setMouseTracking(True)
|
|
||||||
|
|
||||||
def keyPressEvent(self, ev):
|
|
||||||
ev.ignore()
|
|
||||||
|
|
||||||
def setMaxDim(self, mx=None):
|
|
||||||
if mx is None:
|
|
||||||
mx = self.maxDim
|
|
||||||
else:
|
|
||||||
self.maxDim = mx
|
|
||||||
|
|
||||||
if self.orientation in ['bottom', 'top']:
|
|
||||||
self.setFixedHeight(mx)
|
|
||||||
self.setMaximumWidth(16777215)
|
|
||||||
else:
|
|
||||||
self.setFixedWidth(mx)
|
|
||||||
self.setMaximumHeight(16777215)
|
|
||||||
|
|
||||||
def setOrientation(self, ort):
|
|
||||||
self.orientation = ort
|
|
||||||
self.resetTransform()
|
|
||||||
self.rotate(self.orientations[ort][0])
|
|
||||||
self.scale(*self.orientations[ort][1:])
|
|
||||||
self.setMaxDim()
|
|
||||||
|
|
||||||
def addTick(self, x, color=None, movable=True):
|
|
||||||
if color is None:
|
|
||||||
color = QtGui.QColor(255,255,255)
|
|
||||||
tick = Tick(self, [x*self.length, 0], color, movable, self.tickSize)
|
|
||||||
self.ticks[tick] = x
|
|
||||||
self.scene.addItem(tick)
|
|
||||||
return tick
|
|
||||||
|
|
||||||
def removeTick(self, tick):
|
|
||||||
del self.ticks[tick]
|
|
||||||
self.scene.removeItem(tick)
|
|
||||||
|
|
||||||
def tickMoved(self, tick, pos):
|
|
||||||
#print "tick changed"
|
|
||||||
## Correct position of tick if it has left bounds.
|
|
||||||
newX = min(max(0, pos.x()), self.length)
|
|
||||||
pos.setX(newX)
|
|
||||||
tick.setPos(pos)
|
|
||||||
self.ticks[tick] = float(newX) / self.length
|
|
||||||
|
|
||||||
def tickClicked(self, tick, ev):
|
|
||||||
if ev.button() == QtCore.Qt.RightButton:
|
|
||||||
self.removeTick(tick)
|
|
||||||
|
|
||||||
def widgetLength(self):
|
|
||||||
if self.orientation in ['bottom', 'top']:
|
|
||||||
return self.width()
|
|
||||||
else:
|
|
||||||
return self.height()
|
|
||||||
|
|
||||||
def resizeEvent(self, ev):
|
|
||||||
wlen = max(40, self.widgetLength())
|
|
||||||
self.setLength(wlen-self.tickSize)
|
|
||||||
bounds = self.scene.itemsBoundingRect()
|
|
||||||
bounds.setLeft(min(-self.tickSize*0.5, bounds.left()))
|
|
||||||
bounds.setRight(max(self.length + self.tickSize, bounds.right()))
|
|
||||||
#bounds.setTop(min(bounds.top(), self.tickSize))
|
|
||||||
#bounds.setBottom(max(0, bounds.bottom()))
|
|
||||||
self.setSceneRect(bounds)
|
|
||||||
self.fitInView(bounds, QtCore.Qt.KeepAspectRatio)
|
|
||||||
|
|
||||||
def setLength(self, newLen):
|
|
||||||
for t, x in self.ticks.items():
|
|
||||||
t.setPos(x * newLen, t.pos().y())
|
|
||||||
self.length = float(newLen)
|
|
||||||
|
|
||||||
def mousePressEvent(self, ev):
|
|
||||||
QtGui.QGraphicsView.mousePressEvent(self, ev)
|
|
||||||
self.ignoreRelease = False
|
|
||||||
if len(self.items(ev.pos())) > 0: ## Let items handle their own clicks
|
|
||||||
self.ignoreRelease = True
|
|
||||||
|
|
||||||
def mouseReleaseEvent(self, ev):
|
|
||||||
QtGui.QGraphicsView.mouseReleaseEvent(self, ev)
|
|
||||||
if self.ignoreRelease:
|
|
||||||
return
|
|
||||||
|
|
||||||
pos = self.mapToScene(ev.pos())
|
|
||||||
if pos.x() < 0 or pos.x() > self.length:
|
|
||||||
return
|
|
||||||
if pos.y() < 0 or pos.y() > self.tickSize:
|
|
||||||
return
|
|
||||||
|
|
||||||
if ev.button() == QtCore.Qt.LeftButton and self.allowAdd:
|
|
||||||
pos.setX(min(max(pos.x(), 0), self.length))
|
|
||||||
self.addTick(pos.x()/self.length)
|
|
||||||
elif ev.button() == QtCore.Qt.RightButton:
|
|
||||||
self.showMenu(ev)
|
|
||||||
|
|
||||||
|
|
||||||
def showMenu(self, ev):
|
|
||||||
pass
|
|
||||||
|
|
||||||
def setTickColor(self, tick, color):
|
|
||||||
tick = self.getTick(tick)
|
|
||||||
tick.color = color
|
|
||||||
tick.setBrush(QtGui.QBrush(QtGui.QColor(tick.color)))
|
|
||||||
|
|
||||||
def setTickValue(self, tick, val):
|
|
||||||
tick = self.getTick(tick)
|
|
||||||
val = min(max(0.0, val), 1.0)
|
|
||||||
x = val * self.length
|
|
||||||
pos = tick.pos()
|
|
||||||
pos.setX(x)
|
|
||||||
tick.setPos(pos)
|
|
||||||
self.ticks[tick] = val
|
|
||||||
|
|
||||||
def tickValue(self, tick):
|
|
||||||
tick = self.getTick(tick)
|
|
||||||
return self.ticks[tick]
|
|
||||||
|
|
||||||
def getTick(self, tick):
|
|
||||||
if type(tick) is int:
|
|
||||||
tick = self.listTicks()[tick][0]
|
|
||||||
return tick
|
|
||||||
|
|
||||||
def mouseMoveEvent(self, ev):
|
|
||||||
QtGui.QGraphicsView.mouseMoveEvent(self, ev)
|
|
||||||
#print ev.pos(), ev.buttons()
|
|
||||||
|
|
||||||
def listTicks(self):
|
|
||||||
ticks = self.ticks.items()
|
|
||||||
ticks.sort(lambda a,b: cmp(a[1], b[1]))
|
|
||||||
return ticks
|
|
||||||
|
|
||||||
|
|
||||||
class GradientWidget(TickSlider):
|
|
||||||
|
|
||||||
sigGradientChanged = QtCore.Signal(object)
|
|
||||||
|
|
||||||
def __init__(self, *args, **kargs):
|
|
||||||
TickSlider.__init__(self, *args, **kargs)
|
|
||||||
self.currentTick = None
|
|
||||||
self.currentTickColor = None
|
|
||||||
self.rectSize = 15
|
|
||||||
self.gradRect = QtGui.QGraphicsRectItem(QtCore.QRectF(0, -self.rectSize, 100, self.rectSize))
|
|
||||||
self.colorMode = 'rgb'
|
|
||||||
self.colorDialog = QtGui.QColorDialog()
|
|
||||||
self.colorDialog.setOption(QtGui.QColorDialog.ShowAlphaChannel, True)
|
|
||||||
self.colorDialog.setOption(QtGui.QColorDialog.DontUseNativeDialog, True)
|
|
||||||
#QtCore.QObject.connect(self.colorDialog, QtCore.SIGNAL('currentColorChanged(const QColor&)'), self.currentColorChanged)
|
|
||||||
self.colorDialog.currentColorChanged.connect(self.currentColorChanged)
|
|
||||||
#QtCore.QObject.connect(self.colorDialog, QtCore.SIGNAL('rejected()'), self.currentColorRejected)
|
|
||||||
self.colorDialog.rejected.connect(self.currentColorRejected)
|
|
||||||
|
|
||||||
#self.gradient = QtGui.QLinearGradient(QtCore.QPointF(0,0), QtCore.QPointF(100,0))
|
|
||||||
self.scene.addItem(self.gradRect)
|
|
||||||
self.addTick(0, QtGui.QColor(0,0,0), True)
|
|
||||||
self.addTick(1, QtGui.QColor(255,0,0), True)
|
|
||||||
|
|
||||||
self.setMaxDim(self.rectSize + self.tickSize)
|
|
||||||
self.updateGradient()
|
|
||||||
|
|
||||||
#self.btn = QtGui.QPushButton('RGB')
|
|
||||||
#self.btnProxy = self.scene.addWidget(self.btn)
|
|
||||||
#self.btnProxy.setFlag(self.btnProxy.ItemIgnoresTransformations)
|
|
||||||
#self.btnProxy.scale(0.7, 0.7)
|
|
||||||
#self.btnProxy.translate(-self.btnProxy.sceneBoundingRect().width()+self.tickSize/2., 0)
|
|
||||||
#if self.orientation == 'bottom':
|
|
||||||
#self.btnProxy.translate(0, -self.rectSize)
|
|
||||||
|
|
||||||
def setColorMode(self, cm):
|
|
||||||
if cm not in ['rgb', 'hsv']:
|
|
||||||
raise Exception("Unknown color mode %s" % str(cm))
|
|
||||||
self.colorMode = cm
|
|
||||||
self.updateGradient()
|
|
||||||
|
|
||||||
def updateGradient(self):
|
|
||||||
self.gradient = self.getGradient()
|
|
||||||
self.gradRect.setBrush(QtGui.QBrush(self.gradient))
|
|
||||||
#self.emit(QtCore.SIGNAL('gradientChanged'), self)
|
|
||||||
self.sigGradientChanged.emit(self)
|
|
||||||
|
|
||||||
def setLength(self, newLen):
|
|
||||||
TickSlider.setLength(self, newLen)
|
|
||||||
self.gradRect.setRect(0, -self.rectSize, newLen, self.rectSize)
|
|
||||||
self.updateGradient()
|
|
||||||
|
|
||||||
def currentColorChanged(self, color):
|
|
||||||
if color.isValid() and self.currentTick is not None:
|
|
||||||
self.setTickColor(self.currentTick, color)
|
|
||||||
self.updateGradient()
|
|
||||||
|
|
||||||
def currentColorRejected(self):
|
|
||||||
self.setTickColor(self.currentTick, self.currentTickColor)
|
|
||||||
self.updateGradient()
|
|
||||||
|
|
||||||
def tickClicked(self, tick, ev):
|
|
||||||
if ev.button() == QtCore.Qt.LeftButton:
|
|
||||||
if not tick.colorChangeAllowed:
|
|
||||||
return
|
|
||||||
self.currentTick = tick
|
|
||||||
self.currentTickColor = tick.color
|
|
||||||
self.colorDialog.setCurrentColor(tick.color)
|
|
||||||
self.colorDialog.open()
|
|
||||||
#color = QtGui.QColorDialog.getColor(tick.color, self, "Select Color", QtGui.QColorDialog.ShowAlphaChannel)
|
|
||||||
#if color.isValid():
|
|
||||||
#self.setTickColor(tick, color)
|
|
||||||
#self.updateGradient()
|
|
||||||
elif ev.button() == QtCore.Qt.RightButton:
|
|
||||||
if not tick.removeAllowed:
|
|
||||||
return
|
|
||||||
if len(self.ticks) > 2:
|
|
||||||
self.removeTick(tick)
|
|
||||||
self.updateGradient()
|
|
||||||
|
|
||||||
def tickMoved(self, tick, pos):
|
|
||||||
TickSlider.tickMoved(self, tick, pos)
|
|
||||||
self.updateGradient()
|
|
||||||
|
|
||||||
|
|
||||||
def getGradient(self):
|
|
||||||
g = QtGui.QLinearGradient(QtCore.QPointF(0,0), QtCore.QPointF(self.length,0))
|
|
||||||
if self.colorMode == 'rgb':
|
|
||||||
ticks = self.listTicks()
|
|
||||||
g.setStops([(x, QtGui.QColor(t.color)) for t,x in ticks])
|
|
||||||
elif self.colorMode == 'hsv': ## HSV mode is approximated for display by interpolating 10 points between each stop
|
|
||||||
ticks = self.listTicks()
|
|
||||||
stops = []
|
|
||||||
stops.append((ticks[0][1], ticks[0][0].color))
|
|
||||||
for i in range(1,len(ticks)):
|
|
||||||
x1 = ticks[i-1][1]
|
|
||||||
x2 = ticks[i][1]
|
|
||||||
dx = (x2-x1) / 10.
|
|
||||||
for j in range(1,10):
|
|
||||||
x = x1 + dx*j
|
|
||||||
stops.append((x, self.getColor(x)))
|
|
||||||
stops.append((x2, self.getColor(x2)))
|
|
||||||
g.setStops(stops)
|
|
||||||
return g
|
|
||||||
|
|
||||||
def getColor(self, x):
|
|
||||||
ticks = self.listTicks()
|
|
||||||
if x <= ticks[0][1]:
|
|
||||||
return QtGui.QColor(ticks[0][0].color) # always copy colors before handing them out
|
|
||||||
if x >= ticks[-1][1]:
|
|
||||||
return QtGui.QColor(ticks[-1][0].color)
|
|
||||||
|
|
||||||
x2 = ticks[0][1]
|
|
||||||
for i in range(1,len(ticks)):
|
|
||||||
x1 = x2
|
|
||||||
x2 = ticks[i][1]
|
|
||||||
if x1 <= x and x2 >= x:
|
|
||||||
break
|
|
||||||
|
|
||||||
dx = (x2-x1)
|
|
||||||
if dx == 0:
|
|
||||||
f = 0.
|
|
||||||
else:
|
|
||||||
f = (x-x1) / dx
|
|
||||||
c1 = ticks[i-1][0].color
|
|
||||||
c2 = ticks[i][0].color
|
|
||||||
if self.colorMode == 'rgb':
|
|
||||||
r = c1.red() * (1.-f) + c2.red() * f
|
|
||||||
g = c1.green() * (1.-f) + c2.green() * f
|
|
||||||
b = c1.blue() * (1.-f) + c2.blue() * f
|
|
||||||
a = c1.alpha() * (1.-f) + c2.alpha() * f
|
|
||||||
return QtGui.QColor(r, g, b,a)
|
|
||||||
elif self.colorMode == 'hsv':
|
|
||||||
h1,s1,v1,_ = c1.getHsv()
|
|
||||||
h2,s2,v2,_ = c2.getHsv()
|
|
||||||
h = h1 * (1.-f) + h2 * f
|
|
||||||
s = s1 * (1.-f) + s2 * f
|
|
||||||
v = v1 * (1.-f) + v2 * f
|
|
||||||
c = QtGui.QColor()
|
|
||||||
c.setHsv(h,s,v)
|
|
||||||
return c
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def mouseReleaseEvent(self, ev):
|
|
||||||
TickSlider.mouseReleaseEvent(self, ev)
|
|
||||||
self.updateGradient()
|
|
||||||
|
|
||||||
def addTick(self, x, color=None, movable=True):
|
|
||||||
if color is None:
|
|
||||||
color = self.getColor(x)
|
|
||||||
t = TickSlider.addTick(self, x, color=color, movable=movable)
|
|
||||||
t.colorChangeAllowed = True
|
|
||||||
t.removeAllowed = True
|
|
||||||
return t
|
|
||||||
|
|
||||||
def saveState(self):
|
|
||||||
ticks = []
|
|
||||||
for t in self.ticks:
|
|
||||||
c = t.color
|
|
||||||
ticks.append((self.ticks[t], (c.red(), c.green(), c.blue(), c.alpha())))
|
|
||||||
state = {'mode': self.colorMode, 'ticks': ticks}
|
|
||||||
return state
|
|
||||||
|
|
||||||
def restoreState(self, state):
|
|
||||||
self.setColorMode(state['mode'])
|
|
||||||
for t in self.ticks.keys():
|
|
||||||
self.removeTick(t)
|
|
||||||
for t in state['ticks']:
|
|
||||||
c = QtGui.QColor(*t[1])
|
|
||||||
self.addTick(t[0], c)
|
|
||||||
self.updateGradient()
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class BlackWhiteSlider(GradientWidget):
|
|
||||||
def __init__(self, parent):
|
|
||||||
GradientWidget.__init__(self, parent)
|
|
||||||
self.getTick(0).colorChangeAllowed = False
|
|
||||||
self.getTick(1).colorChangeAllowed = False
|
|
||||||
self.allowAdd = False
|
|
||||||
self.setTickColor(self.getTick(1), QtGui.QColor(255,255,255))
|
|
||||||
self.setOrientation('right')
|
|
||||||
|
|
||||||
def getLevels(self):
|
|
||||||
return (self.tickValue(0), self.tickValue(1))
|
|
||||||
|
|
||||||
def setLevels(self, black, white):
|
|
||||||
self.setTickValue(0, black)
|
|
||||||
self.setTickValue(1, white)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class GammaWidget(TickSlider):
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
class Tick(QtGui.QGraphicsPolygonItem):
|
|
||||||
def __init__(self, view, pos, color, movable=True, scale=10):
|
|
||||||
#QObjectWorkaround.__init__(self)
|
|
||||||
self.movable = movable
|
|
||||||
self.view = weakref.ref(view)
|
|
||||||
self.scale = scale
|
|
||||||
self.color = color
|
|
||||||
#self.endTick = endTick
|
|
||||||
self.pg = QtGui.QPolygonF([QtCore.QPointF(0,0), QtCore.QPointF(-scale/3**0.5,scale), QtCore.QPointF(scale/3**0.5,scale)])
|
|
||||||
QtGui.QGraphicsPolygonItem.__init__(self, self.pg)
|
|
||||||
self.setPos(pos[0], pos[1])
|
|
||||||
self.setFlags(QtGui.QGraphicsItem.ItemIsMovable | QtGui.QGraphicsItem.ItemIsSelectable)
|
|
||||||
self.setBrush(QtGui.QBrush(QtGui.QColor(self.color)))
|
|
||||||
if self.movable:
|
|
||||||
self.setZValue(1)
|
|
||||||
else:
|
|
||||||
self.setZValue(0)
|
|
||||||
|
|
||||||
#def x(self):
|
|
||||||
#return self.pos().x()/100.
|
|
||||||
|
|
||||||
def mouseMoveEvent(self, ev):
|
|
||||||
#print self, "move", ev.scenePos()
|
|
||||||
if not self.movable:
|
|
||||||
return
|
|
||||||
if not ev.buttons() & QtCore.Qt.LeftButton:
|
|
||||||
return
|
|
||||||
|
|
||||||
|
|
||||||
newPos = ev.scenePos() + self.mouseOffset
|
|
||||||
newPos.setY(self.pos().y())
|
|
||||||
#newPos.setX(min(max(newPos.x(), 0), 100))
|
|
||||||
self.setPos(newPos)
|
|
||||||
self.view().tickMoved(self, newPos)
|
|
||||||
self.movedSincePress = True
|
|
||||||
#self.emit(QtCore.SIGNAL('tickChanged'), self)
|
|
||||||
ev.accept()
|
|
||||||
|
|
||||||
def mousePressEvent(self, ev):
|
|
||||||
self.movedSincePress = False
|
|
||||||
if ev.button() == QtCore.Qt.LeftButton:
|
|
||||||
ev.accept()
|
|
||||||
self.mouseOffset = self.pos() - ev.scenePos()
|
|
||||||
self.pressPos = ev.scenePos()
|
|
||||||
elif ev.button() == QtCore.Qt.RightButton:
|
|
||||||
ev.accept()
|
|
||||||
#if self.endTick:
|
|
||||||
#return
|
|
||||||
#self.view.tickChanged(self, delete=True)
|
|
||||||
|
|
||||||
def mouseReleaseEvent(self, ev):
|
|
||||||
#print self, "release", ev.scenePos()
|
|
||||||
if not self.movedSincePress:
|
|
||||||
self.view().tickClicked(self, ev)
|
|
||||||
|
|
||||||
#if ev.button() == QtCore.Qt.LeftButton and ev.scenePos() == self.pressPos:
|
|
||||||
#color = QtGui.QColorDialog.getColor(self.color, None, "Select Color", QtGui.QColorDialog.ShowAlphaChannel)
|
|
||||||
#if color.isValid():
|
|
||||||
#self.color = color
|
|
||||||
#self.setBrush(QtGui.QBrush(QtGui.QColor(self.color)))
|
|
||||||
##self.emit(QtCore.SIGNAL('tickChanged'), self)
|
|
||||||
#self.view.tickChanged(self)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
app = QtGui.QApplication([])
|
|
||||||
w = QtGui.QMainWindow()
|
|
||||||
w.show()
|
|
||||||
w.resize(400,400)
|
|
||||||
cw = QtGui.QWidget()
|
|
||||||
w.setCentralWidget(cw)
|
|
||||||
|
|
||||||
l = QtGui.QGridLayout()
|
|
||||||
l.setSpacing(0)
|
|
||||||
cw.setLayout(l)
|
|
||||||
|
|
||||||
w1 = GradientWidget(orientation='top')
|
|
||||||
w2 = GradientWidget(orientation='right', allowAdd=False)
|
|
||||||
w2.setTickColor(1, QtGui.QColor(255,255,255))
|
|
||||||
w3 = GradientWidget(orientation='bottom')
|
|
||||||
w4 = TickSlider(orientation='left')
|
|
||||||
|
|
||||||
l.addWidget(w1, 0, 1)
|
|
||||||
l.addWidget(w2, 1, 2)
|
|
||||||
l.addWidget(w3, 2, 1)
|
|
||||||
l.addWidget(w4, 1, 0)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
521
GraphicsView.py
521
GraphicsView.py
@ -1,521 +0,0 @@
|
|||||||
# -*- coding: utf-8 -*-
|
|
||||||
"""
|
|
||||||
GraphicsView.py - Extension of QGraphicsView
|
|
||||||
Copyright 2010 Luke Campagnola
|
|
||||||
Distributed under MIT/X11 license. See license.txt for more infomation.
|
|
||||||
"""
|
|
||||||
|
|
||||||
from PyQt4 import QtCore, QtGui, QtOpenGL, QtSvg
|
|
||||||
#from numpy import vstack
|
|
||||||
#import time
|
|
||||||
from Point import *
|
|
||||||
#from vector import *
|
|
||||||
import sys, os
|
|
||||||
import debug
|
|
||||||
|
|
||||||
class GraphicsView(QtGui.QGraphicsView):
|
|
||||||
|
|
||||||
sigRangeChanged = QtCore.Signal(object, object)
|
|
||||||
sigMouseReleased = QtCore.Signal(object)
|
|
||||||
sigSceneMouseMoved = QtCore.Signal(object)
|
|
||||||
#sigRegionChanged = QtCore.Signal(object)
|
|
||||||
lastFileDir = None
|
|
||||||
|
|
||||||
def __init__(self, parent=None, useOpenGL=False):
|
|
||||||
"""Re-implementation of QGraphicsView that removes scrollbars and allows unambiguous control of the
|
|
||||||
viewed coordinate range. Also automatically creates a QGraphicsScene and a central QGraphicsWidget
|
|
||||||
that is automatically scaled to the full view geometry.
|
|
||||||
|
|
||||||
By default, the view coordinate system matches the widget's pixel coordinates and
|
|
||||||
automatically updates when the view is resized. This can be overridden by setting
|
|
||||||
autoPixelRange=False. The exact visible range can be set with setRange().
|
|
||||||
|
|
||||||
The view can be panned using the middle mouse button and scaled using the right mouse button if
|
|
||||||
enabled via enableMouse()."""
|
|
||||||
self.closed = False
|
|
||||||
|
|
||||||
QtGui.QGraphicsView.__init__(self, parent)
|
|
||||||
if 'linux' in sys.platform: ## linux has bugs in opengl implementation
|
|
||||||
useOpenGL = False
|
|
||||||
self.useOpenGL(useOpenGL)
|
|
||||||
|
|
||||||
self.setCacheMode(self.CacheBackground)
|
|
||||||
|
|
||||||
brush = QtGui.QBrush(QtGui.QColor(0,0,0))
|
|
||||||
self.setBackgroundBrush(brush)
|
|
||||||
|
|
||||||
self.setFocusPolicy(QtCore.Qt.StrongFocus)
|
|
||||||
self.setFrameShape(QtGui.QFrame.NoFrame)
|
|
||||||
self.setVerticalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff)
|
|
||||||
self.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff)
|
|
||||||
self.setTransformationAnchor(QtGui.QGraphicsView.NoAnchor)
|
|
||||||
self.setResizeAnchor(QtGui.QGraphicsView.AnchorViewCenter)
|
|
||||||
self.setViewportUpdateMode(QtGui.QGraphicsView.MinimalViewportUpdate)
|
|
||||||
|
|
||||||
|
|
||||||
#self.setSceneRect(QtCore.QRectF(-1e10, -1e10, 2e10, 2e10))
|
|
||||||
|
|
||||||
self.lockedViewports = []
|
|
||||||
self.lastMousePos = None
|
|
||||||
#self.setMouseTracking(False)
|
|
||||||
self.aspectLocked = False
|
|
||||||
#self.yInverted = True
|
|
||||||
self.range = QtCore.QRectF(0, 0, 1, 1)
|
|
||||||
self.autoPixelRange = True
|
|
||||||
self.currentItem = None
|
|
||||||
self.clearMouse()
|
|
||||||
self.updateMatrix()
|
|
||||||
self.sceneObj = QtGui.QGraphicsScene()
|
|
||||||
self.setScene(self.sceneObj)
|
|
||||||
|
|
||||||
## by default we set up a central widget with a grid layout.
|
|
||||||
## this can be replaced if needed.
|
|
||||||
self.centralWidget = None
|
|
||||||
self.setCentralItem(QtGui.QGraphicsWidget())
|
|
||||||
self.centralLayout = QtGui.QGraphicsGridLayout()
|
|
||||||
self.centralWidget.setLayout(self.centralLayout)
|
|
||||||
|
|
||||||
self.mouseEnabled = False
|
|
||||||
self.scaleCenter = False ## should scaling center around view center (True) or mouse click (False)
|
|
||||||
self.clickAccepted = False
|
|
||||||
|
|
||||||
#def paintEvent(self, *args):
|
|
||||||
#prof = debug.Profiler('GraphicsView.paintEvent '+str(id(self)), disabled=False)
|
|
||||||
#QtGui.QGraphicsView.paintEvent(self, *args)
|
|
||||||
#prof.finish()
|
|
||||||
|
|
||||||
def close(self):
|
|
||||||
self.centralWidget = None
|
|
||||||
self.scene().clear()
|
|
||||||
#print " ", self.scene().itemCount()
|
|
||||||
self.currentItem = None
|
|
||||||
self.sceneObj = None
|
|
||||||
self.closed = True
|
|
||||||
self.setViewport(None)
|
|
||||||
|
|
||||||
def useOpenGL(self, b=True):
|
|
||||||
if b:
|
|
||||||
v = QtOpenGL.QGLWidget()
|
|
||||||
else:
|
|
||||||
v = QtGui.QWidget()
|
|
||||||
|
|
||||||
#v.setStyleSheet("background-color: #000000;")
|
|
||||||
self.setViewport(v)
|
|
||||||
|
|
||||||
def keyPressEvent(self, ev):
|
|
||||||
ev.ignore()
|
|
||||||
|
|
||||||
def setCentralItem(self, item):
|
|
||||||
"""Sets a QGraphicsWidget to automatically fill the entire view."""
|
|
||||||
if self.centralWidget is not None:
|
|
||||||
self.scene().removeItem(self.centralWidget)
|
|
||||||
self.centralWidget = item
|
|
||||||
self.sceneObj.addItem(item)
|
|
||||||
self.resizeEvent(None)
|
|
||||||
|
|
||||||
def addItem(self, *args):
|
|
||||||
return self.scene().addItem(*args)
|
|
||||||
|
|
||||||
def removeItem(self, *args):
|
|
||||||
return self.scene().removeItem(*args)
|
|
||||||
|
|
||||||
def enableMouse(self, b=True):
|
|
||||||
self.mouseEnabled = b
|
|
||||||
self.autoPixelRange = (not b)
|
|
||||||
|
|
||||||
def clearMouse(self):
|
|
||||||
self.mouseTrail = []
|
|
||||||
self.lastButtonReleased = None
|
|
||||||
|
|
||||||
def resizeEvent(self, ev):
|
|
||||||
if self.closed:
|
|
||||||
return
|
|
||||||
if self.autoPixelRange:
|
|
||||||
self.range = QtCore.QRectF(0, 0, self.size().width(), self.size().height())
|
|
||||||
self.setRange(self.range, padding=0, disableAutoPixel=False)
|
|
||||||
self.updateMatrix()
|
|
||||||
|
|
||||||
def updateMatrix(self, propagate=True):
|
|
||||||
self.setSceneRect(self.range)
|
|
||||||
if self.aspectLocked:
|
|
||||||
self.fitInView(self.range, QtCore.Qt.KeepAspectRatio)
|
|
||||||
else:
|
|
||||||
self.fitInView(self.range, QtCore.Qt.IgnoreAspectRatio)
|
|
||||||
|
|
||||||
##print "udpateMatrix:"
|
|
||||||
#translate = Point(self.range.center())
|
|
||||||
#if self.range.width() == 0 or self.range.height() == 0:
|
|
||||||
#return
|
|
||||||
#scale = Point(self.size().width()/self.range.width(), self.size().height()/self.range.height())
|
|
||||||
|
|
||||||
#m = QtGui.QTransform()
|
|
||||||
|
|
||||||
### First center the viewport at 0
|
|
||||||
#self.resetMatrix()
|
|
||||||
#center = self.viewportTransform().inverted()[0].map(Point(self.width()/2., self.height()/2.))
|
|
||||||
#if self.yInverted:
|
|
||||||
#m.translate(center.x(), center.y())
|
|
||||||
##print " inverted; translate", center.x(), center.y()
|
|
||||||
#else:
|
|
||||||
#m.translate(center.x(), -center.y())
|
|
||||||
##print " not inverted; translate", center.x(), -center.y()
|
|
||||||
|
|
||||||
### Now scale and translate properly
|
|
||||||
#if self.aspectLocked:
|
|
||||||
#scale = Point(scale.min())
|
|
||||||
#if not self.yInverted:
|
|
||||||
#scale = scale * Point(1, -1)
|
|
||||||
#m.scale(scale[0], scale[1])
|
|
||||||
##print " scale:", scale
|
|
||||||
#st = translate
|
|
||||||
#m.translate(-st[0], -st[1])
|
|
||||||
##print " translate:", st
|
|
||||||
#self.setTransform(m)
|
|
||||||
#self.currentScale = scale
|
|
||||||
##self.emit(QtCore.SIGNAL('viewChanged'), self.range)
|
|
||||||
self.sigRangeChanged.emit(self, self.range)
|
|
||||||
|
|
||||||
if propagate:
|
|
||||||
for v in self.lockedViewports:
|
|
||||||
v.setXRange(self.range, padding=0)
|
|
||||||
|
|
||||||
def visibleRange(self):
|
|
||||||
"""Return the boundaries of the view in scene coordinates"""
|
|
||||||
## easier to just return self.range ?
|
|
||||||
r = QtCore.QRectF(self.rect())
|
|
||||||
return self.viewportTransform().inverted()[0].mapRect(r)
|
|
||||||
|
|
||||||
def translate(self, dx, dy):
|
|
||||||
self.range.adjust(dx, dy, dx, dy)
|
|
||||||
self.updateMatrix()
|
|
||||||
|
|
||||||
def scale(self, sx, sy, center=None):
|
|
||||||
scale = [sx, sy]
|
|
||||||
if self.aspectLocked:
|
|
||||||
scale[0] = scale[1]
|
|
||||||
#adj = (self.range.width()*0.5*(1.0-(1.0/scale[0])), self.range.height()*0.5*(1.0-(1.0/scale[1])))
|
|
||||||
#print "======\n", scale, adj
|
|
||||||
#print self.range
|
|
||||||
#self.range.adjust(adj[0], adj[1], -adj[0], -adj[1])
|
|
||||||
#print self.range
|
|
||||||
|
|
||||||
if self.scaleCenter:
|
|
||||||
center = None
|
|
||||||
if center is None:
|
|
||||||
center = self.range.center()
|
|
||||||
|
|
||||||
w = self.range.width() / scale[0]
|
|
||||||
h = self.range.height() / scale[1]
|
|
||||||
self.range = QtCore.QRectF(center.x() - (center.x()-self.range.left()) / scale[0], center.y() - (center.y()-self.range.top()) /scale[1], w, h)
|
|
||||||
|
|
||||||
|
|
||||||
self.updateMatrix()
|
|
||||||
|
|
||||||
def setRange(self, newRect=None, padding=0.05, lockAspect=None, propagate=True, disableAutoPixel=True):
|
|
||||||
if disableAutoPixel:
|
|
||||||
self.autoPixelRange=False
|
|
||||||
if newRect is None:
|
|
||||||
newRect = self.visibleRange()
|
|
||||||
padding = 0
|
|
||||||
padding = Point(padding)
|
|
||||||
newRect = QtCore.QRectF(newRect)
|
|
||||||
pw = newRect.width() * padding[0]
|
|
||||||
ph = newRect.height() * padding[1]
|
|
||||||
self.range = newRect.adjusted(-pw, -ph, pw, ph)
|
|
||||||
#print "New Range:", self.range
|
|
||||||
self.centralWidget.setGeometry(self.range)
|
|
||||||
self.updateMatrix(propagate)
|
|
||||||
|
|
||||||
def scaleToImage(self, image):
|
|
||||||
"""Scales such that pixels in image are the same size as screen pixels. This may result in a significant performance increase."""
|
|
||||||
pxSize = image.pixelSize()
|
|
||||||
tl = image.sceneBoundingRect().topLeft()
|
|
||||||
w = self.size().width() * pxSize[0]
|
|
||||||
h = self.size().height() * pxSize[1]
|
|
||||||
range = QtCore.QRectF(tl.x(), tl.y(), w, h)
|
|
||||||
self.setRange(range, padding=0)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def lockXRange(self, v1):
|
|
||||||
if not v1 in self.lockedViewports:
|
|
||||||
self.lockedViewports.append(v1)
|
|
||||||
|
|
||||||
def setXRange(self, r, padding=0.05):
|
|
||||||
r1 = QtCore.QRectF(self.range)
|
|
||||||
r1.setLeft(r.left())
|
|
||||||
r1.setRight(r.right())
|
|
||||||
self.setRange(r1, padding=[padding, 0], propagate=False)
|
|
||||||
|
|
||||||
def setYRange(self, r, padding=0.05):
|
|
||||||
r1 = QtCore.QRectF(self.range)
|
|
||||||
r1.setTop(r.top())
|
|
||||||
r1.setBottom(r.bottom())
|
|
||||||
self.setRange(r1, padding=[0, padding], propagate=False)
|
|
||||||
|
|
||||||
#def invertY(self, invert=True):
|
|
||||||
##if self.yInverted != invert:
|
|
||||||
##self.scale[1] *= -1.
|
|
||||||
#self.yInverted = invert
|
|
||||||
#self.updateMatrix()
|
|
||||||
|
|
||||||
|
|
||||||
def wheelEvent(self, ev):
|
|
||||||
QtGui.QGraphicsView.wheelEvent(self, ev)
|
|
||||||
if not self.mouseEnabled:
|
|
||||||
return
|
|
||||||
sc = 1.001 ** ev.delta()
|
|
||||||
#self.scale *= sc
|
|
||||||
#self.updateMatrix()
|
|
||||||
self.scale(sc, sc)
|
|
||||||
|
|
||||||
def setAspectLocked(self, s):
|
|
||||||
self.aspectLocked = s
|
|
||||||
|
|
||||||
#def mouseDoubleClickEvent(self, ev):
|
|
||||||
#QtGui.QGraphicsView.mouseDoubleClickEvent(self, ev)
|
|
||||||
#pass
|
|
||||||
|
|
||||||
### This function is here because interactive mode is disabled due to bugs.
|
|
||||||
#def graphicsSceneEvent(self, ev, pev=None, fev=None):
|
|
||||||
#ev1 = GraphicsSceneMouseEvent()
|
|
||||||
#ev1.setPos(QtCore.QPointF(ev.pos().x(), ev.pos().y()))
|
|
||||||
#ev1.setButtons(ev.buttons())
|
|
||||||
#ev1.setButton(ev.button())
|
|
||||||
#ev1.setModifiers(ev.modifiers())
|
|
||||||
#ev1.setScenePos(self.mapToScene(QtCore.QPoint(ev.pos())))
|
|
||||||
#if pev is not None:
|
|
||||||
#ev1.setLastPos(pev.pos())
|
|
||||||
#ev1.setLastScenePos(pev.scenePos())
|
|
||||||
#ev1.setLastScreenPos(pev.screenPos())
|
|
||||||
#if fev is not None:
|
|
||||||
#ev1.setButtonDownPos(fev.pos())
|
|
||||||
#ev1.setButtonDownScenePos(fev.scenePos())
|
|
||||||
#ev1.setButtonDownScreenPos(fev.screenPos())
|
|
||||||
#return ev1
|
|
||||||
|
|
||||||
def mousePressEvent(self, ev):
|
|
||||||
QtGui.QGraphicsView.mousePressEvent(self, ev)
|
|
||||||
|
|
||||||
#print "Press over:"
|
|
||||||
#for i in self.items(ev.pos()):
|
|
||||||
# print i.zValue(), int(i.acceptedMouseButtons()), i, i.scenePos()
|
|
||||||
#print "Event accepted:", ev.isAccepted()
|
|
||||||
#print "Grabber:", self.scene().mouseGrabberItem()
|
|
||||||
|
|
||||||
|
|
||||||
if not self.mouseEnabled:
|
|
||||||
return
|
|
||||||
self.lastMousePos = Point(ev.pos())
|
|
||||||
self.mousePressPos = ev.pos()
|
|
||||||
self.clickAccepted = ev.isAccepted()
|
|
||||||
if not self.clickAccepted:
|
|
||||||
self.scene().clearSelection()
|
|
||||||
return ## Everything below disabled for now..
|
|
||||||
|
|
||||||
#self.currentItem = None
|
|
||||||
#maxZ = None
|
|
||||||
#for i in self.items(ev.pos()):
|
|
||||||
#if maxZ is None or maxZ < i.zValue():
|
|
||||||
#self.currentItem = i
|
|
||||||
#maxZ = i.zValue()
|
|
||||||
#print "make event"
|
|
||||||
#self.pev = self.graphicsSceneEvent(ev)
|
|
||||||
#self.fev = self.pev
|
|
||||||
#if self.currentItem is not None:
|
|
||||||
#self.currentItem.mousePressEvent(self.pev)
|
|
||||||
##self.clearMouse()
|
|
||||||
##self.mouseTrail.append(Point(self.mapToScene(ev.pos())))
|
|
||||||
#self.emit(QtCore.SIGNAL("mousePressed(PyQt_PyObject)"), self.mouseTrail)
|
|
||||||
|
|
||||||
def mouseReleaseEvent(self, ev):
|
|
||||||
QtGui.QGraphicsView.mouseReleaseEvent(self, ev)
|
|
||||||
if not self.mouseEnabled:
|
|
||||||
return
|
|
||||||
#self.mouseTrail.append(Point(self.mapToScene(ev.pos())))
|
|
||||||
#self.emit(QtCore.SIGNAL("mouseReleased"), ev)
|
|
||||||
self.sigMouseReleased.emit(ev)
|
|
||||||
self.lastButtonReleased = ev.button()
|
|
||||||
return ## Everything below disabled for now..
|
|
||||||
|
|
||||||
##self.mouseTrail.append(Point(self.mapToScene(ev.pos())))
|
|
||||||
#self.emit(QtCore.SIGNAL("mouseReleased(PyQt_PyObject)"), self.mouseTrail)
|
|
||||||
#if self.currentItem is not None:
|
|
||||||
#pev = self.graphicsSceneEvent(ev, self.pev, self.fev)
|
|
||||||
#self.pev = pev
|
|
||||||
#self.currentItem.mouseReleaseEvent(pev)
|
|
||||||
#self.currentItem = None
|
|
||||||
|
|
||||||
def mouseMoveEvent(self, ev):
|
|
||||||
if self.lastMousePos is None:
|
|
||||||
self.lastMousePos = Point(ev.pos())
|
|
||||||
delta = Point(ev.pos() - self.lastMousePos)
|
|
||||||
self.lastMousePos = Point(ev.pos())
|
|
||||||
|
|
||||||
QtGui.QGraphicsView.mouseMoveEvent(self, ev)
|
|
||||||
if not self.mouseEnabled:
|
|
||||||
return
|
|
||||||
#self.emit(QtCore.SIGNAL("sceneMouseMoved(PyQt_PyObject)"), self.mapToScene(ev.pos()))
|
|
||||||
self.sigSceneMouseMoved.emit(self.mapToScene(ev.pos()))
|
|
||||||
#print "moved. Grabber:", self.scene().mouseGrabberItem()
|
|
||||||
|
|
||||||
|
|
||||||
if self.clickAccepted: ## Ignore event if an item in the scene has already claimed it.
|
|
||||||
return
|
|
||||||
|
|
||||||
if ev.buttons() == QtCore.Qt.RightButton:
|
|
||||||
delta = Point(clip(delta[0], -50, 50), clip(-delta[1], -50, 50))
|
|
||||||
scale = 1.01 ** delta
|
|
||||||
#if self.yInverted:
|
|
||||||
#scale[0] = 1. / scale[0]
|
|
||||||
self.scale(scale[0], scale[1], center=self.mapToScene(self.mousePressPos))
|
|
||||||
#self.emit(QtCore.SIGNAL('regionChanged(QRectF)'), self.range)
|
|
||||||
self.sigRangeChanged.emit(self, self.range)
|
|
||||||
|
|
||||||
elif ev.buttons() in [QtCore.Qt.MidButton, QtCore.Qt.LeftButton]: ## Allow panning by left or mid button.
|
|
||||||
px = self.pixelSize()
|
|
||||||
tr = -delta * px
|
|
||||||
|
|
||||||
self.translate(tr[0], tr[1])
|
|
||||||
#self.emit(QtCore.SIGNAL('regionChanged(QRectF)'), self.range)
|
|
||||||
self.sigRangeChanged.emit(self, self.range)
|
|
||||||
|
|
||||||
#return ## Everything below disabled for now..
|
|
||||||
|
|
||||||
##self.mouseTrail.append(Point(self.mapToScene(ev.pos())))
|
|
||||||
#if self.currentItem is not None:
|
|
||||||
#pev = self.graphicsSceneEvent(ev, self.pev, self.fev)
|
|
||||||
#self.pev = pev
|
|
||||||
#self.currentItem.mouseMoveEvent(pev)
|
|
||||||
|
|
||||||
|
|
||||||
def pixelSize(self):
|
|
||||||
"""Return vector with the length and width of one view pixel in scene coordinates"""
|
|
||||||
p0 = Point(0,0)
|
|
||||||
p1 = Point(1,1)
|
|
||||||
tr = self.transform().inverted()[0]
|
|
||||||
p01 = tr.map(p0)
|
|
||||||
p11 = tr.map(p1)
|
|
||||||
return Point(p11 - p01)
|
|
||||||
|
|
||||||
|
|
||||||
def writeSvg(self, fileName=None):
|
|
||||||
if fileName is None:
|
|
||||||
self.fileDialog = QtGui.QFileDialog()
|
|
||||||
self.fileDialog.setFileMode(QtGui.QFileDialog.AnyFile)
|
|
||||||
self.fileDialog.setAcceptMode(QtGui.QFileDialog.AcceptSave)
|
|
||||||
if GraphicsView.lastFileDir is not None:
|
|
||||||
self.fileDialog.setDirectory(GraphicsView.lastFileDir)
|
|
||||||
self.fileDialog.show()
|
|
||||||
self.fileDialog.fileSelected.connect(self.writeSvg)
|
|
||||||
return
|
|
||||||
fileName = str(fileName)
|
|
||||||
GraphicsView.lastFileDir = os.path.split(fileName)[0]
|
|
||||||
self.svg = QtSvg.QSvgGenerator()
|
|
||||||
self.svg.setFileName(fileName)
|
|
||||||
self.svg.setSize(self.size())
|
|
||||||
self.svg.setResolution(600)
|
|
||||||
painter = QtGui.QPainter(self.svg)
|
|
||||||
self.render(painter)
|
|
||||||
|
|
||||||
def writeImage(self, fileName=None):
|
|
||||||
if fileName is None:
|
|
||||||
self.fileDialog = QtGui.QFileDialog()
|
|
||||||
self.fileDialog.setFileMode(QtGui.QFileDialog.AnyFile)
|
|
||||||
self.fileDialog.setAcceptMode(QtGui.QFileDialog.AcceptSave)
|
|
||||||
if GraphicsView.lastFileDir is not None:
|
|
||||||
self.fileDialog.setDirectory(GraphicsView.lastFileDir)
|
|
||||||
self.fileDialog.show()
|
|
||||||
self.fileDialog.fileSelected.connect(self.writePng)
|
|
||||||
return
|
|
||||||
fileName = str(fileName)
|
|
||||||
GraphicsView.lastFileDir = os.path.split(fileName)[0]
|
|
||||||
self.png = QtGui.QImage(self.size(), QtGui.QImage.Format_ARGB32)
|
|
||||||
painter = QtGui.QPainter(self.png)
|
|
||||||
rh = self.renderHints()
|
|
||||||
self.setRenderHints(QtGui.QPainter.Antialiasing)
|
|
||||||
self.render(painter)
|
|
||||||
self.setRenderHints(rh)
|
|
||||||
self.png.save(fileName)
|
|
||||||
|
|
||||||
def writePs(self, fileName=None):
|
|
||||||
if fileName is None:
|
|
||||||
fileName = str(QtGui.QFileDialog.getSaveFileName())
|
|
||||||
printer = QtGui.QPrinter(QtGui.QPrinter.HighResolution)
|
|
||||||
printer.setOutputFileName(fileName)
|
|
||||||
painter = QtGui.QPainter(printer)
|
|
||||||
self.render(painter)
|
|
||||||
painter.end()
|
|
||||||
|
|
||||||
def dragEnterEvent(self, ev):
|
|
||||||
ev.ignore() ## not sure why, but for some reason this class likes to consume drag events
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#def getFreehandLine(self):
|
|
||||||
|
|
||||||
## Wait for click
|
|
||||||
#self.clearMouse()
|
|
||||||
#while self.lastButtonReleased != QtCore.Qt.LeftButton:
|
|
||||||
#QtGui.qApp.sendPostedEvents()
|
|
||||||
#QtGui.qApp.processEvents()
|
|
||||||
#time.sleep(0.01)
|
|
||||||
#fl = vstack(self.mouseTrail)
|
|
||||||
#return fl
|
|
||||||
|
|
||||||
#def getClick(self):
|
|
||||||
#fl = self.getFreehandLine()
|
|
||||||
#return fl[-1]
|
|
||||||
|
|
||||||
|
|
||||||
#class GraphicsSceneMouseEvent(QtGui.QGraphicsSceneMouseEvent):
|
|
||||||
#"""Stand-in class for QGraphicsSceneMouseEvent"""
|
|
||||||
#def __init__(self):
|
|
||||||
#QtGui.QGraphicsSceneMouseEvent.__init__(self)
|
|
||||||
|
|
||||||
#def setPos(self, p):
|
|
||||||
#self.vpos = p
|
|
||||||
#def setButtons(self, p):
|
|
||||||
#self.vbuttons = p
|
|
||||||
#def setButton(self, p):
|
|
||||||
#self.vbutton = p
|
|
||||||
#def setModifiers(self, p):
|
|
||||||
#self.vmodifiers = p
|
|
||||||
#def setScenePos(self, p):
|
|
||||||
#self.vscenePos = p
|
|
||||||
#def setLastPos(self, p):
|
|
||||||
#self.vlastPos = p
|
|
||||||
#def setLastScenePos(self, p):
|
|
||||||
#self.vlastScenePos = p
|
|
||||||
#def setLastScreenPos(self, p):
|
|
||||||
#self.vlastScreenPos = p
|
|
||||||
#def setButtonDownPos(self, p):
|
|
||||||
#self.vbuttonDownPos = p
|
|
||||||
#def setButtonDownScenePos(self, p):
|
|
||||||
#self.vbuttonDownScenePos = p
|
|
||||||
#def setButtonDownScreenPos(self, p):
|
|
||||||
#self.vbuttonDownScreenPos = p
|
|
||||||
|
|
||||||
#def pos(self):
|
|
||||||
#return self.vpos
|
|
||||||
#def buttons(self):
|
|
||||||
#return self.vbuttons
|
|
||||||
#def button(self):
|
|
||||||
#return self.vbutton
|
|
||||||
#def modifiers(self):
|
|
||||||
#return self.vmodifiers
|
|
||||||
#def scenePos(self):
|
|
||||||
#return self.vscenePos
|
|
||||||
#def lastPos(self):
|
|
||||||
#return self.vlastPos
|
|
||||||
#def lastScenePos(self):
|
|
||||||
#return self.vlastScenePos
|
|
||||||
#def lastScreenPos(self):
|
|
||||||
#return self.vlastScreenPos
|
|
||||||
#def buttonDownPos(self):
|
|
||||||
#return self.vbuttonDownPos
|
|
||||||
#def buttonDownScenePos(self):
|
|
||||||
#return self.vbuttonDownScenePos
|
|
||||||
#def buttonDownScreenPos(self):
|
|
||||||
#return self.vbuttonDownScreenPos
|
|
||||||
|
|
@ -1,283 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<ui version="4.0">
|
|
||||||
<class>Form</class>
|
|
||||||
<widget class="QWidget" name="Form">
|
|
||||||
<property name="geometry">
|
|
||||||
<rect>
|
|
||||||
<x>0</x>
|
|
||||||
<y>0</y>
|
|
||||||
<width>726</width>
|
|
||||||
<height>588</height>
|
|
||||||
</rect>
|
|
||||||
</property>
|
|
||||||
<property name="windowTitle">
|
|
||||||
<string>Form</string>
|
|
||||||
</property>
|
|
||||||
<layout class="QVBoxLayout" name="verticalLayout">
|
|
||||||
<property name="spacing">
|
|
||||||
<number>0</number>
|
|
||||||
</property>
|
|
||||||
<property name="margin">
|
|
||||||
<number>0</number>
|
|
||||||
</property>
|
|
||||||
<item>
|
|
||||||
<widget class="QSplitter" name="splitter">
|
|
||||||
<property name="orientation">
|
|
||||||
<enum>Qt::Vertical</enum>
|
|
||||||
</property>
|
|
||||||
<widget class="QWidget" name="layoutWidget">
|
|
||||||
<layout class="QGridLayout" name="gridLayout">
|
|
||||||
<property name="margin">
|
|
||||||
<number>0</number>
|
|
||||||
</property>
|
|
||||||
<property name="spacing">
|
|
||||||
<number>0</number>
|
|
||||||
</property>
|
|
||||||
<item row="1" column="0" rowspan="3">
|
|
||||||
<widget class="GraphicsView" name="graphicsView" native="true">
|
|
||||||
<property name="sizePolicy">
|
|
||||||
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
|
|
||||||
<horstretch>10</horstretch>
|
|
||||||
<verstretch>10</verstretch>
|
|
||||||
</sizepolicy>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="3" column="3">
|
|
||||||
<widget class="QPushButton" name="roiBtn">
|
|
||||||
<property name="sizePolicy">
|
|
||||||
<sizepolicy hsizetype="Minimum" vsizetype="Fixed">
|
|
||||||
<horstretch>0</horstretch>
|
|
||||||
<verstretch>1</verstretch>
|
|
||||||
</sizepolicy>
|
|
||||||
</property>
|
|
||||||
<property name="maximumSize">
|
|
||||||
<size>
|
|
||||||
<width>30</width>
|
|
||||||
<height>16777215</height>
|
|
||||||
</size>
|
|
||||||
</property>
|
|
||||||
<property name="text">
|
|
||||||
<string>R</string>
|
|
||||||
</property>
|
|
||||||
<property name="checkable">
|
|
||||||
<bool>true</bool>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="1" column="3">
|
|
||||||
<widget class="GradientWidget" name="gradientWidget" native="true">
|
|
||||||
<property name="sizePolicy">
|
|
||||||
<sizepolicy hsizetype="Preferred" vsizetype="Expanding">
|
|
||||||
<horstretch>0</horstretch>
|
|
||||||
<verstretch>100</verstretch>
|
|
||||||
</sizepolicy>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="2" column="3">
|
|
||||||
<widget class="QPushButton" name="normBtn">
|
|
||||||
<property name="sizePolicy">
|
|
||||||
<sizepolicy hsizetype="Minimum" vsizetype="Fixed">
|
|
||||||
<horstretch>0</horstretch>
|
|
||||||
<verstretch>1</verstretch>
|
|
||||||
</sizepolicy>
|
|
||||||
</property>
|
|
||||||
<property name="maximumSize">
|
|
||||||
<size>
|
|
||||||
<width>30</width>
|
|
||||||
<height>16777215</height>
|
|
||||||
</size>
|
|
||||||
</property>
|
|
||||||
<property name="text">
|
|
||||||
<string>N</string>
|
|
||||||
</property>
|
|
||||||
<property name="checkable">
|
|
||||||
<bool>true</bool>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="0" column="0" colspan="4">
|
|
||||||
<widget class="QGroupBox" name="normGroup">
|
|
||||||
<property name="title">
|
|
||||||
<string>Normalization</string>
|
|
||||||
</property>
|
|
||||||
<layout class="QGridLayout" name="gridLayout_2">
|
|
||||||
<property name="margin">
|
|
||||||
<number>0</number>
|
|
||||||
</property>
|
|
||||||
<property name="spacing">
|
|
||||||
<number>0</number>
|
|
||||||
</property>
|
|
||||||
<item row="0" column="2">
|
|
||||||
<widget class="QRadioButton" name="normSubtractRadio">
|
|
||||||
<property name="text">
|
|
||||||
<string>Subtract</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="0" column="1">
|
|
||||||
<widget class="QRadioButton" name="normDivideRadio">
|
|
||||||
<property name="text">
|
|
||||||
<string>Divide</string>
|
|
||||||
</property>
|
|
||||||
<property name="checked">
|
|
||||||
<bool>false</bool>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="0" column="0">
|
|
||||||
<widget class="QLabel" name="label_5">
|
|
||||||
<property name="font">
|
|
||||||
<font>
|
|
||||||
<weight>75</weight>
|
|
||||||
<bold>true</bold>
|
|
||||||
</font>
|
|
||||||
</property>
|
|
||||||
<property name="text">
|
|
||||||
<string>Operation:</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="1" column="0">
|
|
||||||
<widget class="QLabel" name="label_3">
|
|
||||||
<property name="font">
|
|
||||||
<font>
|
|
||||||
<weight>75</weight>
|
|
||||||
<bold>true</bold>
|
|
||||||
</font>
|
|
||||||
</property>
|
|
||||||
<property name="text">
|
|
||||||
<string>Mean:</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="2" column="0">
|
|
||||||
<widget class="QLabel" name="label_4">
|
|
||||||
<property name="font">
|
|
||||||
<font>
|
|
||||||
<weight>75</weight>
|
|
||||||
<bold>true</bold>
|
|
||||||
</font>
|
|
||||||
</property>
|
|
||||||
<property name="text">
|
|
||||||
<string>Blur:</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="1" column="1">
|
|
||||||
<widget class="QCheckBox" name="normROICheck">
|
|
||||||
<property name="text">
|
|
||||||
<string>ROI</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="2" column="2">
|
|
||||||
<widget class="QDoubleSpinBox" name="normXBlurSpin"/>
|
|
||||||
</item>
|
|
||||||
<item row="2" column="1">
|
|
||||||
<widget class="QLabel" name="label_8">
|
|
||||||
<property name="text">
|
|
||||||
<string>X</string>
|
|
||||||
</property>
|
|
||||||
<property name="alignment">
|
|
||||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="2" column="3">
|
|
||||||
<widget class="QLabel" name="label_9">
|
|
||||||
<property name="text">
|
|
||||||
<string>Y</string>
|
|
||||||
</property>
|
|
||||||
<property name="alignment">
|
|
||||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="2" column="4">
|
|
||||||
<widget class="QDoubleSpinBox" name="normYBlurSpin"/>
|
|
||||||
</item>
|
|
||||||
<item row="2" column="5">
|
|
||||||
<widget class="QLabel" name="label_10">
|
|
||||||
<property name="text">
|
|
||||||
<string>T</string>
|
|
||||||
</property>
|
|
||||||
<property name="alignment">
|
|
||||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="0" column="3">
|
|
||||||
<widget class="QRadioButton" name="normOffRadio">
|
|
||||||
<property name="text">
|
|
||||||
<string>Off</string>
|
|
||||||
</property>
|
|
||||||
<property name="checked">
|
|
||||||
<bool>true</bool>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="1" column="3">
|
|
||||||
<widget class="QCheckBox" name="normTimeRangeCheck">
|
|
||||||
<property name="text">
|
|
||||||
<string>Time range</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="1" column="2">
|
|
||||||
<widget class="QCheckBox" name="normFrameCheck">
|
|
||||||
<property name="text">
|
|
||||||
<string>Frame</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="2" column="6">
|
|
||||||
<widget class="QDoubleSpinBox" name="normTBlurSpin"/>
|
|
||||||
</item>
|
|
||||||
</layout>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
</layout>
|
|
||||||
</widget>
|
|
||||||
<widget class="PlotWidget" name="roiPlot" native="true">
|
|
||||||
<property name="sizePolicy">
|
|
||||||
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
|
|
||||||
<horstretch>0</horstretch>
|
|
||||||
<verstretch>0</verstretch>
|
|
||||||
</sizepolicy>
|
|
||||||
</property>
|
|
||||||
<property name="minimumSize">
|
|
||||||
<size>
|
|
||||||
<width>0</width>
|
|
||||||
<height>40</height>
|
|
||||||
</size>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
</layout>
|
|
||||||
</widget>
|
|
||||||
<customwidgets>
|
|
||||||
<customwidget>
|
|
||||||
<class>GradientWidget</class>
|
|
||||||
<extends>QWidget</extends>
|
|
||||||
<header>pyqtgraph.GradientWidget</header>
|
|
||||||
<container>1</container>
|
|
||||||
</customwidget>
|
|
||||||
<customwidget>
|
|
||||||
<class>GraphicsView</class>
|
|
||||||
<extends>QWidget</extends>
|
|
||||||
<header>GraphicsView</header>
|
|
||||||
<container>1</container>
|
|
||||||
</customwidget>
|
|
||||||
<customwidget>
|
|
||||||
<class>PlotWidget</class>
|
|
||||||
<extends>QWidget</extends>
|
|
||||||
<header>PlotWidget</header>
|
|
||||||
<container>1</container>
|
|
||||||
</customwidget>
|
|
||||||
</customwidgets>
|
|
||||||
<resources/>
|
|
||||||
<connections/>
|
|
||||||
</ui>
|
|
10
LICENSE.txt
Normal file
10
LICENSE.txt
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
Copyright (c) 2012 University of North Carolina at Chapel Hill
|
||||||
|
Luke Campagnola ('luke.campagnola@%s.com' % 'gmail')
|
||||||
|
|
||||||
|
The MIT License
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
|
1284
PlotItem.py
1284
PlotItem.py
File diff suppressed because it is too large
Load Diff
18
README
18
README
@ -1,18 +0,0 @@
|
|||||||
PyQtGraph - A pure-Python graphics library for PyQt/PySide
|
|
||||||
Copyright 2011 University of North Carolina at Chapel Hill
|
|
||||||
|
|
||||||
Authors:
|
|
||||||
Luke Campagnola ('luke.campagnola@%s.com' % 'gmail')
|
|
||||||
Megan Kratz
|
|
||||||
Ingo Breßler
|
|
||||||
|
|
||||||
Requirements:
|
|
||||||
PyQt 4.5+ or (coming soon) PySide
|
|
||||||
python 2.6+
|
|
||||||
numpy, scipy
|
|
||||||
|
|
||||||
Known to run on Windows, Linux, and Mac.
|
|
||||||
|
|
||||||
Documentation:
|
|
||||||
None.
|
|
||||||
You can look around in the examples directory or pester Luke to write some.
|
|
39
README.txt
Normal file
39
README.txt
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
PyQtGraph - A pure-Python graphics library for PyQt/PySide
|
||||||
|
Copyright 2012 Luke Campagnola, University of North Carolina at Chapel Hill
|
||||||
|
http://www.pyqtgraph.org
|
||||||
|
|
||||||
|
Authors:
|
||||||
|
Luke Campagnola ('luke.campagnola@%s.com' % 'gmail')
|
||||||
|
Megan Kratz
|
||||||
|
Ingo Breßler
|
||||||
|
|
||||||
|
Requirements:
|
||||||
|
PyQt 4.7+ or PySide
|
||||||
|
python 2.6, 2.7, or 3.x
|
||||||
|
numpy, scipy
|
||||||
|
For 3D graphics: pyopengl
|
||||||
|
Known to run on Windows, Linux, and Mac.
|
||||||
|
|
||||||
|
Support:
|
||||||
|
Post at the mailing list / forum:
|
||||||
|
https://groups.google.com/forum/?fromgroups#!forum/pyqtgraph
|
||||||
|
|
||||||
|
Installation Methods:
|
||||||
|
- To use with a specific project, simply copy the pyqtgraph subdirectory
|
||||||
|
anywhere that is importable from your project
|
||||||
|
- To install system-wide from source distribution:
|
||||||
|
$ python setup.py install
|
||||||
|
- For instalation packages, see the website (pyqtgraph.org)
|
||||||
|
|
||||||
|
Documentation:
|
||||||
|
There are many examples; run "python -m pyqtgraph.examples" for a menu.
|
||||||
|
Some (incomplete) documentation exists at this time.
|
||||||
|
- Easiest place to get documentation is at
|
||||||
|
http://www.pyqtgraph.org/documentation
|
||||||
|
- If you acquired this code as a .tar.gz file from the website, then you can also look in
|
||||||
|
doc/html.
|
||||||
|
- If you acquired this code via BZR, then you can build the documentation using sphinx.
|
||||||
|
From the documentation directory, run:
|
||||||
|
$ make html
|
||||||
|
Please feel free to pester Luke or post to the forum if you need a specific
|
||||||
|
section of documentation.
|
@ -1,78 +0,0 @@
|
|||||||
# -*- coding: utf-8 -*-
|
|
||||||
from PyQt4 import QtCore
|
|
||||||
from ptime import time
|
|
||||||
|
|
||||||
class SignalProxy(QtCore.QObject):
|
|
||||||
"""Object which collects rapid-fire signals and condenses them
|
|
||||||
into a single signal. Used, for example, to prevent a SpinBox
|
|
||||||
from generating multiple signals when the mouse wheel is rolled
|
|
||||||
over it."""
|
|
||||||
|
|
||||||
def __init__(self, source, signal, delay=0.3):
|
|
||||||
"""Initialization arguments:
|
|
||||||
source - Any QObject that will emit signal, or None if signal is new style
|
|
||||||
signal - Output of QtCore.SIGNAL(...), or obj.signal for new style
|
|
||||||
delay - Time (in seconds) to wait for signals to stop before emitting (default 0.3s)"""
|
|
||||||
|
|
||||||
QtCore.QObject.__init__(self)
|
|
||||||
if source is None:
|
|
||||||
signal.connect(self.signalReceived)
|
|
||||||
self.signal = QtCore.SIGNAL('signal')
|
|
||||||
else:
|
|
||||||
source.connect(source, signal, self.signalReceived)
|
|
||||||
self.signal = signal
|
|
||||||
self.delay = delay
|
|
||||||
self.args = None
|
|
||||||
self.timer = QtCore.QTimer()
|
|
||||||
self.timer.timeout.connect(self.flush)
|
|
||||||
self.block = False
|
|
||||||
|
|
||||||
def setDelay(self, delay):
|
|
||||||
self.delay = delay
|
|
||||||
|
|
||||||
def signalReceived(self, *args):
|
|
||||||
"""Received signal. Cancel previous timer and store args to be forwarded later."""
|
|
||||||
if self.block:
|
|
||||||
return
|
|
||||||
self.args = args
|
|
||||||
self.timer.stop()
|
|
||||||
self.timer.start((self.delay*1000)+1)
|
|
||||||
|
|
||||||
def flush(self):
|
|
||||||
"""If there is a signal queued up, send it now."""
|
|
||||||
if self.args is None or self.block:
|
|
||||||
return False
|
|
||||||
self.emit(self.signal, *self.args)
|
|
||||||
self.args = None
|
|
||||||
return True
|
|
||||||
|
|
||||||
def disconnect(self):
|
|
||||||
self.block = True
|
|
||||||
|
|
||||||
|
|
||||||
def proxyConnect(source, signal, slot, delay=0.3):
|
|
||||||
"""Connect a signal to a slot with delay. Returns the SignalProxy
|
|
||||||
object that was created. Be sure to store this object so it is not
|
|
||||||
garbage-collected immediately."""
|
|
||||||
sp = SignalProxy(source, signal, delay)
|
|
||||||
if source is None:
|
|
||||||
sp.connect(sp, QtCore.SIGNAL('signal'), slot)
|
|
||||||
else:
|
|
||||||
sp.connect(sp, signal, slot)
|
|
||||||
return sp
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
from PyQt4 import QtGui
|
|
||||||
app = QtGui.QApplication([])
|
|
||||||
win = QtGui.QMainWindow()
|
|
||||||
spin = QtGui.QSpinBox()
|
|
||||||
win.setCentralWidget(spin)
|
|
||||||
win.show()
|
|
||||||
|
|
||||||
def fn(*args):
|
|
||||||
print "Got signal:", args
|
|
||||||
|
|
||||||
proxy = proxyConnect(spin, QtCore.SIGNAL('valueChanged(int)'), fn)
|
|
||||||
|
|
||||||
|
|
39
__init__.py
39
__init__.py
@ -1,39 +0,0 @@
|
|||||||
# -*- coding: utf-8 -*-
|
|
||||||
### import all the goodies and add some helper functions for easy CLI use
|
|
||||||
|
|
||||||
from functions import *
|
|
||||||
from graphicsItems import *
|
|
||||||
from graphicsWindows import *
|
|
||||||
#import PlotWidget
|
|
||||||
#import ImageView
|
|
||||||
from PyQt4 import QtGui
|
|
||||||
from Point import Point
|
|
||||||
from Transform import Transform
|
|
||||||
|
|
||||||
plots = []
|
|
||||||
images = []
|
|
||||||
QAPP = None
|
|
||||||
|
|
||||||
def plot(*args, **kargs):
|
|
||||||
mkQApp()
|
|
||||||
if 'title' in kargs:
|
|
||||||
w = PlotWindow(title=kargs['title'])
|
|
||||||
del kargs['title']
|
|
||||||
else:
|
|
||||||
w = PlotWindow()
|
|
||||||
w.plot(*args, **kargs)
|
|
||||||
plots.append(w)
|
|
||||||
w.show()
|
|
||||||
return w
|
|
||||||
|
|
||||||
def show(*args, **kargs):
|
|
||||||
mkQApp()
|
|
||||||
w = ImageWindow(*args, **kargs)
|
|
||||||
images.append(w)
|
|
||||||
w.show()
|
|
||||||
return w
|
|
||||||
|
|
||||||
def mkQApp():
|
|
||||||
if QtGui.QApplication.instance() is None:
|
|
||||||
global QAPP
|
|
||||||
QAPP = QtGui.QApplication([])
|
|
130
doc/Makefile
Normal file
130
doc/Makefile
Normal file
@ -0,0 +1,130 @@
|
|||||||
|
# Makefile for Sphinx documentation
|
||||||
|
#
|
||||||
|
|
||||||
|
# You can set these variables from the command line.
|
||||||
|
SPHINXOPTS =
|
||||||
|
SPHINXBUILD = sphinx-build
|
||||||
|
PAPER =
|
||||||
|
BUILDDIR = build
|
||||||
|
|
||||||
|
# Internal variables.
|
||||||
|
PAPEROPT_a4 = -D latex_paper_size=a4
|
||||||
|
PAPEROPT_letter = -D latex_paper_size=letter
|
||||||
|
ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) source
|
||||||
|
|
||||||
|
.PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest
|
||||||
|
|
||||||
|
help:
|
||||||
|
@echo "Please use \`make <target>' where <target> is one of"
|
||||||
|
@echo " html to make standalone HTML files"
|
||||||
|
@echo " dirhtml to make HTML files named index.html in directories"
|
||||||
|
@echo " singlehtml to make a single large HTML file"
|
||||||
|
@echo " pickle to make pickle files"
|
||||||
|
@echo " json to make JSON files"
|
||||||
|
@echo " htmlhelp to make HTML files and a HTML help project"
|
||||||
|
@echo " qthelp to make HTML files and a qthelp project"
|
||||||
|
@echo " devhelp to make HTML files and a Devhelp project"
|
||||||
|
@echo " epub to make an epub"
|
||||||
|
@echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter"
|
||||||
|
@echo " latexpdf to make LaTeX files and run them through pdflatex"
|
||||||
|
@echo " text to make text files"
|
||||||
|
@echo " man to make manual pages"
|
||||||
|
@echo " changes to make an overview of all changed/added/deprecated items"
|
||||||
|
@echo " linkcheck to check all external links for integrity"
|
||||||
|
@echo " doctest to run all doctests embedded in the documentation (if enabled)"
|
||||||
|
|
||||||
|
clean:
|
||||||
|
-rm -rf $(BUILDDIR)/*
|
||||||
|
|
||||||
|
html:
|
||||||
|
$(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html
|
||||||
|
@echo
|
||||||
|
@echo "Build finished. The HTML pages are in $(BUILDDIR)/html."
|
||||||
|
|
||||||
|
dirhtml:
|
||||||
|
$(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml
|
||||||
|
@echo
|
||||||
|
@echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml."
|
||||||
|
|
||||||
|
singlehtml:
|
||||||
|
$(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml
|
||||||
|
@echo
|
||||||
|
@echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml."
|
||||||
|
|
||||||
|
pickle:
|
||||||
|
$(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle
|
||||||
|
@echo
|
||||||
|
@echo "Build finished; now you can process the pickle files."
|
||||||
|
|
||||||
|
json:
|
||||||
|
$(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json
|
||||||
|
@echo
|
||||||
|
@echo "Build finished; now you can process the JSON files."
|
||||||
|
|
||||||
|
htmlhelp:
|
||||||
|
$(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp
|
||||||
|
@echo
|
||||||
|
@echo "Build finished; now you can run HTML Help Workshop with the" \
|
||||||
|
".hhp project file in $(BUILDDIR)/htmlhelp."
|
||||||
|
|
||||||
|
qthelp:
|
||||||
|
$(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp
|
||||||
|
@echo
|
||||||
|
@echo "Build finished; now you can run "qcollectiongenerator" with the" \
|
||||||
|
".qhcp project file in $(BUILDDIR)/qthelp, like this:"
|
||||||
|
@echo "# qcollectiongenerator $(BUILDDIR)/qthelp/pyqtgraph.qhcp"
|
||||||
|
@echo "To view the help file:"
|
||||||
|
@echo "# assistant -collectionFile $(BUILDDIR)/qthelp/pyqtgraph.qhc"
|
||||||
|
|
||||||
|
devhelp:
|
||||||
|
$(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp
|
||||||
|
@echo
|
||||||
|
@echo "Build finished."
|
||||||
|
@echo "To view the help file:"
|
||||||
|
@echo "# mkdir -p $$HOME/.local/share/devhelp/pyqtgraph"
|
||||||
|
@echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/pyqtgraph"
|
||||||
|
@echo "# devhelp"
|
||||||
|
|
||||||
|
epub:
|
||||||
|
$(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub
|
||||||
|
@echo
|
||||||
|
@echo "Build finished. The epub file is in $(BUILDDIR)/epub."
|
||||||
|
|
||||||
|
latex:
|
||||||
|
$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
|
||||||
|
@echo
|
||||||
|
@echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex."
|
||||||
|
@echo "Run \`make' in that directory to run these through (pdf)latex" \
|
||||||
|
"(use \`make latexpdf' here to do that automatically)."
|
||||||
|
|
||||||
|
latexpdf:
|
||||||
|
$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
|
||||||
|
@echo "Running LaTeX files through pdflatex..."
|
||||||
|
make -C $(BUILDDIR)/latex all-pdf
|
||||||
|
@echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex."
|
||||||
|
|
||||||
|
text:
|
||||||
|
$(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text
|
||||||
|
@echo
|
||||||
|
@echo "Build finished. The text files are in $(BUILDDIR)/text."
|
||||||
|
|
||||||
|
man:
|
||||||
|
$(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man
|
||||||
|
@echo
|
||||||
|
@echo "Build finished. The manual pages are in $(BUILDDIR)/man."
|
||||||
|
|
||||||
|
changes:
|
||||||
|
$(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes
|
||||||
|
@echo
|
||||||
|
@echo "The overview file is in $(BUILDDIR)/changes."
|
||||||
|
|
||||||
|
linkcheck:
|
||||||
|
$(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck
|
||||||
|
@echo
|
||||||
|
@echo "Link check complete; look for any errors in the above output " \
|
||||||
|
"or in $(BUILDDIR)/linkcheck/output.txt."
|
||||||
|
|
||||||
|
doctest:
|
||||||
|
$(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest
|
||||||
|
@echo "Testing of doctests in the sources finished, look at the " \
|
||||||
|
"results in $(BUILDDIR)/doctest/output.txt."
|
14
doc/listmissing.py
Normal file
14
doc/listmissing.py
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
import os
|
||||||
|
dirs = [
|
||||||
|
('graphicsItems', 'graphicsItems'),
|
||||||
|
('3dgraphics', 'opengl/items'),
|
||||||
|
('widgets', 'widgets'),
|
||||||
|
]
|
||||||
|
|
||||||
|
path = os.path.join(os.path.dirname(os.path.abspath(__file__)), '..')
|
||||||
|
for a, b in dirs:
|
||||||
|
rst = [os.path.splitext(x)[0].lower() for x in os.listdir(os.path.join(path, 'documentation', 'source', a))]
|
||||||
|
py = [os.path.splitext(x)[0].lower() for x in os.listdir(os.path.join(path, b))]
|
||||||
|
print a
|
||||||
|
for x in set(py) - set(rst):
|
||||||
|
print " ", x
|
155
doc/make.bat
Normal file
155
doc/make.bat
Normal file
@ -0,0 +1,155 @@
|
|||||||
|
@ECHO OFF
|
||||||
|
|
||||||
|
REM Command file for Sphinx documentation
|
||||||
|
|
||||||
|
if "%SPHINXBUILD%" == "" (
|
||||||
|
set SPHINXBUILD=sphinx-build
|
||||||
|
)
|
||||||
|
set BUILDDIR=build
|
||||||
|
set ALLSPHINXOPTS=-d %BUILDDIR%/doctrees %SPHINXOPTS% source
|
||||||
|
if NOT "%PAPER%" == "" (
|
||||||
|
set ALLSPHINXOPTS=-D latex_paper_size=%PAPER% %ALLSPHINXOPTS%
|
||||||
|
)
|
||||||
|
|
||||||
|
if "%1" == "" goto help
|
||||||
|
|
||||||
|
if "%1" == "help" (
|
||||||
|
:help
|
||||||
|
echo.Please use `make ^<target^>` where ^<target^> is one of
|
||||||
|
echo. html to make standalone HTML files
|
||||||
|
echo. dirhtml to make HTML files named index.html in directories
|
||||||
|
echo. singlehtml to make a single large HTML file
|
||||||
|
echo. pickle to make pickle files
|
||||||
|
echo. json to make JSON files
|
||||||
|
echo. htmlhelp to make HTML files and a HTML help project
|
||||||
|
echo. qthelp to make HTML files and a qthelp project
|
||||||
|
echo. devhelp to make HTML files and a Devhelp project
|
||||||
|
echo. epub to make an epub
|
||||||
|
echo. latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter
|
||||||
|
echo. text to make text files
|
||||||
|
echo. man to make manual pages
|
||||||
|
echo. changes to make an overview over all changed/added/deprecated items
|
||||||
|
echo. linkcheck to check all external links for integrity
|
||||||
|
echo. doctest to run all doctests embedded in the documentation if enabled
|
||||||
|
goto end
|
||||||
|
)
|
||||||
|
|
||||||
|
if "%1" == "clean" (
|
||||||
|
for /d %%i in (%BUILDDIR%\*) do rmdir /q /s %%i
|
||||||
|
del /q /s %BUILDDIR%\*
|
||||||
|
goto end
|
||||||
|
)
|
||||||
|
|
||||||
|
if "%1" == "html" (
|
||||||
|
%SPHINXBUILD% -b html %ALLSPHINXOPTS% %BUILDDIR%/html
|
||||||
|
echo.
|
||||||
|
echo.Build finished. The HTML pages are in %BUILDDIR%/html.
|
||||||
|
goto end
|
||||||
|
)
|
||||||
|
|
||||||
|
if "%1" == "dirhtml" (
|
||||||
|
%SPHINXBUILD% -b dirhtml %ALLSPHINXOPTS% %BUILDDIR%/dirhtml
|
||||||
|
echo.
|
||||||
|
echo.Build finished. The HTML pages are in %BUILDDIR%/dirhtml.
|
||||||
|
goto end
|
||||||
|
)
|
||||||
|
|
||||||
|
if "%1" == "singlehtml" (
|
||||||
|
%SPHINXBUILD% -b singlehtml %ALLSPHINXOPTS% %BUILDDIR%/singlehtml
|
||||||
|
echo.
|
||||||
|
echo.Build finished. The HTML pages are in %BUILDDIR%/singlehtml.
|
||||||
|
goto end
|
||||||
|
)
|
||||||
|
|
||||||
|
if "%1" == "pickle" (
|
||||||
|
%SPHINXBUILD% -b pickle %ALLSPHINXOPTS% %BUILDDIR%/pickle
|
||||||
|
echo.
|
||||||
|
echo.Build finished; now you can process the pickle files.
|
||||||
|
goto end
|
||||||
|
)
|
||||||
|
|
||||||
|
if "%1" == "json" (
|
||||||
|
%SPHINXBUILD% -b json %ALLSPHINXOPTS% %BUILDDIR%/json
|
||||||
|
echo.
|
||||||
|
echo.Build finished; now you can process the JSON files.
|
||||||
|
goto end
|
||||||
|
)
|
||||||
|
|
||||||
|
if "%1" == "htmlhelp" (
|
||||||
|
%SPHINXBUILD% -b htmlhelp %ALLSPHINXOPTS% %BUILDDIR%/htmlhelp
|
||||||
|
echo.
|
||||||
|
echo.Build finished; now you can run HTML Help Workshop with the ^
|
||||||
|
.hhp project file in %BUILDDIR%/htmlhelp.
|
||||||
|
goto end
|
||||||
|
)
|
||||||
|
|
||||||
|
if "%1" == "qthelp" (
|
||||||
|
%SPHINXBUILD% -b qthelp %ALLSPHINXOPTS% %BUILDDIR%/qthelp
|
||||||
|
echo.
|
||||||
|
echo.Build finished; now you can run "qcollectiongenerator" with the ^
|
||||||
|
.qhcp project file in %BUILDDIR%/qthelp, like this:
|
||||||
|
echo.^> qcollectiongenerator %BUILDDIR%\qthelp\pyqtgraph.qhcp
|
||||||
|
echo.To view the help file:
|
||||||
|
echo.^> assistant -collectionFile %BUILDDIR%\qthelp\pyqtgraph.ghc
|
||||||
|
goto end
|
||||||
|
)
|
||||||
|
|
||||||
|
if "%1" == "devhelp" (
|
||||||
|
%SPHINXBUILD% -b devhelp %ALLSPHINXOPTS% %BUILDDIR%/devhelp
|
||||||
|
echo.
|
||||||
|
echo.Build finished.
|
||||||
|
goto end
|
||||||
|
)
|
||||||
|
|
||||||
|
if "%1" == "epub" (
|
||||||
|
%SPHINXBUILD% -b epub %ALLSPHINXOPTS% %BUILDDIR%/epub
|
||||||
|
echo.
|
||||||
|
echo.Build finished. The epub file is in %BUILDDIR%/epub.
|
||||||
|
goto end
|
||||||
|
)
|
||||||
|
|
||||||
|
if "%1" == "latex" (
|
||||||
|
%SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex
|
||||||
|
echo.
|
||||||
|
echo.Build finished; the LaTeX files are in %BUILDDIR%/latex.
|
||||||
|
goto end
|
||||||
|
)
|
||||||
|
|
||||||
|
if "%1" == "text" (
|
||||||
|
%SPHINXBUILD% -b text %ALLSPHINXOPTS% %BUILDDIR%/text
|
||||||
|
echo.
|
||||||
|
echo.Build finished. The text files are in %BUILDDIR%/text.
|
||||||
|
goto end
|
||||||
|
)
|
||||||
|
|
||||||
|
if "%1" == "man" (
|
||||||
|
%SPHINXBUILD% -b man %ALLSPHINXOPTS% %BUILDDIR%/man
|
||||||
|
echo.
|
||||||
|
echo.Build finished. The manual pages are in %BUILDDIR%/man.
|
||||||
|
goto end
|
||||||
|
)
|
||||||
|
|
||||||
|
if "%1" == "changes" (
|
||||||
|
%SPHINXBUILD% -b changes %ALLSPHINXOPTS% %BUILDDIR%/changes
|
||||||
|
echo.
|
||||||
|
echo.The overview file is in %BUILDDIR%/changes.
|
||||||
|
goto end
|
||||||
|
)
|
||||||
|
|
||||||
|
if "%1" == "linkcheck" (
|
||||||
|
%SPHINXBUILD% -b linkcheck %ALLSPHINXOPTS% %BUILDDIR%/linkcheck
|
||||||
|
echo.
|
||||||
|
echo.Link check complete; look for any errors in the above output ^
|
||||||
|
or in %BUILDDIR%/linkcheck/output.txt.
|
||||||
|
goto end
|
||||||
|
)
|
||||||
|
|
||||||
|
if "%1" == "doctest" (
|
||||||
|
%SPHINXBUILD% -b doctest %ALLSPHINXOPTS% %BUILDDIR%/doctest
|
||||||
|
echo.
|
||||||
|
echo.Testing of doctests in the sources finished, look at the ^
|
||||||
|
results in %BUILDDIR%/doctest/output.txt.
|
||||||
|
goto end
|
||||||
|
)
|
||||||
|
|
||||||
|
:end
|
48
doc/source/3dgraphics.rst
Normal file
48
doc/source/3dgraphics.rst
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
3D Graphics
|
||||||
|
===========
|
||||||
|
|
||||||
|
Pyqtgraph uses OpenGL to provide a 3D scenegraph system. This system is functional but still early in development.
|
||||||
|
Current capabilities include:
|
||||||
|
|
||||||
|
* 3D view widget with zoom/rotate controls (mouse drag and wheel)
|
||||||
|
* Scenegraph allowing items to be added/removed from scene with per-item transformations and parent/child relationships.
|
||||||
|
* Triangular meshes
|
||||||
|
* Basic mesh computation functions: isosurfaces, per-vertex normals
|
||||||
|
* Volumetric rendering item
|
||||||
|
* Grid/axis items
|
||||||
|
|
||||||
|
See the :doc:`API Reference </3dgraphics/index>` and the Volumetric (GLVolumeItem.py) and Isosurface (GLMeshItem.py) examples for more information.
|
||||||
|
|
||||||
|
Basic usage example::
|
||||||
|
|
||||||
|
## build a QApplication before building other widgets
|
||||||
|
import pyqtgraph as pg
|
||||||
|
pg.mkQApp()
|
||||||
|
|
||||||
|
## make a widget for displaying 3D objects
|
||||||
|
import pyqtgraph.opengl as gl
|
||||||
|
view = gl.GLViewWidget()
|
||||||
|
view.show()
|
||||||
|
|
||||||
|
## create three grids, add each to the view
|
||||||
|
xgrid = gl.GLGridItem()
|
||||||
|
ygrid = gl.GLGridItem()
|
||||||
|
zgrid = gl.GLGridItem()
|
||||||
|
view.addItem(xgrid)
|
||||||
|
view.addItem(ygrid)
|
||||||
|
view.addItem(zgrid)
|
||||||
|
|
||||||
|
## rotate x and y grids to face the correct direction
|
||||||
|
xgrid.rotate(90, 0, 1, 0)
|
||||||
|
ygrid.rotate(90, 1, 0, 0)
|
||||||
|
|
||||||
|
## scale each grid differently
|
||||||
|
xgrid.scale(0.2, 0.1, 0.1)
|
||||||
|
ygrid.scale(0.2, 0.1, 0.1)
|
||||||
|
zgrid.scale(0.1, 0.2, 0.1)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
8
doc/source/3dgraphics/glaxisitem.rst
Normal file
8
doc/source/3dgraphics/glaxisitem.rst
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
GLAxisItem
|
||||||
|
==========
|
||||||
|
|
||||||
|
.. autoclass:: pyqtgraph.opengl.GLAxisItem
|
||||||
|
:members:
|
||||||
|
|
||||||
|
.. automethod:: pyqtgraph.opengl.GLAxisItem.__init__
|
||||||
|
|
8
doc/source/3dgraphics/glgraphicsitem.rst
Normal file
8
doc/source/3dgraphics/glgraphicsitem.rst
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
GLGraphicsItem
|
||||||
|
==============
|
||||||
|
|
||||||
|
.. autoclass:: pyqtgraph.opengl.GLGraphicsItem
|
||||||
|
:members:
|
||||||
|
|
||||||
|
.. automethod:: pyqtgraph.GLGraphicsItem.__init__
|
||||||
|
|
8
doc/source/3dgraphics/glgriditem.rst
Normal file
8
doc/source/3dgraphics/glgriditem.rst
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
GLGridItem
|
||||||
|
==========
|
||||||
|
|
||||||
|
.. autoclass:: pyqtgraph.opengl.GLGridItem
|
||||||
|
:members:
|
||||||
|
|
||||||
|
.. automethod:: pyqtgraph.opengl.GLGridItem.__init__
|
||||||
|
|
8
doc/source/3dgraphics/glimageitem.rst
Normal file
8
doc/source/3dgraphics/glimageitem.rst
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
GLImageItem
|
||||||
|
===========
|
||||||
|
|
||||||
|
.. autoclass:: pyqtgraph.opengl.GLImageItem
|
||||||
|
:members:
|
||||||
|
|
||||||
|
.. automethod:: pyqtgraph.opengl.GLImageItem.__init__
|
||||||
|
|
8
doc/source/3dgraphics/glmeshitem.rst
Normal file
8
doc/source/3dgraphics/glmeshitem.rst
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
GLMeshItem
|
||||||
|
==========
|
||||||
|
|
||||||
|
.. autoclass:: pyqtgraph.opengl.GLMeshItem
|
||||||
|
:members:
|
||||||
|
|
||||||
|
.. automethod:: pyqtgraph.opengl.GLMeshItem.__init__
|
||||||
|
|
8
doc/source/3dgraphics/glscatterplotitem.rst
Normal file
8
doc/source/3dgraphics/glscatterplotitem.rst
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
GLScatterPlotItem
|
||||||
|
=================
|
||||||
|
|
||||||
|
.. autoclass:: pyqtgraph.opengl.GLScatterPlotItem
|
||||||
|
:members:
|
||||||
|
|
||||||
|
.. automethod:: pyqtgraph.opengl.GLScatterPlotItem.__init__
|
||||||
|
|
8
doc/source/3dgraphics/glsurfaceplotitem.rst
Normal file
8
doc/source/3dgraphics/glsurfaceplotitem.rst
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
GLSurfacePlotItem
|
||||||
|
=================
|
||||||
|
|
||||||
|
.. autoclass:: pyqtgraph.opengl.GLSurfacePlotItem
|
||||||
|
:members:
|
||||||
|
|
||||||
|
.. automethod:: pyqtgraph.opengl.GLSurfacePlotItem.__init__
|
||||||
|
|
8
doc/source/3dgraphics/glviewwidget.rst
Normal file
8
doc/source/3dgraphics/glviewwidget.rst
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
GLViewWidget
|
||||||
|
============
|
||||||
|
|
||||||
|
.. autoclass:: pyqtgraph.opengl.GLViewWidget
|
||||||
|
:members:
|
||||||
|
|
||||||
|
.. automethod:: pyqtgraph.opengl.GLViewWidget.__init__
|
||||||
|
|
8
doc/source/3dgraphics/glvolumeitem.rst
Normal file
8
doc/source/3dgraphics/glvolumeitem.rst
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
GLVolumeItem
|
||||||
|
============
|
||||||
|
|
||||||
|
.. autoclass:: pyqtgraph.opengl.GLVolumeItem
|
||||||
|
:members:
|
||||||
|
|
||||||
|
.. automethod:: pyqtgraph.opengl.GLVolumeItem.__init__
|
||||||
|
|
27
doc/source/3dgraphics/index.rst
Normal file
27
doc/source/3dgraphics/index.rst
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
Pyqtgraph's 3D Graphics System
|
||||||
|
==============================
|
||||||
|
|
||||||
|
The 3D graphics system in pyqtgraph is composed of a :class:`view widget <pyqtgraph.opengl.GLViewWidget>` and
|
||||||
|
several graphics items (all subclasses of :class:`GLGraphicsItem <pyqtgraph.opengl.GLGraphicsItem>`) which
|
||||||
|
can be added to a view widget.
|
||||||
|
|
||||||
|
**Note:** use of this system requires python-opengl bindings. Linux users should install the python-opengl
|
||||||
|
packages from their distribution. Windows/OSX users can download from `<http://pyopengl.sourceforge.net>`_.
|
||||||
|
|
||||||
|
Contents:
|
||||||
|
|
||||||
|
.. toctree::
|
||||||
|
:maxdepth: 2
|
||||||
|
|
||||||
|
glviewwidget
|
||||||
|
|
||||||
|
glgriditem
|
||||||
|
glsurfaceplotitem
|
||||||
|
glvolumeitem
|
||||||
|
glimageitem
|
||||||
|
glmeshitem
|
||||||
|
glaxisitem
|
||||||
|
glgraphicsitem
|
||||||
|
glscatterplotitem
|
||||||
|
meshdata
|
||||||
|
|
8
doc/source/3dgraphics/meshdata.rst
Normal file
8
doc/source/3dgraphics/meshdata.rst
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
MeshData
|
||||||
|
========
|
||||||
|
|
||||||
|
.. autoclass:: pyqtgraph.opengl.MeshData
|
||||||
|
:members:
|
||||||
|
|
||||||
|
.. automethod:: pyqtgraph.opengl.MeshData.__init__
|
||||||
|
|
14
doc/source/apireference.rst
Normal file
14
doc/source/apireference.rst
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
API Reference
|
||||||
|
=============
|
||||||
|
|
||||||
|
Contents:
|
||||||
|
|
||||||
|
.. toctree::
|
||||||
|
:maxdepth: 2
|
||||||
|
|
||||||
|
functions
|
||||||
|
graphicsItems/index
|
||||||
|
widgets/index
|
||||||
|
3dgraphics/index
|
||||||
|
parametertree/index
|
||||||
|
graphicsscene/index
|
218
doc/source/conf.py
Normal file
218
doc/source/conf.py
Normal file
@ -0,0 +1,218 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
#
|
||||||
|
# pyqtgraph documentation build configuration file, created by
|
||||||
|
# sphinx-quickstart on Fri Nov 18 19:33:12 2011.
|
||||||
|
#
|
||||||
|
# This file is execfile()d with the current directory set to its containing dir.
|
||||||
|
#
|
||||||
|
# Note that not all possible configuration values are present in this
|
||||||
|
# autogenerated file.
|
||||||
|
#
|
||||||
|
# All configuration values have a default; values that are commented out
|
||||||
|
# serve to show the default.
|
||||||
|
|
||||||
|
import sys, os
|
||||||
|
|
||||||
|
# If extensions (or modules to document with autodoc) are in another directory,
|
||||||
|
# add these directories to sys.path here. If the directory is relative to the
|
||||||
|
# documentation root, use os.path.abspath to make it absolute, like shown here.
|
||||||
|
path = os.path.dirname(os.path.abspath(__file__))
|
||||||
|
sys.path.insert(0, os.path.join(path, '..', '..', '..'))
|
||||||
|
print sys.path
|
||||||
|
|
||||||
|
# -- General configuration -----------------------------------------------------
|
||||||
|
|
||||||
|
# If your documentation needs a minimal Sphinx version, state it here.
|
||||||
|
#needs_sphinx = '1.0'
|
||||||
|
|
||||||
|
# Add any Sphinx extension module names here, as strings. They can be extensions
|
||||||
|
# coming with Sphinx (named 'sphinx.ext.*') or your custom ones.
|
||||||
|
extensions = ['sphinx.ext.autodoc', 'sphinx.ext.viewcode']
|
||||||
|
|
||||||
|
# Add any paths that contain templates here, relative to this directory.
|
||||||
|
templates_path = ['_templates']
|
||||||
|
|
||||||
|
# The suffix of source filenames.
|
||||||
|
source_suffix = '.rst'
|
||||||
|
|
||||||
|
# The encoding of source files.
|
||||||
|
#source_encoding = 'utf-8-sig'
|
||||||
|
|
||||||
|
# The master toctree document.
|
||||||
|
master_doc = 'index'
|
||||||
|
|
||||||
|
# General information about the project.
|
||||||
|
project = 'pyqtgraph'
|
||||||
|
copyright = '2011, Luke Campagnola'
|
||||||
|
|
||||||
|
# The version info for the project you're documenting, acts as replacement for
|
||||||
|
# |version| and |release|, also used in various other places throughout the
|
||||||
|
# built documents.
|
||||||
|
#
|
||||||
|
# The short X.Y version.
|
||||||
|
version = '1.8'
|
||||||
|
# The full version, including alpha/beta/rc tags.
|
||||||
|
release = '1.8'
|
||||||
|
|
||||||
|
# The language for content autogenerated by Sphinx. Refer to documentation
|
||||||
|
# for a list of supported languages.
|
||||||
|
#language = None
|
||||||
|
|
||||||
|
# There are two options for replacing |today|: either, you set today to some
|
||||||
|
# non-false value, then it is used:
|
||||||
|
#today = ''
|
||||||
|
# Else, today_fmt is used as the format for a strftime call.
|
||||||
|
#today_fmt = '%B %d, %Y'
|
||||||
|
|
||||||
|
# List of patterns, relative to source directory, that match files and
|
||||||
|
# directories to ignore when looking for source files.
|
||||||
|
exclude_patterns = []
|
||||||
|
|
||||||
|
# The reST default role (used for this markup: `text`) to use for all documents.
|
||||||
|
#default_role = None
|
||||||
|
|
||||||
|
# If true, '()' will be appended to :func: etc. cross-reference text.
|
||||||
|
#add_function_parentheses = True
|
||||||
|
|
||||||
|
# If true, the current module name will be prepended to all description
|
||||||
|
# unit titles (such as .. function::).
|
||||||
|
#add_module_names = True
|
||||||
|
|
||||||
|
# If true, sectionauthor and moduleauthor directives will be shown in the
|
||||||
|
# output. They are ignored by default.
|
||||||
|
#show_authors = False
|
||||||
|
|
||||||
|
# The name of the Pygments (syntax highlighting) style to use.
|
||||||
|
pygments_style = 'sphinx'
|
||||||
|
|
||||||
|
# A list of ignored prefixes for module index sorting.
|
||||||
|
#modindex_common_prefix = []
|
||||||
|
|
||||||
|
|
||||||
|
# -- Options for HTML output ---------------------------------------------------
|
||||||
|
|
||||||
|
# The theme to use for HTML and HTML Help pages. See the documentation for
|
||||||
|
# a list of builtin themes.
|
||||||
|
html_theme = 'default'
|
||||||
|
|
||||||
|
# Theme options are theme-specific and customize the look and feel of a theme
|
||||||
|
# further. For a list of options available for each theme, see the
|
||||||
|
# documentation.
|
||||||
|
#html_theme_options = {}
|
||||||
|
|
||||||
|
# Add any paths that contain custom themes here, relative to this directory.
|
||||||
|
#html_theme_path = []
|
||||||
|
|
||||||
|
# The name for this set of Sphinx documents. If None, it defaults to
|
||||||
|
# "<project> v<release> documentation".
|
||||||
|
#html_title = None
|
||||||
|
|
||||||
|
# A shorter title for the navigation bar. Default is the same as html_title.
|
||||||
|
#html_short_title = None
|
||||||
|
|
||||||
|
# The name of an image file (relative to this directory) to place at the top
|
||||||
|
# of the sidebar.
|
||||||
|
#html_logo = None
|
||||||
|
|
||||||
|
# The name of an image file (within the static path) to use as favicon of the
|
||||||
|
# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32
|
||||||
|
# pixels large.
|
||||||
|
#html_favicon = None
|
||||||
|
|
||||||
|
# Add any paths that contain custom static files (such as style sheets) here,
|
||||||
|
# relative to this directory. They are copied after the builtin static files,
|
||||||
|
# so a file named "default.css" will overwrite the builtin "default.css".
|
||||||
|
html_static_path = ['_static']
|
||||||
|
|
||||||
|
# If not '', a 'Last updated on:' timestamp is inserted at every page bottom,
|
||||||
|
# using the given strftime format.
|
||||||
|
#html_last_updated_fmt = '%b %d, %Y'
|
||||||
|
|
||||||
|
# If true, SmartyPants will be used to convert quotes and dashes to
|
||||||
|
# typographically correct entities.
|
||||||
|
#html_use_smartypants = True
|
||||||
|
|
||||||
|
# Custom sidebar templates, maps document names to template names.
|
||||||
|
#html_sidebars = {}
|
||||||
|
|
||||||
|
# Additional templates that should be rendered to pages, maps page names to
|
||||||
|
# template names.
|
||||||
|
#html_additional_pages = {}
|
||||||
|
|
||||||
|
# If false, no module index is generated.
|
||||||
|
#html_domain_indices = True
|
||||||
|
|
||||||
|
# If false, no index is generated.
|
||||||
|
#html_use_index = True
|
||||||
|
|
||||||
|
# If true, the index is split into individual pages for each letter.
|
||||||
|
#html_split_index = False
|
||||||
|
|
||||||
|
# If true, links to the reST sources are added to the pages.
|
||||||
|
#html_show_sourcelink = True
|
||||||
|
|
||||||
|
# If true, "Created using Sphinx" is shown in the HTML footer. Default is True.
|
||||||
|
#html_show_sphinx = True
|
||||||
|
|
||||||
|
# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True.
|
||||||
|
#html_show_copyright = True
|
||||||
|
|
||||||
|
# If true, an OpenSearch description file will be output, and all pages will
|
||||||
|
# contain a <link> tag referring to it. The value of this option must be the
|
||||||
|
# base URL from which the finished HTML is served.
|
||||||
|
#html_use_opensearch = ''
|
||||||
|
|
||||||
|
# This is the file name suffix for HTML files (e.g. ".xhtml").
|
||||||
|
#html_file_suffix = None
|
||||||
|
|
||||||
|
# Output file base name for HTML help builder.
|
||||||
|
htmlhelp_basename = 'pyqtgraphdoc'
|
||||||
|
|
||||||
|
|
||||||
|
# -- Options for LaTeX output --------------------------------------------------
|
||||||
|
|
||||||
|
# The paper size ('letter' or 'a4').
|
||||||
|
#latex_paper_size = 'letter'
|
||||||
|
|
||||||
|
# The font size ('10pt', '11pt' or '12pt').
|
||||||
|
#latex_font_size = '10pt'
|
||||||
|
|
||||||
|
# Grouping the document tree into LaTeX files. List of tuples
|
||||||
|
# (source start file, target name, title, author, documentclass [howto/manual]).
|
||||||
|
latex_documents = [
|
||||||
|
('index', 'pyqtgraph.tex', 'pyqtgraph Documentation',
|
||||||
|
'Luke Campagnola', 'manual'),
|
||||||
|
]
|
||||||
|
|
||||||
|
# The name of an image file (relative to this directory) to place at the top of
|
||||||
|
# the title page.
|
||||||
|
#latex_logo = None
|
||||||
|
|
||||||
|
# For "manual" documents, if this is true, then toplevel headings are parts,
|
||||||
|
# not chapters.
|
||||||
|
#latex_use_parts = False
|
||||||
|
|
||||||
|
# If true, show page references after internal links.
|
||||||
|
#latex_show_pagerefs = False
|
||||||
|
|
||||||
|
# If true, show URL addresses after external links.
|
||||||
|
#latex_show_urls = False
|
||||||
|
|
||||||
|
# Additional stuff for the LaTeX preamble.
|
||||||
|
#latex_preamble = ''
|
||||||
|
|
||||||
|
# Documents to append as an appendix to all manuals.
|
||||||
|
#latex_appendices = []
|
||||||
|
|
||||||
|
# If false, no module index is generated.
|
||||||
|
#latex_domain_indices = True
|
||||||
|
|
||||||
|
|
||||||
|
# -- Options for manual page output --------------------------------------------
|
||||||
|
|
||||||
|
# One entry per manual page. List of tuples
|
||||||
|
# (source start file, name, description, authors, manual section).
|
||||||
|
man_pages = [
|
||||||
|
('index', 'pyqtgraph', 'pyqtgraph Documentation',
|
||||||
|
['Luke Campagnola'], 1)
|
||||||
|
]
|
100
doc/source/functions.rst
Normal file
100
doc/source/functions.rst
Normal file
@ -0,0 +1,100 @@
|
|||||||
|
Pyqtgraph's Helper Functions
|
||||||
|
============================
|
||||||
|
|
||||||
|
Simple Data Display Functions
|
||||||
|
-----------------------------
|
||||||
|
|
||||||
|
.. autofunction:: pyqtgraph.plot
|
||||||
|
|
||||||
|
.. autofunction:: pyqtgraph.image
|
||||||
|
|
||||||
|
.. autofunction:: pyqtgraph.dbg
|
||||||
|
|
||||||
|
Color, Pen, and Brush Functions
|
||||||
|
-------------------------------
|
||||||
|
|
||||||
|
Qt uses the classes QColor, QPen, and QBrush to determine how to draw lines and fill shapes. These classes are highly capable but somewhat awkward to use. Pyqtgraph offers the functions :func:`~pyqtgraph.mkColor`, :func:`~pyqtgraph.mkPen`, and :func:`~pyqtgraph.mkBrush` to simplify the process of creating these classes. In most cases, however, it will be unnecessary to call these functions directly--any function or method that accepts *pen* or *brush* arguments will make use of these functions for you. For example, the following three lines all have the same effect::
|
||||||
|
|
||||||
|
pg.plot(xdata, ydata, pen='r')
|
||||||
|
pg.plot(xdata, ydata, pen=pg.mkPen('r'))
|
||||||
|
pg.plot(xdata, ydata, pen=QPen(QColor(255, 0, 0)))
|
||||||
|
|
||||||
|
|
||||||
|
.. autofunction:: pyqtgraph.mkColor
|
||||||
|
|
||||||
|
.. autofunction:: pyqtgraph.mkPen
|
||||||
|
|
||||||
|
.. autofunction:: pyqtgraph.mkBrush
|
||||||
|
|
||||||
|
.. autofunction:: pyqtgraph.hsvColor
|
||||||
|
|
||||||
|
.. autofunction:: pyqtgraph.intColor
|
||||||
|
|
||||||
|
.. autofunction:: pyqtgraph.colorTuple
|
||||||
|
|
||||||
|
.. autofunction:: pyqtgraph.colorStr
|
||||||
|
|
||||||
|
.. autofunction:: pyqtgraph.glColor
|
||||||
|
|
||||||
|
|
||||||
|
Data Slicing
|
||||||
|
------------
|
||||||
|
|
||||||
|
.. autofunction:: pyqtgraph.affineSlice
|
||||||
|
|
||||||
|
|
||||||
|
Coordinate Transformation
|
||||||
|
-------------------------
|
||||||
|
|
||||||
|
.. autofunction:: pyqtgraph.transformToArray
|
||||||
|
|
||||||
|
.. autofunction:: pyqtgraph.transformCoordinates
|
||||||
|
|
||||||
|
.. autofunction:: pyqtgraph.solve3DTransform
|
||||||
|
|
||||||
|
.. autofunction:: pyqtgraph.solveBilinearTransform
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
SI Unit Conversion Functions
|
||||||
|
----------------------------
|
||||||
|
|
||||||
|
.. autofunction:: pyqtgraph.siFormat
|
||||||
|
|
||||||
|
.. autofunction:: pyqtgraph.siScale
|
||||||
|
|
||||||
|
.. autofunction:: pyqtgraph.siEval
|
||||||
|
|
||||||
|
|
||||||
|
Image Preparation Functions
|
||||||
|
---------------------------
|
||||||
|
|
||||||
|
.. autofunction:: pyqtgraph.makeARGB
|
||||||
|
|
||||||
|
.. autofunction:: pyqtgraph.makeQImage
|
||||||
|
|
||||||
|
.. autofunction:: pyqtgraph.applyLookupTable
|
||||||
|
|
||||||
|
.. autofunction:: pyqtgraph.rescaleData
|
||||||
|
|
||||||
|
.. autofunction:: pyqtgraph.imageToArray
|
||||||
|
|
||||||
|
|
||||||
|
Mesh Generation Functions
|
||||||
|
-------------------------
|
||||||
|
|
||||||
|
.. autofunction:: pyqtgraph.isocurve
|
||||||
|
|
||||||
|
.. autofunction:: pyqtgraph.isosurface
|
||||||
|
|
||||||
|
|
||||||
|
Miscellaneous Functions
|
||||||
|
-----------------------
|
||||||
|
|
||||||
|
.. autofunction:: pyqtgraph.pseudoScatter
|
||||||
|
|
||||||
|
.. autofunction:: pyqtgraph.systemInfo
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
8
doc/source/graphicsItems/arrowitem.rst
Normal file
8
doc/source/graphicsItems/arrowitem.rst
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
ArrowItem
|
||||||
|
=========
|
||||||
|
|
||||||
|
.. autoclass:: pyqtgraph.ArrowItem
|
||||||
|
:members:
|
||||||
|
|
||||||
|
.. automethod:: pyqtgraph.ArrowItem.__init__
|
||||||
|
|
8
doc/source/graphicsItems/axisitem.rst
Normal file
8
doc/source/graphicsItems/axisitem.rst
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
AxisItem
|
||||||
|
========
|
||||||
|
|
||||||
|
.. autoclass:: pyqtgraph.AxisItem
|
||||||
|
:members:
|
||||||
|
|
||||||
|
.. automethod:: pyqtgraph.AxisItem.__init__
|
||||||
|
|
8
doc/source/graphicsItems/buttonitem.rst
Normal file
8
doc/source/graphicsItems/buttonitem.rst
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
ButtonItem
|
||||||
|
==========
|
||||||
|
|
||||||
|
.. autoclass:: pyqtgraph.ButtonItem
|
||||||
|
:members:
|
||||||
|
|
||||||
|
.. automethod:: pyqtgraph.ButtonItem.__init__
|
||||||
|
|
8
doc/source/graphicsItems/curvearrow.rst
Normal file
8
doc/source/graphicsItems/curvearrow.rst
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
CurveArrow
|
||||||
|
==========
|
||||||
|
|
||||||
|
.. autoclass:: pyqtgraph.CurveArrow
|
||||||
|
:members:
|
||||||
|
|
||||||
|
.. automethod:: pyqtgraph.CurveArrow.__init__
|
||||||
|
|
8
doc/source/graphicsItems/curvepoint.rst
Normal file
8
doc/source/graphicsItems/curvepoint.rst
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
CurvePoint
|
||||||
|
==========
|
||||||
|
|
||||||
|
.. autoclass:: pyqtgraph.CurvePoint
|
||||||
|
:members:
|
||||||
|
|
||||||
|
.. automethod:: pyqtgraph.CurvePoint.__init__
|
||||||
|
|
8
doc/source/graphicsItems/fillbetweenitem.rst
Normal file
8
doc/source/graphicsItems/fillbetweenitem.rst
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
FillBetweenItem
|
||||||
|
===============
|
||||||
|
|
||||||
|
.. autoclass:: pyqtgraph.FillBetweenItem
|
||||||
|
:members:
|
||||||
|
|
||||||
|
.. automethod:: pyqtgraph.FillBetweenItem.__init__
|
||||||
|
|
19
doc/source/graphicsItems/gradienteditoritem.rst
Normal file
19
doc/source/graphicsItems/gradienteditoritem.rst
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
GradientEditorItem
|
||||||
|
==================
|
||||||
|
|
||||||
|
.. autoclass:: pyqtgraph.GradientEditorItem
|
||||||
|
:members:
|
||||||
|
|
||||||
|
.. automethod:: pyqtgraph.GradientEditorItem.__init__
|
||||||
|
|
||||||
|
|
||||||
|
TickSliderItem
|
||||||
|
==================
|
||||||
|
|
||||||
|
.. autoclass:: pyqtgraph.TickSliderItem
|
||||||
|
:members:
|
||||||
|
|
||||||
|
.. automethod:: pyqtgraph.TickSliderItem.__init__
|
||||||
|
|
||||||
|
|
||||||
|
|
8
doc/source/graphicsItems/gradientlegend.rst
Normal file
8
doc/source/graphicsItems/gradientlegend.rst
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
GradientLegend
|
||||||
|
==============
|
||||||
|
|
||||||
|
.. autoclass:: pyqtgraph.GradientLegend
|
||||||
|
:members:
|
||||||
|
|
||||||
|
.. automethod:: pyqtgraph.GradientLegend.__init__
|
||||||
|
|
6
doc/source/graphicsItems/graphicsitem.rst
Normal file
6
doc/source/graphicsItems/graphicsitem.rst
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
GraphicsItem
|
||||||
|
============
|
||||||
|
|
||||||
|
.. autoclass:: pyqtgraph.GraphicsItem
|
||||||
|
:members:
|
||||||
|
|
8
doc/source/graphicsItems/graphicslayout.rst
Normal file
8
doc/source/graphicsItems/graphicslayout.rst
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
GraphicsLayout
|
||||||
|
==============
|
||||||
|
|
||||||
|
.. autoclass:: pyqtgraph.GraphicsLayout
|
||||||
|
:members:
|
||||||
|
|
||||||
|
.. automethod:: pyqtgraph.GraphicsLayout.__init__
|
||||||
|
|
8
doc/source/graphicsItems/graphicsobject.rst
Normal file
8
doc/source/graphicsItems/graphicsobject.rst
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
GraphicsObject
|
||||||
|
==============
|
||||||
|
|
||||||
|
.. autoclass:: pyqtgraph.GraphicsObject
|
||||||
|
:members:
|
||||||
|
|
||||||
|
.. automethod:: pyqtgraph.GraphicsObject.__init__
|
||||||
|
|
8
doc/source/graphicsItems/graphicswidget.rst
Normal file
8
doc/source/graphicsItems/graphicswidget.rst
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
GraphicsWidget
|
||||||
|
==============
|
||||||
|
|
||||||
|
.. autoclass:: pyqtgraph.GraphicsWidget
|
||||||
|
:members:
|
||||||
|
|
||||||
|
.. automethod:: pyqtgraph.GraphicsWidget.__init__
|
||||||
|
|
8
doc/source/graphicsItems/graphicswidgetanchor.rst
Normal file
8
doc/source/graphicsItems/graphicswidgetanchor.rst
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
GraphicsWidgetAnchor
|
||||||
|
====================
|
||||||
|
|
||||||
|
.. autoclass:: pyqtgraph.GraphicsWidgetAnchor
|
||||||
|
:members:
|
||||||
|
|
||||||
|
.. automethod:: pyqtgraph.GraphicsWidgetAnchor.__init__
|
||||||
|
|
8
doc/source/graphicsItems/griditem.rst
Normal file
8
doc/source/graphicsItems/griditem.rst
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
GridItem
|
||||||
|
========
|
||||||
|
|
||||||
|
.. autoclass:: pyqtgraph.GridItem
|
||||||
|
:members:
|
||||||
|
|
||||||
|
.. automethod:: pyqtgraph.GridItem.__init__
|
||||||
|
|
8
doc/source/graphicsItems/histogramlutitem.rst
Normal file
8
doc/source/graphicsItems/histogramlutitem.rst
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
HistogramLUTItem
|
||||||
|
================
|
||||||
|
|
||||||
|
.. autoclass:: pyqtgraph.HistogramLUTItem
|
||||||
|
:members:
|
||||||
|
|
||||||
|
.. automethod:: pyqtgraph.HistogramLUTItem.__init__
|
||||||
|
|
8
doc/source/graphicsItems/imageitem.rst
Normal file
8
doc/source/graphicsItems/imageitem.rst
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
ImageItem
|
||||||
|
=========
|
||||||
|
|
||||||
|
.. autoclass:: pyqtgraph.ImageItem
|
||||||
|
:members:
|
||||||
|
|
||||||
|
.. automethod:: pyqtgraph.ImageItem.__init__
|
||||||
|
|
43
doc/source/graphicsItems/index.rst
Normal file
43
doc/source/graphicsItems/index.rst
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
Pyqtgraph's Graphics Items
|
||||||
|
==========================
|
||||||
|
|
||||||
|
Since pyqtgraph relies on Qt's GraphicsView framework, most of its graphics functionality is implemented as QGraphicsItem subclasses. This has two important consequences: 1) virtually anything you want to draw can be easily accomplished using the functionality provided by Qt. 2) Many of pyqtgraph's GraphicsItem classes can be used in any normal QGraphicsScene.
|
||||||
|
|
||||||
|
|
||||||
|
Contents:
|
||||||
|
|
||||||
|
.. toctree::
|
||||||
|
:maxdepth: 2
|
||||||
|
|
||||||
|
plotdataitem
|
||||||
|
plotitem
|
||||||
|
imageitem
|
||||||
|
viewbox
|
||||||
|
linearregionitem
|
||||||
|
infiniteline
|
||||||
|
roi
|
||||||
|
graphicslayout
|
||||||
|
plotcurveitem
|
||||||
|
scatterplotitem
|
||||||
|
isocurveitem
|
||||||
|
axisitem
|
||||||
|
textitem
|
||||||
|
arrowitem
|
||||||
|
fillbetweenitem
|
||||||
|
curvepoint
|
||||||
|
curvearrow
|
||||||
|
griditem
|
||||||
|
scalebar
|
||||||
|
labelitem
|
||||||
|
vtickgroup
|
||||||
|
legenditem
|
||||||
|
gradienteditoritem
|
||||||
|
histogramlutitem
|
||||||
|
gradientlegend
|
||||||
|
buttonitem
|
||||||
|
graphicsobject
|
||||||
|
graphicswidget
|
||||||
|
graphicsitem
|
||||||
|
uigraphicsitem
|
||||||
|
graphicswidgetanchor
|
||||||
|
|
8
doc/source/graphicsItems/infiniteline.rst
Normal file
8
doc/source/graphicsItems/infiniteline.rst
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
InfiniteLine
|
||||||
|
============
|
||||||
|
|
||||||
|
.. autoclass:: pyqtgraph.InfiniteLine
|
||||||
|
:members:
|
||||||
|
|
||||||
|
.. automethod:: pyqtgraph.InfiniteLine.__init__
|
||||||
|
|
7
doc/source/graphicsItems/isocurveitem.rst
Normal file
7
doc/source/graphicsItems/isocurveitem.rst
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
IsocurveItem
|
||||||
|
============
|
||||||
|
|
||||||
|
.. autoclass:: pyqtgraph.IsocurveItem
|
||||||
|
:members:
|
||||||
|
|
||||||
|
.. automethod:: pyqtgraph.IsocurveItem.__init__
|
8
doc/source/graphicsItems/labelitem.rst
Normal file
8
doc/source/graphicsItems/labelitem.rst
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
LabelItem
|
||||||
|
=========
|
||||||
|
|
||||||
|
.. autoclass:: pyqtgraph.LabelItem
|
||||||
|
:members:
|
||||||
|
|
||||||
|
.. automethod:: pyqtgraph.LabelItem.__init__
|
||||||
|
|
8
doc/source/graphicsItems/legenditem.rst
Normal file
8
doc/source/graphicsItems/legenditem.rst
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
LegendItem
|
||||||
|
==========
|
||||||
|
|
||||||
|
.. autoclass:: pyqtgraph.LegendItem
|
||||||
|
:members:
|
||||||
|
|
||||||
|
.. automethod:: pyqtgraph.LegendItem.__init__
|
||||||
|
|
8
doc/source/graphicsItems/linearregionitem.rst
Normal file
8
doc/source/graphicsItems/linearregionitem.rst
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
LinearRegionItem
|
||||||
|
================
|
||||||
|
|
||||||
|
.. autoclass:: pyqtgraph.LinearRegionItem
|
||||||
|
:members:
|
||||||
|
|
||||||
|
.. automethod:: pyqtgraph.LinearRegionItem.__init__
|
||||||
|
|
37
doc/source/graphicsItems/make
Normal file
37
doc/source/graphicsItems/make
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
files = """ArrowItem
|
||||||
|
AxisItem
|
||||||
|
ButtonItem
|
||||||
|
CurvePoint
|
||||||
|
GradientEditorItem
|
||||||
|
GradientLegend
|
||||||
|
GraphicsLayout
|
||||||
|
GraphicsObject
|
||||||
|
GraphicsWidget
|
||||||
|
GridItem
|
||||||
|
HistogramLUTItem
|
||||||
|
ImageItem
|
||||||
|
InfiniteLine
|
||||||
|
LabelItem
|
||||||
|
LinearRegionItem
|
||||||
|
PlotCurveItem
|
||||||
|
PlotDataItem
|
||||||
|
ROI
|
||||||
|
ScaleBar
|
||||||
|
ScatterPlotItem
|
||||||
|
UIGraphicsItem
|
||||||
|
ViewBox
|
||||||
|
VTickGroup""".split('\n')
|
||||||
|
|
||||||
|
for f in files:
|
||||||
|
print f
|
||||||
|
fh = open(f.lower()+'.rst', 'w')
|
||||||
|
fh.write(
|
||||||
|
"""%s
|
||||||
|
%s
|
||||||
|
|
||||||
|
.. autoclass:: pyqtgraph.%s
|
||||||
|
:members:
|
||||||
|
|
||||||
|
.. automethod:: pyqtgraph.%s.__init__
|
||||||
|
|
||||||
|
""" % (f, '='*len(f), f, f))
|
8
doc/source/graphicsItems/plotcurveitem.rst
Normal file
8
doc/source/graphicsItems/plotcurveitem.rst
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
PlotCurveItem
|
||||||
|
=============
|
||||||
|
|
||||||
|
.. autoclass:: pyqtgraph.PlotCurveItem
|
||||||
|
:members:
|
||||||
|
|
||||||
|
.. automethod:: pyqtgraph.PlotCurveItem.__init__
|
||||||
|
|
8
doc/source/graphicsItems/plotdataitem.rst
Normal file
8
doc/source/graphicsItems/plotdataitem.rst
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
PlotDataItem
|
||||||
|
============
|
||||||
|
|
||||||
|
.. autoclass:: pyqtgraph.PlotDataItem
|
||||||
|
:members:
|
||||||
|
|
||||||
|
.. automethod:: pyqtgraph.PlotDataItem.__init__
|
||||||
|
|
7
doc/source/graphicsItems/plotitem.rst
Normal file
7
doc/source/graphicsItems/plotitem.rst
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
PlotItem
|
||||||
|
========
|
||||||
|
|
||||||
|
.. autoclass:: pyqtgraph.PlotItem()
|
||||||
|
:members:
|
||||||
|
|
||||||
|
.. automethod:: pyqtgraph.PlotItem.__init__
|
8
doc/source/graphicsItems/roi.rst
Normal file
8
doc/source/graphicsItems/roi.rst
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
ROI
|
||||||
|
===
|
||||||
|
|
||||||
|
.. autoclass:: pyqtgraph.ROI
|
||||||
|
:members:
|
||||||
|
|
||||||
|
.. automethod:: pyqtgraph.ROI.__init__
|
||||||
|
|
8
doc/source/graphicsItems/scalebar.rst
Normal file
8
doc/source/graphicsItems/scalebar.rst
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
ScaleBar
|
||||||
|
========
|
||||||
|
|
||||||
|
.. autoclass:: pyqtgraph.ScaleBar
|
||||||
|
:members:
|
||||||
|
|
||||||
|
.. automethod:: pyqtgraph.ScaleBar.__init__
|
||||||
|
|
8
doc/source/graphicsItems/scatterplotitem.rst
Normal file
8
doc/source/graphicsItems/scatterplotitem.rst
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
ScatterPlotItem
|
||||||
|
===============
|
||||||
|
|
||||||
|
.. autoclass:: pyqtgraph.ScatterPlotItem
|
||||||
|
:members:
|
||||||
|
|
||||||
|
.. automethod:: pyqtgraph.ScatterPlotItem.__init__
|
||||||
|
|
8
doc/source/graphicsItems/textitem.rst
Normal file
8
doc/source/graphicsItems/textitem.rst
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
TextItem
|
||||||
|
========
|
||||||
|
|
||||||
|
.. autoclass:: pyqtgraph.TextItem
|
||||||
|
:members:
|
||||||
|
|
||||||
|
.. automethod:: pyqtgraph.TextItem.__init__
|
||||||
|
|
8
doc/source/graphicsItems/uigraphicsitem.rst
Normal file
8
doc/source/graphicsItems/uigraphicsitem.rst
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
UIGraphicsItem
|
||||||
|
==============
|
||||||
|
|
||||||
|
.. autoclass:: pyqtgraph.UIGraphicsItem
|
||||||
|
:members:
|
||||||
|
|
||||||
|
.. automethod:: pyqtgraph.UIGraphicsItem.__init__
|
||||||
|
|
8
doc/source/graphicsItems/viewbox.rst
Normal file
8
doc/source/graphicsItems/viewbox.rst
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
ViewBox
|
||||||
|
=======
|
||||||
|
|
||||||
|
.. autoclass:: pyqtgraph.ViewBox
|
||||||
|
:members:
|
||||||
|
|
||||||
|
.. automethod:: pyqtgraph.ViewBox.__init__
|
||||||
|
|
8
doc/source/graphicsItems/vtickgroup.rst
Normal file
8
doc/source/graphicsItems/vtickgroup.rst
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
VTickGroup
|
||||||
|
==========
|
||||||
|
|
||||||
|
.. autoclass:: pyqtgraph.VTickGroup
|
||||||
|
:members:
|
||||||
|
|
||||||
|
.. automethod:: pyqtgraph.VTickGroup.__init__
|
||||||
|
|
8
doc/source/graphicsscene/graphicsscene.rst
Normal file
8
doc/source/graphicsscene/graphicsscene.rst
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
GraphicsScene
|
||||||
|
=============
|
||||||
|
|
||||||
|
.. autoclass:: pyqtgraph.GraphicsScene
|
||||||
|
:members:
|
||||||
|
|
||||||
|
.. automethod:: pyqtgraph.GraphicsScene.__init__
|
||||||
|
|
5
doc/source/graphicsscene/hoverevent.rst
Normal file
5
doc/source/graphicsscene/hoverevent.rst
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
HoverEvent
|
||||||
|
==========
|
||||||
|
|
||||||
|
.. autoclass:: pyqtgraph.GraphicsScene.mouseEvents.HoverEvent
|
||||||
|
:members:
|
12
doc/source/graphicsscene/index.rst
Normal file
12
doc/source/graphicsscene/index.rst
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
GraphicsScene and Mouse Events
|
||||||
|
==============================
|
||||||
|
|
||||||
|
Contents:
|
||||||
|
|
||||||
|
.. toctree::
|
||||||
|
:maxdepth: 2
|
||||||
|
|
||||||
|
graphicsscene
|
||||||
|
hoverevent
|
||||||
|
mouseclickevent
|
||||||
|
mousedragevent
|
5
doc/source/graphicsscene/mouseclickevent.rst
Normal file
5
doc/source/graphicsscene/mouseclickevent.rst
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
MouseClickEvent
|
||||||
|
===============
|
||||||
|
|
||||||
|
.. autoclass:: pyqtgraph.GraphicsScene.mouseEvents.MouseClickEvent
|
||||||
|
:members:
|
5
doc/source/graphicsscene/mousedragevent.rst
Normal file
5
doc/source/graphicsscene/mousedragevent.rst
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
MouseDragEvent
|
||||||
|
==============
|
||||||
|
|
||||||
|
.. autoclass:: pyqtgraph.GraphicsScene.mouseEvents.MouseDragEvent
|
||||||
|
:members:
|
8
doc/source/graphicswindow.rst
Normal file
8
doc/source/graphicswindow.rst
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
Basic display widgets
|
||||||
|
=====================
|
||||||
|
|
||||||
|
- GraphicsWindow
|
||||||
|
- GraphicsView
|
||||||
|
- GraphicsLayoutItem
|
||||||
|
- ViewBox
|
||||||
|
|
73
doc/source/how_to_use.rst
Normal file
73
doc/source/how_to_use.rst
Normal file
@ -0,0 +1,73 @@
|
|||||||
|
How to use pyqtgraph
|
||||||
|
====================
|
||||||
|
|
||||||
|
There are a few suggested ways to use pyqtgraph:
|
||||||
|
|
||||||
|
* From the interactive shell (python -i, ipython, etc)
|
||||||
|
* Displaying pop-up windows from an application
|
||||||
|
* Embedding widgets in a PyQt application
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Command-line use
|
||||||
|
----------------
|
||||||
|
|
||||||
|
Pyqtgraph makes it very easy to visualize data from the command line. Observe::
|
||||||
|
|
||||||
|
import pyqtgraph as pg
|
||||||
|
pg.plot(data) # data can be a list of values or a numpy array
|
||||||
|
|
||||||
|
The example above would open a window displaying a line plot of the data given. The call to :func:`pg.plot <pyqtgraph.plot>` returns a handle to the :class:`plot widget <pyqtgraph.PlotWidget>` that is created, allowing more data to be added to the same window.
|
||||||
|
|
||||||
|
Further examples::
|
||||||
|
|
||||||
|
pw = pg.plot(xVals, yVals, pen='r') # plot x vs y in red
|
||||||
|
pw.plot(xVals, yVals2, pen='b')
|
||||||
|
|
||||||
|
win = pg.GraphicsWindow() # Automatically generates grids with multiple items
|
||||||
|
win.addPlot(data1, row=0, col=0)
|
||||||
|
win.addPlot(data2, row=0, col=1)
|
||||||
|
win.addPlot(data3, row=1, col=0, colspan=2)
|
||||||
|
|
||||||
|
pg.show(imageData) # imageData must be a numpy array with 2 to 4 dimensions
|
||||||
|
|
||||||
|
We're only scratching the surface here--these functions accept many different data formats and options for customizing the appearance of your data.
|
||||||
|
|
||||||
|
|
||||||
|
Displaying windows from within an application
|
||||||
|
---------------------------------------------
|
||||||
|
|
||||||
|
While I consider this approach somewhat lazy, it is often the case that 'lazy' is indistinguishable from 'highly efficient'. The approach here is simply to use the very same functions that would be used on the command line, but from within an existing application. I often use this when I simply want to get a immediate feedback about the state of data in my application without taking the time to build a user interface for it.
|
||||||
|
|
||||||
|
|
||||||
|
Embedding widgets inside PyQt applications
|
||||||
|
------------------------------------------
|
||||||
|
|
||||||
|
For the serious application developer, all of the functionality in pyqtgraph is available via :ref:`widgets <api_widgets>` that can be embedded just like any other Qt widgets. Most importantly, see: :class:`PlotWidget <pyqtgraph.PlotWidget>`, :class:`ImageView <pyqtgraph.ImageView>`, :class:`GraphicsLayoutWidget <pyqtgraph.GraphicsLayoutWidget>`, and :class:`GraphicsView <pyqtgraph.GraphicsView>`. Pyqtgraph's widgets can be included in Designer's ui files via the "Promote To..." functionality:
|
||||||
|
|
||||||
|
#. In Designer, create a QGraphicsView widget ("Graphics View" under the "Display Widgets" category).
|
||||||
|
#. Right-click on the QGraphicsView and select "Promote To...".
|
||||||
|
#. Under "Promoted class name", enter the class name you wish to use ("PlotWidget", "GraphicsLayoutWidget", etc).
|
||||||
|
#. Under "Header file", enter "pyqtgraph".
|
||||||
|
#. Click "Add", then click "Promote".
|
||||||
|
|
||||||
|
See the designer documentation for more information on promoting widgets.
|
||||||
|
|
||||||
|
|
||||||
|
PyQt and PySide
|
||||||
|
---------------
|
||||||
|
|
||||||
|
Pyqtgraph supports two popular python wrappers for the Qt library: PyQt and PySide. Both packages provide nearly identical
|
||||||
|
APIs and functionality, but for various reasons (discussed elsewhere) you may prefer to use one package or the other. When
|
||||||
|
pyqtgraph is first imported, it automatically determines which library to use by making the fillowing checks:
|
||||||
|
|
||||||
|
#. If PyQt4 is already imported, use that
|
||||||
|
#. Else, if PySide is already imported, use that
|
||||||
|
#. Else, attempt to import PyQt4
|
||||||
|
#. If that import fails, attempt to import PySide.
|
||||||
|
|
||||||
|
If you have both libraries installed on your system and you wish to force pyqtgraph to use one or the other, simply
|
||||||
|
make sure it is imported before pyqtgraph::
|
||||||
|
|
||||||
|
import PySide ## this will force pyqtgraph to use PySide instead of PyQt4
|
||||||
|
import pyqtgraph as pg
|
26
doc/source/images.rst
Normal file
26
doc/source/images.rst
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
Displaying images and video
|
||||||
|
===========================
|
||||||
|
|
||||||
|
Pyqtgraph displays 2D numpy arrays as images and provides tools for determining how to translate between the numpy data type and RGB values on the screen. If you want to display data from common image and video file formats, you will need to load the data first using another library (PIL works well for images and built-in numpy conversion).
|
||||||
|
|
||||||
|
The easiest way to display 2D or 3D data is using the :func:`pyqtgraph.image` function::
|
||||||
|
|
||||||
|
import pyqtgraph as pg
|
||||||
|
pg.image(imageData)
|
||||||
|
|
||||||
|
This function will accept any floating-point or integer data types and displays a single :class:`~pyqtgraph.ImageView` widget containing your data. This widget includes controls for determining how the image data will be converted to 32-bit RGBa values. Conversion happens in two steps (both are optional):
|
||||||
|
|
||||||
|
1. Scale and offset the data (by selecting the dark/light levels on the displayed histogram)
|
||||||
|
2. Convert the data to color using a lookup table (determined by the colors shown in the gradient editor)
|
||||||
|
|
||||||
|
If the data is 3D (time, x, y), then a time axis will be shown with a slider that can set the currently displayed frame. (if the axes in your data are ordered differently, use numpy.transpose to rearrange them)
|
||||||
|
|
||||||
|
There are a few other methods for displaying images as well:
|
||||||
|
|
||||||
|
* The :class:`~pyqtgraph.ImageView` class can also be instantiated directly and embedded in Qt applications.
|
||||||
|
* Instances of :class:`~pyqtgraph.ImageItem` can be used inside a :class:`ViewBox <pyqtgraph.ViewBox>` or :class:`GraphicsView <pyqtgraph.GraphicsView>`.
|
||||||
|
* For higher performance, use :class:`~pyqtgraph.RawImageWidget`.
|
||||||
|
|
||||||
|
Any of these classes are acceptable for displaying video by calling setImage() to display a new frame. To increase performance, the image processing system uses scipy.weave to produce compiled libraries. If your computer has a compiler available, weave will automatically attempt to build the libraries it needs on demand. If this fails, then the slower pure-python methods will be used instead.
|
||||||
|
|
||||||
|
For more information, see the classes listed above and the 'VideoSpeedTest', 'ImageItem', 'ImageView', and 'HistogramLUT' :ref:`examples`.
|
BIN
doc/source/images/plottingClasses.png
Normal file
BIN
doc/source/images/plottingClasses.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 67 KiB |
580
doc/source/images/plottingClasses.svg
Normal file
580
doc/source/images/plottingClasses.svg
Normal file
@ -0,0 +1,580 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||||
|
|
||||||
|
<svg
|
||||||
|
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||||
|
xmlns:cc="http://creativecommons.org/ns#"
|
||||||
|
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||||
|
xmlns:svg="http://www.w3.org/2000/svg"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||||
|
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||||
|
width="648.03278"
|
||||||
|
height="268.51233"
|
||||||
|
id="svg2"
|
||||||
|
version="1.1"
|
||||||
|
inkscape:version="0.48.1 r9760"
|
||||||
|
sodipodi:docname="plottingClasses.svg"
|
||||||
|
inkscape:export-filename="/home/luke/work/manis_lab/code/pyqtgraph/documentation/source/images/plottingClasses.png"
|
||||||
|
inkscape:export-xdpi="124.99"
|
||||||
|
inkscape:export-ydpi="124.99">
|
||||||
|
<defs
|
||||||
|
id="defs4">
|
||||||
|
<filter
|
||||||
|
inkscape:collect="always"
|
||||||
|
id="filter4029"
|
||||||
|
color-interpolation-filters="sRGB">
|
||||||
|
<feGaussianBlur
|
||||||
|
inkscape:collect="always"
|
||||||
|
stdDeviation="3.3898323"
|
||||||
|
id="feGaussianBlur4031" />
|
||||||
|
</filter>
|
||||||
|
<filter
|
||||||
|
color-interpolation-filters="sRGB"
|
||||||
|
inkscape:collect="always"
|
||||||
|
id="filter4029-0">
|
||||||
|
<feGaussianBlur
|
||||||
|
inkscape:collect="always"
|
||||||
|
stdDeviation="3.3898323"
|
||||||
|
id="feGaussianBlur4031-5" />
|
||||||
|
</filter>
|
||||||
|
</defs>
|
||||||
|
<sodipodi:namedview
|
||||||
|
id="base"
|
||||||
|
pagecolor="#ffffff"
|
||||||
|
bordercolor="#666666"
|
||||||
|
borderopacity="1.0"
|
||||||
|
inkscape:pageopacity="0.0"
|
||||||
|
inkscape:pageshadow="2"
|
||||||
|
inkscape:zoom="1.4"
|
||||||
|
inkscape:cx="383.64946"
|
||||||
|
inkscape:cy="21.059243"
|
||||||
|
inkscape:document-units="px"
|
||||||
|
inkscape:current-layer="g3978"
|
||||||
|
showgrid="false"
|
||||||
|
inkscape:window-width="1400"
|
||||||
|
inkscape:window-height="1030"
|
||||||
|
inkscape:window-x="-3"
|
||||||
|
inkscape:window-y="-3"
|
||||||
|
inkscape:window-maximized="1"
|
||||||
|
fit-margin-top="0"
|
||||||
|
fit-margin-left="0"
|
||||||
|
fit-margin-right="0"
|
||||||
|
fit-margin-bottom="0" />
|
||||||
|
<metadata
|
||||||
|
id="metadata7">
|
||||||
|
<rdf:RDF>
|
||||||
|
<cc:Work
|
||||||
|
rdf:about="">
|
||||||
|
<dc:format>image/svg+xml</dc:format>
|
||||||
|
<dc:type
|
||||||
|
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||||
|
<dc:title></dc:title>
|
||||||
|
</cc:Work>
|
||||||
|
</rdf:RDF>
|
||||||
|
</metadata>
|
||||||
|
<g
|
||||||
|
inkscape:label="Layer 1"
|
||||||
|
inkscape:groupmode="layer"
|
||||||
|
id="layer1"
|
||||||
|
transform="translate(-9.6542608,-141.60496)">
|
||||||
|
<g
|
||||||
|
id="g3941"
|
||||||
|
transform="matrix(0.62675963,0,0,0.62675963,-43.966218,98.521874)">
|
||||||
|
<g
|
||||||
|
style="stroke-width:2;stroke-miterlimit:4;stroke-dasharray:none"
|
||||||
|
transform="translate(0,-258)"
|
||||||
|
id="g3765">
|
||||||
|
<rect
|
||||||
|
y="336.48514"
|
||||||
|
x="95.275459"
|
||||||
|
height="407.9704"
|
||||||
|
width="495.98489"
|
||||||
|
id="rect4003"
|
||||||
|
style="fill:#000000;fill-opacity:1;stroke:#000000;stroke-width:3.19101596;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;filter:url(#filter4029)" />
|
||||||
|
<rect
|
||||||
|
style="fill:#cecae4;fill-opacity:1;stroke:#000000;stroke-width:3.19101596;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
|
||||||
|
id="rect2985"
|
||||||
|
width="495.98489"
|
||||||
|
height="407.9704"
|
||||||
|
x="88.893425"
|
||||||
|
y="330.10312" />
|
||||||
|
<text
|
||||||
|
xml:space="preserve"
|
||||||
|
style="font-size:72px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Arial;-inkscape-font-specification:Arial"
|
||||||
|
x="91.923874"
|
||||||
|
y="348.28586"
|
||||||
|
id="text3755"
|
||||||
|
sodipodi:linespacing="125%"><tspan
|
||||||
|
sodipodi:role="line"
|
||||||
|
id="tspan3757"
|
||||||
|
x="91.923874"
|
||||||
|
y="348.28586"
|
||||||
|
style="font-size:20px">PlotWidget(GraphicsView)</tspan></text>
|
||||||
|
</g>
|
||||||
|
<g
|
||||||
|
transform="translate(3.0304576,-251.93908)"
|
||||||
|
id="g3770">
|
||||||
|
<rect
|
||||||
|
style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:1.59550798;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
|
||||||
|
id="rect3759"
|
||||||
|
width="450.52805"
|
||||||
|
height="361.871"
|
||||||
|
x="111.11678"
|
||||||
|
y="355.35693" />
|
||||||
|
<text
|
||||||
|
sodipodi:linespacing="125%"
|
||||||
|
id="text3761"
|
||||||
|
y="376.57013"
|
||||||
|
x="124.24876"
|
||||||
|
style="font-size:72px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Arial;-inkscape-font-specification:Arial"
|
||||||
|
xml:space="preserve"><tspan
|
||||||
|
style="font-size:18px"
|
||||||
|
y="376.57013"
|
||||||
|
x="124.24876"
|
||||||
|
id="tspan3763"
|
||||||
|
sodipodi:role="line">PlotItem(GraphicsItem)</tspan></text>
|
||||||
|
</g>
|
||||||
|
<g
|
||||||
|
id="g3777"
|
||||||
|
transform="translate(70.710678,-158.4213)">
|
||||||
|
<rect
|
||||||
|
y="355.35693"
|
||||||
|
x="111.11678"
|
||||||
|
height="226.27419"
|
||||||
|
width="314.15744"
|
||||||
|
id="rect3779"
|
||||||
|
style="fill:#d7d7d7;fill-opacity:1;stroke:#000000;stroke-width:1.59550798;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0" />
|
||||||
|
<text
|
||||||
|
xml:space="preserve"
|
||||||
|
style="font-size:16px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Arial;-inkscape-font-specification:Arial"
|
||||||
|
x="125.25891"
|
||||||
|
y="378.59042"
|
||||||
|
id="text3781"
|
||||||
|
sodipodi:linespacing="125%"><tspan
|
||||||
|
sodipodi:role="line"
|
||||||
|
id="tspan3783"
|
||||||
|
x="125.25891"
|
||||||
|
y="378.59042"
|
||||||
|
style="font-size:16px">ViewBox(GraphicsItem)</tspan></text>
|
||||||
|
<path
|
||||||
|
transform="translate(-39.395949,-44.446712)"
|
||||||
|
inkscape:connector-curvature="0"
|
||||||
|
id="path3789"
|
||||||
|
d="m 171.72593,536.17423 29.29443,-30.30457 28.28427,54.54823 22.22335,-34.34518 23.23351,24.24366 31.31473,-10.10153 27.27412,-34.34518 23.23351,-40.40611 23.23351,31.31473 36.36549,1.01016 19.1929,40.4061"
|
||||||
|
style="fill:none;stroke:#000000;stroke-width:1.59550798px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
|
||||||
|
</g>
|
||||||
|
<g
|
||||||
|
id="g3801"
|
||||||
|
transform="matrix(0,-1,1,0,-207.00664,541.37735)">
|
||||||
|
<rect
|
||||||
|
y="355.35693"
|
||||||
|
x="119.19801"
|
||||||
|
height="29.294403"
|
||||||
|
width="225.26402"
|
||||||
|
id="rect3803"
|
||||||
|
style="fill:#d7d7d7;fill-opacity:1;stroke:#000000;stroke-width:1.59550798;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0" />
|
||||||
|
<text
|
||||||
|
xml:space="preserve"
|
||||||
|
style="font-size:16px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Arial;-inkscape-font-specification:Arial"
|
||||||
|
x="150.59395"
|
||||||
|
y="374.5498"
|
||||||
|
id="text3805"
|
||||||
|
sodipodi:linespacing="125%"><tspan
|
||||||
|
sodipodi:role="line"
|
||||||
|
id="tspan3807"
|
||||||
|
x="150.59395"
|
||||||
|
y="374.5498"
|
||||||
|
style="font-size:16px">AxisItem(GraphicsItem)</tspan></text>
|
||||||
|
</g>
|
||||||
|
<g
|
||||||
|
id="g3809"
|
||||||
|
transform="translate(104.06602,-189.05576)">
|
||||||
|
<rect
|
||||||
|
y="355.35693"
|
||||||
|
x="77.781746"
|
||||||
|
height="26.85568"
|
||||||
|
width="313.26996"
|
||||||
|
id="rect3811"
|
||||||
|
style="fill:#d7d7d7;fill-opacity:1;stroke:#000000;stroke-width:1.59550798;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0" />
|
||||||
|
<text
|
||||||
|
xml:space="preserve"
|
||||||
|
style="font-size:16px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Arial;-inkscape-font-specification:Arial"
|
||||||
|
x="154.59395"
|
||||||
|
y="374.5498"
|
||||||
|
id="text3813"
|
||||||
|
sodipodi:linespacing="125%"><tspan
|
||||||
|
sodipodi:role="line"
|
||||||
|
id="tspan3815"
|
||||||
|
x="154.59395"
|
||||||
|
y="374.5498"
|
||||||
|
style="font-size:16px">AxisItem(GraphicsItem)</tspan></text>
|
||||||
|
</g>
|
||||||
|
<g
|
||||||
|
transform="translate(104.06602,72.94424)"
|
||||||
|
id="g3817">
|
||||||
|
<rect
|
||||||
|
style="fill:#d7d7d7;fill-opacity:1;stroke:#000000;stroke-width:1.59550798;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
|
||||||
|
id="rect3819"
|
||||||
|
width="313.26996"
|
||||||
|
height="26.85568"
|
||||||
|
x="77.781746"
|
||||||
|
y="355.35693" />
|
||||||
|
<text
|
||||||
|
sodipodi:linespacing="125%"
|
||||||
|
id="text3821"
|
||||||
|
y="374.5498"
|
||||||
|
x="154.59395"
|
||||||
|
style="font-size:16px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Arial;-inkscape-font-specification:Arial"
|
||||||
|
xml:space="preserve"><tspan
|
||||||
|
style="font-size:16px"
|
||||||
|
y="374.5498"
|
||||||
|
x="154.59395"
|
||||||
|
id="tspan3823"
|
||||||
|
sodipodi:role="line">AxisItem(GraphicsItem)</tspan></text>
|
||||||
|
</g>
|
||||||
|
<g
|
||||||
|
transform="matrix(0,-1,1,0,144.99336,541.37735)"
|
||||||
|
id="g3825">
|
||||||
|
<rect
|
||||||
|
style="fill:#d7d7d7;fill-opacity:1;stroke:#000000;stroke-width:1.59550798;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
|
||||||
|
id="rect3827"
|
||||||
|
width="225.26402"
|
||||||
|
height="29.294403"
|
||||||
|
x="119.19801"
|
||||||
|
y="355.35693" />
|
||||||
|
<text
|
||||||
|
sodipodi:linespacing="125%"
|
||||||
|
id="text3829"
|
||||||
|
y="374.5498"
|
||||||
|
x="150.59395"
|
||||||
|
style="font-size:16px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Arial;-inkscape-font-specification:Arial"
|
||||||
|
xml:space="preserve"><tspan
|
||||||
|
style="font-size:16px"
|
||||||
|
y="374.5498"
|
||||||
|
x="150.59395"
|
||||||
|
id="tspan3831"
|
||||||
|
sodipodi:role="line">AxisItem(GraphicsItem)</tspan></text>
|
||||||
|
</g>
|
||||||
|
<g
|
||||||
|
transform="translate(104.06602,-219.05576)"
|
||||||
|
id="g3833">
|
||||||
|
<rect
|
||||||
|
style="fill:#d7d7d7;fill-opacity:1;stroke:#000000;stroke-width:1.59550798;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
|
||||||
|
id="rect3835"
|
||||||
|
width="313.26996"
|
||||||
|
height="26.85568"
|
||||||
|
x="77.781746"
|
||||||
|
y="355.35693" />
|
||||||
|
<text
|
||||||
|
sodipodi:linespacing="125%"
|
||||||
|
id="text3837"
|
||||||
|
y="374.5498"
|
||||||
|
x="118.59395"
|
||||||
|
style="font-size:16px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Arial;-inkscape-font-specification:Arial"
|
||||||
|
xml:space="preserve"><tspan
|
||||||
|
style="font-size:16px"
|
||||||
|
y="374.5498"
|
||||||
|
x="118.59395"
|
||||||
|
id="tspan3839"
|
||||||
|
sodipodi:role="line">Title - LabelItem(GraphicsItem)</tspan></text>
|
||||||
|
</g>
|
||||||
|
<text
|
||||||
|
sodipodi:linespacing="125%"
|
||||||
|
id="text3879"
|
||||||
|
y="363.02704"
|
||||||
|
x="301.12698"
|
||||||
|
style="font-size:14px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Arial;-inkscape-font-specification:Arial"
|
||||||
|
xml:space="preserve"><tspan
|
||||||
|
y="363.02704"
|
||||||
|
x="301.12698"
|
||||||
|
id="tspan3881"
|
||||||
|
sodipodi:role="line">PlotDataItem(GraphicsItem)</tspan></text>
|
||||||
|
</g>
|
||||||
|
<g
|
||||||
|
id="g3978"
|
||||||
|
transform="matrix(0.62675963,0,0,0.62675963,280.29275,-190.12921)">
|
||||||
|
<rect
|
||||||
|
y="540.00317"
|
||||||
|
x="96.42733"
|
||||||
|
height="407.9704"
|
||||||
|
width="495.98489"
|
||||||
|
id="rect4003-9"
|
||||||
|
style="fill:#000000;fill-opacity:1;stroke:#000000;stroke-width:3.19101596;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;filter:url(#filter4029-0)" />
|
||||||
|
<g
|
||||||
|
transform="translate(0,202)"
|
||||||
|
id="g3883">
|
||||||
|
<rect
|
||||||
|
y="330.10312"
|
||||||
|
x="88.893425"
|
||||||
|
height="407.9704"
|
||||||
|
width="495.98489"
|
||||||
|
id="rect3885"
|
||||||
|
style="fill:#cecae4;fill-opacity:1;stroke:#000000;stroke-width:3.19101596;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0" />
|
||||||
|
<text
|
||||||
|
sodipodi:linespacing="125%"
|
||||||
|
id="text3887"
|
||||||
|
y="348.28586"
|
||||||
|
x="91.923874"
|
||||||
|
style="font-size:72px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Arial;-inkscape-font-specification:Arial"
|
||||||
|
xml:space="preserve"><tspan
|
||||||
|
style="font-size:20px"
|
||||||
|
y="348.28586"
|
||||||
|
x="91.923874"
|
||||||
|
id="tspan3889"
|
||||||
|
sodipodi:role="line">GraphicsLayoutWidget(GraphicsView)</tspan></text>
|
||||||
|
</g>
|
||||||
|
<g
|
||||||
|
id="g3891"
|
||||||
|
transform="translate(3.0304576,214.06092)">
|
||||||
|
<rect
|
||||||
|
y="355.35693"
|
||||||
|
x="111.11678"
|
||||||
|
height="361.871"
|
||||||
|
width="450.52805"
|
||||||
|
id="rect3893"
|
||||||
|
style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:1.59550798;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0" />
|
||||||
|
<text
|
||||||
|
xml:space="preserve"
|
||||||
|
style="font-size:72px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Arial;-inkscape-font-specification:Arial"
|
||||||
|
x="124.24876"
|
||||||
|
y="376.57013"
|
||||||
|
id="text3895"
|
||||||
|
sodipodi:linespacing="125%"><tspan
|
||||||
|
sodipodi:role="line"
|
||||||
|
id="tspan3897"
|
||||||
|
x="124.24876"
|
||||||
|
y="376.57013"
|
||||||
|
style="font-size:18px">GraphicsLayoutItem(GraphicsItem)</tspan></text>
|
||||||
|
</g>
|
||||||
|
<g
|
||||||
|
transform="translate(17.172593,259.49748)"
|
||||||
|
id="g3909">
|
||||||
|
<rect
|
||||||
|
style="fill:#d7d7d7;fill-opacity:1;stroke:#000000;stroke-width:1.59550798;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
|
||||||
|
id="rect3911"
|
||||||
|
width="199.00005"
|
||||||
|
height="144.45183"
|
||||||
|
x="111.11678"
|
||||||
|
y="355.35693" />
|
||||||
|
<text
|
||||||
|
sodipodi:linespacing="125%"
|
||||||
|
id="text3913"
|
||||||
|
y="378.59042"
|
||||||
|
x="125.25891"
|
||||||
|
style="font-size:16px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Arial;-inkscape-font-specification:Arial"
|
||||||
|
xml:space="preserve"><tspan
|
||||||
|
style="font-size:16px"
|
||||||
|
y="378.59042"
|
||||||
|
x="125.25891"
|
||||||
|
id="tspan3915"
|
||||||
|
sodipodi:role="line">PlotItem</tspan></text>
|
||||||
|
<g
|
||||||
|
transform="matrix(0.73495341,0,0,0.52372233,28.190975,147.93852)"
|
||||||
|
id="g4155"
|
||||||
|
style="opacity:0.21238936">
|
||||||
|
<g
|
||||||
|
transform="matrix(0.62675963,0,0,0.62675963,80.420081,271.29053)"
|
||||||
|
id="g3777-4">
|
||||||
|
<rect
|
||||||
|
style="fill:#d7d7d7;fill-opacity:1;stroke:#000000;stroke-width:4.10315084;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
|
||||||
|
id="rect3779-6"
|
||||||
|
width="314.15744"
|
||||||
|
height="226.27419"
|
||||||
|
x="111.11678"
|
||||||
|
y="355.35693" />
|
||||||
|
<path
|
||||||
|
style="fill:none;stroke:#000000;stroke-width:4.10315084px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||||
|
d="m 171.72593,536.17423 29.29443,-30.30457 28.28427,54.54823 22.22335,-34.34518 23.23351,24.24366 31.31473,-10.10153 27.27412,-34.34518 23.23351,-40.40611 23.23351,31.31473 36.36549,1.01016 19.1929,40.4061"
|
||||||
|
id="path3789-2"
|
||||||
|
inkscape:connector-curvature="0"
|
||||||
|
transform="translate(-39.395949,-44.446712)" />
|
||||||
|
</g>
|
||||||
|
<g
|
||||||
|
transform="matrix(0,-0.62675963,0.62675963,0,-93.641919,709.89607)"
|
||||||
|
id="g3801-4">
|
||||||
|
<rect
|
||||||
|
style="fill:#d7d7d7;fill-opacity:1;stroke:#000000;stroke-width:4.10315084;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
|
||||||
|
id="rect3803-7"
|
||||||
|
width="225.26402"
|
||||||
|
height="29.294403"
|
||||||
|
x="119.19801"
|
||||||
|
y="355.35693" />
|
||||||
|
</g>
|
||||||
|
<g
|
||||||
|
transform="matrix(0.62675963,0,0,0.62675963,101.32586,252.09009)"
|
||||||
|
id="g3809-4">
|
||||||
|
<rect
|
||||||
|
style="fill:#d7d7d7;fill-opacity:1;stroke:#000000;stroke-width:4.10315084;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
|
||||||
|
id="rect3811-8"
|
||||||
|
width="313.26996"
|
||||||
|
height="26.85568"
|
||||||
|
x="77.781746"
|
||||||
|
y="355.35693" />
|
||||||
|
</g>
|
||||||
|
<g
|
||||||
|
id="g3817-8"
|
||||||
|
transform="matrix(0.62675963,0,0,0.62675963,101.32586,416.30111)">
|
||||||
|
<rect
|
||||||
|
y="355.35693"
|
||||||
|
x="77.781746"
|
||||||
|
height="26.85568"
|
||||||
|
width="313.26996"
|
||||||
|
id="rect3819-9"
|
||||||
|
style="fill:#d7d7d7;fill-opacity:1;stroke:#000000;stroke-width:4.10315084;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0" />
|
||||||
|
</g>
|
||||||
|
<g
|
||||||
|
id="g3825-8"
|
||||||
|
transform="matrix(0,-0.62675963,0.62675963,0,126.97747,709.89607)">
|
||||||
|
<rect
|
||||||
|
y="355.35693"
|
||||||
|
x="119.19801"
|
||||||
|
height="29.294403"
|
||||||
|
width="225.26402"
|
||||||
|
id="rect3827-0"
|
||||||
|
style="fill:#d7d7d7;fill-opacity:1;stroke:#000000;stroke-width:4.10315084;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0" />
|
||||||
|
</g>
|
||||||
|
<g
|
||||||
|
id="g3833-0"
|
||||||
|
transform="matrix(0.62675963,0,0,0.62675963,101.32586,233.2873)">
|
||||||
|
<rect
|
||||||
|
y="355.35693"
|
||||||
|
x="77.781746"
|
||||||
|
height="26.85568"
|
||||||
|
width="313.26996"
|
||||||
|
id="rect3835-5"
|
||||||
|
style="fill:#d7d7d7;fill-opacity:1;stroke:#000000;stroke-width:4.10315084;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0" />
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
<g
|
||||||
|
id="g3919"
|
||||||
|
transform="translate(237.17259,259.49748)">
|
||||||
|
<rect
|
||||||
|
y="355.35693"
|
||||||
|
x="111.11678"
|
||||||
|
height="144.45183"
|
||||||
|
width="199.00005"
|
||||||
|
id="rect3925"
|
||||||
|
style="fill:#d7d7d7;fill-opacity:1;stroke:#000000;stroke-width:1.59550798;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0" />
|
||||||
|
<text
|
||||||
|
xml:space="preserve"
|
||||||
|
style="font-size:16px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Arial;-inkscape-font-specification:Arial"
|
||||||
|
x="125.25891"
|
||||||
|
y="378.59042"
|
||||||
|
id="text3921"
|
||||||
|
sodipodi:linespacing="125%"><tspan
|
||||||
|
sodipodi:role="line"
|
||||||
|
id="tspan3923"
|
||||||
|
x="125.25891"
|
||||||
|
y="378.59042"
|
||||||
|
style="font-size:16px">ViewBox</tspan></text>
|
||||||
|
<path
|
||||||
|
inkscape:connector-curvature="0"
|
||||||
|
id="path3927"
|
||||||
|
d="m 132.32998,422.03916 15.82573,16.2779 15.28001,-29.30022 12.00571,18.44828 12.55144,-13.02232 16.91715,5.42597 14.7343,18.44829 12.55143,21.70388 12.55144,-16.8205 19.64573,-0.54261 10.36857,-21.70387"
|
||||||
|
style="fill:none;stroke:#000000;stroke-width:1.59550798px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
|
||||||
|
</g>
|
||||||
|
<g
|
||||||
|
id="g3931"
|
||||||
|
transform="translate(17.172593,417.49748)">
|
||||||
|
<rect
|
||||||
|
y="355.35693"
|
||||||
|
x="111.11678"
|
||||||
|
height="144.45183"
|
||||||
|
width="419.21329"
|
||||||
|
id="rect3937"
|
||||||
|
style="fill:#d7d7d7;fill-opacity:1;stroke:#000000;stroke-width:1.59550798;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0" />
|
||||||
|
<text
|
||||||
|
xml:space="preserve"
|
||||||
|
style="font-size:16px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Arial;-inkscape-font-specification:Arial"
|
||||||
|
x="125.25891"
|
||||||
|
y="378.59042"
|
||||||
|
id="text3933"
|
||||||
|
sodipodi:linespacing="125%"><tspan
|
||||||
|
sodipodi:role="line"
|
||||||
|
id="tspan3935"
|
||||||
|
x="125.25891"
|
||||||
|
y="378.59042"
|
||||||
|
style="font-size:16px">PlotItem</tspan></text>
|
||||||
|
<g
|
||||||
|
transform="matrix(1.675408,0,0,0.51883759,-93.913147,152.77473)"
|
||||||
|
id="g4155-5"
|
||||||
|
style="opacity:0.18141593">
|
||||||
|
<g
|
||||||
|
transform="matrix(0.62675963,0,0,0.62675963,80.420081,271.29053)"
|
||||||
|
id="g3777-4-0">
|
||||||
|
<rect
|
||||||
|
style="fill:#d7d7d7;fill-opacity:1;stroke:#000000;stroke-width:2.73037291;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
|
||||||
|
id="rect3779-6-6"
|
||||||
|
width="314.15744"
|
||||||
|
height="226.27419"
|
||||||
|
x="111.11678"
|
||||||
|
y="355.35693" />
|
||||||
|
<path
|
||||||
|
style="fill:none;stroke:#000000;stroke-width:2.73037291px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||||
|
d="m 171.72593,536.17423 29.29443,-30.30457 28.28427,54.54823 22.22335,-34.34518 23.23351,24.24366 31.31473,-10.10153 27.27412,-34.34518 23.23351,-40.40611 23.23351,31.31473 36.36549,1.01016 19.1929,40.4061"
|
||||||
|
id="path3789-2-4"
|
||||||
|
inkscape:connector-curvature="0"
|
||||||
|
transform="translate(-39.395949,-44.446712)" />
|
||||||
|
</g>
|
||||||
|
<g
|
||||||
|
transform="matrix(0,-0.62675963,0.26439647,0,45.741554,709.89607)"
|
||||||
|
id="g3801-4-6">
|
||||||
|
<rect
|
||||||
|
style="fill:#d7d7d7;fill-opacity:1;stroke:#000000;stroke-width:4.203825;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
|
||||||
|
id="rect3803-7-2"
|
||||||
|
width="225.26402"
|
||||||
|
height="29.294403"
|
||||||
|
x="119.19801"
|
||||||
|
y="355.35693" />
|
||||||
|
</g>
|
||||||
|
<g
|
||||||
|
transform="matrix(0.62675963,0,0,0.62675963,101.32586,252.09009)"
|
||||||
|
id="g3809-4-5">
|
||||||
|
<rect
|
||||||
|
style="fill:#d7d7d7;fill-opacity:1;stroke:#000000;stroke-width:2.73037291;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
|
||||||
|
id="rect3811-8-8"
|
||||||
|
width="313.26996"
|
||||||
|
height="26.85568"
|
||||||
|
x="77.781746"
|
||||||
|
y="355.35693" />
|
||||||
|
</g>
|
||||||
|
<g
|
||||||
|
id="g3817-8-6"
|
||||||
|
transform="matrix(0.62675963,0,0,0.62675963,101.32586,416.30111)">
|
||||||
|
<rect
|
||||||
|
y="355.35693"
|
||||||
|
x="77.781746"
|
||||||
|
height="26.85568"
|
||||||
|
width="313.26996"
|
||||||
|
id="rect3819-9-2"
|
||||||
|
style="fill:#d7d7d7;fill-opacity:1;stroke:#000000;stroke-width:2.73037291;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0" />
|
||||||
|
</g>
|
||||||
|
<g
|
||||||
|
id="g3825-8-8"
|
||||||
|
transform="matrix(0,-0.62675963,0.24174877,0,263.79375,709.89607)">
|
||||||
|
<rect
|
||||||
|
y="355.35693"
|
||||||
|
x="119.19801"
|
||||||
|
height="29.294403"
|
||||||
|
width="225.26402"
|
||||||
|
id="rect3827-0-4"
|
||||||
|
style="fill:#d7d7d7;fill-opacity:1;stroke:#000000;stroke-width:4.39633036;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0" />
|
||||||
|
</g>
|
||||||
|
<g
|
||||||
|
id="g3833-0-7"
|
||||||
|
transform="matrix(0.62675963,0,0,0.62675963,101.32586,233.2873)">
|
||||||
|
<rect
|
||||||
|
y="355.35693"
|
||||||
|
x="77.781746"
|
||||||
|
height="26.85568"
|
||||||
|
width="313.26996"
|
||||||
|
id="rect3835-5-2"
|
||||||
|
style="fill:#d7d7d7;fill-opacity:1;stroke:#000000;stroke-width:2.73037291;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0" />
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 25 KiB |
35
doc/source/index.rst
Normal file
35
doc/source/index.rst
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
.. pyqtgraph documentation master file, created by
|
||||||
|
sphinx-quickstart on Fri Nov 18 19:33:12 2011.
|
||||||
|
You can adapt this file completely to your liking, but it should at least
|
||||||
|
contain the root `toctree` directive.
|
||||||
|
|
||||||
|
Welcome to the documentation for pyqtgraph 1.8
|
||||||
|
==============================================
|
||||||
|
|
||||||
|
Contents:
|
||||||
|
|
||||||
|
.. toctree::
|
||||||
|
:maxdepth: 2
|
||||||
|
|
||||||
|
introduction
|
||||||
|
mouse_interaction
|
||||||
|
how_to_use
|
||||||
|
installation
|
||||||
|
plotting
|
||||||
|
images
|
||||||
|
3dgraphics
|
||||||
|
style
|
||||||
|
region_of_interest
|
||||||
|
prototyping
|
||||||
|
parametertree/index
|
||||||
|
internals
|
||||||
|
apireference
|
||||||
|
|
||||||
|
|
||||||
|
Indices and tables
|
||||||
|
==================
|
||||||
|
|
||||||
|
* :ref:`genindex`
|
||||||
|
* :ref:`modindex`
|
||||||
|
* :ref:`search`
|
||||||
|
|
9
doc/source/installation.rst
Normal file
9
doc/source/installation.rst
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
Installation
|
||||||
|
============
|
||||||
|
|
||||||
|
Pyqtgraph does not really require any installation scripts. All that is needed is for the pyqtgraph folder to be placed someplace importable. Most people will prefer to simply place this folder within a larger project folder. If you want to make pyqtgraph available system-wide, use one of the methods listed below:
|
||||||
|
|
||||||
|
* **Debian, Ubuntu, and similar Linux:** Download the .deb file linked at the top of the pyqtgraph web page or install using apt by putting "deb http://luke.campagnola.me/debian dev/" in your /etc/apt/sources.list file and install the python-pyqtgraph package.
|
||||||
|
* **Arch Linux:** Looks like someone has posted unofficial packages for Arch (thanks windel). (https://aur.archlinux.org/packages.php?ID=62577)
|
||||||
|
* **Windows:** Download and run the .exe installer file linked at the top of the pyqtgraph web page.
|
||||||
|
* **Everybody (including OSX):** Download the .tar.gz source package linked at the top of the pyqtgraph web page, extract its contents, and run "python setup.py install" from within the extracted directory.
|
9
doc/source/internals.rst
Normal file
9
doc/source/internals.rst
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
Internals - Extensions to Qt's GraphicsView
|
||||||
|
===========================================
|
||||||
|
|
||||||
|
* GraphicsView
|
||||||
|
* GraphicsScene (mouse events)
|
||||||
|
* GraphicsObject
|
||||||
|
* GraphicsWidget
|
||||||
|
* ViewBox
|
||||||
|
|
51
doc/source/introduction.rst
Normal file
51
doc/source/introduction.rst
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
Introduction
|
||||||
|
============
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
What is pyqtgraph?
|
||||||
|
------------------
|
||||||
|
|
||||||
|
Pyqtgraph is a graphics and user interface library for Python that provides functionality commonly required in engineering and science applications. Its primary goals are 1) to provide fast, interactive graphics for displaying data (plots, video, etc.) and 2) to provide tools to aid in rapid application development (for example, property trees such as used in Qt Designer).
|
||||||
|
|
||||||
|
Pyqtgraph makes heavy use of the Qt GUI platform (via PyQt or PySide) for its high-performance graphics and numpy for heavy number crunching. In particular, pyqtgraph uses Qt's GraphicsView framework which is a highly capable graphics system on its own; we bring optimized and simplified primitives to this framework to allow data visualization with minimal effort.
|
||||||
|
|
||||||
|
It is known to run on Linux, Windows, and OSX
|
||||||
|
|
||||||
|
|
||||||
|
What can it do?
|
||||||
|
---------------
|
||||||
|
|
||||||
|
Amongst the core features of pyqtgraph are:
|
||||||
|
|
||||||
|
* Basic data visualization primitives: Images, line and scatter plots
|
||||||
|
* Fast enough for realtime update of video/plot data
|
||||||
|
* Interactive scaling/panning, averaging, FFTs, SVG/PNG export
|
||||||
|
* Widgets for marking/selecting plot regions
|
||||||
|
* Widgets for marking/selecting image region-of-interest and automatically slicing multi-dimensional image data
|
||||||
|
* Framework for building customized image region-of-interest widgets
|
||||||
|
* Docking system that replaces/complements Qt's dock system to allow more complex (and more predictable) docking arrangements
|
||||||
|
* ParameterTree widget for rapid prototyping of dynamic interfaces (Similar to the property trees in Qt Designer and many other applications)
|
||||||
|
|
||||||
|
|
||||||
|
.. _examples:
|
||||||
|
|
||||||
|
Examples
|
||||||
|
--------
|
||||||
|
|
||||||
|
Pyqtgraph includes an extensive set of examples that can be accessed by running::
|
||||||
|
|
||||||
|
import pyqtgraph.examples
|
||||||
|
pyqtgraph.examples.run()
|
||||||
|
|
||||||
|
This will start a launcher with a list of available examples. Select an item from the list to view its source code and double-click an item to run the example.
|
||||||
|
|
||||||
|
|
||||||
|
How does it compare to...
|
||||||
|
-------------------------
|
||||||
|
|
||||||
|
* matplotlib: For plotting, pyqtgraph is not nearly as complete/mature as matplotlib, but runs much faster. Matplotlib is more aimed toward making publication-quality graphics, whereas pyqtgraph is intended for use in data acquisition and analysis applications. Matplotlib is more intuitive for matlab programmers; pyqtgraph is more intuitive for python/qt programmers. Matplotlib (to my knowledge) does not include many of pyqtgraph's features such as image interaction, volumetric rendering, parameter trees, flowcharts, etc.
|
||||||
|
|
||||||
|
* pyqwt5: About as fast as pyqwt5, but not quite as complete for plotting functionality. Image handling in pyqtgraph is much more complete (again, no ROI widgets in qwt). Also, pyqtgraph is written in pure python, so it is more portable than pyqwt, which often lags behind pyqt in development (I originally used pyqwt, but decided it was too much trouble to rely on it as a dependency in my projects). Like matplotlib, pyqwt (to my knowledge) does not include many of pyqtgraph's features such as image interaction, volumetric rendering, parameter trees, flowcharts, etc.
|
||||||
|
|
||||||
|
(My experience with these libraries is somewhat outdated; please correct me if I am wrong here)
|
49
doc/source/mouse_interaction.rst
Normal file
49
doc/source/mouse_interaction.rst
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
Mouse Interaction
|
||||||
|
=================
|
||||||
|
|
||||||
|
Most applications that use pyqtgraph's data visualization will generate widgets that can be interactively scaled, panned, and otherwise configured using the mouse. This section describes mouse interaction with these widgets.
|
||||||
|
|
||||||
|
|
||||||
|
2D Graphics
|
||||||
|
-----------
|
||||||
|
|
||||||
|
In pyqtgraph, most 2D visualizations follow the following mouse interaction:
|
||||||
|
|
||||||
|
* Left button: Interacts with items in the scene (select/move objects, etc). If there are no movable objects under the mouse cursor, then dragging with the left button will pan the scene instead.
|
||||||
|
* Right button drag: Scales the scene. Dragging left/right scales horizontally; dragging up/down scales vertically (although some scenes will have their x/y scales locked together). If there are x/y axes fisible in the scene, then right-dragging over the axis will _only_ affect that axis.
|
||||||
|
* Right button click: Clicking the right button in most cases will show a context menu with a variety of options depending on the object(s) under the mouse cursor.
|
||||||
|
* Middle button (or wheel) drag: Dragging the mouse with the wheel pressed down will always pan the scene (this is useful in instances where panning with the left button is prevented by other objects in the scene).
|
||||||
|
* Wheel spin: Zooms the scene in and out.
|
||||||
|
|
||||||
|
For machines where dragging with the right or middle buttons is difficult (usually Mac), another mouse interaction mode exists. In this mode, dragging with the left mouse button draws a box over a region of the scene. After the button is released, the scene is scaled and panned to fit the box. This mode can be accessed in the context menu or by calling::
|
||||||
|
|
||||||
|
pyqtgraph.setConfigOption('leftButtonPan', False)
|
||||||
|
|
||||||
|
|
||||||
|
Context Menu
|
||||||
|
------------
|
||||||
|
|
||||||
|
Right-clicking on most scenes will show a context menu with various options for changing the behavior of the scene. Some of the options available in this menu are:
|
||||||
|
|
||||||
|
* Enable/disable automatic scaling when the data range changes
|
||||||
|
* Link the axes of multiple views together
|
||||||
|
* Enable disable mouse interaction per axis
|
||||||
|
* Explicitly set the visible range values
|
||||||
|
|
||||||
|
The exact set of items available in the menu depends on the contents of the scene and the object clicked on.
|
||||||
|
|
||||||
|
|
||||||
|
3D Graphics
|
||||||
|
-----------
|
||||||
|
|
||||||
|
3D visualizations use the following mouse interaction:
|
||||||
|
|
||||||
|
* Left button drag: Rotates the scene around a central point
|
||||||
|
* Middle button drag: Pan the scene by moving the central "look-at" point within the x-y plane
|
||||||
|
* Middle button drag + CTRL: Pan the scene by moving the central "look-at" point along the z axis
|
||||||
|
* Wheel spin: zoom in/out
|
||||||
|
* Wheel + CTRL: change field-of-view angle
|
||||||
|
|
||||||
|
And keyboard controls:
|
||||||
|
|
||||||
|
* Arrow keys rotate around central point, just like dragging the left mouse button
|
15
doc/source/parametertree/apiref.rst
Normal file
15
doc/source/parametertree/apiref.rst
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
ParameterTree API Reference
|
||||||
|
===========================
|
||||||
|
|
||||||
|
Also see the 'parametertree' example included with pyqtgraph
|
||||||
|
|
||||||
|
Contents:
|
||||||
|
|
||||||
|
.. toctree::
|
||||||
|
:maxdepth: 2
|
||||||
|
|
||||||
|
parameter
|
||||||
|
parametertree
|
||||||
|
parametertypes
|
||||||
|
parameteritem
|
||||||
|
|
21
doc/source/parametertree/index.rst
Normal file
21
doc/source/parametertree/index.rst
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
.. _parametertree:
|
||||||
|
|
||||||
|
Parameter Trees
|
||||||
|
===============
|
||||||
|
|
||||||
|
Parameter trees are a system for handling hierarchies of parameters while automatically generating one or more GUIs to display and interact with the parameters.
|
||||||
|
This feature is commonly seen, for example, in user interface design applications which display a list of editable properties for each widget.
|
||||||
|
Parameters generally have a name, a data type (int, float, string, color, etc), and a value matching the data type. Parameters may be grouped and nested
|
||||||
|
to form hierarchies and may be subclassed to provide custom behavior and display widgets.
|
||||||
|
|
||||||
|
Pyqtgraph's parameter tree system works similarly to the model-view architecture used by some components of Qt: Parameters are purely data-handling classes
|
||||||
|
that exist independent of any graphical interface. A ParameterTree is a widget that automatically generates a graphical interface which represents
|
||||||
|
the state of a haierarchy of Parameter objects and allows the user to edit the values within that hierarchy. This separation of data (model) and graphical
|
||||||
|
interface (view) allows the same data to be represented multiple times and in a variety of different ways.
|
||||||
|
|
||||||
|
For more information, see the 'parametertree' example included with pyqtgraph and the API reference
|
||||||
|
|
||||||
|
.. toctree::
|
||||||
|
:maxdepth: 2
|
||||||
|
|
||||||
|
apiref
|
8
doc/source/parametertree/parameter.rst
Normal file
8
doc/source/parametertree/parameter.rst
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
Parameter
|
||||||
|
=========
|
||||||
|
|
||||||
|
.. autoclass:: pyqtgraph.parametertree.Parameter
|
||||||
|
:members:
|
||||||
|
|
||||||
|
.. automethod:: pyqtgraph.parametertree.Parameter.__init__
|
||||||
|
|
8
doc/source/parametertree/parameteritem.rst
Normal file
8
doc/source/parametertree/parameteritem.rst
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
ParameterItem
|
||||||
|
=============
|
||||||
|
|
||||||
|
.. autoclass:: pyqtgraph.parametertree.ParameterItem
|
||||||
|
:members:
|
||||||
|
|
||||||
|
.. automethod:: pyqtgraph.parametertree.ParameterItem.__init__
|
||||||
|
|
8
doc/source/parametertree/parametertree.rst
Normal file
8
doc/source/parametertree/parametertree.rst
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
ParameterTree
|
||||||
|
=============
|
||||||
|
|
||||||
|
.. autoclass:: pyqtgraph.parametertree.ParameterTree
|
||||||
|
:members:
|
||||||
|
|
||||||
|
.. automethod:: pyqtgraph.parametertree.ParameterTree.__init__
|
||||||
|
|
6
doc/source/parametertree/parametertypes.rst
Normal file
6
doc/source/parametertree/parametertypes.rst
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
Built-in Parameter Types
|
||||||
|
========================
|
||||||
|
|
||||||
|
.. automodule:: pyqtgraph.parametertree.parameterTypes
|
||||||
|
:members:
|
||||||
|
|
73
doc/source/plotting.rst
Normal file
73
doc/source/plotting.rst
Normal file
@ -0,0 +1,73 @@
|
|||||||
|
Plotting in pyqtgraph
|
||||||
|
=====================
|
||||||
|
|
||||||
|
There are a few basic ways to plot data in pyqtgraph:
|
||||||
|
|
||||||
|
================================================================ ==================================================
|
||||||
|
:func:`pyqtgraph.plot` Create a new plot window showing your data
|
||||||
|
:func:`PlotWidget.plot() <pyqtgraph.PlotWidget.plot>` Add a new set of data to an existing plot widget
|
||||||
|
:func:`PlotItem.plot() <pyqtgraph.PlotItem.plot>` Add a new set of data to an existing plot widget
|
||||||
|
:func:`GraphicsWindow.addPlot() <pyqtgraph.GraphicsWindow.plot>` Add a new plot to a grid of plots
|
||||||
|
================================================================ ==================================================
|
||||||
|
|
||||||
|
All of these will accept the same basic arguments which control how the plot data is interpreted and displayed:
|
||||||
|
|
||||||
|
* x - Optional X data; if not specified, then a range of integers will be generated automatically.
|
||||||
|
* y - Y data.
|
||||||
|
* pen - The pen to use when drawing plot lines, or None to disable lines.
|
||||||
|
* symbol - A string describing the shape of symbols to use for each point. Optionally, this may also be a sequence of strings with a different symbol for each point.
|
||||||
|
* symbolPen - The pen (or sequence of pens) to use when drawing the symbol outline.
|
||||||
|
* symbolBrush - The brush (or sequence of brushes) to use when filling the symbol.
|
||||||
|
* fillLevel - Fills the area under the plot curve to this Y-value.
|
||||||
|
* brush - The brush to use when filling under the curve.
|
||||||
|
|
||||||
|
See the 'plotting' :ref:`example <examples>` for a demonstration of these arguments.
|
||||||
|
|
||||||
|
All of the above functions also return handles to the objects that are created, allowing the plots and data to be further modified.
|
||||||
|
|
||||||
|
Organization of Plotting Classes
|
||||||
|
--------------------------------
|
||||||
|
|
||||||
|
There are several classes invloved in displaying plot data. Most of these classes are instantiated automatically, but it is useful to understand how they are organized and relate to each other. Pyqtgraph is based heavily on Qt's GraphicsView framework--if you are not already familiar with this, it's worth reading about (but not essential). Most importantly: 1) Qt GUIs are composed of QWidgets, 2) A special widget called QGraphicsView is used for displaying complex graphics, and 3) QGraphicsItems define the objects that are displayed within a QGraphicsView.
|
||||||
|
|
||||||
|
* Data Classes (all subclasses of QGraphicsItem)
|
||||||
|
* PlotCurveItem - Displays a plot line given x,y data
|
||||||
|
* ScatterPlotItem - Displays points given x,y data
|
||||||
|
* :class:`PlotDataItem <pyqtgraph.graphicsItems.PlotDataItem.PlotDataItem>` - Combines PlotCurveItem and ScatterPlotItem. The plotting functions discussed above create objects of this type.
|
||||||
|
* Container Classes (subclasses of QGraphicsItem; contain other QGraphicsItem objects and must be viewed from within a GraphicsView)
|
||||||
|
* PlotItem - Contains a ViewBox for displaying data as well as AxisItems and labels for displaying the axes and title. This is a QGraphicsItem subclass and thus may only be used from within a GraphicsView
|
||||||
|
* GraphicsLayoutItem - QGraphicsItem subclass which displays a grid of items. This is used to display multiple PlotItems together.
|
||||||
|
* ViewBox - A QGraphicsItem subclass for displaying data. The user may scale/pan the contents of a ViewBox using the mouse. Typically all PlotData/PlotCurve/ScatterPlotItems are displayed from within a ViewBox.
|
||||||
|
* AxisItem - Displays axis values, ticks, and labels. Most commonly used with PlotItem.
|
||||||
|
* Container Classes (subclasses of QWidget; may be embedded in PyQt GUIs)
|
||||||
|
* PlotWidget - A subclass of GraphicsView with a single PlotItem displayed. Most of the methods provided by PlotItem are also available through PlotWidget.
|
||||||
|
* GraphicsLayoutWidget - QWidget subclass displaying a single GraphicsLayoutItem. Most of the methods provided by GraphicsLayoutItem are also available through GraphicsLayoutWidget.
|
||||||
|
|
||||||
|
.. image:: images/plottingClasses.png
|
||||||
|
|
||||||
|
|
||||||
|
Examples
|
||||||
|
--------
|
||||||
|
|
||||||
|
See the 'plotting' and 'PlotWidget' :ref:`examples included with pyqtgraph <examples>` for more information.
|
||||||
|
|
||||||
|
Show x,y data as scatter plot::
|
||||||
|
|
||||||
|
import pyqtgraph as pg
|
||||||
|
import numpy as np
|
||||||
|
x = np.random.normal(size=1000)
|
||||||
|
y = np.random.normal(size=1000)
|
||||||
|
pg.plot(x, y, pen=None, symbol='o') ## setting pen=None disables line drawing
|
||||||
|
|
||||||
|
Create/show a plot widget, display three data curves::
|
||||||
|
|
||||||
|
import pyqtgraph as pg
|
||||||
|
import numpy as np
|
||||||
|
x = np.arange(1000)
|
||||||
|
y = np.random.normal(size=(3, 1000))
|
||||||
|
plotWidget = pg.plot(title="Three plot curves")
|
||||||
|
for i in range(3):
|
||||||
|
plotWidget.plot(x, y[i], pen=(i,3)) ## setting pen=(i,3) automaticaly creates three different-colored pens
|
||||||
|
|
||||||
|
|
||||||
|
|
41
doc/source/prototyping.rst
Normal file
41
doc/source/prototyping.rst
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
Rapid GUI prototyping
|
||||||
|
=====================
|
||||||
|
|
||||||
|
[Just an overview; documentation is not complete yet]
|
||||||
|
|
||||||
|
Pyqtgraph offers several powerful features which are commonly used in engineering and scientific applications.
|
||||||
|
|
||||||
|
Parameter Trees
|
||||||
|
---------------
|
||||||
|
|
||||||
|
The parameter tree system provides a widget displaying a tree of modifiable values similar to those used in most GUI editor applications. This allows a large number of variables to be controlled by the user with relatively little programming effort. The system also provides separation between the data being controlled and the user interface controlling it (model/view architecture). Parameters may be grouped/nested to any depth and custom parameter types can be built by subclassing from Parameter and ParameterItem.
|
||||||
|
|
||||||
|
See the `parametertree documentation <parametertree>`_ for more information.
|
||||||
|
|
||||||
|
|
||||||
|
Visual Programming Flowcharts
|
||||||
|
-----------------------------
|
||||||
|
|
||||||
|
Pyqtgraph's flowcharts provide a visual programming environment similar in concept to LabView--functional modules are added to a flowchart and connected by wires to define a more complex and arbitrarily configurable algorithm. A small number of predefined modules (called Nodes) are included with pyqtgraph, but most flowchart developers will want to define their own library of Nodes. At their core, the Nodes are little more than 1) a Python function 2) a list of input/output terminals, and 3) an optional widget providing a control panel for the Node. Nodes may transmit/receive any type of Python object via their terminals.
|
||||||
|
|
||||||
|
One major limitation of flowcharts is that there is no mechanism for looping within a flowchart. (however individual Nodes may contain loops (they may contain any Python code at all), and an entire flowchart may be executed from within a loop).
|
||||||
|
|
||||||
|
There are two distinct modes of executing the code in a flowchart:
|
||||||
|
|
||||||
|
1. Provide data to the input terminals of the flowchart. This method is slower and will provide a graphical representation of the data as it passes through the flowchart. This is useful for debugging as it allows the user to inspect the data at each terminal and see where exceptions occurred within the flowchart.
|
||||||
|
2. Call Flowchart.process. This method does not update the displayed state of the flowchart and only retains the state of each terminal as long as it is needed. Additionally, Nodes which do not contribute to the output values of the flowchart (such as plotting nodes) are ignored. This mode allows for faster processing of large data sets and avoids memory issues which can occur if doo much data is present in the flowchart at once (e.g., when processing image data through several stages).
|
||||||
|
|
||||||
|
See the flowchart example for more information.
|
||||||
|
|
||||||
|
Graphical Canvas
|
||||||
|
----------------
|
||||||
|
|
||||||
|
The Canvas is a system designed to allow the user to add/remove items to a 2D canvas similar to most vector graphics applications. Items can be translated/scaled/rotated and each item may define its own custom control interface.
|
||||||
|
|
||||||
|
|
||||||
|
Dockable Widgets
|
||||||
|
----------------
|
||||||
|
|
||||||
|
The dockarea system allows the design of user interfaces which can be rearranged by the user at runtime. Docks can be moved, resized, stacked, and torn out of the main window. This is similar in principle to the docking system built into Qt, but offers a more deterministic dock placement API (in Qt it is very difficult to programatically generate complex dock arrangements). Additionally, Qt's docks are designed to be used as small panels around the outer edge of a window. Pyqtgraph's docks were created with the notion that the entire window (or any portion of it) would consist of dockable components.
|
||||||
|
|
||||||
|
|
23
doc/source/region_of_interest.rst
Normal file
23
doc/source/region_of_interest.rst
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
Interactive Data Selection Controls
|
||||||
|
===================================
|
||||||
|
|
||||||
|
Pyqtgraph includes graphics items which allow the user to select and mark regions of data.
|
||||||
|
|
||||||
|
Linear Selection and Marking
|
||||||
|
----------------------------
|
||||||
|
|
||||||
|
Two classes allow marking and selecting 1-dimensional data: :class:`LinearRegionItem <pyqtgraph.LinearRegionItem>` and :class:`InfiniteLine <pyqtgraph.InfiniteLine>`. The first class, :class:`LinearRegionItem <pyqtgraph.LinearRegionItem>`, may be added to any ViewBox or PlotItem to mark either a horizontal or vertical region. The region can be dragged and its bounding edges can be moved independently. The second class, :class:`InfiniteLine <pyqtgraph.InfiniteLine>`, is usually used to mark a specific position along the x or y axis. These may be dragged by the user.
|
||||||
|
|
||||||
|
|
||||||
|
2D Selection and Marking
|
||||||
|
------------------------
|
||||||
|
|
||||||
|
To select a 2D region from an image, pyqtgraph uses the :class:`ROI <pyqtgraph.ROI>` class or any of its subclasses. By default, :class:`ROI <pyqtgraph.ROI>` simply displays a rectangle which can be moved by the user to mark a specific region (most often this will be a region of an image, but this is not required). To allow the ROI to be resized or rotated, there are several methods for adding handles (:func:`addScaleHandle <pyqtgraph.ROI.addScaleHandle>`, :func:`addRotateHandle <pyqtgraph.ROI.addRotateHandle>`, etc.) which can be dragged by the user. These handles may be placed at any location relative to the ROI and may scale/rotate the ROI around any arbitrary center point. There are several ROI subclasses with a variety of shapes and modes of interaction.
|
||||||
|
|
||||||
|
To automatically extract a region of image data using an ROI and an ImageItem, use :func:`ROI.getArrayRegion <pyqtgraph.ROI.getArrayRegion>`. ROI classes use the :func:`affineSlice <pyqtgraph.affineSlice>` function to perform this extraction.
|
||||||
|
|
||||||
|
ROI can also be used as a control for moving/rotating/scaling items in a scene similar to most vetctor graphics editing applications.
|
||||||
|
|
||||||
|
See the ROITypes example for more information.
|
||||||
|
|
||||||
|
|
47
doc/source/style.rst
Normal file
47
doc/source/style.rst
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
Line, Fill, and Color
|
||||||
|
=====================
|
||||||
|
|
||||||
|
Qt relies on its QColor, QPen and QBrush classes for specifying line and fill styles for all of its drawing.
|
||||||
|
Internally, pyqtgraph uses the same system but also allows many shorthand methods of specifying
|
||||||
|
the same style options.
|
||||||
|
|
||||||
|
Many functions and methods in pyqtgraph accept arguments specifying the line style (pen), fill style (brush), or color.
|
||||||
|
For most of these function arguments, the following values may be used:
|
||||||
|
|
||||||
|
* single-character string representing color (b, g, r, c, m, y, k, w)
|
||||||
|
* (r, g, b) or (r, g, b, a) tuple
|
||||||
|
* single greyscale value (0.0 - 1.0)
|
||||||
|
* (index, maximum) tuple for automatically iterating through colors (see :func:`intColor <pyqtgraph.intColor>`)
|
||||||
|
* QColor
|
||||||
|
* QPen / QBrush where appropriate
|
||||||
|
|
||||||
|
Notably, more complex pens and brushes can be easily built using the
|
||||||
|
:func:`mkPen() <pyqtgraph.mkPen>` / :func:`mkBrush() <pyqtgraph.mkBrush>` functions or with Qt's QPen and QBrush classes::
|
||||||
|
|
||||||
|
mkPen('y', width=3, style=QtCore.Qt.DashLine) ## Make a dashed yellow line 2px wide
|
||||||
|
mkPen(0.5) ## solid grey line 1px wide
|
||||||
|
mkPen(color=(200, 200, 255), style=QtCore.Qt.DotLine) ## Dotted pale-blue line
|
||||||
|
|
||||||
|
See the Qt documentation for 'QPen' and 'PenStyle' for more line-style options and 'QBrush' for more fill options.
|
||||||
|
Colors can also be built using :func:`mkColor() <pyqtgraph.mkColor>`,
|
||||||
|
:func:`intColor() <pyqtgraph.intColor>`, :func:`hsvColor() <pyqtgraph.hsvColor>`, or Qt's QColor class.
|
||||||
|
|
||||||
|
|
||||||
|
Default Background and Foreground Colors
|
||||||
|
----------------------------------------
|
||||||
|
|
||||||
|
By default, pyqtgraph uses a black background for its plots and grey for axes, text, and plot lines.
|
||||||
|
These defaults can be changed using pyqtgraph.setConfigOption()::
|
||||||
|
|
||||||
|
import pyqtgraph as pg
|
||||||
|
|
||||||
|
## Switch to using white background and black foreground
|
||||||
|
pg.setConfigOption('background', 'w')
|
||||||
|
pg.setConfigOption('foreground', 'k')
|
||||||
|
|
||||||
|
## The following plot has inverted colors
|
||||||
|
pg.plot([1,4,2,3,5])
|
||||||
|
|
||||||
|
(Note that this must be set *before* creating any widgets)
|
||||||
|
|
||||||
|
|
8
doc/source/widgets/busycursor.rst
Normal file
8
doc/source/widgets/busycursor.rst
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
BusyCursor
|
||||||
|
==========
|
||||||
|
|
||||||
|
.. autoclass:: pyqtgraph.BusyCursor
|
||||||
|
:members:
|
||||||
|
|
||||||
|
.. automethod:: pyqtgraph.BusyCursor.__init__
|
||||||
|
|
8
doc/source/widgets/checktable.rst
Normal file
8
doc/source/widgets/checktable.rst
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
CheckTable
|
||||||
|
==========
|
||||||
|
|
||||||
|
.. autoclass:: pyqtgraph.CheckTable
|
||||||
|
:members:
|
||||||
|
|
||||||
|
.. automethod:: pyqtgraph.CheckTable.__init__
|
||||||
|
|
8
doc/source/widgets/colorbutton.rst
Normal file
8
doc/source/widgets/colorbutton.rst
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
ColorButton
|
||||||
|
===========
|
||||||
|
|
||||||
|
.. autoclass:: pyqtgraph.ColorButton
|
||||||
|
:members:
|
||||||
|
|
||||||
|
.. automethod:: pyqtgraph.ColorButton.__init__
|
||||||
|
|
8
doc/source/widgets/combobox.rst
Normal file
8
doc/source/widgets/combobox.rst
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
ComboBox
|
||||||
|
========
|
||||||
|
|
||||||
|
.. autoclass:: pyqtgraph.ComboBox
|
||||||
|
:members:
|
||||||
|
|
||||||
|
.. automethod:: pyqtgraph.ComboBox.__init__
|
||||||
|
|
8
doc/source/widgets/datatreewidget.rst
Normal file
8
doc/source/widgets/datatreewidget.rst
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
DataTreeWidget
|
||||||
|
==============
|
||||||
|
|
||||||
|
.. autoclass:: pyqtgraph.DataTreeWidget
|
||||||
|
:members:
|
||||||
|
|
||||||
|
.. automethod:: pyqtgraph.DataTreeWidget.__init__
|
||||||
|
|
5
doc/source/widgets/dockarea.rst
Normal file
5
doc/source/widgets/dockarea.rst
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
dockarea module
|
||||||
|
===============
|
||||||
|
|
||||||
|
.. automodule:: pyqtgraph.dockarea
|
||||||
|
:members:
|
8
doc/source/widgets/feedbackbutton.rst
Normal file
8
doc/source/widgets/feedbackbutton.rst
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
FeedbackButton
|
||||||
|
==============
|
||||||
|
|
||||||
|
.. autoclass:: pyqtgraph.FeedbackButton
|
||||||
|
:members:
|
||||||
|
|
||||||
|
.. automethod:: pyqtgraph.FeedbackButton.__init__
|
||||||
|
|
8
doc/source/widgets/filedialog.rst
Normal file
8
doc/source/widgets/filedialog.rst
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
FileDialog
|
||||||
|
==========
|
||||||
|
|
||||||
|
.. autoclass:: pyqtgraph.FileDialog
|
||||||
|
:members:
|
||||||
|
|
||||||
|
.. automethod:: pyqtgraph.FileDialog.__init__
|
||||||
|
|
8
doc/source/widgets/gradientwidget.rst
Normal file
8
doc/source/widgets/gradientwidget.rst
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
GradientWidget
|
||||||
|
==============
|
||||||
|
|
||||||
|
.. autoclass:: pyqtgraph.GradientWidget
|
||||||
|
:members:
|
||||||
|
|
||||||
|
.. automethod:: pyqtgraph.GradientWidget.__init__
|
||||||
|
|
8
doc/source/widgets/graphicslayoutwidget.rst
Normal file
8
doc/source/widgets/graphicslayoutwidget.rst
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
GraphicsLayoutWidget
|
||||||
|
====================
|
||||||
|
|
||||||
|
.. autoclass:: pyqtgraph.GraphicsLayoutWidget
|
||||||
|
:members:
|
||||||
|
|
||||||
|
.. automethod:: pyqtgraph.GraphicsLayoutWidget.__init__
|
||||||
|
|
8
doc/source/widgets/graphicsview.rst
Normal file
8
doc/source/widgets/graphicsview.rst
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
GraphicsView
|
||||||
|
============
|
||||||
|
|
||||||
|
.. autoclass:: pyqtgraph.GraphicsView
|
||||||
|
:members:
|
||||||
|
|
||||||
|
.. automethod:: pyqtgraph.GraphicsView.__init__
|
||||||
|
|
8
doc/source/widgets/histogramlutwidget.rst
Normal file
8
doc/source/widgets/histogramlutwidget.rst
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
HistogramLUTWidget
|
||||||
|
==================
|
||||||
|
|
||||||
|
.. autoclass:: pyqtgraph.HistogramLUTWidget
|
||||||
|
:members:
|
||||||
|
|
||||||
|
.. automethod:: pyqtgraph.HistogramLUTWidget.__init__
|
||||||
|
|
8
doc/source/widgets/imageview.rst
Normal file
8
doc/source/widgets/imageview.rst
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
ImageView
|
||||||
|
=========
|
||||||
|
|
||||||
|
.. autoclass:: pyqtgraph.ImageView
|
||||||
|
:members:
|
||||||
|
|
||||||
|
.. automethod:: pyqtgraph.ImageView.__init__
|
||||||
|
|
40
doc/source/widgets/index.rst
Normal file
40
doc/source/widgets/index.rst
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
.. _api_widgets:
|
||||||
|
|
||||||
|
Pyqtgraph's Widgets
|
||||||
|
===================
|
||||||
|
|
||||||
|
Pyqtgraph provides several QWidget subclasses which are useful for building user interfaces. These widgets can generally be used in any Qt application and provide functionality that is frequently useful in science and engineering applications.
|
||||||
|
|
||||||
|
Contents:
|
||||||
|
|
||||||
|
.. toctree::
|
||||||
|
:maxdepth: 2
|
||||||
|
|
||||||
|
plotwidget
|
||||||
|
imageview
|
||||||
|
dockarea
|
||||||
|
spinbox
|
||||||
|
gradientwidget
|
||||||
|
histogramlutwidget
|
||||||
|
parametertree
|
||||||
|
graphicsview
|
||||||
|
rawimagewidget
|
||||||
|
datatreewidget
|
||||||
|
tablewidget
|
||||||
|
treewidget
|
||||||
|
checktable
|
||||||
|
colorbutton
|
||||||
|
graphicslayoutwidget
|
||||||
|
progressdialog
|
||||||
|
filedialog
|
||||||
|
joystickbutton
|
||||||
|
multiplotwidget
|
||||||
|
verticallabel
|
||||||
|
remotegraphicsview
|
||||||
|
matplotlibwidget
|
||||||
|
feedbackbutton
|
||||||
|
combobox
|
||||||
|
layoutwidget
|
||||||
|
pathbutton
|
||||||
|
valuelabel
|
||||||
|
busycursor
|
8
doc/source/widgets/joystickbutton.rst
Normal file
8
doc/source/widgets/joystickbutton.rst
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
JoystickButton
|
||||||
|
==============
|
||||||
|
|
||||||
|
.. autoclass:: pyqtgraph.JoystickButton
|
||||||
|
:members:
|
||||||
|
|
||||||
|
.. automethod:: pyqtgraph.JoystickButton.__init__
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user