Ejemplo n.º 1
0
    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
Ejemplo n.º 2
0
    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
Ejemplo n.º 3
0
 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
Ejemplo n.º 4
0
    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
Ejemplo n.º 5
0
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")
Ejemplo n.º 6
0
    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
Ejemplo n.º 7
0
    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.set_finished()

            status = Status(obj=self)
            Thread(target=inner, args=(self.min_duration, status)).start()
        else:
            status = Status(obj=self)
            status.set_finished()
        if monitor_status is None:
            return status
        else:
            return status & monitor_status
Ejemplo n.º 8
0
    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
Ejemplo n.º 9
0
    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
Ejemplo n.º 10
0
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())
Ejemplo n.º 11
0
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()
Ejemplo n.º 12
0
 def trigger(self):
     status = Status(obj=self, timeout=5)
     # status.add_callback(self.callback)
     self.mmc.waitForDevice(self.mmc_device_name)
     status.set_finished()
     return status
Ejemplo n.º 13
0
 def trigger(self):
     status = Status(obj=self, timeout=5)
     status.set_finished()
     return status
Ejemplo n.º 14
0
 def trigger(self):
     status = Status()
     status.set_finished()
     return status