merged updates from acq4

This commit is contained in:
Luke Campagnola 2013-03-19 16:04:46 -04:00
parent 4839998574
commit cefb4f9828
6 changed files with 112 additions and 28 deletions

View 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_()

View File

@ -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)

View File

@ -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:**

View File

@ -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))

View File

@ -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

View File

@ -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