def test_elapsed_time_parameter_init(): tp1 = ElapsedTimeParameter('time1') sleep(0.01) tp2 = ElapsedTimeParameter('time2') assert tp1() > tp2()
def test_elapsed_time_parameter_reset_clock(): tp = ElapsedTimeParameter('time') sleep(0.01) t1 = tp() tp.reset_clock() t2 = tp() assert t1 > t2
def test_elapsed_time_parameter_monotonic(): tp = ElapsedTimeParameter('time') times = [tp() for _ in range(25)] assert sorted(times) == times
def test_elapsed_time_parameter_forbidden_kwargs(): forbidden_kwargs = ['unit', 'get_cmd', 'set_cmd'] for fb_kwarg in forbidden_kwargs: match = f'Can not set "{fb_kwarg}" for an ElapsedTimeParameter' with pytest.raises(ValueError, match=match): ElapsedTimeParameter('time', **{fb_kwarg: None})
def _create_measurement(self, *set_params): meas = Measurement() self._etp = ElapsedTimeParameter('time') meas.register_parameter(self._etp) for param in set_params: meas.register_parameter(param) for param in self._params: meas.register_parameter(param.param, setpoints=(*set_params, self._etp)) for sr830 in self._sr830s: meas.register_parameter(sr830.sr830.X, setpoints=(*set_params, self._etp)) meas.register_parameter(sr830.sr830.Y, setpoints=(*set_params, self._etp)) if self._fbl is not None: for c in self._fbl.channels: meas.register_custom_parameter(f'fbl_c{c}_x', setpoints=(*set_params, self._etp)) meas.register_custom_parameter(f'fbl_c{c}_p', setpoints=(*set_params, self._etp)) if self._fbl.outputs: meas.register_custom_parameter(f'fbl_c{c}_o', setpoints=(*set_params, self._etp)) if self._fbl.setpoints: meas.register_custom_parameter(f'fbl_c{c}_s', setpoints=(*set_params, self._etp)) if self._fbl.dc: meas.register_custom_parameter(f'fbl_c{c}_dc', setpoints=(*set_params, self._etp)) for fn in self._fns: meas.register_custom_parameter(fn.name, setpoints=(*set_params, self._etp)) return meas
self.i += 1 return (self.i, self.i + 100) now = str(datetime.datetime.now()) path = os.path.join(os.getcwd(), 'test.db') initialise_or_create_database_at(path) load_or_create_experiment('tutorial ' + now, 'no sample') my_param = MyCounter('test_instr') from qcodes.instrument.specialized_parameters import ElapsedTimeParameter x = qc.Parameter(name='x', label='Voltage_x', unit='V', set_cmd=None, get_cmd=None) y = qc.Parameter(name='y', label='Voltage_y', unit='V', set_cmd=None, get_cmd=None) timer = ElapsedTimeParameter('time') my_param_multi_test = dummy_multi_parameter_2dawg('param') from core_tools.GUI.keysight_videomaps.data_getter.scan_generator_Virtual import construct_1D_scan_fast, construct_2D_scan_fast, fake_digitizer param_1D = construct_1D_scan_fast("P2", 10, 10, 5000, True, None, fake_digitizer('test')) param_2D = construct_2D_scan_fast('P2', 10, 10, 'P5', 10, 10, 50000, True, None, fake_digitizer('test')) data_1D = param_1D.get() do0D(param_2D).run() do1D(x, 0, 5, 100, 0.01, param_1D).run()
def test_elapsed_time_parameter_not_settable(): tp = ElapsedTimeParameter('time') with pytest.raises(NotImplementedError): tp(0)
class Sweep: """Perform measurement sweeps of various kinds. You will want to use the various follow_* functions to add parameters to follow, then call one of the sweep functions. You can reuse the same Sweep object for multiple sweeps. """ def __init__(self): self._params = [] self._sr830s = [] self._fbl = None self._fbl_sock = None self._fns = [] self._etp = None self._plots = [] self._stop_when_fn = None def follow_param(self, param, gain=1.0): """Follow a qcodes Parameter.""" if not isinstance(param, qc.Parameter): raise ValueError( f'param is not a qcodes Parameter, it is a {type(param)}') self._params.append(_Param(param, gain)) return self def follow_sr830(self, sr830, gain=1.0, autorange=True): """Follow an SR830.""" if not isinstance(sr830, SR830): raise ValueError( f'sr830 is not a qcodes SR830, it is a {type(sr830)}') self._sr830s.append(_SR830(sr830, gain, autorange)) return self def follow_fbl(self, channels, host='localhost', port=10000, gains=None, outputs=False, setpoints=False, dc=False): if self._fbl is not None: raise Exception( 'cannot follow_fbl twice, please do it in one call') if gains is None: gains = np.ones(len(channels)) elif len(gains) != len(channels): raise ValueError( f'different number of gains ({len(gains)}) and channels ({len(channels)})' ) self._fbl = _FBL(host, port, channels, gains, outputs, setpoints, dc) return self def follow_fn(self, fn, name, gain=1.0, unit=None): """Follow an arbitrary function. The function will be passed a dictionary containing mappings of parameter.full_name -> value for each parameter. Your function should return one number. """ self._fns.append(_Fn(fn, gain, name, unit)) return self def stop_when(self, fn): if self._stop_when_fn is not None: # TODO: Is this necessary? Can OR them all I suppose, if that's clear behavior. raise Exception( 'cannot add two stop_when functions, just combine them into one' ) self._stop_when_fn = fn def _autorange_sr830(self, sr830, max_changes=3): def autorange_once(): r = sr830.R.get() sens = sr830.sensitivity.get() if r > 0.9 * sens: return sr830.increment_sensitivity() elif r < 0.1 * sens: return sr830.decrement_sensitivity() return False sets = 0 while autorange_once() and sets < max_changes: sets += 1 # Sleep 10 times the time constant between range sets. # The manual has more detailed guidelines for how long to wait. time.sleep(10 * sr830.time_constant.get()) def _create_measurement(self, *set_params): meas = Measurement() self._etp = ElapsedTimeParameter('time') meas.register_parameter(self._etp) for param in set_params: meas.register_parameter(param) for param in self._params: meas.register_parameter(param.param, setpoints=(*set_params, self._etp)) for sr830 in self._sr830s: meas.register_parameter(sr830.sr830.X, setpoints=(*set_params, self._etp)) meas.register_parameter(sr830.sr830.Y, setpoints=(*set_params, self._etp)) if self._fbl is not None: for c in self._fbl.channels: meas.register_custom_parameter(f'fbl_c{c}_x', setpoints=(*set_params, self._etp)) meas.register_custom_parameter(f'fbl_c{c}_p', setpoints=(*set_params, self._etp)) if self._fbl.outputs: meas.register_custom_parameter(f'fbl_c{c}_o', setpoints=(*set_params, self._etp)) if self._fbl.setpoints: meas.register_custom_parameter(f'fbl_c{c}_s', setpoints=(*set_params, self._etp)) if self._fbl.dc: meas.register_custom_parameter(f'fbl_c{c}_dc', setpoints=(*set_params, self._etp)) for fn in self._fns: meas.register_custom_parameter(fn.name, setpoints=(*set_params, self._etp)) return meas def _measure_param(self, param): return param.param() / param.gain def _measure_sr830(self, sr830): if sr830.autorange: self._autorange_sr830(sr830.sr830) # Snap grabs both x and y simultaneously. # Grabbing them separately may bias results. x, y = sr830.sr830.snap('x', 'y') return x / sr830.gain, y / sr830.gain def _measure_fbl(self): if self._fbl is None: return [] self._fbl_sock.sendall(b'send_data\n') recv = self._fbl_sock.recv( 8 * 32 * 4) # Double precision (8), 32 channels, 4 variables. arr = np.frombuffer(recv, dtype=np.float64).reshape(32, 4, order='F') data = [] for c, g in zip(self._fbl.channels, self._fbl.gains): if self._fbl.outputs: data.append((f'fbl_c{c}_o', arr[c, 0])) if self._fbl.setpoints: data.append((f'fbl_c{c}_s', arr[c, 1])) data.append((f'fbl_c{c}_x', arr[c, 2] / g)) data.append((f'fbl_c{c}_p', arr[c, 3])) if self._fbl.dc: data.append((f'fbl_c{c}_dc', arr[c, 4])) return data def _measure_inputs(self): data = [(self._etp, self._etp())] for param in self._params: data.append([param.param, self._measure_param(param)]) for sr830 in self._sr830s: x, y = self._measure_sr830(sr830) data.extend([[sr830.sr830.X, x], [sr830.sr830.Y, y]]) data.extend(self._measure_fbl()) return data def _format_data_map(self, data): m = {} for p, v in data: if isinstance(p, str): m[p] = v else: m[p.full_name] = v return m def _call_fns(self, data): fn_input = self._format_data_map(data) fn_data = [] for fn in self._fns: fn_data.append([fn.name, fn.fn(fn_input) / fn.gain]) return fn_data def _should_stop(self, data): # TODO: If we want to add more communication stuff then this needs # to be in an actual event loop. As-is, double-tapping may(?) race with # sending the image over for display. messages = [] while self._plot_conn.poll(): messages.append(self._plot_conn.recv()) for m in messages: if m['action'] == 'stop': return True if self._stop_when_fn is None: return False fn_input = self._format_data_map(data) return self._stop_when_fn(fn_input) def _send_plot_data(self, data): self._plot_conn.send({ 'action': 'add_point', 'data': self._format_data_map(data) }) def plot(self, x=None, y=None, z=None): if isinstance(x, list): raise ValueError('don' 't put multiple xs you goofus') if x is None or y is None: raise ValueError('x and y cannot be empty') if z is not None: raise ValueError('2D plots not supported rn') def to_names(v): if v is None: return [] def n(p): if isinstance(p, str): return p return p.full_name if isinstance(v, list): nl = [] for item in v: nl.append(n(item)) return nl return [n(v)] self._plots.append((to_names(x), to_names(y), to_names(z))) @_with_live_plotting @_interruptible @_with_fbl_socket def sweep(self, set_param, vals, inter_delay=0): print(f'Minimum duration: {_sec_to_str(len(vals) * inter_delay)}') meas = self._create_measurement(set_param) with meas.run() as datasaver: for setpoint in vals: set_param.set(setpoint) time.sleep(inter_delay) data = [(set_param, setpoint)] data.extend(self._measure_inputs()) data.extend(self._call_fns(data)) datasaver.add_result(*data) self._send_plot_data(data) if self._should_stop(data): break self.dataset = datasaver.dataset @_with_live_plotting @_interruptible @_with_fbl_socket def watch(self, inter_delay=0, max_duration=None): meas = self._create_measurement() with meas.run() as datasaver: self._etp.reset_clock() while max_duration is None or self._etp() < max_duration: time.sleep(inter_delay) data = self._measure_inputs() data.extend(self._call_fns(data)) datasaver.add_result(*data) self._send_plot_data(data) if self._should_stop(data): break self.dataset = datasaver.dataset @_with_live_plotting @_interruptible @_with_fbl_socket def megasweep(self, slow_p, slow_v, fast_p, fast_v, slow_delay=0, fast_delay=0): print( f'Minimum duration: {_sec_to_str(len(slow_v)*len(fast_v)*fast_delay + len(slow_v)*slow_delay)}' ) meas = self._create_measurement(slow_p, fast_p) with meas.run() as datasaver: should_stop = False for ov in slow_v: slow_p.set(ov) time.sleep(slow_delay) for iv in fast_v: fast_p.set(iv) time.sleep(fast_delay) data = [(slow_p, ov), (fast_p, iv)] data.extend(self._measure_inputs()) data.extend(self._call_fns(data)) datasaver.add_result(*data) self._send_plot_data(data) if self._should_stop(data): should_stop = True if should_stop: break self.dataset = datasaver.dataset