示例#1
0
def test_status_with_name(hw):
    from ophyd.status import DeviceStatus
    st = DeviceStatus(device=hw.det)
    pbar = ProgressBar([st])
    st._finished()

    st = DeviceStatus(device=hw.det)
    pbar = ProgressBar([st])
    assert pbar.delay_draw == 0.2
    time.sleep(0.25)
    st._finished()
示例#2
0
def test_status_with_name(hw):
    from ophyd.status import DeviceStatus
    st = DeviceStatus(device=hw.det)
    pbar = ProgressBar([st])
    st._finished()

    st = DeviceStatus(device=hw.det)
    pbar = ProgressBar([st])
    assert pbar.delay_draw == 0.2
    time.sleep(0.25)
    st._finished()
示例#3
0
class HxnTriggeringScaler(HxnModalBase, StruckScaler):
    def __init__(self, prefix, *, scan_type_triggers=None, **kwargs):
        super().__init__(prefix, **kwargs)

        if scan_type_triggers is None:
            scan_type_triggers = {'step': [],
                                  'fly': [],
                                  }

        self.scan_type_triggers = dict(scan_type_triggers)

        # Scaler 1 should be in output mode 1 to properly trigger
        self.stage_sigs[self.output_mode] = 'Mode 1'
        # Ensure that the scaler isn't counting in mcs mode for any reason
        self.stage_sigs[self.stop_all] = 1
        # Ensure that the scaler isn't counting
        self.stage_sigs[self.count] = 0

        self.external_signals = [self.erase_start,
                                 self.start_all,
                                 self.input_mode,
                                 self.channel_advance,
                                 self.nuse_all,
                                 self.preset_real,
                                 self.dwell]

    def mode_internal(self):
        super().mode_internal()

        settings = self.mode_settings

        # ensure that no external signals are in the stage sigs list:
        for ext_sig in self.external_signals:
            if ext_sig in self.stage_sigs:
                del self.stage_sigs[ext_sig]

        scan_type = settings.scan_type.get()

        triggers = self.scan_type_triggers[scan_type]
        settings.triggers.put(list(triggers))

        self.stop_all.put(1, wait=True)
        self.count.put(0, wait=True)
        self.stage_sigs[self.preset_time] = self.count_time.get()

    def mode_external(self):
        super().mode_external()

        if self.preset_time in self.stage_sigs:
            del self.stage_sigs[self.preset_time]

        self.stage_sigs[self.preset_real] = 0.0
        self.stage_sigs[self.dwell] = 0.0
        self.stage_sigs[self.channel_advance] = 'External'
        self.stage_sigs[self.input_mode] = 'Mode 2'
        self.stage_sigs[self.nuse_all] = self.mode_settings.total_points.get()

        self.stage_sigs[self.erase_start] = 1
        self.stage_sigs.move_to_end(self.erase_start)

    def trigger(self):
        if self._staged != Staged.yes:
            raise RuntimeError("This detector is not ready to trigger."
                               "Call the stage() method before triggering.")

        mode = self.mode_settings.mode.get()
        mode_trigger = getattr(self, 'trigger_{}'.format(mode))
        return mode_trigger()

    def trigger_internal(self):
        return super().trigger()

    def trigger_external(self):
        self._status = DeviceStatus(self)
        self._status._finished()
        return self._status
class ContinuousAcquisitionTrigger(BlueskyInterface):
    """
    This trigger mixin class records images when it is triggered.

    It expects the detector to *already* be acquiring, continously.
    """
    def __init__(self, *args, plugin_name=None, image_name=None, **kwargs):
        if plugin_name is None:
            raise ValueError("plugin name is a required keyword argument")
        super().__init__(*args, **kwargs)
        self._plugin = getattr(self, plugin_name)
        if image_name is None:
            image_name = '_'.join([self.name, 'image'])
        self._plugin.stage_sigs[self._plugin.auto_save] = 'No'
        self.cam.stage_sigs[self.cam.image_mode] = 'Continuous'
        self._plugin.stage_sigs[self._plugin.file_write_mode] = 'Capture'
        self._image_name = image_name
        self._status = None
        self._num_captured_signal = self._plugin.num_captured
        self._num_captured_signal.subscribe(self._num_captured_changed)
        self._save_started = False

    def stage(self):
        if self.cam.acquire.get() != 1:
            raise RuntimeError("The ContinuousAcuqisitionTrigger expects "
                               "the detector to already be acquiring.")
        return super().stage()
        # put logic to look up proper dark frame
        # die if none is found

    def trigger(self):
        "Trigger one acquisition."
        if not self._staged:
            raise RuntimeError("This detector is not ready to trigger."
                               "Call the stage() method before triggering.")
        self._save_started = False
        self._status = DeviceStatus(self)
        self._desired_number_of_sets = self.number_of_sets.get()
        self._plugin.num_capture.put(self._desired_number_of_sets)
        self.dispatch(self._image_name, ttime.time())
        # reset the proc buffer, this needs to be generalized
        self.proc.reset_filter.put(1)
        self._plugin.capture.put(1)  # Now the TIFF plugin is capturing.
        return self._status

    def _num_captured_changed(self, value=None, old_value=None, **kwargs):
        "This is called when the 'acquire' signal changes."
        if self._status is None:
            return
        if value == self._desired_number_of_sets:
            # This is run on a thread, so exceptions might pass silently.
            # Print and reraise so they are at least noticed.
            try:
                self.tiff.write_file.put(1)
            except Exception as e:
                print(e)
                raise
            self._save_started = True
        if value == 0 and self._save_started:
            self._status._finished()
            self._status = None
            self._save_started = False
示例#5
0
class DCMFlyer(Device):
    """DCM flyer with HC10E counter board

    :PV fly_motor : monochromator theta1
    :PV fly_motor_speed : monochromator speed [deg/sec]
    :PV fly_motor_stop : Stop monochromator theta
    :PV fly_motor_done_move : Done moving when value is '1', '0' : moving
    :PV scaler_mode : change mode. '0' : normal mode, '1' : fly(trigger) mode
    :PV encoder_steps : Flyer will accumulate counts during specified encoder steps
    :PV scaler_preset : set to '0' will result in measured values to reset
    :PV scaler_reset : reset array waveform

    :PV enc_waveform : encoder waveform
    :PV I0_waveform : I0 waveform
    :PV It_waveform : It waveform
    :PV If_waveform : If waveform
    :PV Ir_waveform : Ir waveform

    """
    fly_motor = Cpt(EpicsSignal, pv_names['DCM']["mono_theta"])
    fly_motor_speed = Cpt(EpicsSignal, pv_names['DCM']["mono_theta_speed"])
    fly_motor_stop = Cpt(EpicsSignal, pv_names['DCM']["mono_theta_stop"])
    fly_motor_done_move = Cpt(EpicsSignalRO,
                              pv_names['DCM']["mono_theta_dmov"])
    fly_motor_eres = Cpt(EpicsSignalRO, pv_names['DCM']["mono_enc_resolution"])

    scaler_mode = Cpt(EpicsSignal, pv_names['Scaler']["HC10E_Mode"])
    encoder_steps = Cpt(EpicsSignal, pv_names['Scaler']["HC10E_TrigStep"])
    scaler_preset = Cpt(EpicsSignal, pv_names['Scaler']["HC10E_Preset"])
    scaler_reset = Cpt(EpicsSignal, pv_names['Scaler']["HC10E_Reset"])

    enc_waveform = Cpt(EpicsSignalRO, pv_names['Scaler']["HC10E_ENC_WF"])
    I0_waveform = Cpt(EpicsSignalRO, pv_names['Scaler']["HC10E_I0_WF"])
    It_waveform = Cpt(EpicsSignalRO, pv_names['Scaler']["HC10E_It_WF"])
    If_waveform = Cpt(EpicsSignalRO, pv_names['Scaler']["HC10E_If_WF"])
    Ir_waveform = Cpt(EpicsSignalRO, pv_names['Scaler']["HC10E_Ir_WF"])

    def __init__(self,
                 *args,
                 target_energy=None,
                 speed=None,
                 encoder_steps=None,
                 stream_names=None,
                 **kwargs):
        super().__init__(*args, **kwargs)

        self.complete_status = None
        self._acquiring = False
        self._paused = False

        self.stream_names = stream_names
        self._collected_data = None
        self._start_energy = 8333

        # Flyer motor target position
        if target_energy is None:
            self._target_energy = 9300
        else:
            self._target_energy = target_energy

        # Flyer motor speed
        self._speed = speed

        # Encoder step size for accumulating counts
        self._encoder_step_counts = encoder_steps

        # Number of scan points to read
        self._num_of_counts = int(100)

    def energyToTheta(self, energy):
        _th = np.rad2deg(np.arcsin(_hc / (2. * _si_111 * energy)))
        return _th

    def pause(self):
        # Stop motor motion
        self.fly_motor_stop.put(1, wait=True)

    def resume(self):
        # Resume without erasing
        _th = self.energyToTheta(self._target_energy)
        self.fly_motor.put(_th, wait=True)

    def setStartEnergy(self, energy):
        self._start_energy = energy

    def setTargetEnergy(self, energy):
        self._target_energy = energy

    def setSpeed(self, speed):
        """Set Scan Speed"""
        self._speed = speed

    def setEncSteps(self, steps):
        self._encoder_step_counts = steps

    def setNumOfCounts(self, counts):
        self._num_of_counts = int(counts)

    def checkMotor(self):
        """check motor motion on a separated thread"""

        # Wait for completion
        while True:
            if self.fly_motor_done_move.get() == 0:
                # logger.error("fly_motor : {}".format(self.fly_motor_done_move.get()))
                ttime.sleep(0.1)
            else:
                # logger.error("fly_motor : {}".format(self.fly_motor_done_move.get()))
                break

        # logger.error("Done fly")
        # After the wait, we declare success
        self._acquiring = False
        self.complete_status._finished(success=True)

    def kickoff(self):
        '''Start collection

        Returns
        -------
        DeviceStatus
            This will be set to done when acquisition has begun
        '''
        # Put scaler in fly mode
        # self.scaler_mode.put(1, wait=True)

        # Set monochromator speed
        self.fly_motor_speed.put(self._speed, wait=True)

        # Set encoder step size for accumulating counts
        self.encoder_steps.put(self._encoder_step_counts, wait=True)

        # Reset scaler array waveform
        self.scaler_reset.put(1, wait=True)

        # Reset scaler counter
        self.scaler_preset.put(0, wait=True)

        # Wait For HC10E scaler reset
        ttime.sleep(.2)

        # Indicators
        self._start_time = ttime.time()
        self._acquiring = True
        self._paused = False

        # Put scaler in fly mode
        self.scaler_mode.put(1, wait=True)

        # Start motor motion to target_position asynchronously
        _th = self.energyToTheta(self._target_energy)
        self.fly_motor.put(_th, wait=False)
        ttime.sleep(0.2)

        thread = threading.Thread(target=self.checkMotor, daemon=True)
        thread.start()

        # make status object, Indicate flying has started
        self.kickoff_status = DeviceStatus(self)
        self.kickoff_status._finished(success=True)

        self.complete_status = DeviceStatus(self)

        return self.kickoff_status

    def complete(self):
        '''Wait for flying to be complete'''
        if self.complete_status is None:
            raise RuntimeError('No collection in progress')

        return self.complete_status

    def describe_collect(self):
        d = dict(source="HC10E", dtype="number", shape=(1, ))

        return {'primary': {"ENC": d, "I0": d, "It": d, "If": d, "Ir": d}}

    def collect(self):
        # Put scaler in normal mode
        self.scaler_mode.put(0, wait=False)

        # '''Retrieve all collected data'''
        if self._acquiring:
            raise RuntimeError('Acquisition still in progress. Call complete()'
                               ' first.')

        self.complete_status = None

        # Retrive waveforms from epics PVs
        ENC = self.enc_waveform.get()
        if isinstance(ENC, type(None)):
            ENC = self.enc_waveform.get()

        I0 = self.I0_waveform.get()
        if isinstance(I0, type(None)):
            I0 = self.I0_waveform.get()

        It = self.It_waveform.get()
        if isinstance(It, type(None)):
            It = self.It_waveform.get()

        If = self.If_waveform.get()
        if isinstance(If, type(None)):
            If = self.If_waveform.get()

        Ir = self.Ir_waveform.get()
        if isinstance(Ir, type(None)):
            Ir = self.Ir_waveform.get()

        if self._num_of_counts > len(ENC):
            self._num_of_counts = len(ENC)

        # logger.error("ENC : {}".format(ENC))
        # logger.error("num_of_counts : {}".format(self._num_of_counts))
        # for idx in range(len(ENC)):
        for idx in range(int(self._num_of_counts)):
            t = ttime.time()
            enc = ENC[idx]
            _i0 = I0[idx]
            _it = It[idx]
            _if = If[idx]
            _ir = Ir[idx]

            d = dict(time=t,
                     data=dict(ENC=enc, I0=_i0, It=_it, If=_if, Ir=_ir),
                     timestamps=dict(ENC=t, I0=t, It=t, If=t, Ir=t))
            yield d
示例#6
0
class HxnXspressTrigger(HxnModalBase, BlueskyInterface):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self._status = None
        self._acquisition_signal = self.settings.acquire
        self._abs_trigger_count = 0

    def unstage(self):
        ret = super().unstage()
        try:
            self._acquisition_signal.clear_sub(self._acquire_changed)
        except KeyError:
            pass

        return ret

    def _acquire_changed(self, value=None, old_value=None, **kwargs):
        "This is called when the 'acquire' signal changes."
        if self._status is None:
            return
        if (old_value == 1) and (value == 0):
            # Negative-going edge means an acquisition just finished.
            self._status._finished()

    def mode_internal(self):
        self._abs_trigger_count = 0
        self.stage_sigs[self.external_trig] = False
        self.stage_sigs[self.settings.acquire_time] = self.count_time.get()
        self._acquisition_signal.subscribe(self._acquire_changed)

    def mode_external(self):
        ms = self.mode_settings
        # NOTE: these are used in Xspress3Filestore.stage
        self.stage_sigs[self.external_trig] = True
        self.stage_sigs[self.total_points] = ms.total_points.get()
        self.stage_sigs[self.spectra_per_point] = 1
        self.stage_sigs[self.settings.acquire_time] = 0.001

        # NOTE: these are taken care of in Xspress3Filestore
        # self.stage_sigs[self.settings.trigger_mode] = 'TTL Veto Only'
        # self.stage_sigs[self.settings.num_images] = total_capture

    def _dispatch_channels(self, trigger_time):
        self._abs_trigger_count += 1
        channels = self._channels.values()
        for sn in self.read_attrs:
            ch = getattr(self, sn)
            if ch in channels:
                self.dispatch(ch.name, trigger_time)

    def trigger_internal(self):
        if self._staged != Staged.yes:
            raise RuntimeError("not staged")
        self._status = DeviceStatus(self)
        self.settings.erase.put(1)
        self._acquisition_signal.put(1, wait=False)
        self._dispatch_channels(trigger_time=time.time())
        return self._status

    def trigger_external(self):
        if self._staged != Staged.yes:
            raise RuntimeError("not staged")

        self._status = DeviceStatus(self)
        self._status._finished()
        if self.mode_settings.scan_type.get() != 'fly':
            self._dispatch_channels(trigger_time=time.time())
            # fly-scans take care of dispatching on their own

        return self._status

    def stage(self):
        staged = super().stage()
        mode = self.mode_settings.mode.get()
        if mode == 'external':
            # In external triggering mode, the devices is only triggered once
            # at stage
            self.settings.erase.put(1, wait=True)
            self._acquisition_signal.put(1, wait=False)
        return staged