Commit dc29a906 authored by Luke Campagnola's avatar Luke Campagnola
Browse files

documentation updates

parent 61ea0361
......@@ -51,3 +51,21 @@ SI Unit Conversion Functions
.. autofunction:: pyqtgraph.siEval
Image Preparation Functions
---------------------------
.. autofunction:: pyqtgraph.makeARGB
.. autofunction:: pyqtgraph.makeQImage
Mesh Generation Functions
-------------------------
.. autofunction:: pyqtgraph.isocurve
.. autofunction:: pyqtgraph.isosurface
Internals - Extensions to Qt's GraphicsView
================================
===========================================
* GraphicsView
* GraphicsScene (mouse events)
......
......@@ -740,13 +740,13 @@ def rescaleData(data, scale, offset):
def isocurve(data, level):
"""
Generate isocurve from 2D data using marching squares algorithm.
*data* 2D numpy array of scalar values
*level* The level at which to generate an isosurface
This function is SLOW; plenty of room for optimization here.
"""
Generate isocurve from 2D data using marching squares algorithm.
*data* 2D numpy array of scalar values
*level* The level at which to generate an isosurface
This function is SLOW; plenty of room for optimization here.
"""
sideTable = [
[],
......@@ -820,7 +820,7 @@ def isocurve(data, level):
def isosurface(data, level):
"""
Generate isosurface from volumetric data using marching tetrahedra algorithm.
Generate isosurface from volumetric data using marching cubes algorithm.
See Paul Bourke, "Polygonising a Scalar Field"
(http://local.wasp.uwa.edu.au/~pbourke/geometry/polygonise/)
......@@ -1196,60 +1196,3 @@ def isosurface(data, level):
return facets
## code has moved to opengl/MeshData.py
#def meshNormals(data):
#"""
#Return list of normal vectors and list of faces which reference the normals
#data must be list of triangles; each triangle is a list of three points
#[ [(x,y,z), (x,y,z), (x,y,z)], ...]
#Return values are
#normals: [(x,y,z), ...]
#faces: [(n1, n2, n3), ...]
#"""
#normals = []
#points = {}
#for i, face in enumerate(data):
### compute face normal
#pts = [QtGui.QVector3D(*x) for x in face]
#norm = QtGui.QVector3D.crossProduct(pts[1]-pts[0], pts[2]-pts[0])
#normals.append(norm)
### remember each point was associated with this normal
#for p in face:
#p = tuple(map(lambda x: np.round(x, 8), p))
#if p not in points:
#points[p] = []
#points[p].append(i)
### compute averages
#avgLookup = {}
#avgNorms = []
#for k,v in points.iteritems():
#norms = [normals[i] for i in v]
#a = norms[0]
#if len(v) > 1:
#for n in norms[1:]:
#a = a + n
#a = a / len(v)
#avgLookup[k] = len(avgNorms)
#avgNorms.append(a)
### generate return array
#faces = []
#for i, face in enumerate(data):
#f = []
#for p in face:
#p = tuple(map(lambda x: np.round(x, 8), p))
#f.append(avgLookup[p])
#faces.append(tuple(f))
#return avgNorms, faces
......@@ -6,6 +6,7 @@ __all__ = ['GraphicsLayout']
class GraphicsLayout(GraphicsWidget):
"""
Used for laying out GraphicsWidgets in a grid.
This is usually created automatically as part of a :class:`GraphicsWindow <pyqtgraph.GraphicsWindow>` or :class:`GraphicsLayoutWidget <pyqtgraph.GraphicsLayoutWidget>`.
"""
......@@ -33,29 +34,54 @@ class GraphicsLayout(GraphicsWidget):
return self.currentCol-colspan
def nextCol(self, *args, **kargs):
"""Advance to next column for automatic item placement"""
return self.nextColumn(*args, **kargs)
def addPlot(self, row=None, col=None, rowspan=1, colspan=1, **kargs):
"""
Create a PlotItem and place it in the next available cell (or in the cell specified)
All extra keyword arguments are passed to :func:`PlotItem.__init__ <pyqtgraph.PlotItem.__init__>`
Returns the created item.
"""
plot = PlotItem(**kargs)
self.addItem(plot, row, col, rowspan, colspan)
return plot
def addViewBox(self, row=None, col=None, rowspan=1, colspan=1, **kargs):
"""
Create a ViewBox and place it in the next available cell (or in the cell specified)
All extra keyword arguments are passed to :func:`ViewBox.__init__ <pyqtgraph.ViewBox.__init__>`
Returns the created item.
"""
vb = ViewBox(**kargs)
self.addItem(vb, row, col, rowspan, colspan)
return vb
def addLabel(self, text=' ', row=None, col=None, rowspan=1, colspan=1, **kargs):
"""
Create a LabelItem with *text* and place it in the next available cell (or in the cell specified)
All extra keyword arguments are passed to :func:`LabelItem.__init__ <pyqtgraph.LabelItem.__init__>`
Returns the created item.
"""
text = LabelItem(text, **kargs)
self.addItem(text, row, col, rowspan, colspan)
return text
def addLayout(self, row=None, col=None, rowspan=1, colspan=1, **kargs):
"""
Create an empty GraphicsLayout and place it in the next available cell (or in the cell specified)
All extra keyword arguments are passed to :func:`GraphicsLayout.__init__ <pyqtgraph.GraphicsLayout.__init__>`
Returns the created item.
"""
layout = GraphicsLayout(**kargs)
self.addItem(layout, row, col, rowspan, colspan)
return layout
def addItem(self, item, row=None, col=None, rowspan=1, colspan=1):
"""
Add an item to the layout and place it in the next available cell (or in the cell specified).
The item must be an instance of a QGraphicsWidget subclass.
"""
if row is None:
row = self.currentRow
if col is None:
......@@ -69,6 +95,7 @@ class GraphicsLayout(GraphicsWidget):
self.layout.addItem(item, row, col, rowspan, colspan)
def getItem(self, row, col):
"""Return the item in (*row*, *col*)"""
return self.row[row][col]
def boundingRect(self):
......@@ -89,6 +116,7 @@ class GraphicsLayout(GraphicsWidget):
raise Exception("Could not determine index of item " + str(item))
def removeItem(self, item):
"""Remove *item* from the layout."""
ind = self.itemIndex(item)
self.layout.removeAt(ind)
self.scene().removeItem(item)
......
......@@ -55,24 +55,35 @@ except:
class PlotItem(GraphicsWidget):
sigYRangeChanged = QtCore.Signal(object, object)
sigXRangeChanged = QtCore.Signal(object, object)
sigRangeChanged = QtCore.Signal(object, object)
"""
Plot graphics item that can be added to any graphics scene. Implements axis titles, scales, interactive viewbox.
Use plot(...) to create a new PlotDataItem and add it to the view.
Use addItem(...) add any QGraphicsItem to the view
Use :func:`plot() <pyqtgraph.PlotItem.plot>` to create a new PlotDataItem and add it to the view.
Use :func:`addItem() <pyqtgraph.PlotItem.addItem>` to add any QGraphicsItem to the view
This class wraps several methods from its internal ViewBox:
setXRange, setYRange, setXLink, setYLink,
setRange, autoRange, viewRect, setMouseEnabled,
enableAutoRange, disableAutoRange, setAspectLocked,
register, unregister.
:func:`setXRange <pyqtgraph.ViewBox.setXRange>`,
:func:`setYRange <pyqtgraph.ViewBox.setYRange>`,
:func:`setRange <pyqtgraph.ViewBox.setRange>`,
:func:`autoRange <pyqtgraph.ViewBox.autoRange>`,
:func:`setXLink <pyqtgraph.ViewBox.setXLink>`,
:func:`setYLink <pyqtgraph.ViewBox.setYLink>`,
:func:`viewRect <pyqtgraph.ViewBox.viewRect>`,
:func:`setMouseEnabled <pyqtgraph.ViewBox.setMouseEnabled>`,
:func:`enableAutoRange <pyqtgraph.ViewBox.enableAutoRange>`,
:func:`disableAutoRange <pyqtgraph.ViewBox.disableAutoRange>`,
:func:`setAspectLocked <pyqtgraph.ViewBox.setAspectLocked>`,
:func:`register <pyqtgraph.ViewBox.register>`,
:func:`unregister <pyqtgraph.ViewBox.unregister>`
The ViewBox itself can be accessed by calling getVewBox()
The ViewBox itself can be accessed by calling :func:`getViewBox() <pyqtgraph.PlotItem.getViewBox>`
"""
sigRangeChanged = QtCore.Signal(object, object) ## Emitted when the ViewBox range has changed
sigYRangeChanged = QtCore.Signal(object, object) ## Emitted when the ViewBox Y range has changed
sigXRangeChanged = QtCore.Signal(object, object) ## Emitted when the ViewBox X range has changed
lastFileDir = None
managers = {}
......@@ -81,14 +92,18 @@ class PlotItem(GraphicsWidget):
Create a new PlotItem. All arguments are optional.
Any extra keyword arguments are passed to PlotItem.plot().
Arguments:
*title* - Title to display at the top of the item. Html is allowed.
*labels* - A dictionary specifying the axis labels to display.
{'left': (args), 'bottom': (args), ...}
The name of each axis and the corresponding arguments are passed to PlotItem.setLabel()
Optionally, PlotItem my also be initialized with the keyword arguments left,
right, top, or bottom to achieve the same effect.
*name* - Registers a name for this view so that others may link to it
============= ==========================================================================================
**Arguments**
*title* Title to display at the top of the item. Html is allowed.
*labels* A dictionary specifying the axis labels to display::
{'left': (args), 'bottom': (args), ...}
The name of each axis and the corresponding arguments are passed to PlotItem.setLabel()
Optionally, PlotItem my also be initialized with the keyword arguments left,
right, top, or bottom to achieve the same effect.
*name* Registers a name for this view so that others may link to it
============= ==========================================================================================
"""
......@@ -165,7 +180,7 @@ class PlotItem(GraphicsWidget):
'setXRange', 'setYRange', 'setXLink', 'setYLink',
'setRange', 'autoRange', 'viewRect', 'setMouseEnabled',
'enableAutoRange', 'disableAutoRange', 'setAspectLocked',
'register', 'unregister']:
'register', 'unregister']: ## NOTE: If you update this list, please update the class docstring as well.
setattr(self, m, getattr(self.vb, m))
self.items = []
......@@ -779,7 +794,7 @@ class PlotItem(GraphicsWidget):
def plot(self, *args, **kargs):
"""
Add and return a new plot.
See PlotDataItem.__init__ for data arguments
See :func:`PlotDataItem.__init__ <pyqtgraph.PlotDataItem.__init__>` for data arguments
Extra allowed arguments are:
clear - clear all plots before displaying new data
......@@ -1262,13 +1277,16 @@ class PlotItem(GraphicsWidget):
def setLabel(self, axis, text=None, units=None, unitPrefix=None, **args):
"""
Set the label for an axis. Basic HTML formatting is allowed.
Arguments:
axis - must be one of 'left', 'bottom', 'right', or 'top'
text - text to display along the axis. HTML allowed.
units - units to display after the title. If units are given,
then an SI prefix will be automatically appended
and the axis values will be scaled accordingly.
(ie, use 'V' instead of 'mV'; 'm' will be added automatically)
============= =================================================================
**Arguments**
axis must be one of 'left', 'bottom', 'right', or 'top'
text text to display along the axis. HTML allowed.
units units to display after the title. If units are given,
then an SI prefix will be automatically appended
and the axis values will be scaled accordingly.
(ie, use 'V' instead of 'mV'; 'm' will be added automatically)
============= =================================================================
"""
self.getScale(axis).setLabel(text=text, units=units, **args)
......
......@@ -28,6 +28,15 @@ class ChildGroup(ItemGroup):
class ViewBox(GraphicsWidget):
"""
Box that allows internal scaling/panning of children by mouse drag.
This class is usually created automatically as part of a :class:`PlotItem <pyqtgraph.PlotItem>` or :class:`Canvas <pyqtgraph.canvas.Canvas>` or with :func:`GraphicsLayout.addViewBox() <pyqtgraph.GraphicsLayout.addViewBox>`.
Features:
- Scaling contents by mouse or auto-scale when contents change
- View linking--multiple views display the same data ranges
- Configurable by context menu
- Item coordinate mapping methods
Not really compatible with GraphicsView having the same functionality.
"""
......@@ -53,6 +62,21 @@ class ViewBox(GraphicsWidget):
def __init__(self, parent=None, border=None, lockAspect=False, enableMouse=True, invertY=False, name=None):
"""
============= =============================================================
**Arguments**
*parent* (QGraphicsWidget) Optional parent widget
*border* (QPen) Do draw a border around the view, give any
single argument accepted by :func:`mkPen <pyqtgraph.mkPen>`
*lockAspect* (False or float) The aspect ratio to lock the view
coorinates to. (or False to allow the ratio to change)
*enableMouse* (bool) Whether mouse can be used to scale/pan the view
*invertY* (bool) See :func:`invertY <pyqtgraph.ViewBox.invertY>`
============= =============================================================
"""
GraphicsWidget.__init__(self, parent)
self.name = None
self.linksBlocked = False
......@@ -112,7 +136,7 @@ class ViewBox(GraphicsWidget):
self.setAspectLocked(lockAspect)
self.border = border
self.border = fn.mkPen(border)
self.menu = ViewBoxMenu(self)
self.register(name)
......@@ -134,6 +158,9 @@ class ViewBox(GraphicsWidget):
ViewBox.updateAllViewLists()
def unregister(self):
"""
Remove this ViewBox forom the list of linkable views. (see :func:`register() <pyqtgraph.ViewBox.register>`)
"""
del ViewBox.AllViews[self]
if self.name is not None:
del ViewBox.NamedViews[self.name]
......@@ -165,6 +192,11 @@ class ViewBox(GraphicsWidget):
def setMouseMode(self, mode):
"""
Set the mouse interaction mode. *mode* must be either ViewBox.PanMode or ViewBox.RectMode.
In PanMode, the left mouse button pans the view and the right button scales.
In RectMode, the left button draws a rectangle which updates the visible region (this mode is more suitable for single-button mice)
"""
if mode not in [ViewBox.PanMode, ViewBox.RectMode]:
raise Exception("Mode must be ViewBox.PanMode or ViewBox.RectMode")
self.state['mouseMode'] = mode
......@@ -188,6 +220,10 @@ class ViewBox(GraphicsWidget):
return self.childGroup
def setMouseEnabled(self, x=None, y=None):
"""
Set whether each axis is enabled for mouse interaction. *x*, *y* arguments must be True or False.
This allows the user to pan/scale one axis of the view while leaving the other axis unchanged.
"""
if x is not None:
self.state['mouseEnabled'][0] = x
if y is not None:
......@@ -198,6 +234,10 @@ class ViewBox(GraphicsWidget):
return self.state['mouseEnabled'][:]
def addItem(self, item, ignoreBounds=False):
"""
Add a QGraphicsItem to this view. The view will include this item when determining how to set its range
automatically unless *ignoreBounds* is True.
"""
if item.zValue() < self.zValue():
item.setZValue(self.zValue()+1)
item.setParentItem(self.childGroup)
......@@ -207,6 +247,7 @@ class ViewBox(GraphicsWidget):
#print "addItem:", item, item.boundingRect()
def removeItem(self, item):
"""Remove an item from this view."""
try:
self.addedItems.remove(item)
except:
......@@ -223,6 +264,7 @@ class ViewBox(GraphicsWidget):
#self.linkedYChanged()
def viewRange(self):
"""Return a the view's visible range as a list: [[xmin, xmax], [ymin, ymax]]"""
return [x[:] for x in self.state['viewRange']] ## return copy
def viewRect(self):
......@@ -261,12 +303,14 @@ class ViewBox(GraphicsWidget):
Set the visible range of the ViewBox.
Must specify at least one of *range*, *xRange*, or *yRange*.
Arguments:
*rect* (QRectF) - The full range that should be visible in the view box.
*xRange* (min,max) - The range that should be visible along the x-axis.
*yRange* (min,max) - The range that should be visible along the y-axis.
*padding* (float) - Expand the view by a fraction of the requested range
By default, this value is 0.02 (2%)
============= =====================================================================
**Arguments**
*rect* (QRectF) The full range that should be visible in the view box.
*xRange* (min,max) The range that should be visible along the x-axis.
*yRange* (min,max) The range that should be visible along the y-axis.
*padding* (float) Expand the view by a fraction of the requested range.
By default, this value is 0.02 (2%)
============= =====================================================================
"""
changes = {}
......@@ -326,14 +370,24 @@ class ViewBox(GraphicsWidget):
def setYRange(self, min, max, padding=0.02, update=True):
"""
Set the visible Y range of the view to [*min*, *max*].
The *padding* argument causes the range to be set larger by the fraction specified.
"""
self.setRange(yRange=[min, max], update=update, padding=padding)
def setXRange(self, min, max, padding=0.02, update=True):
"""
Set the visible X range of the view to [*min*, *max*].
The *padding* argument causes the range to be set larger by the fraction specified.
"""
self.setRange(xRange=[min, max], update=update, padding=padding)
def autoRange(self, padding=0.02):
"""
Set the range of the view box to make all children visible.
Note that this is not the same as enableAutoRange, which causes the view to
automatically auto-range whenever its contents are changed.
"""
bounds = self.childrenBoundingRect()
if bounds is not None:
......@@ -404,6 +458,7 @@ class ViewBox(GraphicsWidget):
self.sigStateChanged.emit(self)
def disableAutoRange(self, axis=None):
"""Disables auto-range. (See enableAutoRange)"""
self.enableAutoRange(axis, enable=False)
def autoRangeEnabled(self):
......@@ -433,9 +488,11 @@ class ViewBox(GraphicsWidget):
self.setRange(tr, padding=0, disableAutoRange=False)
def setXLink(self, view):
"""Link this view's X axis to another view. (see LinkView)"""
self.linkView(self.XAxis, view)
def setYLink(self, view):
"""Link this view's Y axis to another view. (see LinkView)"""
self.linkView(self.YAxis, view)
......@@ -610,10 +667,12 @@ class ViewBox(GraphicsWidget):
return self.mapToScene(self.mapFromView(obj))
def mapFromItemToView(self, item, obj):
"""Maps *obj* from the local coordinate system of *item* to the view coordinates"""
return self.childGroup.mapFromItem(item, obj)
#return self.mapSceneToView(item.mapToScene(obj))
def mapFromViewToItem(self, item, obj):
"""Maps *obj* from view coordinates to the local coordinate system of *item*."""
return self.childGroup.mapToItem(item, obj)
#return item.mapFromScene(self.mapViewToScene(obj))
......@@ -963,19 +1022,19 @@ class ViewBox(GraphicsWidget):
#p.fillRect(bounds, QtGui.QColor(0, 0, 0))
p.drawPath(bounds)
def saveSvg(self):
pass
#def saveSvg(self):
#pass
def saveImage(self):
pass
#def saveImage(self):
#pass
def savePrint(self):
printer = QtGui.QPrinter()
if QtGui.QPrintDialog(printer).exec_() == QtGui.QDialog.Accepted:
p = QtGui.QPainter(printer)
p.setRenderHint(p.Antialiasing)
self.scene().render(p)
p.end()
#def savePrint(self):
#printer = QtGui.QPrinter()
#if QtGui.QPrintDialog(printer).exec_() == QtGui.QDialog.Accepted:
#p = QtGui.QPainter(printer)
#p.setRenderHint(p.Antialiasing)
#self.scene().render(p)
#p.end()
def updateViewLists(self):
def cmpViews(a, b):
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment