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 class Canvas(FigureCanvas):
00096 """Ultimately, this is a QWidget (as well as a FigureCanvasAgg, etc.)."""
00097 def __init__(self, parent=None):
00098 super(MatDataPlot.Canvas, self).__init__(Figure())
00099 self.axes = self.figure.add_subplot(111)
00100 self.axes.grid(True, color='gray')
00101 self.figure.tight_layout()
00102 self.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
00103 self.updateGeometry()
00104
00105 def resizeEvent(self, event):
00106 super(MatDataPlot.Canvas, self).resizeEvent(event)
00107 self.figure.tight_layout()
00108
00109 limits_changed = Signal()
00110
00111 def __init__(self, parent=None):
00112 super(MatDataPlot, self).__init__(parent)
00113 self._canvas = MatDataPlot.Canvas()
00114 self._toolbar = NavigationToolbar(self._canvas, self._canvas)
00115 vbox = QVBoxLayout()
00116 vbox.addWidget(self._toolbar)
00117 vbox.addWidget(self._canvas)
00118 self.setLayout(vbox)
00119
00120 self._curves = {}
00121 self._current_vline = None
00122 self._canvas.mpl_connect('button_release_event', self._limits_changed)
00123
00124 def _limits_changed(self, event):
00125 self.limits_changed.emit()
00126
00127 def add_curve(self, curve_id, curve_name, curve_color=QColor(Qt.blue), markers_on=False):
00128
00129
00130 x_limits = self.get_xlim()
00131 y_limits = self.get_ylim()
00132 if markers_on:
00133 marker_size = 3
00134 else:
00135 marker_size = 0
00136 line = self._canvas.axes.plot([], [], 'o-', markersize=marker_size, label=curve_name, linewidth=1, picker=5, color=curve_color.name())[0]
00137 self._curves[curve_id] = line
00138 self._update_legend()
00139 self.set_xlim(x_limits)
00140 self.set_ylim(y_limits)
00141
00142 def remove_curve(self, curve_id):
00143 curve_id = str(curve_id)
00144 if curve_id in self._curves:
00145 self._curves[curve_id].remove()
00146 del self._curves[curve_id]
00147 self._update_legend()
00148
00149 def _update_legend(self):
00150 handles, labels = self._canvas.axes.get_legend_handles_labels()
00151 if handles:
00152 hl = sorted(zip(handles, labels), key=operator.itemgetter(1))
00153 handles, labels = zip(*hl)
00154 self._canvas.axes.legend(handles, labels, loc='upper left')
00155
00156 def set_values(self, curve, data_x, data_y):
00157 line = self._curves[curve]
00158 line.set_data(data_x, data_y)
00159
00160 def redraw(self):
00161 self._canvas.axes.grid(True, color='gray')
00162 self._canvas.draw()
00163
00164 def vline(self, x, color):
00165
00166 matcolor=(color[0]/255.0, color[1]/255.0, color[2]/255.0)
00167 if self._current_vline:
00168 self._current_vline.remove()
00169 self._current_vline = self._canvas.axes.axvline(x=x, color=matcolor)
00170
00171 def set_xlim(self, limits):
00172 self._canvas.axes.set_xbound(lower=limits[0], upper=limits[1])
00173
00174 def set_ylim(self, limits):
00175 self._canvas.axes.set_ybound(lower=limits[0], upper=limits[1])
00176
00177 def get_xlim(self):
00178 return list(self._canvas.axes.get_xbound())
00179
00180 def get_ylim(self):
00181 return list(self._canvas.axes.get_ybound())