00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033 from python_qt_binding import QT_BINDING, QT_BINDING_VERSION
00034
00035 try:
00036 from pkg_resources import parse_version
00037 except:
00038 import re
00039
00040 def parse_version(s):
00041 return [int(x) for x in re.sub(r'(\.0+)*$', '', s).split('.')]
00042
00043 if QT_BINDING == 'pyside':
00044 qt_binding_version = QT_BINDING_VERSION.replace('~', '-')
00045 if parse_version(qt_binding_version) <= parse_version('1.1.2'):
00046 raise ImportError('A PySide version newer than 1.1.0 is required.')
00047
00048 from python_qt_binding.QtCore import Slot, Qt, qVersion, qWarning, Signal
00049 from python_qt_binding.QtGui import QColor
00050 from python_qt_binding.QtWidgets import QWidget, QVBoxLayout, QSizePolicy
00051
00052 import operator
00053 import matplotlib
00054 if qVersion().startswith('5.'):
00055 if QT_BINDING == 'pyside':
00056 if parse_version(matplotlib.__version__) < parse_version('2.1.0'):
00057 raise ImportError('A newer matplotlib is required (at least 2.1.0 for PySide 2)')
00058 if parse_version(matplotlib.__version__) < parse_version('1.4.0'):
00059 raise ImportError('A newer matplotlib is required (at least 1.4.0 for Qt 5)')
00060 try:
00061 matplotlib.use('Qt5Agg')
00062 from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas
00063 except ImportError:
00064
00065 import sys
00066 import thread
00067 sys.modules['_thread'] = thread
00068 from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas
00069 from matplotlib.backends.backend_qt5agg import NavigationToolbar2QT as NavigationToolbar
00070 elif qVersion().startswith('4.'):
00071 if parse_version(matplotlib.__version__) < parse_version('1.1.0'):
00072 raise ImportError('A newer matplotlib is required (at least 1.1.0 for Qt 4)')
00073 try:
00074 matplotlib.use('Qt4Agg')
00075 from matplotlib.backends.backend_qt4agg import FigureCanvasQTAgg as FigureCanvas
00076 except ImportError:
00077
00078 import sys
00079 import thread
00080 sys.modules['_thread'] = thread
00081 from matplotlib.backends.backend_qt4agg import FigureCanvasQTAgg as FigureCanvas
00082 try:
00083 from matplotlib.backends.backend_qt4agg import NavigationToolbar2QTAgg as NavigationToolbar
00084 except ImportError:
00085 from matplotlib.backends.backend_qt4agg import NavigationToolbar2QT as NavigationToolbar
00086 else:
00087 raise NotImplementedError('Unsupport Qt version: %s' % qVersion())
00088
00089 from matplotlib.figure import Figure
00090
00091 import numpy
00092
00093
00094 class MatDataPlot(QWidget):
00095
00096 class Canvas(FigureCanvas):
00097
00098 """Ultimately, this is a QWidget (as well as a FigureCanvasAgg, etc.)."""
00099
00100 def __init__(self, parent=None):
00101 super(MatDataPlot.Canvas, self).__init__(Figure())
00102 self.axes = self.figure.add_subplot(111)
00103 self.axes.grid(True, color='gray')
00104 self.figure.tight_layout()
00105 self.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
00106 self.updateGeometry()
00107
00108 def resizeEvent(self, event):
00109 super(MatDataPlot.Canvas, self).resizeEvent(event)
00110 self.figure.tight_layout()
00111
00112 limits_changed = Signal()
00113
00114 def __init__(self, parent=None):
00115 super(MatDataPlot, self).__init__(parent)
00116 self._canvas = MatDataPlot.Canvas()
00117 self._toolbar = NavigationToolbar(self._canvas, self._canvas)
00118 vbox = QVBoxLayout()
00119 vbox.addWidget(self._toolbar)
00120 vbox.addWidget(self._canvas)
00121 self.setLayout(vbox)
00122
00123 self._curves = {}
00124 self._current_vline = None
00125 self._canvas.mpl_connect('button_release_event', self._limits_changed)
00126
00127 def _limits_changed(self, event):
00128 self.limits_changed.emit()
00129
00130 def add_curve(self, curve_id, curve_name, curve_color=QColor(Qt.blue), markers_on=False):
00131
00132
00133 x_limits = self.get_xlim()
00134 y_limits = self.get_ylim()
00135 if markers_on:
00136 marker_size = 3
00137 else:
00138 marker_size = 0
00139 line = self._canvas.axes.plot([], [], 'o-', markersize=marker_size, label=curve_name,
00140 linewidth=1, picker=5, color=curve_color.name())[0]
00141 self._curves[curve_id] = line
00142 self._update_legend()
00143 self.set_xlim(x_limits)
00144 self.set_ylim(y_limits)
00145
00146 def remove_curve(self, curve_id):
00147 curve_id = str(curve_id)
00148 if curve_id in self._curves:
00149 self._curves[curve_id].remove()
00150 del self._curves[curve_id]
00151 self._update_legend()
00152
00153 def _update_legend(self):
00154 handles, labels = self._canvas.axes.get_legend_handles_labels()
00155 if handles:
00156 hl = sorted(zip(handles, labels), key=operator.itemgetter(1))
00157 handles, labels = zip(*hl)
00158 self._canvas.axes.legend(handles, labels, loc='upper left')
00159
00160 def set_values(self, curve, data_x, data_y):
00161 line = self._curves[curve]
00162 line.set_data(data_x, data_y)
00163
00164 def redraw(self):
00165 self._canvas.axes.grid(True, color='gray')
00166 self._canvas.draw()
00167
00168 def vline(self, x, color):
00169
00170 matcolor = (color[0] / 255.0, color[1] / 255.0, color[2] / 255.0)
00171 if self._current_vline:
00172 self._current_vline.remove()
00173 self._current_vline = self._canvas.axes.axvline(x=x, color=matcolor)
00174
00175 def set_xlim(self, limits):
00176 self._canvas.axes.set_xbound(lower=limits[0], upper=limits[1])
00177
00178 def set_ylim(self, limits):
00179 self._canvas.axes.set_ybound(lower=limits[0], upper=limits[1])
00180
00181 def get_xlim(self):
00182 return list(self._canvas.axes.get_xbound())
00183
00184 def get_ylim(self):
00185 return list(self._canvas.axes.get_ybound())