After some problems I reported earlier I finally made the matplotlib exporter to work for me.
However, data are exported without errorbars. See screenshot:
in /exporters/Matplotlib.py
one can see:
pl = ax.plot(x, y, marker=symbol, color=color, linewidth=pen.width(), linestyle=linestyle, markeredgecolor=markeredgecolor, markerfacecolor=markerfacecolor, markersize=markersize)
which probably needs to be changed to:
pl = ax.errorbar(x, y, yerr=yerr, marker=symbol, color=color, linewidth=pen.width(), linestyle=linestyle, markeredgecolor=markeredgecolor, markerfacecolor=markerfacecolor, markersize=markersize)
but how do I get the yerr values within the Matplotlib.py?
BTW, errorbars were plotted in pyqtgraph with (e.g. part of my code):
err1 = pg.ErrorBarItem(x=fit.fit_results.rv_model.jd[fit.filelist.idset==i], y=fit.fit_results.rv_model.rvs[fit.filelist.idset==i],symbol='o', height=error_list[fit.filelist.idset==i], beam=0.0, pen=colors[i]) p1.addItem(err1)
#!/usr/bin/env python3
import sys
from PyQt5 import QtCore, QtWidgets, uic
from PyQt5.QtWidgets import QFileDialog
import numpy as np
import pyqtgraph as pg
import test_matplotlib_plots as plots
class PlotWindow(QtWidgets.QMainWindow):
def __init__(self):
super().__init__()
pg.setConfigOptions(antialias=True)
# Load GUI layout from .ui file (named same as this source file, but with .ui extension)
uic.loadUi(__file__.split('.py')[0] + '.ui', self)
# Finish up the GUI and connections
self.statusbar.showMessage("Welcome!")
self.actionExport.triggered.connect(self.export_plot)
self.plot = self.glw.addPlot()
# Make some test data
self.xcoords = np.arange(0, 100, 3)
self.data = 50.0*np.random.random((5, self.xcoords.shape[0]))
self.data += 1.0 + 2.0*self.xcoords
# Plot test data
self.errorbars = pg.ErrorBarItem(x=self.xcoords, y=np.mean(self.data, axis=0), height=np.std(self.data, axis=0), beam=1)
self.plot.addItem(self.errorbars)
self.plot.plot(x=self.xcoords, y=np.mean(self.data, axis=0), symbol="o")
self.plot.setLabels(bottom="Time, (s)", left="Intensity (a.u.)")
def export_plot(self):
self.statusbar.showMessage('Exporting plot...')
filename, _ = QFileDialog.getSaveFileName(self, "Export As...", "", "PDF Image (*.pdf);;All Files (*)")
if filename:
# Remove any duplicated file extensions that Qt might add
filename = filename.partition(".pdf")[0] + ".pdf"
plots.testdata_image(self.xcoords, self.data, filename, label="Test data", xlim=self.plot.viewRange()[0], ylim=self.plot.viewRange()[1])
self.statusbar.showMessage("Data saved to {}.".format(filename))
else:
self.statusbar.showMessage("Export cancelled.")
def main():
app = QtWidgets.QApplication(sys.argv)
mainwindow = PlotWindow()
mainwindow.show()
sys.exit(app.exec_())
if __name__ == '__main__':
main()import numpy as np
import matplotlib.pyplot as plt
from cycler import cycler
from matplotlib.ticker import AutoMinorLocator
def testdata_figure(xcoords, data, **kwargs):
"""Plot data, returning a matplotlib figure object."""
args = {"xlim": None,
"ylim": None,
"label": "",
"xlabel": "Time (s)",
"ylabel": "Intensity (a.u.)",
"ccycle": ['#0000a0', '#a00000', '#00a000', '#000000', '#a000a0', '#a0a000', '#00a0a0', '#808080'],
"figsize": (5.0, 3.75),
"legendloc": "best"}
args.update(kwargs)
# Configure figure, axes
fig, ax = plt.subplots(figsize=args["figsize"])
ax.set_prop_cycle(cycler('color', args["ccycle"]))
ax.set_xlabel(args["xlabel"])
ax.set_ylabel(args["ylabel"])
if args["xlim"] is not None:
ax.set_xlim(args["xlim"])
if args["ylim"] is not None:
ax.set_ylim(args["ylim"])
ax.xaxis.set_minor_locator(AutoMinorLocator(2))
ax.yaxis.set_minor_locator(AutoMinorLocator(2))
ax.errorbar(xcoords, np.mean(data, axis=0), yerr=np.std(data, axis=0), capsize=3, label=args["label"])
ax.legend(fontsize='medium', frameon=False, loc=args["legendloc"])
plt.tight_layout()
return fig
def testdata_image(xcoords, data, output_filename, **kwargs):
"""Plot data to an image file."""
args = {"dpi": 300}
args.update(kwargs)
fig = testdata_figure(xcoords, data, **kwargs)
fig.savefig(output_filename, dpi=args["dpi"])
plt.close(fig)<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>MainWindow</class>
<widget class="QMainWindow" name="MainWindow">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>800</width>
<height>600</height>
</rect>
</property>
<property name="windowTitle">
<string>Test MPL Export</string>
</property>
<widget class="QWidget" name="centralwidget">
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="GraphicsLayoutWidget" name="glw"/>
</item>
</layout>
</widget>
<widget class="QMenuBar" name="menubar">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>800</width>
<height>19</height>
</rect>
</property>
<widget class="QMenu" name="menuFile">
<property name="title">
<string>&File</string>
</property>
<addaction name="actionExport"/>
<addaction name="separator"/>
<addaction name="actionExit"/>
</widget>
<addaction name="menuFile"/>
</widget>
<widget class="QStatusBar" name="statusbar"/>
<action name="actionExport">
<property name="text">
<string>&Export plot...</string>
</property>
</action>
<action name="actionExit">
<property name="text">
<string>E&xit</string>
</property>
</action>
</widget>
<customwidgets>
<customwidget>
<class>GraphicsLayoutWidget</class>
<extends>QGraphicsView</extends>
<header>pyqtgraph</header>
</customwidget>
</customwidgets>
<resources/>
<connections>
<connection>
<sender>actionExit</sender>
<signal>triggered()</signal>
<receiver>MainWindow</receiver>
<slot>close()</slot>
<hints>
<hint type="sourcelabel">
<x>-1</x>
<y>-1</y>
</hint>
<hint type="destinationlabel">
<x>399</x>
<y>299</y>
</hint>
</hints>
</connection>
</connections>
</ui>
def export(self, fileName=None):
if isinstance(self.item, PlotItem):
mpw = MatplotlibWindow()
MatplotlibExporter.windows.append(mpw)
stdFont = 'Arial'
fig = mpw.getFigure()
# get labels from the graphic item
xlabel = self.item.axes['bottom']['item'].label.toPlainText()
ylabel = self.item.axes['left']['item'].label.toPlainText()
title = self.item.titleLabel.text
ax = fig.add_subplot(111, title=title)
ax.clear()
self.cleanAxes(ax)
#ax.grid(True)
for indx, item in enumerate(self.item.curves):
x, y = item.getData()
if x is None:
continue
opts = item.opts
#print(opts)
pen = fn.mkPen(opts['pen'])
if pen.style() == QtCore.Qt.NoPen:
linestyle = ''
else:
linestyle = '-'
color = tuple([c/255. for c in fn.colorTuple(pen.color())])
symbol = opts['symbol']
if symbol == 't':
symbol = '^'
symbolPen = fn.mkPen(opts['symbolPen'])
symbolBrush = fn.mkBrush(opts['symbolBrush'])
markeredgecolor = tuple([c/255. for c in fn.colorTuple(symbolPen.color())])
markerfacecolor = tuple([c/255. for c in fn.colorTuple(symbolBrush.color())])
markersize = opts['symbolSize']
if opts['fillLevel'] is not None and opts['fillBrush'] is not None:
fillBrush = fn.mkBrush(opts['fillBrush'])
fillcolor = tuple([c/255. for c in fn.colorTuple(fillBrush.color())])
ax.fill_between(x=x, y1=y, y2=opts['fillLevel'], facecolor=fillcolor)
ax.plot(x, y, marker=symbol, color=color, linewidth=pen.width(),
linestyle=linestyle,
markeredgecolor=markeredgecolor,
markerfacecolor=markerfacecolor,
markersize=markersize)
xr, yr = self.item.viewRange()
ax.set_xbound(*xr)
ax.set_ybound(*yr)
###### This is the simple hack: the loops looks for ErrorBarItem is inside "items" and plots them using the mpl errorbar()
for indx, item in enumerate(self.item.items):
if indx <=1:
continue
if "height" in self.item.items[indx].opts:
ax.errorbar(x=self.item.items[indx].opts["x"], y=self.item.items[indx].opts["y"],
yerr=self.item.items[indx].opts["height"]/2., linestyle='', marker='o',markersize=0.5, linewidth=1.0,
color=self.item.items[indx].opts["pen"], capsize = 0, elinewidth=1,mew=0.0, zorder=-10)
################### end of the hack ################################
ax.set_xlabel(xlabel) # place the labels.
ax.set_ylabel(ylabel)
ax.spines['top'].set_color('k')
ax.spines['right'].set_color('k')
mpw.draw()
else:
raise Exception("Matplotlib export currently only works with plot items")