def ramp_to(self, vals_dict, start_on_finish=False, persist=None, multiplier=1): # Ensure we aren't currently running if self.is_ramping: print( f"Currently ramping. Finish current ramp before starting another." ) return if self.is_running: print(f"Already running. Stop the sweep before ramping.") return ramp_params_dict = {} n_steps = 1 for p, v in vals_dict.items(): if p not in self.set_params_dict.keys(): print("Cannot ramp parameter not in our sweep.") return p_step = self.set_params_dict[p]['step'] if abs(v - safe_get(p)) - abs(p_step / 2) < abs(p_step) * 1e-4: continue ramp_params_dict[p] = {} ramp_params_dict[p]['start'] = safe_get(p) ramp_params_dict[p]['stop'] = v p_steps = abs( (ramp_params_dict[p]['stop'] - ramp_params_dict[p]['start']) / p_step * multiplier) if p_steps > n_steps: n_steps = math.ceil(p_steps) if len(ramp_params_dict.keys()) == 0: print("Already at the values, no ramp needed.") self.done_ramping(vals_dict, start_on_finish=start_on_finish, pd=persist) return for p, v in ramp_params_dict.items(): v['step'] = (v['stop'] - v['start']) / n_steps self.ramp_sweep = SimulSweep(ramp_params_dict, n_steps=n_steps, inter_delay=self.inter_delay, plot_data=True, save_data=False, complete_func=partial( self.done_ramping, vals_dict, start_on_finish=start_on_finish, pd=persist)) self.is_ramping = True self.is_running = False self.ramp_sweep.start(ramp_to_start=False)
def estimate_time(self, verbose=True): rate = safe_get(self.magnet.sweeprate_field) B_range = abs(safe_get(self.magnet.field) - self.setpoint) t_est = B_range * 60 / rate hours = int(t_est / 3600) minutes = int((t_est % 3600) / 60) seconds = t_est % 60 if verbose is True: print( f'Estimated time for {repr(self)} to run: {hours}h:{minutes:2.0f}m:{seconds:2.0f}s' ) return t_est
def done_ramping(self, vals_dict, start_on_finish=False, pd=None): self.is_ramping = False self.is_running = False # Check if we are at the value we expect, otherwise something went wrong with the ramp for p, v in vals_dict.items(): p_step = self.set_params_dict[p]['step'] if abs(safe_get(p) - v) - abs(p_step / 2) > abs(p_step) * 1e-4: print( f'Ramping failed (possible that the direction was changed while ramping). ' f'Expected {p.label} final value: {v}. Actual value: {safe_get(p)}. ' f'Stopping the sweep.') if self.ramp_sweep is not None: self.ramp_sweep.kill() self.ramp_sweep = None return print(f'Done ramping!') for p, v in vals_dict.items(): safe_set(p, v) self.set_params_dict[p][ 'setpoint'] = v - self.set_params_dict[p]['step'] if self.ramp_sweep is not None: self.ramp_sweep.kill() self.ramp_sweep = None if start_on_finish is True: self.start(ramp_to_start=False, persist_data=pd)
def update_values(self): """ Iterates our data points, changing our setpoint if we are sweeping, and refreshing the values of all our followed parameters. If we are saving data, it happens here, and the data is returned. Returns: data - A list of tuples with the new data. Each tuple is of the format (<QCoDeS Parameter>, measurement value). The tuples are passed in order of time, then set_param (if applicable), then all the followed params. """ t = time.monotonic() - self.t0 data = [('time', t)] sp_data = self.step_param() if sp_data is not None: data += sp_data else: return None for i, (l, _, gain) in enumerate(self._srs): _autorange_srs(l, 3) for i, p in enumerate(self._params): if p not in self.simul_params: v = safe_get(p) data.append((p, v)) if self.save_data and self.is_running: self.runner.datasaver.add_result(*data) # self.send_updates() return data
def __init__(self, _p, n_steps=None, bidirectional=False, continual=False, *args, **kwargs): if len(_p.keys()) < 1 or not all( isinstance(p, dict) for p in _p.values()): raise ValueError( 'Must pass at least one Parameter and the associated values as dictionaries.' ) self.simul_params = [] self.set_params_dict = _p.copy() self.bidirectional = bidirectional self.continuous = continual self.direction = 0 self.n_steps = n_steps self.is_ramping = False self.ramp_sweep = None # Take the first parameter, and set it as the normal Sweep1D set param sp = list(_p.keys())[0] # Force time to be on the x axis kwargs['x_axis_time'] = 1 QObject.__init__(self) BaseSweep.__init__(self, set_param=sp, *args, **kwargs) if n_steps is not None: for p, v in self.set_params_dict.items(): v['step'] = (v['stop'] - v['start']) / n_steps else: _n_steps = [] for key, p in _p.items(): _n_steps.append( int(abs(p['stop'] - p['start']) / abs(p['step']))) if not all(steps == _n_steps[0] for steps in _n_steps): raise ValueError( 'Parameters have a different number of steps for the sweep. The Parameters must have ' 'the same number of steps to sweep them simultaneously.' f'\nStep numbers: {_n_steps}') self.n_steps = _n_steps[0] for p, v in self.set_params_dict.items(): self.simul_params.append(p) # Make sure the step is in the right direction if (v['stop'] - v['start']) > 0: v['step'] = abs(v['step']) else: v['step'] = (-1) * abs(v['step']) v['setpoint'] = safe_get(p) - v['step'] self.follow_param( [p for p in self.simul_params if p is not self.set_param]) self.persist_data = []
def get_param(self, p): try: return str(safe_get(p)) except ParameterException as e: self.show_error( 'Error', f'Could not get {p.label}. Check the exception and try again.', e) return ''
def step_AMI430(self): """ Used to control sweeps of AMI430 Instrument. The endpoint is determined prior to the sweep, and the current field is measured during ramping. Returns --------- The parameter-value pair that was measured. """ # Check if we have set the magnetic field yet if self.magnet_initialized is False: self.instrument.set_field(self.end, block=False) self.magnet_initialized = True time.sleep(self.inter_delay) while safe_get(self.instrument.ramping_state) != 'ramping': time.sleep(self.inter_delay) # Grab our data dt = safe_get(self.set_param) data_pair = (self.set_param, dt) self.setpoint = dt # Check our stop conditions- being at the end point if safe_get(self.instrument.ramping_state) == 'holding': self.magnet_initialized = False if self.save_data: self.runner.flush_flag = True self.is_running = False print(f"Done with the sweep, {self.set_param.label}={self.set_param.get()}") self.flip_direction() self.completed.emit() if self.parent is None: self.runner.kill_flag = True # Return our data pair, just like any other sweep return [data_pair]
def estimate_time(self, verbose=True): t_est = 0 if isinstance(self.instrument, AMI430): rate = safe_get(self.instrument.ramp_rate) if safe_get(self.instrument.ramp_rate_units) == 0: t_est = abs((self.end - self.begin) / rate) else: t_est = abs((self.end - self.begin) * 60 / rate) else: t_est = abs((self.begin - self.end) / self.step) * self.inter_delay if self.continuous is True: print(f'No estimated time for {repr(self)} to run.') return 0 elif self.bidirectional is True: t_est *= 2 hours = int(t_est / 3600) minutes = int((t_est % 3600) / 60) seconds = t_est % 60 if verbose is True: print(f'Estimated time for {repr(self)} to run: {hours}h:{minutes:2.0f}m:{seconds:2.0f}s') return t_est
def update_values(self): """ Called as Runner Thread loops to update parameter values. Verifies the data to be updated depending on type of sweep. Iterates through data point intervals, assigning collected values to their respective parameters. If data is to be saved, it happens here, and the updated data is emitted to all connected slots. Returns --------- data: A dictionary of tuples with the updated data. Each tuple is of the format (<QCoDeS Parameter>, measurement value). The tuples are passed in order of time, then set_param (if applicable), then all the followed params. """ t = time.monotonic() - self.t0 data = [('time', t)] if self.set_param is not None: sp_data = self.step_param() if sp_data is not None: data += sp_data else: return None persist_param = None if self.persist_data is not None: data.append(self.persist_data) persist_param = self.persist_data[0] for i, (l, _, gain) in enumerate(self._srs): _autorange_srs(l, 3) for i, p in enumerate(self._params): if p is not persist_param: v = safe_get(p) data.append((p, v)) if self.save_data and self.is_running: self.runner.datasaver.add_result(*data) self.send_updates() return data
def done_ramping(self, value, start_on_finish=False, pd=None): """ Alerts the sweep that the ramp is finished. Parameters --------- value: The starting value for the sweep, also the current parameter value. start_on_finish: Sweep will be called to start immediately after ramping when set to True. pd: Sets persistent data if running Sweep2D. """ self.is_ramping = False self.is_running = False # Grab the beginning # value = self.ramp_sweep.begin # Check if we are at the value we expect, otherwise something went wrong with the ramp if abs(safe_get(self.set_param) - value) - abs(self.step/2) > abs(self.step) * 1e-4: print(f'Ramping failed (possible that the direction was changed while ramping). ' f'Expected {self.set_param.label} final value: {value}. Actual value: {safe_get(self.set_param)}. ' f'Stopping the sweep.') if self.ramp_sweep is not None: self.ramp_sweep.kill() self.ramp_sweep = None return print(f'Done ramping {self.set_param.label} to {value}') safe_set(self.set_param, value) self.setpoint = value - self.step # if self.ramp_sweep is not None and self.ramp_sweep.plotter is not None: # self.ramp_sweep.plotter.clear() if self.ramp_sweep is not None: self.ramp_sweep.kill() self.ramp_sweep = None if start_on_finish is True: self.start(persist_data=pd, ramp_to_start=False)
def ramp_to(self, value, start_on_finish=False, persist=None, multiplier=1): """ Ramps the set_param to a given value, at a rate dictated by the multiplier. Parameters --------- value: The desired starting value for the sweep. start_on_finish: Flag to determine whether to begin the sweep as soon as ramp is finished. multiplier: Factor to alter the step size, used to ramp quicker than the sweep speed. """ # Ensure we aren't currently running if self.is_ramping: print(f"Currently ramping. Finish current ramp before starting another.") return if self.is_running: print(f"Already running. Stop the sweep before ramping.") return # Check if we are already at the value curr_value = safe_get(self.set_param) if abs(value - curr_value) - abs(self.step/2) < abs(self.step) * 1e-4: # print(f"Already within {self.step} of the desired ramp value. Current value: {curr_value}, # ramp setpoint: {value}.\nSetting our setpoint directly to the ramp value.") self.done_ramping(value, start_on_finish, persist) return # Create a new sweep to ramp our outer parameter to zero self.ramp_sweep = Sweep1D(self.set_param, curr_value, value, multiplier * self.step, inter_delay=self.inter_delay, complete_func=partial(self.done_ramping, value, start_on_finish, persist), save_data=False, plot_data=self.plot_data) self.is_running = False self.is_ramping = True self.ramp_sweep.start(ramp_to_start=False) print(f'Ramping {self.set_param.label} to {value} . . . ')
def update_values(self): """ Obtains all parameter values for each sweep step. Sends data through signal for saving and/or live-plotting. Returns --------- data: A list of tuples with the new data. Each tuple is of the format (<QCoDeS Parameter>, measurement value). The tuples are passed in order of time, set_param (if applicable), then all the followed parameters. """ if not self.initialized: print("Checking the status of the magnet and switch heater.") self.magnet.leave_persistent_mode() time.sleep(1) # Set the field setpoint self.magnet.field_setpoint.set(self.setpoint) time.sleep(0.5) # Set us to go to setpoint self.magnet.activity(1) self.initialized = True data = [] t = time.monotonic() - self.t0 data.append(('time', t)) # Check our stop conditions- being at the end point if self.magnet.mode2() == 'At rest': self.is_running = False if self.save_data: self.runner.datasaver.flush_data_to_database() print( f"Done with the sweep, B={self.magnet.field.get():.2f} T, t={t:.2f} s." ) # Set status to 'hold' self.magnet.activity(0) time.sleep(1) self.magnet_initialized = False print("Done with the sweep!") if self.persistent_magnet is True: self.magnet.set_persistent() self.completed.emit() persist_param = None if self.persist_data is not None: data.append(self.persist_data) persist_param = self.persist_data[0] for i, (l, _, gain) in enumerate(self._srs): _autorange_srs(l, 3) for i, p in enumerate(self._params): if p is not persist_param: v = safe_get(p) data.append((p, v)) if self.save_data and self.is_running: self.runner.datasaver.add_result(*data) self.send_updates() # print(data) return data