def remove(self, size=None, wait=False, timeout=None, **kwargs): """ Open the slits to unblock the beam. Parameters ---------- size : float, optional Open the slits to a specific size. Defaults to `.nominal_aperture`. wait : bool, optional Wait for the status object to complete the move before returning. timeout : float, optional Maximum time to wait for the motion. If `None`, the default timeout for this positioner is used. Returns ------- Status `~ophyd.Status` object based on move completion. See Also -------- :meth:`Slits.move` """ # Use nominal_aperture by default size = size or self.nominal_aperture if size > min(self.current_aperture): return self.move(size, wait=wait, timeout=timeout, **kwargs) else: status = Status() status.set_finished() return status
def trigger(self): print("trigger!") self.next_state, self.terminal, self.reward = self.cartpole_env.execute( actions=self.action.get()) status = Status() status.set_finished() return status
def set(self, value): status = Status(obj=self, timeout=5) self.mmc.setPosition(float(value)) self.mmc.waitForDevice(self.mmc_device_name) self.position = self.mmc.getPosition() status.set_finished() return status
def trigger(self): self.status = Status() def run_count(): self.client.count(self.duration, callback=self._data_callback) self.status.set_finished() threading.Thread(target=run_count).start() return self.status
def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.tolerance = 0.002 self.readback.subscribe(self.done.get) self.setpoint.subscribe(self.done.get) self._status_obj = Status(self) # Make the default alias for the readback the name of the # positioner itself as in EpicsMotor. self.readback.name = self.name
def set(self, value, timeout=10): """Find the Home pulse in either forward or reverse direction.""" if not hasattr(self, value): raise KeyError("either 'forward' or 'reverse'" f", not: '{value}'") signal = getattr(self, value) st = Status(self, timeout=timeout) def put_cb(**kwargs): st._finished(success=True) signal.put(1, use_complete=True, callback=put_cb) st.wait(timeout=timeout) return st
def test_logger_adapter_status(): log_buffer = io.StringIO() log_stream = logging.StreamHandler(stream=log_buffer) log_stream.setFormatter(log.LogFormatter()) log.logger.addHandler(log_stream) status = Status() status.log.info("here is some info") assert log_buffer.getvalue().endswith( f"[{str(status)}] here is some info\n") status.set_finished() status.log.info("here is more info") assert log_buffer.getvalue().endswith( f"[{str(status)}] here is more info\n")
def complete(self): print('*** here in complete') time.sleep(3) self.status = Status() self.status.done = True self.status.success = True return self.status
def _get_end_status(self): """ Return a `Status` object that will be marked done when the DAQ has finished acquiring. Returns ------- end_status: `Status` """ logger.debug('Daq._get_end_status()') def finish_thread(control, status): try: logger.debug('Daq.control.end()') control.end() except RuntimeError: pass # This means we aren't running, so no need to wait self._reset_begin() status._finished(success=True) logger.debug('Marked acquisition as complete') end_status = Status(obj=self) watcher = threading.Thread(target=finish_thread, args=(self._control, end_status)) watcher.start() return end_status
def _get_end_status(self): """ Return a `Status` object that will be marked done when the DAQ has finished acquiring. This will be marked as done immediately if the daq is configured to run forever, because waiting for the end doesn't make sense in this case. Returns ------- end_status: `Status` """ logger.debug('Daq._get_end_status()') events = self._events duration = self._duration if events or duration: logger.debug('Getting end status for events=%s, duration=%s', events, duration) def finish_thread(control, status): try: logger.debug('Daq.control.end()') control.end() except RuntimeError: pass # This means we aren't running, so no need to wait self._last_stop = time.time() self._reset_begin() status.set_finished() logger.debug('Marked acquisition as complete') end_status = Status(obj=self) watcher = threading.Thread(target=finish_thread, args=(self._control, end_status)) watcher.start() return end_status else: # Configured to run forever, say we're done so we can wait for just # the other things in the scan logger.debug( 'Returning finished status for infinite run with ' 'events=%s, duration=%s', events, duration) status = Status(obj=self) status.set_finished() return status
def set(self, position, *, wait=False, timeout=None, settle_time=None, moved_cb=None): # In case nothing needs to be moved, just create a finished status status = Status() status.set_finished() # Mono if abs(self.get()-position) > mono.energy.tolerance.get(): mono_status = mono.energy.set( position, wait=wait, timeout=timeout, moved_cb=moved_cb ) status = AndStatus(status, mono_status) # Phase retarders for pr in [pr1, pr2, pr3]: if pr.tracking.get(): pr_status = pr.energy.move( position, wait=wait, timeout=timeout, moved_cb=moved_cb ) status = AndStatus(status, pr_status) # Undulator if undulator.downstream.tracking.get(): und_pos = position + undulator.downstream.energy.offset.get() und_status = undulator.downstream.energy.move( und_pos, wait=wait, timeout=timeout, moved_cb=moved_cb ) status = AndStatus(status, und_status) if wait: status_wait(status) return status
def kickoff(self): # do one step print('*** here in kickoff') self.status = Status() self.status.done = True self.status.success = True # tell the control level to start the scan self.push_socket.send_string('step') return self.status
def threaded_status(qtbot): status = Status() listener = Listener() thread = TyphonStatusThread(status) qtbot.addWidget(listener) thread.status_started.connect(listener.started) thread.status_finished.connect(listener.finished) yield listener, thread, status if thread.isRunning(): thread.quit()
def my_method(self): self.mock() status = Status() def sleep_and_finish(): time.sleep(3) status._finished() self._thread = threading.Thread(target=sleep_and_finish) self._thread.start() return status
def _status_done(self): # Create status that checks when the timestamp updates. status = Status(self.timestamp, settle_time=0.01) def _set_finished(**kwargs): status.set_finished() self.timestamp.clear_sub(_set_finished) self.timestamp.subscribe(_set_finished, event_type='value', run=False) return status
def trigger(self): # do one step self.status = Status() # tell the control level to do a step in the scan # to-do: pass it the motor positions, ideally both # requested/measured positions. # maybe don't launch the step directly here # with a daqstate command, since it would block # the event-loop? self.push_socket.send_string('running') # BeginStep self.push_socket.send_string('starting') # EndStep return self.status
def trigger(self): hdf5_st = Status() # callback to watch for the hdf5 plugin to finish, not needed for AD >= 3.3 def cb(value, **kwargs): if value == 0: hdf5_st._finished() self.hdf1.write_file.clear_sub(cb) # subscribe before we start running but don't run on current value # should not matter, but belt and suspenders. self.hdf1.write_file.subscribe(cb, run=False) st = super().trigger() return st & hdf5_st
def trigger(self): """ Called during a bluesky scan to clear the accumulated pyami data. This must be done because the pyami.Entry objects continually accumulate data forever. You can stop it by deleting the objects as in `unstage`, and you can clear it here to at least start from a clean slate. If min_duration is zero, this will return a status already marked done and successful. Otherwise, this will return a status that will be marked done after min_duration seconds. If there is a normalization detector in use and it has not been staged, it will be staged during the first trigger in a scan. """ if self._entry is None: raise RuntimeError('AmiDet %s(%s) was never staged!', self.name, self.prefix) if self._monitor is not None and self._monitor is not self: if self._monitor._staged != Staged.yes: self._monitor.unstage() self._monitor.stage() monitor_status = self._monitor.trigger() else: monitor_status = None self._entry.clear() if self.min_duration: def inner(duration, status): time.sleep(duration) status._finished() status = Status(obj=self) Thread(target=inner, args=(self.min_duration, status)).start() else: status = Status(obj=self, done=True, success=True) if monitor_status is None: return status else: return status & monitor_status
def trigger(self): """ Perform one training step: - read the next agent action from the self.action signal - execute that action in the cartpole environment - record the new state of the environment - record the agent's reward - record whether the cartpole episode has terminated - if the game has terminated reset the cartpole environment Returns ------- action_status: Status a status object in the `finished` state """ _next_state, _terminal, _reward = self.cartpole_env.execute( actions=self.action.get()) self.next_state.put(_next_state) self.terminal.put(_terminal) self.reward.put(_reward) # self.cartpole_env indicates two different terminal conditions: # terminal==1 -- the pole fell over # terminal==2 -- the maximum number of timesteps have been taken if self.terminal.get() > 0: # the game has ended, so reset the environment self.state_after_reset.put(self.cartpole_env.reset()) else: # the game is not over yet, so self.state_after_reset has no information self.state_after_reset.put( np.asarray([math.nan, math.nan, math.nan, math.nan])) action_status = Status() action_status.set_finished() return action_status
def move(self, position, wait=True, **kwargs): """ Moves the undulator energy. Currently, the backlash has to be handled within Bluesky. The actual motion is done by `self._move` using threading. kwargs are passed to PVPositioner.move(). Parameters ---------- position : float Position to move to wait : boolean, optional Flag to block the execution until motion is completed. Returns ------- status : Status """ self._status_obj = Status(self) # If position is in the the deadband -> do nothing. if abs(position - self.readback.get()) <= self.tolerance: self._status_obj.set_finished() # Otherwise -> let's move! else: thread = Thread(target=self._move, args=(position, ), kwargs=kwargs) thread.start() if wait: status_wait(self._status_obj) return self._status_obj
def kickoff(self): print('kickoff', self.name) if self._twin_adc is None: raise ValueError("ADC must have a twin") if self._twin_adc._kickoff_adc is False: self._ready_to_collect = True "Start writing data into the file." # set_and_wait(self.enable_sel, 0) st = self.enable_sel.set(0) self._kickoff_adc = True return st else: print("ADC {} was kicked off by {} already".format( self.name, self._twin_adc.name)) self._ready_to_collect = True #reset kickoff self._kickoff_adc = False #reset twin self._twin_adc._kickoff_adc = False st = Status() st._finished() return st
def set(self, value): status = Status() def write_and_wait(): # This blocks until the write is accepted, which in this case means # the write is complete. Do not use this approach for a motor or # something that takes time to execute the write. try: self._attribute_proxy.write(value) except Exception as exc: status.set_exception(exc) else: status.set_finished() threading.Thread(target=write_and_wait).start() return status
def trigger(self): # do one step self.status = Status() # tell the control level to do a step in the scan # to-do: pass it the motor positions, ideally both # requested/measured positions. # maybe don't launch the step directly here # with a daqstate command, since it would block # the event-loop? print('*** here in trigger', self.motor.position, self.motor.read()) # this dict should be put into beginstep phase1 json motor_dict = { 'motor1': self.motor.position, 'motor2': self.motor.position } self.push_socket.send_string('running') # BeginStep self.push_socket.send_string('starting') # EndStep return self.status
def bad_set(mirror, cmd=None, **kwargs): logger.info("{0}Setting Attributes. (BAD)".format(mirror.log_pref)) logger.debug("{0}Setting: CMD:{1}, {2} (BAD)".format( mirror.log_pref, cmd, kwargs)) err = 0.1 if cmd in ("IN", "OUT"): pass # If these were removable we'd implement it here elif cmd is not None: # Here is where we move the pitch motor if a value is set cmd += err mirror.sim_pitch = cmd return mirror.pitch.set(cmd) mirror.sim_x = kwargs.get('x', mirror.sim_x) mirror.sim_z = kwargs.get('z', mirror.sim_z) mirror.sim_pitch = kwargs.get('pitch', mirror.sim_pitch) for motor in mirror.motors: motor_params = motor.read() for key in kwargs.keys(): if key in motor_params: # Add error term to sets motor.set(kwargs[key] + err) return Status(done=True, success=True)
def set(self, value): """Set value of signal. Sets value of redis key to the serialized dictionary of value and timestamp. Returns ------- st : Status The status object is set to finished on successful write to redis, or an exception is set if redis.ConnectionError is raised. """ st = Status(self) try: server_time = self._r.time() ts = server_time[0] + server_time[1] / 1000000 self._r.set( self._key, self._serializer({ "value": value, "timestamp": ts }), ) except redis.ConnectionError as e: st.set_exception(e) st.set_finished() return st
def kickoff(self, events=None, duration=None, use_l3t=None, controls=None): """ Begin acquisition. This method is non-blocking. See `begin` for a description of the parameters. This method does not supply arguments for configuration parameters, it supplies arguments directly to ``pydaq.Control.begin``. It will configure before running if there are queued configuration changes. This is part of the ``bluesky`` ``Flyer`` interface. Returns ------- ready_status: ``Status`` ``Status`` that will be marked as done when the daq has begun. """ logger.debug('Daq.kickoff()') self._check_duration(duration) if self._desired_config or not self.configured: try: self.configure() except StateTransitionError: err = ('Illegal reconfigure with {} during an open run. End ' 'the current run with daq.end_run() before running ' 'with a new configuration'.format(self._desired_config)) logger.debug(err, exc_info=True) raise StateTransitionError(err) def start_thread(control, status, events, duration, use_l3t, controls): tmo = BEGIN_TIMEOUT dt = 0.1 logger.debug('Make sure daq is ready to begin') # Stop and start if we already started if self.state == 'Running': self.stop() # It can take up to 0.4s after a previous begin to be ready while tmo > 0: if self.state in ('Configured', 'Open'): break else: tmo -= dt if self.state in ('Configured', 'Open'): begin_args = self._begin_args(events, duration, use_l3t, controls) logger.debug('daq.control.begin(%s)', begin_args) control.begin(**begin_args) # Cache these so we know what the most recent begin was told self._begin = dict(events=events, duration=duration, use_l3t=use_l3t, controls=controls) logger.debug('Marking kickoff as complete') status._finished(success=True) else: logger.debug('Marking kickoff as failed') status._finished(success=False) begin_status = Status(obj=self) watcher = threading.Thread(target=start_thread, args=(self._control, begin_status, events, duration, use_l3t, controls)) watcher.start() return begin_status
class UndulatorEnergy(PVPositioner): """ Undulator energy positioner. Always move the undulator to final position from the high to low energy direction, by applying a backlash (hysteresis) correction as needed. """ # Position readback = Component(EpicsSignalRO, 'Energy', kind='hinted', auto_monitor=True) setpoint = Component(EpicsSignal, 'EnergySet', put_complete=True, auto_monitor=True, kind='normal') # Configuration deadband = Component(Signal, value=0.002, kind='config') backlash = Component(Signal, value=0.25, kind='config') offset = Component(Signal, value=0, kind='config') # Buttons actuate = Component(EpicsSignal, "Start.VAL", kind='omitted', put_complete=True) actuate_value = 3 stop_signal = Component(EpicsSignal, "Stop.VAL", kind='omitted') stop_value = 1 # TODO: Does this work!?!? # done = Component(DoneSignal, value=0, kind='omitted') # done_value = 1 done = Component(EpicsSignal, "Busy.VAL", kind="omitted") done_value = 0 def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.tolerance = 0.002 self.readback.subscribe(self.done.get) self.setpoint.subscribe(self.done.get) self._status_obj = Status(self) # Make the default alias for the readback the name of the # positioner itself as in EpicsMotor. self.readback.name = self.name @deadband.sub_value def _change_tolerance(self, value=None, **kwargs): if value: self.tolerance = value # TODO: This is unnecessary if use done EpicsSignal. # @done.sub_value # def _move_changed(self, **kwargs): # super()._move_changed(**kwargs) def move(self, position, wait=True, **kwargs): """ Moves the undulator energy. Currently, the backlash has to be handled within Bluesky. The actual motion is done by `self._move` using threading. kwargs are passed to PVPositioner.move(). Parameters ---------- position : float Position to move to wait : boolean, optional Flag to block the execution until motion is completed. Returns ------- status : Status """ self._status_obj = Status(self) # If position is in the the deadband -> do nothing. if abs(position - self.readback.get()) <= self.tolerance: self._status_obj.set_finished() # Otherwise -> let's move! else: thread = Thread(target=self._move, args=(position, ), kwargs=kwargs) thread.start() if wait: status_wait(self._status_obj) return self._status_obj def _move(self, position, **kwargs): """ Moves undulator. This is meant to run using threading, so the move will block by construction. """ # Applies backlash if needed. if position > self.readback.get(): self._move_and_wait(position + self.backlash.get(), **kwargs) # Check if stop was requested during first part of the motion. if not self._status_obj.done: self._move_and_wait(position, **kwargs) self._finish_status() def _move_and_wait(self, position, **kwargs): status = super().move(position, wait=False, **kwargs) status_wait(status) def _finish_status(self): try: self._status_obj.set_finished() except InvalidState: pass def stop(self, *, success=False): super().stop(success=success) self._finish_status()
class Counter: def __init__(self, client, name="SPEC", visualize_counters=[]): """ Create a bluesky combatible detector from SPEC counters Parameters: client: An instance of the Client class name (string): Name to be used in bluesky visualize_counters (list): List of counter names to use for best-effort visualization """ if not isinstance(client, SPECClient): raise ValueError("client needs to be instance of Client") self.client = client self.name = name self.hints = {'fields': visualize_counters} self.parent = None self.data = OrderedDict() self.duration = 1 def read(self): return self.data def describe(self): out = OrderedDict() for mne in self.data.keys(): out[mne] = { 'source': "scaler/{}/value".format(mne), 'dtype': 'number', 'shape': [], 'name': self.client.counter_names[mne] } return out def _data_callback(self, rdata): self.data = OrderedDict() for key, value in rdata.items(): self.data[key] = {'value': value, 'timestamp': tm.time()} def trigger(self): self.status = Status() def run_count(): self.client.count(self.duration, callback=self._data_callback) self.status.set_finished() threading.Thread(target=run_count).start() return self.status def read_configuration(self): return OrderedDict([('duration', { 'value': self.duration, 'timestamp': tm.time() })]) def describe_configuration(self): return OrderedDict([('duration', { 'source': "User defined", 'dtype': 'number', 'shape': [] })]) def configure(self, duration: float): """ Configure the time (in seconds) to count Parameters: duration (float): Number of seconds to count """ old = self.read_configuration() self.duration = duration return (old, self.read_configuration())
def status(qtbot): status = Status() return status
def bad_set(yag, cmd=None, **kwargs): logger.info("{0}Setting Attributes. (BAD)".format(yag.log_pref)) logger.debug("{0}Setting: CMD:{1}, {2} (BAD)".format( yag.log_pref, cmd, kwargs)) return Status(done=True, success=False)