Major merge with dev branch; this branch is ready to become stable after

a few rounds of bugfixes.
This commit is contained in:
Luke Campagnola 2012-12-26 20:37:02 -05:00
commit bc7e927ba7
387 changed files with 45968 additions and 8912 deletions

View File

@ -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)

View File

@ -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

View File

@ -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
View 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.

File diff suppressed because it is too large Load Diff

18
README
View File

@ -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
View 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.

View File

@ -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)

View File

@ -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
View 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
View 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
View 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
View 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)

View File

@ -0,0 +1,8 @@
GLAxisItem
==========
.. autoclass:: pyqtgraph.opengl.GLAxisItem
:members:
.. automethod:: pyqtgraph.opengl.GLAxisItem.__init__

View File

@ -0,0 +1,8 @@
GLGraphicsItem
==============
.. autoclass:: pyqtgraph.opengl.GLGraphicsItem
:members:
.. automethod:: pyqtgraph.GLGraphicsItem.__init__

View File

@ -0,0 +1,8 @@
GLGridItem
==========
.. autoclass:: pyqtgraph.opengl.GLGridItem
:members:
.. automethod:: pyqtgraph.opengl.GLGridItem.__init__

View File

@ -0,0 +1,8 @@
GLImageItem
===========
.. autoclass:: pyqtgraph.opengl.GLImageItem
:members:
.. automethod:: pyqtgraph.opengl.GLImageItem.__init__

View File

@ -0,0 +1,8 @@
GLMeshItem
==========
.. autoclass:: pyqtgraph.opengl.GLMeshItem
:members:
.. automethod:: pyqtgraph.opengl.GLMeshItem.__init__

View File

@ -0,0 +1,8 @@
GLScatterPlotItem
=================
.. autoclass:: pyqtgraph.opengl.GLScatterPlotItem
:members:
.. automethod:: pyqtgraph.opengl.GLScatterPlotItem.__init__

View File

@ -0,0 +1,8 @@
GLSurfacePlotItem
=================
.. autoclass:: pyqtgraph.opengl.GLSurfacePlotItem
:members:
.. automethod:: pyqtgraph.opengl.GLSurfacePlotItem.__init__

View File

@ -0,0 +1,8 @@
GLViewWidget
============
.. autoclass:: pyqtgraph.opengl.GLViewWidget
:members:
.. automethod:: pyqtgraph.opengl.GLViewWidget.__init__

View File

@ -0,0 +1,8 @@
GLVolumeItem
============
.. autoclass:: pyqtgraph.opengl.GLVolumeItem
:members:
.. automethod:: pyqtgraph.opengl.GLVolumeItem.__init__

View 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

View File

@ -0,0 +1,8 @@
MeshData
========
.. autoclass:: pyqtgraph.opengl.MeshData
:members:
.. automethod:: pyqtgraph.opengl.MeshData.__init__

View 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
View 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
View 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

View File

@ -0,0 +1,8 @@
ArrowItem
=========
.. autoclass:: pyqtgraph.ArrowItem
:members:
.. automethod:: pyqtgraph.ArrowItem.__init__

View File

@ -0,0 +1,8 @@
AxisItem
========
.. autoclass:: pyqtgraph.AxisItem
:members:
.. automethod:: pyqtgraph.AxisItem.__init__

View File

@ -0,0 +1,8 @@
ButtonItem
==========
.. autoclass:: pyqtgraph.ButtonItem
:members:
.. automethod:: pyqtgraph.ButtonItem.__init__

View File

@ -0,0 +1,8 @@
CurveArrow
==========
.. autoclass:: pyqtgraph.CurveArrow
:members:
.. automethod:: pyqtgraph.CurveArrow.__init__

View File

@ -0,0 +1,8 @@
CurvePoint
==========
.. autoclass:: pyqtgraph.CurvePoint
:members:
.. automethod:: pyqtgraph.CurvePoint.__init__

View File

@ -0,0 +1,8 @@
FillBetweenItem
===============
.. autoclass:: pyqtgraph.FillBetweenItem
:members:
.. automethod:: pyqtgraph.FillBetweenItem.__init__

View File

@ -0,0 +1,19 @@
GradientEditorItem
==================
.. autoclass:: pyqtgraph.GradientEditorItem
:members:
.. automethod:: pyqtgraph.GradientEditorItem.__init__
TickSliderItem
==================
.. autoclass:: pyqtgraph.TickSliderItem
:members:
.. automethod:: pyqtgraph.TickSliderItem.__init__

View File

@ -0,0 +1,8 @@
GradientLegend
==============
.. autoclass:: pyqtgraph.GradientLegend
:members:
.. automethod:: pyqtgraph.GradientLegend.__init__

View File

@ -0,0 +1,6 @@
GraphicsItem
============
.. autoclass:: pyqtgraph.GraphicsItem
:members:

View File

@ -0,0 +1,8 @@
GraphicsLayout
==============
.. autoclass:: pyqtgraph.GraphicsLayout
:members:
.. automethod:: pyqtgraph.GraphicsLayout.__init__

View File

@ -0,0 +1,8 @@
GraphicsObject
==============
.. autoclass:: pyqtgraph.GraphicsObject
:members:
.. automethod:: pyqtgraph.GraphicsObject.__init__

View File

@ -0,0 +1,8 @@
GraphicsWidget
==============
.. autoclass:: pyqtgraph.GraphicsWidget
:members:
.. automethod:: pyqtgraph.GraphicsWidget.__init__

View File

@ -0,0 +1,8 @@
GraphicsWidgetAnchor
====================
.. autoclass:: pyqtgraph.GraphicsWidgetAnchor
:members:
.. automethod:: pyqtgraph.GraphicsWidgetAnchor.__init__

View File

@ -0,0 +1,8 @@
GridItem
========
.. autoclass:: pyqtgraph.GridItem
:members:
.. automethod:: pyqtgraph.GridItem.__init__

View File

@ -0,0 +1,8 @@
HistogramLUTItem
================
.. autoclass:: pyqtgraph.HistogramLUTItem
:members:
.. automethod:: pyqtgraph.HistogramLUTItem.__init__

View File

@ -0,0 +1,8 @@
ImageItem
=========
.. autoclass:: pyqtgraph.ImageItem
:members:
.. automethod:: pyqtgraph.ImageItem.__init__

View 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

View File

@ -0,0 +1,8 @@
InfiniteLine
============
.. autoclass:: pyqtgraph.InfiniteLine
:members:
.. automethod:: pyqtgraph.InfiniteLine.__init__

View File

@ -0,0 +1,7 @@
IsocurveItem
============
.. autoclass:: pyqtgraph.IsocurveItem
:members:
.. automethod:: pyqtgraph.IsocurveItem.__init__

View File

@ -0,0 +1,8 @@
LabelItem
=========
.. autoclass:: pyqtgraph.LabelItem
:members:
.. automethod:: pyqtgraph.LabelItem.__init__

View File

@ -0,0 +1,8 @@
LegendItem
==========
.. autoclass:: pyqtgraph.LegendItem
:members:
.. automethod:: pyqtgraph.LegendItem.__init__

View File

@ -0,0 +1,8 @@
LinearRegionItem
================
.. autoclass:: pyqtgraph.LinearRegionItem
:members:
.. automethod:: pyqtgraph.LinearRegionItem.__init__

View 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))

View File

@ -0,0 +1,8 @@
PlotCurveItem
=============
.. autoclass:: pyqtgraph.PlotCurveItem
:members:
.. automethod:: pyqtgraph.PlotCurveItem.__init__

View File

@ -0,0 +1,8 @@
PlotDataItem
============
.. autoclass:: pyqtgraph.PlotDataItem
:members:
.. automethod:: pyqtgraph.PlotDataItem.__init__

View File

@ -0,0 +1,7 @@
PlotItem
========
.. autoclass:: pyqtgraph.PlotItem()
:members:
.. automethod:: pyqtgraph.PlotItem.__init__

View File

@ -0,0 +1,8 @@
ROI
===
.. autoclass:: pyqtgraph.ROI
:members:
.. automethod:: pyqtgraph.ROI.__init__

View File

@ -0,0 +1,8 @@
ScaleBar
========
.. autoclass:: pyqtgraph.ScaleBar
:members:
.. automethod:: pyqtgraph.ScaleBar.__init__

View File

@ -0,0 +1,8 @@
ScatterPlotItem
===============
.. autoclass:: pyqtgraph.ScatterPlotItem
:members:
.. automethod:: pyqtgraph.ScatterPlotItem.__init__

View File

@ -0,0 +1,8 @@
TextItem
========
.. autoclass:: pyqtgraph.TextItem
:members:
.. automethod:: pyqtgraph.TextItem.__init__

View File

@ -0,0 +1,8 @@
UIGraphicsItem
==============
.. autoclass:: pyqtgraph.UIGraphicsItem
:members:
.. automethod:: pyqtgraph.UIGraphicsItem.__init__

View File

@ -0,0 +1,8 @@
ViewBox
=======
.. autoclass:: pyqtgraph.ViewBox
:members:
.. automethod:: pyqtgraph.ViewBox.__init__

View File

@ -0,0 +1,8 @@
VTickGroup
==========
.. autoclass:: pyqtgraph.VTickGroup
:members:
.. automethod:: pyqtgraph.VTickGroup.__init__

View File

@ -0,0 +1,8 @@
GraphicsScene
=============
.. autoclass:: pyqtgraph.GraphicsScene
:members:
.. automethod:: pyqtgraph.GraphicsScene.__init__

View File

@ -0,0 +1,5 @@
HoverEvent
==========
.. autoclass:: pyqtgraph.GraphicsScene.mouseEvents.HoverEvent
:members:

View File

@ -0,0 +1,12 @@
GraphicsScene and Mouse Events
==============================
Contents:
.. toctree::
:maxdepth: 2
graphicsscene
hoverevent
mouseclickevent
mousedragevent

View File

@ -0,0 +1,5 @@
MouseClickEvent
===============
.. autoclass:: pyqtgraph.GraphicsScene.mouseEvents.MouseClickEvent
:members:

View File

@ -0,0 +1,5 @@
MouseDragEvent
==============
.. autoclass:: pyqtgraph.GraphicsScene.mouseEvents.MouseDragEvent
:members:

View File

@ -0,0 +1,8 @@
Basic display widgets
=====================
- GraphicsWindow
- GraphicsView
- GraphicsLayoutItem
- ViewBox

73
doc/source/how_to_use.rst Normal file
View 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
View 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`.

Binary file not shown.

After

Width:  |  Height:  |  Size: 67 KiB

View 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
View 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`

View 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
View File

@ -0,0 +1,9 @@
Internals - Extensions to Qt's GraphicsView
===========================================
* GraphicsView
* GraphicsScene (mouse events)
* GraphicsObject
* GraphicsWidget
* ViewBox

View 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)

View 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

View File

@ -0,0 +1,15 @@
ParameterTree API Reference
===========================
Also see the 'parametertree' example included with pyqtgraph
Contents:
.. toctree::
:maxdepth: 2
parameter
parametertree
parametertypes
parameteritem

View 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

View File

@ -0,0 +1,8 @@
Parameter
=========
.. autoclass:: pyqtgraph.parametertree.Parameter
:members:
.. automethod:: pyqtgraph.parametertree.Parameter.__init__

View File

@ -0,0 +1,8 @@
ParameterItem
=============
.. autoclass:: pyqtgraph.parametertree.ParameterItem
:members:
.. automethod:: pyqtgraph.parametertree.ParameterItem.__init__

View File

@ -0,0 +1,8 @@
ParameterTree
=============
.. autoclass:: pyqtgraph.parametertree.ParameterTree
:members:
.. automethod:: pyqtgraph.parametertree.ParameterTree.__init__

View File

@ -0,0 +1,6 @@
Built-in Parameter Types
========================
.. automodule:: pyqtgraph.parametertree.parameterTypes
:members:

73
doc/source/plotting.rst Normal file
View 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

View 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.

View 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
View 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)

View File

@ -0,0 +1,8 @@
BusyCursor
==========
.. autoclass:: pyqtgraph.BusyCursor
:members:
.. automethod:: pyqtgraph.BusyCursor.__init__

View File

@ -0,0 +1,8 @@
CheckTable
==========
.. autoclass:: pyqtgraph.CheckTable
:members:
.. automethod:: pyqtgraph.CheckTable.__init__

View File

@ -0,0 +1,8 @@
ColorButton
===========
.. autoclass:: pyqtgraph.ColorButton
:members:
.. automethod:: pyqtgraph.ColorButton.__init__

View File

@ -0,0 +1,8 @@
ComboBox
========
.. autoclass:: pyqtgraph.ComboBox
:members:
.. automethod:: pyqtgraph.ComboBox.__init__

View File

@ -0,0 +1,8 @@
DataTreeWidget
==============
.. autoclass:: pyqtgraph.DataTreeWidget
:members:
.. automethod:: pyqtgraph.DataTreeWidget.__init__

View File

@ -0,0 +1,5 @@
dockarea module
===============
.. automodule:: pyqtgraph.dockarea
:members:

View File

@ -0,0 +1,8 @@
FeedbackButton
==============
.. autoclass:: pyqtgraph.FeedbackButton
:members:
.. automethod:: pyqtgraph.FeedbackButton.__init__

View File

@ -0,0 +1,8 @@
FileDialog
==========
.. autoclass:: pyqtgraph.FileDialog
:members:
.. automethod:: pyqtgraph.FileDialog.__init__

View File

@ -0,0 +1,8 @@
GradientWidget
==============
.. autoclass:: pyqtgraph.GradientWidget
:members:
.. automethod:: pyqtgraph.GradientWidget.__init__

View File

@ -0,0 +1,8 @@
GraphicsLayoutWidget
====================
.. autoclass:: pyqtgraph.GraphicsLayoutWidget
:members:
.. automethod:: pyqtgraph.GraphicsLayoutWidget.__init__

View File

@ -0,0 +1,8 @@
GraphicsView
============
.. autoclass:: pyqtgraph.GraphicsView
:members:
.. automethod:: pyqtgraph.GraphicsView.__init__

View File

@ -0,0 +1,8 @@
HistogramLUTWidget
==================
.. autoclass:: pyqtgraph.HistogramLUTWidget
:members:
.. automethod:: pyqtgraph.HistogramLUTWidget.__init__

View File

@ -0,0 +1,8 @@
ImageView
=========
.. autoclass:: pyqtgraph.ImageView
:members:
.. automethod:: pyqtgraph.ImageView.__init__

View 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

View 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