Compare commits

..

5 Commits

Author SHA1 Message Date
0f41648053 test(rt-flomni): fix tests for rt-flomni
All checks were successful
CI for csaxs_bec / test (pull_request) Successful in 1m25s
CI for csaxs_bec / test (push) Successful in 1m35s
2025-12-09 16:51:24 +01:00
ec45bb4c33 fix(controller): deprecate get_device_manager() in favor of dm 2025-12-09 16:34:53 +01:00
ac8177a132 fix(controller): add controller.on to wait_for_connection for devices with socket controllers 2025-12-09 16:34:53 +01:00
36e8d87411 refactor(controller): refactor set_device_enable method from controller to set_device_read_write 2025-12-09 16:34:53 +01:00
f56a834db5 fix(controller): fix controller init for all controller instances, fix formatting 2025-12-09 16:34:53 +01:00
18 changed files with 532 additions and 432 deletions

View File

@@ -412,10 +412,11 @@ class NPointAxis(Device, PositionerBase):
sign=1, sign=1,
socket_cls=SocketIO, socket_cls=SocketIO,
tolerance: float = 0.05, tolerance: float = 0.05,
device_manager=None,
**kwargs, **kwargs,
): ):
self.controller = NPointController( self.controller = NPointController(
socket_cls=socket_cls, socket_host=host, socket_port=port socket_cls=socket_cls, socket_host=host, socket_port=port, device_manager=device_manager
) )
self.axis_Id = axis_Id self.axis_Id = axis_Id
self.sign = sign self.sign = sign

View File

@@ -175,7 +175,7 @@ class FlomniGalilMotor(Device, PositionerBase):
**kwargs, **kwargs,
): ):
self.controller = FlomniGalilController( self.controller = FlomniGalilController(
socket_cls=socket_cls, socket_host=host, socket_port=port socket_cls=socket_cls, socket_host=host, socket_port=port, device_manager=device_manager
) )
self.axis_Id = axis_Id self.axis_Id = axis_Id
self.controller.set_axis(axis=self, axis_nr=self.axis_Id_numeric) self.controller.set_axis(axis=self, axis_nr=self.axis_Id_numeric)
@@ -212,6 +212,10 @@ class FlomniGalilMotor(Device, PositionerBase):
self.low_limit_travel.put(limits[0]) self.low_limit_travel.put(limits[0])
self.high_limit_travel.put(limits[1]) self.high_limit_travel.put(limits[1])
def wait_for_connection(self, timeout: int = 30, **kwargs) -> None:
"""Wait for the device to be connected."""
self.controller.on(timeout=timeout)
@property @property
def limits(self): def limits(self):
return (self.low_limit_travel.get(), self.high_limit_travel.get()) return (self.low_limit_travel.get(), self.high_limit_travel.get())
@@ -342,10 +346,10 @@ class FlomniGalilMotor(Device, PositionerBase):
Drive an axis to the limit in a specified direction. Drive an axis to the limit in a specified direction.
Args: Args:
direction (str): Direction in which the axis should be driven to the limit. Either 'forward' or 'reverse'. direction (str): Direction in which the axis should be driven to the limit. Either 'forward' or 'reverse'.
""" """
self.controller.drive_axis_to_limit(self.axis_Id_numeric, direction) self.controller.drive_axis_to_limit(self.axis_Id_numeric, direction)
#now force position read to cache # now force position read to cache
val = self.readback.read() val = self.readback.read()
self._run_subs(sub_type=self.SUB_READBACK, value=val, timestamp=time.time()) self._run_subs(sub_type=self.SUB_READBACK, value=val, timestamp=time.time())

View File

@@ -149,7 +149,7 @@ class FuprGalilMotor(Device, PositionerBase):
**kwargs, **kwargs,
): ):
self.controller = FuprGalilController( self.controller = FuprGalilController(
socket_cls=socket_cls, socket_host=host, socket_port=port socket_cls=socket_cls, socket_host=host, socket_port=port, device_manager=device_manager
) )
self.axis_Id = axis_Id self.axis_Id = axis_Id
self.controller.set_axis(axis=self, axis_nr=self.axis_Id_numeric) self.controller.set_axis(axis=self, axis_nr=self.axis_Id_numeric)
@@ -185,6 +185,10 @@ class FuprGalilMotor(Device, PositionerBase):
self.low_limit_travel.put(limits[0]) self.low_limit_travel.put(limits[0])
self.high_limit_travel.put(limits[1]) self.high_limit_travel.put(limits[1])
def wait_for_connection(self, timeout: int = 30, **kwargs) -> None:
"""Wait for the device to be connected."""
self.controller.on(timeout=timeout)
@property @property
def limits(self): def limits(self):
return (self.low_limit_travel.get(), self.high_limit_travel.get()) return (self.low_limit_travel.get(), self.high_limit_travel.get())

View File

@@ -59,12 +59,12 @@ class GalilController(Controller):
"all_axes_referenced", "all_axes_referenced",
] ]
OKBLUE = '\033[94m' OKBLUE = "\033[94m"
OKCYAN = '\033[96m' OKCYAN = "\033[96m"
OKGREEN = '\033[92m' OKGREEN = "\033[92m"
WARNING = '\033[93m' WARNING = "\033[93m"
FAIL = '\033[91m' FAIL = "\033[91m"
ENDC = '\033[0m' ENDC = "\033[0m"
@threadlocked @threadlocked
def socket_put(self, val: str) -> None: def socket_put(self, val: str) -> None:
@@ -115,29 +115,29 @@ class GalilController(Controller):
def axis_is_referenced(self, axis_Id_numeric) -> bool: def axis_is_referenced(self, axis_Id_numeric) -> bool:
return bool(float(self.socket_put_and_receive(f"MG axisref[{axis_Id_numeric}]").strip())) return bool(float(self.socket_put_and_receive(f"MG axisref[{axis_Id_numeric}]").strip()))
def folerr_status(self, axis_Id_numeric) -> bool: def folerr_status(self, axis_Id_numeric) -> bool:
return bool(float(self.socket_put_and_receive(f"MG folaxerr[{axis_Id_numeric}]").strip())) return bool(float(self.socket_put_and_receive(f"MG folaxerr[{axis_Id_numeric}]").strip()))
def motor_temperature(self, axis_Id_numeric) -> float: def motor_temperature(self, axis_Id_numeric) -> float:
#this is only valid for omny. consider moving to ogalil # this is only valid for omny. consider moving to ogalil
voltage = float(self.socket_put_and_receive(f"MG @AN[{axis_Id_numeric+1}]").strip()) voltage = float(self.socket_put_and_receive(f"MG @AN[{axis_Id_numeric+1}]").strip())
voltage2 = float(self.socket_put_and_receive(f"MG @AN[{axis_Id_numeric+1}]").strip()) voltage2 = float(self.socket_put_and_receive(f"MG @AN[{axis_Id_numeric+1}]").strip())
if voltage2 < voltage: if voltage2 < voltage:
voltage = voltage2 voltage = voltage2
# convert from [-10,10]V to [0,300]degC # convert from [-10,10]V to [0,300]degC
temperature_degC = round((voltage+10.0) / 20.0 * 300.0, 1) temperature_degC = round((voltage + 10.0) / 20.0 * 300.0, 1)
#the motors of the parking station have a different offset # the motors of the parking station have a different offset
#the range is reduced, so if at the limit, we show an extreme value # the range is reduced, so if at the limit, we show an extreme value
if self.sock.port == 8082: if self.sock.port == 8082:
#controller 2 # controller 2
if axis_Id_numeric == 6: if axis_Id_numeric == 6:
temperature_degC = round((voltage+10.0-11.4) / 20.0 * 300.0, 1) temperature_degC = round((voltage + 10.0 - 11.4) / 20.0 * 300.0, 1)
if voltage > 9.9: if voltage > 9.9:
temperature_degC = 300 temperature_degC = 300
if axis_Id_numeric == 7: if axis_Id_numeric == 7:
temperature_degC = round((voltage+.0-12) / 20.0 * 300.0, 1) temperature_degC = round((voltage + 0.0 - 12) / 20.0 * 300.0, 1)
if voltage > 9.9: if voltage > 9.9:
temperature_degC = 300 temperature_degC = 300
return temperature_degC return temperature_degC
@@ -147,16 +147,15 @@ class GalilController(Controller):
Check if all axes are referenced. Check if all axes are referenced.
""" """
return bool(float(self.socket_put_and_receive("MG allaxref").strip())) return bool(float(self.socket_put_and_receive("MG allaxref").strip()))
def _omny_get_microstep_position(self,axis_Id): def _omny_get_microstep_position(self, axis_Id):
return float(self.socket_put_and_receive(f"MG _TD{axis_Id}").strip()) return float(self.socket_put_and_receive(f"MG _TD{axis_Id}").strip())
def _omny_get_reference_limit(self, axis_Id):
def _omny_get_reference_limit(self,axis_Id):
get_axis_no = float(self.socket_put_and_receive(f"MG frmmv").strip()) get_axis_no = float(self.socket_put_and_receive(f"MG frmmv").strip())
if(get_axis_no>0): if get_axis_no > 0:
reference_is_before = float(self.socket_put_and_receive(f"MG _FL{axis_Id}").strip()) reference_is_before = float(self.socket_put_and_receive(f"MG _FL{axis_Id}").strip())
elif(get_axis_no<0): elif get_axis_no < 0:
reference_is_before = float(self.socket_put_and_receive(f"MG _BL{axis_Id}").strip()) reference_is_before = float(self.socket_put_and_receive(f"MG _BL{axis_Id}").strip())
else: else:
reference_is_before = 0 reference_is_before = 0
@@ -187,7 +186,11 @@ class GalilController(Controller):
while self.is_axis_moving(None, axis_Id_numeric): while self.is_axis_moving(None, axis_Id_numeric):
time.sleep(0.01) time.sleep(0.01)
if verbose: if verbose:
self.get_device_manager().connector.send_client_info(f"Current microstep position {self._omny_get_microstep_position(axis_Id):.0f}", scope="drive axis to limit", show_asap=True) self.device_manager.connector.send_client_info(
f"Current microstep position {self._omny_get_microstep_position(axis_Id):.0f}",
scope="drive axis to limit",
show_asap=True,
)
time.sleep(0.5) time.sleep(0.5)
# check if we actually hit the limit # check if we actually hit the limit
@@ -201,13 +204,7 @@ class GalilController(Controller):
else: else:
print("Limit reached.") print("Limit reached.")
def get_device_manager(self): def find_reference(self, axis_Id_numeric: int, verbose=0, raise_error=1) -> None:
for axis in self._axis:
if hasattr(axis, "device_manager") and axis.device_manager:
return axis.device_manager
raise BECConfigError("Could not access the device_manager")
def find_reference(self, axis_Id_numeric: int, verbose=0, raise_error = 1) -> None:
""" """
Find the reference of an axis. Find the reference of an axis.
@@ -224,7 +221,11 @@ class GalilController(Controller):
while self.is_axis_moving(None, axis_Id_numeric): while self.is_axis_moving(None, axis_Id_numeric):
time.sleep(0.1) time.sleep(0.1)
if verbose: if verbose:
self.get_device_manager().connector.send_client_info(f"Current microstep position {self._omny_get_microstep_position(axis_Id):.0f} reference is before {self._omny_get_reference_limit(axis_Id)}", scope="find axis reference", show_asap=True) self.device_manager.connector.send_client_info(
f"Current microstep position {self._omny_get_microstep_position(axis_Id):.0f} reference is before {self._omny_get_reference_limit(axis_Id)}",
scope="find axis reference",
show_asap=True,
)
time.sleep(0.5) time.sleep(0.5)
if not self.axis_is_referenced(axis_Id_numeric): if not self.axis_is_referenced(axis_Id_numeric):
@@ -236,7 +237,6 @@ class GalilController(Controller):
logger.info(f"Successfully found reference of axis {axis_Id_numeric}.") logger.info(f"Successfully found reference of axis {axis_Id_numeric}.")
print(f"Successfully found reference of axis {axis_Id_numeric}.") print(f"Successfully found reference of axis {axis_Id_numeric}.")
def show_running_threads(self) -> None: def show_running_threads(self) -> None:
t = PrettyTable() t = PrettyTable()
t.title = f"Threads on {self.sock.host}:{self.sock.port}" t.title = f"Threads on {self.sock.host}:{self.sock.port}"
@@ -251,7 +251,7 @@ class GalilController(Controller):
def is_motor_on(self, axis_Id) -> bool: def is_motor_on(self, axis_Id) -> bool:
return not bool(float(self.socket_put_and_receive(f"MG _MO{axis_Id}").strip())) return not bool(float(self.socket_put_and_receive(f"MG _MO{axis_Id}").strip()))
def get_motor_limit_switch(self, axis_Id) -> list: def get_motor_limit_switch(self, axis_Id) -> list:
""" """
Get the status of the motor limit switches. Get the status of the motor limit switches.
@@ -269,14 +269,7 @@ class GalilController(Controller):
def describe(self) -> None: def describe(self) -> None:
t = PrettyTable() t = PrettyTable()
t.title = f"{self.__class__.__name__} on {self.sock.host}:{self.sock.port}" t.title = f"{self.__class__.__name__} on {self.sock.host}:{self.sock.port}"
field_names = [ field_names = ["Axis", "Name", "Referenced", "Motor On", "Limits", "Position"]
"Axis",
"Name",
"Referenced",
"Motor On",
"Limits",
"Position",
]
# in case of OMNY # in case of OMNY
if self.sock.host == "mpc3217.psi.ch": if self.sock.host == "mpc3217.psi.ch":
field_names.append("Temperature") field_names.append("Temperature")
@@ -286,7 +279,7 @@ class GalilController(Controller):
axis = self._axis[ax] axis = self._axis[ax]
if axis is not None: if axis is not None:
if self.sock.host == "mpc3217.psi.ch": if self.sock.host == "mpc3217.psi.ch":
#case of omny. possibly consider moving to ogalil # case of omny. possibly consider moving to ogalil
motor_on = self.is_motor_on(axis.axis_Id) motor_on = self.is_motor_on(axis.axis_Id)
if motor_on == True: if motor_on == True:
motor_on = self.WARNING + "ON" + self.ENDC motor_on = self.WARNING + "ON" + self.ENDC
@@ -299,7 +292,7 @@ class GalilController(Controller):
else: else:
folerr_status = "False" folerr_status = "False"
position = axis.readback.read().get(axis.name).get("value") position = axis.readback.read().get(axis.name).get("value")
position = f'{position:.3f}' position = f"{position:.3f}"
t.add_row( t.add_row(
[ [
f"{axis.axis_Id_numeric}/{axis.axis_Id}", f"{axis.axis_Id_numeric}/{axis.axis_Id}",
@@ -330,8 +323,6 @@ class GalilController(Controller):
self.show_running_threads() self.show_running_threads()
self.show_status_other() self.show_status_other()
def show_status_other(self) -> None: def show_status_other(self) -> None:
""" """
Show additional device-specific status information. Show additional device-specific status information.
@@ -420,7 +411,7 @@ class GalilSetpointSignal(GalilSignalBase):
while self.controller.is_thread_active(0): while self.controller.is_thread_active(0):
time.sleep(0.1) time.sleep(0.1)
#in the case of lamni, consider moving to lgalil # in the case of lamni, consider moving to lgalil
if self.parent.axis_Id_numeric == 2 and self.controller.sock.host == "mpc2680.psi.ch": if self.parent.axis_Id_numeric == 2 and self.controller.sock.host == "mpc2680.psi.ch":
try: try:
rt = self.parent.device_manager.devices[self.parent.rt] rt = self.parent.device_manager.devices[self.parent.rt]

View File

@@ -73,6 +73,7 @@ class LamniGalilController(GalilController):
air_off = bool(self.socket_put_and_receive("MG@OUT[13]")) air_off = bool(self.socket_put_and_receive("MG@OUT[13]"))
return rt_not_blocked_by_galil and air_off return rt_not_blocked_by_galil and air_off
class LamniGalilReadbackSignal(GalilSignalRO): class LamniGalilReadbackSignal(GalilSignalRO):
@retry_once @retry_once
@threadlocked @threadlocked
@@ -99,6 +100,7 @@ class LamniGalilReadbackSignal(GalilSignalRO):
logger.warning("Failed to set RT value during readback.") logger.warning("Failed to set RT value during readback.")
return val return val
class LamniGalilMotor(Device, PositionerBase): class LamniGalilMotor(Device, PositionerBase):
USER_ACCESS = ["controller", "drive_axis_to_limit", "find_reference"] USER_ACCESS = ["controller", "drive_axis_to_limit", "find_reference"]
readback = Cpt(LamniGalilReadbackSignal, signal_name="readback", kind="hinted") readback = Cpt(LamniGalilReadbackSignal, signal_name="readback", kind="hinted")
@@ -132,7 +134,7 @@ class LamniGalilMotor(Device, PositionerBase):
**kwargs, **kwargs,
): ):
self.controller = LamniGalilController( self.controller = LamniGalilController(
socket_cls=socket_cls, socket_host=host, socket_port=port socket_cls=socket_cls, socket_host=host, socket_port=port, device_manager=device_manager
) )
self.axis_Id = axis_Id self.axis_Id = axis_Id
self.controller.set_axis(axis=self, axis_nr=self.axis_Id_numeric) self.controller.set_axis(axis=self, axis_nr=self.axis_Id_numeric)
@@ -168,6 +170,10 @@ class LamniGalilMotor(Device, PositionerBase):
self.low_limit_travel.put(limits[0]) self.low_limit_travel.put(limits[0])
self.high_limit_travel.put(limits[1]) self.high_limit_travel.put(limits[1])
def wait_for_connection(self, timeout: int = 30, **kwargs) -> None:
"""Wait for the device to be connected."""
self.controller.on(timeout=timeout)
@property @property
def limits(self): def limits(self):
return (self.low_limit_travel.get(), self.high_limit_travel.get()) return (self.low_limit_travel.get(), self.high_limit_travel.get())
@@ -292,7 +298,7 @@ class LamniGalilMotor(Device, PositionerBase):
Find the reference of the axis. Find the reference of the axis.
""" """
self.controller.find_reference(self.axis_Id_numeric) self.controller.find_reference(self.axis_Id_numeric)
#now force position read to cache # now force position read to cache
val = self.readback.read() val = self.readback.read()
self._run_subs(sub_type=self.SUB_READBACK, value=val, timestamp=time.time()) self._run_subs(sub_type=self.SUB_READBACK, value=val, timestamp=time.time())
@@ -301,10 +307,10 @@ class LamniGalilMotor(Device, PositionerBase):
Drive an axis to the limit in a specified direction. Drive an axis to the limit in a specified direction.
Args: Args:
direction (str): Direction in which the axis should be driven to the limit. Either 'forward' or 'reverse'. direction (str): Direction in which the axis should be driven to the limit. Either 'forward' or 'reverse'.
""" """
self.controller.drive_axis_to_limit(self.axis_Id_numeric, direction) self.controller.drive_axis_to_limit(self.axis_Id_numeric, direction)
#now force position read to cache # now force position read to cache
val = self.readback.read() val = self.readback.read()
self._run_subs(sub_type=self.SUB_READBACK, value=val, timestamp=time.time()) self._run_subs(sub_type=self.SUB_READBACK, value=val, timestamp=time.time())

View File

@@ -46,7 +46,7 @@ class GalilMotorResolution(GalilSignalRO):
@threadlocked @threadlocked
def _socket_get(self): def _socket_get(self):
if self.controller.sock.port == 8083 and self.parent.axis_Id_numeric == 2: if self.controller.sock.port == 8083 and self.parent.axis_Id_numeric == 2:
# rotation stage # rotation stage
return 89565.8666667 return 89565.8666667
else: else:
return 51200 return 51200
@@ -69,37 +69,43 @@ class OMNYGalilReadbackSignal(GalilSignalRO):
current_pos = float(self.controller.socket_put_and_receive(f"TP{self.parent.axis_Id}")) current_pos = float(self.controller.socket_put_and_receive(f"TP{self.parent.axis_Id}"))
current_pos *= self.parent.sign current_pos *= self.parent.sign
step_mm = self.parent.motor_resolution.get() step_mm = self.parent.motor_resolution.get()
#here we introduce an offset of 25 to the rotation axis # here we introduce an offset of 25 to the rotation axis
#when setting a position this is taken into account in the controller # when setting a position this is taken into account in the controller
#that way we just do tomography from 0 to 180 degrees # that way we just do tomography from 0 to 180 degrees
if self.parent.axis_Id_numeric == 2 and self.controller.sock.port == 8083: if self.parent.axis_Id_numeric == 2 and self.controller.sock.port == 8083:
return (current_pos / step_mm)+25 return (current_pos / step_mm) + 25
else: else:
return current_pos / step_mm return current_pos / step_mm
def read(self): def read(self):
self._metadata["timestamp"] = time.time() self._metadata["timestamp"] = time.time()
val = super().read() val = super().read()
#if reading rotation stage angle # if reading rotation stage angle
if self.parent.axis_Id_numeric == 2 and self.controller.sock.port == 8083: if self.parent.axis_Id_numeric == 2 and self.controller.sock.port == 8083:
current_readback_value = val[self.parent.name]["value"] current_readback_value = val[self.parent.name]["value"]
#print (f"previous rotation angle {self.previous_rotation_angle}, current readback {current_readback_value}.") # print (f"previous rotation angle {self.previous_rotation_angle}, current readback {current_readback_value}.")
if np.fabs((self.previous_rotation_angle-current_readback_value)>10): if np.fabs((self.previous_rotation_angle - current_readback_value) > 10):
message = f"Glitch detected in rotation stage. Previous rotation angle {self.previous_rotation_angle}, current readback {current_readback_value}." message = f"Glitch detected in rotation stage. Previous rotation angle {self.previous_rotation_angle}, current readback {current_readback_value}."
print(message) print(message)
self.parent.device_manager.connector.send_client_info(message, scope="glitch detector", show_asap=True) self.parent.device_manager.connector.send_client_info(
message, scope="glitch detector", show_asap=True
)
val = super().read() val = super().read()
current_readback_value = val[self.parent.name]["value"] current_readback_value = val[self.parent.name]["value"]
if np.fabs((self.previous_rotation_angle-current_readback_value)>10): if np.fabs((self.previous_rotation_angle - current_readback_value) > 10):
message = f"Glitch detected in rotation stage second read. Previous rotation angle {self.previous_rotation_angle}, current readback {current_readback_value}. Disabling the controller." message = f"Glitch detected in rotation stage second read. Previous rotation angle {self.previous_rotation_angle}, current readback {current_readback_value}. Disabling the controller."
print(message) print(message)
self.parent.device_manager.connector.send_client_info(message, scope="glitch detector", show_asap=True) self.parent.device_manager.connector.send_client_info(
message, scope="glitch detector", show_asap=True
self.parent.device_manager.devices["osamroy"].obj.controller.socket_put_confirmed("allaxref=0") )
self.parent.device_manager.devices["osamroy"].obj.controller.socket_put_confirmed(
"allaxref=0"
)
self.parent.device_manager.devices["osamroy"].obj.enabled = False self.parent.device_manager.devices["osamroy"].obj.enabled = False
return val return val
@@ -108,13 +114,12 @@ class OMNYGalilReadbackSignal(GalilSignalRO):
try: try:
rt = self.parent.device_manager.devices["rtx"] rt = self.parent.device_manager.devices["rtx"]
if rt.enabled: if rt.enabled:
rt.obj.controller.set_rotation_angle(val[self.parent.name]["value"]-25+54) rt.obj.controller.set_rotation_angle(val[self.parent.name]["value"] - 25 + 54)
except KeyError: except KeyError:
logger.warning("Failed to set RT value during ogalil readback.") logger.warning("Failed to set RT value during ogalil readback.")
return val return val
class OMNYGalilController(GalilController): class OMNYGalilController(GalilController):
USER_ACCESS = [ USER_ACCESS = [
"describe", "describe",
@@ -132,18 +137,18 @@ class OMNYGalilController(GalilController):
"_ogalil_folerr_not_ignore", "_ogalil_folerr_not_ignore",
] ]
OKBLUE = '\033[94m' OKBLUE = "\033[94m"
OKCYAN = '\033[96m' OKCYAN = "\033[96m"
OKGREEN = '\033[92m' OKGREEN = "\033[92m"
WARNING = '\033[93m' WARNING = "\033[93m"
FAIL = '\033[91m' FAIL = "\033[91m"
ENDC = '\033[0m' ENDC = "\033[0m"
def on(self) -> None: def on(self, timeout: int = 10) -> None:
"""Open a new socket connection to the controller""" """Open a new socket connection to the controller"""
self._ogalil_switchsocket_switch_all_on() self._ogalil_switchsocket_switch_all_on()
time.sleep(0.3) time.sleep(0.3)
super().on() super().on(timeout=timeout)
def _ogalil_switchsocket(self, number: int, switch: bool): def _ogalil_switchsocket(self, number: int, switch: bool):
# number is socket number ranging from 1 to 4 # number is socket number ranging from 1 to 4
@@ -185,15 +190,16 @@ class OMNYGalilController(GalilController):
self.socket_put_confirmed("IgNoFol=1") self.socket_put_confirmed("IgNoFol=1")
self.socket_put_confirmed("XQ#STOP,1") self.socket_put_confirmed("XQ#STOP,1")
def _ogalil_set_axis_to_pos_wo_reference_search(
def _ogalil_set_axis_to_pos_wo_reference_search(self, axis_id_numeric, axis_id, pos_mm, motor_resolution, motor_sign): self, axis_id_numeric, axis_id, pos_mm, motor_resolution, motor_sign
):
self.socket_put_confirmed("IgNoFol=1") self.socket_put_confirmed("IgNoFol=1")
# pos_mm = pos_encoder / motor_resolution # pos_mm = pos_encoder / motor_resolution
pos_encoder = pos_mm * motor_resolution * motor_sign pos_encoder = pos_mm * motor_resolution * motor_sign
#print(motor_resolution) # print(motor_resolution)
self.socket_put_confirmed(f"DE{axis_id}={pos_encoder:.0f}") self.socket_put_confirmed(f"DE{axis_id}={pos_encoder:.0f}")
self.socket_put_confirmed(f"DP{axis_id}=_TP{axis_id}*ratio[{axis_id_numeric:.0f}]") self.socket_put_confirmed(f"DP{axis_id}=_TP{axis_id}*ratio[{axis_id_numeric:.0f}]")
@@ -203,7 +209,6 @@ class OMNYGalilController(GalilController):
self._ogalil_folerr_not_ignore() self._ogalil_folerr_not_ignore()
def _ogalil_folerr_not_ignore(self): def _ogalil_folerr_not_ignore(self):
self.socket_put_confirmed("IgNoFol=0") self.socket_put_confirmed("IgNoFol=0")
@@ -240,7 +245,18 @@ class OMNYGalilController(GalilController):
class OMNYGalilMotor(Device, PositionerBase): class OMNYGalilMotor(Device, PositionerBase):
USER_ACCESS = ["controller", "find_reference", "omny_osamx_to_scan_center", "drive_axis_to_limit", "_ogalil_folerr_reset_and_ignore", "_ogalil_set_axis_to_pos_wo_reference_search", "get_motor_limit_switch", "axis_is_referenced", "get_motor_temperature", "folerr_status"] USER_ACCESS = [
"controller",
"find_reference",
"omny_osamx_to_scan_center",
"drive_axis_to_limit",
"_ogalil_folerr_reset_and_ignore",
"_ogalil_set_axis_to_pos_wo_reference_search",
"get_motor_limit_switch",
"axis_is_referenced",
"get_motor_temperature",
"folerr_status",
]
readback = Cpt(OMNYGalilReadbackSignal, signal_name="readback", kind="hinted") readback = Cpt(OMNYGalilReadbackSignal, signal_name="readback", kind="hinted")
user_setpoint = Cpt(GalilSetpointSignal, signal_name="setpoint") user_setpoint = Cpt(GalilSetpointSignal, signal_name="setpoint")
motor_resolution = Cpt(GalilMotorResolution, signal_name="resolution", kind="config") motor_resolution = Cpt(GalilMotorResolution, signal_name="resolution", kind="config")
@@ -272,7 +288,7 @@ class OMNYGalilMotor(Device, PositionerBase):
**kwargs, **kwargs,
): ):
self.controller = OMNYGalilController( self.controller = OMNYGalilController(
socket_cls=socket_cls, socket_host=host, socket_port=port socket_cls=socket_cls, socket_host=host, socket_port=port, device_manager=device_manager
) )
self.axis_Id = axis_Id self.axis_Id = axis_Id
self.controller.set_axis(axis=self, axis_nr=self.axis_Id_numeric) self.controller.set_axis(axis=self, axis_nr=self.axis_Id_numeric)
@@ -308,6 +324,10 @@ class OMNYGalilMotor(Device, PositionerBase):
self.low_limit_travel.put(limits[0]) self.low_limit_travel.put(limits[0])
self.high_limit_travel.put(limits[1]) self.high_limit_travel.put(limits[1])
def wait_for_connection(self, timeout: int = 30, **kwargs) -> None:
"""Wait for the device to be connected."""
self.controller.on(timeout=timeout)
@property @property
def limits(self): def limits(self):
return (self.low_limit_travel.get(), self.high_limit_travel.get()) return (self.low_limit_travel.get(), self.high_limit_travel.get())
@@ -433,8 +453,10 @@ class OMNYGalilMotor(Device, PositionerBase):
def _ogalil_set_axis_to_pos_wo_reference_search(self, pos_mm): def _ogalil_set_axis_to_pos_wo_reference_search(self, pos_mm):
motor_resolution = self.motor_resolution.get() motor_resolution = self.motor_resolution.get()
self.controller._ogalil_set_axis_to_pos_wo_reference_search(self.axis_Id_numeric, self.axis_Id, pos_mm, motor_resolution, self.sign) self.controller._ogalil_set_axis_to_pos_wo_reference_search(
#now force position read to cache self.axis_Id_numeric, self.axis_Id, pos_mm, motor_resolution, self.sign
)
# now force position read to cache
val = self.readback.read() val = self.readback.read()
self._run_subs(sub_type=self.SUB_READBACK, value=val, timestamp=time.time()) self._run_subs(sub_type=self.SUB_READBACK, value=val, timestamp=time.time())
@@ -442,9 +464,9 @@ class OMNYGalilMotor(Device, PositionerBase):
""" """
Find the reference of the axis. Find the reference of the axis.
""" """
verbose=1 verbose = 1
self.controller.find_reference(self.axis_Id_numeric, verbose, raise_error) self.controller.find_reference(self.axis_Id_numeric, verbose, raise_error)
#now force position read to cache # now force position read to cache
val = self.readback.read() val = self.readback.read()
self._run_subs(sub_type=self.SUB_READBACK, value=val, timestamp=time.time()) self._run_subs(sub_type=self.SUB_READBACK, value=val, timestamp=time.time())
@@ -453,10 +475,10 @@ class OMNYGalilMotor(Device, PositionerBase):
Drive an axis to the limit in a specified direction. Drive an axis to the limit in a specified direction.
Args: Args:
direction (str): Direction in which the axis should be driven to the limit. Either 'forward' or 'reverse'. direction (str): Direction in which the axis should be driven to the limit. Either 'forward' or 'reverse'.
""" """
self.controller.drive_axis_to_limit(self.axis_Id_numeric, direction, verbose=1) self.controller.drive_axis_to_limit(self.axis_Id_numeric, direction, verbose=1)
#now force position read to cache # now force position read to cache
val = self.readback.read() val = self.readback.read()
self._run_subs(sub_type=self.SUB_READBACK, value=val, timestamp=time.time()) self._run_subs(sub_type=self.SUB_READBACK, value=val, timestamp=time.time())
@@ -487,29 +509,31 @@ class OMNYGalilMotor(Device, PositionerBase):
def omny_osamx_to_scan_center(self, cenx): def omny_osamx_to_scan_center(self, cenx):
if self.controller.sock.port == 8082 and self.axis_Id_numeric == 0: if self.controller.sock.port == 8082 and self.axis_Id_numeric == 0:
# get last setpoint # get last setpoint
osamx = self.device_manager.devices["osamx"] osamx = self.device_manager.devices["osamx"]
osamx_current_setpoint = osamx.obj.readback.get() osamx_current_setpoint = osamx.obj.readback.get()
omny_samx_in = self._get_user_param_safe("osamx","in") omny_samx_in = self._get_user_param_safe("osamx", "in")
if np.fabs(osamx_current_setpoint-(omny_samx_in+cenx/1000)) > 0.025: if np.fabs(osamx_current_setpoint - (omny_samx_in + cenx / 1000)) > 0.025:
message=f"Moving osamx to scan center. new osamx target {omny_samx_in+cenx/1000:.3f}." message = (
logger.info(message) f"Moving osamx to scan center. new osamx target {omny_samx_in+cenx/1000:.3f}."
)
logger.info(message)
osamx.read_only = False osamx.read_only = False
#osamx.controller.("osamx", "controller.socket_put_confirmed('axspeed[0]=1000')") # osamx.controller.("osamx", "controller.socket_put_confirmed('axspeed[0]=1000')")
osamx.set(omny_samx_in+cenx/1000) osamx.set(omny_samx_in + cenx / 1000)
time.sleep(0.1) time.sleep(0.1)
while(osamx.motor_is_moving.get()): while osamx.motor_is_moving.get():
time.sleep(0.05) time.sleep(0.05)
osamx.read_only = True osamx.read_only = True
time.sleep(2) time.sleep(2)
rt = self.device_manager.devices["rtx"] rt = self.device_manager.devices["rtx"]
if rt.enabled: if rt.enabled:
rt.obj.controller.laser_tracker_on() rt.obj.controller.laser_tracker_on()
rt.obj.controller.laser_tracker_check_and_wait_for_signalstrength() rt.obj.controller.laser_tracker_check_and_wait_for_signalstrength()
def folerr_status(self) -> bool: def folerr_status(self) -> bool:
return self.controller.folerr_status(self.axis_Id_numeric) return self.controller.folerr_status(self.axis_Id_numeric)
def stop(self, *, success=False): def stop(self, *, success=False):
self.controller.stop_all_axes() self.controller.stop_all_axes()
return super().stop(success=success) return super().stop(success=success)

View File

@@ -52,33 +52,12 @@ class GalilController(Controller):
"fly_grid_scan", "fly_grid_scan",
"read_encoder_position", "read_encoder_position",
] ]
_axes_per_controller = 8
def __init__( def on(self, timeout: int = 10) -> None:
self,
*,
name="GalilController",
kind=None,
parent=None,
socket=None,
attr_name="",
labels=None,
):
if not hasattr(self, "_initialized") or not self._initialized:
self._galil_axis_per_controller = 8
self._axis = [None for axis_num in range(self._galil_axis_per_controller)]
super().__init__(
name=name,
socket=socket,
attr_name=attr_name,
parent=parent,
labels=labels,
kind=kind,
)
def on(self, controller_num=0) -> None:
"""Open a new socket connection to the controller""" """Open a new socket connection to the controller"""
if not self.connected: if not self.connected:
self.sock.open() self.sock.open(timeout=timeout)
self.connected = True self.connected = True
else: else:
logger.info("The connection has already been established.") logger.info("The connection has already been established.")
@@ -165,11 +144,11 @@ class GalilController(Controller):
def show_running_threads(self) -> None: def show_running_threads(self) -> None:
t = PrettyTable() t = PrettyTable()
t.title = f"Threads on {self.sock.host}:{self.sock.port}" t.title = f"Threads on {self.sock.host}:{self.sock.port}"
t.field_names = [str(ax) for ax in range(self._galil_axis_per_controller)] t.field_names = [str(ax) for ax in range(self._axes_per_controller)]
t.add_row( t.add_row(
[ [
"active" if self.is_thread_active(t) else "inactive" "active" if self.is_thread_active(t) else "inactive"
for t in range(self._galil_axis_per_controller) for t in range(self._axes_per_controller)
] ]
) )
print(t) print(t)
@@ -199,7 +178,7 @@ class GalilController(Controller):
"Limits", "Limits",
"Position", "Position",
] ]
for ax in range(self._galil_axis_per_controller): for ax in range(self._axes_per_controller):
axis = self._axis[ax] axis = self._axis[ax]
if axis is not None: if axis is not None:
t.add_row( t.add_row(
@@ -516,7 +495,9 @@ class SGalilMotor(Device, PositionerBase):
): ):
self.axis_Id = axis_Id self.axis_Id = axis_Id
self.sign = sign self.sign = sign
self.controller = GalilController(socket=socket_cls(host=host, port=port)) self.controller = GalilController(
socket_cls=socket_cls, socket_host=host, socket_port=port, device_manager=device_manager
)
self.controller.set_axis(axis=self, axis_nr=self.axis_Id_numeric) self.controller.set_axis(axis=self, axis_nr=self.axis_Id_numeric)
self.tolerance = kwargs.pop("tolerance", 0.5) self.tolerance = kwargs.pop("tolerance", 0.5)
self.device_mapping = kwargs.pop("device_mapping", {}) self.device_mapping = kwargs.pop("device_mapping", {})
@@ -549,6 +530,10 @@ class SGalilMotor(Device, PositionerBase):
self.low_limit_travel.put(limits[0]) self.low_limit_travel.put(limits[0])
self.high_limit_travel.put(limits[1]) self.high_limit_travel.put(limits[1])
def wait_for_connection(self, timeout: int = 30, **kwargs) -> None:
"""Wait for the device to be connected."""
self.controller.on(timeout=timeout)
@property @property
def limits(self): def limits(self):
return (self.low_limit_travel.get(), self.high_limit_travel.get()) return (self.low_limit_travel.get(), self.high_limit_travel.get())

View File

@@ -57,6 +57,7 @@ class RtFlomniController(Controller):
socket_cls=None, socket_cls=None,
socket_host=None, socket_host=None,
socket_port=None, socket_port=None,
device_manager=None,
attr_name="", attr_name="",
parent=None, parent=None,
labels=None, labels=None,
@@ -67,6 +68,7 @@ class RtFlomniController(Controller):
socket_cls=socket_cls, socket_cls=socket_cls,
socket_host=socket_host, socket_host=socket_host,
socket_port=socket_port, socket_port=socket_port,
device_manager=device_manager,
attr_name=attr_name, attr_name=attr_name,
parent=parent, parent=parent,
labels=labels, labels=labels,
@@ -126,15 +128,15 @@ class RtFlomniController(Controller):
while not self.slew_rate_limiters_on_target() or np.abs(self.pid_y()) > 0.1: while not self.slew_rate_limiters_on_target() or np.abs(self.pid_y()) > 0.1:
time.sleep(0.05) time.sleep(0.05)
self.get_device_manager().devices.rty.update_user_parameter({"tomo_additional_offsety": 0}) self.device_manager.devices.rty.update_user_parameter({"tomo_additional_offsety": 0})
self.clear_trajectory_generator() self.clear_trajectory_generator()
self.laser_tracker_on() self.laser_tracker_on()
# move to 0. FUPR will set the rotation angle during readout # move to 0. FUPR will set the rotation angle during readout
self.get_device_manager().devices.fsamroy.obj.move(0, wait=True) self.device_manager.devices.fsamroy.obj.move(0, wait=True)
fsamx = self.get_device_manager().devices.fsamx fsamx = self.device_manager.devices.fsamx
fsamx.obj.pid_x_correction = 0 fsamx.obj.pid_x_correction = 0
fsamx.obj.controller.socket_put_confirmed("axspeed[4]=0.1*stppermm[4]") fsamx.obj.controller.socket_put_confirmed("axspeed[4]=0.1*stppermm[4]")
@@ -164,18 +166,18 @@ class RtFlomniController(Controller):
self.show_cyclic_error_compensation() self.show_cyclic_error_compensation()
self.rt_pid_voltage = self.get_pid_x() self.rt_pid_voltage = self.get_pid_x()
rtx = self.get_device_manager().devices.rtx rtx = self.device_manager.devices.rtx
rtx.update_user_parameter({"rt_pid_voltage": self.rt_pid_voltage}) rtx.update_user_parameter({"rt_pid_voltage": self.rt_pid_voltage})
self.set_device_enabled("fsamx", False) self.set_device_read_write("fsamx", False)
self.set_device_enabled("fsamy", False) self.set_device_read_write("fsamy", False)
self.set_device_enabled("foptx", False) self.set_device_read_write("foptx", False)
self.set_device_enabled("fopty", False) self.set_device_read_write("fopty", False)
def move_samx_to_scan_region(self, fovx: float, cenx: float): def move_samx_to_scan_region(self, fovx: float, cenx: float):
time.sleep(0.05) time.sleep(0.05)
if self.rt_pid_voltage is None: if self.rt_pid_voltage is None:
rtx = self.get_device_manager().devices.rtx rtx = self.device_manager.devices.rtx
self.rt_pid_voltage = rtx.user_parameter.get("rt_pid_voltage") self.rt_pid_voltage = rtx.user_parameter.get("rt_pid_voltage")
if self.rt_pid_voltage is None: if self.rt_pid_voltage is None:
raise RtError( raise RtError(
@@ -192,7 +194,7 @@ class RtFlomniController(Controller):
break break
wait_on_exit = True wait_on_exit = True
self.socket_put("v0") self.socket_put("v0")
fsamx = self.get_device_manager().devices.fsamx fsamx = self.device_manager.devices.fsamx
fsamx.read_only = False fsamx.read_only = False
fsamx.obj.controller.socket_put_confirmed("axspeed[4]=0.1*stppermm[4]") fsamx.obj.controller.socket_put_confirmed("axspeed[4]=0.1*stppermm[4]")
fsamx.obj.pid_x_correction -= (self.get_pid_x() - expected_voltage) * 0.007 fsamx.obj.pid_x_correction -= (self.get_pid_x() - expected_voltage) * 0.007
@@ -223,22 +225,22 @@ class RtFlomniController(Controller):
print("Feedback is not running; likely an error in the interferometer.") print("Feedback is not running; likely an error in the interferometer.")
raise RtError("Feedback is not running; likely an error in the interferometer.") raise RtError("Feedback is not running; likely an error in the interferometer.")
self.set_device_enabled("fsamx", False) self.set_device_read_write("fsamx", False)
self.set_device_enabled("fsamy", False) self.set_device_read_write("fsamy", False)
self.set_device_enabled("foptx", False) self.set_device_read_write("foptx", False)
self.set_device_enabled("fopty", False) self.set_device_read_write("fopty", False)
def feedback_disable(self): def feedback_disable(self):
self.clear_trajectory_generator() self.clear_trajectory_generator()
self.move_to_zero() self.move_to_zero()
self.socket_put("l0") self.socket_put("l0")
self.set_device_enabled("fsamx", True) self.set_device_read_write("fsamx", True)
self.set_device_enabled("fsamy", True) self.set_device_read_write("fsamy", True)
self.set_device_enabled("foptx", True) self.set_device_read_write("foptx", True)
self.set_device_enabled("fopty", True) self.set_device_read_write("fopty", True)
fsamx = self.get_device_manager().devices.fsamx fsamx = self.device_manager.devices.fsamx
fsamx.obj.controller.socket_put_confirmed("axspeed[4]=025*stppermm[4]") fsamx.obj.controller.socket_put_confirmed("axspeed[4]=025*stppermm[4]")
print("rt feedback is now disalbed.") print("rt feedback is now disalbed.")
@@ -289,12 +291,8 @@ class RtFlomniController(Controller):
self.socket_put("T1") self.socket_put("T1")
time.sleep(0.5) time.sleep(0.5)
self.get_device_manager().devices.ftrackz.obj.controller.socket_put_confirmed( self.device_manager.devices.ftrackz.obj.controller.socket_put_confirmed("trackyct=0")
"trackyct=0" self.device_manager.devices.ftrackz.obj.controller.socket_put_confirmed("trackzct=0")
)
self.get_device_manager().devices.ftrackz.obj.controller.socket_put_confirmed(
"trackzct=0"
)
self.laser_tracker_wait_on_target() self.laser_tracker_wait_on_target()
logger.info("Laser tracker running!") logger.info("Laser tracker running!")
@@ -341,7 +339,7 @@ class RtFlomniController(Controller):
} }
def laser_tracker_galil_enable(self): def laser_tracker_galil_enable(self):
ftrackz_con = self.get_device_manager().devices.ftrackz.obj.controller ftrackz_con = self.device_manager.devices.ftrackz.obj.controller
ftrackz_con.socket_put_confirmed("tracken=1") ftrackz_con.socket_put_confirmed("tracken=1")
ftrackz_con.socket_put_confirmed("trackyct=0") ftrackz_con.socket_put_confirmed("trackyct=0")
ftrackz_con.socket_put_confirmed("trackzct=0") ftrackz_con.socket_put_confirmed("trackzct=0")
@@ -389,7 +387,7 @@ class RtFlomniController(Controller):
self.laser_tracker_wait_on_target() self.laser_tracker_wait_on_target()
signal = self.read_ssi_interferometer(1) signal = self.read_ssi_interferometer(1)
rtx = self.get_device_manager().devices.rtx rtx = self.device_manager.devices.rtx
min_signal = rtx.user_parameter.get("min_signal") min_signal = rtx.user_parameter.get("min_signal")
low_signal = rtx.user_parameter.get("low_signal") low_signal = rtx.user_parameter.get("low_signal")
print(f"low signal: {low_signal}") print(f"low signal: {low_signal}")
@@ -478,12 +476,6 @@ class RtFlomniController(Controller):
current_position_in_scan = int(float(return_table[2])) current_position_in_scan = int(float(return_table[2]))
return (mode, number_of_positions_planned, current_position_in_scan) return (mode, number_of_positions_planned, current_position_in_scan)
def get_device_manager(self):
for axis in self._axis:
if hasattr(axis, "device_manager") and axis.device_manager:
return axis.device_manager
raise BECConfigError("Could not access the device_manager")
def read_positions_from_sampler(self): def read_positions_from_sampler(self):
# this was for reading after the scan completed # this was for reading after the scan completed
number_of_samples_to_read = 1 # self.get_scan_status()[1] #number of valid samples, will be updated upon first data read number_of_samples_to_read = 1 # self.get_scan_status()[1] #number of valid samples, will be updated upon first data read
@@ -498,7 +490,7 @@ class RtFlomniController(Controller):
# if not (mode==2 or mode==3): # if not (mode==2 or mode==3):
# error # error
self.get_device_manager().connector.set( self.device_manager.connector.set(
MessageEndpoints.device_status("rt_scan"), MessageEndpoints.device_status("rt_scan"),
messages.DeviceStatusMessage( messages.DeviceStatusMessage(
device="rt_scan", status=1, metadata=self.readout_metadata device="rt_scan", status=1, metadata=self.readout_metadata
@@ -533,7 +525,7 @@ class RtFlomniController(Controller):
signals = self._get_signals_from_table(return_table) signals = self._get_signals_from_table(return_table)
self.publish_device_data(signals=signals, point_id=int(return_table[0])) self.publish_device_data(signals=signals, point_id=int(return_table[0]))
self.get_device_manager().connector.set( self.device_manager.connector.set(
MessageEndpoints.device_status("rt_scan"), MessageEndpoints.device_status("rt_scan"),
messages.DeviceStatusMessage( messages.DeviceStatusMessage(
device="rt_scan", status=0, metadata=self.readout_metadata device="rt_scan", status=0, metadata=self.readout_metadata
@@ -547,7 +539,7 @@ class RtFlomniController(Controller):
) )
def publish_device_data(self, signals, point_id): def publish_device_data(self, signals, point_id):
self.get_device_manager().connector.set_and_publish( self.device_manager.connector.set_and_publish(
MessageEndpoints.device_read("rt_flomni"), MessageEndpoints.device_read("rt_flomni"),
messages.DeviceMessage( messages.DeviceMessage(
signals=signals, metadata={"point_id": point_id, **self.readout_metadata} signals=signals, metadata={"point_id": point_id, **self.readout_metadata}
@@ -658,7 +650,7 @@ class RtFlomniMotor(Device, PositionerBase):
self.axis_Id = axis_Id self.axis_Id = axis_Id
self.sign = sign self.sign = sign
self.controller = RtFlomniController( self.controller = RtFlomniController(
socket_cls=socket_cls, socket_host=host, socket_port=port socket_cls=socket_cls, socket_host=host, socket_port=port, device_manager=device_manager
) )
self.controller.set_axis(axis=self, axis_nr=self.axis_Id_numeric) self.controller.set_axis(axis=self, axis_nr=self.axis_Id_numeric)
self.device_manager = device_manager self.device_manager = device_manager
@@ -686,6 +678,10 @@ class RtFlomniMotor(Device, PositionerBase):
self.low_limit_travel.put(limits[0]) self.low_limit_travel.put(limits[0])
self.high_limit_travel.put(limits[1]) self.high_limit_travel.put(limits[1])
def wait_for_connection(self, timeout: int = 30, **kwargs) -> None:
"""Wait for the device to be connected."""
self.controller.on(timeout=timeout)
@property @property
def limits(self): def limits(self):
return (self.low_limit_travel.get(), self.high_limit_travel.get()) return (self.low_limit_travel.get(), self.high_limit_travel.get())
@@ -813,7 +809,7 @@ class RtFlomniMotor(Device, PositionerBase):
if __name__ == "__main__": if __name__ == "__main__":
rtcontroller = RtFlomniController( rtcontroller = RtFlomniController(
socket_cls=SocketIO, socket_host="mpc2844.psi.ch", socket_port=2222 socket_cls=SocketIO, socket_host="mpc2844.psi.ch", socket_port=2222, device_manager=None
) )
rtcontroller.on() rtcontroller.on()
rtcontroller.laser_tracker_on() rtcontroller.laser_tracker_on()

View File

@@ -71,6 +71,7 @@ class RtLamniController(Controller):
socket_cls=None, socket_cls=None,
socket_host=None, socket_host=None,
socket_port=None, socket_port=None,
device_manager=None,
attr_name="", attr_name="",
parent=None, parent=None,
labels=None, labels=None,
@@ -81,6 +82,7 @@ class RtLamniController(Controller):
socket_cls=socket_cls, socket_cls=socket_cls,
socket_host=socket_host, socket_host=socket_host,
socket_port=socket_port, socket_port=socket_port,
device_manager=device_manager,
attr_name=attr_name, attr_name=attr_name,
parent=parent, parent=parent,
labels=labels, labels=labels,
@@ -92,11 +94,11 @@ class RtLamniController(Controller):
def feedback_disable(self): def feedback_disable(self):
self.socket_put("J0") self.socket_put("J0")
logger.info("LamNI Feedback disabled.") logger.info("LamNI Feedback disabled.")
self.set_device_enabled("lsamx", True) self.set_device_read_write("lsamx", True)
self.set_device_enabled("lsamy", True) self.set_device_read_write("lsamy", True)
self.set_device_enabled("loptx", True) self.set_device_read_write("loptx", True)
self.set_device_enabled("lopty", True) self.set_device_read_write("lopty", True)
self.set_device_enabled("loptz", True) self.set_device_read_write("loptz", True)
def is_axis_moving(self, axis_Id) -> bool: def is_axis_moving(self, axis_Id) -> bool:
# this checks that axis is on target # this checks that axis is on target
@@ -150,25 +152,25 @@ class RtLamniController(Controller):
# set these as closed loop target position # set these as closed loop target position
self.socket_put(f"pa0,{x_curr:.4f}") self.socket_put(f"pa0,{x_curr:.4f}")
self.socket_put(f"pa1,{y_curr:.4f}") self.socket_put(f"pa1,{y_curr:.4f}")
self.get_device_manager().devices.rtx.obj.user_setpoint.set_with_feedback_disabled(x_curr) self.device_manager.devices.rtx.obj.user_setpoint.set_with_feedback_disabled(x_curr)
self.get_device_manager().devices.rty.obj.user_setpoint.set_with_feedback_disabled(y_curr) self.device_manager.devices.rty.obj.user_setpoint.set_with_feedback_disabled(y_curr)
self.socket_put("J5") self.socket_put("J5")
logger.info("LamNI Feedback enabled (without reset).") logger.info("LamNI Feedback enabled (without reset).")
self.set_device_enabled("lsamx", False) self.set_device_read_write("lsamx", False)
self.set_device_enabled("lsamy", False) self.set_device_read_write("lsamy", False)
self.set_device_enabled("loptx", False) self.set_device_read_write("loptx", False)
self.set_device_enabled("lopty", False) self.set_device_read_write("lopty", False)
self.set_device_enabled("loptz", False) self.set_device_read_write("loptz", False)
@threadlocked @threadlocked
def feedback_disable_and_even_reset_lamni_angle_interferometer(self): def feedback_disable_and_even_reset_lamni_angle_interferometer(self):
self.socket_put("J6") self.socket_put("J6")
logger.info("LamNI Feedback disabled including the angular interferometer.") logger.info("LamNI Feedback disabled including the angular interferometer.")
self.set_device_enabled("lsamx", True) self.set_device_read_write("lsamx", True)
self.set_device_enabled("lsamy", True) self.set_device_read_write("lsamy", True)
self.set_device_enabled("loptx", True) self.set_device_read_write("loptx", True)
self.set_device_enabled("lopty", True) self.set_device_read_write("lopty", True)
self.set_device_enabled("loptz", True) self.set_device_read_write("loptz", True)
@threadlocked @threadlocked
def clear_trajectory_generator(self): def clear_trajectory_generator(self):
@@ -284,7 +286,7 @@ class RtLamniController(Controller):
# if not (mode==2 or mode==3): # if not (mode==2 or mode==3):
# error # error
self.get_device_manager().connector.set( self.device_manager.connector.set(
MessageEndpoints.device_status("rt_scan"), MessageEndpoints.device_status("rt_scan"),
messages.DeviceStatusMessage( messages.DeviceStatusMessage(
device="rt_scan", status=1, metadata=self.readout_metadata device="rt_scan", status=1, metadata=self.readout_metadata
@@ -319,7 +321,7 @@ class RtLamniController(Controller):
signals = self._get_signals_from_table(return_table) signals = self._get_signals_from_table(return_table)
self.publish_device_data(signals=signals, point_id=int(return_table[0])) self.publish_device_data(signals=signals, point_id=int(return_table[0]))
self.get_device_manager().connector.set( self.device_manager.connector.set(
MessageEndpoints.device_status("rt_scan"), MessageEndpoints.device_status("rt_scan"),
messages.DeviceStatusMessage( messages.DeviceStatusMessage(
device="rt_scan", status=0, metadata=self.readout_metadata device="rt_scan", status=0, metadata=self.readout_metadata
@@ -331,7 +333,7 @@ class RtLamniController(Controller):
) )
def publish_device_data(self, signals, point_id): def publish_device_data(self, signals, point_id):
self.get_device_manager().connector.set_and_publish( self.device_manager.connector.set_and_publish(
MessageEndpoints.device_read("rt_lamni"), MessageEndpoints.device_read("rt_lamni"),
messages.DeviceMessage( messages.DeviceMessage(
signals=signals, metadata={"point_id": point_id, **self.readout_metadata} signals=signals, metadata={"point_id": point_id, **self.readout_metadata}
@@ -366,10 +368,10 @@ class RtLamniController(Controller):
) # we set all three outputs of the traj. gen. although in LamNI case only 0,1 are used ) # we set all three outputs of the traj. gen. although in LamNI case only 0,1 are used
self.clear_trajectory_generator() self.clear_trajectory_generator()
self.get_device_manager().devices.lsamrot.obj.move(0, wait=True) self.device_manager.devices.lsamrot.obj.move(0, wait=True)
galil_controller_rt_status = ( galil_controller_rt_status = (
self.get_device_manager().devices.lsamx.obj.controller.lgalil_is_air_off_and_orchestra_enabled() self.device_manager.devices.lsamx.obj.controller.lgalil_is_air_off_and_orchestra_enabled()
) )
if galil_controller_rt_status == 0: if galil_controller_rt_status == 0:
@@ -382,16 +384,16 @@ class RtLamniController(Controller):
time.sleep(0.03) time.sleep(0.03)
lsamx_user_params = self.get_device_manager().devices.lsamx.user_parameter lsamx_user_params = self.device_manager.devices.lsamx.user_parameter
if lsamx_user_params is None or lsamx_user_params.get("center") is None: if lsamx_user_params is None or lsamx_user_params.get("center") is None:
raise RuntimeError("lsamx center is not defined") raise RuntimeError("lsamx center is not defined")
lsamy_user_params = self.get_device_manager().devices.lsamy.user_parameter lsamy_user_params = self.device_manager.devices.lsamy.user_parameter
if lsamy_user_params is None or lsamy_user_params.get("center") is None: if lsamy_user_params is None or lsamy_user_params.get("center") is None:
raise RuntimeError("lsamy center is not defined") raise RuntimeError("lsamy center is not defined")
lsamx_center = lsamx_user_params.get("center") lsamx_center = lsamx_user_params.get("center")
lsamy_center = lsamy_user_params.get("center") lsamy_center = lsamy_user_params.get("center")
self.get_device_manager().devices.lsamx.obj.move(lsamx_center, wait=True) self.device_manager.devices.lsamx.obj.move(lsamx_center, wait=True)
self.get_device_manager().devices.lsamy.obj.move(lsamy_center, wait=True) self.device_manager.devices.lsamy.obj.move(lsamy_center, wait=True)
self.socket_put("J1") self.socket_put("J1")
_waitforfeedbackctr = 0 _waitforfeedbackctr = 0
@@ -405,11 +407,11 @@ class RtLamniController(Controller):
(self.socket_put_and_receive("J2")).split(",")[0] (self.socket_put_and_receive("J2")).split(",")[0]
) )
self.set_device_enabled("lsamx", False) self.set_device_read_write("lsamx", False)
self.set_device_enabled("lsamy", False) self.set_device_read_write("lsamy", False)
self.set_device_enabled("loptx", False) self.set_device_read_write("loptx", False)
self.set_device_enabled("lopty", False) self.set_device_read_write("lopty", False)
self.set_device_enabled("loptz", False) self.set_device_read_write("loptz", False)
if interferometer_feedback_not_running == 1: if interferometer_feedback_not_running == 1:
logger.error( logger.error(
@@ -559,7 +561,7 @@ class RtLamniMotor(Device, PositionerBase):
self.axis_Id = axis_Id self.axis_Id = axis_Id
self.sign = sign self.sign = sign
self.controller = RtLamniController( self.controller = RtLamniController(
socket_cls=socket_cls, socket_host=host, socket_port=port socket_cls=socket_cls, socket_host=host, socket_port=port, device_manager=device_manager
) )
self.controller.set_axis(axis=self, axis_nr=self.axis_Id_numeric) self.controller.set_axis(axis=self, axis_nr=self.axis_Id_numeric)
self.device_manager = device_manager self.device_manager = device_manager
@@ -586,6 +588,10 @@ class RtLamniMotor(Device, PositionerBase):
self.low_limit_travel.put(limits[0]) self.low_limit_travel.put(limits[0])
self.high_limit_travel.put(limits[1]) self.high_limit_travel.put(limits[1])
def wait_for_connection(self, timeout: int = 30, **kwargs) -> None:
"""Wait for the device to be connected."""
self.controller.on(timeout=timeout)
@property @property
def limits(self): def limits(self):
return (self.low_limit_travel.get(), self.high_limit_travel.get()) return (self.low_limit_travel.get(), self.high_limit_travel.get())

View File

@@ -1,8 +1,8 @@
import builtins
import socket
import threading import threading
import time import time
from typing import List from typing import List
import builtins
import socket
import numpy as np import numpy as np
from bec_lib import bec_logger, messages from bec_lib import bec_logger, messages
@@ -34,12 +34,15 @@ from csaxs_bec.devices.omny.rt.rt_ophyd import (
logger = bec_logger.logger logger = bec_logger.logger
class RtOMNY_mirror_switchbox_Error(Exception): class RtOMNY_mirror_switchbox_Error(Exception):
pass pass
class RtOMNY_Error(Exception): class RtOMNY_Error(Exception):
pass pass
class RtOMNYController(Controller): class RtOMNYController(Controller):
_axes_per_controller = 3 _axes_per_controller = 3
red = "\x1b[91m" red = "\x1b[91m"
@@ -87,6 +90,7 @@ class RtOMNYController(Controller):
socket_cls=None, socket_cls=None,
socket_host=None, socket_host=None,
socket_port=None, socket_port=None,
device_manager=None,
attr_name="", attr_name="",
parent=None, parent=None,
labels=None, labels=None,
@@ -97,6 +101,7 @@ class RtOMNYController(Controller):
socket_cls=socket_cls, socket_cls=socket_cls,
socket_host=socket_host, socket_host=socket_host,
socket_port=socket_port, socket_port=socket_port,
device_manager=device_manager,
attr_name=attr_name, attr_name=attr_name,
parent=parent, parent=parent,
labels=labels, labels=labels,
@@ -234,7 +239,7 @@ class RtOMNYController(Controller):
"opt_amplitude1_neg": 3000, "opt_amplitude1_neg": 3000,
"opt_amplitude2_pos": 3000, "opt_amplitude2_pos": 3000,
"opt_amplitude2_neg": 3000, "opt_amplitude2_neg": 3000,
} },
} }
# def is_axis_moving(self, axis_Id) -> bool: # def is_axis_moving(self, axis_Id) -> bool:
@@ -261,42 +266,60 @@ class RtOMNYController(Controller):
threading.Thread(target=send_positions, args=(self, positions), daemon=True).start() threading.Thread(target=send_positions, args=(self, positions), daemon=True).start()
def get_mirror_parameters(self,channel): def get_mirror_parameters(self, channel):
return self.mirror_parameters[channel] return self.mirror_parameters[channel]
def laser_tracker_check_and_wait_for_signalstrength(self): def laser_tracker_check_and_wait_for_signalstrength(self):
self.get_device_manager().connector.send_client_info("Checking laser tracker...", scope="", show_asap=True) self.device_manager.connector.send_client_info(
"Checking laser tracker...", scope="", show_asap=True
)
if not self.laser_tracker_check_enabled(): if not self.laser_tracker_check_enabled():
print("laser_tracker_check_and_wait_for_signalstrength: The laser tracker is not even enabled.") print(
"laser_tracker_check_and_wait_for_signalstrength: The laser tracker is not even enabled."
)
return return
#first check on target # first check on target
self.laser_tracker_wait_on_target() self.laser_tracker_wait_on_target()
#when on target, check interferometer signal # when on target, check interferometer signal
signal = self._omny_interferometer_get_signalsample("ssi_4",0.1) signal = self._omny_interferometer_get_signalsample("ssi_4", 0.1)
rtx = self.get_device_manager().devices.rtx rtx = self.device_manager.devices.rtx
min_signal = rtx.user_parameter.get("min_signal") min_signal = rtx.user_parameter.get("min_signal")
low_signal = rtx.user_parameter.get("low_signal") low_signal = rtx.user_parameter.get("low_signal")
wait_counter = 0 wait_counter = 0
while signal < min_signal and wait_counter<10: while signal < min_signal and wait_counter < 10:
self.get_device_manager().connector.send_client_info(f"The signal of the tracker {signal} is below the minimum required signal of {min_signal}. Waiting...", scope="laser_tracker_check_and_wait_for_signalstrength", show_asap=True) self.device_manager.connector.send_client_info(
f"The signal of the tracker {signal} is below the minimum required signal of {min_signal}. Waiting...",
scope="laser_tracker_check_and_wait_for_signalstrength",
show_asap=True,
)
wait_counter+=1 wait_counter += 1
time.sleep(0.2) time.sleep(0.2)
signal = self._omny_interferometer_get_signalsample("ssi_4",0.1) signal = self._omny_interferometer_get_signalsample("ssi_4", 0.1)
if signal < low_signal: if signal < low_signal:
self.get_device_manager().connector.send_client_info(f"\x1b[91mThe signal of the tracker {signal} is below the low limit of {low_signal}. Auto readjustment...\x1b[0m", scope="laser_tracker_check_and_wait_for_signalstrength", show_asap=True) self.device_manager.connector.send_client_info(
f"\x1b[91mThe signal of the tracker {signal} is below the low limit of {low_signal}. Auto readjustment...\x1b[0m",
scope="laser_tracker_check_and_wait_for_signalstrength",
show_asap=True,
)
self.omny_interferometer_align_tracking() self.omny_interferometer_align_tracking()
self.get_device_manager().connector.send_client_info("Checking laser tracker completed.", scope="", show_asap=True) self.device_manager.connector.send_client_info(
"Checking laser tracker completed.", scope="", show_asap=True
)
def omny_interferometer_align_tracking(self): def omny_interferometer_align_tracking(self):
mirror_channel=6 mirror_channel = 6
signal = self._omny_interferometer_get_signalsample(self.mirror_parameters[mirror_channel]["opt_signalchannel"], self.mirror_parameters[mirror_channel]["opt_averaging_time"]) signal = self._omny_interferometer_get_signalsample(
self.mirror_parameters[mirror_channel]["opt_signalchannel"],
self.mirror_parameters[mirror_channel]["opt_averaging_time"],
)
if signal > self.mirror_parameters[mirror_channel]["opt_signal_stop"]: if signal > self.mirror_parameters[mirror_channel]["opt_signal_stop"]:
print(f"Interferometer signal of axis {self.mirror_parameters[mirror_channel]['opt_mirrorname']} is good, no alignment needed.") print(
f"Interferometer signal of axis {self.mirror_parameters[mirror_channel]['opt_mirrorname']} is good, no alignment needed."
)
else: else:
self._omny_interferometer_switch_channel(mirror_channel) self._omny_interferometer_switch_channel(mirror_channel)
time.sleep(0.1) time.sleep(0.1)
@@ -307,16 +330,19 @@ class RtOMNYController(Controller):
self._omny_interferometer_switch_alloff() self._omny_interferometer_switch_alloff()
self.show_signal_strength_interferometer() self.show_signal_strength_interferometer()
mirror_channel=-1 mirror_channel = -1
def omny_interferometer_align_incoupling_angle(self): def omny_interferometer_align_incoupling_angle(self):
mirror_channel=1 mirror_channel = 1
signal = self._omny_interferometer_get_signalsample(self.mirror_parameters[mirror_channel]["opt_signalchannel"], self.mirror_parameters[mirror_channel]["opt_averaging_time"]) signal = self._omny_interferometer_get_signalsample(
self.mirror_parameters[mirror_channel]["opt_signalchannel"],
self.mirror_parameters[mirror_channel]["opt_averaging_time"],
)
if signal > self.mirror_parameters[mirror_channel]["opt_signal_stop"]: if signal > self.mirror_parameters[mirror_channel]["opt_signal_stop"]:
print(f"Interferometer signal of axis {self.mirror_parameters[mirror_channel]['opt_mirrorname']} is good, no alignment needed.") print(
f"Interferometer signal of axis {self.mirror_parameters[mirror_channel]['opt_mirrorname']} is good, no alignment needed."
)
else: else:
self._omny_interferometer_switch_channel(mirror_channel) self._omny_interferometer_switch_channel(mirror_channel)
time.sleep(0.1) time.sleep(0.1)
@@ -327,19 +353,18 @@ class RtOMNYController(Controller):
self._omny_interferometer_switch_alloff() self._omny_interferometer_switch_alloff()
self.show_signal_strength_interferometer() self.show_signal_strength_interferometer()
mirror_channel=-1 mirror_channel = -1
def _omny_interferometer_openloop_steps(self, channel, steps, amplitude): def _omny_interferometer_openloop_steps(self, channel, steps, amplitude):
if channel not in range(3,5): if channel not in range(3, 5):
raise RtOMNY_Error(f"invalid channel number {channel}.") raise RtOMNY_Error(f"invalid channel number {channel}.")
if amplitude > 4090: if amplitude > 4090:
amplitude = 4090 amplitude = 4090
elif amplitude < 10: elif amplitude < 10:
amplitude = 10 amplitude = 10
oshield = self.get_device_manager().devices.oshield oshield = self.device_manager.devices.oshield
oshield.obj.controller.move_open_loop_steps( oshield.obj.controller.move_open_loop_steps(
channel, steps, amplitude=amplitude, frequency=500 channel, steps, amplitude=amplitude, frequency=500
@@ -351,7 +376,7 @@ class RtOMNYController(Controller):
def _omny_interferometer_optimize(self, mirror_channel, channel): def _omny_interferometer_optimize(self, mirror_channel, channel):
if mirror_channel == -1: if mirror_channel == -1:
raise RtOMNY_Error("no mirror channel selected") raise RtOMNY_Error("no mirror channel selected")
#mirror channel is mirror number and channel is smaract channel, i.e. axis of the mirror # mirror channel is mirror number and channel is smaract channel, i.e. axis of the mirror
if channel == 3: if channel == 3:
steps_pos = self.mirror_parameters[mirror_channel]["opt_steps1_pos"] steps_pos = self.mirror_parameters[mirror_channel]["opt_steps1_pos"]
steps_neg = self.mirror_parameters[mirror_channel]["opt_steps1_neg"] steps_neg = self.mirror_parameters[mirror_channel]["opt_steps1_neg"]
@@ -365,67 +390,80 @@ class RtOMNYController(Controller):
else: else:
raise RtOMNY_Error(f"invalid channel number {channel}.") raise RtOMNY_Error(f"invalid channel number {channel}.")
previous_signal = self._omny_interferometer_get_signalsample(self.mirror_parameters[mirror_channel]["opt_signalchannel"], self.mirror_parameters[mirror_channel]["opt_averaging_time"]) previous_signal = self._omny_interferometer_get_signalsample(
self.mirror_parameters[mirror_channel]["opt_signalchannel"],
self.mirror_parameters[mirror_channel]["opt_averaging_time"],
)
min_begin = self.mirror_parameters[mirror_channel]["opt_signal_min_begin"] min_begin = self.mirror_parameters[mirror_channel]["opt_signal_min_begin"]
if previous_signal < min_begin: if previous_signal < min_begin:
#raise OMNY_rt_clientError("error1") #(f"Minimum signal of axis {self.mirror_parameters[mirror_channel]["opt_mirrorname"]} to start alignment not present.") # raise OMNY_rt_clientError("error1") #(f"Minimum signal of axis {self.mirror_parameters[mirror_channel]["opt_mirrorname"]} to start alignment not present.")
print(f"\rMinimum signal for auto alignment {min_begin} not reached.") print(f"\rMinimum signal for auto alignment {min_begin} not reached.")
return return
elif previous_signal > self.mirror_parameters[mirror_channel]["opt_signal_stop"]: elif previous_signal > self.mirror_parameters[mirror_channel]["opt_signal_stop"]:
print(f"\rInterferometer signal of axis is good") # {self.mirror_parameters[mirror_channel]["opt_mirrorname"]} is good.") print(
return f"\rInterferometer signal of axis is good"
) # {self.mirror_parameters[mirror_channel]["opt_mirrorname"]} is good.")
return
else: else:
direction = 1 direction = 1
cycle_counter=0 cycle_counter = 0
cycle_max=20 cycle_max = 20
reversal_counter=0 reversal_counter = 0
reversal_max=4 reversal_max = 4
self.mirror_amplitutde_increase=0 self.mirror_amplitutde_increase = 0
current_sample = self._omny_interferometer_get_signalsample(self.mirror_parameters[mirror_channel]["opt_signalchannel"], self.mirror_parameters[mirror_channel]["opt_averaging_time"]) current_sample = self._omny_interferometer_get_signalsample(
max=current_sample self.mirror_parameters[mirror_channel]["opt_signalchannel"],
self.mirror_parameters[mirror_channel]["opt_averaging_time"],
)
max = current_sample
while current_sample < self.mirror_parameters[mirror_channel]["opt_signal_stop"] and cycle_counter<cycle_max and reversal_counter < reversal_max: while (
current_sample < self.mirror_parameters[mirror_channel]["opt_signal_stop"]
and cycle_counter < cycle_max
and reversal_counter < reversal_max
):
# if current_sample < self.mirror_parameters[mirror_channel]["opt_signal_min_begin"]: # if current_sample < self.mirror_parameters[mirror_channel]["opt_signal_min_begin"]:
# raise OMNY_rt_clientError("error2") #(f"Minimum signal of axis {self.mirror_parameters[mirror_channel]["opt_mirrorname"]} to start alignment not present.") # raise OMNY_rt_clientError("error2") #(f"Minimum signal of axis {self.mirror_parameters[mirror_channel]["opt_mirrorname"]} to start alignment not present.")
if direction>0: if direction > 0:
self._omny_interferometer_openloop_steps(channel, steps_pos, opt_amplitude_pos) self._omny_interferometer_openloop_steps(channel, steps_pos, opt_amplitude_pos)
verbose_str = f"channel {channel}, steps {steps_pos}" verbose_str = f"channel {channel}, steps {steps_pos}"
else: else:
self._omny_interferometer_openloop_steps(channel, -steps_neg, opt_amplitude_neg) self._omny_interferometer_openloop_steps(channel, -steps_neg, opt_amplitude_neg)
verbose_str = f"auto action {channel}, steps {-steps_pos}" verbose_str = f"auto action {channel}, steps {-steps_pos}"
#print(f"Aligning axis ") #{self.mirror_parameters[mirror_channel]["opt_mirrorname"]}. Target: {self.mirror_parameters[mirror_channel]["opt_signal_stop"]}, current {current_sample}") # print(f"Aligning axis ") #{self.mirror_parameters[mirror_channel]["opt_mirrorname"]}. Target: {self.mirror_parameters[mirror_channel]["opt_signal_stop"]}, current {current_sample}")
current_sample = self._omny_interferometer_get_signalsample(self.mirror_parameters[mirror_channel]["opt_signalchannel"], self.mirror_parameters[mirror_channel]["opt_averaging_time"]) current_sample = self._omny_interferometer_get_signalsample(
self.mirror_parameters[mirror_channel]["opt_signalchannel"],
self.mirror_parameters[mirror_channel]["opt_averaging_time"],
)
opt_mirrorname = self.mirror_parameters[mirror_channel]["opt_mirrorname"] opt_mirrorname = self.mirror_parameters[mirror_channel]["opt_mirrorname"]
info_str = f"\rAuto aligning Channel {mirror_channel}, {opt_mirrorname}, Current signal: {current_sample:.0f}" info_str = f"\rAuto aligning Channel {mirror_channel}, {opt_mirrorname}, Current signal: {current_sample:.0f}"
message=info_str +" (q)uit \r" message = info_str + " (q)uit \r"
self.get_device_manager().connector.send_client_info(message, scope="_omny_interferometer_optimize", show_asap=True) self.device_manager.connector.send_client_info(
message, scope="_omny_interferometer_optimize", show_asap=True
)
if previous_signal>current_sample:
if direction<0:
steps_pos=int(steps_pos/2)
steps_neg=int(steps_neg/2)
if steps_pos<1:
steps_pos=1
if steps_neg<1:
steps_neg=1
direction=direction*(-1)
reversal_counter+=1
previous_signal=current_sample
cycle_counter+=1
print(f"\r\nFinished aligning channel {channel} of mirror {mirror_channel}\n\r") # {self.mirror_parameters[mirror_channel]["opt_mirrorname"]}. Target: {self.mirror_parameters[mirror_channel]["opt_signal_stop"]}, current {current_sample}")
if previous_signal > current_sample:
if direction < 0:
steps_pos = int(steps_pos / 2)
steps_neg = int(steps_neg / 2)
if steps_pos < 1:
steps_pos = 1
if steps_neg < 1:
steps_neg = 1
direction = direction * (-1)
reversal_counter += 1
previous_signal = current_sample
cycle_counter += 1
print(
f"\r\nFinished aligning channel {channel} of mirror {mirror_channel}\n\r"
) # {self.mirror_parameters[mirror_channel]["opt_mirrorname"]}. Target: {self.mirror_parameters[mirror_channel]["opt_signal_stop"]}, current {current_sample}")
def move_to_zero(self): def move_to_zero(self):
self.socket_put("pa0,0") self.socket_put("pa0,0")
@@ -457,7 +495,7 @@ class RtOMNYController(Controller):
if ret == 1: if ret == 1:
return True return True
return False return False
def feedback_is_running(self) -> bool: def feedback_is_running(self) -> bool:
self.feedback_get_status_and_ssi() self.feedback_get_status_and_ssi()
interferometer_feedback_not_running = int(self.ssi["feedback_error"]) interferometer_feedback_not_running = int(self.ssi["feedback_error"])
@@ -466,7 +504,9 @@ class RtOMNYController(Controller):
return True return True
def feedback_enable_with_reset(self): def feedback_enable_with_reset(self):
self.get_device_manager().connector.send_client_info(f"Enabling the feedback...", scope="", show_asap=True) self.device_manager.connector.send_client_info(
f"Enabling the feedback...", scope="", show_asap=True
)
self.socket_put("J0") # disable feedback self.socket_put("J0") # disable feedback
time.sleep(0.01) time.sleep(0.01)
@@ -485,14 +525,16 @@ class RtOMNYController(Controller):
self.laser_tracker_on() self.laser_tracker_on()
time.sleep(0.01) time.sleep(0.01)
osamroy = self.get_device_manager().devices.osamroy osamroy = self.device_manager.devices.osamroy
# the following read will also upate the angle in rt during readout # the following read will also upate the angle in rt during readout
readback = osamroy.obj.readback.get() readback = osamroy.obj.readback.get()
if (np.fabs(readback) > 0.1): if np.fabs(readback) > 0.1:
self.get_device_manager().connector.send_client_info(f"Rotating to zero", scope="feedback enable", show_asap=True) self.device_manager.connector.send_client_info(
f"Rotating to zero", scope="feedback enable", show_asap=True
)
osamroy.obj.move(0, wait=True) osamroy.obj.move(0, wait=True)
osamx = self.get_device_manager().devices.osamx osamx = self.device_manager.devices.osamx
osamx_in = osamx.user_parameter.get("in") osamx_in = osamx.user_parameter.get("in")
if not np.isclose(osamx.obj.readback.get(), osamx_in, atol=0.01): if not np.isclose(osamx.obj.readback.get(), osamx_in, atol=0.01):
@@ -514,16 +556,15 @@ class RtOMNYController(Controller):
time.sleep(1.5) time.sleep(1.5)
self.set_device_enabled("osamx", False) self.set_device_read_write("osamx", False)
self.set_device_enabled("osamy", False) self.set_device_read_write("osamy", False)
self.set_device_enabled("ofzpx", False) self.set_device_read_write("ofzpx", False)
self.set_device_enabled("ofzpy", False) self.set_device_read_write("ofzpy", False)
self.set_device_enabled("oosax", False) self.set_device_read_write("oosax", False)
self.set_device_enabled("oosax", False) self.set_device_read_write("oosax", False)
print("Feedback is running.") print("Feedback is running.")
@threadlocked @threadlocked
def clear_trajectory_generator(self): def clear_trajectory_generator(self):
self.socket_put("sc") self.socket_put("sc")
@@ -534,16 +575,15 @@ class RtOMNYController(Controller):
self.move_to_zero() self.move_to_zero()
self.socket_put("J0") self.socket_put("J0")
self.set_device_enabled("osamx", True) self.set_device_read_write("osamx", True)
self.set_device_enabled("osamy", True) self.set_device_read_write("osamy", True)
self.set_device_enabled("ofzpx", True) self.set_device_read_write("ofzpx", True)
self.set_device_enabled("ofzpy", True) self.set_device_read_write("ofzpy", True)
self.set_device_enabled("oosax", True) self.set_device_read_write("oosax", True)
self.set_device_enabled("oosax", True) self.set_device_read_write("oosax", True)
print("rt feedback is now disabled.") print("rt feedback is now disabled.")
def set_rotation_angle(self, val: float) -> None: def set_rotation_angle(self, val: float) -> None:
self.socket_put(f"a{val/180*np.pi}") self.socket_put(f"a{val/180*np.pi}")
@@ -578,12 +618,13 @@ class RtOMNYController(Controller):
"enabled_z": bool(tracker_values[10]), "enabled_z": bool(tracker_values[10]),
} }
def laser_tracker_on(self): def laser_tracker_on(self):
#update variables and enable if not yet active # update variables and enable if not yet active
if not self.laser_tracker_check_enabled(): if not self.laser_tracker_check_enabled():
logger.info("Enabling the laser tracker. Please wait...") logger.info("Enabling the laser tracker. Please wait...")
self.get_device_manager().connector.send_client_info(f"Enabling the laser tracker. Please wait...", scope="", show_asap=True) self.device_manager.connector.send_client_info(
f"Enabling the laser tracker. Please wait...", scope="", show_asap=True
)
tracker_intensity = self.tracker_info["tracker_intensity"] tracker_intensity = self.tracker_info["tracker_intensity"]
if ( if (
@@ -598,18 +639,13 @@ class RtOMNYController(Controller):
self.socket_put("T1") self.socket_put("T1")
time.sleep(0.5) time.sleep(0.5)
self.get_device_manager().devices.otracky.obj.controller.socket_put_confirmed( self.device_manager.devices.otracky.obj.controller.socket_put_confirmed("trackyct=0")
"trackyct=0" self.device_manager.devices.otracky.obj.controller.socket_put_confirmed("trackzct=0")
)
self.get_device_manager().devices.otracky.obj.controller.socket_put_confirmed(
"trackzct=0"
)
self.laser_tracker_wait_on_target() self.laser_tracker_wait_on_target()
logger.info("Laser tracker running!") logger.info("Laser tracker running!")
print("Laser tracker running!") print("Laser tracker running!")
def laser_tracker_check_enabled(self) -> bool: def laser_tracker_check_enabled(self) -> bool:
self.laser_update_tracker_info() self.laser_update_tracker_info()
if self.tracker_info["enabled_z"] and self.tracker_info["enabled_y"]: if self.tracker_info["enabled_z"] and self.tracker_info["enabled_y"]:
@@ -628,11 +664,10 @@ class RtOMNYController(Controller):
return True return True
return False return False
def laser_tracker_wait_on_target(self): def laser_tracker_wait_on_target(self):
max_repeat = 15 max_repeat = 15
count = 0 count = 0
while not self.laser_tracker_check_on_target() and count<max_repeat: while not self.laser_tracker_check_on_target() and count < max_repeat:
logger.info("Waiting for laser tracker to reach target position.") logger.info("Waiting for laser tracker to reach target position.")
time.sleep(0.5) time.sleep(0.5)
count += 1 count += 1
@@ -641,75 +676,74 @@ class RtOMNYController(Controller):
raise RtError("Failed to reach laser target position.") raise RtError("Failed to reach laser target position.")
def laser_tracker_print_intensity_for_otrack_tweaking(self): def laser_tracker_print_intensity_for_otrack_tweaking(self):
#self.laser_update_tracker_info() # self.laser_update_tracker_info()
#_laser_tracker_intensity = self.tracker_info["tracker_intensity"] # _laser_tracker_intensity = self.tracker_info["tracker_intensity"]
#print(f"\r PSD beam intensity: {_laser_tracker_intensity:.2f}\r") # print(f"\r PSD beam intensity: {_laser_tracker_intensity:.2f}\r")
self.laser_tracker_show_all(extra_endline="\r") self.laser_tracker_show_all(extra_endline="\r")
def laser_tracker_show_all(self,extra_endline=""): def laser_tracker_show_all(self, extra_endline=""):
self.laser_update_tracker_info() self.laser_update_tracker_info()
enabled_y = self.tracker_info["enabled_y"] enabled_y = self.tracker_info["enabled_y"]
print(extra_endline+f"Tracker enabled: {bool(enabled_y)}"+extra_endline) print(extra_endline + f"Tracker enabled: {bool(enabled_y)}" + extra_endline)
if self.tracker_info["tracker_intensity"] < self.tracker_info["threshold_intensity_y"]: if self.tracker_info["tracker_intensity"] < self.tracker_info["threshold_intensity_y"]:
print(self.red+" LOW INTENSITY"+self.white+extra_endline) print(self.red + " LOW INTENSITY" + self.white + extra_endline)
_laser_tracker_intensity = self.tracker_info["tracker_intensity"] _laser_tracker_intensity = self.tracker_info["tracker_intensity"]
print(f" PSD beam intensity: {_laser_tracker_intensity:.2f}"+extra_endline) print(f" PSD beam intensity: {_laser_tracker_intensity:.2f}" + extra_endline)
_laser_tracker_y_beampos = self.tracker_info["beampos_y"] _laser_tracker_y_beampos = self.tracker_info["beampos_y"]
print(f" Y beam position: {_laser_tracker_y_beampos:.2f}"+extra_endline) print(f" Y beam position: {_laser_tracker_y_beampos:.2f}" + extra_endline)
_laser_tracker_y_target = self.tracker_info["target_y"] _laser_tracker_y_target = self.tracker_info["target_y"]
print(f" target position: {_laser_tracker_y_target:.2f}"+extra_endline) print(f" target position: {_laser_tracker_y_target:.2f}" + extra_endline)
_laser_tracker_y_threshold_intensity = self.tracker_info["threshold_intensity_y"] _laser_tracker_y_threshold_intensity = self.tracker_info["threshold_intensity_y"]
print(f" threshold intensity: {_laser_tracker_y_threshold_intensity:.2f}"+extra_endline) print(
f" threshold intensity: {_laser_tracker_y_threshold_intensity:.2f}" + extra_endline
)
_laser_tracker_y_piezo_voltage = self.tracker_info["piezo_voltage_y"] _laser_tracker_y_piezo_voltage = self.tracker_info["piezo_voltage_y"]
print(f" Piezo voltage: {_laser_tracker_y_piezo_voltage:.2f}"+extra_endline) print(f" Piezo voltage: {_laser_tracker_y_piezo_voltage:.2f}" + extra_endline)
_laser_tracker_z_beampos = self.tracker_info["beampos_z"] _laser_tracker_z_beampos = self.tracker_info["beampos_z"]
print(f" Z beam position: {_laser_tracker_z_beampos:.2f}"+extra_endline) print(f" Z beam position: {_laser_tracker_z_beampos:.2f}" + extra_endline)
_laser_tracker_z_target = self.tracker_info["target_z"] _laser_tracker_z_target = self.tracker_info["target_z"]
print(f" target position: {_laser_tracker_z_target:.2f}"+extra_endline) print(f" target position: {_laser_tracker_z_target:.2f}" + extra_endline)
_laser_tracker_z_threshold_intensity = self.tracker_info["threshold_intensity_z"] _laser_tracker_z_threshold_intensity = self.tracker_info["threshold_intensity_z"]
print(f" threshold intensity: {_laser_tracker_z_threshold_intensity:.2f}"+extra_endline) print(
f" threshold intensity: {_laser_tracker_z_threshold_intensity:.2f}" + extra_endline
)
_laser_tracker_z_piezo_voltage = self.tracker_info["piezo_voltage_z"] _laser_tracker_z_piezo_voltage = self.tracker_info["piezo_voltage_z"]
print(f" Piezo voltage: {_laser_tracker_z_piezo_voltage:.2f}"+extra_endline) print(f" Piezo voltage: {_laser_tracker_z_piezo_voltage:.2f}" + extra_endline)
print(" Reminder - there is also an upper threshold active in rt\n"+extra_endline) print(" Reminder - there is also an upper threshold active in rt\n" + extra_endline)
if extra_endline == "": if extra_endline == "":
self.laser_tracker_galil_status() self.laser_tracker_galil_status()
def laser_tracker_galil_enable(self): def laser_tracker_galil_enable(self):
otracky_con = self.get_device_manager().devices.otracky.obj.controller otracky_con = self.device_manager.devices.otracky.obj.controller
otracky_con.socket_put_confirmed("tracken=1") otracky_con.socket_put_confirmed("tracken=1")
otracky_con.socket_put_confirmed("trackyct=0") otracky_con.socket_put_confirmed("trackyct=0")
otracky_con.socket_put_confirmed("trackzct=0") otracky_con.socket_put_confirmed("trackzct=0")
def laser_tracker_galil_disable(self): def laser_tracker_galil_disable(self):
otracky_con = self.get_device_manager().devices.otracky.obj.controller otracky_con = self.device_manager.devices.otracky.obj.controller
otracky_con.socket_put_confirmed("tracken=0") otracky_con.socket_put_confirmed("tracken=0")
def laser_tracker_galil_status(self): def laser_tracker_galil_status(self):
otracky_con = self.get_device_manager().devices.otracky.obj.controller otracky_con = self.device_manager.devices.otracky.obj.controller
if bool(float(otracky_con.socket_put_and_receive("MGtracken").strip())) == 0: if bool(float(otracky_con.socket_put_and_receive("MGtracken").strip())) == 0:
print(self.red+"Tracking in the Galil Controller is disabled."+self.white) print(self.red + "Tracking in the Galil Controller is disabled." + self.white)
print("Use dev.rtx.controller.laser_tracker_galil_enable to enable.\n") print("Use dev.rtx.controller.laser_tracker_galil_enable to enable.\n")
return(0) return 0
else: else:
print("Tracking in the Galil Controller is enabled.") print("Tracking in the Galil Controller is enabled.")
trackyct=int(float(otracky_con.socket_put_and_receive("MGtrackyct").strip())) trackyct = int(float(otracky_con.socket_put_and_receive("MGtrackyct").strip()))
trackzct=int(float(otracky_con.socket_put_and_receive("MGtrackzct").strip())) trackzct = int(float(otracky_con.socket_put_and_receive("MGtrackzct").strip()))
print(f"Galil Trackcounters y={trackyct}, z={trackzct}") print(f"Galil Trackcounters y={trackyct}, z={trackzct}")
def show_signal_strength_interferometer(self): def show_signal_strength_interferometer(self):
channelnames={1:"OSA FZP Y",2:"ST OSA Y",3:"OSA FZP X",4:"ST OSA X",5:"Angle"} channelnames = {1: "OSA FZP Y", 2: "ST OSA Y", 3: "OSA FZP X", 4: "ST OSA X", 5: "Angle"}
self.feedback_get_status_and_ssi() self.feedback_get_status_and_ssi()
t = PrettyTable() t = PrettyTable()
t.title = f"Interferometer signal strength" t.title = f"Interferometer signal strength"
t.field_names = ["Channel", "Name", "Value"] t.field_names = ["Channel", "Name", "Value"]
for i in range(1,6): for i in range(1, 6):
ssi = self.ssi[f"ssi_{i}"] ssi = self.ssi[f"ssi_{i}"]
t.add_row([i,channelnames[i], ssi]) t.add_row([i, channelnames[i], ssi])
print(t) print(t)
def _omny_interferometer_switch_open_socket(self): def _omny_interferometer_switch_open_socket(self):
@@ -722,44 +756,42 @@ class RtOMNYController(Controller):
self._omny_interferometer_switch_put_and_receive("?000\r") self._omny_interferometer_switch_put_and_receive("?000\r")
time.sleep(1) time.sleep(1)
def _omny_interferometer_switch_channel(self, channel): def _omny_interferometer_switch_channel(self, channel):
self._omny_interferometer_switch_alloff() self._omny_interferometer_switch_alloff()
time.sleep(0.1) time.sleep(0.1)
if channel == 1: #Relais 1 and 2 if channel == 1: # Relais 1 and 2
rback = self._omny_interferometer_switch_put_and_receive("!0020003\r") rback = self._omny_interferometer_switch_put_and_receive("!0020003\r")
#if "|0003\r" != self._omny_interferometer_switch_put_and_receive("!0020003\r"): # if "|0003\r" != self._omny_interferometer_switch_put_and_receive("!0020003\r"):
# raise RtOMNY_mirror_switchbox_Error("Channel switching failed.") # raise RtOMNY_mirror_switchbox_Error("Channel switching failed.")
elif channel == 2: #Relais 3 and 4 elif channel == 2: # Relais 3 and 4
rback = self._omny_interferometer_switch_put_and_receive("!002000C\r") rback = self._omny_interferometer_switch_put_and_receive("!002000C\r")
# if "|000C\r" != self._omny_interferometer_switch_put_and_receive("!002000C\r"): # if "|000C\r" != self._omny_interferometer_switch_put_and_receive("!002000C\r"):
# raise RtOMNY_mirror_switchbox_Error("Channel switching failed.") # raise RtOMNY_mirror_switchbox_Error("Channel switching failed.")
elif channel == 3: #Relais 5 and 6 elif channel == 3: # Relais 5 and 6
rback = self._omny_interferometer_switch_put_and_receive("!0020030\r") rback = self._omny_interferometer_switch_put_and_receive("!0020030\r")
# if "|0030\r" != self._omny_interferometer_switch_put_and_receive("!0020030\r"): # if "|0030\r" != self._omny_interferometer_switch_put_and_receive("!0020030\r"):
# raise RtOMNY_mirror_switchbox_Error("Channel switching failed.") # raise RtOMNY_mirror_switchbox_Error("Channel switching failed.")
elif channel == 4: #Relais 7 and 8 elif channel == 4: # Relais 7 and 8
rback = self._omny_interferometer_switch_put_and_receive("!00200C0\r") rback = self._omny_interferometer_switch_put_and_receive("!00200C0\r")
# if "|00C0\r" != self._omny_interferometer_switch_put_and_receive("!00200C0\r"): # if "|00C0\r" != self._omny_interferometer_switch_put_and_receive("!00200C0\r"):
# raise RtOMNY_mirror_switchbox_Error("Channel switching failed.") # raise RtOMNY_mirror_switchbox_Error("Channel switching failed.")
elif channel == 5: #Relais 9 and 10 elif channel == 5: # Relais 9 and 10
rback = self._omny_interferometer_switch_put_and_receive("!0020300\r") rback = self._omny_interferometer_switch_put_and_receive("!0020300\r")
# if "|0300\r" != self._omny_interferometer_switch_put_and_receive("!0020300\r"): # if "|0300\r" != self._omny_interferometer_switch_put_and_receive("!0020300\r"):
# raise RtOMNY_mirror_switchbox_Error("Channel switching failed.") # raise RtOMNY_mirror_switchbox_Error("Channel switching failed.")
elif channel == 6: #Relais 11 and 12 elif channel == 6: # Relais 11 and 12
rback = self._omny_interferometer_switch_put_and_receive("!0020C00\r") rback = self._omny_interferometer_switch_put_and_receive("!0020C00\r")
# if "|0C00\r" != self._omny_interferometer_switch_put_and_receive("!0020C00\r"): # if "|0C00\r" != self._omny_interferometer_switch_put_and_receive("!0020C00\r"):
# raise RtOMNY_mirror_switchbox_Error("Channel switching failed.") # raise RtOMNY_mirror_switchbox_Error("Channel switching failed.")
elif channel == 7: #Relais 13 and 14 elif channel == 7: # Relais 13 and 14
rback = self._omny_interferometer_switch_put_and_receive("!0023000\r") rback = self._omny_interferometer_switch_put_and_receive("!0023000\r")
# if "|3000\r" != self._omny_interferometer_switch_put_and_receive("!0023000\r"): # if "|3000\r" != self._omny_interferometer_switch_put_and_receive("!0023000\r"):
# raise RtOMNY_mirror_switchbox_Error("Channel switching failed.") # raise RtOMNY_mirror_switchbox_Error("Channel switching failed.")
elif channel == 8: #Relais 7 and 8 SPECIAL CASE use osafzp y signal to align osa y elif channel == 8: # Relais 7 and 8 SPECIAL CASE use osafzp y signal to align osa y
rback = self._omny_interferometer_switch_put_and_receive("!00200C0\r") rback = self._omny_interferometer_switch_put_and_receive("!00200C0\r")
# if "|00C0\r" != self._omny_interferometer_switch_put_and_receive("!00200C0\r"): # if "|00C0\r" != self._omny_interferometer_switch_put_and_receive("!00200C0\r"):
# raise RtOMNY_mirror_switchbox_Error("Channel switching failed.") # raise RtOMNY_mirror_switchbox_Error("Channel switching failed.")
elif channel == 9: #Relais 15 and 16 elif channel == 9: # Relais 15 and 16
rback = self._omny_interferometer_switch_put_and_receive("!002C000\r") rback = self._omny_interferometer_switch_put_and_receive("!002C000\r")
# if "|C000\r" != self._omny_interferometer_switch_put_and_receive("!002C000\r"): # if "|C000\r" != self._omny_interferometer_switch_put_and_receive("!002C000\r"):
# raise RtOMNY_mirror_switchbox_Error("Channel switching failed.") # raise RtOMNY_mirror_switchbox_Error("Channel switching failed.")
@@ -785,14 +817,14 @@ class RtOMNYController(Controller):
self._omny_interferometer_switch_put_and_receive("!00S01\r") self._omny_interferometer_switch_put_and_receive("!00S01\r")
def _omny_interferometer_switch_alloff(self): def _omny_interferometer_switch_alloff(self):
#switch all off # switch all off
self._omny_interferometer_switch_put_and_receive("!0020000\r") self._omny_interferometer_switch_put_and_receive("!0020000\r")
#LED OFF # LED OFF
time.sleep(0.1) time.sleep(0.1)
self._omny_interferometer_switch_put_and_receive("!00S00\r") self._omny_interferometer_switch_put_and_receive("!00S00\r")
time.sleep(0.1) time.sleep(0.1)
alloff = self._omny_interferometer_switch_put_and_receive("?002\r") alloff = self._omny_interferometer_switch_put_and_receive("?002\r")
#check all off # check all off
if "00" not in alloff: if "00" not in alloff:
raise RtOMNY_mirror_switchbox_Error("Not all channels switched off.") raise RtOMNY_mirror_switchbox_Error("Not all channels switched off.")
@@ -800,17 +832,16 @@ class RtOMNYController(Controller):
self.socket_put("J3") self.socket_put("J3")
def _omny_interferometer_get_signalsample(self, channel, averaging_duration): def _omny_interferometer_get_signalsample(self, channel, averaging_duration):
#channel is string, eg ssi_1 # channel is string, eg ssi_1
#ensure no averaging running currently # ensure no averaging running currently
self.feedback_is_running() self.feedback_is_running()
#measure first sample # measure first sample
self._rt_start_averaging_SSI() self._rt_start_averaging_SSI()
time.sleep(averaging_duration) time.sleep(averaging_duration)
self.feedback_is_running() self.feedback_is_running()
return self.ssi[channel] return self.ssi[channel]
def _get_signals_from_table(self, return_table) -> dict: def _get_signals_from_table(self, return_table) -> dict:
self.average_stdeviations_x_st_fzp += float(return_table[16]) self.average_stdeviations_x_st_fzp += float(return_table[16])
self.average_stdeviations_y_st_fzp += float(return_table[18]) self.average_stdeviations_y_st_fzp += float(return_table[18])
@@ -831,7 +862,6 @@ class RtOMNYController(Controller):
"stdev_x_st_fzp": {"value": float(return_table[16])}, "stdev_x_st_fzp": {"value": float(return_table[16])},
"average_y_st_fzp": {"value": float(return_table[17])}, "average_y_st_fzp": {"value": float(return_table[17])},
"stdev_y_st_fzp": {"value": float(return_table[18])}, "stdev_y_st_fzp": {"value": float(return_table[18])},
"average_stdeviations_x_st_fzp": { "average_stdeviations_x_st_fzp": {
"value": self.average_stdeviations_x_st_fzp / (int(return_table[0]) + 1) "value": self.average_stdeviations_x_st_fzp / (int(return_table[0]) + 1)
}, },
@@ -840,7 +870,7 @@ class RtOMNYController(Controller):
}, },
} }
return signals return signals
@threadlocked @threadlocked
def start_scan(self): def start_scan(self):
if not self.feedback_is_running(): if not self.feedback_is_running():
@@ -862,7 +892,6 @@ class RtOMNYController(Controller):
# start a point-by-point scan (for cont scan in flomni it would be "sa") # start a point-by-point scan (for cont scan in flomni it would be "sa")
self.socket_put_and_receive("sd") self.socket_put_and_receive("sd")
@retry_once @retry_once
@threadlocked @threadlocked
def get_scan_status(self): def get_scan_status(self):
@@ -881,13 +910,6 @@ class RtOMNYController(Controller):
current_position_in_scan = int(float(return_table[2])) current_position_in_scan = int(float(return_table[2]))
return (mode, number_of_positions_planned, current_position_in_scan) return (mode, number_of_positions_planned, current_position_in_scan)
def get_device_manager(self):
for axis in self._axis:
if hasattr(axis, "device_manager") and axis.device_manager:
return axis.device_manager
raise BECConfigError("Could not access the device_manager")
def read_positions_from_sampler(self): def read_positions_from_sampler(self):
# this was for reading after the scan completed # this was for reading after the scan completed
number_of_samples_to_read = 1 # self.get_scan_status()[1] #number of valid samples, will be updated upon first data read number_of_samples_to_read = 1 # self.get_scan_status()[1] #number of valid samples, will be updated upon first data read
@@ -901,7 +923,7 @@ class RtOMNYController(Controller):
# if not (mode==2 or mode==3): # if not (mode==2 or mode==3):
# error # error
self.get_device_manager().connector.set( self.device_manager.connector.set(
MessageEndpoints.device_status("rt_scan"), MessageEndpoints.device_status("rt_scan"),
messages.DeviceStatusMessage( messages.DeviceStatusMessage(
device="rt_scan", status=1, metadata=self.readout_metadata device="rt_scan", status=1, metadata=self.readout_metadata
@@ -936,7 +958,7 @@ class RtOMNYController(Controller):
signals = self._get_signals_from_table(return_table) signals = self._get_signals_from_table(return_table)
self.publish_device_data(signals=signals, point_id=int(return_table[0])) self.publish_device_data(signals=signals, point_id=int(return_table[0]))
self.get_device_manager().connector.set( self.device_manager.connector.set(
MessageEndpoints.device_status("rt_scan"), MessageEndpoints.device_status("rt_scan"),
messages.DeviceStatusMessage( messages.DeviceStatusMessage(
device="rt_scan", status=0, metadata=self.readout_metadata device="rt_scan", status=0, metadata=self.readout_metadata
@@ -949,15 +971,16 @@ class RtOMNYController(Controller):
f" {self.average_stdeviations_y_st_fzp/read_counter*1000:.1f}." f" {self.average_stdeviations_y_st_fzp/read_counter*1000:.1f}."
) )
self.get_device_manager().connector.send_client_info( self.device_manager.connector.send_client_info(
"OMNY statistics: Average of all standard deviations [nm]: x" "OMNY statistics: Average of all standard deviations [nm]: x"
f" {self.average_stdeviations_x_st_fzp/read_counter*1000:.1f}, y" f" {self.average_stdeviations_x_st_fzp/read_counter*1000:.1f}, y"
f" {self.average_stdeviations_y_st_fzp/read_counter*1000:.1f}.", f" {self.average_stdeviations_y_st_fzp/read_counter*1000:.1f}.",
scope="", show_asap=True) scope="",
show_asap=True,
)
def publish_device_data(self, signals, point_id): def publish_device_data(self, signals, point_id):
self.get_device_manager().connector.set_and_publish( self.device_manager.connector.set_and_publish(
MessageEndpoints.device_read("rt_omny"), MessageEndpoints.device_read("rt_omny"),
messages.DeviceMessage( messages.DeviceMessage(
signals=signals, metadata={"point_id": point_id, **self.readout_metadata} signals=signals, metadata={"point_id": point_id, **self.readout_metadata}
@@ -1068,7 +1091,7 @@ class RtOMNYMotor(Device, PositionerBase):
self.axis_Id = axis_Id self.axis_Id = axis_Id
self.sign = sign self.sign = sign
self.controller = RtOMNYController( self.controller = RtOMNYController(
socket_cls=socket_cls, socket_host=host, socket_port=port socket_cls=socket_cls, socket_host=host, socket_port=port, device_manager=device_manager
) )
self.controller.set_axis(axis=self, axis_nr=self.axis_Id_numeric) self.controller.set_axis(axis=self, axis_nr=self.axis_Id_numeric)
self.device_manager = device_manager self.device_manager = device_manager
@@ -1096,6 +1119,10 @@ class RtOMNYMotor(Device, PositionerBase):
self.low_limit_travel.put(limits[0]) self.low_limit_travel.put(limits[0])
self.high_limit_travel.put(limits[1]) self.high_limit_travel.put(limits[1])
def wait_for_connection(self, timeout: int = 30, **kwargs) -> None:
"""Wait for the device to be connected."""
self.controller.on(timeout=timeout)
@property @property
def limits(self): def limits(self):
return (self.low_limit_travel.get(), self.high_limit_travel.get()) return (self.low_limit_travel.get(), self.high_limit_travel.get())
@@ -1182,7 +1209,6 @@ class RtOMNYMotor(Device, PositionerBase):
return status return status
@property @property
def axis_Id(self): def axis_Id(self):
return self._axis_Id_alpha return self._axis_Id_alpha
@@ -1227,7 +1253,7 @@ class RtOMNYMotor(Device, PositionerBase):
if __name__ == "__main__": if __name__ == "__main__":
rtcontroller = RtOMNYController( rtcontroller = RtOMNYController(
socket_cls=SocketIO, socket_host="mpc2844.psi.ch", socket_port=2222 socket_cls=SocketIO, socket_host="mpc2844.psi.ch", socket_port=2222, device_manager=None
) )
rtcontroller.on() rtcontroller.on()
rtcontroller.laser_tracker_on() rtcontroller.laser_tracker_on()

View File

@@ -93,6 +93,7 @@ class SmaractController(Controller):
socket_cls=None, socket_cls=None,
socket_host=None, socket_host=None,
socket_port=None, socket_port=None,
device_manager=None,
attr_name="", attr_name="",
labels=None, labels=None,
): ):
@@ -102,6 +103,7 @@ class SmaractController(Controller):
socket_cls=socket_cls, socket_cls=socket_cls,
socket_host=socket_host, socket_host=socket_host,
socket_port=socket_port, socket_port=socket_port,
device_manager=device_manager,
attr_name=attr_name, attr_name=attr_name,
parent=parent, parent=parent,
labels=labels, labels=labels,

View File

@@ -123,10 +123,11 @@ class SmaractMotor(Device, PositionerBase):
limits=None, limits=None,
sign=1, sign=1,
socket_cls=SocketIO, socket_cls=SocketIO,
device_manager=None,
**kwargs, **kwargs,
): ):
self.controller = SmaractController( self.controller = SmaractController(
socket_cls=socket_cls, socket_host=host, socket_port=port socket_cls=socket_cls, socket_host=host, socket_port=port, device_manager=device_manager
) )
self.axis_Id = axis_Id self.axis_Id = axis_Id
self.sign = sign self.sign = sign

View File

@@ -7,10 +7,15 @@ from csaxs_bec.devices.omny.galil.fupr_ophyd import FuprGalilController, FuprGal
@pytest.fixture @pytest.fixture
def fsamroy(): def fsamroy(dm_with_devices):
FuprGalilController._reset_controller() FuprGalilController._reset_controller()
fsamroy_motor = FuprGalilMotor( fsamroy_motor = FuprGalilMotor(
"A", name="fsamroy", host="mpc2680.psi.ch", port=8081, socket_cls=SocketMock "A",
name="fsamroy",
host="mpc2680.psi.ch",
port=8081,
socket_cls=SocketMock,
device_manager=dm_with_devices,
) )
fsamroy_motor.controller.on() fsamroy_motor.controller.on()
assert isinstance(fsamroy_motor.controller, FuprGalilController) assert isinstance(fsamroy_motor.controller, FuprGalilController)

View File

@@ -8,10 +8,15 @@ from csaxs_bec.devices.omny.galil.lgalil_ophyd import LamniGalilController, Lamn
@pytest.fixture(scope="function") @pytest.fixture(scope="function")
def leyey(): def leyey(dm_with_devices):
LamniGalilController._reset_controller() LamniGalilController._reset_controller()
leyey_motor = LamniGalilMotor( leyey_motor = LamniGalilMotor(
"H", name="leyey", host="mpc2680.psi.ch", port=8081, socket_cls=SocketMock "H",
name="leyey",
host="mpc2680.psi.ch",
port=8081,
socket_cls=SocketMock,
device_manager=dm_with_devices,
) )
leyey_motor.controller.on() leyey_motor.controller.on()
yield leyey_motor yield leyey_motor
@@ -20,10 +25,15 @@ def leyey():
@pytest.fixture(scope="function") @pytest.fixture(scope="function")
def leyex(): def leyex(dm_with_devices):
LamniGalilController._reset_controller() LamniGalilController._reset_controller()
leyex_motor = LamniGalilMotor( leyex_motor = LamniGalilMotor(
"A", name="leyey", host="mpc2680.psi.ch", port=8081, socket_cls=SocketMock "A",
name="leyey",
host="mpc2680.psi.ch",
port=8081,
socket_cls=SocketMock,
device_manager=dm_with_devices,
) )
leyex_motor.controller.on() leyex_motor.controller.on()
yield leyex_motor yield leyex_motor

View File

@@ -7,10 +7,15 @@ from csaxs_bec.devices.omny.galil.fgalil_ophyd import FlomniGalilController, Flo
@pytest.fixture(scope="function") @pytest.fixture(scope="function")
def leyey(): def leyey(dm_with_devices):
FlomniGalilController._reset_controller() FlomniGalilController._reset_controller()
leyey_motor = FlomniGalilMotor( leyey_motor = FlomniGalilMotor(
"H", name="leyey", host="mpc2680.psi.ch", port=8081, socket_cls=SocketMock "H",
name="leyey",
host="mpc2680.psi.ch",
port=8081,
socket_cls=SocketMock,
device_manager=dm_with_devices,
) )
leyey_motor.controller.on() leyey_motor.controller.on()
yield leyey_motor yield leyey_motor
@@ -19,10 +24,15 @@ def leyey():
@pytest.fixture(scope="function") @pytest.fixture(scope="function")
def leyex(): def leyex(dm_with_devices):
FlomniGalilController._reset_controller() FlomniGalilController._reset_controller()
leyex_motor = FlomniGalilMotor( leyex_motor = FlomniGalilMotor(
"H", name="leyey", host="mpc2680.psi.ch", port=8081, socket_cls=SocketMock "H",
name="leyey",
host="mpc2680.psi.ch",
port=8081,
socket_cls=SocketMock,
device_manager=dm_with_devices,
) )
leyex_motor.controller.on() leyex_motor.controller.on()
yield leyex_motor yield leyex_motor
@@ -157,11 +167,16 @@ def test_find_reference(leyex, axis_nr, socket_put_messages, socket_get_messages
], ],
) )
def test_fosaz_light_curtain_is_triggered( def test_fosaz_light_curtain_is_triggered(
axis_Id, socket_put_messages, socket_get_messages, triggered axis_Id, socket_put_messages, socket_get_messages, triggered, dm_with_devices
): ):
"""test that the light curtain is triggered""" """test that the light curtain is triggered"""
fosaz = FlomniGalilMotor( fosaz = FlomniGalilMotor(
axis_Id, name="fosaz", host="mpc2680.psi.ch", port=8081, socket_cls=SocketMock axis_Id,
name="fosaz",
host="mpc2680.psi.ch",
port=8081,
socket_cls=SocketMock,
device_manager=dm_with_devices,
) )
fosaz.controller.on() fosaz.controller.on()
fosaz.controller.sock.flush_buffer() fosaz.controller.sock.flush_buffer()

View File

@@ -16,7 +16,10 @@ def controller():
""" """
with mock.patch("ophyd_devices.utils.socket.SocketIO") as socket_cls: with mock.patch("ophyd_devices.utils.socket.SocketIO") as socket_cls:
controller = NPointController( controller = NPointController(
socket_cls=socket_cls, socket_host="localhost", socket_port=1234 socket_cls=socket_cls,
socket_host="localhost",
socket_port=1234,
device_manager=mock.MagicMock(),
) )
controller.on() controller.on()
controller.sock.reset_mock() controller.sock.reset_mock()
@@ -25,13 +28,18 @@ def controller():
@pytest.fixture @pytest.fixture
def npointx(): def npointx(dm_with_devices):
""" """
Fixture to create a NPointAxis object. Fixture to create a NPointAxis object.
""" """
controller = mock.MagicMock() controller = mock.MagicMock()
npointx = NPointAxis( npointx = NPointAxis(
axis_Id="A", name="npointx", host="localhost", port=1234, socket_cls=controller axis_Id="A",
name="npointx",
host="localhost",
port=1234,
socket_cls=controller,
device_manager=dm_with_devices,
) )
npointx.controller.on() npointx.controller.on()
npointx.controller.sock.reset_mock() npointx.controller.sock.reset_mock()
@@ -107,13 +115,18 @@ def test_axis_get_in(npointx, axis, msg_in, msg_out):
npointx.controller.sock.put.assert_called_once_with(msg_in) npointx.controller.sock.put.assert_called_once_with(msg_in)
def test_axis_out_of_range(controller): def test_axis_out_of_range(dm_with_devices):
""" """
Test that an error is raised when trying to create an NPointAxis object with an invalid axis ID. Test that an error is raised when trying to create an NPointAxis object with an invalid axis ID.
""" """
with pytest.raises(ValueError): with pytest.raises(ValueError):
npointx = NPointAxis( npointx = NPointAxis(
axis_Id="G", name="npointx", host="localhost", port=1234, socket_cls=mock.MagicMock() axis_Id="G",
name="npointx",
host="localhost",
port=1234,
socket_cls=mock.MagicMock(),
device_manager=dm_with_devices,
) )

View File

@@ -11,26 +11,29 @@ from csaxs_bec.devices.omny.rt.rt_ophyd import RtError
def rt_flomni(): def rt_flomni():
RtFlomniController._reset_controller() RtFlomniController._reset_controller()
rt_flomni = RtFlomniController( rt_flomni = RtFlomniController(
name="rt_flomni", socket_cls=SocketMock, socket_host="localhost", socket_port=8081 name="rt_flomni",
socket_cls=SocketMock,
socket_host="localhost",
socket_port=8081,
device_manager=mock.MagicMock(),
) )
with mock.patch.object(rt_flomni, "get_device_manager"): with mock.patch.object(rt_flomni, "sock"):
with mock.patch.object(rt_flomni, "sock"): rtx = mock.MagicMock(spec=RtFlomniMotor)
rtx = mock.MagicMock(spec=RtFlomniMotor) rtx.name = "rtx"
rtx.name = "rtx" rtx.axis_Id = "A"
rtx.axis_Id = "A" rtx.axis_Id_numeric = 0
rtx.axis_Id_numeric = 0 rty = mock.MagicMock(spec=RtFlomniMotor)
rty = mock.MagicMock(spec=RtFlomniMotor) rty.name = "rty"
rty.name = "rty" rty.axis_Id = "B"
rty.axis_Id = "B" rty.axis_Id_numeric = 1
rty.axis_Id_numeric = 1 rtz = mock.MagicMock(spec=RtFlomniMotor)
rtz = mock.MagicMock(spec=RtFlomniMotor) rtz.name = "rtz"
rtz.name = "rtz" rtz.axis_Id = "C"
rtz.axis_Id = "C" rtz.axis_Id_numeric = 2
rtz.axis_Id_numeric = 2 rt_flomni.set_axis(axis=rtx, axis_nr=0)
rt_flomni.set_axis(axis=rtx, axis_nr=0) rt_flomni.set_axis(axis=rty, axis_nr=1)
rt_flomni.set_axis(axis=rty, axis_nr=1) rt_flomni.set_axis(axis=rtz, axis_nr=2)
rt_flomni.set_axis(axis=rtz, axis_nr=2) yield rt_flomni
yield rt_flomni
RtFlomniController._reset_controller() RtFlomniController._reset_controller()
@@ -52,7 +55,7 @@ def test_rt_flomni_feedback_is_running(rt_flomni, return_value, is_running):
def test_feedback_enable_with_reset(rt_flomni): def test_feedback_enable_with_reset(rt_flomni):
device_manager = rt_flomni.get_device_manager() device_manager = rt_flomni.device_manager
device_manager.devices.fsamx.user_parameter.get.return_value = 0.05 device_manager.devices.fsamx.user_parameter.get.return_value = 0.05
device_manager.devices.fsamx.obj.readback.get.return_value = 0.05 device_manager.devices.fsamx.obj.readback.get.return_value = 0.05
@@ -68,7 +71,7 @@ def test_feedback_enable_with_reset(rt_flomni):
def test_move_samx_to_scan_region(rt_flomni): def test_move_samx_to_scan_region(rt_flomni):
device_manager = rt_flomni.get_device_manager() device_manager = rt_flomni.device_manager
device_manager.devices.rtx.user_parameter.get.return_value = 1 device_manager.devices.rtx.user_parameter.get.return_value = 1
rt_flomni.move_samx_to_scan_region(20, 2) rt_flomni.move_samx_to_scan_region(20, 2)
assert mock.call(b"v0\n") not in rt_flomni.sock.put.mock_calls assert mock.call(b"v0\n") not in rt_flomni.sock.put.mock_calls
@@ -76,16 +79,16 @@ def test_move_samx_to_scan_region(rt_flomni):
def test_feedback_enable_without_reset(rt_flomni): def test_feedback_enable_without_reset(rt_flomni):
with mock.patch.object(rt_flomni, "set_device_enabled") as set_device_enabled: with mock.patch.object(rt_flomni, "set_device_read_write") as set_device_read_write:
with mock.patch.object(rt_flomni, "feedback_is_running", return_value=True): with mock.patch.object(rt_flomni, "feedback_is_running", return_value=True):
with mock.patch.object(rt_flomni, "laser_tracker_on") as laser_tracker_on: with mock.patch.object(rt_flomni, "laser_tracker_on") as laser_tracker_on:
rt_flomni.feedback_enable_without_reset() rt_flomni.feedback_enable_without_reset()
laser_tracker_on.assert_called_once() laser_tracker_on.assert_called_once()
assert mock.call(b"l3\n") in rt_flomni.sock.put.mock_calls assert mock.call(b"l3\n") in rt_flomni.sock.put.mock_calls
assert mock.call("fsamx", False) in set_device_enabled.mock_calls assert mock.call("fsamx", False) in set_device_read_write.mock_calls
assert mock.call("fsamy", False) in set_device_enabled.mock_calls assert mock.call("fsamy", False) in set_device_read_write.mock_calls
assert mock.call("foptx", False) in set_device_enabled.mock_calls assert mock.call("foptx", False) in set_device_read_write.mock_calls
assert mock.call("fopty", False) in set_device_enabled.mock_calls assert mock.call("fopty", False) in set_device_read_write.mock_calls
def test_feedback_enable_without_reset_raises(rt_flomni): def test_feedback_enable_without_reset_raises(rt_flomni):

View File

@@ -10,19 +10,27 @@ from csaxs_bec.devices.smaract.smaract_ophyd import SmaractMotor
@pytest.fixture @pytest.fixture
def controller(): def controller(dm_with_devices):
SmaractController._reset_controller() SmaractController._reset_controller()
controller = SmaractController(socket_cls=SocketMock, socket_host="dummy", socket_port=123) controller = SmaractController(
socket_cls=SocketMock, socket_host="dummy", socket_port=123, device_manager=dm_with_devices
)
controller.on() controller.on()
controller.sock.flush_buffer() controller.sock.flush_buffer()
yield controller yield controller
@pytest.fixture @pytest.fixture
def lsmarA(): def lsmarA(dm_with_devices):
SmaractController._reset_controller() SmaractController._reset_controller()
motor_a = SmaractMotor( motor_a = SmaractMotor(
"A", name="lsmarA", host="mpc2680.psi.ch", port=8085, sign=1, socket_cls=SocketMock "A",
name="lsmarA",
host="mpc2680.psi.ch",
port=8085,
sign=1,
socket_cls=SocketMock,
device_manager=dm_with_devices,
) )
motor_a.controller.on() motor_a.controller.on()
motor_a.controller.sock.flush_buffer() motor_a.controller.sock.flush_buffer()