Commit a157d9c4 authored by Luke Campagnola's avatar Luke Campagnola
Browse files

Added better API for controlling antialiasing in plots

PlotItem auto-range button is now hidden by default; only appears for plots that are not already auto-ranged and have mouse hover.
parent ef9d730d
......@@ -18,7 +18,7 @@ app = QtGui.QApplication([])
#mw.resize(800,800)
win = pg.GraphicsWindow(title="Basic plotting examples")
win.resize(800,600)
win.resize(1000,600)
......
......@@ -6,6 +6,7 @@ from .GraphicsObject import GraphicsObject
import pyqtgraph.functions as fn
from pyqtgraph import debug
from pyqtgraph.Point import Point
import pyqtgraph as pg
import struct, sys
__all__ = ['PlotCurveItem']
......@@ -52,7 +53,6 @@ class PlotCurveItem(GraphicsObject):
self.path = None
self.fillPath = None
self.exportOpts = False
self.antialias = False
## this is disastrous for performance.
......@@ -65,7 +65,8 @@ class PlotCurveItem(GraphicsObject):
'fillLevel': None,
'brush': None,
'stepMode': False,
'name': None
'name': None,
'antialias': pg.getConfigOption('antialias'),
}
self.setClickable(kargs.get('clickable', False))
self.setData(*args, **kargs)
......@@ -168,7 +169,7 @@ class PlotCurveItem(GraphicsObject):
def setData(self, *args, **kargs):
"""
============== =======================================================
============== ========================================================
**Arguments:**
x, y (numpy arrays) Data to show
pen Pen to use when drawing. Any single argument accepted by
......@@ -181,7 +182,9 @@ class PlotCurveItem(GraphicsObject):
*fillLevel*
brush QBrush to use when filling. Any single argument accepted
by :func:`mkBrush <pyqtgraph.mkBrush>` is allowed.
============== =======================================================
antialias (bool) Whether to use antialiasing when drawing. This
is disabled by default because it decreases performance.
============== ========================================================
If non-keyword arguments are used, they will be interpreted as
setData(y) for a single argument and setData(x, y) for two
......@@ -250,6 +253,8 @@ class PlotCurveItem(GraphicsObject):
self.setFillLevel(kargs['fillLevel'])
if 'brush' in kargs:
self.setBrush(kargs['brush'])
if 'antialias' in kargs:
self.opts['antialias'] = kargs['antialias']
prof.mark('set')
......@@ -398,6 +403,14 @@ class PlotCurveItem(GraphicsObject):
path = self.path
prof.mark('generate path')
if self.exportOpts is not False:
aa = self.exportOpts['antialias']
else:
aa = self.opts['antialias']
p.setRenderHint(p.Antialiasing, aa)
if self.opts['brush'] is not None and self.opts['fillLevel'] is not None:
if self.fillPath is None:
......@@ -426,12 +439,6 @@ class PlotCurveItem(GraphicsObject):
#pen.setColor(c)
##pen.setCosmetic(True)
if self.exportOpts is not False:
aa = self.exportOpts['antialias']
else:
aa = self.antialias
p.setRenderHint(p.Antialiasing, aa)
if sp is not None:
......
......@@ -7,6 +7,7 @@ import numpy as np
import scipy
import pyqtgraph.functions as fn
import pyqtgraph.debug as debug
import pyqtgraph as pg
class PlotDataItem(GraphicsObject):
"""
......@@ -84,6 +85,9 @@ 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.
identical *deprecated*
decimate (int) sub-sample data by selecting every nth sample before plotting
========== =====================================================================
......@@ -130,6 +134,7 @@ class PlotDataItem(GraphicsObject):
'symbolBrush': (50, 50, 150),
'pxMode': True,
'antialias': pg.getConfigOption('antialias'),
'pointMode': None,
'data': None,
......@@ -379,11 +384,11 @@ class PlotDataItem(GraphicsObject):
#c.scene().removeItem(c)
curveArgs = {}
for k,v in [('pen','pen'), ('shadowPen','shadowPen'), ('fillLevel','fillLevel'), ('fillBrush', 'brush')]:
for k,v in [('pen','pen'), ('shadowPen','shadowPen'), ('fillLevel','fillLevel'), ('fillBrush', 'brush'), ('antialias', 'antialias')]:
curveArgs[v] = self.opts[k]
scatterArgs = {}
for k,v in [('symbolPen','pen'), ('symbolBrush','brush'), ('symbol','symbol'), ('symbolSize', 'size'), ('data', 'data'), ('pxMode', 'pxMode')]:
for k,v in [('symbolPen','pen'), ('symbolBrush','brush'), ('symbol','symbol'), ('symbolSize', 'size'), ('data', 'data'), ('pxMode', 'pxMode'), ('antialias', 'antialias')]:
if k in self.opts:
scatterArgs[v] = self.opts[k]
......
......@@ -131,6 +131,9 @@ class PlotItem(GraphicsWidget):
self.autoBtn = ButtonItem(pyqtgraph.pixmaps.getPixmap('auto'), 14, self)
self.autoBtn.mode = 'auto'
self.autoBtn.clicked.connect(self.autoBtnClicked)
#self.autoBtn.hide()
self.buttonsHidden = False ## whether the user has requested buttons to be hidden
self.mouseHovering = False
self.layout = QtGui.QGraphicsGridLayout()
self.layout.setContentsMargins(1,1,1,1)
......@@ -141,6 +144,7 @@ class PlotItem(GraphicsWidget):
if viewBox is None:
viewBox = ViewBox()
self.vb = viewBox
self.vb.sigStateChanged.connect(self.viewStateChanged)
self.setMenuEnabled(enableMenu, enableMenu) ## en/disable plotitem and viewbox menus
if name is not None:
......@@ -476,9 +480,13 @@ class PlotItem(GraphicsWidget):
def autoBtnClicked(self):
if self.autoBtn.mode == 'auto':
self.enableAutoRange()
self.autoBtn.hide()
else:
self.disableAutoRange()
def viewStateChanged(self):
self.updateButtons()
def enableAutoScale(self):
"""
Enable auto-scaling. The plot will continuously scale to fit the boundaries of its data.
......@@ -1003,7 +1011,14 @@ class PlotItem(GraphicsWidget):
def menuEnabled(self):
return self._menuEnabled
def hoverEvent(self, ev):
if ev.enter:
self.mouseHovering = True
if ev.exit:
self.mouseHovering = False
self.updateButtons()
def getLabel(self, key):
pass
......@@ -1082,8 +1097,20 @@ class PlotItem(GraphicsWidget):
def hideButtons(self):
"""Causes auto-scale button ('A' in lower-left corner) to be hidden for this PlotItem"""
#self.ctrlBtn.hide()
self.autoBtn.hide()
self.buttonsHidden = True
self.updateButtons()
def showButtons(self):
"""Causes auto-scale button ('A' in lower-left corner) to be visible for this PlotItem"""
#self.ctrlBtn.hide()
self.buttonsHidden = False
self.updateButtons()
def updateButtons(self):
if self.mouseHovering and not self.buttonsHidden and not all(self.vb.autoRangeEnabled()):
self.autoBtn.show()
else:
self.autoBtn.hide()
def _plotArray(self, arr, x=None, **kargs):
if arr.ndim != 1:
......
......@@ -8,6 +8,7 @@ import scipy.stats
import weakref
import pyqtgraph.debug as debug
from pyqtgraph.pgcollections import OrderedDict
import pyqtgraph as pg
#import pyqtgraph as pg
__all__ = ['ScatterPlotItem', 'SpotItem']
......@@ -233,7 +234,12 @@ class ScatterPlotItem(GraphicsObject):
self.bounds = [None, None] ## caches data bounds
self._maxSpotWidth = 0 ## maximum size of the scale-variant portion of all spots
self._maxSpotPxWidth = 0 ## maximum size of the scale-invariant portion of all spots
self.opts = {'pxMode': True, 'useCache': True, 'exportMode': False} ## If useCache is False, symbols are re-drawn on every paint.
self.opts = {
'pxMode': True,
'useCache': True, ## If useCache is False, symbols are re-drawn on every paint.
'antialias': pg.getConfigOption('antialias'),
}
self.exportOpts = False
self.setPen(200,200,200, update=False)
self.setBrush(100,100,150, update=False)
......@@ -278,6 +284,9 @@ class ScatterPlotItem(GraphicsObject):
it is in the item's local coordinate system.
*data* a list of python objects used to uniquely identify each spot.
*identical* *Deprecated*. This functionality is handled automatically now.
*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
incurs very little performance cost)
====================== ===============================================================================================
"""
oldData = self.data ## this causes cached pixmaps to be preserved while new data is registered.
......@@ -369,6 +378,8 @@ class ScatterPlotItem(GraphicsObject):
if 'pxMode' in kargs:
self.setPxMode(kargs['pxMode'])
if 'antialias' in kargs:
self.opts['antialias'] = kargs['antialias']
## Set any extra parameters provided in keyword arguments
for k in ['pen', 'brush', 'symbol', 'size']:
......@@ -378,7 +389,7 @@ class ScatterPlotItem(GraphicsObject):
if 'data' in kargs:
self.setPointData(kargs['data'], dataSet=newData)
self.prepareGeometryChange()
self.bounds = [None, None]
self.invalidate()
......@@ -664,8 +675,13 @@ class ScatterPlotItem(GraphicsObject):
rect = QtCore.QRectF(y, x, h, w)
self.fragments.append(QtGui.QPainter.PixmapFragment.create(pos, rect))
def setExportMode(self, enabled, opts):
self.opts['exportMode'] = enabled
def setExportMode(self, export, opts):
if export:
self.exportOpts = opts
if 'antialias' not in opts:
self.exportOpts['antialias'] = True
else:
self.exportOpts = False
def paint(self, p, *args):
......@@ -685,9 +701,15 @@ class ScatterPlotItem(GraphicsObject):
p.resetTransform()
if not USE_PYSIDE and self.opts['useCache'] and self.opts['exportMode'] is False:
if not USE_PYSIDE and self.opts['useCache'] and self.exportOpts is False:
p.drawPixmapFragments(self.fragments, atlas)
else:
if self.exportOpts is not False:
aa = self.exportOpts['antialias']
else:
aa = self.opts['antialias']
p.setRenderHint(p.Antialiasing, aa)
for i in range(len(self.data)):
rec = self.data[i]
frag = self.fragments[i]
......@@ -705,6 +727,11 @@ class ScatterPlotItem(GraphicsObject):
drawSymbol(p2, *self.getSpotOpts(rec))
p2.end()
if self.exportOpts is not False:
aa = self.exportOpts['antialias']
else:
aa = self.opts['antialias']
p.setRenderHint(p.Antialiasing, aa)
self.picture.play(p)
......
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