diff --git a/eco/acquisition/daq_client.py b/eco/acquisition/daq_client.py index b271d7f..2b27cda 100644 --- a/eco/acquisition/daq_client.py +++ b/eco/acquisition/daq_client.py @@ -28,6 +28,8 @@ class Daq: self.channels["channels_BS"] = channels_BS if channels_BSCAM: self.channels["channels_BSCAM"] = channels_BSCAM + if channels_CA: + self.channels["channels_CA"] = channels_CA self.broker_address = broker_address self.timeout = timeout self.pgroup = pgroup @@ -56,6 +58,7 @@ class Daq: channels_JF=self.channels["channels_JF"].get_current_value(), channels_BS=self.channels["channels_BS"].get_current_value(), channels_BSCAM=self.channels["channels_BSCAM"].get_current_value(), + channels_CA=self.channels["channels_CA"].get_current_value(), **acq_pars, ) acquisition.acquisition_kwargs.update({"file_names": file_names}) @@ -133,7 +136,7 @@ class Daq: print(parameters) if channels_CA: parameters["pv_list"] = channels_CA - files_extensions.append("CADUMP") + files_extensions.append("PVCHANNELS") if channels_BS: parameters["channels_list"] = channels_BS files_extensions.append("BSDATA") diff --git a/eco/devices_general/detectors.py b/eco/devices_general/detectors.py index dd22a97..92a7b57 100755 --- a/eco/devices_general/detectors.py +++ b/eco/devices_general/detectors.py @@ -14,6 +14,19 @@ from datetime import datetime from ..acquisition.utilities import Acquisition from ..aliases import Alias +from ..elements import Assembly + + +class PvData(Assembly): + def __init__(self, pvname, name=None): + super().__init__(name=name) + self.pvname = pvname + self._pv = PV(pvname) + self.name = name + self.alias = Alias(self.name, channel=self.pvname, channeltype="CA") + + def get_current_value(self): + return self._pv.get() class PvDataStream: @@ -108,8 +121,6 @@ class PvDataStream: _cameraArrayTypes = ["monochrome", "rgb"] - - class CameraCA: def __init__(self, pvname, cameraArrayType="monochrome", elog=None): self.Id = pvname diff --git a/eco/elements/assembly.py b/eco/elements/assembly.py index c12749e..83fa2a5 100644 --- a/eco/elements/assembly.py +++ b/eco/elements/assembly.py @@ -2,6 +2,7 @@ from ..aliases import Alias from tabulate import tabulate import colorama from . import memory +from enum import Enum class Collection: @@ -15,16 +16,16 @@ class Collection: return self._list def append(self, obj, recursive=True, force=False): - # if force: - # if not (obj in self._list): - # self._list.append(obj) + if force: + if not (obj in self._list): + self._list.append(obj) - if hasattr(obj, self.name): + elif hasattr(obj, self.name): if isinstance(obj.__dict__[self.name], type(self)): if not recursive: # if (obj in obj.__dict__[self.name]()): - if not (obj in self._list): - self._list.append(obj) + if not (obj in self._list): + self._list.append(obj) else: for it in obj.__dict__[self.name].get_list(): if not (it in self._list): @@ -63,7 +64,7 @@ class Assembly: is_status=True, is_alias=True, view_toplevel_only=True, - **kwargs + **kwargs, ): self.__dict__[name] = foo_obj_init(*args, **kwargs, name=name) self.alias.append(self.__dict__[name].alias) @@ -139,13 +140,20 @@ class Assembly: return s def get_status_indicator_str(self): + main_name = self.name stats = self.status_indicators_collection() # stats_dict = {} tab = [] for to in stats: name = to.alias.get_full_name(base=self) value = to.get_current_value() - tab.append([name, value]) + if isinstance(value, Enum): + value = f"{value.value} ({value.name})" + try: + unit = to.unit() + except: + unit = None + tab.append([".".join([main_name, name]), value, unit]) s = tabulate(tab) return s @@ -172,7 +180,7 @@ class Assembly_old: is_status=True, is_alias=True, view_toplevel_only=True, - **kwargs + **kwargs, ): self.__dict__[name] = foo_obj_init(*args, **kwargs, name=name) self.alias.append(self.__dict__[name].alias) diff --git a/eco/fel/swissfel.py b/eco/fel/swissfel.py index 2cd504d..368e9e1 100644 --- a/eco/fel/swissfel.py +++ b/eco/fel/swissfel.py @@ -1,14 +1,21 @@ from ..elements.assembly import Assembly from ..xoptics.dcm import EcolEnergy_new from ..devices_general.adjustable import PvString +from ..devices_general.detectors import PvData class SwissFel(Assembly): def __init__(self, name=None): super().__init__(name=name) + self._append( + PvData, + "SWISSFEL-STATUS:Bunch-1-Appl-Freq-RB", + name="aramis_rep_rate", + is_status=True, + ) self._append(EcolEnergy_new, name="ecol_energy", is_status=True) self._append( - MessageBoard, name="message", is_setting=True, view_toplevel_only=False + MessageBoard, name="message", is_setting=True, is_status="recursive" ) diff --git a/eco/timing/lasertiming_edwin.py b/eco/timing/lasertiming_edwin.py index 890ddad..580200b 100644 --- a/eco/timing/lasertiming_edwin.py +++ b/eco/timing/lasertiming_edwin.py @@ -11,6 +11,7 @@ from ..devices_general.adjustable import ( spec_convenience, ) from ..aliases import append_object_to_object, Alias +from ..elements import Assembly @spec_convenience @@ -81,3 +82,108 @@ class XltEpics: def reset_current_value_to(self, value): self.offset.set_target_value((self.get_current_dial_value() - value)).wait() + + +@spec_convenience +class XltEpics(Assembly): + def __init__(self, pvname="SLAAR02-LTIM-PDLY", name="lxt_epics"): + super().__init__(name=name) + self.pvname = pvname + self.settings_collection.append(self, force=True) + self.status_indicators_collection.append(self, force=True) + self._append( + PvEnum, + self.pvname + ":SHOTDELAY", + name="oscillator_pulse_offset", + is_setting=True, + is_status=True, + ) + self._append( + PvEnum, + self.pvname + ":SHOTMOFFS_ENA", + name="modulo_offset_mode", + is_setting=True, + is_status=True, + ) + self._append( + PvRecord, + self.pvname + ":DELAY_Z_OFFS", + name="_offset", + is_setting=True, + is_status=False, + ) + self._append( + AdjustableVirtual, + [self._offset], + lambda offset: offset * 1e-12, + lambda offset: offset / 1e-12, + name="offset", + is_setting=False, + is_status=True, + ) + self._append( + PvRecord, + self.pvname + ":DELAY", + name="_set_user_delay_value", + is_setting=False, + is_status=False, + ) + self._append( + PvRecord, + self.pvname + ":P_RATIO", + name="rep_len", + is_setting=True, + is_status=True, + ) + self._append( + PvRecord, + "SIN-TIMAST-TMA:Evt-22-Freq-SP", + name="laser_frequency", + is_setting=True, + is_status=True, + ) + self._delay_dial_rb = PV("SLAAR-LGEN:DLY_OFFS2") + self.alias.append( + Alias("delay_dial_rb", "SLAAR-LGEN:DLY_OFFS2", channeltype="CA") + ) + self.waiting_for_change = PV(self.pvname + ":WAITING") + + def get_current_dial_value(self): + return self._delay_dial_rb.get() * 1e-6 + + def get_current_value(self): + return self.get_current_dial_value() - self.offset.get_current_value() + + def change_user_and_wait(self, value, check_interval=0.03): + if np.abs(value) > 0.1: + raise Exception("Very large value! This value is counted in seconds!") + if not self.waiting_for_change.get(): + raise Exception("lxt is still moving!") + self.is_moving = False + self.is_stopped = False + + def set_is_stopped(**kwargs): + old_status = self.is_moving + new_status = not bool(kwargs["value"]) + if (not new_status) and old_status: + self.is_stopped = True + self.is_moving = new_status + + self.waiting_for_change.add_callback(callback=set_is_stopped) + self._set_user_delay_value.set_target_value(value / 1e-12) + + while not self.is_stopped: + time.sleep(check_interval) + self.waiting_for_change.clear_callbacks() + + def set_target_value(self, value, hold=False): + return Changer( + target=value, + parent=self, + changer=self.change_user_and_wait, + hold=hold, + stopper=None, + ) + + def reset_current_value_to(self, value): + self.offset.set_target_value((self.get_current_dial_value() - value)).wait() \ No newline at end of file diff --git a/eco/xdiagnostics/bsen_usd.py b/eco/xdiagnostics/bsen_usd.py index ea95fba..323de49 100644 --- a/eco/xdiagnostics/bsen_usd.py +++ b/eco/xdiagnostics/bsen_usd.py @@ -84,47 +84,48 @@ class Bsen(Assembly): "SARES20-PROF141-M1", name="camera_microscope", is_setting=True, + is_status=False, ) self._append( CameraPCO, "SARES20-CAMS142-M5", name="camera_spectrometer", is_setting=True, + is_status=False, ) self._append( - PvRecord, - pvsetname = "SLAAR21-LMNP-ESBIR11:DRIVE", - pvreadbackname = "SLAAR21-LMNP-ESBIR11:MOTRBV", - name="las_in_ry", - accuracy=10, - is_setting=True + PvRecord, + pvsetname="SLAAR21-LMNP-ESBIR11:DRIVE", + pvreadbackname="SLAAR21-LMNP-ESBIR11:MOTRBV", + name="las_in_ry", + accuracy=10, + is_setting=True, ) self._append( - PvRecord, - pvsetname = "SLAAR21-LMNP-ESBIR12:DRIVE", - pvreadbackname = "SLAAR21-LMNP-ESBIR12:MOTRBV", - name="las_in_rx", - accuracy=10, - is_setting=True + PvRecord, + pvsetname="SLAAR21-LMNP-ESBIR12:DRIVE", + pvreadbackname="SLAAR21-LMNP-ESBIR12:MOTRBV", + name="las_in_rx", + accuracy=10, + is_setting=True, ) self._append( - PvRecord, - pvsetname = "SLAAR21-LMNP-ESBIR13:DRIVE", - pvreadbackname = "SLAAR21-LMNP-ESBIR13:MOTRBV", - name="las_out_rx", - accuracy=10, - is_setting=True + PvRecord, + pvsetname="SLAAR21-LMNP-ESBIR13:DRIVE", + pvreadbackname="SLAAR21-LMNP-ESBIR13:MOTRBV", + name="las_out_rx", + accuracy=10, + is_setting=True, ) self._append( - PvRecord, - pvsetname = "SLAAR21-LMNP-ESBIR14:DRIVE", - pvreadbackname = "SLAAR21-LMNP-ESBIR14:MOTRBV", - name="las_out_ry", - accuracy=10, - is_setting=True + PvRecord, + pvsetname="SLAAR21-LMNP-ESBIR14:DRIVE", + pvreadbackname="SLAAR21-LMNP-ESBIR14:MOTRBV", + name="las_out_ry", + accuracy=10, + is_setting=True, ) - def get_proc_config(self): return self.proc_client.get_pipeline_config(self.proc_pipeline)