def _run_loop(self, first_delay=0, action_indices=(), loop_indices=(), current_values=(), **ignore_kwargs): """ the routine that actually executes the loop, and can be called from one loop to execute a nested loop first_delay: any delay carried over from an outer loop action_indices: where we are in any outer loop action arrays loop_indices: setpoint indices in any outer loops current_values: setpoint values in any outer loops signal_queue: queue to communicate with main process directly ignore_kwargs: for compatibility with other loop tasks """ # at the beginning of the loop, the time to wait after setting # the loop parameter may be increased if an outer loop requested longer delay = max(self.delay, first_delay) callables = self._compile_actions(self.actions, action_indices) t0 = time.time() last_task = t0 last_task_failed = False imax = len(self.sweep_values) for i, value in enumerate(self.sweep_values): if self.progress_interval is not None: tprint('loop %s: %d/%d (%.1f [s])' % (self.sweep_values.name, i, imax, time.time() - t0), dt=self.progress_interval, tag='outerloop') set_val = self.sweep_values.set(value) new_indices = loop_indices + (i, ) new_values = current_values + (value, ) data_to_store = {} if hasattr(self.sweep_values, "parameters"): set_name = self.data_set.action_id_map[action_indices] if hasattr(self.sweep_values, 'aggregate'): value = self.sweep_values.aggregate(*set_val) self.data_set.store(new_indices, {set_name: value}) for j, val in enumerate(set_val): set_index = action_indices + (j + 1, ) set_name = (self.data_set.action_id_map[set_index]) data_to_store[set_name] = val else: set_name = self.data_set.action_id_map[action_indices] data_to_store[set_name] = value self.data_set.store(new_indices, data_to_store) if not self._nest_first: # only wait the delay time if an inner loop will not inherit it self._wait(delay) try: for f in callables: f(first_delay=delay, loop_indices=new_indices, current_values=new_values) # after the first action, no delay is inherited delay = 0 except _QcodesBreak: break # after the first setpoint, delay reverts to the loop delay delay = self.delay # now check for a background task and execute it if it's # been long enough since the last time # don't let exceptions in the background task interrupt # the loop # if the background task fails twice consecutively, stop # executing it if self.bg_task is not None: t = time.time() if t - last_task >= self.bg_min_delay: try: self.bg_task() last_task_failed = False except Exception: if last_task_failed: self.bg_task = None last_task_failed = True last_task = t if self.progress_interval is not None: # final progress note: set dt=-1 so it *always* prints tprint('loop %s DONE: %d/%d (%.1f [s])' % (self.sweep_values.name, i + 1, imax, time.time() - t0), dt=-1, tag='outerloop') # run the background task one last time to catch the last setpoint(s) if self.bg_task is not None: self.bg_task() # the loop is finished - run the .then actions for f in self._compile_actions(self.then_actions, ()): f() # run the bg_final_task from the bg_task: if self.bg_final_task is not None: self.bg_final_task()
def _run_loop(self, first_delay=0, action_indices=(), loop_indices=(), current_values=(), **ignore_kwargs): """ the routine that actually executes the loop, and can be called from one loop to execute a nested loop first_delay: any delay carried over from an outer loop action_indices: where we are in any outer loop action arrays loop_indices: setpoint indices in any outer loops current_values: setpoint values in any outer loops signal_queue: queue to communicate with main process directly ignore_kwargs: for compatibility with other loop tasks """ # at the beginning of the loop, the time to wait after setting # the loop parameter may be increased if an outer loop requested longer delay = max(self.delay, first_delay) callables = self._compile_actions(self.actions, action_indices) n_callables = 0 for item in callables: if hasattr(item, 'param_ids'): n_callables += len(item.param_ids) else: n_callables += 1 t0 = time.time() last_task = t0 imax = len(self.sweep_values) self.last_task_failed = False for i, value in enumerate(self.sweep_values): if self.progress_interval is not None: tprint('loop %s: %d/%d (%.1f [s])' % ( self.sweep_values.name, i, imax, time.time() - t0), dt=self.progress_interval, tag='outerloop') if i: tprint("Estimated finish time: %s" % ( time.asctime(time.localtime(t0 + ((time.time() - t0) * imax / i)))), dt=self.progress_interval, tag="finish") set_val = self.sweep_values.set(value) new_indices = loop_indices + (i,) new_values = current_values + (value,) data_to_store = {} if hasattr(self.sweep_values, "parameters"): # combined parameter set_name = self.data_set.action_id_map[action_indices] if hasattr(self.sweep_values, 'aggregate'): value = self.sweep_values.aggregate(*set_val) # below is useful but too verbose even at debug # log.debug('Calling .store method of DataSet because ' # 'sweep_values.parameters exist') self.data_set.store(new_indices, {set_name: value}) # set_val list of values to set [param1_setpoint, param2_setpoint ..] for j, val in enumerate(set_val): set_index = action_indices + (j+n_callables, ) set_name = (self.data_set.action_id_map[set_index]) data_to_store[set_name] = val else: set_name = self.data_set.action_id_map[action_indices] data_to_store[set_name] = value # below is useful but too verbose even at debug # log.debug('Calling .store method of DataSet because a sweep step' # ' was taken') self.data_set.store(new_indices, data_to_store) if not self._nest_first: # only wait the delay time if an inner loop will not inherit it self._wait(delay) try: for f in callables: # below is useful but too verbose even at debug # log.debug('Going through callables at this sweep step.' # ' Calling {}'.format(f)) f(first_delay=delay, loop_indices=new_indices, current_values=new_values) # after the first action, no delay is inherited delay = 0 except _QcodesBreak: break # after the first setpoint, delay reverts to the loop delay delay = self.delay # now check for a background task and execute it if it's # been long enough since the last time # don't let exceptions in the background task interrupt # the loop # if the background task fails twice consecutively, stop # executing it if self.bg_task is not None: t = time.time() if t - last_task >= self.bg_min_delay: try: self.bg_task() except Exception: if self.last_task_failed: self.bg_task = None self.last_task_failed = True log.exception("Failed to execute bg task") last_task = t # run the background task one last time to catch the last setpoint(s) if self.bg_task is not None: log.debug('Running the background task one last time.') self.bg_task() # the loop is finished - run the .then actions #log.debug('Finishing loop, running the .then actions...') for f in self._compile_actions(self.then_actions, ()): #log.debug('...running .then action {}'.format(f)) f() # run the bg_final_task from the bg_task: if self.bg_final_task is not None: log.debug('Running the bg_final_task') self.bg_final_task()
def _run_loop(self, first_delay=0, action_indices=(), loop_indices=(), current_values=(), **ignore_kwargs): """ the routine that actually executes the loop, and can be called from one loop to execute a nested loop first_delay: any delay carried over from an outer loop action_indices: where we are in any outer loop action arrays loop_indices: setpoint indices in any outer loops current_values: setpoint values in any outer loops signal_queue: queue to communicate with main process directly ignore_kwargs: for compatibility with other loop tasks """ # at the beginning of the loop, the time to wait after setting # the loop parameter may be increased if an outer loop requested longer ActiveLoop.action_indices = action_indices delay = max(self.delay, first_delay) callables = self._compile_actions(self.actions, action_indices) self.timings = [[callable, 0] for callable in callables] n_callables = 0 for item in callables: if hasattr(item, 'param_ids'): n_callables += len(item.param_ids) else: n_callables += 1 t0 = time.time() last_task = t0 imax = len(self.sweep_values) self.last_task_failed = False for i, value in enumerate(self.sweep_values): if self.progress_interval is not None: tprint('loop %s: %d/%d (%.1f [s])' % (self.sweep_values.name, i, imax, time.time() - t0), dt=self.progress_interval, tag='outerloop') set_val = self.sweep_values.set(value) new_indices = loop_indices + (i, ) ActiveLoop.loop_indices = new_indices new_values = current_values + (value, ) data_to_store = {} if hasattr(self.sweep_values, "parameters"): # combined parameter set_name = self.data_set.action_id_map[action_indices] if hasattr(self.sweep_values, 'aggregate'): value = self.sweep_values.aggregate(*set_val) # below is useful but too verbose even at debug # log.debug('Calling .store method of DataSet because ' # 'sweep_values.parameters exist') self.data_set.store(new_indices, {set_name: value}) # set_val list of values to set [param1_setpoint, param2_setpoint ..] for j, val in enumerate(set_val): set_index = action_indices + (j + n_callables, ) set_name = (self.data_set.action_id_map[set_index]) data_to_store[set_name] = val else: set_name = self.data_set.action_id_map[action_indices] data_to_store[set_name] = value # below is useful but too verbose even at debug # log.debug('Calling .store method of DataSet because a sweep step' # ' was taken') self.data_set.store(new_indices, data_to_store) if not self._nest_first: # only wait the delay time if an inner loop will not inherit it self._wait(delay) f = None try: current_action_idx = 0 for k, f in enumerate(callables): t0 = time.time() # below is useful but too verbose even at debug # log.debug('Going through callables at this sweep step.' # ' Calling {}'.format(f)) if not isinstance(f, _Measure): # Register current action as active one, a _Measure # does this internally for each of its actions ActiveLoop.action_indices = action_indices + ( current_action_idx, ) ActiveLoop.active_action = f if ActiveLoop.interleave_actions: try: ActiveLoop.interleave_action_results = [ action() for action in ActiveLoop.interleave_actions ] print('Finished all interleaved actions') except Exception as e: traceback.print_tb(e.__traceback__) finally: ActiveLoop.interleave_actions = [] # Before continuing with a measurement, wait until pause is # removed. while self.flags['pause']: # Update is_paused here, since the pause flag may be # True, but it is still executing a previous function self.is_paused = True time.sleep(0.1) self.is_paused = False f(first_delay=delay, action_indices=action_indices, current_action_idx=current_action_idx, loop_indices=new_indices, current_values=new_values) self.timings[k][1] += time.time() - t0 if not isinstance(f, _Measure): # Increment current action idx so that loop_position is # maintained (done internally for _Measure) current_action_idx += 1 else: current_action_idx += len(f.param_ids) # after the first action, no delay is inherited delay = 0 except _QcodesBreak: if not isinstance(f, (ContinueIf, SkipIf)): break # after the first setpoint, delay reverts to the loop delay delay = self.delay # now check for a background task and execute it if it's # been long enough since the last time # don't let exceptions in the background task interrupt # the loop # if the background task fails twice consecutively, stop # executing it if self.bg_task is not None: t = time.time() if t - last_task >= self.bg_min_delay: try: self.bg_task() except _QcodesBreak: log.error('QCodes break raise, stopping') break except Exception: if self.last_task_failed: self.bg_task = None self.last_task_failed = True log.exception("Failed to execute bg task") last_task = t # run the background task one last time to catch the last setpoint(s) if self.bg_task is not None: log.debug('Running the background task one last time.') try: self.bg_task() except _QcodesBreak: pass # the loop is finished - run the .then actions #log.debug('Finishing loop, running the .then actions...') for f in self._compile_actions(self.then_actions, ()): #log.debug('...running .then action {}'.format(f)) f() # run the bg_final_task from the bg_task: if self.bg_final_task is not None: log.debug('Running the bg_final_task') self.bg_final_task()