Handle axis SI prefix scaling in MatplotlibExporter (#1282)
* Handle axis SI prefix scaling in MatplotlibExporter * Added some MatplotlibExporter tests and added matplotlib to CI deps * Install mpl with pip instead of conda * Cleanup
This commit is contained in:
parent
96d1ef986f
commit
4110b3e539
|
@ -106,8 +106,9 @@ jobs:
|
||||||
fi
|
fi
|
||||||
conda info
|
conda info
|
||||||
conda install $(qt.bindings) numpy scipy pyopengl h5py six --yes --quiet
|
conda install $(qt.bindings) numpy scipy pyopengl h5py six --yes --quiet
|
||||||
|
pip install matplotlib
|
||||||
else
|
else
|
||||||
pip install $(qt.bindings) numpy scipy pyopengl h5py six
|
pip install $(qt.bindings) numpy scipy pyopengl h5py six matplotlib
|
||||||
fi
|
fi
|
||||||
pip install pytest pytest-cov coverage pytest-xdist
|
pip install pytest pytest-cov coverage pytest-xdist
|
||||||
if [ $(python.version) == "2.7" ]
|
if [ $(python.version) == "2.7" ]
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
from ..Qt import QtGui, QtCore
|
from ..Qt import QtGui, QtCore
|
||||||
from .Exporter import Exporter
|
from .Exporter import Exporter
|
||||||
from .. import PlotItem
|
from .. import PlotItem
|
||||||
|
@ -31,6 +32,7 @@ publication. Fonts are not vectorized (outlined), and window colors are white.
|
||||||
class MatplotlibExporter(Exporter):
|
class MatplotlibExporter(Exporter):
|
||||||
Name = "Matplotlib Window"
|
Name = "Matplotlib Window"
|
||||||
windows = []
|
windows = []
|
||||||
|
|
||||||
def __init__(self, item):
|
def __init__(self, item):
|
||||||
Exporter.__init__(self, item)
|
Exporter.__init__(self, item)
|
||||||
|
|
||||||
|
@ -55,26 +57,38 @@ class MatplotlibExporter(Exporter):
|
||||||
ax.xaxis.set_ticks_position('bottom')
|
ax.xaxis.set_ticks_position('bottom')
|
||||||
|
|
||||||
def export(self, fileName=None):
|
def export(self, fileName=None):
|
||||||
|
if not isinstance(self.item, PlotItem):
|
||||||
|
raise Exception("MatplotlibExporter currently only works with PlotItem")
|
||||||
|
|
||||||
if isinstance(self.item, PlotItem):
|
|
||||||
mpw = MatplotlibWindow()
|
mpw = MatplotlibWindow()
|
||||||
MatplotlibExporter.windows.append(mpw)
|
MatplotlibExporter.windows.append(mpw)
|
||||||
|
|
||||||
stdFont = 'Arial'
|
|
||||||
|
|
||||||
fig = mpw.getFigure()
|
fig = mpw.getFigure()
|
||||||
|
|
||||||
|
xax = self.item.getAxis('bottom')
|
||||||
|
yax = self.item.getAxis('left')
|
||||||
|
|
||||||
# get labels from the graphic item
|
# get labels from the graphic item
|
||||||
xlabel = self.item.axes['bottom']['item'].label.toPlainText()
|
xlabel = xax.label.toPlainText()
|
||||||
ylabel = self.item.axes['left']['item'].label.toPlainText()
|
ylabel = yax.label.toPlainText()
|
||||||
title = self.item.titleLabel.text
|
title = self.item.titleLabel.text
|
||||||
|
|
||||||
|
# if axes use autoSIPrefix, scale the data so mpl doesn't add its own
|
||||||
|
# scale factor label
|
||||||
|
xscale = yscale = 1.0
|
||||||
|
if xax.autoSIPrefix:
|
||||||
|
xscale = xax.autoSIPrefixScale
|
||||||
|
if yax.autoSIPrefix:
|
||||||
|
yscale = yax.autoSIPrefixScale
|
||||||
|
|
||||||
ax = fig.add_subplot(111, title=title)
|
ax = fig.add_subplot(111, title=title)
|
||||||
ax.clear()
|
ax.clear()
|
||||||
self.cleanAxes(ax)
|
self.cleanAxes(ax)
|
||||||
#ax.grid(True)
|
|
||||||
for item in self.item.curves:
|
for item in self.item.curves:
|
||||||
x, y = item.getData()
|
x, y = item.getData()
|
||||||
|
x = x * xscale
|
||||||
|
y = y * yscale
|
||||||
|
|
||||||
opts = item.opts
|
opts = item.opts
|
||||||
pen = fn.mkPen(opts['pen'])
|
pen = fn.mkPen(opts['pen'])
|
||||||
if pen.style() == QtCore.Qt.NoPen:
|
if pen.style() == QtCore.Qt.NoPen:
|
||||||
|
@ -99,14 +113,14 @@ class MatplotlibExporter(Exporter):
|
||||||
pl = ax.plot(x, y, marker=symbol, color=color, linewidth=pen.width(),
|
pl = ax.plot(x, y, marker=symbol, color=color, linewidth=pen.width(),
|
||||||
linestyle=linestyle, markeredgecolor=markeredgecolor, markerfacecolor=markerfacecolor,
|
linestyle=linestyle, markeredgecolor=markeredgecolor, markerfacecolor=markerfacecolor,
|
||||||
markersize=markersize)
|
markersize=markersize)
|
||||||
|
|
||||||
xr, yr = self.item.viewRange()
|
xr, yr = self.item.viewRange()
|
||||||
ax.set_xbound(*xr)
|
ax.set_xbound(xr[0]*xscale, xr[1]*xscale)
|
||||||
ax.set_ybound(*yr)
|
ax.set_ybound(yr[0]*yscale, yr[1]*yscale)
|
||||||
|
|
||||||
ax.set_xlabel(xlabel) # place the labels.
|
ax.set_xlabel(xlabel) # place the labels.
|
||||||
ax.set_ylabel(ylabel)
|
ax.set_ylabel(ylabel)
|
||||||
mpw.draw()
|
mpw.draw()
|
||||||
else:
|
|
||||||
raise Exception("Matplotlib export currently only works with plot items")
|
|
||||||
|
|
||||||
MatplotlibExporter.register()
|
MatplotlibExporter.register()
|
||||||
|
|
||||||
|
|
50
pyqtgraph/exporters/tests/test_matplotlib.py
Normal file
50
pyqtgraph/exporters/tests/test_matplotlib.py
Normal file
|
@ -0,0 +1,50 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
import pytest
|
||||||
|
import pyqtgraph as pg
|
||||||
|
from pyqtgraph.exporters import MatplotlibExporter
|
||||||
|
pytest.importorskip("matplotlib")
|
||||||
|
|
||||||
|
app = pg.mkQApp()
|
||||||
|
|
||||||
|
|
||||||
|
def test_MatplotlibExporter():
|
||||||
|
plt = pg.plot()
|
||||||
|
|
||||||
|
# curve item
|
||||||
|
plt.plot([0, 1, 2], [0, 1, 2])
|
||||||
|
# scatter item
|
||||||
|
plt.plot([0, 1, 2], [1, 2, 3], pen=None, symbolBrush='r')
|
||||||
|
# curve + scatter
|
||||||
|
plt.plot([0, 1, 2], [2, 3, 4], pen='k', symbolBrush='r')
|
||||||
|
|
||||||
|
exp = MatplotlibExporter(plt.getPlotItem())
|
||||||
|
exp.export()
|
||||||
|
|
||||||
|
|
||||||
|
def test_MatplotlibExporter_nonplotitem():
|
||||||
|
# attempting to export something other than a PlotItem raises an exception
|
||||||
|
plt = pg.plot()
|
||||||
|
plt.plot([0, 1, 2], [2, 3, 4])
|
||||||
|
exp = MatplotlibExporter(plt.getPlotItem().getViewBox())
|
||||||
|
with pytest.raises(Exception):
|
||||||
|
exp.export()
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize('scale', [1e10, 1e-9])
|
||||||
|
def test_MatplotlibExporter_siscale(scale):
|
||||||
|
# coarse test to verify that plot data is scaled before export when
|
||||||
|
# autoSIPrefix is in effect (so mpl doesn't add its own multiplier label)
|
||||||
|
plt = pg.plot([0, 1, 2], [(i+1)*scale for i in range(3)])
|
||||||
|
# set the label so autoSIPrefix works
|
||||||
|
plt.setLabel('left', 'magnitude')
|
||||||
|
exp = MatplotlibExporter(plt.getPlotItem())
|
||||||
|
exp.export()
|
||||||
|
|
||||||
|
mpw = MatplotlibExporter.windows[-1]
|
||||||
|
fig = mpw.getFigure()
|
||||||
|
ymin, ymax = fig.axes[0].get_ylim()
|
||||||
|
|
||||||
|
if scale < 1:
|
||||||
|
assert ymax > scale
|
||||||
|
else:
|
||||||
|
assert ymax < scale
|
Loading…
Reference in New Issue
Block a user