37 from python_qt_binding 
import QT_BINDING
 
   38 from python_qt_binding.QtCore 
import Qt, qVersion, qWarning, Signal
 
   39 from python_qt_binding.QtGui 
import QColor
 
   40 from python_qt_binding.QtWidgets 
import QWidget, QHBoxLayout
 
   44     from .pyqtgraph_data_plot 
import PyQtGraphDataPlot
 
   45 except ImportError 
as e:
 
   46     PyQtGraphDataPlot = 
None 
   49     from .mat_data_plot 
import MatDataPlot
 
   50 except ImportError 
as e:
 
   54     from .qwt_data_plot 
import QwtDataPlot
 
   55 except ImportError 
as e:
 
   69     """A widget for displaying a plot of data 
   71     The DataPlot widget displays a plot, on one of several plotting backends, 
   72     depending on which backend(s) are available at runtime. It currently 
   73     supports PyQtGraph, MatPlot and QwtPlot backends. 
   75     The DataPlot widget manages the plot backend internally, and can save 
   76     and restore the internal state using `save_settings` and `restore_settings` 
   79     Currently, the user MUST call `restore_settings` before using the widget, 
   80     to cause the creation of the enclosed plotting widget. 
   86             'widget_class': PyQtGraphDataPlot,
 
   88                 'Based on PyQtGraph\n- installer: http://luke.campagnola.me/code/pyqtgraph\n',
 
   89             'enabled': PyQtGraphDataPlot 
is not None,
 
   93             'widget_class': MatDataPlot,
 
   95                 'Based on MatPlotLib\n- needs most CPU\n- needs matplotlib >= 1.1.0\n- if using ' 
   96                 'PySide: PySide > 1.1.0\n',
 
   97             'enabled': MatDataPlot 
is not None,
 
  101             'widget_class': QwtDataPlot,
 
  103                 'Based on QwtPlot\n- does not use timestamps\n- uses least CPU\n- needs Python ' 
  105             'enabled': QwtDataPlot 
is not None,
 
  118     _colors = [Qt.blue, Qt.red, Qt.cyan, Qt.magenta, Qt.green,
 
  119                Qt.darkYellow, Qt.black, Qt.darkCyan, Qt.darkRed, Qt.gray]
 
  121     limits_changed = Signal()
 
  123     _add_curve = Signal(str, str, 
'QColor', bool)
 
  126         """Create a new, empty DataPlot 
  128         This will raise a RuntimeError if none of the supported plotting 
  129         backends can be found 
  131         super(DataPlot, self).
__init__(parent)
 
  149         enabled_plot_types = [pt 
for pt 
in self.
plot_types if pt[
'enabled']]
 
  150         if not enabled_plot_types:
 
  151             if qVersion().startswith(
'4.'):
 
  152                 version_info = 
'1.1.0' 
  155                 version_info = 
'1.4.0' 
  156             if QT_BINDING == 
'pyside':
 
  157                 version_info += 
' and PySide %s' % \
 
  158                     (
'> 1.1.0' if qVersion().startswith(
'4.') 
else '>= 2.0.0')
 
  160                 'No usable plot type found. Install at least one of: PyQtGraph, MatPlotLib ' 
  161                 '(at least %s) or Python-Qwt5.' % version_info)
 
  168         """Internal method for activating a plotting backend by index""" 
  170         if not self.
plot_types[plot_index][
'enabled']:
 
  172             for index, plot_type 
in enumerate(self.
plot_types):
 
  173                 if plot_type[
'enabled']:
 
  189             x_limits = [0.0, 10.0]
 
  190             y_limits = [-0.001, 0.001]
 
  223         """get the title of the current plotting backend""" 
  227         """Save the settings associated with this widget 
  229         Currently, this is just the plot type, but may include more useful 
  230         data in the future""" 
  231         instance_settings.set_value(
'plot_type', self.
_plot_index)
 
  236         xlim = [float(x) 
for x 
in xlim]
 
  237         ylim = [float(y) 
for y 
in ylim]
 
  238         instance_settings.set_value(
'x_limits', pack(xlim))
 
  239         instance_settings.set_value(
'y_limits', pack(ylim))
 
  242         """Restore the settings for this widget 
  244         Currently, this just restores the plot type.""" 
  246         xlim = unpack(instance_settings.value(
'x_limits', []))
 
  247         ylim = unpack(instance_settings.value(
'y_limits', []))
 
  252                 xlim = [float(x) 
for x 
in xlim]
 
  255                 qWarning(
"Failed to restore X limits")
 
  258                 ylim = [float(y) 
for y 
in ylim]
 
  261                 qWarning(
"Failed to restore Y limits")
 
  264         """Present the user with a dialog for choosing the plot backend 
  266         This displays a SimpleSettingsDialog asking the user to choose a 
  267         plot type, gets the result, and updates the plot type as necessary 
  269         This method is blocking""" 
  273                 'title': 
'Show Plot Markers',
 
  275                     'Warning: Displaying markers in rqt_plot may cause\n \t high cpu load, ' 
  276                     'especially using PyQtGraph\n',
 
  280             selected_checkboxes = [0]
 
  282             selected_checkboxes = []
 
  285         dialog.add_exclusive_option_group(
 
  287         dialog.add_checkbox_group(
 
  288             title=
'Plot Markers', options=marker_settings, selected_indexes=selected_checkboxes)
 
  289         [plot_type, checkboxes] = dialog.get_settings()
 
  290         if plot_type 
is not None and \
 
  291                 plot_type[
'selected_index'] 
is not None and \
 
  294                 plot_type[
'selected_index'], 0 
in checkboxes[
'selected_indexes'])
 
  296             if checkboxes 
is not None and self.
_markers_on != (0 
in checkboxes[
'selected_indexes']):
 
  302         """Enable or disable autoscrolling of the plot""" 
  309         """Redraw the underlying plot 
  311         This causes the underlying plot to be redrawn. This is usually used 
  312         after adding or updating the plot data""" 
  331     def add_curve(self, curve_id, curve_name, data_x, data_y):
 
  332         """Add a new, named curve to this plot 
  334         Add a curve named `curve_name` to the plot, with initial data series 
  335         `data_x` and `data_y`. 
  337         Future references to this curve should use the provided `curve_id` 
  339         Note that the plot is not redraw automatically; call `redraw()` to make 
  340         any changes visible to the user. 
  345         self.
_curves[curve_id] = {
'x': numpy.array(data_x),
 
  346                                   'y': numpy.array(data_y),
 
  348                                   'color': curve_color}
 
  353         """Remove the specified curve from this plot""" 
  361         """Append new data to an existing curve 
  363         `values_x` and `values_y` will be appended to the existing data for 
  366         Note that the plot is not redraw automatically; call `redraw()` to make 
  367         any changes visible to the user. 
  369         If `sort_data` is set to False, values won't be sorted by `values_x` 
  373         curve[
'x'] = numpy.append(curve[
'x'], values_x)
 
  374         curve[
'y'] = numpy.append(curve[
'y'], values_y)
 
  378             sort_order = curve[
'x'].argsort()
 
  379             curve[
'x'] = curve[
'x'][sort_order]
 
  380             curve[
'y'] = curve[
'y'][sort_order]
 
  383         """Clear the values for the specified curve, or all curves 
  385         This will erase the data series associaed with `curve_id`, or all 
  386         curves if `curve_id` is not present or is None 
  388         Note that the plot is not redraw automatically; call `redraw()` to make 
  389         any changes visible to the user. 
  394             curve[
'x'] = numpy.array([])
 
  395             curve[
'y'] = numpy.array([])
 
  398                 self.
_curves[curve_id][
'x'] = numpy.array([])
 
  399                 self.
_curves[curve_id][
'y'] = numpy.array([])
 
  402         """Draw a vertical line on the plot 
  404         Draw a line a position X, with the given color 
  406         @param x: position of the vertical line to draw 
  407         @param color: optional parameter specifying the color, as tuple of 
  408                       RGB values from 0 to 255 
  416         """Change autoscaling of plot axes 
  418         if a parameter is not passed, the autoscaling setting for that axis is 
  421         @param x: enable or disable autoscaling for X 
  422         @param y: set autoscaling mode for Y 
  446         x_limit = [numpy.inf, -numpy.inf]
 
  450                 if len(curve[
'x']) > 0:
 
  451                     x_limit[0] = min(x_limit[0], curve[
'x'].min())
 
  452                     x_limit[1] = max(x_limit[1], curve[
'x'].max())
 
  456             x_width = x_limit[1] - x_limit[0]
 
  459             x_limit[1] = -numpy.inf
 
  464                 if len(curve[
'x']) > 0:
 
  465                     x_limit[1] = max(x_limit[1], curve[
'x'].max())
 
  468             x_limit[0] = x_limit[1] - x_width
 
  474         if numpy.isinf(x_limit[0]):
 
  476         if numpy.isinf(x_limit[1]):
 
  479         y_limit = [numpy.inf, -numpy.inf]
 
  488                 end_index = len(curve[
'x'])
 
  494                     start_index = curve[
'x'].searchsorted(x_limit[0])
 
  496                     end_index = curve[
'x'].searchsorted(x_limit[1])
 
  500                 region = curve[
'y'][start_index:end_index]
 
  502                     y_limit[0] = min(y_limit[0], region.min())
 
  503                     y_limit[1] = max(y_limit[1], region.max())
 
  521         if numpy.isinf(y_limit[0]):
 
  523         if numpy.isinf(y_limit[1]):
 
  534             qWarning(
"No plot widget; returning default X limits")
 
  542             qWarning(
"No plot widget; can't set X limits")
 
  549             qWarning(
"No plot widget; returning default Y limits")
 
  557             qWarning(
"No plot widget; can't set Y limits")