From cc249c919cafaf0b1cc5fdacd75b6e7e03f2ccfb Mon Sep 17 00:00:00 2001 From: giulio ungaretti Date: Mon, 16 Jan 2017 11:27:16 +0100 Subject: [PATCH 01/14] feature: Add wrappers this covers some of the request made years ago. Because of the design of many pieces of qcodes the code is really hacky and anti-cool. --- qcodes/__init__.py | 1 + qcodes/data/io.py | 1 - qcodes/data/location.py | 6 +- qcodes/tests/instrument_mocks.py | 2 +- qcodes/utils/wrappers.py | 235 +++++++++++++++++++++++++++++++ 5 files changed, 241 insertions(+), 4 deletions(-) create mode 100644 qcodes/utils/wrappers.py diff --git a/qcodes/__init__.py b/qcodes/__init__.py index 859bcaf45dd3..307d1ac7b1de 100644 --- a/qcodes/__init__.py +++ b/qcodes/__init__.py @@ -34,6 +34,7 @@ 'try "from qcodes.plots.pyqtgraph import QtPlot" ' 'to see the full error') +from qcodes.utils.wrappers import do1d, do2d, do1dDiagonal, show_num, init # only import in name space if the gui is set to noebook # and there is multiprocessing if config['gui']['notebook'] and config['core']['legacy_mp']: diff --git a/qcodes/data/io.py b/qcodes/data/io.py index 4b7a82c8588b..4b2fd45381c3 100644 --- a/qcodes/data/io.py +++ b/qcodes/data/io.py @@ -91,7 +91,6 @@ def open(self, filename, mode, encoding=None): raise ValueError('mode {} not allowed in IO managers'.format(mode)) filepath = self.to_path(filename) - # make directories if needed dirpath = os.path.dirname(filepath) if not os.path.exists(dirpath): diff --git a/qcodes/data/location.py b/qcodes/data/location.py index 91af8594cf1d..b342b0bfbf0b 100644 --- a/qcodes/data/location.py +++ b/qcodes/data/location.py @@ -85,6 +85,7 @@ class FormatLocation: default_fmt = config['core']['default_fmt'] + def __init__(self, fmt=None, fmt_date=None, fmt_time=None, fmt_counter=None, record=None): #TODO(giulioungaretti) this should be @@ -95,7 +96,7 @@ def __init__(self, fmt=None, fmt_date=None, fmt_time=None, self.fmt_counter = fmt_counter or '{:03}' self.base_record = record self.formatter = SafeFormatter() - + self.counter = 0 for testval in (1, 23, 456, 7890): if self._findint(self.fmt_counter.format(testval)) != testval: raise ValueError('fmt_counter must produce a correct integer ' @@ -163,7 +164,8 @@ def __call__(self, io, record=None): cnt = self._findint(f[len(head):]) existing_count = max(existing_count, cnt) - format_record['counter'] = self.fmt_counter.format(existing_count + 1) + self.counter = existing_count +1 + format_record['counter'] = self.fmt_counter.format(self.counter) location = self.formatter.format(loc_fmt, **format_record) return location diff --git a/qcodes/tests/instrument_mocks.py b/qcodes/tests/instrument_mocks.py index 3163d2e95b65..255eb7e0df3b 100644 --- a/qcodes/tests/instrument_mocks.py +++ b/qcodes/tests/instrument_mocks.py @@ -297,7 +297,7 @@ def __init__(self, name='dummy', gates=['dac1', 'dac2', 'dac3'], **kwargs): self.add_parameter(g, parameter_class=ManualParameter, initial_value=0, - label='Gate {} (arb. units)'.format(g), + label='Gate {} (arbUnit)'.format(g), vals=Numbers(-800, 400)) diff --git a/qcodes/utils/wrappers.py b/qcodes/utils/wrappers.py new file mode 100644 index 000000000000..49e68501079f --- /dev/null +++ b/qcodes/utils/wrappers.py @@ -0,0 +1,235 @@ +import qcodes as qc +from os.path import abspath +from os.path import sep +from os import makedirs +import logging +from qcodes.plots.pyqtgraph import QtPlot +from IPython import get_ipython +CURRENT_EXPERIMENT = {} + +def init(mainfolder:str, sample_name: str): + """ + + Args: + mainfolder: base loacation for the data + sample_name: name of the sample + + """ + if sep in sample_name: + raise TypeError("Use Relative names. That is wihtout {}".format(sep)) + # always remove trailing sep in the main folder + if mainfolder[-1] == sep: + mainfolder = mainfolder[:-1] + + mainfolder = abspath(mainfolder) + + CURRENT_EXPERIMENT["mainfolder"] = mainfolder + CURRENT_EXPERIMENT["subfolder"] = sample_name + CURRENT_EXPERIMENT['init'] = True + + path_to_experiment_folder = sep.join([mainfolder, sample_name, ""]) + CURRENT_EXPERIMENT["exp_folder"] = path_to_experiment_folder + + + try: + makedirs(path_to_experiment_folder) + except FileExistsError: + pass + + logging.info("experiment started at {}".format(path_to_experiment_folder)) + + + loc_provider = qc.FormatLocation( + fmt= path_to_experiment_folder + '{counter}') + qc.data.data_set.DataSet.location_provider = loc_provider + CURRENT_EXPERIMENT["provider"] = loc_provider + + ipython = get_ipython() + # turn on logging only if in ipython + # else crash and burn + if ipython is None: + raise RuntimeWarning("History can't be saved refusing to proceed (use IPython/jupyter)") + else: + logfile = "{}{}".format(path_to_experiment_folder, "commands.log") + logging.debug("Logging commands to: t{}".format(logfile)) + ipython.magic("%logstart -t {} {}".format(logfile, "append")) + +def do1d(inst_set, start, stop, division, delay, *inst_meas): + """ + + Args: + inst_set: Instrument to sweep over + start: Start of sweep + stop: End of sweep + division: Spacing between values + delay: Delay at every step + *inst_meas: any number of instrument to measure + + Returns: + plot, data : returns the plot and the dataset + + """ + loop = qc.Loop(inst_set.sweep(start, stop, division), delay).each(*inst_meas) + data = loop.get_data_set() + title = "#{0:03d}".format(data.location_provider.counter) + plot = QtPlot() + + for j, i in enumerate(inst_meas): + if getattr(i, "names", False): + # deal with multi dimenstional parameter + for k, name in enumerate(i.names): + inst_meas_name = "{}_{}".format(i._instrument.name, name) + plot.add(getattr(data, inst_meas_name), subplot=j + k + 1) + plot.subplots[j+k].showGrid(True, True) + if j == 0: + plot.subplots[0].setTitle(title) + else: + plot.subplots[j+k].setTitle("") + else: + # simple_parameters + inst_meas_name = "{}_{}".format(i._instrument.name, i.name) + plot.add(getattr(data, inst_meas_name), subplot=j + 1) + plot.subplots[j].showGrid(True, True) + if j == 0: + plot.subplots[0].setTitle(title) + else: + plot.subplots[j].setTitle("") + try: + _ = loop.with_bg_task(plot.update, plot.save).run() + except KeyboardInterrupt: + print("Measurement Interrupted") + return plot, data + + +def do1dDiagonal(inst_set, inst2_set, start, stop, division, delay, start2, slope, *inst_meas): + """ + Perform diagonal sweep in 1 dimension, given two insturments + + Args: + inst_set: Instrument to sweep over + inst2_set: Second instrument to sweep over + start: Start of sweep + stop: End of sweep + division: Spacing between values + delay: Delay at every step + start2: Second start point + slope: slope of the diagonal cut + *inst_meas: any number of instrument to measure + + Returns: + plot, data : returns the plot and the dataset + + """ + loop = qc.Loop(inst_set.sweep(start, stop, division), delay).each( + qc.Task(inst2_set, (inst_set) * slope + (slope * start - start2)), *inst_meas, inst2_set) + data = loop.get_data_set() + title = "#{0:03d}".format(data.location_provider.counter) + plot = QtPlot() + for j, i in enumerate(inst_meas): + if getattr(i, "names", False): + # deal with multi dimenstional parameter + for k, name in enumerate(i.names): + inst_meas_name = "{}_{}".format(i._instrument.name, name) + plot.add(getattr(data, inst_meas_name), subplot=j + k + 1) + plot.subplots[j+k].showGrid(True, True) + if j == 0: + plot.subplots[0].setTitle(title) + else: + plot.subplots[j+k].setTitle("") + else: + inst_meas_name = "{}_{}".format(i._instrument.name, i.name) + plot.add(getattr(data, inst_meas_name), subplot=j + 1 ) + plot.subplots[j].showGrid(True, True) + if j == 0: + plot.subplots[0].setTitle(title) + else: + plot.subplots[j].setTitle("") + try: + _ = loop.with_bg_task(plot.update, plot.save).run() + except KeyboardInterrupt: + print("Measurement Interrupted") + return data + + +def do2d(inst_set, start, stop, division, delay, inst_set2, start2, stop2, division2, delay2, *inst_meas): + """ + + Args: + inst_set: Instrument to sweep over + start: Start of sweep + stop: End of sweep + division: Spacing between values + delay: Delay at every step + inst_set_2: Second instrument to sweep over + start_2: Start of sweep for second intrument + stop_2: End of sweep for second intrument + division_2: Spacing between values for second intrument + delay_2: Delay at every step for second intrument + *inst_meas: + + Returns: + plot, data : returns the plot and the dataset + + """ + for inst in inst_meas: + if getattr(inst, "setpoints", False): + raise ValueError("3d plotting is not supported") + + loop = qc.Loop(inst_set.sweep(start, stop, division), delay).loop(inst_set2.sweep(start2,stop2,division2), delay2).each( + *inst_meas) + data = loop.get_data_set() + title = "#{0:03d}".format(data.location_provider.counter) + plot = QtPlot() + for j, i in enumerate(inst_meas): + if getattr(i, "names", False): + # deal with multi dimenstional parameter + for k, name in enumerate(i.names): + inst_meas_name = "{}_{}".format(i._instrument.name, name) + plot.add(getattr(data, inst_meas_name), subplot=j + k + 1) + plot.subplots[j+k].showGrid(True, True) + if j == 0: + plot.subplots[0].setTitle(title) + else: + plot.subplots[j+k].setTitle("") + else: + inst_meas_name = "{}_{}".format(i._instrument.name, i.name) + plot.add(getattr(data, inst_meas_name), subplot=j + 1) + plot.subplots[j].showGrid(True, True) + if j == 0: + plot.subplots[0].setTitle(title) + else: + plot.subplots[j].setTitle("") + try: + _ = loop.with_bg_task(plot.update, plot.save).run() + except KeyboardInterrupt: + print("Measurement Interrupted") + return plot, data + + +def show_num(id): + """ + Show and return plot and data for id in current instrument. + Args: + id(number): id of intrumetn + + Returns: + plot, data : returns the plot and the dataset + + """ + if not getattr(CURRENT_EXPERIMENT, "init", True): + raise RuntimeError("Experiment not initalized. use qc.Init(mainfolder, samplename)") + + str_id = '{0:03d}'.format(id) + + t = qc.DataSet.location_provider.fmt.format(counter=str_id) + data = qc.load_data(t) + + plots = [] + for value in data.arrays.keys(): + if "set" not in value: + plot = QtPlot(getattr(data, value)) + title = "#{}".format(str_id) + plot.subplots[0].setTitle(title) + plot.subplots[0].showGrid(True, True) + plots.append(plot) + return data, plots From 5a0d03ea9a07f4909756cb3989666e39328417b1 Mon Sep 17 00:00:00 2001 From: Giulio Ungaretti Date: Mon, 20 Feb 2017 16:16:07 +0100 Subject: [PATCH 02/14] Clean up wrappers --- qcodes/utils/wrappers.py | 98 ++++++++++++++-------------------------- 1 file changed, 33 insertions(+), 65 deletions(-) diff --git a/qcodes/utils/wrappers.py b/qcodes/utils/wrappers.py index 49e68501079f..3d33ac849396 100644 --- a/qcodes/utils/wrappers.py +++ b/qcodes/utils/wrappers.py @@ -6,6 +6,7 @@ from qcodes.plots.pyqtgraph import QtPlot from IPython import get_ipython CURRENT_EXPERIMENT = {} +CURRENT_EXPERIMENT["logging_enabled"] = False def init(mainfolder:str, sample_name: str): """ @@ -24,7 +25,7 @@ def init(mainfolder:str, sample_name: str): mainfolder = abspath(mainfolder) CURRENT_EXPERIMENT["mainfolder"] = mainfolder - CURRENT_EXPERIMENT["subfolder"] = sample_name + CURRENT_EXPERIMENT["sample_name"] = sample_name CURRENT_EXPERIMENT['init'] = True path_to_experiment_folder = sep.join([mainfolder, sample_name, ""]) @@ -38,7 +39,6 @@ def init(mainfolder:str, sample_name: str): logging.info("experiment started at {}".format(path_to_experiment_folder)) - loc_provider = qc.FormatLocation( fmt= path_to_experiment_folder + '{counter}') qc.data.data_set.DataSet.location_provider = loc_provider @@ -51,29 +51,17 @@ def init(mainfolder:str, sample_name: str): raise RuntimeWarning("History can't be saved refusing to proceed (use IPython/jupyter)") else: logfile = "{}{}".format(path_to_experiment_folder, "commands.log") - logging.debug("Logging commands to: t{}".format(logfile)) - ipython.magic("%logstart -t {} {}".format(logfile, "append")) - -def do1d(inst_set, start, stop, division, delay, *inst_meas): - """ - - Args: - inst_set: Instrument to sweep over - start: Start of sweep - stop: End of sweep - division: Spacing between values - delay: Delay at every step - *inst_meas: any number of instrument to measure + if not CURRENT_EXPERIMENT["logging_enabled"]: + logging.debug("Logging commands to: t{}".format(logfile)) + ipython.magic("%logstart -t {} {}".format(logfile, "append")) + CURRENT_EXPERIMENT["logging_enabled"] = True + else: + logging.debug("Logging already started at {}".format(logfile)) - Returns: - plot, data : returns the plot and the dataset - """ - loop = qc.Loop(inst_set.sweep(start, stop, division), delay).each(*inst_meas) - data = loop.get_data_set() - title = "#{0:03d}".format(data.location_provider.counter) +def _plot_setup(data, inst_meas): + title = "{} #{:03d}".format(CURRENT_EXPERIMENT["sample_name"], data.location_provider.counter) plot = QtPlot() - for j, i in enumerate(inst_meas): if getattr(i, "names", False): # deal with multi dimenstional parameter @@ -94,6 +82,26 @@ def do1d(inst_set, start, stop, division, delay, *inst_meas): plot.subplots[0].setTitle(title) else: plot.subplots[j].setTitle("") + return plot + +def do1d(inst_set, start, stop, division, delay, *inst_meas): + """ + + Args: + inst_set: Instrument to sweep over + start: Start of sweep + stop: End of sweep + division: Spacing between values + delay: Delay at every step + *inst_meas: any number of instrument to measure + + Returns: + plot, data : returns the plot and the dataset + + """ + loop = qc.Loop(inst_set.sweep(start, stop, division), delay).each(*inst_meas) + data = loop.get_data_set() + plot = _plot_setup(data, inst_meas) try: _ = loop.with_bg_task(plot.update, plot.save).run() except KeyboardInterrupt: @@ -123,27 +131,7 @@ def do1dDiagonal(inst_set, inst2_set, start, stop, division, delay, start2, slop loop = qc.Loop(inst_set.sweep(start, stop, division), delay).each( qc.Task(inst2_set, (inst_set) * slope + (slope * start - start2)), *inst_meas, inst2_set) data = loop.get_data_set() - title = "#{0:03d}".format(data.location_provider.counter) - plot = QtPlot() - for j, i in enumerate(inst_meas): - if getattr(i, "names", False): - # deal with multi dimenstional parameter - for k, name in enumerate(i.names): - inst_meas_name = "{}_{}".format(i._instrument.name, name) - plot.add(getattr(data, inst_meas_name), subplot=j + k + 1) - plot.subplots[j+k].showGrid(True, True) - if j == 0: - plot.subplots[0].setTitle(title) - else: - plot.subplots[j+k].setTitle("") - else: - inst_meas_name = "{}_{}".format(i._instrument.name, i.name) - plot.add(getattr(data, inst_meas_name), subplot=j + 1 ) - plot.subplots[j].showGrid(True, True) - if j == 0: - plot.subplots[0].setTitle(title) - else: - plot.subplots[j].setTitle("") + plot = _plot_setup(data, inst_meas) try: _ = loop.with_bg_task(plot.update, plot.save).run() except KeyboardInterrupt: @@ -178,27 +166,7 @@ def do2d(inst_set, start, stop, division, delay, inst_set2, start2, stop2, divis loop = qc.Loop(inst_set.sweep(start, stop, division), delay).loop(inst_set2.sweep(start2,stop2,division2), delay2).each( *inst_meas) data = loop.get_data_set() - title = "#{0:03d}".format(data.location_provider.counter) - plot = QtPlot() - for j, i in enumerate(inst_meas): - if getattr(i, "names", False): - # deal with multi dimenstional parameter - for k, name in enumerate(i.names): - inst_meas_name = "{}_{}".format(i._instrument.name, name) - plot.add(getattr(data, inst_meas_name), subplot=j + k + 1) - plot.subplots[j+k].showGrid(True, True) - if j == 0: - plot.subplots[0].setTitle(title) - else: - plot.subplots[j+k].setTitle("") - else: - inst_meas_name = "{}_{}".format(i._instrument.name, i.name) - plot.add(getattr(data, inst_meas_name), subplot=j + 1) - plot.subplots[j].showGrid(True, True) - if j == 0: - plot.subplots[0].setTitle(title) - else: - plot.subplots[j].setTitle("") + plot = _plot_setup(data, inst_meas) try: _ = loop.with_bg_task(plot.update, plot.save).run() except KeyboardInterrupt: @@ -228,7 +196,7 @@ def show_num(id): for value in data.arrays.keys(): if "set" not in value: plot = QtPlot(getattr(data, value)) - title = "#{}".format(str_id) + title = "{} #{}".format(CURRENT_EXPERIMENT["sample_name"], str_id) plot.subplots[0].setTitle(title) plot.subplots[0].showGrid(True, True) plots.append(plot) From 9cc03329e0dd952f9e5fef3ad76574fe7c07f072 Mon Sep 17 00:00:00 2001 From: Jens Hedegaard Nielsen Date: Tue, 14 Mar 2017 16:51:15 +0100 Subject: [PATCH 03/14] Fix: set default matplotlib colormap to hot to match pyqtgraph --- qcodes/plots/qcmatplotlib.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/qcodes/plots/qcmatplotlib.py b/qcodes/plots/qcmatplotlib.py index 7f0aa1fb06f3..711644e77eba 100644 --- a/qcodes/plots/qcmatplotlib.py +++ b/qcodes/plots/qcmatplotlib.py @@ -6,6 +6,7 @@ import matplotlib.pyplot as plt from matplotlib.transforms import Bbox +from matplotlib import cm import numpy as np from numpy.ma import masked_invalid, getmask @@ -226,6 +227,8 @@ def _draw_pcolormesh(self, ax, z, x=None, y=None, subplot=1, # if any entire array is masked, don't draw at all # there's nothing to draw, and anyway it throws a warning return False + if 'cmap' not in kwargs: + kwargs['cmap'] = cm.hot pc = ax.pcolormesh(*args, **kwargs) if getattr(ax, 'qcodes_colorbar', None): From 8268412f9ea5b3dfe2f19c6f5a0b9c236c0a3a96 Mon Sep 17 00:00:00 2001 From: Jens Hedegaard Nielsen Date: Tue, 14 Mar 2017 16:57:18 +0100 Subject: [PATCH 04/14] Fix: improve quality of saved pdf images in matplotlib by drawing edges --- qcodes/plots/qcmatplotlib.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/qcodes/plots/qcmatplotlib.py b/qcodes/plots/qcmatplotlib.py index 711644e77eba..685f4604e5c2 100644 --- a/qcodes/plots/qcmatplotlib.py +++ b/qcodes/plots/qcmatplotlib.py @@ -229,6 +229,12 @@ def _draw_pcolormesh(self, ax, z, x=None, y=None, subplot=1, return False if 'cmap' not in kwargs: kwargs['cmap'] = cm.hot + if 'edgecolors' not in kwargs: + # Matplotlib pcolormesh per default are drawn as individual patches lined up next to each other + # due to rounding this produces visible gaps in some pdf viewers. To prevent this we draw each + # mesh with a visible edge (slightly overlapping) this assumes alpha=1 or it will produce artifacts + # at the overlaps + kwargs['edgecolors'] = 'face' pc = ax.pcolormesh(*args, **kwargs) if getattr(ax, 'qcodes_colorbar', None): From d75bb67d429badab6cc348cf35fdccff16fbea82 Mon Sep 17 00:00:00 2001 From: Jens Hedegaard Nielsen Date: Tue, 14 Mar 2017 16:58:51 +0100 Subject: [PATCH 05/14] Fix: add support to wrappers for plotting pdf via matplotlib --- qcodes/utils/wrappers.py | 63 ++++++++++++++++++++++++++++------------ 1 file changed, 44 insertions(+), 19 deletions(-) diff --git a/qcodes/utils/wrappers.py b/qcodes/utils/wrappers.py index 3d33ac849396..562120476666 100644 --- a/qcodes/utils/wrappers.py +++ b/qcodes/utils/wrappers.py @@ -4,7 +4,9 @@ from os import makedirs import logging from qcodes.plots.pyqtgraph import QtPlot +from qcodes.plots.qcmatplotlib import MatPlot from IPython import get_ipython +from matplotlib import cm CURRENT_EXPERIMENT = {} CURRENT_EXPERIMENT["logging_enabled"] = False @@ -12,7 +14,7 @@ def init(mainfolder:str, sample_name: str): """ Args: - mainfolder: base loacation for the data + mainfolder: base location for the data sample_name: name of the sample """ @@ -59,29 +61,46 @@ def init(mainfolder:str, sample_name: str): logging.debug("Logging already started at {}".format(logfile)) -def _plot_setup(data, inst_meas): +def _plot_setup(data, inst_meas, useQT=True): title = "{} #{:03d}".format(CURRENT_EXPERIMENT["sample_name"], data.location_provider.counter) - plot = QtPlot() + if useQT: + plot = QtPlot() + else: + plot = MatPlot() for j, i in enumerate(inst_meas): if getattr(i, "names", False): - # deal with multi dimenstional parameter + # deal with multidimensional parameter for k, name in enumerate(i.names): inst_meas_name = "{}_{}".format(i._instrument.name, name) plot.add(getattr(data, inst_meas_name), subplot=j + k + 1) - plot.subplots[j+k].showGrid(True, True) - if j == 0: - plot.subplots[0].setTitle(title) + if useQT: + plot.subplots[j+k].showGrid(True, True) + if j == 0: + plot.subplots[0].setTitle(title) + else: + plot.subplots[j+k].setTitle("") else: - plot.subplots[j+k].setTitle("") + plot.subplots[j+k].grid() + if j == 0: + plot.subplots[0].set_title(title) + else: + plot.subplots[j+k].set_title("") else: # simple_parameters inst_meas_name = "{}_{}".format(i._instrument.name, i.name) plot.add(getattr(data, inst_meas_name), subplot=j + 1) - plot.subplots[j].showGrid(True, True) - if j == 0: - plot.subplots[0].setTitle(title) + if useQT: + plot.subplots[j].showGrid(True, True) + if j == 0: + plot.subplots[0].setTitle(title) + else: + plot.subplots[j].setTitle("") else: - plot.subplots[j].setTitle("") + plot.subplots[j].grid() + if j == 0: + plot.subplots[0].set_title(title) + else: + plot.subplots[j].set_title("") return plot def do1d(inst_set, start, stop, division, delay, *inst_meas): @@ -106,12 +125,14 @@ def do1d(inst_set, start, stop, division, delay, *inst_meas): _ = loop.with_bg_task(plot.update, plot.save).run() except KeyboardInterrupt: print("Measurement Interrupted") + staticplot = _plot_setup(data, inst_meas, useQT=False) + staticplot.save(staticplot.get_default_title()+'.pdf') return plot, data def do1dDiagonal(inst_set, inst2_set, start, stop, division, delay, start2, slope, *inst_meas): """ - Perform diagonal sweep in 1 dimension, given two insturments + Perform diagonal sweep in 1 dimension, given two instruments Args: inst_set: Instrument to sweep over @@ -136,7 +157,9 @@ def do1dDiagonal(inst_set, inst2_set, start, stop, division, delay, start2, slop _ = loop.with_bg_task(plot.update, plot.save).run() except KeyboardInterrupt: print("Measurement Interrupted") - return data + staticplot = _plot_setup(data, inst_meas, useQT=False) + staticplot.save(staticplot.get_default_title()+'.pdf') + return plot, data def do2d(inst_set, start, stop, division, delay, inst_set2, start2, stop2, division2, delay2, *inst_meas): @@ -149,10 +172,10 @@ def do2d(inst_set, start, stop, division, delay, inst_set2, start2, stop2, divis division: Spacing between values delay: Delay at every step inst_set_2: Second instrument to sweep over - start_2: Start of sweep for second intrument - stop_2: End of sweep for second intrument - division_2: Spacing between values for second intrument - delay_2: Delay at every step for second intrument + start_2: Start of sweep for second instrument + stop_2: End of sweep for second instrument + division_2: Spacing between values for second instrument + delay_2: Delay at every step for second instrument *inst_meas: Returns: @@ -171,6 +194,8 @@ def do2d(inst_set, start, stop, division, delay, inst_set2, start2, stop2, divis _ = loop.with_bg_task(plot.update, plot.save).run() except KeyboardInterrupt: print("Measurement Interrupted") + staticplot = _plot_setup(data, inst_meas, useQT=False) + staticplot.save(staticplot.get_default_title()+'.pdf') return plot, data @@ -178,7 +203,7 @@ def show_num(id): """ Show and return plot and data for id in current instrument. Args: - id(number): id of intrumetn + id(number): id of instrument Returns: plot, data : returns the plot and the dataset From e110e1587653767c75bed6843d2f36595a325333 Mon Sep 17 00:00:00 2001 From: Jens Hedegaard Nielsen Date: Wed, 15 Mar 2017 16:29:24 +0100 Subject: [PATCH 06/14] fix: make show_num default to plot with matplotlib --- qcodes/utils/wrappers.py | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/qcodes/utils/wrappers.py b/qcodes/utils/wrappers.py index 562120476666..d3627d76b783 100644 --- a/qcodes/utils/wrappers.py +++ b/qcodes/utils/wrappers.py @@ -199,7 +199,7 @@ def do2d(inst_set, start, stop, division, delay, inst_set2, start2, stop2, divis return plot, data -def show_num(id): +def show_num(id, useQT=False): """ Show and return plot and data for id in current instrument. Args: @@ -220,9 +220,15 @@ def show_num(id): plots = [] for value in data.arrays.keys(): if "set" not in value: - plot = QtPlot(getattr(data, value)) - title = "{} #{}".format(CURRENT_EXPERIMENT["sample_name"], str_id) - plot.subplots[0].setTitle(title) - plot.subplots[0].showGrid(True, True) + if useQT: + plot = QtPlot(getattr(data, value)) + title = "{} #{}".format(CURRENT_EXPERIMENT["sample_name"], str_id) + plot.subplots[0].setTitle(title) + plot.subplots[0].showGrid(True, True) + else: + plot = MatPlot(getattr(data, value)) + title = "{} #{}".format(CURRENT_EXPERIMENT["sample_name"], str_id) + plot.subplots[0].set_title(title) + plot.subplots[0].grid() plots.append(plot) return data, plots From f492a532024c5de0948d7abfbca57f442b4f7808 Mon Sep 17 00:00:00 2001 From: Jens Hedegaard Nielsen Date: Thu, 16 Mar 2017 10:04:05 +0100 Subject: [PATCH 07/14] fix save individual plots as pdf --- qcodes/utils/wrappers.py | 36 ++++++++++++++++++++++++++++++------ 1 file changed, 30 insertions(+), 6 deletions(-) diff --git a/qcodes/utils/wrappers.py b/qcodes/utils/wrappers.py index d3627d76b783..8c5a915e73f2 100644 --- a/qcodes/utils/wrappers.py +++ b/qcodes/utils/wrappers.py @@ -103,6 +103,33 @@ def _plot_setup(data, inst_meas, useQT=True): plot.subplots[j].set_title("") return plot + +def _save_individual_plots(data, inst_meas): + title = "{} #{:03d}".format(CURRENT_EXPERIMENT["sample_name"], data.location_provider.counter) + counter_two = 0 + for j, i in enumerate(inst_meas): + if getattr(i, "names", False): + # deal with multidimensional parameter + for k, name in enumerate(i.names): + counter_two += 1 + plot = MatPlot() + inst_meas_name = "{}_{}".format(i._instrument.name, name) + plot.add(getattr(data, inst_meas_name)) + plot.subplots[0].set_title(title) + plot.subplots[0].grid() + plot.save("{}_{:03d}.pdf".format(plot.get_default_title(), counter_two)) + else: + counter_two += 1 + plot = MatPlot() + # simple_parameters + inst_meas_name = "{}_{}".format(i._instrument.name, i.name) + plot.add(getattr(data, inst_meas_name)) + plot.subplots[0].set_title(title) + plot.subplots[0].grid() + plot.save("{}_{:03d}.pdf".format(plot.get_default_title(), counter_two)) + + + def do1d(inst_set, start, stop, division, delay, *inst_meas): """ @@ -125,8 +152,7 @@ def do1d(inst_set, start, stop, division, delay, *inst_meas): _ = loop.with_bg_task(plot.update, plot.save).run() except KeyboardInterrupt: print("Measurement Interrupted") - staticplot = _plot_setup(data, inst_meas, useQT=False) - staticplot.save(staticplot.get_default_title()+'.pdf') + _save_individual_plots(data, inst_meas) return plot, data @@ -157,8 +183,7 @@ def do1dDiagonal(inst_set, inst2_set, start, stop, division, delay, start2, slop _ = loop.with_bg_task(plot.update, plot.save).run() except KeyboardInterrupt: print("Measurement Interrupted") - staticplot = _plot_setup(data, inst_meas, useQT=False) - staticplot.save(staticplot.get_default_title()+'.pdf') + _save_individual_plots(data, inst_meas) return plot, data @@ -194,8 +219,7 @@ def do2d(inst_set, start, stop, division, delay, inst_set2, start2, stop2, divis _ = loop.with_bg_task(plot.update, plot.save).run() except KeyboardInterrupt: print("Measurement Interrupted") - staticplot = _plot_setup(data, inst_meas, useQT=False) - staticplot.save(staticplot.get_default_title()+'.pdf') + _save_individual_plots(data, inst_meas) return plot, data From c157041b8f30d5232433d7dbd83366f6bdf5eb03 Mon Sep 17 00:00:00 2001 From: Jens Hedegaard Nielsen Date: Fri, 17 Mar 2017 16:45:03 +0100 Subject: [PATCH 08/14] Fix add basic support for moving qt windows to a specific position --- qcodes/plots/pyqtgraph.py | 12 +++++++++++- qcodes/utils/wrappers.py | 16 +++++++++++----- 2 files changed, 22 insertions(+), 6 deletions(-) diff --git a/qcodes/plots/pyqtgraph.py b/qcodes/plots/pyqtgraph.py index a2d541008f5f..a78249c00615 100644 --- a/qcodes/plots/pyqtgraph.py +++ b/qcodes/plots/pyqtgraph.py @@ -4,6 +4,7 @@ import numpy as np import pyqtgraph as pg import pyqtgraph.multiprocess as pgmp +from qtpy import QtWidgets import warnings from collections import namedtuple @@ -27,6 +28,10 @@ class QtPlot(BasePlot): figsize: (width, height) tuple in pixels to pass to GraphicsWindow default (1000, 600) + fig_x_pos: fraction of screen width to place the figure at + 0 is all the way to the left and + 1 is all the way to the right. + default None let qt decide. interval: period in seconds between update checks default 0.25 theme: tuple of (foreground_color, background_color), where each is @@ -39,7 +44,8 @@ class QtPlot(BasePlot): rpg = None def __init__(self, *args, figsize=(1000, 600), interval=0.25, - window_title='', theme=((60, 60, 60), 'w'), show_window=True, remote=True, **kwargs): + window_title='', theme=((60, 60, 60), 'w'), show_window=True, remote=True, fig_x_position=None, + **kwargs): super().__init__(interval) if 'windowTitle' in kwargs.keys(): @@ -58,6 +64,10 @@ def __init__(self, *args, figsize=(1000, 600), interval=0.25, self.win = self.rpg.GraphicsWindow(title=window_title) self.win.setBackground(theme[1]) self.win.resize(*figsize) + if fig_x_position: + _, _, width, height = QtWidgets.QDesktopWidget().screenGeometry().getCoords() + y_pos = self.win.y() + self.win.move(width * fig_x_position, y_pos) self.subplots = [self.add_subplot()] if args or kwargs: diff --git a/qcodes/utils/wrappers.py b/qcodes/utils/wrappers.py index 8c5a915e73f2..f52bf102a03d 100644 --- a/qcodes/utils/wrappers.py +++ b/qcodes/utils/wrappers.py @@ -3,19 +3,24 @@ from os.path import sep from os import makedirs import logging +from qtpy import QtWidgets + from qcodes.plots.pyqtgraph import QtPlot from qcodes.plots.qcmatplotlib import MatPlot from IPython import get_ipython -from matplotlib import cm + CURRENT_EXPERIMENT = {} CURRENT_EXPERIMENT["logging_enabled"] = False -def init(mainfolder:str, sample_name: str): +def init(mainfolder:str, sample_name: str, plot_x_position=0.66): """ Args: mainfolder: base location for the data sample_name: name of the sample + plot_x_position: fractional of screen position to put QT plots. + 0 is all the way to the left and + 1 is all the way to the right. """ if sep in sample_name: @@ -30,10 +35,11 @@ def init(mainfolder:str, sample_name: str): CURRENT_EXPERIMENT["sample_name"] = sample_name CURRENT_EXPERIMENT['init'] = True + CURRENT_EXPERIMENT['plot_x_position'] = plot_x_position + path_to_experiment_folder = sep.join([mainfolder, sample_name, ""]) CURRENT_EXPERIMENT["exp_folder"] = path_to_experiment_folder - try: makedirs(path_to_experiment_folder) except FileExistsError: @@ -64,7 +70,7 @@ def init(mainfolder:str, sample_name: str): def _plot_setup(data, inst_meas, useQT=True): title = "{} #{:03d}".format(CURRENT_EXPERIMENT["sample_name"], data.location_provider.counter) if useQT: - plot = QtPlot() + plot = QtPlot(fig_x_position=CURRENT_EXPERIMENT['plot_x_position']) else: plot = MatPlot() for j, i in enumerate(inst_meas): @@ -245,7 +251,7 @@ def show_num(id, useQT=False): for value in data.arrays.keys(): if "set" not in value: if useQT: - plot = QtPlot(getattr(data, value)) + plot = QtPlot(getattr(data, value), fig_x_position=CURRENT_EXPERIMENT['plot_x_position']) title = "{} #{}".format(CURRENT_EXPERIMENT["sample_name"], str_id) plot.subplots[0].setTitle(title) plot.subplots[0].showGrid(True, True) From 7b3f11bffa0a4209bb3c688c41bf4d43162e4412 Mon Sep 17 00:00:00 2001 From: Jens Hedegaard Nielsen Date: Tue, 21 Mar 2017 10:01:36 +0100 Subject: [PATCH 09/14] fix: dont depend on qtpy --- qcodes/plots/pyqtgraph.py | 4 ++-- qcodes/utils/wrappers.py | 1 - 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/qcodes/plots/pyqtgraph.py b/qcodes/plots/pyqtgraph.py index a78249c00615..06dc97226086 100644 --- a/qcodes/plots/pyqtgraph.py +++ b/qcodes/plots/pyqtgraph.py @@ -4,7 +4,7 @@ import numpy as np import pyqtgraph as pg import pyqtgraph.multiprocess as pgmp -from qtpy import QtWidgets +from pyqtgraph import QtGui # note that pyqtgraph still uses the old pyqt4 layout import warnings from collections import namedtuple @@ -65,7 +65,7 @@ def __init__(self, *args, figsize=(1000, 600), interval=0.25, self.win.setBackground(theme[1]) self.win.resize(*figsize) if fig_x_position: - _, _, width, height = QtWidgets.QDesktopWidget().screenGeometry().getCoords() + _, _, width, height = QtGui.QDesktopWidget().screenGeometry().getCoords() y_pos = self.win.y() self.win.move(width * fig_x_position, y_pos) self.subplots = [self.add_subplot()] diff --git a/qcodes/utils/wrappers.py b/qcodes/utils/wrappers.py index f52bf102a03d..5c43f4a672a5 100644 --- a/qcodes/utils/wrappers.py +++ b/qcodes/utils/wrappers.py @@ -3,7 +3,6 @@ from os.path import sep from os import makedirs import logging -from qtpy import QtWidgets from qcodes.plots.pyqtgraph import QtPlot from qcodes.plots.qcmatplotlib import MatPlot From ad05a69b53b2921824db4207f60916a9d1aa1fac Mon Sep 17 00:00:00 2001 From: Jens Hedegaard Nielsen Date: Fri, 24 Mar 2017 16:00:06 +0100 Subject: [PATCH 10/14] Fix: zi ensure single trigger mode is always set This get reset when enabling the read --- qcodes/instrument_drivers/ZI/ZIUHFLI.py | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/qcodes/instrument_drivers/ZI/ZIUHFLI.py b/qcodes/instrument_drivers/ZI/ZIUHFLI.py index 1f78667d953a..41d04faea960 100644 --- a/qcodes/instrument_drivers/ZI/ZIUHFLI.py +++ b/qcodes/instrument_drivers/ZI/ZIUHFLI.py @@ -390,6 +390,13 @@ def get(self): params['scope_runstop'].set('run') log.info('[*] Starting ZI scope acquisition.') + # one shot per trigger. This needs to be set every time + # a the scope is enabled as below using scope_runstop + # We should also test if scopeModule/mode and scopeModule/averager/weight + # needs to be set every time since we are creating a new scopemodule + # here + self._instrument.daq.setInt('/{}/scopes/0/single'.format(self._instrument.device), 1) + self._instrument.daq.sync() # Start something... hauling data from the scopeModule? scope.execute() From 16bc8f5f85f71f500e0aa7e041bd6b6c7af42652 Mon Sep 17 00:00:00 2001 From: jana-d Date: Fri, 24 Mar 2017 17:05:55 +0100 Subject: [PATCH 11/14] fix move trigger mode setting to where it belongs --- qcodes/instrument_drivers/ZI/ZIUHFLI.py | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/qcodes/instrument_drivers/ZI/ZIUHFLI.py b/qcodes/instrument_drivers/ZI/ZIUHFLI.py index 41d04faea960..40f9d61fd256 100644 --- a/qcodes/instrument_drivers/ZI/ZIUHFLI.py +++ b/qcodes/instrument_drivers/ZI/ZIUHFLI.py @@ -379,7 +379,13 @@ def get(self): # We add one second to account for latencies and random delays meas_time = segs*(params['scope_duration'].get()+deadtime)+1 npts = params['scope_length'].get() - + # one shot per trigger. This needs to be set every time + # a the scope is enabled as below using scope_runstop + # We should also test if scopeModule/mode and scopeModule/averager/weight + # needs to be set every time since we are creating a new scopemodule + # here + self._instrument.daq.setInt('/{}/scopes/0/single'.format(self._instrument.device), 1) + self._instrument.daq.sync() # Create a new scopeModule instance (TODO: Why a new instance?) scope = self._instrument.daq.scopeModule() @@ -390,13 +396,7 @@ def get(self): params['scope_runstop'].set('run') log.info('[*] Starting ZI scope acquisition.') - # one shot per trigger. This needs to be set every time - # a the scope is enabled as below using scope_runstop - # We should also test if scopeModule/mode and scopeModule/averager/weight - # needs to be set every time since we are creating a new scopemodule - # here - self._instrument.daq.setInt('/{}/scopes/0/single'.format(self._instrument.device), 1) - self._instrument.daq.sync() + # Start something... hauling data from the scopeModule? scope.execute() From cb977ca0ac8aaef88eea6a457ed8148573957440 Mon Sep 17 00:00:00 2001 From: jana-d Date: Fri, 24 Mar 2017 17:07:01 +0100 Subject: [PATCH 12/14] HACK: hardcode scope settings because setting them in the main driver does not work This breaks all other scope fucs for now --- qcodes/instrument_drivers/ZI/ZIUHFLI.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/qcodes/instrument_drivers/ZI/ZIUHFLI.py b/qcodes/instrument_drivers/ZI/ZIUHFLI.py index 40f9d61fd256..6abd0186f384 100644 --- a/qcodes/instrument_drivers/ZI/ZIUHFLI.py +++ b/qcodes/instrument_drivers/ZI/ZIUHFLI.py @@ -388,7 +388,11 @@ def get(self): self._instrument.daq.sync() # Create a new scopeModule instance (TODO: Why a new instance?) scope = self._instrument.daq.scopeModule() - + # TODO We are hard coding scope mode and avg weight here because the setting + # in the main driver references a different scope which will fail and give garbage data + # YOU cannot set other scope modes or weights at the moment + scope.set('scopeModule/mode', 1) + scope.set('scopeModule/averager/weight', 1) # Subscribe to the relevant... publisher? scope.subscribe('/{}/scopes/0/wave'.format(self._instrument.device)) From c46572c48a0d416c9df0dd752a9837136cad303b Mon Sep 17 00:00:00 2001 From: William Nielsen Date: Tue, 28 Mar 2017 13:48:44 +0200 Subject: [PATCH 13/14] fix: Ignore MAC OSX DS_Store files Add .DS_Store to list of git ignored files --- .gitignore | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.gitignore b/.gitignore index 840a47c00374..a77a2c6c4c17 100644 --- a/.gitignore +++ b/.gitignore @@ -53,6 +53,9 @@ coverage.xml *.mo *.pot +# MAC OSX junk files +.DS_Store + # Django stuff: *.log From 45970d24a41f665a547aafa14209bda0b78f7869 Mon Sep 17 00:00:00 2001 From: William Nielsen Date: Tue, 28 Mar 2017 14:25:02 +0200 Subject: [PATCH 14/14] fix: Allow execution of tasks in doNd[_diagonal] Check whether stuff to do at each step in a loop is plottable. --- qcodes/utils/wrappers.py | 62 ++++++++++++++++++++++++++++------------ 1 file changed, 44 insertions(+), 18 deletions(-) diff --git a/qcodes/utils/wrappers.py b/qcodes/utils/wrappers.py index 5c43f4a672a5..3e40d3ddd686 100644 --- a/qcodes/utils/wrappers.py +++ b/qcodes/utils/wrappers.py @@ -8,9 +8,10 @@ from qcodes.plots.qcmatplotlib import MatPlot from IPython import get_ipython -CURRENT_EXPERIMENT = {} +CURRENT_EXPERIMENT = {} CURRENT_EXPERIMENT["logging_enabled"] = False + def init(mainfolder:str, sample_name: str, plot_x_position=0.66): """ @@ -23,14 +24,14 @@ def init(mainfolder:str, sample_name: str, plot_x_position=0.66): """ if sep in sample_name: - raise TypeError("Use Relative names. That is wihtout {}".format(sep)) + raise TypeError("Use Relative names. That is wihtout {}".format(sep)) # always remove trailing sep in the main folder - if mainfolder[-1] == sep: + if mainfolder[-1] == sep: mainfolder = mainfolder[:-1] mainfolder = abspath(mainfolder) - CURRENT_EXPERIMENT["mainfolder"] = mainfolder + CURRENT_EXPERIMENT["mainfolder"] = mainfolder CURRENT_EXPERIMENT["sample_name"] = sample_name CURRENT_EXPERIMENT['init'] = True @@ -66,8 +67,25 @@ def init(mainfolder:str, sample_name: str, plot_x_position=0.66): logging.debug("Logging already started at {}".format(logfile)) +def _select_plottables(tasks): + """ + Helper function to select plottable tasks. Used inside the doNd functions. + + A task is here understood to be anything that the qc.Loop 'each' can eat. + """ + # allow passing a single task + if not isinstance(tasks, tuple): + tasks = (tasks,) + + # is the following check necessary AND sufficient? + plottables = [task for task in tasks if hasattr(task, '_instrument')] + + return tuple(plottables) + + def _plot_setup(data, inst_meas, useQT=True): - title = "{} #{:03d}".format(CURRENT_EXPERIMENT["sample_name"], data.location_provider.counter) + title = "{} #{:03d}".format(CURRENT_EXPERIMENT["sample_name"], + data.location_provider.counter) if useQT: plot = QtPlot(fig_x_position=CURRENT_EXPERIMENT['plot_x_position']) else: @@ -134,7 +152,6 @@ def _save_individual_plots(data, inst_meas): plot.save("{}_{:03d}.pdf".format(plot.get_default_title(), counter_two)) - def do1d(inst_set, start, stop, division, delay, *inst_meas): """ @@ -144,20 +161,23 @@ def do1d(inst_set, start, stop, division, delay, *inst_meas): stop: End of sweep division: Spacing between values delay: Delay at every step - *inst_meas: any number of instrument to measure + *inst_meas: any number of instrument to measure and/or tasks to + perform at each step of the sweep Returns: plot, data : returns the plot and the dataset """ - loop = qc.Loop(inst_set.sweep(start, stop, division), delay).each(*inst_meas) + loop = qc.Loop(inst_set.sweep(start, + stop, division), delay).each(*inst_meas) data = loop.get_data_set() - plot = _plot_setup(data, inst_meas) + plottables = _select_plottables(inst_meas) + plot = _plot_setup(data, plottables) try: _ = loop.with_bg_task(plot.update, plot.save).run() except KeyboardInterrupt: print("Measurement Interrupted") - _save_individual_plots(data, inst_meas) + _save_individual_plots(data, plottables) return plot, data @@ -183,12 +203,13 @@ def do1dDiagonal(inst_set, inst2_set, start, stop, division, delay, start2, slop loop = qc.Loop(inst_set.sweep(start, stop, division), delay).each( qc.Task(inst2_set, (inst_set) * slope + (slope * start - start2)), *inst_meas, inst2_set) data = loop.get_data_set() - plot = _plot_setup(data, inst_meas) + plottables = _select_plottables(inst_meas) + plot = _plot_setup(data, plottables) try: _ = loop.with_bg_task(plot.update, plot.save).run() except KeyboardInterrupt: print("Measurement Interrupted") - _save_individual_plots(data, inst_meas) + _save_individual_plots(data, plottables) return plot, data @@ -219,12 +240,13 @@ def do2d(inst_set, start, stop, division, delay, inst_set2, start2, stop2, divis loop = qc.Loop(inst_set.sweep(start, stop, division), delay).loop(inst_set2.sweep(start2,stop2,division2), delay2).each( *inst_meas) data = loop.get_data_set() - plot = _plot_setup(data, inst_meas) + plottables = _select_plottables(inst_meas) + plot = _plot_setup(data, plottables) try: _ = loop.with_bg_task(plot.update, plot.save).run() except KeyboardInterrupt: print("Measurement Interrupted") - _save_individual_plots(data, inst_meas) + _save_individual_plots(data, plottables) return plot, data @@ -239,7 +261,8 @@ def show_num(id, useQT=False): """ if not getattr(CURRENT_EXPERIMENT, "init", True): - raise RuntimeError("Experiment not initalized. use qc.Init(mainfolder, samplename)") + raise RuntimeError("Experiment not initalized. " + "use qc.Init(mainfolder, samplename)") str_id = '{0:03d}'.format(id) @@ -250,13 +273,16 @@ def show_num(id, useQT=False): for value in data.arrays.keys(): if "set" not in value: if useQT: - plot = QtPlot(getattr(data, value), fig_x_position=CURRENT_EXPERIMENT['plot_x_position']) - title = "{} #{}".format(CURRENT_EXPERIMENT["sample_name"], str_id) + plot = QtPlot(getattr(data, value), + fig_x_position=CURRENT_EXPERIMENT['plot_x_position']) + title = "{} #{}".format(CURRENT_EXPERIMENT["sample_name"], + str_id) plot.subplots[0].setTitle(title) plot.subplots[0].showGrid(True, True) else: plot = MatPlot(getattr(data, value)) - title = "{} #{}".format(CURRENT_EXPERIMENT["sample_name"], str_id) + title = "{} #{}".format(CURRENT_EXPERIMENT["sample_name"], + str_id) plot.subplots[0].set_title(title) plot.subplots[0].grid() plots.append(plot)