merge from inp, removed print statement
This commit is contained in:
commit
21dff0525a
@ -17,7 +17,7 @@ Pyqtgraph makes it very easy to visualize data from the command line. Observe::
|
|||||||
import pyqtgraph as pg
|
import pyqtgraph as pg
|
||||||
pg.plot(data) # data can be a list of values or a numpy array
|
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.
|
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. **Note:** interactive plotting from the python prompt is only available with PyQt; PySide does not run the Qt event loop while the interactive prompt is running. If you wish to use pyqtgraph interactively with PySide, see the 'console' :ref:`example <examples>`.
|
||||||
|
|
||||||
Further examples::
|
Further examples::
|
||||||
|
|
||||||
|
@ -66,6 +66,12 @@ Signals, Slots, and Events
|
|||||||
|
|
||||||
[ to be continued.. please post a request on the pyqtgraph forum if you'd like to read more ]
|
[ to be continued.. please post a request on the pyqtgraph forum if you'd like to read more ]
|
||||||
|
|
||||||
|
Qt detects and reacts to user interaction by executing its *event loop*.
|
||||||
|
|
||||||
|
- what happens in the event loop?
|
||||||
|
- when do I need to use QApplication.exec_() ?
|
||||||
|
- what control do I have over event loop execution? (QApplication.processEvents)
|
||||||
|
|
||||||
|
|
||||||
GraphicsView and GraphicsItems
|
GraphicsView and GraphicsItems
|
||||||
------------------------------
|
------------------------------
|
||||||
@ -79,8 +85,8 @@ Mouse and Keyboard Input
|
|||||||
------------------------
|
------------------------
|
||||||
|
|
||||||
|
|
||||||
QTimer, the Event Loop, and Multi-Threading
|
QTimer, Multi-Threading
|
||||||
-------------------------------------------
|
-----------------------
|
||||||
|
|
||||||
|
|
||||||
Multi-threading vs Multi-processing in Qt
|
Multi-threading vs Multi-processing in Qt
|
||||||
|
@ -62,7 +62,7 @@ w.addItem(p3)
|
|||||||
|
|
||||||
## Animated example
|
## Animated example
|
||||||
## compute surface vertex data
|
## compute surface vertex data
|
||||||
cols = 100
|
cols = 90
|
||||||
rows = 100
|
rows = 100
|
||||||
x = np.linspace(-8, 8, cols+1).reshape(cols+1,1)
|
x = np.linspace(-8, 8, cols+1).reshape(cols+1,1)
|
||||||
y = np.linspace(-8, 8, rows+1).reshape(1,rows+1)
|
y = np.linspace(-8, 8, rows+1).reshape(1,rows+1)
|
||||||
|
@ -1,4 +1,15 @@
|
|||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
|
"""
|
||||||
|
This example demonstrates the use of ImageView, which is a high-level widget for
|
||||||
|
displaying and analyzing 2D and 3D data. ImageView provides:
|
||||||
|
|
||||||
|
1. A zoomable region (ViewBox) for displaying the image
|
||||||
|
2. A combination histogram and gradient editor (HistogramLUTItem) for
|
||||||
|
controlling the visual appearance of the image
|
||||||
|
3. A timeline for selecting the currently displayed frame (for 3D data only).
|
||||||
|
4. Tools for very basic analysis of image data (see ROI and Norm buttons)
|
||||||
|
|
||||||
|
"""
|
||||||
## Add path to library (just for examples; you do not need this)
|
## Add path to library (just for examples; you do not need this)
|
||||||
import initExample
|
import initExample
|
||||||
|
|
||||||
@ -22,9 +33,6 @@ img = img[np.newaxis,:,:]
|
|||||||
decay = np.exp(-np.linspace(0,0.3,100))[:,np.newaxis,np.newaxis]
|
decay = np.exp(-np.linspace(0,0.3,100))[:,np.newaxis,np.newaxis]
|
||||||
data = np.random.normal(size=(100, 200, 200))
|
data = np.random.normal(size=(100, 200, 200))
|
||||||
data += img * decay
|
data += img * decay
|
||||||
|
|
||||||
#for i in range(data.shape[0]):
|
|
||||||
#data[i] += 10*exp(-(2.*i)/data.shape[0])
|
|
||||||
data += 2
|
data += 2
|
||||||
|
|
||||||
## Add time-varying signal
|
## Add time-varying signal
|
||||||
@ -37,7 +45,7 @@ sig = sig[:,np.newaxis,np.newaxis] * 3
|
|||||||
data[:,50:60,50:60] += sig
|
data[:,50:60,50:60] += sig
|
||||||
|
|
||||||
|
|
||||||
## Display the data
|
## Display the data and assign each frame a time value from 1.0 to 3.0
|
||||||
imv.setImage(data, xvals=np.linspace(1., 3., data.shape[0]))
|
imv.setImage(data, xvals=np.linspace(1., 3., data.shape[0]))
|
||||||
|
|
||||||
## Start Qt event loop unless running in interactive mode.
|
## Start Qt event loop unless running in interactive mode.
|
||||||
|
@ -66,6 +66,7 @@ for i in range(0, 5):
|
|||||||
|
|
||||||
## Test large numbers
|
## Test large numbers
|
||||||
curve = pw3.plot(np.random.normal(size=100)*1e0, clickable=True)
|
curve = pw3.plot(np.random.normal(size=100)*1e0, clickable=True)
|
||||||
|
curve.curve.setClickable(True)
|
||||||
curve.setPen('w') ## white pen
|
curve.setPen('w') ## white pen
|
||||||
curve.setShadowPen(pg.mkPen((70,70,30), width=6, cosmetic=True))
|
curve.setShadowPen(pg.mkPen((70,70,30), width=6, cosmetic=True))
|
||||||
|
|
||||||
|
@ -22,7 +22,7 @@ class PlotData(object):
|
|||||||
self.maxVals = {} ## cache for max/min
|
self.maxVals = {} ## cache for max/min
|
||||||
self.minVals = {}
|
self.minVals = {}
|
||||||
|
|
||||||
def addFields(self, fields):
|
def addFields(self, **fields):
|
||||||
for f in fields:
|
for f in fields:
|
||||||
if f not in self.fields:
|
if f not in self.fields:
|
||||||
self.fields[f] = None
|
self.fields[f] = None
|
||||||
|
@ -212,6 +212,19 @@ class Dock(QtGui.QWidget, DockDrop):
|
|||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return "<Dock %s %s>" % (self.name(), self.stretch())
|
return "<Dock %s %s>" % (self.name(), self.stretch())
|
||||||
|
|
||||||
|
## PySide bug: We need to explicitly redefine these methods
|
||||||
|
## or else drag/drop events will not be delivered.
|
||||||
|
def dragEnterEvent(self, *args):
|
||||||
|
DockDrop.dragEnterEvent(self, *args)
|
||||||
|
|
||||||
|
def dragMoveEvent(self, *args):
|
||||||
|
DockDrop.dragMoveEvent(self, *args)
|
||||||
|
|
||||||
|
def dragLeaveEvent(self, *args):
|
||||||
|
DockDrop.dragLeaveEvent(self, *args)
|
||||||
|
|
||||||
|
def dropEvent(self, *args):
|
||||||
|
DockDrop.dropEvent(self, *args)
|
||||||
|
|
||||||
class DockLabel(VerticalLabel):
|
class DockLabel(VerticalLabel):
|
||||||
|
|
||||||
|
@ -301,5 +301,19 @@ class DockArea(Container, QtGui.QWidget, DockDrop):
|
|||||||
self.home.removeTempArea(self)
|
self.home.removeTempArea(self)
|
||||||
#self.close()
|
#self.close()
|
||||||
|
|
||||||
|
## PySide bug: We need to explicitly redefine these methods
|
||||||
|
## or else drag/drop events will not be delivered.
|
||||||
|
def dragEnterEvent(self, *args):
|
||||||
|
DockDrop.dragEnterEvent(self, *args)
|
||||||
|
|
||||||
|
def dragMoveEvent(self, *args):
|
||||||
|
DockDrop.dragMoveEvent(self, *args)
|
||||||
|
|
||||||
|
def dragLeaveEvent(self, *args):
|
||||||
|
DockDrop.dragLeaveEvent(self, *args)
|
||||||
|
|
||||||
|
def dropEvent(self, *args):
|
||||||
|
DockDrop.dropEvent(self, *args)
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -85,7 +85,40 @@ class ArrowItem(QtGui.QGraphicsPathItem):
|
|||||||
p.setRenderHint(QtGui.QPainter.Antialiasing)
|
p.setRenderHint(QtGui.QPainter.Antialiasing)
|
||||||
QtGui.QGraphicsPathItem.paint(self, p, *args)
|
QtGui.QGraphicsPathItem.paint(self, p, *args)
|
||||||
|
|
||||||
|
#p.setPen(fn.mkPen('r'))
|
||||||
|
#p.setBrush(fn.mkBrush(None))
|
||||||
|
#p.drawRect(self.boundingRect())
|
||||||
|
|
||||||
def shape(self):
|
def shape(self):
|
||||||
#if not self.opts['pxMode']:
|
#if not self.opts['pxMode']:
|
||||||
#return QtGui.QGraphicsPathItem.shape(self)
|
#return QtGui.QGraphicsPathItem.shape(self)
|
||||||
return self.path
|
return self.path
|
||||||
|
|
||||||
|
## dataBounds and pixelPadding methods are provided to ensure ViewBox can
|
||||||
|
## properly auto-range
|
||||||
|
def dataBounds(self, ax, frac, orthoRange=None):
|
||||||
|
pw = 0
|
||||||
|
pen = self.pen()
|
||||||
|
if not pen.isCosmetic():
|
||||||
|
pw = pen.width() * 0.7072
|
||||||
|
if self.opts['pxMode']:
|
||||||
|
return [0,0]
|
||||||
|
else:
|
||||||
|
br = self.boundingRect()
|
||||||
|
if ax == 0:
|
||||||
|
return [br.left()-pw, br.right()+pw]
|
||||||
|
else:
|
||||||
|
return [br.top()-pw, br.bottom()+pw]
|
||||||
|
|
||||||
|
def pixelPadding(self):
|
||||||
|
pad = 0
|
||||||
|
if self.opts['pxMode']:
|
||||||
|
br = self.boundingRect()
|
||||||
|
pad += (br.width()**2 + br.height()**2) ** 0.5
|
||||||
|
pen = self.pen()
|
||||||
|
if pen.isCosmetic():
|
||||||
|
pad += max(1, pen.width()) * 0.7072
|
||||||
|
return pad
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -336,7 +336,7 @@ class ViewBox(GraphicsWidget):
|
|||||||
print("make qrectf failed:", self.state['targetRange'])
|
print("make qrectf failed:", self.state['targetRange'])
|
||||||
raise
|
raise
|
||||||
|
|
||||||
def setRange(self, rect=None, xRange=None, yRange=None, padding=0.02, update=True, disableAutoRange=True):
|
def setRange(self, rect=None, xRange=None, yRange=None, padding=None, update=True, disableAutoRange=True):
|
||||||
"""
|
"""
|
||||||
Set the visible range of the ViewBox.
|
Set the visible range of the ViewBox.
|
||||||
Must specify at least one of *range*, *xRange*, or *yRange*.
|
Must specify at least one of *range*, *xRange*, or *yRange*.
|
||||||
@ -347,7 +347,8 @@ class ViewBox(GraphicsWidget):
|
|||||||
*xRange* (min,max) The range that should be visible along the x-axis.
|
*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.
|
*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.
|
*padding* (float) Expand the view by a fraction of the requested range.
|
||||||
By default, this value is 0.02 (2%)
|
By default, this value is set between 0.02 and 0.1 depending on
|
||||||
|
the size of the ViewBox.
|
||||||
============= =====================================================================
|
============= =====================================================================
|
||||||
|
|
||||||
"""
|
"""
|
||||||
@ -367,6 +368,10 @@ class ViewBox(GraphicsWidget):
|
|||||||
|
|
||||||
changed = [False, False]
|
changed = [False, False]
|
||||||
for ax, range in changes.items():
|
for ax, range in changes.items():
|
||||||
|
if padding is None:
|
||||||
|
xpad = self.suggestPadding(ax)
|
||||||
|
else:
|
||||||
|
xpad = padding
|
||||||
mn = min(range)
|
mn = min(range)
|
||||||
mx = max(range)
|
mx = max(range)
|
||||||
if mn == mx: ## If we requested 0 range, try to preserve previous scale. Otherwise just pick an arbitrary scale.
|
if mn == mx: ## If we requested 0 range, try to preserve previous scale. Otherwise just pick an arbitrary scale.
|
||||||
@ -375,11 +380,11 @@ class ViewBox(GraphicsWidget):
|
|||||||
dy = 1
|
dy = 1
|
||||||
mn -= dy*0.5
|
mn -= dy*0.5
|
||||||
mx += dy*0.5
|
mx += dy*0.5
|
||||||
padding = 0.0
|
xpad = 0.0
|
||||||
if any(np.isnan([mn, mx])) or any(np.isinf([mn, mx])):
|
if any(np.isnan([mn, mx])) or any(np.isinf([mn, mx])):
|
||||||
raise Exception("Not setting range [%s, %s]" % (str(mn), str(mx)))
|
raise Exception("Not setting range [%s, %s]" % (str(mn), str(mx)))
|
||||||
|
|
||||||
p = (mx-mn) * padding
|
p = (mx-mn) * xpad
|
||||||
mn -= p
|
mn -= p
|
||||||
mx += p
|
mx += p
|
||||||
|
|
||||||
@ -412,34 +417,53 @@ class ViewBox(GraphicsWidget):
|
|||||||
elif changed[1] and self.state['autoVisibleOnly'][0]:
|
elif changed[1] and self.state['autoVisibleOnly'][0]:
|
||||||
self.updateAutoRange()
|
self.updateAutoRange()
|
||||||
|
|
||||||
def setYRange(self, min, max, padding=0.02, update=True):
|
def setYRange(self, min, max, padding=None, update=True):
|
||||||
"""
|
"""
|
||||||
Set the visible Y range of the view to [*min*, *max*].
|
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.
|
The *padding* argument causes the range to be set larger by the fraction specified.
|
||||||
|
(by default, this value is between 0.02 and 0.1 depending on the size of the ViewBox)
|
||||||
"""
|
"""
|
||||||
self.setRange(yRange=[min, max], update=update, padding=padding)
|
self.setRange(yRange=[min, max], update=update, padding=padding)
|
||||||
|
|
||||||
def setXRange(self, min, max, padding=0.02, update=True):
|
def setXRange(self, min, max, padding=None, update=True):
|
||||||
"""
|
"""
|
||||||
Set the visible X range of the view to [*min*, *max*].
|
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.
|
The *padding* argument causes the range to be set larger by the fraction specified.
|
||||||
|
(by default, this value is between 0.02 and 0.1 depending on the size of the ViewBox)
|
||||||
"""
|
"""
|
||||||
self.setRange(xRange=[min, max], update=update, padding=padding)
|
self.setRange(xRange=[min, max], update=update, padding=padding)
|
||||||
|
|
||||||
def autoRange(self, padding=0.02, item=None):
|
def autoRange(self, padding=None, items=None, item=None):
|
||||||
"""
|
"""
|
||||||
Set the range of the view box to make all children visible.
|
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
|
Note that this is not the same as enableAutoRange, which causes the view to
|
||||||
automatically auto-range whenever its contents are changed.
|
automatically auto-range whenever its contents are changed.
|
||||||
|
|
||||||
|
=========== ============================================================
|
||||||
|
Arguments
|
||||||
|
padding The fraction of the total data range to add on to the final
|
||||||
|
visible range. By default, this value is set between 0.02
|
||||||
|
and 0.1 depending on the size of the ViewBox.
|
||||||
|
items If specified, this is a list of items to consider when
|
||||||
|
determining the visible range.
|
||||||
|
=========== ============================================================
|
||||||
"""
|
"""
|
||||||
if item is None:
|
if item is None:
|
||||||
bounds = self.childrenBoundingRect()
|
bounds = self.childrenBoundingRect(items=items)
|
||||||
else:
|
else:
|
||||||
|
print "Warning: ViewBox.autoRange(item=__) is deprecated. Use 'items' argument instead."
|
||||||
bounds = self.mapFromItemToView(item, item.boundingRect()).boundingRect()
|
bounds = self.mapFromItemToView(item, item.boundingRect()).boundingRect()
|
||||||
|
|
||||||
if bounds is not None:
|
if bounds is not None:
|
||||||
self.setRange(bounds, padding=padding)
|
self.setRange(bounds, padding=padding)
|
||||||
|
|
||||||
|
def suggestPadding(self, axis):
|
||||||
|
l = self.width() if axis==0 else self.height()
|
||||||
|
if l > 0:
|
||||||
|
padding = np.clip(1./(l**0.5), 0.02, 0.1)
|
||||||
|
else:
|
||||||
|
padding = 0.02
|
||||||
|
return padding
|
||||||
|
|
||||||
def scaleBy(self, s, center=None):
|
def scaleBy(self, s, center=None):
|
||||||
"""
|
"""
|
||||||
@ -577,9 +601,7 @@ class ViewBox(GraphicsWidget):
|
|||||||
w2 = (targetRect[ax][1]-targetRect[ax][0]) / 2.
|
w2 = (targetRect[ax][1]-targetRect[ax][0]) / 2.
|
||||||
childRange[ax] = [x-w2, x+w2]
|
childRange[ax] = [x-w2, x+w2]
|
||||||
else:
|
else:
|
||||||
l = self.width() if ax==0 else self.height()
|
padding = self.suggestPadding(ax)
|
||||||
if l > 0:
|
|
||||||
padding = np.clip(1./(l**0.5), 0.02, 0.1)
|
|
||||||
wp = (xr[1] - xr[0]) * padding
|
wp = (xr[1] - xr[0]) * padding
|
||||||
childRange[ax][0] -= wp
|
childRange[ax][0] -= wp
|
||||||
childRange[ax][1] += wp
|
childRange[ax][1] += wp
|
||||||
@ -995,12 +1017,13 @@ class ViewBox(GraphicsWidget):
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
def childrenBounds(self, frac=None, orthoRange=(None,None)):
|
def childrenBounds(self, frac=None, orthoRange=(None,None), items=None):
|
||||||
"""Return the bounding range of all children.
|
"""Return the bounding range of all children.
|
||||||
[[xmin, xmax], [ymin, ymax]]
|
[[xmin, xmax], [ymin, ymax]]
|
||||||
Values may be None if there are no specific bounds for an axis.
|
Values may be None if there are no specific bounds for an axis.
|
||||||
"""
|
"""
|
||||||
prof = debug.Profiler('updateAutoRange', disabled=True)
|
prof = debug.Profiler('updateAutoRange', disabled=True)
|
||||||
|
if items is None:
|
||||||
items = self.addedItems
|
items = self.addedItems
|
||||||
|
|
||||||
## measure pixel dimensions in view box
|
## measure pixel dimensions in view box
|
||||||
|
@ -206,6 +206,11 @@ class ImageView(QtGui.QWidget):
|
|||||||
This is only needed to override the default guess. Format is::
|
This is only needed to override the default guess. Format is::
|
||||||
|
|
||||||
{'t':0, 'x':1, 'y':2, 'c':3};
|
{'t':0, 'x':1, 'y':2, 'c':3};
|
||||||
|
|
||||||
|
*pos* Change the position of the displayed image
|
||||||
|
*scale* Change the scale of the displayed image
|
||||||
|
*transform* Set the transform of the dispalyed image. This option overrides *pos*
|
||||||
|
and *scale*.
|
||||||
============== =======================================================================
|
============== =======================================================================
|
||||||
"""
|
"""
|
||||||
prof = debug.Profiler('ImageView.setImage', disabled=True)
|
prof = debug.Profiler('ImageView.setImage', disabled=True)
|
||||||
|
@ -436,7 +436,7 @@ class MeshData(object):
|
|||||||
elif self._faceColorsIndexedByFaces is not None:
|
elif self._faceColorsIndexedByFaces is not None:
|
||||||
names.append('_faceColorsIndexedByFaces')
|
names.append('_faceColorsIndexedByFaces')
|
||||||
|
|
||||||
state = {n:getattr(self, n) for n in names}
|
state = dict([(n,getattr(self, n)) for n in names])
|
||||||
return pickle.dumps(state)
|
return pickle.dumps(state)
|
||||||
|
|
||||||
def restore(self, state):
|
def restore(self, state):
|
||||||
|
@ -127,8 +127,8 @@ class GLSurfacePlotItem(GLMeshItem):
|
|||||||
|
|
||||||
|
|
||||||
def generateFaces(self):
|
def generateFaces(self):
|
||||||
cols = self._z.shape[0]-1
|
cols = self._z.shape[1]-1
|
||||||
rows = self._z.shape[1]-1
|
rows = self._z.shape[0]-1
|
||||||
faces = np.empty((cols*rows*2, 3), dtype=np.uint)
|
faces = np.empty((cols*rows*2, 3), dtype=np.uint)
|
||||||
rowtemplate1 = np.arange(cols).reshape(cols, 1) + np.array([[0, 1, cols+1]])
|
rowtemplate1 = np.arange(cols).reshape(cols, 1) + np.array([[0, 1, cols+1]])
|
||||||
rowtemplate2 = np.arange(cols).reshape(cols, 1) + np.array([[cols+1, 1, cols+2]])
|
rowtemplate2 = np.arange(cols).reshape(cols, 1) + np.array([[cols+1, 1, cols+2]])
|
||||||
|
Loading…
Reference in New Issue
Block a user