merged updates from acq4
This commit is contained in:
parent
4839998574
commit
cefb4f9828
38
examples/ScatterPlotWidget.py
Normal file
38
examples/ScatterPlotWidget.py
Normal file
@ -0,0 +1,38 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
import initExample ## Add path to library (just for examples; you do not need this)
|
||||
|
||||
import pyqtgraph as pg
|
||||
from pyqtgraph.Qt import QtCore, QtGui
|
||||
import numpy as np
|
||||
|
||||
pg.mkQApp()
|
||||
|
||||
spw = pg.ScatterPlotWidget()
|
||||
spw.show()
|
||||
|
||||
data = np.array([
|
||||
(1, 1, 3, 4, 'x'),
|
||||
(2, 3, 3, 7, 'y'),
|
||||
(3, 2, 5, 2, 'z'),
|
||||
(4, 4, 6, 9, 'z'),
|
||||
(5, 3, 6, 7, 'x'),
|
||||
(6, 5, 2, 6, 'y'),
|
||||
(7, 5, 7, 2, 'z'),
|
||||
], dtype=[('col1', float), ('col2', float), ('col3', int), ('col4', int), ('col5', 'S10')])
|
||||
|
||||
spw.setFields([
|
||||
('col1', {'units': 'm'}),
|
||||
('col2', {'units': 'm'}),
|
||||
('col3', {}),
|
||||
('col4', {}),
|
||||
('col5', {'mode': 'enum', 'values': ['x', 'y', 'z']}),
|
||||
])
|
||||
|
||||
spw.setData(data)
|
||||
|
||||
|
||||
## Start Qt event loop unless running in interactive mode or using pyside.
|
||||
if __name__ == '__main__':
|
||||
import sys
|
||||
if (sys.flags.interactive != 1) or not hasattr(QtCore, 'PYQT_VERSION'):
|
||||
QtGui.QApplication.instance().exec_()
|
@ -523,6 +523,15 @@ class ConnectionItem(GraphicsObject):
|
||||
self.hovered = False
|
||||
self.path = None
|
||||
self.shapePath = None
|
||||
self.style = {
|
||||
'shape': 'line',
|
||||
'color': (100, 100, 250),
|
||||
'width': 1.0,
|
||||
'hoverColor': (150, 150, 250),
|
||||
'hoverWidth': 1.0,
|
||||
'selectedColor': (200, 200, 0),
|
||||
'selectedWidth': 3.0,
|
||||
}
|
||||
#self.line = QtGui.QGraphicsLineItem(self)
|
||||
self.source.getViewBox().addItem(self)
|
||||
self.updateLine()
|
||||
@ -537,6 +546,13 @@ class ConnectionItem(GraphicsObject):
|
||||
self.target = target
|
||||
self.updateLine()
|
||||
|
||||
def setStyle(self, **kwds):
|
||||
self.style.update(kwds)
|
||||
if 'shape' in kwds:
|
||||
self.updateLine()
|
||||
else:
|
||||
self.update()
|
||||
|
||||
def updateLine(self):
|
||||
start = Point(self.source.connectPoint())
|
||||
if isinstance(self.target, TerminalGraphicsItem):
|
||||
@ -547,19 +563,20 @@ class ConnectionItem(GraphicsObject):
|
||||
return
|
||||
self.prepareGeometryChange()
|
||||
|
||||
self.path = QtGui.QPainterPath()
|
||||
self.path.moveTo(start)
|
||||
self.path.cubicTo(Point(stop.x(), start.y()), Point(start.x(), stop.y()), Point(stop.x(), stop.y()))
|
||||
self.path = self.generatePath(start, stop)
|
||||
self.shapePath = None
|
||||
#self.resetTransform()
|
||||
#ang = (stop-start).angle(Point(0, 1))
|
||||
#if ang is None:
|
||||
#ang = 0
|
||||
#self.rotate(ang)
|
||||
#self.setPos(start)
|
||||
#self.length = (start-stop).length()
|
||||
self.update()
|
||||
#self.line.setLine(start.x(), start.y(), stop.x(), stop.y())
|
||||
|
||||
def generatePath(self, start, stop):
|
||||
path = QtGui.QPainterPath()
|
||||
path.moveTo(start)
|
||||
if self.style['shape'] == 'line':
|
||||
path.lineTo(stop)
|
||||
elif self.style['shape'] == 'cubic':
|
||||
path.cubicTo(Point(stop.x(), start.y()), Point(start.x(), stop.y()), Point(stop.x(), stop.y()))
|
||||
else:
|
||||
raise Exception('Invalid shape "%s"; options are "line" or "cubic"' % self.style['shape'])
|
||||
return path
|
||||
|
||||
def keyPressEvent(self, ev):
|
||||
if ev.key() == QtCore.Qt.Key_Delete or ev.key() == QtCore.Qt.Key_Backspace:
|
||||
@ -609,12 +626,12 @@ class ConnectionItem(GraphicsObject):
|
||||
|
||||
def paint(self, p, *args):
|
||||
if self.isSelected():
|
||||
p.setPen(fn.mkPen(200, 200, 0, width=3))
|
||||
p.setPen(fn.mkPen(self.style['selectedColor'], width=self.style['selectedWidth']))
|
||||
else:
|
||||
if self.hovered:
|
||||
p.setPen(fn.mkPen(150, 150, 250, width=1))
|
||||
p.setPen(fn.mkPen(self.style['hoverColor'], width=self.style['hoverWidth']))
|
||||
else:
|
||||
p.setPen(fn.mkPen(100, 100, 250, width=1))
|
||||
p.setPen(fn.mkPen(self.style['color'], width=self.style['width']))
|
||||
|
||||
#p.drawLine(0, 0, 0, self.length)
|
||||
|
||||
|
@ -84,13 +84,24 @@ class PlotDataItem(GraphicsObject):
|
||||
|
||||
**Optimization keyword arguments:**
|
||||
|
||||
========== =====================================================================
|
||||
============ =====================================================================
|
||||
antialias (bool) By default, antialiasing is disabled to improve performance.
|
||||
Note that in some cases (in particluar, when pxMode=True), points
|
||||
will be rendered antialiased even if this is set to False.
|
||||
decimate (int) Sub-sample data by selecting every nth sample before plotting
|
||||
onlyVisible (bool) If True, only plot data that is visible within the X range of
|
||||
the containing ViewBox. This can improve performance when plotting
|
||||
very large data sets where only a fraction of the data is visible
|
||||
at any time.
|
||||
autoResample (bool) If True, resample the data before plotting to avoid plotting
|
||||
multiple line segments per pixel. This can improve performance when
|
||||
viewing very high-density data, but increases the initial overhead
|
||||
and memory usage.
|
||||
sampleRate (float) The sample rate of the data along the X axis (for data with
|
||||
a fixed sample rate). Providing this value improves performance of
|
||||
the *onlyVisible* and *autoResample* options.
|
||||
identical *deprecated*
|
||||
decimate (int) sub-sample data by selecting every nth sample before plotting
|
||||
========== =====================================================================
|
||||
============ =====================================================================
|
||||
|
||||
**Meta-info keyword arguments:**
|
||||
|
||||
|
@ -677,15 +677,12 @@ class ScatterPlotItem(GraphicsObject):
|
||||
pts[1] = self.data['y']
|
||||
pts = fn.transformCoordinates(tr, pts)
|
||||
self.fragments = []
|
||||
pts = np.clip(pts, -2**31, 2**31) ## prevent Qt segmentation fault.
|
||||
pts = np.clip(pts, -2**30, 2**30) ## prevent Qt segmentation fault.
|
||||
## Still won't be able to render correctly, though.
|
||||
for i in xrange(len(self.data)):
|
||||
rec = self.data[i]
|
||||
pos = QtCore.QPointF(pts[0,i], pts[1,i])
|
||||
x,y,w,h = rec['fragCoords']
|
||||
if abs(w) > 10000 or abs(h) > 10000:
|
||||
print self.data
|
||||
raise Exception("fragment corrupt")
|
||||
rect = QtCore.QRectF(y, x, h, w)
|
||||
self.fragments.append(QtGui.QPainter.PixmapFragment.create(pos, rect))
|
||||
|
||||
|
@ -104,6 +104,10 @@ class EnumFilterItem(ptree.types.SimpleParameter):
|
||||
ch = ptree.Parameter.create(name=str(v), type='bool', value=True)
|
||||
ch.maskValue = v
|
||||
childs.append(ch)
|
||||
ch = ptree.Parameter.create(name='(other)', type='bool', value=True)
|
||||
ch.maskValue = '__other__'
|
||||
childs.append(ch)
|
||||
|
||||
ptree.types.SimpleParameter.__init__(self,
|
||||
name=name, autoIncrementName=True, type='bool', value=True, removable=True, renamable=True,
|
||||
children=childs)
|
||||
@ -111,9 +115,14 @@ class EnumFilterItem(ptree.types.SimpleParameter):
|
||||
def generateMask(self, data):
|
||||
vals = data[self.fieldName]
|
||||
mask = np.ones(len(data), dtype=bool)
|
||||
otherMask = np.ones(len(data), dtype=bool)
|
||||
for c in self:
|
||||
if c.value() is True:
|
||||
continue
|
||||
key = c.maskValue
|
||||
mask &= vals != key
|
||||
if key == '__other__':
|
||||
m = ~otherMask
|
||||
else:
|
||||
m = vals != key
|
||||
otherMask &= m
|
||||
if c.value() is False:
|
||||
mask &= m
|
||||
return mask
|
||||
|
@ -48,13 +48,15 @@ class ScatterPlotWidget(QtGui.QSplitter):
|
||||
self.addWidget(self.plot)
|
||||
|
||||
self.data = None
|
||||
self.mouseOverField = None
|
||||
self.scatterPlot = None
|
||||
self.style = dict(pen=None, symbol='o')
|
||||
|
||||
self.fieldList.itemSelectionChanged.connect(self.fieldSelectionChanged)
|
||||
self.filter.sigFilterChanged.connect(self.filterChanged)
|
||||
self.colorMap.sigColorMapChanged.connect(self.updatePlot)
|
||||
|
||||
def setFields(self, fields):
|
||||
def setFields(self, fields, mouseOverField=None):
|
||||
"""
|
||||
Set the list of field names/units to be processed.
|
||||
|
||||
@ -62,6 +64,7 @@ class ScatterPlotWidget(QtGui.QSplitter):
|
||||
:func:`ColorMapWidget.setFields <pyqtgraph.widgets.ColorMapWidget.ColorMapParameter.setFields>`
|
||||
"""
|
||||
self.fields = OrderedDict(fields)
|
||||
self.mouseOverField = mouseOverField
|
||||
self.fieldList.clear()
|
||||
for f,opts in fields:
|
||||
item = QtGui.QListWidgetItem(f)
|
||||
@ -158,7 +161,7 @@ class ScatterPlotWidget(QtGui.QSplitter):
|
||||
axis = self.plot.getAxis(['bottom', 'left'][i])
|
||||
if xy[i] is not None and xy[i].dtype.kind in ('S', 'O'):
|
||||
vals = self.fields[sel[i]].get('values', list(set(xy[i])))
|
||||
xy[i] = np.array([vals.index(x) if x in vals else None for x in xy[i]], dtype=float)
|
||||
xy[i] = np.array([vals.index(x) if x in vals else len(vals) for x in xy[i]], dtype=float)
|
||||
axis.setTicks([list(enumerate(vals))])
|
||||
else:
|
||||
axis.setTicks(None) # reset to automatic ticking
|
||||
@ -179,7 +182,16 @@ class ScatterPlotWidget(QtGui.QSplitter):
|
||||
else:
|
||||
y = y[mask]
|
||||
|
||||
|
||||
self.plot.plot(x, y, **style)
|
||||
if self.scatterPlot is not None:
|
||||
try:
|
||||
self.scatterPlot.sigPointsClicked.disconnect(self.plotClicked)
|
||||
except:
|
||||
pass
|
||||
self.scatterPlot = self.plot.plot(x, y, data=data[mask], **style)
|
||||
self.scatterPlot.sigPointsClicked.connect(self.plotClicked)
|
||||
|
||||
|
||||
def plotClicked(self, plot, points):
|
||||
pass
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user