Esempio n. 1
0
def test_epicssignal_set(put_complete):
    sim_pv = EpicsSignal(write_pv='XF:31IDA-OP{Tbl-Ax:X1}Mtr.VAL',
                         read_pv='XF:31IDA-OP{Tbl-Ax:X1}Mtr.RBV',
                         put_complete=put_complete)
    sim_pv.wait_for_connection()

    logging.getLogger('ophyd.signal').setLevel(logging.DEBUG)
    logging.getLogger('ophyd.utils.epics_pvs').setLevel(logging.DEBUG)
    print('tolerance=', sim_pv.tolerance)
    assert sim_pv.tolerance is not None

    start_pos = sim_pv.get()

    # move to +0.2 and check the status object
    target = sim_pv.get() + 0.2
    st = sim_pv.set(target, timeout=1, settle_time=0.001)
    wait(st, timeout=5)
    assert st.done
    assert st.success
    print('status 1', st)
    assert abs(target - sim_pv.get()) < 0.05

    # move back to -0.2, forcing a timeout with a low value
    target = sim_pv.get() - 0.2
    st = sim_pv.set(target, timeout=1e-6)
    time.sleep(0.1)
    print('status 2', st)
    assert st.done
    assert not st.success

    # keep the axis in position
    st = sim_pv.set(start_pos)
    wait(st, timeout=5)
Esempio n. 2
0
def test_epicssignal_set(cleanup, motor, put_complete):
    sim_pv = EpicsSignal(write_pv=motor.user_setpoint.pvname,
                         read_pv=motor.user_readback.pvname,
                         put_complete=put_complete)
    cleanup.add(sim_pv)
    sim_pv.wait_for_connection()

    logging.getLogger('ophyd.signal').setLevel(logging.DEBUG)
    logging.getLogger('ophyd.utils.epics_pvs').setLevel(logging.DEBUG)
    print('tolerance=', sim_pv.tolerance)
    assert sim_pv.tolerance is not None

    start_pos = sim_pv.get()

    # move to +0.2 and check the status object
    target = sim_pv.get() + 0.2
    st = sim_pv.set(target, timeout=1, settle_time=0.001)
    wait(st, timeout=5)
    assert st.done
    assert st.success
    print('status 1', st)
    assert abs(target - sim_pv.get()) < 0.05

    # move back to -0.2, forcing a timeout with a low value
    target = sim_pv.get() - 0.2
    st = sim_pv.set(target, timeout=1e-6)
    time.sleep(0.5)
    print('status 2', st)
    assert st.done
    assert not st.success

    # keep the axis in position
    st = sim_pv.set(start_pos)
    wait(st, timeout=5)
Esempio n. 3
0
def test_epicssignal_set(put_complete):
    sim_pv = EpicsSignal(write_pv='XF:31IDA-OP{Tbl-Ax:X1}Mtr.VAL',
                         read_pv='XF:31IDA-OP{Tbl-Ax:X1}Mtr.RBV',
                         put_complete=put_complete)
    sim_pv.wait_for_connection()

    logging.getLogger('ophyd.signal').setLevel(logging.DEBUG)
    logging.getLogger('ophyd.utils.epics_pvs').setLevel(logging.DEBUG)
    print('tolerance=', sim_pv.tolerance)
    assert sim_pv.tolerance is not None

    start_pos = sim_pv.get()

    # move to +0.2 and check the status object
    target = sim_pv.get() + 0.2
    st = sim_pv.set(target, timeout=1, settle_time=0.001)
    wait(st)
    assert st.done
    assert st.success
    print('status 1', st)
    assert abs(target - sim_pv.get()) < 0.05

    # move back to -0.2, forcing a timeout with a low value
    target = sim_pv.get() - 0.2
    st = sim_pv.set(target, timeout=1e-6)
    time.sleep(0.1)
    print('status 2', st)
    assert st.done
    assert not st.success

    # keep the axis in position
    st = sim_pv.set(start_pos)
    wait(st)
Esempio n. 4
0
 def matlabPV_FB(feedbackvalue):  #get and put timedelay signal
     matPV = EpicsSignal('LAS:FS4:VIT:matlab:04')
     org_matPV = matPV.get()  #the matlab PV value before FB
     fbvalns = feedbackvalue * 1e+9  #feedback value in ns
     fbinput = org_matPV + fbvalns  #relative to absolute value
     matPV.put(fbinput)
     return
Esempio n. 5
0
 def get_ttall():  #get timetool related signal
     ttall = EpicsSignal('XCS:TIMETOOL:TTALL')
     ttdata = ttall.get()
     current_tt = ttdata[1, ]
     ttamp = ttdata[2, ]
     ipm4val = ttdata[3, ]
     ttfwhm = ttdata[5, ]
     return current_tt, ttamp, ipm4val, ttfwhm
Esempio n. 6
0
def test_no_connection(cleanup, signal_test_ioc):
    sig = EpicsSignal('does_not_connect')
    cleanup.add(sig)

    with pytest.raises(TimeoutError):
        sig.wait_for_connection()

    sig = EpicsSignal('does_not_connect')
    cleanup.add(sig)

    with pytest.raises(TimeoutError):
        sig.put(0.0)

    with pytest.raises(TimeoutError):
        sig.get()

    sig = EpicsSignal(signal_test_ioc.pvs['read_only'], write_pv='does_not_connect')
    cleanup.add(sig)
    with pytest.raises(TimeoutError):
        sig.wait_for_connection()
Esempio n. 7
0
def test_no_connection(cleanup, signal_test_ioc):
    sig = EpicsSignal('does_not_connect')
    cleanup.add(sig)

    with pytest.raises(TimeoutError):
        sig.wait_for_connection()

    sig = EpicsSignal('does_not_connect')
    cleanup.add(sig)

    with pytest.raises(TimeoutError):
        sig.put(0.0)

    with pytest.raises(TimeoutError):
        sig.get()

    sig = EpicsSignal(signal_test_ioc.pvs['read_only'], write_pv='does_not_connect')
    cleanup.add(sig)
    with pytest.raises(TimeoutError):
        sig.wait_for_connection()
Esempio n. 8
0
class TimingChannel(object):
    def __init__(self, setpoint_PV, readback_PV, name):
        self.control_PV = EpicsSignal(setpoint_PV)  # DG/Vitara PV
        self.storage_PV = EpicsSignal(readback_PV)  # Notepad PV
        self.name = name

    def save_t0(self, val=None):
        """
        Set the t0 value directly, or save the current value as t0.
        """
        if not val:  # Take current value to be t0 if not provided
            val = self.control_PV.get()
        self.storage_PV.put(val)  # Save t0 value

    def restore_t0(self):
        """
        Restore the t0 value from the current saved value for t0.
        """
        val = self.storage_PV.get()
        self.control_PV.put(val)  # write t0 value

    def mvr(self, relval):
        """
        Move the control PV relative to it's current value.
        """
        currval = self.control_PV.get()
        self.control_PV.put(currval - relval)

    def mv(self, val):
        t0 = self.storage_PV.get()
        self.control_PV.put(t0 - val)

    def get_delay(self, verbose=False):
        delay = self.control_PV.get() - self.storage_PV.get()
        if delay > 0:
            print("X-rays arrive {} s before the optical laser".format(
                abs(delay)))
        elif delay < 0:
            print("X-rays arrive {} s after the optical laser".format(
                abs(delay)))
        else:  # delay is 0
            print("X-rays arrive at the same time as the optical laser")
        if verbose:
            control_data = (self.name, self.control_PV.pvname,
                            self.control_PV.get())
            storage_data = (self.name, self.storage_PV.pvname,
                            self.storage_PV.get())
            print("{} Control PV: {}, Control Value: {}".format(*control_data))
            print("{} Storage PV: {}, Storage Value: {}".format(*storage_data))
Esempio n. 9
0
        def tt_rough_FB(ttamp_th=0.02, ipm4_th=500, tt_window=0.05):
            fbvalue = 0  # for drift record
            while (1):
                tenshots_tt = np.zeros([
                    1,
                ])
                dlen = 0
                while (dlen < 61):
                    #ttcomm = Popen("caget XPP:TIMETOOL:TTALL",shell = True, stdout=PIPE)
                    #ttdata = (ttcomm.communicate()[0]).decode()
                    ttall = EpicsSignal('XCS:TIMETOOL:TTALL')
                    ttdata = ttall.get()

                    current_tt = ttdata[1, ]
                    ttamp = ttdata[2, ]
                    ipm4val = ttdata[3, ]
                    ttfwhm = ttdata[5, ]
                    #current_tt = float((ttdata.split(" "))[3])
                    #ttamp = float((ttdata.split(" "))[4])
                    #ipm2val = float((ttdata.split(" "))[5])
                    #ttfwhm = float((ttdata.split(" "))[7])
                    if (dlen % 10 == 0):
                        #print("tt_value",current_tt,"ttamp",ttamp,"ipm4",ipm4val)
                        print("tt_value:%0.3f" % current_tt +
                              "   ttamp:%0.3f " % ttamp +
                              "   ipm4:%d" % ipm4val)
                    if (ttamp > ttamp_th) and (ipm4val > ipm4_th) and (
                            ttfwhm < 130
                    ) and (ttfwhm > 30) and (
                            current_tt != tenshots_tt[-1, ]
                    ):  # for filtering the last one is for when DAQ is stopping
                        tenshots_tt = np.insert(tenshots_tt, dlen, current_tt)
                        dlen = np.shape(tenshots_tt)[0]
                    time.sleep(0.01)
                tenshots_tt = np.delete(tenshots_tt, 0)
                ave_tt = np.mean(tenshots_tt)
                print("Moving average of timetool value:", ave_tt)

                if np.abs(ave_tt) > tt_window:
                    ave_tt_second = -(ave_tt * 1e-12)
                    lxt.mvr(ave_tt_second)
                    print("feedback %f ps" % ave_tt)
                    fbvalue = ave_tt + fbvalue
                    #drift_log(str(fbvalue))
            return
Esempio n. 10
0
def test_epicssignal_waveform(cleanup, signal_test_ioc):
    called = False

    def update_cb(value=None, **kwargs):
        nonlocal called
        assert len(value) > 1
        called = True

    signal = EpicsSignal(signal_test_ioc.pvs['waveform'], string=True)
    cleanup.add(signal)
    signal.wait_for_connection()

    sub = signal.subscribe(update_cb, event_type=signal.SUB_VALUE)
    assert len(signal.get()) > 1
    # force the current thread to allow other threads to run to service
    # subscription
    time.sleep(0.2)
    assert called
    signal.unsubscribe(sub)
Esempio n. 11
0
class User():
    def __init__(self):
        #switch to trigger instead of full evr
        self._sync_markers = {
            0.5: 0,
            1: 1,
            5: 2,
            10: 3,
            30: 4,
            60: 5,
            120: 6,
            360: 7
        }
        self.trigger_mag = Trigger('XCS:R42:EVR:01:TRIG4', name='trigger_mag')
        self.trigger_pp = Trigger('XCS:USR:EVR:TRIG1', name='trigger_pp')
        #self.nemptyshots = actions(0, name='nemptyshots')
        #self.isfire = actions(False, name='isfire')
        #self.emptyshotspacing = actions(0, name='emptyshotspacing')
        #self.nshots = actions(0, name='nshots')
        #self.shotspacing = actions(0, name='shotspacing')
        #with safe_load('Pirani and Cold Cathode Gauges'):
        #    self.mag_pirani = BaseGauge('XCS:USR:GPI:01', name='mag_pirani')
        #    self.mag_cc = BaseGauge('XCS:USR:GCC:01', name='mag_cc')
        self.sample_temp = LakeShoreChannel('XCS:USR:TCT:02', name='A')
        self.mag_temp = LakeShoreChannel('XCS:USR:TCT:02', name='B')
        self.ttl_high = 2.0
        self.ttl_low = 0.8
        self._ready_sig = EpicsSignal('XCS:USR:ai1:0',
                                      name='User Analog Input channel 0',
                                      kind='omitted')
        self.i0_threshold = 4000  # default threshold is 0
        self.i0_avg = AvgSignal(ipm4.wave8.isum, 30, name='ipm4_sum_avg')
        self.i0_mag_retry = 10
        self._gdet_threshold_pv = EpicsSignal('XCS:VARS:J78:GDET_THRES',
                                              kind='normal')
        #self.gdet_avg_count = 30
        #self.gdet_mag_retry = 10
        #self.gdet = GasDetector('GDET:FEE1', name='gas detector')
        #self._bykik_pv = Cpt(EpicsSignal('IOC:IN20:EV01:BYKIK_ABTACT', kind = 'normal', string=True, doc='BYKIK: Abort Active')
        self._req_burst_rate = 'Full'
        self._test_burst_rate = EpicsSignal('PATT:SYS0:1:TESTBURSTRATE',
                                            name='test_burst_rate',
                                            kind='normal')
        self._mps_burst_rate = EpicsSignal('PATT:SYS0:1:MPSBURSTRATE',
                                           name='mps_burst_rate')
        # number of seconds to pause between empty and magnet
        self.pause_time = 2.
        self._min_empty_delay = 4
        self._beam_owner = EpicsSignal('ECS:SYS0:0:BEAM_OWNER_ID',
                                       name='beam_owner',
                                       kind='normal')
        self._att = att
        self.hutch = 'xcs'
        self._hutch_id = EpicsSignal('ECS:SYS0:4:HUTCH_ID',
                                     name='hutch_id',
                                     kind='normal')
        self.aliases = ['BEAM']
        self.gainmodes = ''

#use lcls.(tab) to find bykik controls

    @property
    def machine_burst_rate(self):
        if self._beam_owner.get() == self._hutch_id.get():
            self._mps_burst_rate.get()
        else:
            self._test_burst_rate.get()

    @machine_burst_rate.setter
    def machine_burst_rate(self, rate):
        if self._beam_owner.get() == self._hutch_id.get():
            self._mps_burst_rate.put(rate)
        else:
            self._test_burst_rate.put(rate)

    def check_burst_rate(self):
        if self.machine_burst_rate != self._req_burst_rate:
            print('Machine burst frequency not set to %s! - fixing...' %
                  self._req_burst_rate)
            if self._beam_owner.get() == self._hutch_id.get():
                set_and_wait(
                    self._mps_burst_rate, self._req_burst_rate
                )  #ophyd set and wait() - ophyd.utils.epics_pvs.set_and_wait
            else:
                set_and_wait(self._test_burst_rate, self._req_burst_rate)
            print('done.')

    @property
    def ready_sig(self):
        return self._ready_sig.get()

    def seq_wait(self, timeout=0, sleeptime=1.0):
        print(f'timeout = {timeout}, sleep = {sleeptime}')
        sleep(sleeptime)
        start = time.time()
        print(f'start time: {start}')
        while seq.play_status.get() != 0:
            if timeout > 0 and (time.time() - start >= timeout):
                raise ValueError('Timed out')

    def _prepare_burst(self,
                       Nshots,
                       Nbursts=1,
                       freq=120,
                       delay=None,
                       burstMode=False):
        if Nshots == 1:
            pp.flipflop()
        elif Nshots > 1:
            pp.burst()
        if Nbursts == 1:
            seq.play_mode.put(0)
        elif Nbursts > 1:
            seq.play_mode.put(1)
            seq.rep_count.put(Nbursts)
        elif Nbursts < 0:
            seq.play_mode.put(2)
        if burstMode:
            burst = Nshots + 2
        else:
            burst = 0
        if not freq == 120:
            raise (NotImplementedError('Not implemented yet!'))
        if Nshots == 1:
            if delay is None:
                delay = 3
            elif delay < 2:
                raise ValueError(
                    'Delay between flip flops of less than two is not allowed')
            ff_seq = [[84, delay, 0, burst], [86, 0, 0, burst],
                      [85, 2, 0, burst]]
        elif Nshots > 1:
            if delay is None:
                delay = 1
            elif delay < 1:
                raise ValueError(
                    'Delay between bursts of less than one is not allowed')
            ff_seq = [[84, delay, 0, burst], [86, 0, 0, burst],
                      [86, 1, 0, burst]]
            for shotNo in range(Nshots):
                ff_seq.append([85, 1, 0, burst])
                if shotNo == Nshots - 2:
                    ff_seq.append([84, 0, 0, burst])

        seq.sequence.put_seq(ff_seq)

    def _prepNonMagShots(self, nshots):
        #copy code from old pulsepicker.py file in (blinst) and change where needed or xpp experiment
        self._prepare_burst(nshots, burstMode=True)

    def _prepSpacedNonMagShots(self, nshots_per_burst, spacing):
        nshots = 1
        burstDelay = spacing - 2
        self.prepare_burst(nshots,
                           Nbursts=nshots_per_burst,
                           delay=burstDelay,
                           burstMode=True)

    def _takeNonMagShots(self):
        seq.start()

    def _prepMagShot(self, isfire, delay=1):
        pp.flipflop()
        seq.play_mode.put(0)
        ff_seq = [[84, delay, 0, 3], [86, 0, 0, 0]]
        if isfire:
            ff_seq.append([self.trigger_mag.get_eventcode(), 2, 0, 0])
            ff_seq.append([85, 0, 0, 0])
        else:
            ff_seq.append([85, 2, 0, 0])
        seq.sequence.put_seq(ff_seq)

    def _takeMagShot(self):
        seq.start()

    def _laserOn(self):
        """
        laser on by goose trigger 88
        """
        os.system('caput XCS:ECS:IOC:01:EC_11:00 88')
        os.system('caput ECS:SYS0:11:LEN 1')
        os.system('caput ECS:SYS0:11:PLYCTL 1')

    def _laserOff(self):
        """
        laser off by goose trigger 89
        """
        os.system('caput XCS:ECS:IOC:01:EC_11:00 89')
        os.system('caput ECS:SYS0:11:LEN 1')
        os.system('caput ECS:SYS0:11:PLYCTL 1')

    def _laserNormal(self):
        """
        normal on/off mode
        """
        os.system('caput XCS:ECS:IOC:01:EC_11:00 88')
        os.system('caput ECS:SYS0:11:LEN 7')
        os.system('caput ECS:SYS0:11:PLYCTL 1')

    def takeEmptyShots(self, nshots, shotspacing, use_daq=False, record=None):
        calibcontrols = {
            'nshots': ConfigVal(nshots),
            'shotspacing': ConfigVal(shotspacing)
        }

        if shotspacing > 0:
            self._prepSpacedNonMagShots(nshots, shotspacing)
        else:
            self._prepNonMagShots(nshots)
        #configure daq if being used
        if use_daq:
            daq.record = record
            daq.configure(events=0, controls=calibcontrols)
        try:
            if use_daq:
                daq.begin(events=nshots, controls=calibcontrols)
            seq.start()
            self.seq_wait()
            if use_daq:
                daq.wait()
        except KeyboardInterrupt:
            seq.stop()
        finally:
            if use_daq:
                daq.record = None
                daq.disconnect()

    def takeMagnetShot(self,
                       nemptyshots,
                       emptyshotspacing=0,
                       isfire=False,
                       record=None):
        calibcontrols = {
            'mag_isfire': ConfigVal(isfire),
            'mag_trigger_delay': self.trigger_mag.ns_delay,
            'mag_trig_width': self.trigger_mag.width,
            'mag_trig_eventcode': self.trigger_mag.eventcode,
            'nemptyshots': ConfigVal(nemptyshots),
            'emptyshotspacing': ConfigVal(emptyshotspacing)
        }
        # check the machine burst rate and set to Full rate if not
        self.check_burst_rate()
        # disable BYKIK before taking shots
        lcls.bykik_disable()
        # check if emptyshotspacing is valid
        if 0 < emptyshotspacing < self._min_empty_delay:
            raise ValueError(
                "When using spacing between empty shots it must be >= %d" %
                self._min_empty_delay)
        spacer = "*********************************"
        print("\n%s\n* Preparing to take magnet shot *\n%s\n" %
              (spacer, spacer))
        if emptyshotspacing > 0:
            mag_status = "Taking %d shots, with a spacing between each of %d beam pulses, before firing the magnet\n" % (
                nemptyshots, emptyshotspacing)
        else:
            mag_status = "Taking %d shots before firing the magnet\n" % nemptyshots
        mag_status += "Magnet pulse eventcode: %d\n" % self.trigger_mag.get_eventcode(
        )
        mag_status += "Magnet pulse trigger delay: %f\n" % self.trigger_mag.get_delay(
        )
        mag_status += "Magnet pulse trigger width: %f\n" % self.trigger_mag.get_width(
        )
        mag_status += "Magnet to be fired: %s\n" % isfire
        print(mag_status)
        try:
            daq.record = record
            daq.configure(events=0, controls=calibcontrols)
            # Pre empty shots
            if nemptyshots > 0:
                print("\nPreparing sequencer for pre-firing, non-magnet shots")
                if emptyshotspacing > 0:
                    self._prepSpacedNonMagShots(nemptyshots, emptyshotspacing)
                else:
                    self._prepNonMagShots(nemptyshots)
                    time.sleep(self.pause_time)
                daq.begin(events=nemptyshots, controls=calibcontrols)
                print("\nTaking %d pre-firing, non-magnet shots\n" %
                      nemptyshots)
                # pause after changing pulse picker mode
                time.sleep(self.pause_time)
                self._takeNonMagShots()
                print('Taking shots')
                self.seq_wait()
                print('seq finished')
                daq.wait()
                print('daq finished')
            else:
                print("\nSkipping prefiring, non-magnet shots\n")
            # pause after empty shots
            time.sleep(self.pause_time)
            print('sleep finished')
            # Fire the magnet sequence based on isfire flag
            if isfire:
                print("Start magnet firing sequence\n")
            else:
                print("Start magnet test 'firing' sequence\n")
            print("\nPreparing sequencer for magnet shot")
            if emptyshotspacing > 0:
                self._prepMagShot(isfire, emptyshotspacing)
            else:
                self._prepMagShot(isfire)
                time.sleep(self.pause_time)
            # pause after changing pulse picker mode
            time.sleep(self.pause_time)
            #checking ipm4??
            num_tries = 0
            i0_good = False
            while num_tries < self.i0_mag_retry:
                i0_val = self.i0_avg.get()
                if i0_val < self.i0_threshold:
                    print(
                        "\nNot firing magnet due to low beam current (ipm4): %.3f \n"
                        % (i0_val))
                    backoff_time = 2**num_tries
                    print("Sleeping for %d seconds...\n" % backoff_time)
                    time.sleep(backoff_time)
                    num_tries += 1
                else:
                    #ipm4 is good - fire!
                    i0_good = True
                    print("\nInitial intensity(ipm4) looks good: %.3f\n" %
                          i0_val)
                    break
            if not i0_good:
                print(
                    "Max number of i0 checks (%d) exceeded! - Abort shot attempt.\n"
                    % self.i0_mag_retry)
                return False
            # take the magnet shot
            daq.begin(events=1, controls=calibcontrols)
            print("\nTaking magnet shot\n")
            self._takeMagShot()
            self.seq_wait()
            daq.wait()
            #pause after magnet shots
            time.sleep(self.pause_time)
            #post empty shots
            if nemptyshots > 0:
                print(
                    "\nPreparing sequencer for post-firing, non-magnet shots")
                if emptyshotspacing > 0:
                    self._prepSpacedNonMagShots(nemptyshots, emptyshotspacing)
                else:
                    self._prepNonMagShots(nemptyshots)
                    time.sleep(self.pause_time)
                daq.begin(events=nemptyshots, controls=calibcontrols)
                print("\nTaking %d post-firing, non-magnet shots\n" %
                      nemptyshots)
                # pause after changing pulse picker mode
                time.sleep(self.pause_time)
                self._takeNonMagShots()
                self.seq_wait()
                daq.wait()
            else:
                print("\nSkipping post-firing, non-magnet shots\n")
            return True
        except KeyboardInterrupt:
            seq.stop()
            daq.stop()
            return False
        finally:
            daq.record = None
            daq.disconnect()
            lcls.bykik_enable()

    def takeMagnetShotMulti(self,
                            nemptyshots,
                            emptyshotspacing=0,
                            isfire=False,
                            record=None,
                            ignore_ready=False):
        """
        Takes magnet shots in a continous fashion waiting for a ready signal from the magnet controller
        """
        latch = False
        nmagshots = 0
        shotgood = True
        spacer = '##############################'
        try:
            while shotgood:
                if not latch and (self.ready_sig > self.ttl_high
                                  or ignore_ready):
                    i0_val = self.i0_avg.get()
                    if i0_val < self.i0_threshold:
                        print(
                            "\nNot firing magnet due to low beam current (ipm4): %.3f \n"
                            % (i0_val))
                        backoff_time = 1
                        print("Sleeping for %d second...\n" % backoff_time)
                        time.sleep(backoff_time)
                        continue
                    latch = True
                    print("\n%s\nStarting shot %d\n%s\n" %
                          (spacer, nmagshots, spacer))
                    start_time = time.time()
                    shotgood = self.takeMagnetShot(nemptyshots,
                                                   emptyshotspacing, isfire,
                                                   record)
                    stop_time = time.time()
                    print("\n%s\nCompleted shot %d in %.2f s\n%s\n" %
                          (spacer, nmagshots,
                           (stop_time - start_time), spacer))
                    nmagshots += 1
                if latch and (self.ready_sig < self.ttl_low or ignore_ready):
                    latch = False
                time.sleep(0.25)
        except KeyboardInterrupt:
            print('\nExiting...\n')
        finally:
            print('Took %d total magnet shots\n' % nmagshots)

    def takeRun(self, nEvents, record=None, use_l3t=False):
        daq.configure(events=120, record=record, use_l3t=use_l3t)
        daq.begin(events=nEvents)
        daq.wait()
        daq.end_run()

    def ascan(self,
              motor,
              start,
              end,
              nsteps,
              nEvents,
              record=None,
              use_l3t=False):
        self.cleanup_RE()
        currPos = motor.wm()
        daq.configure(nEvents,
                      record=record,
                      controls=[motor],
                      use_l3t=use_l3t)
        try:
            RE(scan([daq], motor, start, end, nsteps))
        except Exception:
            logger.debug('RE Exit', exc_info=True)
        finally:
            self.cleanup_RE()
        motor.mv(currPos)

    def pv_ascan(self,
                 signal,
                 start,
                 end,
                 nsteps,
                 nEvents,
                 record=None,
                 use_l3t=False):
        self.cleanup_RE()
        currPos = signal.get()
        daq.configure(nEvents,
                      record=record,
                      controls=[signal],
                      use_l3t=use_l3t)
        try:
            RE(scan([daq], signal, start, end, nsteps))
        except Exception:
            logger.debug('RE Exit', exc_info=True)
        finally:
            self.cleanup_RE()
        signal.put(currPos)

    def listscan(self, motor, posList, nEvents, record=None, use_l3t=False):
        self.cleanup_RE()
        currPos = motor.wm()
        daq.configure(nEvents,
                      record=record,
                      controls=[motor],
                      use_l3t=use_l3t)
        try:
            RE(list_scan([daq], motor, posList))
        except Exception:
            logger.debug('RE Exit', exc_info=True)
        finally:
            self.cleanup_RE()
        motor.mv(currPos)

    def list3scan(self,
                  m1,
                  p1,
                  m2,
                  p2,
                  m3,
                  p3,
                  nEvents,
                  record=None,
                  use_l3t=False):
        self.cleanup_RE()
        currPos1 = m1.wm()
        currPos2 = m2.wm()
        currPos3 = m3.wm()
        daq.configure(nEvents,
                      record=record,
                      controls=[m1, m2, m3],
                      use_l3t=use_l3t)
        try:
            RE(list_scan([daq], m1, p1, m2, p2, m3, p3))
        except Exception:
            logger.debug('RE Exit', exc_info=True)
        finally:
            self.cleanup_RE()
        m1.mv(currPos1)
        m2.mv(currPos2)
        m3.mv(currPos3)

    def dscan(self,
              motor,
              start,
              end,
              nsteps,
              nEvents,
              record=None,
              use_l3t=False):
        self.cleanup_RE()
        daq.configure(nEvents,
                      record=record,
                      controls=[motor],
                      use_l3t=use_l3t)
        currPos = motor.wm()
        try:
            RE(scan([daq], motor, currPos + start, currPos + end, nsteps))
        except Exception:
            logger.debug('RE Exit', exc_info=True)
        finally:
            self.cleanup_RE()
        motor.mv(currPos)

    def pv_dscan(self,
                 signal,
                 start,
                 end,
                 nsteps,
                 nEvents,
                 record=None,
                 use_l3t=False):
        self.cleanup_RE()
        daq.configure(nEvents,
                      record=record,
                      controls=[signal],
                      use_l3t=use_l3t)
        currPos = signal.get()
        try:
            RE(scan([daq], signal, currPos + start, currPos + end, nsteps))
        except Exception:
            logger.debug('RE Exit', exc_info=True)
        finally:
            self.cleanup_RE()
        signal.put(currPos)

    def a2scan(self,
               m1,
               a1,
               b1,
               m2,
               a2,
               b2,
               nsteps,
               nEvents,
               record=True,
               use_l3t=False):
        self.cleanup_RE()
        daq.configure(nEvents,
                      record=record,
                      controls=[m1, m2],
                      use_l3t=use_l3t)
        try:
            RE(scan([daq], m1, a1, b1, m2, a2, b2, nsteps))
        except Exception:
            logger.debug('RE Exit', exc_info=True)
        finally:
            self.cleanup_RE()

    def a3scan(self,
               m1,
               a1,
               b1,
               m2,
               a2,
               b2,
               m3,
               a3,
               b3,
               nsteps,
               nEvents,
               record=True):
        self.cleanup_RE()
        daq.configure(nEvents, record=record, controls=[m1, m2, m3])
        try:
            RE(scan([daq], m1, a1, b1, m2, a2, b2, m3, a3, b3, nsteps))
        except Exception:
            logger.debug('RE Exit', exc_info=True)
        finally:
            self.cleanup_RE()

    def delay_scan(self,
                   start,
                   end,
                   sweep_time,
                   record=None,
                   use_l3t=False,
                   duration=None):
        """Delay scan with the daq."""
        self.cleanup_RE()
        daq.configure(events=None,
                      duration=None,
                      record=record,
                      use_l3t=use_l3t,
                      controls=[lxt_fast])
        try:
            RE(
                delay_scan(daq,
                           lxt_fast, [start, end],
                           sweep_time,
                           duration=duration))
        except Exception:
            logger.debug('RE Exit', exc_info=True)
        finally:
            self.cleanup_RE()

    def empty_delay_scan(self,
                         start,
                         end,
                         sweep_time,
                         record=None,
                         use_l3t=False,
                         duration=None):
        """Delay scan without the daq."""
        self.cleanup_RE()
        #daq.configure(events=None, duration=None, record=record,
        #              use_l3t=use_l3t, controls=[lxt_fast])
        try:
            RE(
                delay_scan(None,
                           lxt_fast, [start, end],
                           sweep_time,
                           duration=duration))
        except Exception:
            logger.debug('RE Exit', exc_info=True)
        finally:
            self.cleanup_RE()

    def cleanup_RE(self):
        if not RE.state.is_idle:
            print('Cleaning up RunEngine')
            print('Stopping previous run')
            try:
                RE.stop()
            except Exception:
                pass