def __init__(self, *args, **kargs): """ There are many different ways to create a PlotDataItem: **Data initialization arguments:** (x,y data only) =================================== ====================================== PlotDataItem(xValues, yValues) x and y values may be any sequence (including ndarray) of real numbers PlotDataItem(yValues) y values only -- x will be automatically set to range(len(y)) PlotDataItem(x=xValues, y=yValues) x and y given by keyword arguments PlotDataItem(ndarray(Nx2)) numpy array with shape (N, 2) where x=data[:,0] and y=data[:,1] =================================== ====================================== **Data initialization arguments:** (x,y data AND may include spot style) =========================== ========================================= PlotDataItem(recarray) numpy array with dtype=[('x', float), ('y', float), ...] PlotDataItem(list-of-dicts) [{'x': x, 'y': y, ...}, ...] PlotDataItem(dict-of-lists) {'x': [...], 'y': [...], ...} PlotDataItem(MetaArray) 1D array of Y values with X sepecified as axis values OR 2D array with a column 'y' and extra columns as needed. =========================== ========================================= **Line style keyword arguments:** ========== ================================================ pen pen to use for drawing line between points. Default is solid grey, 1px width. Use None to disable line drawing. May be any single argument accepted by :func:`mkPen() <pyqtgraph.mkPen>` shadowPen pen for secondary line to draw behind the primary line. disabled by default. May be any single argument accepted by :func:`mkPen() <pyqtgraph.mkPen>` fillLevel fill the area between the curve and fillLevel fillBrush fill to use when fillLevel is specified May be any single argument accepted by :func:`mkBrush() <pyqtgraph.mkBrush>` ========== ================================================ **Point style keyword arguments:** ============ ================================================ symbol (str) symbol to use for drawing points OR list of symbols, one per point. Default is no symbol. options are o, s, t, d, + symbolPen outline pen for drawing points OR list of pens, one per point May be any single argument accepted by :func:`mkPen() <pyqtgraph.mkPen>` symbolBrush brush for filling points OR list of brushes, one per point May be any single argument accepted by :func:`mkBrush() <pyqtgraph.mkBrush>` symbolSize diameter of symbols OR list of diameters pxMode (bool) If True, then symbolSize is specified in pixels. If False, then symbolSize is specified in data coordinates. ============ ================================================ **Optimization keyword arguments:** ========== ================================================ identical spots are all identical. The spot image will be rendered only once and repeated for every point decimate (int) decimate data ========== ================================================ **Meta-info keyword arguments:** ========== ================================================ name name of dataset. This would appear in a legend ========== ================================================ """ GraphicsObject.__init__(self) self.setFlag(self.ItemHasNoContents) self.xData = None self.yData = None self.xDisp = None self.yDisp = None #self.curves = [] #self.scatters = [] self.curve = PlotCurveItem() self.scatter = ScatterPlotItem() self.curve.setParentItem(self) self.scatter.setParentItem(self) self.curve.sigClicked.connect(self.curveClicked) self.scatter.sigClicked.connect(self.scatterClicked) #self.clear() self.opts = { 'fftMode': False, 'logMode': [False, False], 'downsample': False, 'alphaHint': 1.0, 'alphaMode': False, 'pen': (200,200,200), 'shadowPen': None, 'fillLevel': None, 'fillBrush': None, 'symbol': None, 'symbolSize': 10, 'symbolPen': (200,200,200), 'symbolBrush': (50, 50, 150), 'identical': False, 'data': None, } self.setData(*args, **kargs)
def __init__(self, *args, **kargs): """ There are many different ways to create a PlotDataItem: **Data initialization arguments:** (x,y data only) =================================== ====================================== PlotDataItem(xValues, yValues) x and y values may be any sequence (including ndarray) of real numbers PlotDataItem(yValues) y values only -- x will be automatically set to range(len(y)) PlotDataItem(x=xValues, y=yValues) x and y given by keyword arguments PlotDataItem(ndarray(Nx2)) numpy array with shape (N, 2) where x=data[:,0] and y=data[:,1] =================================== ====================================== **Data initialization arguments:** (x,y data AND may include spot style) =========================== ========================================= PlotDataItem(recarray) numpy array with dtype=[('x', float), ('y', float), ...] PlotDataItem(list-of-dicts) [{'x': x, 'y': y, ...}, ...] PlotDataItem(dict-of-lists) {'x': [...], 'y': [...], ...} PlotDataItem(MetaArray) 1D array of Y values with X sepecified as axis values OR 2D array with a column 'y' and extra columns as needed. =========================== ========================================= **Line style keyword arguments:** ========== ================================================ pen pen to use for drawing line between points. Default is solid grey, 1px width. Use None to disable line drawing. May be any single argument accepted by :func:`mkPen() <pyqtgraph.mkPen>` shadowPen pen for secondary line to draw behind the primary line. disabled by default. May be any single argument accepted by :func:`mkPen() <pyqtgraph.mkPen>` fillLevel fill the area between the curve and fillLevel fillBrush fill to use when fillLevel is specified May be any single argument accepted by :func:`mkBrush() <pyqtgraph.mkBrush>` ========== ================================================ **Point style keyword arguments:** ============ ================================================ symbol (str) symbol to use for drawing points OR list of symbols, one per point. Default is no symbol. options are o, s, t, d, + symbolPen outline pen for drawing points OR list of pens, one per point May be any single argument accepted by :func:`mkPen() <pyqtgraph.mkPen>` symbolBrush brush for filling points OR list of brushes, one per point May be any single argument accepted by :func:`mkBrush() <pyqtgraph.mkBrush>` symbolSize diameter of symbols OR list of diameters pxMode (bool) If True, then symbolSize is specified in pixels. If False, then symbolSize is specified in data coordinates. ============ ================================================ **Optimization keyword arguments:** ========== ================================================ identical spots are all identical. The spot image will be rendered only once and repeated for every point decimate (int) decimate data ========== ================================================ **Meta-info keyword arguments:** ========== ================================================ name name of dataset. This would appear in a legend ========== ================================================ """ GraphicsObject.__init__(self) self.setFlag(self.ItemHasNoContents) self.xData = None self.yData = None self.xDisp = None self.yDisp = None #self.curves = [] #self.scatters = [] self.curve = PlotCurveItem() self.scatter = ScatterPlotItem() self.curve.setParentItem(self) self.scatter.setParentItem(self) self.curve.sigClicked.connect(self.curveClicked) self.scatter.sigClicked.connect(self.scatterClicked) #self.clear() self.opts = { 'fftMode': False, 'logMode': [False, False], 'downsample': False, 'alphaHint': 1.0, 'alphaMode': False, 'pen': (200, 200, 200), 'shadowPen': None, 'fillLevel': None, 'fillBrush': None, 'symbol': None, 'symbolSize': 10, 'symbolPen': (200, 200, 200), 'symbolBrush': (50, 50, 150), 'identical': False, 'data': None, } self.setData(*args, **kargs)
class PlotDataItem(GraphicsObject): """ **Bases:** :class:`GraphicsObject <pyqtgraph.GraphicsObject>` GraphicsItem for displaying plot curves, scatter plots, or both. While it is possible to use :class:`PlotCurveItem <pyqtgraph.PlotCurveItem>` or :class:`ScatterPlotItem <pyqtgraph.ScatterPlotItem>` individually, this class provides a unified interface to both. Inspances of :class:`PlotDataItem` are usually created by plot() methods such as :func:`pyqtgraph.plot` and :func:`PlotItem.plot() <pyqtgraph.PlotItem.plot>`. ============================== ============================================== **Signals:** sigPlotChanged(self) Emitted when the data in this item is updated. sigClicked(self) Emitted when the item is clicked. sigPointsClicked(self, points) Emitted when a plot point is clicked Sends the list of points under the mouse. ============================== ============================================== """ sigPlotChanged = QtCore.Signal(object) sigClicked = QtCore.Signal(object) sigPointsClicked = QtCore.Signal(object, object) def __init__(self, *args, **kargs): """ There are many different ways to create a PlotDataItem: **Data initialization arguments:** (x,y data only) =================================== ====================================== PlotDataItem(xValues, yValues) x and y values may be any sequence (including ndarray) of real numbers PlotDataItem(yValues) y values only -- x will be automatically set to range(len(y)) PlotDataItem(x=xValues, y=yValues) x and y given by keyword arguments PlotDataItem(ndarray(Nx2)) numpy array with shape (N, 2) where x=data[:,0] and y=data[:,1] =================================== ====================================== **Data initialization arguments:** (x,y data AND may include spot style) =========================== ========================================= PlotDataItem(recarray) numpy array with dtype=[('x', float), ('y', float), ...] PlotDataItem(list-of-dicts) [{'x': x, 'y': y, ...}, ...] PlotDataItem(dict-of-lists) {'x': [...], 'y': [...], ...} PlotDataItem(MetaArray) 1D array of Y values with X sepecified as axis values OR 2D array with a column 'y' and extra columns as needed. =========================== ========================================= **Line style keyword arguments:** ========== ================================================ pen pen to use for drawing line between points. Default is solid grey, 1px width. Use None to disable line drawing. May be any single argument accepted by :func:`mkPen() <pyqtgraph.mkPen>` shadowPen pen for secondary line to draw behind the primary line. disabled by default. May be any single argument accepted by :func:`mkPen() <pyqtgraph.mkPen>` fillLevel fill the area between the curve and fillLevel fillBrush fill to use when fillLevel is specified May be any single argument accepted by :func:`mkBrush() <pyqtgraph.mkBrush>` ========== ================================================ **Point style keyword arguments:** ============ ================================================ symbol (str) symbol to use for drawing points OR list of symbols, one per point. Default is no symbol. options are o, s, t, d, + symbolPen outline pen for drawing points OR list of pens, one per point May be any single argument accepted by :func:`mkPen() <pyqtgraph.mkPen>` symbolBrush brush for filling points OR list of brushes, one per point May be any single argument accepted by :func:`mkBrush() <pyqtgraph.mkBrush>` symbolSize diameter of symbols OR list of diameters pxMode (bool) If True, then symbolSize is specified in pixels. If False, then symbolSize is specified in data coordinates. ============ ================================================ **Optimization keyword arguments:** ========== ================================================ identical spots are all identical. The spot image will be rendered only once and repeated for every point decimate (int) decimate data ========== ================================================ **Meta-info keyword arguments:** ========== ================================================ name name of dataset. This would appear in a legend ========== ================================================ """ GraphicsObject.__init__(self) self.setFlag(self.ItemHasNoContents) self.xData = None self.yData = None self.xDisp = None self.yDisp = None #self.curves = [] #self.scatters = [] self.curve = PlotCurveItem() self.scatter = ScatterPlotItem() self.curve.setParentItem(self) self.scatter.setParentItem(self) self.curve.sigClicked.connect(self.curveClicked) self.scatter.sigClicked.connect(self.scatterClicked) #self.clear() self.opts = { 'fftMode': False, 'logMode': [False, False], 'downsample': False, 'alphaHint': 1.0, 'alphaMode': False, 'pen': (200,200,200), 'shadowPen': None, 'fillLevel': None, 'fillBrush': None, 'symbol': None, 'symbolSize': 10, 'symbolPen': (200,200,200), 'symbolBrush': (50, 50, 150), 'identical': False, 'data': None, } self.setData(*args, **kargs) def implements(self, interface=None): ints = ['plotData'] if interface is None: return ints return interface in ints def boundingRect(self): return QtCore.QRectF() ## let child items handle this def setAlpha(self, alpha, auto): self.opts['alphaHint'] = alpha self.opts['alphaMode'] = auto self.setOpacity(alpha) #self.update() def setFftMode(self, mode): self.opts['fftMode'] = mode self.xDisp = self.yDisp = None self.updateItems() def setLogMode(self, xMode, yMode): self.opts['logMode'] = (xMode, yMode) self.xDisp = self.yDisp = None self.updateItems() def setPointMode(self, mode): self.opts['pointMode'] = mode self.update() def setPen(self, *args, **kargs): """ | Sets the pen used to draw lines between points. | *pen* can be a QPen or any argument accepted by :func:`pyqtgraph.mkPen() <pyqtgraph.mkPen>` """ pen = fn.mkPen(*args, **kargs) self.opts['pen'] = pen #self.curve.setPen(pen) #for c in self.curves: #c.setPen(pen) #self.update() self.updateItems() def setShadowPen(self, *args, **kargs): """ | Sets the shadow pen used to draw lines between points (this is for enhancing contrast or emphacizing data). | This line is drawn behind the primary pen (see :func:`setPen() <pyqtgraph.PlotDataItem.setPen>`) and should generally be assigned greater width than the primary pen. | *pen* can be a QPen or any argument accepted by :func:`pyqtgraph.mkPen() <pyqtgraph.mkPen>` """ pen = fn.mkPen(*args, **kargs) self.opts['shadowPen'] = pen #for c in self.curves: #c.setPen(pen) #self.update() self.updateItems() def setFillBrush(self, *args, **kargs): brush = fn.mkBrush(*args, **kargs) self.opts['fillBrush'] = brush self.updateItems() def setBrush(self, *args, **kargs): return self.setFillBrush(*args, **kargs) def setFillLevel(self, level): self.opts['fillLevel'] = level self.updateItems() def setSymbol(self, symbol): self.opts['symbol'] = symbol #self.scatter.setSymbol(symbol) self.updateItems() def setSymbolPen(self, *args, **kargs): pen = fn.mkPen(*args, **kargs) self.opts['symbolPen'] = pen #self.scatter.setSymbolPen(pen) self.updateItems() def setSymbolBrush(self, *args, **kargs): brush = fn.mkBrush(*args, **kargs) self.opts['symbolBrush'] = brush #self.scatter.setSymbolBrush(brush) self.updateItems() def setSymbolSize(self, size): self.opts['symbolSize'] = size #self.scatter.setSymbolSize(symbolSize) self.updateItems() def setDownsampling(self, ds): if self.opts['downsample'] != ds: self.opts['downsample'] = ds self.xDisp = self.yDisp = None self.updateItems() def setData(self, *args, **kargs): """ Clear any data displayed by this item and display new data. See :func:`__init__() <pyqtgraph.PlotDataItem.__init__>` for details; it accepts the same arguments. """ #self.clear() prof = debug.Profiler('PlotDataItem.setData (0x%x)' % id(self), disabled=True) y = None x = None if len(args) == 1: data = args[0] dt = dataType(data) if dt == 'empty': pass elif dt == 'listOfValues': y = np.array(data) elif dt == 'Nx2array': x = data[:,0] y = data[:,1] elif dt == 'recarray' or dt == 'dictOfLists': if 'x' in data: x = np.array(data['x']) if 'y' in data: y = np.array(data['y']) elif dt == 'listOfDicts': if 'x' in data[0]: x = np.array([d.get('x',None) for d in data]) if 'y' in data[0]: y = np.array([d.get('y',None) for d in data]) for k in ['data', 'symbolSize', 'symbolPen', 'symbolBrush', 'symbolShape']: kargs[k] = [d.get(k, None) for d in data] elif dt == 'MetaArray': y = data.view(np.ndarray) x = data.xvals(0).view(np.ndarray) else: raise Exception('Invalid data type %s' % type(data)) elif len(args) == 2: seq = ('listOfValues', 'MetaArray') if dataType(args[0]) not in seq or dataType(args[1]) not in seq: raise Exception('When passing two unnamed arguments, both must be a list or array of values. (got %s, %s)' % (str(type(args[0])), str(type(args[1])))) if not isinstance(args[0], np.ndarray): x = np.array(args[0]) else: x = args[0].view(np.ndarray) if not isinstance(args[1], np.ndarray): y = np.array(args[1]) else: y = args[1].view(np.ndarray) if 'x' in kargs: x = kargs['x'] if 'y' in kargs: y = kargs['y'] prof.mark('interpret data') ## pull in all style arguments. ## Use self.opts to fill in anything not present in kargs. ## if symbol pen/brush are given with no symbol, then assume symbol is 'o' if 'symbol' not in kargs and ('symbolPen' in kargs or 'symbolBrush' in kargs or 'symbolSize' in kargs): kargs['symbol'] = 'o' if 'brush' in kargs: kargs['fillBrush'] = kargs['brush'] for k in self.opts.keys(): if k in kargs: self.opts[k] = kargs[k] #curveArgs = {} #for k in ['pen', 'shadowPen', 'fillLevel', 'brush']: #if k in kargs: #self.opts[k] = kargs[k] #curveArgs[k] = self.opts[k] #scatterArgs = {} #for k,v in [('symbolPen','pen'), ('symbolBrush','brush'), ('symbol','symbol')]: #if k in kargs: #self.opts[k] = kargs[k] #scatterArgs[v] = self.opts[k] if y is None: return if y is not None and x is None: x = np.arange(len(y)) if isinstance(x, list): x = np.array(x) if isinstance(y, list): y = np.array(y) self.xData = x.view(np.ndarray) ## one last check to make sure there are no MetaArrays getting by self.yData = y.view(np.ndarray) self.xDisp = None self.yDisp = None prof.mark('set data') self.updateItems() prof.mark('update items') view = self.getViewBox() if view is not None: view.itemBoundsChanged(self) ## inform view so it can update its range if it wants self.sigPlotChanged.emit(self) prof.mark('emit') prof.finish() def updateItems(self): #for c in self.curves+self.scatters: #if c.scene() is not None: #c.scene().removeItem(c) curveArgs = {} for k,v in [('pen','pen'), ('shadowPen','shadowPen'), ('fillLevel','fillLevel'), ('fillBrush', 'brush')]: curveArgs[v] = self.opts[k] scatterArgs = {} for k,v in [('symbolPen','pen'), ('symbolBrush','brush'), ('symbol','symbol'), ('symbolSize', 'size'), ('data', 'data')]: if k in self.opts: scatterArgs[v] = self.opts[k] x,y = self.getData() if curveArgs['pen'] is not None or (curveArgs['brush'] is not None and curveArgs['fillLevel'] is not None): self.curve.setData(x=x, y=y, **curveArgs) self.curve.show() else: self.curve.hide() #curve = PlotCurveItem(x=x, y=y, **curveArgs) #curve.setParentItem(self) #self.curves.append(curve) if scatterArgs['symbol'] is not None: self.scatter.setData(x=x, y=y, **scatterArgs) self.scatter.show() else: self.scatter.hide() #sp = ScatterPlotItem(x=x, y=y, **scatterArgs) #sp.setParentItem(self) #self.scatters.append(sp) def getData(self): if self.xData is None: return (None, None) if self.xDisp is None: nanMask = np.isnan(self.xData) | np.isnan(self.yData) if any(nanMask): x = self.xData[~nanMask] y = self.yData[~nanMask] else: x = self.xData y = self.yData ds = self.opts['downsample'] if ds > 1: x = x[::ds] #y = resample(y[:len(x)*ds], len(x)) ## scipy.signal.resample causes nasty ringing y = y[::ds] if self.opts['fftMode']: f = np.fft.fft(y) / len(y) y = abs(f[1:len(f)/2]) dt = x[-1] - x[0] x = np.linspace(0, 0.5*len(x)/dt, len(y)) if self.opts['logMode'][0]: x = np.log10(x) if self.opts['logMode'][1]: y = np.log10(y) if any(self.opts['logMode']): ## re-check for NANs after log nanMask = np.isinf(x) | np.isinf(y) | np.isnan(x) | np.isnan(y) if any(nanMask): x = x[~nanMask] y = y[~nanMask] self.xDisp = x self.yDisp = y #print self.yDisp.shape, self.yDisp.min(), self.yDisp.max() #print self.xDisp.shape, self.xDisp.min(), self.xDisp.max() return self.xDisp, self.yDisp def dataBounds(self, ax, frac=1.0): (x, y) = self.getData() if x is None or len(x) == 0: return (0, 0) if ax == 0: d = x elif ax == 1: d = y if frac >= 1.0: return (np.min(d), np.max(d)) elif frac <= 0.0: raise Exception("Value for parameter 'frac' must be > 0. (got %s)" % str(frac)) else: return (scipy.stats.scoreatpercentile(d, 50 - (frac * 50)), scipy.stats.scoreatpercentile(d, 50 + (frac * 50))) def clear(self): #for i in self.curves+self.scatters: #if i.scene() is not None: #i.scene().removeItem(i) #self.curves = [] #self.scatters = [] self.xData = None self.yData = None self.xDisp = None self.yDisp = None self.curve.setData([]) self.scatter.setData([]) def appendData(self, *args, **kargs): pass def curveClicked(self): self.sigClicked.emit(self) def scatterClicked(self, plt, points): self.sigClicked.emit(self) self.sigPointsClicked.emit(self, points)
class PlotDataItem(GraphicsObject): """ **Bases:** :class:`GraphicsObject <pyqtgraph.GraphicsObject>` GraphicsItem for displaying plot curves, scatter plots, or both. While it is possible to use :class:`PlotCurveItem <pyqtgraph.PlotCurveItem>` or :class:`ScatterPlotItem <pyqtgraph.ScatterPlotItem>` individually, this class provides a unified interface to both. Inspances of :class:`PlotDataItem` are usually created by plot() methods such as :func:`pyqtgraph.plot` and :func:`PlotItem.plot() <pyqtgraph.PlotItem.plot>`. ============================== ============================================== **Signals:** sigPlotChanged(self) Emitted when the data in this item is updated. sigClicked(self) Emitted when the item is clicked. sigPointsClicked(self, points) Emitted when a plot point is clicked Sends the list of points under the mouse. ============================== ============================================== """ sigPlotChanged = QtCore.Signal(object) sigClicked = QtCore.Signal(object) sigPointsClicked = QtCore.Signal(object, object) def __init__(self, *args, **kargs): """ There are many different ways to create a PlotDataItem: **Data initialization arguments:** (x,y data only) =================================== ====================================== PlotDataItem(xValues, yValues) x and y values may be any sequence (including ndarray) of real numbers PlotDataItem(yValues) y values only -- x will be automatically set to range(len(y)) PlotDataItem(x=xValues, y=yValues) x and y given by keyword arguments PlotDataItem(ndarray(Nx2)) numpy array with shape (N, 2) where x=data[:,0] and y=data[:,1] =================================== ====================================== **Data initialization arguments:** (x,y data AND may include spot style) =========================== ========================================= PlotDataItem(recarray) numpy array with dtype=[('x', float), ('y', float), ...] PlotDataItem(list-of-dicts) [{'x': x, 'y': y, ...}, ...] PlotDataItem(dict-of-lists) {'x': [...], 'y': [...], ...} PlotDataItem(MetaArray) 1D array of Y values with X sepecified as axis values OR 2D array with a column 'y' and extra columns as needed. =========================== ========================================= **Line style keyword arguments:** ========== ================================================ pen pen to use for drawing line between points. Default is solid grey, 1px width. Use None to disable line drawing. May be any single argument accepted by :func:`mkPen() <pyqtgraph.mkPen>` shadowPen pen for secondary line to draw behind the primary line. disabled by default. May be any single argument accepted by :func:`mkPen() <pyqtgraph.mkPen>` fillLevel fill the area between the curve and fillLevel fillBrush fill to use when fillLevel is specified May be any single argument accepted by :func:`mkBrush() <pyqtgraph.mkBrush>` ========== ================================================ **Point style keyword arguments:** ============ ================================================ symbol (str) symbol to use for drawing points OR list of symbols, one per point. Default is no symbol. options are o, s, t, d, + symbolPen outline pen for drawing points OR list of pens, one per point May be any single argument accepted by :func:`mkPen() <pyqtgraph.mkPen>` symbolBrush brush for filling points OR list of brushes, one per point May be any single argument accepted by :func:`mkBrush() <pyqtgraph.mkBrush>` symbolSize diameter of symbols OR list of diameters pxMode (bool) If True, then symbolSize is specified in pixels. If False, then symbolSize is specified in data coordinates. ============ ================================================ **Optimization keyword arguments:** ========== ================================================ identical spots are all identical. The spot image will be rendered only once and repeated for every point decimate (int) decimate data ========== ================================================ **Meta-info keyword arguments:** ========== ================================================ name name of dataset. This would appear in a legend ========== ================================================ """ GraphicsObject.__init__(self) self.setFlag(self.ItemHasNoContents) self.xData = None self.yData = None self.xDisp = None self.yDisp = None #self.curves = [] #self.scatters = [] self.curve = PlotCurveItem() self.scatter = ScatterPlotItem() self.curve.setParentItem(self) self.scatter.setParentItem(self) self.curve.sigClicked.connect(self.curveClicked) self.scatter.sigClicked.connect(self.scatterClicked) #self.clear() self.opts = { 'fftMode': False, 'logMode': [False, False], 'downsample': False, 'alphaHint': 1.0, 'alphaMode': False, 'pen': (200, 200, 200), 'shadowPen': None, 'fillLevel': None, 'fillBrush': None, 'symbol': None, 'symbolSize': 10, 'symbolPen': (200, 200, 200), 'symbolBrush': (50, 50, 150), 'identical': False, 'data': None, } self.setData(*args, **kargs) def implements(self, interface=None): ints = ['plotData'] if interface is None: return ints return interface in ints def boundingRect(self): return QtCore.QRectF() ## let child items handle this def setAlpha(self, alpha, auto): self.opts['alphaHint'] = alpha self.opts['alphaMode'] = auto self.setOpacity(alpha) #self.update() def setFftMode(self, mode): self.opts['fftMode'] = mode self.xDisp = self.yDisp = None self.updateItems() def setLogMode(self, xMode, yMode): self.opts['logMode'] = (xMode, yMode) self.xDisp = self.yDisp = None self.updateItems() def setPointMode(self, mode): self.opts['pointMode'] = mode self.update() def setPen(self, *args, **kargs): """ | Sets the pen used to draw lines between points. | *pen* can be a QPen or any argument accepted by :func:`pyqtgraph.mkPen() <pyqtgraph.mkPen>` """ pen = fn.mkPen(*args, **kargs) self.opts['pen'] = pen #self.curve.setPen(pen) #for c in self.curves: #c.setPen(pen) #self.update() self.updateItems() def setShadowPen(self, *args, **kargs): """ | Sets the shadow pen used to draw lines between points (this is for enhancing contrast or emphacizing data). | This line is drawn behind the primary pen (see :func:`setPen() <pyqtgraph.PlotDataItem.setPen>`) and should generally be assigned greater width than the primary pen. | *pen* can be a QPen or any argument accepted by :func:`pyqtgraph.mkPen() <pyqtgraph.mkPen>` """ pen = fn.mkPen(*args, **kargs) self.opts['shadowPen'] = pen #for c in self.curves: #c.setPen(pen) #self.update() self.updateItems() def setFillBrush(self, *args, **kargs): brush = fn.mkBrush(*args, **kargs) self.opts['fillBrush'] = brush self.updateItems() def setBrush(self, *args, **kargs): return self.setFillBrush(*args, **kargs) def setFillLevel(self, level): self.opts['fillLevel'] = level self.updateItems() def setSymbol(self, symbol): self.opts['symbol'] = symbol #self.scatter.setSymbol(symbol) self.updateItems() def setSymbolPen(self, *args, **kargs): pen = fn.mkPen(*args, **kargs) self.opts['symbolPen'] = pen #self.scatter.setSymbolPen(pen) self.updateItems() def setSymbolBrush(self, *args, **kargs): brush = fn.mkBrush(*args, **kargs) self.opts['symbolBrush'] = brush #self.scatter.setSymbolBrush(brush) self.updateItems() def setSymbolSize(self, size): self.opts['symbolSize'] = size #self.scatter.setSymbolSize(symbolSize) self.updateItems() def setDownsampling(self, ds): if self.opts['downsample'] != ds: self.opts['downsample'] = ds self.xDisp = self.yDisp = None self.updateItems() def setData(self, *args, **kargs): """ Clear any data displayed by this item and display new data. See :func:`__init__() <pyqtgraph.PlotDataItem.__init__>` for details; it accepts the same arguments. """ #self.clear() prof = debug.Profiler('PlotDataItem.setData (0x%x)' % id(self), disabled=True) y = None x = None if len(args) == 1: data = args[0] dt = dataType(data) if dt == 'empty': pass elif dt == 'listOfValues': y = np.array(data) elif dt == 'Nx2array': x = data[:, 0] y = data[:, 1] elif dt == 'recarray' or dt == 'dictOfLists': if 'x' in data: x = np.array(data['x']) if 'y' in data: y = np.array(data['y']) elif dt == 'listOfDicts': if 'x' in data[0]: x = np.array([d.get('x', None) for d in data]) if 'y' in data[0]: y = np.array([d.get('y', None) for d in data]) for k in [ 'data', 'symbolSize', 'symbolPen', 'symbolBrush', 'symbolShape' ]: kargs[k] = [d.get(k, None) for d in data] elif dt == 'MetaArray': y = data.view(np.ndarray) x = data.xvals(0).view(np.ndarray) else: raise Exception('Invalid data type %s' % type(data)) elif len(args) == 2: seq = ('listOfValues', 'MetaArray') if dataType(args[0]) not in seq or dataType(args[1]) not in seq: raise Exception( 'When passing two unnamed arguments, both must be a list or array of values. (got %s, %s)' % (str(type(args[0])), str(type(args[1])))) if not isinstance(args[0], np.ndarray): x = np.array(args[0]) else: x = args[0].view(np.ndarray) if not isinstance(args[1], np.ndarray): y = np.array(args[1]) else: y = args[1].view(np.ndarray) if 'x' in kargs: x = kargs['x'] if 'y' in kargs: y = kargs['y'] prof.mark('interpret data') ## pull in all style arguments. ## Use self.opts to fill in anything not present in kargs. ## if symbol pen/brush are given with no symbol, then assume symbol is 'o' if 'symbol' not in kargs and ('symbolPen' in kargs or 'symbolBrush' in kargs or 'symbolSize' in kargs): kargs['symbol'] = 'o' if 'brush' in kargs: kargs['fillBrush'] = kargs['brush'] for k in self.opts.keys(): if k in kargs: self.opts[k] = kargs[k] #curveArgs = {} #for k in ['pen', 'shadowPen', 'fillLevel', 'brush']: #if k in kargs: #self.opts[k] = kargs[k] #curveArgs[k] = self.opts[k] #scatterArgs = {} #for k,v in [('symbolPen','pen'), ('symbolBrush','brush'), ('symbol','symbol')]: #if k in kargs: #self.opts[k] = kargs[k] #scatterArgs[v] = self.opts[k] if y is None: return if y is not None and x is None: x = np.arange(len(y)) if isinstance(x, list): x = np.array(x) if isinstance(y, list): y = np.array(y) self.xData = x.view( np.ndarray ) ## one last check to make sure there are no MetaArrays getting by self.yData = y.view(np.ndarray) self.xDisp = None self.yDisp = None prof.mark('set data') self.updateItems() prof.mark('update items') view = self.getViewBox() if view is not None: view.itemBoundsChanged( self) ## inform view so it can update its range if it wants self.sigPlotChanged.emit(self) prof.mark('emit') prof.finish() def updateItems(self): #for c in self.curves+self.scatters: #if c.scene() is not None: #c.scene().removeItem(c) curveArgs = {} for k, v in [('pen', 'pen'), ('shadowPen', 'shadowPen'), ('fillLevel', 'fillLevel'), ('fillBrush', 'brush')]: curveArgs[v] = self.opts[k] scatterArgs = {} for k, v in [('symbolPen', 'pen'), ('symbolBrush', 'brush'), ('symbol', 'symbol'), ('symbolSize', 'size'), ('data', 'data')]: if k in self.opts: scatterArgs[v] = self.opts[k] x, y = self.getData() if curveArgs['pen'] is not None or (curveArgs['brush'] is not None and curveArgs['fillLevel'] is not None): self.curve.setData(x=x, y=y, **curveArgs) self.curve.show() else: self.curve.hide() #curve = PlotCurveItem(x=x, y=y, **curveArgs) #curve.setParentItem(self) #self.curves.append(curve) if scatterArgs['symbol'] is not None: self.scatter.setData(x=x, y=y, **scatterArgs) self.scatter.show() else: self.scatter.hide() #sp = ScatterPlotItem(x=x, y=y, **scatterArgs) #sp.setParentItem(self) #self.scatters.append(sp) def getData(self): if self.xData is None: return (None, None) if self.xDisp is None: nanMask = np.isnan(self.xData) | np.isnan(self.yData) | np.isinf( self.xData) | np.isinf(self.yData) if any(nanMask): x = self.xData[~nanMask] y = self.yData[~nanMask] else: x = self.xData y = self.yData ds = self.opts['downsample'] if ds > 1: x = x[::ds] #y = resample(y[:len(x)*ds], len(x)) ## scipy.signal.resample causes nasty ringing y = y[::ds] if self.opts['fftMode']: f = np.fft.fft(y) / len(y) y = abs(f[1:len(f) / 2]) dt = x[-1] - x[0] x = np.linspace(0, 0.5 * len(x) / dt, len(y)) if self.opts['logMode'][0]: x = np.log10(x) if self.opts['logMode'][1]: y = np.log10(y) if any(self.opts['logMode']): ## re-check for NANs after log nanMask = np.isinf(x) | np.isinf(y) | np.isnan(x) | np.isnan(y) if any(nanMask): x = x[~nanMask] y = y[~nanMask] self.xDisp = x self.yDisp = y #print self.yDisp.shape, self.yDisp.min(), self.yDisp.max() #print self.xDisp.shape, self.xDisp.min(), self.xDisp.max() return self.xDisp, self.yDisp def dataBounds(self, ax, frac=1.0): (x, y) = self.getData() if x is None or len(x) == 0: return (0, 0) if ax == 0: d = x elif ax == 1: d = y if frac >= 1.0: return (np.min(d), np.max(d)) elif frac <= 0.0: raise Exception( "Value for parameter 'frac' must be > 0. (got %s)" % str(frac)) else: return (scipy.stats.scoreatpercentile(d, 50 - (frac * 50)), scipy.stats.scoreatpercentile(d, 50 + (frac * 50))) def clear(self): #for i in self.curves+self.scatters: #if i.scene() is not None: #i.scene().removeItem(i) #self.curves = [] #self.scatters = [] self.xData = None self.yData = None self.xDisp = None self.yDisp = None self.curve.setData([]) self.scatter.setData([]) def appendData(self, *args, **kargs): pass def curveClicked(self): self.sigClicked.emit(self) def scatterClicked(self, plt, points): self.sigClicked.emit(self) self.sigPointsClicked.emit(self, points)