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
|
||||
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::
|
||||
|
||||
|
@ -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 ]
|
||||
|
||||
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
|
||||
------------------------------
|
||||
@ -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
|
||||
|
@ -62,7 +62,7 @@ w.addItem(p3)
|
||||
|
||||
## Animated example
|
||||
## compute surface vertex data
|
||||
cols = 100
|
||||
cols = 90
|
||||
rows = 100
|
||||
x = np.linspace(-8, 8, cols+1).reshape(cols+1,1)
|
||||
y = np.linspace(-8, 8, rows+1).reshape(1,rows+1)
|
||||
|
@ -1,4 +1,15 @@
|
||||
# -*- 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)
|
||||
import initExample
|
||||
|
||||
@ -22,9 +33,6 @@ img = img[np.newaxis,:,:]
|
||||
decay = np.exp(-np.linspace(0,0.3,100))[:,np.newaxis,np.newaxis]
|
||||
data = np.random.normal(size=(100, 200, 200))
|
||||
data += img * decay
|
||||
|
||||
#for i in range(data.shape[0]):
|
||||
#data[i] += 10*exp(-(2.*i)/data.shape[0])
|
||||
data += 2
|
||||
|
||||
## Add time-varying signal
|
||||
@ -37,7 +45,7 @@ sig = sig[:,np.newaxis,np.newaxis] * 3
|
||||
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]))
|
||||
|
||||
## Start Qt event loop unless running in interactive mode.
|
||||
|
@ -66,6 +66,7 @@ for i in range(0, 5):
|
||||
|
||||
## Test large numbers
|
||||
curve = pw3.plot(np.random.normal(size=100)*1e0, clickable=True)
|
||||
curve.curve.setClickable(True)
|
||||
curve.setPen('w') ## white pen
|
||||
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.minVals = {}
|
||||
|
||||
def addFields(self, fields):
|
||||
def addFields(self, **fields):
|
||||
for f in fields:
|
||||
if f not in self.fields:
|
||||
self.fields[f] = None
|
||||
|
@ -212,6 +212,19 @@ class Dock(QtGui.QWidget, DockDrop):
|
||||
def __repr__(self):
|
||||
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):
|
||||
|
||||
|
@ -301,5 +301,19 @@ class DockArea(Container, QtGui.QWidget, DockDrop):
|
||||
self.home.removeTempArea(self)
|
||||
#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)
|
||||
QtGui.QGraphicsPathItem.paint(self, p, *args)
|
||||
|
||||
#p.setPen(fn.mkPen('r'))
|
||||
#p.setBrush(fn.mkBrush(None))
|
||||
#p.drawRect(self.boundingRect())
|
||||
|
||||
def shape(self):
|
||||
#if not self.opts['pxMode']:
|
||||
#return QtGui.QGraphicsPathItem.shape(self)
|
||||
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'])
|
||||
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.
|
||||
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.
|
||||
*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%)
|
||||
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]
|
||||
for ax, range in changes.items():
|
||||
if padding is None:
|
||||
xpad = self.suggestPadding(ax)
|
||||
else:
|
||||
xpad = padding
|
||||
mn = min(range)
|
||||
mx = max(range)
|
||||
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
|
||||
mn -= 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])):
|
||||
raise Exception("Not setting range [%s, %s]" % (str(mn), str(mx)))
|
||||
|
||||
p = (mx-mn) * padding
|
||||
p = (mx-mn) * xpad
|
||||
mn -= p
|
||||
mx += p
|
||||
|
||||
@ -412,34 +417,53 @@ class ViewBox(GraphicsWidget):
|
||||
elif changed[1] and self.state['autoVisibleOnly'][0]:
|
||||
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*].
|
||||
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)
|
||||
|
||||
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*].
|
||||
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)
|
||||
|
||||
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.
|
||||
Note that this is not the same as enableAutoRange, which causes the view to
|
||||
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:
|
||||
bounds = self.childrenBoundingRect()
|
||||
bounds = self.childrenBoundingRect(items=items)
|
||||
else:
|
||||
print "Warning: ViewBox.autoRange(item=__) is deprecated. Use 'items' argument instead."
|
||||
bounds = self.mapFromItemToView(item, item.boundingRect()).boundingRect()
|
||||
|
||||
if bounds is not None:
|
||||
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):
|
||||
"""
|
||||
@ -577,9 +601,7 @@ class ViewBox(GraphicsWidget):
|
||||
w2 = (targetRect[ax][1]-targetRect[ax][0]) / 2.
|
||||
childRange[ax] = [x-w2, x+w2]
|
||||
else:
|
||||
l = self.width() if ax==0 else self.height()
|
||||
if l > 0:
|
||||
padding = np.clip(1./(l**0.5), 0.02, 0.1)
|
||||
padding = self.suggestPadding(ax)
|
||||
wp = (xr[1] - xr[0]) * padding
|
||||
childRange[ax][0] -= 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.
|
||||
[[xmin, xmax], [ymin, ymax]]
|
||||
Values may be None if there are no specific bounds for an axis.
|
||||
"""
|
||||
prof = debug.Profiler('updateAutoRange', disabled=True)
|
||||
if items is None:
|
||||
items = self.addedItems
|
||||
|
||||
## 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::
|
||||
|
||||
{'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)
|
||||
|
@ -436,7 +436,7 @@ class MeshData(object):
|
||||
elif self._faceColorsIndexedByFaces is not None:
|
||||
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)
|
||||
|
||||
def restore(self, state):
|
||||
|
@ -127,8 +127,8 @@ class GLSurfacePlotItem(GLMeshItem):
|
||||
|
||||
|
||||
def generateFaces(self):
|
||||
cols = self._z.shape[0]-1
|
||||
rows = self._z.shape[1]-1
|
||||
cols = self._z.shape[1]-1
|
||||
rows = self._z.shape[0]-1
|
||||
faces = np.empty((cols*rows*2, 3), dtype=np.uint)
|
||||
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]])
|
||||
|
Loading…
Reference in New Issue
Block a user