doc updates
ViewBox: made padding more consistent for all auto-ranging methods, deprecated autoRange(item=) in favor of autoRange(items=)
This commit is contained in:
parent
86861b5a06
commit
412e1d2ec8
@ -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
|
||||
|
@ -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
|
||||
|
@ -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,12 +601,10 @@ 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)
|
||||
wp = (xr[1] - xr[0]) * padding
|
||||
childRange[ax][0] -= wp
|
||||
childRange[ax][1] += wp
|
||||
padding = self.suggestPadding(ax)
|
||||
wp = (xr[1] - xr[0]) * padding
|
||||
childRange[ax][0] -= wp
|
||||
childRange[ax][1] += wp
|
||||
targetRect[ax] = childRange[ax]
|
||||
args['xRange' if ax == 0 else 'yRange'] = targetRect[ax]
|
||||
if len(args) == 0:
|
||||
@ -995,13 +1017,14 @@ 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)
|
||||
items = self.addedItems
|
||||
if items is None:
|
||||
items = self.addedItems
|
||||
|
||||
## measure pixel dimensions in view box
|
||||
px, py = [v.length() if v is not None else 0 for v in self.childGroup.pixelVectors()]
|
||||
|
Loading…
Reference in New Issue
Block a user