Ejemplo n.º 1
0
class AttenuatorAramis:

    def __init__(self, ID, E_min=1500, sleeptime=1, name=None, limits=[-52, 2], pulse_picker=None):
        self.ID = ID
        self._pv_status_str = PV(ID + ":MOT2TRANS.VALD")
        self._pv_status_int = PV(ID + ":IDX_RB")
        self.E_min = E_min
        self._sleeptime = sleeptime
        self.name = name
        self.alias = Alias(name)
        self.pulse_picker = pulse_picker

        self.motors = [Motor(f"{self.ID}:MOTOR_{n+1}", name=f"motor{n+1}") for n in range(6)]
        for n, mot in enumerate(self.motors):
            self.__dict__[f"motor_{n+1}"] = mot
            self.alias.append(mot.alias)
            if limits:
                mot.set_epics_limits(*limits)


    def updateE(self, energy=None):
        while not energy:
            energy = PV("SARUN03-UIND030:FELPHOTENE").value
            energy = energy * 1000
            if energy < self.E_min:
                energy = None
                print(f"Machine photon energy is below {self.E_min} - waiting for the machine to recover")
                sleep(self._sleeptime)
        PV(self.ID + ":ENERGY").put(energy)
        print("Set energy to %s eV" % energy)

    def set_transmission(self, value, energy=None):
        self.updateE(energy)
        PV(self.ID + ":3RD_HARM_SP").put(0)
        PV(self.ID + ":TRANS_SP").put(value)

    def set_transmission_third_harmonic(self, value, energy=None):
        self.updateE(energy)
        PV(self.ID + ":3RD_HARM_SP").put(1)
        PV(self.ID + ":TRANS_SP").put(value)

    def setE(self):
        pass

    def get_transmission(self, verbose=True):
        tFun = PV(self.ID + ":TRANS_RB").value
        tTHG = PV(self.ID + ":TRANS3EDHARM_RB").value
        if verbose:
            print("Transmission Fundamental: %s THG: %s" % (tFun, tTHG))
        return tFun, tTHG

    def get_current_value(self, *args, **kwargs):
        return self.get_transmission(*args, verbose=False, **kwargs)[0]


    def set_target_value(self, value, sleeptime=10, hold=False):
        def changer():
            self.set_transmission(value)
            sleep(sleeptime)
            if self.pulse_picker:
                self.pulse_picker.open()

        return Task(changer, hold=hold)


    def get_status(self):
        s_str = self._pv_status_str.get(as_string=True)
        s_int = self._pv_status_int.get()
        return s_str, s_int

    def __repr__(self):
        t = self.get_transmission()
        s = "1st harm. transmission = %g\n" % t[0]
        s += "3rd harm. transmission = %g\n" % t[1]
        s += "Targets in beam:\n"
        s += "%s" % self.get_status()[0]
        return s

    def __call__(self, *args, **kwargs):
        self.set_transmission(*args, **kwargs)
Ejemplo n.º 2
0
 def __init__(self, ID, z_undulator=None, description=None):
     self.ID = ID
     self.targetY = Motor(ID + ":MOTOR_PROBE")
     self.cam = CameraCA(ID)
     self._led = PV(self.ID + ":LED")
     self.target = EnumWrapper(self.ID + ":PROBE_SP")
Ejemplo n.º 3
0
 def __init__(self, ID, name=None):
     self.ID = ID
     self._pv = PV(ID)
     self.name = name
     self.alias = Alias(self.name, channel=self.ID, channeltype="CA")
Ejemplo n.º 4
0
class PvDataStream:
    def __init__(self, ID, name=None):
        self.ID = ID
        self._pv = PV(ID)
        self.name = name
        self.alias = Alias(self.name, channel=self.ID, channeltype="CA")

    def collect(self, seconds=None, samples=None):
        if (not seconds) and (not samples):
            raise Exception(
                "Either a time interval or number of samples need to be defined."
            )
        try:
            self._pv.callbacks.pop(self._collection["ix_cb"])
        except:
            pass
        self._collection = {"done": False}
        self.data_collected = []
        if seconds:
            self._collection["start_time"] = time()
            self._collection["seconds"] = seconds
            stopcond = lambda: (time() - self._collection["start_time"]
                                ) > self._collection["seconds"]

            def addData(**kw):
                if not stopcond():
                    self.data_collected.append(kw["value"])
                else:
                    self._pv.callbacks.pop(self._collection["ix_cb"])
                    self._collection["done"] = True

        elif samples:
            self._collection["samples"] = samples
            stopcond = lambda: len(self.data_collected) >= self._collection[
                "samples"]

            def addData(**kw):
                self.data_collected.append(kw["value"])
                if stopcond():
                    self._pv.callbacks.pop(self._collection["ix_cb"])
                    self._collection["done"] = True

        self._collection["ix_cb"] = self._pv.add_callback(addData)
        while not self._collection["done"]:
            sleep(0.005)
        return self.data_collected

    def acquire(self, hold=False, **kwargs):
        _acquire = lambda: self.collect(**kwargs)
        return Task(_acquire, hold=hold)

    def accumulate(self, n_buffer):
        if not hasattr(self, "_accumulate"):
            self._accumulate = {"n_buffer": n_buffer, "ix": 0, "n_cb": -1}
        else:
            self._accumulate["n_buffer"] = n_buffer
            self._accumulate["ix"] = 0
        self._pv.callbacks.pop(self._accumulate["n_cb"], None)
        self._data = np.squeeze(np.zeros([n_buffer * 2, self._pv.count
                                          ])) * np.nan

        def addData(**kw):
            self._accumulate["ix"] = (self._accumulate["ix"] +
                                      1) % self._accumulate["n_buffer"]
            self._data[self._accumulate["ix"]::self.
                       _accumulate["n_buffer"]] = kw["value"]

        self._accumulate["n_cb"] = self._pv.add_callback(addData)

    def get_data(self):
        return self._data[self._accumulate["ix"] + 1:self._accumulate["ix"] +
                          1 + self._accumulate["n_buffer"]]

    data = property(get_data)
Ejemplo n.º 5
0
class CoupledDoubleCrystalMonoEnergyWithTimeCorrection(Adjustable):
    def __init__(self,
                 ID="CDCMEWTC",
                 name="Alvra DCM coupled to FEL energy with time correction",
                 limit_low=None,
                 limit_high=None):
        self.wait_time = 0.1

        self.limit_low = limit_low
        self.limit_high = limit_high

        pvname_setvalue = "SAROP11-ARAMIS:ENERGY_SP"  #_USER" #TODO: where did the _USER go?
        pvname_readback = "SAROP11-ARAMIS:ENERGY"
        #        pvname_moving   = "SGE-OP2E-ARAMIS:MOVING"
        pvname_moving = "SAROP11-ODCM105:MOVING"
        pvname_coupling = "SGE-OP2E-ARAMIS:MODE_SP"

        pv_setvalue = PV(pvname_setvalue)
        pv_readback = PV(pvname_readback)
        pv_moving = PV(pvname_moving)
        pv_coupling = PV(pvname_coupling)

        self.timing = Motor("SLAAR11-LMOT-M452:MOTOR_1")
        self.electron_energy_rb = PV("SARCL02-MBND100:P-READ")
        self.electron_energy_sv = PV("SGE-OP2E-ARAMIS:E_ENERGY_SP")

        units = pv_readback.units
        super().__init__(ID, name=name, units=units)

        self.pvnames = SimpleNamespace(setvalue=pvname_setvalue,
                                       readback=pvname_readback,
                                       moving=pvname_moving,
                                       coupling=pvname_coupling)

        self.pvs = SimpleNamespace(setvalue=pv_setvalue,
                                   readback=pv_readback,
                                   moving=pv_moving,
                                   coupling=pv_coupling)

    def get_current_value(self):
        return self.pvs.readback.get()

    def set_target_value(self, value, hold=False):
        ll = self.limit_low
        if ll is not None:
            if value < ll:
                msg = f"requested value is outside the allowed range: {value} < {ll}"
                print(msg)
                raise KeyboardInterrupt(msg)
        lh = self.limit_high
        if lh is not None:
            if value > lh:
                msg = f"requested value is outside the allowed range: {value} > {lh}"
                print(msg)
                raise KeyboardInterrupt(msg)

        wait_time = self.wait_time

        self.enable_coupling()

        current_energy = self.get_current_value()
        delta_energy = value - current_energy

        timing = self.timing
        current_delay = timing.get_current_value()
        delta_delay = convert_E_to_distance(delta_energy)
        target_delay = current_delay + delta_delay

        print(
            f"Energy = {current_energy} -> delta = {delta_energy} -> {value}")
        print(
            f"Delay  = {current_delay}  -> delta = {delta_delay}  -> {target_delay}"
        )

        timing.set_target_value(target_delay).wait()

        self.pvs.setvalue.put(value)
        sleep(3)  # wait so that the set value has changed

        print("start waiting for DCM")
        while self.is_moving():  #TODO: moving PV seems broken
            sleep(wait_time)
        print("start waiting for electron beam")
        while abs(self.electron_energy_rb.get() -
                  self.electron_energy_sv.get()) > 0.25:
            sleep(wait_time)
        sleep(wait_time)

    def is_moving(self):
        moving = self.pvs.moving.get()
        return bool(moving)

    def enable_coupling(self):
        self.pvs.coupling.put(1)

    def disable_coupling(self):
        self.pvs.coupling.put(0)

    @property
    def coupling(self):
        return self.pvs.coupling.get(as_string=True)
Ejemplo n.º 6
0
class AttenuatorAramis(Adjustable):
    def __init__(self,
                 ID,
                 z_undulator=None,
                 description=None,
                 name="Attenuator Aramis"):
        self.sleeptime = 5

        super().__init__(ID, name=name, units=None)

        self._pv_status_str = PV(ID + ":MOT2TRANS.VALD")
        self._pv_status_int = PV(ID + ":IDX_RB")

    def updateE(self, energy=None):
        if energy == None:
            energy = PV("SARUN03-UIND030:FELPHOTENE").value
            energy = energy * 1000
        PV(self.ID + ":ENERGY").put(energy)
        print("Set energy to %s eV" % energy)

    def set_transmission(self, value, energy=None):
        self.updateE(energy)
        PV(self.ID + ":3RD_HARM_SP").put(0)
        PV(self.ID + ":TRANS_SP").put(value)

    def set_transmission_third_harmonic(self, value, energy=None):
        self.updateE(energy)
        PV(self.ID + ":3RD_HARM_SP").put(1)
        PV(self.ID + ":TRANS_SP").put(value)

    def get_transmission(self, verbose=True):
        tFun = PV(self.ID + ":TRANS_RB").value
        tTHG = PV(self.ID + ":TRANS3EDHARM_RB").value
        if verbose:
            print("Transmission Fundamental: %s THG: %s" % (tFun, tTHG))
        return tFun, tTHG

    def get_current_value(self, *args, **kwargs):
        return self.get_transmission(*args, verbose=False, **kwargs)[0]

    def set_target_value(self, value):
        self.set_transmission(value)
        sleep(self.sleeptime)

    def get_status(self):
        s_str = self._pv_status_str.get(as_string=True)
        s_int = self._pv_status_int.get()
        return s_str, s_int

    def __repr__(self):
        t = self.get_transmission(verbose=False)
        s = "1st harm. transmission\t=  %g\n" % t[0]
        s += "3rd harm. transmission\t=  %g\n" % t[1]
        s += "Targets in beam:\n"
        s += "%s" % self.get_status()[0]
        return s

    def __call__(self, *args, **kwargs):
        self.set_transmission(*args, **kwargs)

    def is_moving(self):
        raise NotImplementedError