From 26c24176d636604418913b417f29cc69dd0333d3 Mon Sep 17 00:00:00 2001 From: Jens Hedegaard Nielsen Date: Thu, 26 Jan 2017 17:43:50 +0100 Subject: [PATCH 01/10] Fix: make tuturial use a mockmodel without mp --- docs/examples/toymodel.py | 5 +- qcodes/instrument/mock.py | 104 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 107 insertions(+), 2 deletions(-) diff --git a/docs/examples/toymodel.py b/docs/examples/toymodel.py index fb28c353b4aa..9b3bc6d865e4 100644 --- a/docs/examples/toymodel.py +++ b/docs/examples/toymodel.py @@ -2,11 +2,12 @@ import math -from qcodes import MockInstrument, MockModel, Parameter, Loop, DataArray +from qcodes import MockInstrument, Parameter, Loop, DataArray +from qcodes.instrument.mock import SingleMockModel from qcodes.utils.validators import Numbers from qcodes.instrument.mock import ArrayGetter -class AModel(MockModel): +class AModel(SingleMockModel): def __init__(self): self._gates = [0.0, 0.0, 0.0] self._excitation = 0.1 diff --git a/qcodes/instrument/mock.py b/qcodes/instrument/mock.py index ec100134e6fd..02c41a1315cc 100644 --- a/qcodes/instrument/mock.py +++ b/qcodes/instrument/mock.py @@ -1,6 +1,7 @@ """Mock instruments for testing purposes.""" import time from datetime import datetime +from uuid import uuid4 from .base import Instrument from .parameter import MultiParameter @@ -283,6 +284,109 @@ def _delattr(self, attr): """ self.ask('method_call', 'delattr', attr) + +# Model is purely in service of mock instruments which *are* tested +# so coverage testing this (by running it locally) would be a waste. +class SingleMockModel: # pragma: no cover + + """ + Base class for models to connect to various MockInstruments. + + Args: + name (str): The server name to create for the model. + Default 'Model-{:.7s}' uses the first 7 characters of + the server's uuid. + + for every instrument that connects to this model, create two methods: + - ``_set(param, value)``: set a parameter on the model + - ``_get(param)``: returns the value of a parameter + ``param`` and the set/return values should all be strings + + If ``param`` and/or ``value`` is not recognized, the method should raise + an error. + + """ + + def __init__(self, name='Model-{:.7s}'): + + self.uuid = uuid4().hex + self.name = name.format(self.uuid) + + def handle_cmd(self, cmd): + """ + Handler for all model queries. + + Args: + cmd (str): Can take several forms: + + - ':?': + calls ``self._get()`` and forwards + the return value. + - '::': + calls ``self._set(, )`` + - ':'. + calls ``self._set(, None)`` + + Returns: + Union(str, None): The parameter value, if ``cmd`` has the form + ':?', otherwise no return. + + Raises: + ValueError: if cmd does not match one of the patterns above. + """ + query = cmd.split(':') + + instrument = query[0] + param = query[1] + + if param[-1] == '?' and len(query) == 2: + return getattr(self, instrument + '_get')(param[:-1]) + + elif len(query) <= 3: + value = query[2] if len(query) == 3 else None + getattr(self, instrument + '_set')(param, value) + + else: + raise ValueError() + + def getattr(self, attr, default=_NoDefault): + """ + Get a (possibly nested) attribute of this model on its server. + + See NestedAttrAccess for details. + """ + return self.ask('method_call', 'getattr', attr, default) + + def setattr(self, attr, value): + """ + Set a (possibly nested) attribute of this model on its server. + + See NestedAttrAccess for details. + """ + self.ask('method_call', 'setattr', attr, value) + + def callattr(self, attr, *args, **kwargs): + """ + Call a (possibly nested) method of this model on its server. + + See NestedAttrAccess for details. + """ + return self.ask('method_call', 'callattr', attr, *args, **kwargs) + + def delattr(self, attr): + """ + Delete a (possibly nested) attribute of this model on its server. + + See NestedAttrAccess for details. + """ + self.ask('method_call', 'delattr', attr) + + def ask(self, func_name, *args, **kwargs): + return self.handle_cmd(args[0]) + + def write(self, func_name, *args, **kwargs): + self.handle_cmd(args[0]) + class ArrayGetter(MultiParameter): """ Example parameter that just returns a single array From 7b2514cbf009307038e796206a0b01e21663be88 Mon Sep 17 00:00:00 2001 From: Jens Hedegaard Nielsen Date: Fri, 27 Jan 2017 11:20:44 +0100 Subject: [PATCH 02/10] Fix: expand_trace is a static method --- qcodes/plots/base.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/qcodes/plots/base.py b/qcodes/plots/base.py index 654ed42d8c4d..fb10840e82bf 100644 --- a/qcodes/plots/base.py +++ b/qcodes/plots/base.py @@ -174,7 +174,8 @@ def get_label(self, data_array): return (getattr(data_array, 'label', '') or getattr(data_array, 'name', '')) - def expand_trace(self, args, kwargs): + @staticmethod + def expand_trace(args, kwargs): """ Complete the x, y (and possibly z) data definition for a trace. From 046d2001fe4cbfc7adb29163c807c699501c8e82 Mon Sep 17 00:00:00 2001 From: Jens Hedegaard Nielsen Date: Fri, 27 Jan 2017 11:44:04 +0100 Subject: [PATCH 03/10] Add simple click widget, still very much wip --- qcodes/plots/qcmatplotlib.py | 44 ++++++++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) diff --git a/qcodes/plots/qcmatplotlib.py b/qcodes/plots/qcmatplotlib.py index 135edac3c9e4..9c549b89d9fb 100644 --- a/qcodes/plots/qcmatplotlib.py +++ b/qcodes/plots/qcmatplotlib.py @@ -6,6 +6,8 @@ import matplotlib.pyplot as plt from matplotlib.transforms import Bbox +from matplotlib.widgets import Cursor + import numpy as np from numpy.ma import masked_invalid, getmask @@ -217,3 +219,45 @@ def save(self, filename=None): default = "{}.png".format(self.get_default_title()) filename = filename or default self.fig.savefig(filename) + + +class ClickWidget: + def __init__(self, dataset): + self._data = {} + BasePlot.expand_trace(args=[dataset], kwargs=self._data) + self.fig, self.ax = plt.subplots(2, 2) + self.ax[0, 0].pcolormesh(self._data['x'], + self._data['y'], + self._data['z']) + self._data['xaxis'] = self._data['x'].ndarray[0, :] + self._data['yaxis'] = self._data['y'].ndarray + self.ax[0, 0].set_xlabel("x") + self.ax[0, 0].set_ylabel("y") + self.ax[1, 0].set_xlabel("x") + self.ax[1, 0].set_ylabel("z") + self.ax[1, 0].set_xlim(min(self._data['xaxis']), max(self._data['xaxis'])) + self.ax[1, 0].set_ylim(0, self._data['z'].max() * 1.05) + self.ax[0, 1].set_xlabel("z") + self.ax[0, 1].set_ylabel("y") + self.ax[0, 1].set_ylim(min(self._data['yaxis']), max(self._data['yaxis'])) + self.ax[0, 1].set_xlim(0, self._data['z'].max() * 1.05) + self._xline = None + self._yline = None + self._cursor = Cursor(self.ax[0, 0], useblit=True, color='black') + self.fig.tight_layout() + self.fig.canvas.mpl_connect('button_press_event', self._click) + + def _click(self, event): + + if event.inaxes == self.ax[0, 0]: + xpos = (abs(self._data['xaxis'] - event.xdata)).argmin() + ypos = (abs(self._data['yaxis'] - event.ydata)).argmin() + print("X: {} Y: {}".format(event.xdata, event.ydata)) + print("Clicked on number {},{}".format(xpos, ypos)) + if self._xline: + self._xline[0].remove() + if self._yline: + self._yline[0].remove() + self._yline = self.ax[0, 1].plot(self._data['z'][:, xpos], self._data['yaxis'], color='C0', marker='.') + self._xline = self.ax[1, 0].plot(self._data['xaxis'], self._data['z'][ypos, :], color='C0', marker='.') + self.fig.canvas.draw() \ No newline at end of file From 4272b6c1003ab5390d8621547aa99cf1bbb675f8 Mon Sep 17 00:00:00 2001 From: Jens Hedegaard Nielsen Date: Fri, 27 Jan 2017 15:40:51 +0100 Subject: [PATCH 04/10] Fix add datacursor to viewer gui --- qcodes/plots/qcmatplotlib.py | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/qcodes/plots/qcmatplotlib.py b/qcodes/plots/qcmatplotlib.py index 9c549b89d9fb..7517162c0699 100644 --- a/qcodes/plots/qcmatplotlib.py +++ b/qcodes/plots/qcmatplotlib.py @@ -7,6 +7,8 @@ import matplotlib.pyplot as plt from matplotlib.transforms import Bbox from matplotlib.widgets import Cursor +import mplcursors + import numpy as np from numpy.ma import masked_invalid, getmask @@ -241,8 +243,8 @@ def __init__(self, dataset): self.ax[0, 1].set_ylabel("y") self.ax[0, 1].set_ylim(min(self._data['yaxis']), max(self._data['yaxis'])) self.ax[0, 1].set_xlim(0, self._data['z'].max() * 1.05) - self._xline = None - self._yline = None + self._lines = [] + self._datacursor = [] self._cursor = Cursor(self.ax[0, 0], useblit=True, color='black') self.fig.tight_layout() self.fig.canvas.mpl_connect('button_press_event', self._click) @@ -254,10 +256,12 @@ def _click(self, event): ypos = (abs(self._data['yaxis'] - event.ydata)).argmin() print("X: {} Y: {}".format(event.xdata, event.ydata)) print("Clicked on number {},{}".format(xpos, ypos)) - if self._xline: - self._xline[0].remove() - if self._yline: - self._yline[0].remove() - self._yline = self.ax[0, 1].plot(self._data['z'][:, xpos], self._data['yaxis'], color='C0', marker='.') - self._xline = self.ax[1, 0].plot(self._data['xaxis'], self._data['z'][ypos, :], color='C0', marker='.') + for line in self._lines: + line.remove() + self._lines = [] + if self._datacursor: + self._datacursor.remove() + self._lines.append(self.ax[0, 1].plot(self._data['z'][:, xpos], self._data['yaxis'], color='C0', marker='.')[0]) + self._lines.append(self.ax[1, 0].plot(self._data['xaxis'], self._data['z'][ypos, :], color='C0', marker='.')[0]) + self._datacursor = mplcursors.cursor(self._lines, multiple=False) self.fig.canvas.draw() \ No newline at end of file From e952d8970a3ee7234e116c0c8b4531c720781800 Mon Sep 17 00:00:00 2001 From: Jens Hedegaard Nielsen Date: Mon, 30 Jan 2017 10:30:08 +0100 Subject: [PATCH 05/10] fix: make get_label static --- qcodes/plots/base.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/qcodes/plots/base.py b/qcodes/plots/base.py index fb10840e82bf..b326f79b7f0b 100644 --- a/qcodes/plots/base.py +++ b/qcodes/plots/base.py @@ -159,7 +159,8 @@ def get_default_title(self): title_parts.append(location) return ', '.join(title_parts) - def get_label(self, data_array): + @staticmethod + def get_label(data_array): """ Look for a label in data_array falling back on name. From bc8ecd705c994f76e9f4e76d45d87612eedbc925 Mon Sep 17 00:00:00 2001 From: Jens Hedegaard Nielsen Date: Mon, 30 Jan 2017 11:11:22 +0100 Subject: [PATCH 06/10] Fix: Clickwidget read labels from dataset --- qcodes/plots/qcmatplotlib.py | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/qcodes/plots/qcmatplotlib.py b/qcodes/plots/qcmatplotlib.py index 7517162c0699..ebf6a30752b8 100644 --- a/qcodes/plots/qcmatplotlib.py +++ b/qcodes/plots/qcmatplotlib.py @@ -227,20 +227,24 @@ class ClickWidget: def __init__(self, dataset): self._data = {} BasePlot.expand_trace(args=[dataset], kwargs=self._data) + xlabel = BasePlot.get_label(self._data['x']) + ylabel = BasePlot.get_label(self._data['y']) + zlabel = BasePlot.get_label(self._data['z']) self.fig, self.ax = plt.subplots(2, 2) self.ax[0, 0].pcolormesh(self._data['x'], self._data['y'], self._data['z']) self._data['xaxis'] = self._data['x'].ndarray[0, :] self._data['yaxis'] = self._data['y'].ndarray - self.ax[0, 0].set_xlabel("x") - self.ax[0, 0].set_ylabel("y") - self.ax[1, 0].set_xlabel("x") - self.ax[1, 0].set_ylabel("z") + + self.ax[0, 0].set_xlabel(xlabel) + self.ax[0, 0].set_ylabel(ylabel) + self.ax[1, 0].set_xlabel(xlabel) + self.ax[1, 0].set_ylabel(zlabel) self.ax[1, 0].set_xlim(min(self._data['xaxis']), max(self._data['xaxis'])) self.ax[1, 0].set_ylim(0, self._data['z'].max() * 1.05) - self.ax[0, 1].set_xlabel("z") - self.ax[0, 1].set_ylabel("y") + self.ax[0, 1].set_xlabel(zlabel) + self.ax[0, 1].set_ylabel(ylabel) self.ax[0, 1].set_ylim(min(self._data['yaxis']), max(self._data['yaxis'])) self.ax[0, 1].set_xlim(0, self._data['z'].max() * 1.05) self._lines = [] From 024bf55bbdf55b75a2250f394a65f442234fb1a9 Mon Sep 17 00:00:00 2001 From: Jens Hedegaard Nielsen Date: Fri, 3 Feb 2017 14:15:28 +0100 Subject: [PATCH 07/10] Fix: more advanced widget --- qcodes/plots/qcmatplotlib.py | 138 ++++++++++++++++++++++++++++------- 1 file changed, 110 insertions(+), 28 deletions(-) diff --git a/qcodes/plots/qcmatplotlib.py b/qcodes/plots/qcmatplotlib.py index ebf6a30752b8..863f9b119acd 100644 --- a/qcodes/plots/qcmatplotlib.py +++ b/qcodes/plots/qcmatplotlib.py @@ -4,6 +4,8 @@ """ from collections import Mapping +from qtpy import QtWidgets + import matplotlib.pyplot as plt from matplotlib.transforms import Bbox from matplotlib.widgets import Cursor @@ -227,45 +229,125 @@ class ClickWidget: def __init__(self, dataset): self._data = {} BasePlot.expand_trace(args=[dataset], kwargs=self._data) - xlabel = BasePlot.get_label(self._data['x']) - ylabel = BasePlot.get_label(self._data['y']) - zlabel = BasePlot.get_label(self._data['z']) - self.fig, self.ax = plt.subplots(2, 2) - self.ax[0, 0].pcolormesh(self._data['x'], - self._data['y'], - self._data['z']) + self._data['xlabel'] = BasePlot.get_label(self._data['x']) + self._data['ylabel'] = BasePlot.get_label(self._data['y']) + self._data['zlabel'] = BasePlot.get_label(self._data['z']) self._data['xaxis'] = self._data['x'].ndarray[0, :] self._data['yaxis'] = self._data['y'].ndarray - self.ax[0, 0].set_xlabel(xlabel) - self.ax[0, 0].set_ylabel(ylabel) - self.ax[1, 0].set_xlabel(xlabel) - self.ax[1, 0].set_ylabel(zlabel) - self.ax[1, 0].set_xlim(min(self._data['xaxis']), max(self._data['xaxis'])) - self.ax[1, 0].set_ylim(0, self._data['z'].max() * 1.05) - self.ax[0, 1].set_xlabel(zlabel) - self.ax[0, 1].set_ylabel(ylabel) - self.ax[0, 1].set_ylim(min(self._data['yaxis']), max(self._data['yaxis'])) - self.ax[0, 1].set_xlim(0, self._data['z'].max() * 1.05) + self.fig = plt.figure() + self._lines = [] self._datacursor = [] - self._cursor = Cursor(self.ax[0, 0], useblit=True, color='black') - self.fig.tight_layout() - self.fig.canvas.mpl_connect('button_press_event', self._click) + self._cid = 0 + + hbox = QtWidgets.QHBoxLayout() + self.fig.canvas.setLayout(hbox) + hspace = QtWidgets.QSpacerItem(0, + 0, + QtWidgets.QSizePolicy.Expanding, + QtWidgets.QSizePolicy.Expanding) + vspace = QtWidgets.QSpacerItem(0, + 0, + QtWidgets.QSizePolicy.Minimum, + QtWidgets.QSizePolicy.Expanding) + hbox.addItem(hspace) + + vbox = QtWidgets.QVBoxLayout() + self.crossbtn = QtWidgets.QCheckBox('Cross') + self.sumbtn = QtWidgets.QCheckBox('Show Sum') + + self.crossbtn.toggled.connect(self.toggle_cross) + self.sumbtn.toggled.connect(self.toggle_sum) + self.toggle_cross() + self.toggle_sum() + + vbox.addItem(vspace) + vbox.addWidget(self.crossbtn) + vbox.addWidget(self.sumbtn) + + hbox.addLayout(vbox) + self.fig.tight_layout(rect=(0, 0, 0.9, 1)) + + def toggle_cross(self): + self.remove_plots() + self.fig.clear() + if self._cid: + self.fig.canvas.mpl_disconnect(self._cid) + if self.crossbtn.isChecked(): + self.ax = np.empty((2, 2), dtype='O') + self.ax[0, 0] = self.fig.add_subplot(2, 2, 1) + self.ax[0, 1] = self.fig.add_subplot(2, 2, 2) + self.ax[1, 0] = self.fig.add_subplot(2, 2, 3) + print("Axis") + self._cid = self.fig.canvas.mpl_connect('button_press_event', self._click) + self._cursor = Cursor(self.ax[0, 0], useblit=True, color='black') + self.toggle_sum() + else: + self.ax = np.empty((1, 1), dtype='O') + self.ax[0, 0] = self.fig.add_subplot(1, 1, 1) + self.ax[0, 0].pcolormesh(self._data['x'], + self._data['y'], + self._data['z']) + self.ax[0, 0].set_xlabel(self._data['xlabel']) + self.ax[0, 0].set_ylabel(self._data['ylabel']) + self.fig.tight_layout(rect=(0, 0.07, 0.9, 1)) + self.fig.canvas.draw_idle() + + def toggle_sum(self): + self.remove_plots() + if not self.crossbtn.isChecked(): + return + if self.sumbtn.isChecked(): + self._cursor.set_active(False) + self.ax[1, 0].set_ylim(0, self._data['z'].sum(axis=0).max() * 1.05) + self.ax[0, 1].set_xlim(0, self._data['z'].sum(axis=1).max() * 1.05) + self.ax[1, 0].set_xlabel(self._data['xlabel']) + self.ax[1, 0].set_ylabel("sum of " + self._data['zlabel']) + self.ax[0, 1].set_xlabel("sum of " + self._data['zlabel']) + self.ax[0, 1].set_ylabel(self._data['ylabel']) + self._lines.append(self.ax[0, 1].plot(self._data['z'].sum(axis=1), + self._data['yaxis'], + color='C0', + marker='.')[0]) + self._lines.append(self.ax[1, 0].plot(self._data['xaxis'], + self._data['z'].sum(axis=0), + color='C0', + marker='.')[0]) + self._datacursor = mplcursors.cursor(self._lines, multiple=False) + else: + self._cursor.set_active(True) + self.ax[1, 0].set_xlabel(self._data['xlabel']) + self.ax[1, 0].set_ylabel(self._data['zlabel']) + self.ax[0, 1].set_xlabel(self._data['zlabel']) + self.ax[0, 1].set_ylabel(self._data['ylabel']) + self.ax[1, 0].set_ylim(0, self._data['z'].max() * 1.05) + self.ax[0, 1].set_xlim(0, self._data['z'].max() * 1.05) + self.fig.canvas.draw_idle() + + def remove_plots(self): + for line in self._lines: + line.remove() + self._lines = [] + if self._datacursor: + self._datacursor.remove() def _click(self, event): - if event.inaxes == self.ax[0, 0]: + if event.inaxes == self.ax[0, 0] and not self.sumbtn.isChecked(): xpos = (abs(self._data['xaxis'] - event.xdata)).argmin() ypos = (abs(self._data['yaxis'] - event.ydata)).argmin() print("X: {} Y: {}".format(event.xdata, event.ydata)) print("Clicked on number {},{}".format(xpos, ypos)) - for line in self._lines: - line.remove() - self._lines = [] - if self._datacursor: - self._datacursor.remove() - self._lines.append(self.ax[0, 1].plot(self._data['z'][:, xpos], self._data['yaxis'], color='C0', marker='.')[0]) - self._lines.append(self.ax[1, 0].plot(self._data['xaxis'], self._data['z'][ypos, :], color='C0', marker='.')[0]) + self.remove_plots() + + self._lines.append(self.ax[0, 1].plot(self._data['z'][:, xpos], + self._data['yaxis'], + color='C0', + marker='.')[0]) + self._lines.append(self.ax[1, 0].plot(self._data['xaxis'], + self._data['z'][ypos, :], + color='C0', + marker='.')[0]) self._datacursor = mplcursors.cursor(self._lines, multiple=False) self.fig.canvas.draw() \ No newline at end of file From 42c8323d0254d4867e99f8394f78cb555da52654 Mon Sep 17 00:00:00 2001 From: Jens Hedegaard Nielsen Date: Fri, 3 Feb 2017 14:24:01 +0100 Subject: [PATCH 08/10] Disable sum button when cross sections are disabled --- qcodes/plots/qcmatplotlib.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/qcodes/plots/qcmatplotlib.py b/qcodes/plots/qcmatplotlib.py index 863f9b119acd..5cf7660f549a 100644 --- a/qcodes/plots/qcmatplotlib.py +++ b/qcodes/plots/qcmatplotlib.py @@ -275,6 +275,7 @@ def toggle_cross(self): if self._cid: self.fig.canvas.mpl_disconnect(self._cid) if self.crossbtn.isChecked(): + self.sumbtn.setEnabled(True) self.ax = np.empty((2, 2), dtype='O') self.ax[0, 0] = self.fig.add_subplot(2, 2, 1) self.ax[0, 1] = self.fig.add_subplot(2, 2, 2) @@ -284,6 +285,7 @@ def toggle_cross(self): self._cursor = Cursor(self.ax[0, 0], useblit=True, color='black') self.toggle_sum() else: + self.sumbtn.setEnabled(False) self.ax = np.empty((1, 1), dtype='O') self.ax[0, 0] = self.fig.add_subplot(1, 1, 1) self.ax[0, 0].pcolormesh(self._data['x'], From 0e951e4fc592d373114ed49ce04e2c8c99ae5d57 Mon Sep 17 00:00:00 2001 From: Jens Hedegaard Nielsen Date: Fri, 3 Feb 2017 14:58:02 +0100 Subject: [PATCH 09/10] Add titles to plots --- qcodes/plots/qcmatplotlib.py | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/qcodes/plots/qcmatplotlib.py b/qcodes/plots/qcmatplotlib.py index 5cf7660f549a..0b86ae5ad5f5 100644 --- a/qcodes/plots/qcmatplotlib.py +++ b/qcodes/plots/qcmatplotlib.py @@ -254,8 +254,11 @@ def __init__(self, dataset): hbox.addItem(hspace) vbox = QtWidgets.QVBoxLayout() - self.crossbtn = QtWidgets.QCheckBox('Cross') - self.sumbtn = QtWidgets.QCheckBox('Show Sum') + self.crossbtn = QtWidgets.QCheckBox('Cross section') + self.crossbtn.setToolTip("Display extra subplots with selectable cross sections " + "or sums along axis.") + self.sumbtn = QtWidgets.QCheckBox('Sum') + self.sumbtn.setToolTip("Display sums or cross sections.") self.crossbtn.toggled.connect(self.toggle_cross) self.sumbtn.toggled.connect(self.toggle_sum) @@ -267,7 +270,6 @@ def __init__(self, dataset): vbox.addWidget(self.sumbtn) hbox.addLayout(vbox) - self.fig.tight_layout(rect=(0, 0, 0.9, 1)) def toggle_cross(self): self.remove_plots() @@ -280,7 +282,6 @@ def toggle_cross(self): self.ax[0, 0] = self.fig.add_subplot(2, 2, 1) self.ax[0, 1] = self.fig.add_subplot(2, 2, 2) self.ax[1, 0] = self.fig.add_subplot(2, 2, 3) - print("Axis") self._cid = self.fig.canvas.mpl_connect('button_press_event', self._click) self._cursor = Cursor(self.ax[0, 0], useblit=True, color='black') self.toggle_sum() @@ -312,10 +313,12 @@ def toggle_sum(self): self._data['yaxis'], color='C0', marker='.')[0]) + self.ax[0, 1].set_title("") self._lines.append(self.ax[1, 0].plot(self._data['xaxis'], self._data['z'].sum(axis=0), color='C0', marker='.')[0]) + self.ax[1, 0].set_title("") self._datacursor = mplcursors.cursor(self._lines, multiple=False) else: self._cursor.set_active(True) @@ -339,17 +342,19 @@ def _click(self, event): if event.inaxes == self.ax[0, 0] and not self.sumbtn.isChecked(): xpos = (abs(self._data['xaxis'] - event.xdata)).argmin() ypos = (abs(self._data['yaxis'] - event.ydata)).argmin() - print("X: {} Y: {}".format(event.xdata, event.ydata)) - print("Clicked on number {},{}".format(xpos, ypos)) self.remove_plots() self._lines.append(self.ax[0, 1].plot(self._data['z'][:, xpos], self._data['yaxis'], color='C0', marker='.')[0]) + self.ax[0,1].set_title("{} = {} ".format(self._data['xlabel'], self._data['xaxis'][xpos]), + fontsize='small') self._lines.append(self.ax[1, 0].plot(self._data['xaxis'], self._data['z'][ypos, :], color='C0', marker='.')[0]) + self.ax[1, 0].set_title("{} = {} ".format(self._data['ylabel'], self._data['yaxis'][ypos]), + fontsize='small') self._datacursor = mplcursors.cursor(self._lines, multiple=False) self.fig.canvas.draw() \ No newline at end of file From 39e16f7d6991b12343ff9c4174ead92361cdbb7c Mon Sep 17 00:00:00 2001 From: Jens Hedegaard Nielsen Date: Fri, 3 Feb 2017 15:36:26 +0100 Subject: [PATCH 10/10] Needs mplcursors too --- requirements.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/requirements.txt b/requirements.txt index 8094b2e926d8..5efdc93dcf6b 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,6 +1,7 @@ jupyter==1.0.0 numpy==1.11.2 matplotlib==1.5.3 +mplcursors==0.1 pyqtgraph==0.10.0 PyVISA==1.8 PyQt5==5.7.1