Commit 03c01d3b authored by Luke Campagnola's avatar Luke Campagnola
Browse files

Fixes related to CSV exporter:

  - CSV headers include data names, if available
  - Exporter correctly handles items with no data
  - pg.plot() avoids creating empty data item
  - removed call to reduce() from exporter; not available in python 3
  - Gave .name() methods to PlotDataItem, PlotCurveItem, and ScatterPlotItem
parent 3b94b0d9
...@@ -27,9 +27,9 @@ pg.setConfigOptions(antialias=True) ...@@ -27,9 +27,9 @@ pg.setConfigOptions(antialias=True)
p1 = win.addPlot(title="Basic array plotting", y=np.random.normal(size=100)) p1 = win.addPlot(title="Basic array plotting", y=np.random.normal(size=100))
p2 = win.addPlot(title="Multiple curves") p2 = win.addPlot(title="Multiple curves")
p2.plot(np.random.normal(size=100), pen=(255,0,0)) p2.plot(np.random.normal(size=100), pen=(255,0,0), name="Red curve")
p2.plot(np.random.normal(size=100)+5, pen=(0,255,0)) p2.plot(np.random.normal(size=110)+5, pen=(0,255,0), name="Blue curve")
p2.plot(np.random.normal(size=100)+10, pen=(0,0,255)) p2.plot(np.random.normal(size=120)+10, pen=(0,0,255), name="Green curve")
p3 = win.addPlot(title="Drawing with points") p3 = win.addPlot(title="Drawing with points")
p3.plot(np.random.normal(size=100), pen=(200,200,200), symbolBrush=(255,0,0), symbolPen='w') p3.plot(np.random.normal(size=100), pen=(200,200,200), symbolBrush=(255,0,0), symbolPen='w')
......
...@@ -292,7 +292,8 @@ def plot(*args, **kargs): ...@@ -292,7 +292,8 @@ def plot(*args, **kargs):
dataArgs[k] = kargs[k] dataArgs[k] = kargs[k]
w = PlotWindow(**pwArgs) w = PlotWindow(**pwArgs)
w.plot(*args, **dataArgs) if len(args) > 0 or len(dataArgs) > 0:
w.plot(*args, **dataArgs)
plots.append(w) plots.append(w)
w.show() w.show()
return w return w
......
...@@ -33,8 +33,14 @@ class CSVExporter(Exporter): ...@@ -33,8 +33,14 @@ class CSVExporter(Exporter):
data = [] data = []
header = [] header = []
for c in self.item.curves: for c in self.item.curves:
data.append(c.getData()) cd = c.getData()
header.extend(['x', 'y']) if cd[0] is None:
continue
data.append(cd)
name = ''
if hasattr(c, 'implements') and c.implements('plotData') and c.name() is not None:
name = c.name().replace('"', '""') + '_'
header.extend(['"'+name+'x"', '"'+name+'y"'])
if self.params['separator'] == 'comma': if self.params['separator'] == 'comma':
sep = ',' sep = ','
...@@ -44,7 +50,7 @@ class CSVExporter(Exporter): ...@@ -44,7 +50,7 @@ class CSVExporter(Exporter):
fd.write(sep.join(header) + '\n') fd.write(sep.join(header) + '\n')
i = 0 i = 0
numFormat = '%%0.%dg' % self.params['precision'] numFormat = '%%0.%dg' % self.params['precision']
numRows = reduce(max, [len(d[0]) for d in data]) numRows = max([len(d[0]) for d in data])
for i in range(numRows): for i in range(numRows):
for d in data: for d in data:
if i < len(d[0]): if i < len(d[0]):
......
...@@ -65,7 +65,7 @@ class PlotCurveItem(GraphicsObject): ...@@ -65,7 +65,7 @@ class PlotCurveItem(GraphicsObject):
'brush': None, 'brush': None,
'stepMode': False, 'stepMode': False,
'name': None, 'name': None,
'antialias': pg.getConfigOption('antialias'),\ 'antialias': pg.getConfigOption('antialias'),
'connect': 'all', 'connect': 'all',
'mouseWidth': 8, # width of shape responding to mouse click 'mouseWidth': 8, # width of shape responding to mouse click
} }
...@@ -78,6 +78,9 @@ class PlotCurveItem(GraphicsObject): ...@@ -78,6 +78,9 @@ class PlotCurveItem(GraphicsObject):
return ints return ints
return interface in ints return interface in ints
def name(self):
return self.opts.get('name', None)
def setClickable(self, s, width=None): def setClickable(self, s, width=None):
"""Sets whether the item responds to mouse clicks. """Sets whether the item responds to mouse clicks.
......
...@@ -170,6 +170,9 @@ class PlotDataItem(GraphicsObject): ...@@ -170,6 +170,9 @@ class PlotDataItem(GraphicsObject):
return ints return ints
return interface in ints return interface in ints
def name(self):
return self.opts.get('name', None)
def boundingRect(self): def boundingRect(self):
return QtCore.QRectF() ## let child items handle this return QtCore.QRectF() ## let child items handle this
......
...@@ -514,7 +514,9 @@ class PlotItem(GraphicsWidget): ...@@ -514,7 +514,9 @@ class PlotItem(GraphicsWidget):
if 'ignoreBounds' in kargs: if 'ignoreBounds' in kargs:
vbargs['ignoreBounds'] = kargs['ignoreBounds'] vbargs['ignoreBounds'] = kargs['ignoreBounds']
self.vb.addItem(item, *args, **vbargs) self.vb.addItem(item, *args, **vbargs)
name = None
if hasattr(item, 'implements') and item.implements('plotData'): if hasattr(item, 'implements') and item.implements('plotData'):
name = item.name()
self.dataItems.append(item) self.dataItems.append(item)
#self.plotChanged() #self.plotChanged()
...@@ -547,7 +549,7 @@ class PlotItem(GraphicsWidget): ...@@ -547,7 +549,7 @@ class PlotItem(GraphicsWidget):
#c.connect(c, QtCore.SIGNAL('plotChanged'), self.plotChanged) #c.connect(c, QtCore.SIGNAL('plotChanged'), self.plotChanged)
#item.sigPlotChanged.connect(self.plotChanged) #item.sigPlotChanged.connect(self.plotChanged)
#self.plotChanged() #self.plotChanged()
name = kargs.get('name', getattr(item, 'opts', {}).get('name', None)) #name = kargs.get('name', getattr(item, 'opts', {}).get('name', None))
if name is not None and hasattr(self, 'legend') and self.legend is not None: if name is not None and hasattr(self, 'legend') and self.legend is not None:
self.legend.addItem(item, name=name) self.legend.addItem(item, name=name)
......
...@@ -234,6 +234,7 @@ class ScatterPlotItem(GraphicsObject): ...@@ -234,6 +234,7 @@ class ScatterPlotItem(GraphicsObject):
'pxMode': True, 'pxMode': True,
'useCache': True, ## If useCache is False, symbols are re-drawn on every paint. 'useCache': True, ## If useCache is False, symbols are re-drawn on every paint.
'antialias': pg.getConfigOption('antialias'), 'antialias': pg.getConfigOption('antialias'),
'name': None,
} }
self.setPen(200,200,200, update=False) self.setPen(200,200,200, update=False)
...@@ -281,6 +282,8 @@ class ScatterPlotItem(GraphicsObject): ...@@ -281,6 +282,8 @@ class ScatterPlotItem(GraphicsObject):
*antialias* Whether to draw symbols with antialiasing. Note that if pxMode is True, symbols are *antialias* Whether to draw symbols with antialiasing. Note that if pxMode is True, symbols are
always rendered with antialiasing (since the rendered symbols can be cached, this always rendered with antialiasing (since the rendered symbols can be cached, this
incurs very little performance cost) incurs very little performance cost)
*name* The name of this item. Names are used for automatically
generating LegendItem entries and by some exporters.
====================== =============================================================================================== ====================== ===============================================================================================
""" """
oldData = self.data ## this causes cached pixmaps to be preserved while new data is registered. oldData = self.data ## this causes cached pixmaps to be preserved while new data is registered.
...@@ -410,6 +413,9 @@ class ScatterPlotItem(GraphicsObject): ...@@ -410,6 +413,9 @@ class ScatterPlotItem(GraphicsObject):
return ints return ints
return interface in ints return interface in ints
def name(self):
return self.opts.get('name', None)
def setPen(self, *args, **kargs): def setPen(self, *args, **kargs):
"""Set the pen(s) used to draw the outline around each spot. """Set the pen(s) used to draw the outline around each spot.
If a list or array is provided, then the pen for each spot will be set separately. If a list or array is provided, then the pen for each spot will be set separately.
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment