optics movements

This commit is contained in:
Holler Mirko
2024-11-05 15:06:35 +01:00
committed by wakonig_k
parent 78b838f516
commit 29a8e1b281
6 changed files with 215 additions and 84 deletions
@@ -37,6 +37,30 @@ class OMNYError(Exception):
class OMNYInitStagesMixin:
def enable_all_devices():
dev.ofzpx.enabled = True
dev.ofzpy.enabled = True
dev.ofzpz.enabled = True
dev.otransx.enabled = True
dev.otransy.enabled = True
dev.otransz.enabled = True
dev.osamx.enabled = True
dev.osamz.enabled = True
dev.oosay.enabled = True
dev.oosax.enabled = True
dev.oosaz.enabled = True
dev.oparkz.enabled = True
dev.oshuttleopen.enabled = True
dev.oshuttlealign.enabled = True
dev.osamy.enabled = True
dev.otracky.enabled = True
dev.osamroy.enabled = True
dev.otrackz.enabled = True
dev.oeyex.enabled = True
dev.oeyez.enabled = True
dev.oeyey.enabled = True
def _omny_find_reference_loop(self, direction_endswitch, device, auto_retry=0):
retry_counter = 0
limits = device.get_motor_limit_switch()
@@ -76,6 +100,9 @@ class OMNYInitStagesMixin:
self.OMNYTools.printgreen(f"The temperature of the motor is {temperature}, and larger than the threshold of 100 degC. Waiting 60 s for cool down.")
time.sleep(60)
temperature = device.get_motor_temperature()
if retry_counter == auto_retry:
self.OMNYTools.printgreen("Maximum automatic init retries reached. Setting auto to 0 offering manual continuation.")
auto_retry = 0
def _check_for_folerr_and_reset(self, device):
#if device.folerr_status():
@@ -83,6 +110,7 @@ class OMNYInitStagesMixin:
# if user_input == "y":
#for now we just reset and ignore. because it might just occur at the beginning of move to ES
device._ogalil_folerr_reset_and_ignore()
time.sleep(0.3)
def omny_init_stages(self, autoconfirm=0, autoretry=0):
@@ -101,7 +129,7 @@ class OMNYInitStagesMixin:
return
if self.check_all_axes_of_OMNY_referenced():
if self.OMNYTools.yesno("All axes are referenced already. Continue anyways?","n"):
if self.OMNYTools.yesno("All axes are referenced already. Reset and reference again?","n"):
self.OMNYTools.printgreen("ok then...")
else:
return
@@ -115,6 +143,12 @@ class OMNYInitStagesMixin:
umv(dev.oshield, 0)
dev.ofzpx.controller.socket_put_confirmed("XQ#CRESET")
dev.osamx.controller.socket_put_confirmed("XQ#CRESET")
dev.osamy.controller.socket_put_confirmed("XQ#CRESET")
time.sleep(1)
if self.OMNYTools.yesno("drive fzp to -Z,-X,+Y limit and reference?","y",autoconfirm=autoconfirm):
dev.ofzpz.drive_axis_to_limit("forward")
self.OMNYTools.printgreen("ofzpz reached limit")
@@ -195,6 +229,7 @@ class OMNYInitStagesMixin:
if self.OMNYTools.yesno("find reference mark of oeyey?","y",autoconfirm=autoconfirm):
#print("oeyey now in limit")
dev.oeyez.drive_axis_to_limit("forward")
dev.oeyey.controller.socket_put_confirmed("indspeed[7]=2000")
#dev.oeyey.find_reference()
self._omny_find_reference_loop("forward", dev.oeyey,auto_retry=autoretry)
@@ -378,24 +413,28 @@ class OMNYInitStagesMixin:
raise OMNYInitError("Automatic init not possible.")
dev.oshield.controller.find_reference_mark(2, 0, 1000, 1)
time.sleep(2)
dev.oshield.limits = [-14.5, 15.8]
dev.ocsx.limits = [-2, 4.3]
dev.ocsy.limits = [-1, 3]
dev.oshield.controller.set_closed_loop_move_speed(0,1)
dev.oshield.controller.set_closed_loop_move_speed(1,1)
dev.oshield.controller.set_closed_loop_move_speed(2,1)
dev.oshield.controller.set_closed_loop_move_speed(0,2)
dev.oshield.controller.set_closed_loop_move_speed(1,2)
dev.oshield.controller.set_closed_loop_move_speed(2,2)
#enable sensor for repeatable open loop motion
dev.oshield.controller.socket_put_and_receive("SSE1")
if self.OMNYTools.yesno("Move CS out of the beam path?","y"):
umv(dev.ocsx, 4.3, dev.ocsy, 2)
self.OMNYTools.printgreen("Finished initialization of OMNY smaract system")
def _setalllimitsomny():
dev.rtx.limits = [-250, 250]
dev.rty.limits = [-250, 250]
dev.rtz.limits = [-250, 250]
def _setalllimitsomny(self):
# dev.rtx.limits = [-250, 250]
# dev.rty.limits = [-250, 250]
# dev.rtz.limits = [-250, 250]
dev.osamx.limits = [-1, 1]
dev.osamy.limits = [2.3000, 3.0000]
dev.osamroy.limits = [-27.0000, 337.0000]
@@ -442,18 +481,10 @@ class OMNYInitStagesMixin:
self._oshield_ST_close()
dev.otracky.limits = [-7, -3]
dev.otracky.limits = [-2, 1]
dev.otrackz.limits = [-2, 1]
otracky_start_pos = dev.otracky.user_parameter.get("start_pos")
if otracky_start_pos is None:
raise OMNYInitError(
"Could not find otracky start position. Please check your device config."
)
otrackz_start_pos = dev.otrackz.user_parameter.get("start_pos")
if otrackz_start_pos is None:
raise OMNYInitError(
"Could not find otrackz start position. Please check your device config."
)
otracky_start_pos = self.OMNYTools._get_user_param_safe("otracky","start_pos")
otrackz_start_pos = self.OMNYTools._get_user_param_safe("otrackz","start_pos")
umv(dev.otracky, otracky_start_pos, dev.otrackz, otrackz_start_pos)
@@ -468,9 +499,6 @@ class OMNYInitStagesMixin:
dev.osamy.controller.socket_put_confirmed("DCE=11264")
dev.osamy.controller.socket_put_confirmed("DCB=11264")
#adjust osamy velocity
dev.osamy.controller.socket_put_confirmed("axspeed[0]=1000")
def check_all_axes_of_OMNY_referenced(self) -> bool:
if (
@@ -42,15 +42,15 @@ class OMNYTools:
def yesno(self,message :str,default="none",autoconfirm=0) -> bool:
if autoconfirm and default == "y":
self.printgreen (message + "Automatically confirming default: yes")
self.printgreen (message + " Automatically confirming default: yes")
return True
elif autoconfirm and default == "n":
self.printgreen (message + "Automatically confirming default: no")
self.printgreen (message + " Automatically confirming default: no")
return False
if default == "y":
message_ending = " Y/n? "
message_ending = " [Y]/n? "
elif default == "n":
message_ending = " y/N? "
message_ending = " y/[N]? "
else:
message_ending = " y/n? "
while True:
@@ -46,27 +46,29 @@ class OMNYOpticsMixin:
def oeye_out(self):
fshclose()
user_input = input("Did you move in the optics?")
if user_input == "y":
if self.OMNYTools.yesno("Did you move in the optics?"):
umv(dev.oeyez, -2)
self._oeyey_mv(-60.3)
# free camera
epics_put("XOMNYI-XEYE-ACQ:0", 2)
else:
raise OMNYError("The optics were not moved in. Please do so prior to eyey_out")
self.OMNYTools.printgreen("Oeye is out.")
def oeye_cam_in(self):
if dev.oeyez.get().readback < -80:
umv(dev.oeyez, -50)
if np.fabs(dev.oeyey.get().readback+4.8) > 0.1:
self._oeyey_mv -4.8
self._oeyey_mv(-4.8)
if np.fabs(dev.oeyez.get().readback+2) > 0.1 or np.fabs(dev.oeyex.get().readback) > 0.1:
umv(dev.oeyez, -2, dev.oeyex, 0)
#if still too close in z -- safety check
if np.fabs(dev.oeyez.get().readback+2) > 0.1:
raise OMNYError("The oeye is too close in z for transfer. ERROR! Aborting.\n")
raise OMNYError("The oeye is too close in z for transfer. ERROR! Aborting.")
self.OMNYTools.printgreen("Oeye is at cam position.")
def _oeye_xray_is_in(self) -> bool:
@@ -100,6 +102,7 @@ class OMNYOpticsMixin:
if np.fabs(omny_oeye_currenty-omny_oeye_xray_iny)>0.1:
raise OMNYError("The oeye did not move up.\n")
umv(dev.oeyex, omny_oeye_xray_inx, dev.oeyez, omny_oeye_xray_inz)
self.OMNYTools.printgreen("Oeye is at X-ray position.")
#some notes for the vis microscope:
#initial position for the vis light microscope
@@ -128,60 +131,69 @@ class OMNYOpticsMixin:
raise OMNYError("oosax did not reach target position. Not moving in z.\n")
def oosa_in(self):
#todo _omnycam_samplestage
self._oosa_check_y()
dev.oshield.read(cached=False)
omny_oshield_current = dev.oshield.get().readback
if omny_oshield_current<15:
#todo _oshield_ST_close
print("todo")
self._oshield_ST_close()
if self.near_field==False:
x_in_pos = self._get_user_param_safe("oosax", "far_field_in")
y_in_pos = self._get_user_param_safe("oosay", "far_field_in")
z_in_pos = self._get_user_param_safe("oosaz", "far_field_in")
print("OSA movement in far-field mode.")
dev.oosaz.read(cached=False)
omny_oosa_currentz = dev.oosaz.get().readback
if omny_oosa_currentz<6.4:
self._oosa_to_move_corridor()
dev.oosaz.limits = [6.4, 6.6]
umv(dev.oosaz, 6.5)
umv(dev.oosax, 3.022)
umv(oosay, 0.4122)
umv(dev.oosaz, z_in_pos)
umv(dev.oosax, x_in_pos)
umv(dev.oosay, y_in_pos)
#### For the 30 nm FZP 220 um we use this part
# umv oosaz 6.5
# umv oosax 3.2453
# umv oosay 0.386015
if self.near_field==True:
x_in_pos = self._get_user_param_safe("oosax", "near_field_in")
y_in_pos = self._get_user_param_safe("oosay", "near_field_in")
z_in_pos = self._get_user_param_safe("oosaz", "near_field_in")
print("OSA movement in near-field mode.")
dev.oosaz.read(cached=False)
omny_oosa_currentz = dev.oosaz.get().readback
if omny_oosa_currentz>0:
self._oosa_to_move_corridor()
dev.oosaz.limits = [-0.4, -0.6]
umv(dev.oosaz, -0.4452)
umv(dev.oosax, 3.2124-0.008)
umv(dev.oosaz, z_in_pos)
umv(dev.oosax, x_in_pos)
omny_osamy_current = dev.osamy.get().readback
if omny_osamy_current<3.25:
umv(dev.oosay, 0.5330-0.002)
umv(dev.oosay, y_in_pos)
else:
raise OMNYError("Failed to move oosa in. osamy position is too large.")
self.OMNYTools.printgreen("OSA is in.")
#todo
# _omny_interferometer_align_tracking
# rt_feedback_enable
def oosa_out(self):
#todo: _omnycam_samplestage
self._oosa_check_y()
dev.oshield.read(cached=False)
omny_oshield_current = dev.oshield.get().readback
if omny_oshield_current<15:
#todo: self._oshield_ST_close()
print("todo")
self._oshield_ST_close()
omny_oosaz_current = dev.oosaz.get().readback
if self.near_field==False:
print("OSA movement in far-field mode.")
if omny_oosaz_current<6.4:
self._oosa_to_move_corridor()
dev.oosaz.limits = [6.4, 6.6]
umv(dev.oosaz, 6.5)
umv(dev.oosax, -2)
if self.near_field==True:
print("OSA movement in near-field mode.")
if omny_oosaz_current>0:
self._oosa_to_move_corridor()
dev.oosaz.limits = [-0.4, -0.6]
@@ -189,6 +201,8 @@ class OMNYOpticsMixin:
umv(dev.oosax, -2)
#todo _omny_interferometer_align_tracking
self.OMNYTools.printgreen("OSA is out.")
def oosa_move_out_of_shield(self):
#todo: _omnycam_samplestage
self._oosa_check_y()
@@ -201,21 +215,99 @@ class OMNYOpticsMixin:
dev.oosaz.limits = [-0.1, 0.1]
umv(dev.oosaz, 0)
self.OMNYTools.printgreen("OSA is out of shield.")
def ofzp_out(self):
if "rtx" in dev and dev.rtx.enabled:
dev.rtx.controller.feedback_disable()
y_out_pos = self._get_user_param_safe("ofzpy", "out")
if np.fabs(dev.ofzpy.get().readback-y_out_pos)>0.02:
umv(dev.ofzpy, y_out_pos)
self.OMNYTools.printgreen("FZP at out position")
def ofzp_in(self):
if "rtx" in dev and dev.rtx.enabled:
dev.rtx.controller.feedback_disable()
x_in_pos = self._get_user_param_safe("ofzpx", "in")
y_in_pos = self._get_user_param_safe("ofzpy", "in")
if np.fabs(dev.ofzpy.get().readback-y_in_pos)>0.02:
umv(dev.ofzpy, y_in_pos)
if np.fabs(dev.ofzpx.get().readback-x_in_pos)>0.02:
umv(dev.ofzpx, x_in_pos)
self.OMNYTools.printgreen("FZP at in position")
#220 mu FZP at ofzpz 31.8025 for eiger probe (about 2.4 mm propagation after focus)
# umv(dev.ofzpy, 0.7944)
# if np.fabs(dev.ofzpx.get().readback+0.4317)>0.05:
# umv(dev.ofzpx, -0.4317)
#note the 220 fzp also works for near field 6.2 kev by just moving back osa and fzp
#ofzpz 24.8 leads to a 9.5 mm propagation distance.
#With the 220 mu FZP this gives 100 nm pixel recons
#for the oosa macro set near_field=1
#170 mu FZP at 6.2 kev for large beam at ofzpz 31.8025 of about 58 mu diameter
#120 mu FZP at ofzpz 28.1991
#250 mu FZP 60 nm at 5.65 keV
#ofzpz 29.7 for propagation distance 2.2
#umv ofzpx -0.4457
#umv ofzpy 0.193630
#150 um fzp, 60 nm, ofzpz 33.8 at 8.9 kev for propagation of 1.7 mm after focus
#umv ofzpx -0.756678
#umv ofzpy 0.193515
#250 um 30 nm FZP upper right
#small abberrations, seems to give good results in weak objects
#ofzpx -0.609240
#umv ofzpy 0.118265
#250 um 30 nm FZP lower right very aberated
#ofzpx -0.881935
#umv ofzpy 0.537050
#ofzpz 28.4027
#5.30 mm prop at 8.9 keV, 45 nm pixel in near field
#ofzpz 33.103
#0.6 mm prop at 8.9 kev far field 7 m flight tube at foptz
#ofzpz 49.4 is reachable just without interferometer swap
#which at 6.2 keV and 250 um diam, 30 nm should gives a propagation of 0.8 after focus
#and a beam size of 6 microns diamter
###coordinates 30 nm FZP for comparing them
#not sure if that is really correct
#FZP 1 - FZP 2
# FZP 5
#FZP 4 - FZP 1
#FZP
##upper right
#umv ofzpx -0.6154 ofzpy 0.1183
#umv ocsx -0.6070 ocsy 0.0540
#lower right
#umv ofzpx -0.8341 ofzpy 0.5683
#umv ocsx -0.3880 ocsy -0.3960
#lower left
#umv ofzpx -0.3876 ofzpy 0.7902
#umv ocsx -0.8380 ocsy -0.6180
#upper left
#umv ofzpx -0.1678 ofzpy 0.3403
#umv ocsx -1.0550 ocsy -0.1680
foptx_in = self._get_user_param_safe("foptx", "in")
fopty_in = self._get_user_param_safe("fopty", "in")
umv(dev.foptx, foptx_in)
def ffzp_info(self, mokev_val=-1):
def ffzp_info(self, mokev_val=-1, ofzpz_val=-1):
print(f"{ofzpz_val}")
if mokev_val == -1:
try:
@@ -225,9 +317,10 @@ class OMNYOpticsMixin:
"Device mokev does not exist. You can specify the energy in keV as an argument instead."
)
return
foptz_val = dev.foptz.readback.get()
distance = -foptz_val + 43.15 + 36.7
print(f"\nThe sample is in a distance of \033[1m{distance:.1f} mm\033[0m from the FZP.\n")
if ofzpz_val == -1:
ofzpz_val = dev.ofzpz.readback.get()
distance = 66+2.4+31.8025-ofzpz_val
print(f"\nThe sample is in a distance of \033[1m{distance:.1f} mm\033[0m from the 60 nm FZP.\n")
print(f"At the current energy of {mokev_val:.4f} keV we have following options:\n")
diameters = [80e-6, 100e-6, 120e-6, 150e-6, 170e-6, 200e-6, 220e-6, 250e-6]
@@ -252,6 +345,10 @@ class OMNYOpticsMixin:
console.print(table)
#30 nm with additional spacer
distance = 53.84+0.6+33.1-ofzpz_val
print(f"\nThe sample is in a distance of \033[1m{distance:.1f} mm\033[0m from the 30 nm FZP.\n")
diameters = [150e-6, 250e-6]
console = Console()
@@ -274,11 +371,16 @@ class OMNYOpticsMixin:
console.print(table)
fosaz_val = dev.fosaz.readback.get()
print("\nOSA Information:")
print(f" Current fosaz {fosaz_val:.1f}")
print(
f" The OSA will collide with a normal OMNY pin at fosaz \033[1m{(33-fosaz_val):.1f}\033[0m"
)
print(f" Remaining space: \033[1m{-fosaz_val+(33-foptz_val):.1f}\033[0m")
"This function can be called with explicit energy and ofzpz position.\n Example: omny.ffzp_info(mokev_val=6.2, ofzpz_val=33.2)"
)
# from flomni
# oosaz_val = dev.oosaz.readback.get()
# print("\nOSA Information:")
# print(f" Current fosaz {fosaz_val:.1f}")
# print(
# f" The OSA will collide with a normal OMNY pin at fosaz \033[1m{(33-fosaz_val):.1f}\033[0m"
# )
# print(f" Remaining space: \033[1m{-fosaz_val+(33-foptz_val):.1f}\033[0m")
@@ -86,9 +86,6 @@ class OMNYSampleTransferMixin:
def _omnycam_samples(self):
pass
def oeye_cam_in(self):
pass
def _otransfer_shuttle_align(self):
self._otransfer_gripper_to_park_z()
self._otransfer_oparkz_safe_shuttle_operation()
@@ -266,12 +263,12 @@ class OMNYSampleTransferMixin:
raise OMNYTransferError("The osa is either not referenced or too close to the sample.")
if not self._oshield_is_ST_open():
umv(dev.oshield, -11.9)
umv(dev.oshield, -11.88)
_shieldattemptopencounter=0
while not self._oshield_is_ST_open() and _shieldattemptopencounter<10:
dev.oshield.controller.move_open_loop_steps(2, -250, amplitude=4000, frequency=5000)
while not self._oshield_is_ST_open() and _shieldattemptopencounter<15:
dev.oshield.controller.move_open_loop_steps(2, -500, amplitude=4000, frequency=1000)
time.sleep(0.2)
_shieldattemptopencounter=+1
_shieldattemptopencounter+=1
if not self._oshield_is_ST_open():
raise OMNYTransferError("The shield of the sample stage did not open.")
@@ -329,7 +326,7 @@ class OMNYSampleTransferMixin:
umv(dev.oshield, 15.5)
def _otransfer_gripper_up(self):
up_position = self._get_user_param_safe(dev.otransy, "up_position")
up_position = self._get_user_param_safe("otransy", "up_position")
if dev.otransy.get().readback < up_position - 0.1:
umv(dev.otransy, -1.2)
if dev.otransy.get().readback < up_position - 0.1:
@@ -378,8 +375,8 @@ class OMNYSampleTransferMixin:
#simultaneous motion to reduce time. otherwise later manual eye in
if not dev.omny_samples.is_sample_in_gripper():
#todo the oeyey mv may not be accessible
_omny_oeye_xray_inx = self._get_user_param_safe(dev.oeyex, "xray_in")
_omny_oeye_xray_iny = self._get_user_param_safe(dev.oeyey, "xray_in")
_omny_oeye_xray_inx = self._get_user_param_safe("oeyex", "xray_in")
_omny_oeye_xray_iny = self._get_user_param_safe("oeyey", "xray_in")
self._oeyey_mv(_omny_oeye_xray_iny)
umv(dev.otransx, -100, dev.oeyex, _omny_oeye_xray_inx, dev.oeyez, -2)
else:
@@ -714,7 +711,7 @@ class OMNYSampleTransferMixin:
def _otransfer_check_sensor_connected(self):
sensorvoltage = (float(dev.otransy.controller.socket_put_and_receive("MG@AN[8001]")))
gripper_sensorvoltagetarget = self._get_user_param_safe(dev.otransy, "gripper_sensorvoltagetarget")
gripper_sensorvoltagetarget = self._get_user_param_safe("otransy", "gripper_sensorvoltagetarget")
if not (sensorvoltage > gripper_sensorvoltagetarget-0.5 and sensorvoltage < gripper_sensorvoltagetarget):
raise OMNYTransferError(f"Sensorvoltage is {sensorvoltage:.2f} V. This indicates a sensor error.")
+11 -7
View File
@@ -31,7 +31,7 @@ ofzpx:
readOnly: false
readoutPriority: baseline
userParameter:
in: 0
in: -0.4317
ofzpy:
description: FZP Y
deviceClass: csaxs_bec.devices.omny.galil.ogalil_ophyd.OMNYGalilMotor
@@ -50,7 +50,8 @@ ofzpy:
readOnly: false
readoutPriority: baseline
userParameter:
in: 0
in: 0.7944
out: 0.6377
ofzpz:
description: FZP Z
deviceClass: csaxs_bec.devices.omny.galil.ogalil_ophyd.OMNYGalilMotor
@@ -184,7 +185,8 @@ oosay:
readOnly: false
readoutPriority: baseline
userParameter:
in: 0
near_field_in: 0.531
far_field_in: 0.4122
oosax:
description: OSA X
deviceClass: csaxs_bec.devices.omny.galil.ogalil_ophyd.OMNYGalilMotor
@@ -203,7 +205,8 @@ oosax:
readOnly: false
readoutPriority: baseline
userParameter:
in: 0
near_field_in: 3.2044
far_field_in: 3.022
oosaz:
description: OSA Z
deviceClass: csaxs_bec.devices.omny.galil.ogalil_ophyd.OMNYGalilMotor
@@ -222,7 +225,8 @@ oosaz:
readOnly: false
readoutPriority: baseline
userParameter:
in: 0
near_field_in: -0.4452
far_field_in: 6.5
oparkz:
description: OSA Y
deviceClass: csaxs_bec.devices.omny.galil.ogalil_ophyd.OMNYGalilMotor
@@ -374,7 +378,7 @@ oeyex:
readOnly: false
readoutPriority: baseline
userParameter:
xray_in: 0
xray_in: -45.7394
oeyez:
description: Xray eye Z
deviceClass: csaxs_bec.devices.omny.galil.ogalil_ophyd.OMNYGalilMotor
@@ -412,7 +416,7 @@ oeyey:
readOnly: false
readoutPriority: baseline
userParameter:
xray_in: 0
xray_in: 0.0229
############################################################
#################### flOMNI Smaract motors #################
+3 -3
View File
@@ -140,9 +140,9 @@ class OMNYGalilController(GalilController):
def _ogalil_folerr_reset_and_ignore(self, axis_id_numeric: int) -> None:
self.socket_put_confirmed(f"folaxerr[{axis_id_numeric}]=0")
self.socket_put_confirmed(f"folerr=0")
self.socket_put_confirmed(f"IgNoFol=1")
self.socket_put_confirmed(f"XQ#STOP,1")
self.socket_put_confirmed("folerr=0")
self.socket_put_confirmed("IgNoFol=1")
self.socket_put_confirmed("XQ#STOP,1")
def _ogalil_set_axis_to_pos_wo_reference_search(self, axis_id_numeric, axis_id, pos_mm, motor_resolution, motor_sign):