Compare commits
10 Commits
fix/online
...
fix/fixes_
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
43ae732e34 | ||
|
|
583b15b772 | ||
|
|
4967474271 | ||
|
|
8d6a2b0f5c | ||
|
|
dcde0e783e | ||
|
|
58cd6bdaf7 | ||
|
|
68320e1944 | ||
|
|
5ff32decc4 | ||
|
|
2c31d79f1b | ||
|
|
3ce6bbc134 |
@@ -356,18 +356,6 @@ class LamNI(LamNIOpticsMixin, LamniGuiTools):
|
||||
# Logging helpers
|
||||
# ------------------------------------------------------------------
|
||||
|
||||
def write_to_spec_log(self, content):
|
||||
try:
|
||||
with open(
|
||||
os.path.expanduser(
|
||||
"~/Data10/specES1/log-files/specES1_started_2022_11_30_1313.log"
|
||||
),
|
||||
"a",
|
||||
) as log_file:
|
||||
log_file.write(content)
|
||||
except Exception:
|
||||
logger.warning("Failed to write to spec log file (omny web page).")
|
||||
|
||||
def write_to_scilog(self, content, tags: list = None):
|
||||
try:
|
||||
if tags is not None:
|
||||
@@ -439,7 +427,6 @@ class LamNI(LamNIOpticsMixin, LamniGuiTools):
|
||||
f"{str(datetime.datetime.now())}: LamNI scan projection at angle {angle},"
|
||||
f" scan number {bec.queue.next_scan_number}.\n"
|
||||
)
|
||||
self.write_to_spec_log(log_message)
|
||||
corridor_size = self.corridor_size if self.corridor_size > 0 else None
|
||||
scans.lamni_fermat_scan(
|
||||
fov_size=[self.lamni_piezo_range_x, self.lamni_piezo_range_y],
|
||||
@@ -779,7 +766,7 @@ class LamNI(LamNIOpticsMixin, LamniGuiTools):
|
||||
|
||||
user_input = input("Are these parameters correctly set for your scan? ")
|
||||
if user_input == "y":
|
||||
print("good then")
|
||||
print("OK. continue.")
|
||||
return
|
||||
|
||||
self.tomo_countingtime = self._get_val("<ctime> s", self.tomo_countingtime, float)
|
||||
|
||||
@@ -5,7 +5,7 @@ from rich import box
|
||||
from rich.console import Console
|
||||
from rich.table import Table
|
||||
|
||||
from csaxs_bec.bec_ipython_client.plugins.cSAXS import epics_put, fshclose
|
||||
from csaxs_bec.bec_ipython_client.plugins.cSAXS import epics_put
|
||||
from csaxs_bec.bec_ipython_client.plugins.omny.omny_general_tools import OMNYTools
|
||||
|
||||
dev = builtins.__dict__.get("dev")
|
||||
@@ -172,7 +172,7 @@ class LamNIOpticsMixin:
|
||||
|
||||
def leye_out(self):
|
||||
self.loptics_in()
|
||||
fshclose()
|
||||
dev.omnyfsh.fshopen()
|
||||
leyey_out = self._get_user_param_safe("leyey", "out")
|
||||
umv(dev.leyey, leyey_out)
|
||||
|
||||
|
||||
@@ -120,7 +120,7 @@ class FlomniInitStagesMixin:
|
||||
|
||||
|
||||
if self.OMNYTools.yesno("Init of foptz. Can the stage move to the upstream limit without collision?"):
|
||||
print("good then")
|
||||
print("OK. continue.")
|
||||
else:
|
||||
return
|
||||
|
||||
@@ -174,7 +174,7 @@ class FlomniInitStagesMixin:
|
||||
print("done")
|
||||
|
||||
if self.OMNYTools.yesno("Init of tracking stages. Did you remove the outer laser flight tubes?"):
|
||||
print("good then")
|
||||
print("OK. continue.")
|
||||
else:
|
||||
print("Stopping.")
|
||||
return
|
||||
@@ -190,7 +190,7 @@ class FlomniInitStagesMixin:
|
||||
print("done")
|
||||
|
||||
if self.OMNYTools.yesno("Init of sample stage. Is the piezo at about 0 deg?"):
|
||||
print("good then")
|
||||
print("OK. continue.")
|
||||
else:
|
||||
print("Stopping.")
|
||||
return
|
||||
@@ -207,7 +207,7 @@ class FlomniInitStagesMixin:
|
||||
|
||||
print("Initializing UPR stage.")
|
||||
if self.OMNYTools.yesno("To ensure that the end switches work, please check that they are currently not pushed. Is everything okay?"):
|
||||
print("good then")
|
||||
print("OK. continue.")
|
||||
else:
|
||||
print("Stopping.")
|
||||
return
|
||||
@@ -228,7 +228,7 @@ class FlomniInitStagesMixin:
|
||||
continue
|
||||
break
|
||||
if self.OMNYTools.yesno("Shall I start the index search?"):
|
||||
print("good then. Starting index search.")
|
||||
print("OK. continue.. Starting index search.")
|
||||
else:
|
||||
print("Stopping.")
|
||||
return
|
||||
@@ -247,7 +247,7 @@ class FlomniInitStagesMixin:
|
||||
print("done")
|
||||
|
||||
if self.OMNYTools.yesno("Init of foptx. Can the stage move to the positive limit without collision? Attention: tracker flight tube!"):
|
||||
print("good then")
|
||||
print("OK. continue.")
|
||||
else:
|
||||
print("Stopping.")
|
||||
return
|
||||
@@ -271,7 +271,7 @@ class FlomniInitStagesMixin:
|
||||
break
|
||||
|
||||
if self.OMNYTools.yesno("Start limit switch search of fopty?"):
|
||||
print("good then")
|
||||
print("OK. continue.")
|
||||
else:
|
||||
print("Stopping.")
|
||||
return
|
||||
@@ -438,7 +438,19 @@ class FlomniSampleTransferMixin:
|
||||
umv(dev.fsamx, fsamx_in)
|
||||
dev.fsamx.limits = [fsamx_in - 0.4, fsamx_in + 0.4]
|
||||
|
||||
#self.flomnigui_idle()
|
||||
print("Moving X-ray eye in.")
|
||||
|
||||
if self.OMNYTools.yesno("Please confirm that this is ok with the flight tube. This check is to be removed after commissioning", "n"):
|
||||
print("OK. continue.")
|
||||
else:
|
||||
print("Stopping.")
|
||||
raise FlomniError("Manual abort of x-ray eye in.")
|
||||
|
||||
self.feye_in()
|
||||
print("Moving X-ray optics out.")
|
||||
self.foptics_out()
|
||||
self.xrayeye_update_frame()
|
||||
|
||||
|
||||
def laser_tracker_show_all(self):
|
||||
dev.rtx.controller.laser_tracker_show_all()
|
||||
@@ -543,12 +555,6 @@ class FlomniSampleTransferMixin:
|
||||
self.flomnigui_show_cameras()
|
||||
|
||||
|
||||
if self.OMNYTools.yesno("Please confirm that there is currently no sample in the gripper. It would be dropped!", "y"):
|
||||
print("good then")
|
||||
else:
|
||||
print("Stopping.")
|
||||
raise FlomniError("The sample transfer was manually aborted.")
|
||||
|
||||
self.ftransfer_gripper_move(position)
|
||||
|
||||
self.ftransfer_controller_enable_mount_mode()
|
||||
@@ -751,7 +757,7 @@ class FlomniSampleTransferMixin:
|
||||
return
|
||||
|
||||
if self.OMNYTools.yesno("All OK? Continue?", "y"):
|
||||
print("good then")
|
||||
print("OK. continue.")
|
||||
dev.ftransy.controller.socket_put_confirmed("confirm=1")
|
||||
else:
|
||||
print("Stopping.")
|
||||
@@ -785,7 +791,7 @@ class FlomniSampleTransferMixin:
|
||||
if position == 0 and fsamx_pos > -160:
|
||||
|
||||
if self.OMNYTools.yesno("May the flomni stage be moved out for the sample change? Feedback will be disabled and alignment will be lost!", "y"):
|
||||
print("good then")
|
||||
print("OK. continue.")
|
||||
self.ftransfer_flomni_stage_out()
|
||||
else:
|
||||
print("Stopping.")
|
||||
@@ -983,56 +989,63 @@ class FlomniAlignmentMixin:
|
||||
|
||||
def read_alignment_offset(
|
||||
self,
|
||||
dir_path=os.path.expanduser("~/Data10/specES1/internal/"),
|
||||
dir_path=os.path.expanduser("~/data/raw/logs/"),
|
||||
setup="flomni",
|
||||
use_vertical_default_values=True,
|
||||
get_data_from_gui=False,
|
||||
):
|
||||
"""
|
||||
Read the alignment parameters from xray eye fit.
|
||||
|
||||
"""
|
||||
tomo_alignment_fit = np.zeros((2, 5))
|
||||
# with open(os.path.join(dir_path, "ptychotomoalign_Ax.txt"), "r") as file:
|
||||
# tomo_alignment_fit[0][0] = file.readline()
|
||||
|
||||
# with open(os.path.join(dir_path, "ptychotomoalign_Bx.txt"), "r") as file:
|
||||
# tomo_alignment_fit[0][1] = file.readline()
|
||||
if not get_data_from_gui:
|
||||
"""
|
||||
Read the alignment parameters from xray eye fit.
|
||||
|
||||
# with open(os.path.join(dir_path, "ptychotomoalign_Cx.txt"), "r") as file:
|
||||
# tomo_alignment_fit[0][2] = file.readline()
|
||||
"""
|
||||
with open(os.path.join(dir_path, "ptychotomoalign_Ax.txt"), "r") as file:
|
||||
tomo_alignment_fit[0][0] = file.readline()
|
||||
|
||||
# with open(os.path.join(dir_path, "ptychotomoalign_Ay.txt"), "r") as file:
|
||||
# tomo_alignment_fit[1][0] = file.readline()
|
||||
with open(os.path.join(dir_path, "ptychotomoalign_Bx.txt"), "r") as file:
|
||||
tomo_alignment_fit[0][1] = file.readline()
|
||||
|
||||
# with open(os.path.join(dir_path, "ptychotomoalign_By.txt"), "r") as file:
|
||||
# tomo_alignment_fit[1][1] = file.readline()
|
||||
with open(os.path.join(dir_path, "ptychotomoalign_Cx.txt"), "r") as file:
|
||||
tomo_alignment_fit[0][2] = file.readline()
|
||||
|
||||
# with open(os.path.join(dir_path, "ptychotomoalign_Cy.txt"), "r") as file:
|
||||
# tomo_alignment_fit[1][2] = file.readline()
|
||||
with open(os.path.join(dir_path, "ptychotomoalign_Ay.txt"), "r") as file:
|
||||
tomo_alignment_fit[1][0] = file.readline()
|
||||
|
||||
# with open(os.path.join(dir_path, "ptychotomoalign_Ay3.txt"), "r") as file:
|
||||
# tomo_alignment_fit[1][3] = file.readline()
|
||||
with open(os.path.join(dir_path, "ptychotomoalign_By.txt"), "r") as file:
|
||||
tomo_alignment_fit[1][1] = file.readline()
|
||||
|
||||
# with open(os.path.join(dir_path, "ptychotomoalign_Cy3.txt"), "r") as file:
|
||||
# tomo_alignment_fit[1][4] = file.readline()
|
||||
with open(os.path.join(dir_path, "ptychotomoalign_Cy.txt"), "r") as file:
|
||||
tomo_alignment_fit[1][2] = file.readline()
|
||||
|
||||
params = dev.omny_xray_gui.fit_params_x.get()
|
||||
with open(os.path.join(dir_path, "ptychotomoalign_Ay3.txt"), "r") as file:
|
||||
tomo_alignment_fit[1][3] = file.readline()
|
||||
|
||||
#amplitude
|
||||
tomo_alignment_fit[0][0] = params['SineModel_0_amplitude']
|
||||
#phase
|
||||
tomo_alignment_fit[0][1] = params['SineModel_0_shift']
|
||||
#offset
|
||||
tomo_alignment_fit[0][2] = params['LinearModel_1_intercept']
|
||||
print("applying vertical default values from mirror calibration, not from fit!")
|
||||
tomo_alignment_fit[1][0] = 0
|
||||
tomo_alignment_fit[1][1] = 0
|
||||
tomo_alignment_fit[1][2] = 0
|
||||
tomo_alignment_fit[1][3] = 0
|
||||
tomo_alignment_fit[1][4] = 0
|
||||
with open(os.path.join(dir_path, "ptychotomoalign_Cy3.txt"), "r") as file:
|
||||
tomo_alignment_fit[1][4] = file.readline()
|
||||
|
||||
print("New alignment parameters loaded from filesystem, meaning Matlab fit:")
|
||||
|
||||
else:
|
||||
params = dev.omny_xray_gui.fit_params_x.get()
|
||||
|
||||
#amplitude
|
||||
tomo_alignment_fit[0][0] = params['SineModel_0_amplitude']
|
||||
#phase
|
||||
tomo_alignment_fit[0][1] = params['SineModel_0_shift']
|
||||
#offset
|
||||
tomo_alignment_fit[0][2] = params['LinearModel_1_intercept']
|
||||
print("applying vertical default values from mirror calibration, not from fit!")
|
||||
tomo_alignment_fit[1][0] = 0
|
||||
tomo_alignment_fit[1][1] = 0
|
||||
tomo_alignment_fit[1][2] = 0
|
||||
tomo_alignment_fit[1][3] = 0
|
||||
tomo_alignment_fit[1][4] = 0
|
||||
print("New alignment parameters loaded based on Xray eye alignment GUI:")
|
||||
|
||||
|
||||
print("New alignment parameters loaded:")
|
||||
print(
|
||||
f"X Amplitude {tomo_alignment_fit[0][0]}, "
|
||||
f"X Phase {tomo_alignment_fit[0][1]}, "
|
||||
@@ -1441,18 +1454,6 @@ class Flomni(
|
||||
def sample_name(self):
|
||||
return self.sample_get_name(0)
|
||||
|
||||
def write_to_spec_log(self, content):
|
||||
try:
|
||||
with open(
|
||||
os.path.expanduser(
|
||||
"~/Data10/specES1/log-files/specES1_started_2022_11_30_1313.log"
|
||||
),
|
||||
"a",
|
||||
) as log_file:
|
||||
log_file.write(content)
|
||||
except Exception:
|
||||
logger.warning("Failed to write to spec log file (omny web page).")
|
||||
|
||||
def write_to_scilog(self, content, tags: list = None):
|
||||
try:
|
||||
if tags is not None:
|
||||
@@ -1474,11 +1475,14 @@ class Flomni(
|
||||
return
|
||||
dev = builtins.__dict__.get("dev")
|
||||
bec = builtins.__dict__.get("bec")
|
||||
|
||||
|
||||
self.feye_out()
|
||||
tags = ["BEC_alignment_tomo", self.sample_name]
|
||||
self.write_to_scilog(
|
||||
f"Starting alignment scan. First scan number: {bec.queue.next_scan_number}.", tags
|
||||
)
|
||||
|
||||
|
||||
start_angle = 0
|
||||
|
||||
angle_end = start_angle + 180
|
||||
@@ -1507,9 +1511,8 @@ class Flomni(
|
||||
for scan_nr in range(start_scan_number, end_scan_number):
|
||||
self._write_tomo_scan_number(scan_nr, angle, 0)
|
||||
|
||||
print("Alignment scan finished. Please run SPEC_ptycho_align and load the new fit.")
|
||||
|
||||
umv(dev.fsamroy, 0)
|
||||
self.OMNYTools.printgreenbold("\n\nAlignment scan finished. Please run SPEC_ptycho_align and load the new fit.")
|
||||
|
||||
def _write_subtomo_to_scilog(self, subtomo_number):
|
||||
dev = builtins.__dict__.get("dev")
|
||||
@@ -1543,6 +1546,9 @@ class Flomni(
|
||||
|
||||
self._write_subtomo_to_scilog(subtomo_number)
|
||||
|
||||
if start_angle is not None:
|
||||
print(f"Sub tomo scan with start angle {start_angle} requested.")
|
||||
|
||||
if start_angle is None:
|
||||
if subtomo_number == 1:
|
||||
start_angle = 0
|
||||
@@ -1561,29 +1567,94 @@ class Flomni(
|
||||
elif subtomo_number == 8:
|
||||
start_angle = self.tomo_angle_stepsize / 8.0 * 7
|
||||
|
||||
|
||||
# _tomo_shift_angles (potential global variable)
|
||||
_tomo_shift_angles = 0
|
||||
angle_end = start_angle + 180
|
||||
# compute number of projections
|
||||
|
||||
start = start_angle + _tomo_shift_angles
|
||||
|
||||
if subtomo_number % 2: # odd = forward
|
||||
max_allowed_angle = 180.05 + self.tomo_angle_stepsize
|
||||
proposed_end = start + 180
|
||||
angle_end = min(proposed_end, max_allowed_angle)
|
||||
span = angle_end - start
|
||||
|
||||
else: # even = reverse
|
||||
min_allowed_angle = 0
|
||||
proposed_end = start - 180
|
||||
angle_end = max(proposed_end, min_allowed_angle)
|
||||
span = start - angle_end
|
||||
|
||||
# number of projections needed to maintain step size
|
||||
N = int(span / self.tomo_angle_stepsize) + 1
|
||||
|
||||
angles = np.linspace(
|
||||
start_angle + _tomo_shift_angles,
|
||||
start,
|
||||
angle_end,
|
||||
num=int(180 / self.tomo_angle_stepsize) + 1,
|
||||
num=N,
|
||||
endpoint=True,
|
||||
)
|
||||
# reverse even sub-tomograms
|
||||
if not (subtomo_number % 2):
|
||||
angles = np.flip(angles)
|
||||
for angle in angles:
|
||||
|
||||
if subtomo_number % 2: # odd subtomos → forward direction
|
||||
# clamp end angle to max allowed
|
||||
max_allowed_angle = 180.05 + self.tomo_angle_stepsize
|
||||
proposed_end = start + 180
|
||||
angle_end = min(proposed_end, max_allowed_angle)
|
||||
|
||||
angles = np.linspace(
|
||||
start,
|
||||
angle_end,
|
||||
num=N,
|
||||
endpoint=True,
|
||||
)
|
||||
|
||||
else: # even subtomos → reverse direction
|
||||
# go FROM start_angle down toward 0
|
||||
min_allowed_angle = 0
|
||||
proposed_end = start - 180
|
||||
angle_end = max(proposed_end, min_allowed_angle)
|
||||
|
||||
angles = np.linspace(
|
||||
start,
|
||||
angle_end,
|
||||
num=N,
|
||||
endpoint=True,
|
||||
)
|
||||
|
||||
for i, angle in enumerate(angles):
|
||||
|
||||
self.progress["subtomo"] = subtomo_number
|
||||
self.progress["subtomo_projection"] = np.where(angles == angle)[0][0]
|
||||
self.progress["subtomo_total_projections"] = 180 / self.tomo_angle_stepsize
|
||||
self.progress["projection"] = (subtomo_number - 1) * self.progress[
|
||||
"subtomo_total_projections"
|
||||
] + self.progress["subtomo_projection"]
|
||||
|
||||
# --- NEW LOGIC FOR OFFSET WHEN start_angle IS SPECIFIED ---
|
||||
if i == 0:
|
||||
step = self.tomo_angle_stepsize
|
||||
sa = start_angle
|
||||
|
||||
if start_angle is None:
|
||||
# normal operation: always start at zero
|
||||
self._subtomo_offset = 0
|
||||
|
||||
else:
|
||||
if subtomo_number % 2: # odd = forward direction
|
||||
self._subtomo_offset = round(sa / step)
|
||||
else: # even = reverse direction
|
||||
self._subtomo_offset = round((180 - sa) / step)
|
||||
|
||||
# progress index must always increase
|
||||
self.progress["subtomo_projection"] = self._subtomo_offset + i
|
||||
# ------------------------------------------------------------
|
||||
|
||||
# existing progress fields
|
||||
self.progress["subtomo_total_projections"] = int(180 / self.tomo_angle_stepsize)
|
||||
self.progress["projection"] = (subtomo_number - 1) * self.progress["subtomo_total_projections"] + self.progress["subtomo_projection"]
|
||||
self.progress["total_projections"] = 180 / self.tomo_angle_stepsize * 8
|
||||
self.progress["angle"] = angle
|
||||
|
||||
# finally do the scan at this angle
|
||||
self._tomo_scan_at_angle(angle, subtomo_number)
|
||||
|
||||
|
||||
def _tomo_scan_at_angle(self, angle, subtomo_number):
|
||||
successful = False
|
||||
error_caught = False
|
||||
@@ -1591,7 +1662,7 @@ class Flomni(
|
||||
print(f"Starting flOMNI scan for angle {angle} in subtomo {subtomo_number}")
|
||||
self._print_progress()
|
||||
while not successful:
|
||||
self.bl_chk._bl_chk_start()
|
||||
#self.bl_chk._bl_chk_start()
|
||||
if not self.special_angles:
|
||||
self._current_special_angles = []
|
||||
if self._current_special_angles:
|
||||
@@ -1614,10 +1685,10 @@ class Flomni(
|
||||
else:
|
||||
raise exc
|
||||
|
||||
if self.bl_chk._bl_chk_stop() and not error_caught:
|
||||
successful = True
|
||||
else:
|
||||
self.bl_chk._bl_chk_wait_until_recovered()
|
||||
# if self.bl_chk._bl_chk_stop() and not error_caught:
|
||||
successful = True
|
||||
# else:
|
||||
# self.bl_chk._bl_chk_wait_until_recovered()
|
||||
end_scan_number = bec.queue.next_scan_number
|
||||
for scan_nr in range(start_scan_number, end_scan_number):
|
||||
self._write_tomo_scan_number(scan_nr, angle, subtomo_number)
|
||||
@@ -1625,6 +1696,14 @@ class Flomni(
|
||||
def tomo_scan(self, subtomo_start=1, start_angle=None, projection_number=None):
|
||||
"""start a tomo scan"""
|
||||
|
||||
if not self._check_eye_out_and_optics_in():
|
||||
print("Attention: The setup is not in measurement condition.\nXray eye might be IN or the Xray optics OUT.")
|
||||
if self.OMNYTools.yesno("Shall I continue?", "n"):
|
||||
print("OK")
|
||||
else:
|
||||
print("Stopping.")
|
||||
return
|
||||
|
||||
self.flomnigui_show_progress()
|
||||
|
||||
bec = builtins.__dict__.get("bec")
|
||||
@@ -1638,19 +1717,19 @@ class Flomni(
|
||||
):
|
||||
|
||||
# pylint: disable=undefined-variable
|
||||
if bec.active_account != "":
|
||||
self.tomo_id = self.add_sample_database(
|
||||
self.sample_name,
|
||||
str(datetime.date.today()),
|
||||
bec.active_account.decode(),
|
||||
bec.queue.next_scan_number,
|
||||
"flomni",
|
||||
"test additional info",
|
||||
"BEC",
|
||||
)
|
||||
self.write_pdf_report()
|
||||
else:
|
||||
self.tomo_id = 0
|
||||
# if bec.active_account != "":
|
||||
# self.tomo_id = self.add_sample_database(
|
||||
# self.sample_name,
|
||||
# str(datetime.date.today()),
|
||||
# bec.active_account,
|
||||
# bec.queue.next_scan_number,
|
||||
# "flomni",
|
||||
# "test additional info",
|
||||
# "BEC",
|
||||
# )
|
||||
# self.write_pdf_report()
|
||||
# else:
|
||||
self.tomo_id = 0
|
||||
|
||||
with scans.dataset_id_on_hold:
|
||||
if self.tomo_type == 1:
|
||||
@@ -1659,7 +1738,7 @@ class Flomni(
|
||||
for ii in range(subtomo_start, 9):
|
||||
self.sub_tomo_scan(ii, start_angle=start_angle)
|
||||
start_angle = None
|
||||
|
||||
|
||||
elif self.tomo_type == 2:
|
||||
# Golden ratio tomography
|
||||
previous_subtomo_number = -1
|
||||
@@ -1755,6 +1834,11 @@ class Flomni(
|
||||
else:
|
||||
raise FlomniError("undefined tomo type")
|
||||
|
||||
self.progress['projection'] = self.progress['total_projections']
|
||||
self.progress["subtomo_projection"] = self.progress["subtomo_total_projections"]
|
||||
self._print_progress()
|
||||
self.OMNYTools.printgreenbold("Tomoscan finished")
|
||||
|
||||
def _print_progress(self):
|
||||
print("\x1b[95mProgress report:")
|
||||
print(f"Tomo type: ....................... {self.progress['tomo_type']}")
|
||||
@@ -1836,7 +1920,7 @@ class Flomni(
|
||||
|
||||
return angle, subtomo_number
|
||||
|
||||
def tomo_reconstruct(self, base_path="~/Data10/specES1"):
|
||||
def tomo_reconstruct(self, base_path="~/data/raw/logs/reconstruction_queue"):
|
||||
"""write the tomo reconstruct file for the reconstruction queue"""
|
||||
bec = builtins.__dict__.get("bec")
|
||||
self.reconstructor.write(
|
||||
@@ -1847,7 +1931,7 @@ class Flomni(
|
||||
|
||||
def _write_tomo_scan_number(self, scan_number: int, angle: float, subtomo_number: int) -> None:
|
||||
tomo_scan_numbers_file = os.path.expanduser(
|
||||
"~/tomography_scannumbers.txt"
|
||||
"~/data/raw/logs/tomography_scannumbers.txt"
|
||||
)
|
||||
with open(tomo_scan_numbers_file, "a+") as out_file:
|
||||
# pylint: disable=undefined-variable
|
||||
@@ -1859,6 +1943,7 @@ class Flomni(
|
||||
|
||||
dev.rtx.controller.laser_tracker_check_signalstrength()
|
||||
|
||||
|
||||
scans = builtins.__dict__.get("scans")
|
||||
|
||||
# additional_correction = self.align.compute_additional_correction(angle)
|
||||
@@ -1893,7 +1978,6 @@ class Flomni(
|
||||
f"{str(datetime.datetime.now())}: flomni scan projection at angle {angle}, scan"
|
||||
f" number {bec.queue.next_scan_number}.\n"
|
||||
)
|
||||
self.write_to_spec_log(log_message)
|
||||
# self.write_to_scilog(log_message, ["BEC_scans", self.sample_name])
|
||||
scans.flomni_fermat_scan(
|
||||
fovx=self.fovx,
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
import time
|
||||
|
||||
import numpy as np
|
||||
from rich import box
|
||||
from rich.console import Console
|
||||
from rich.table import Table
|
||||
|
||||
from csaxs_bec.bec_ipython_client.plugins.cSAXS import epics_put, fshclose
|
||||
from csaxs_bec.bec_ipython_client.plugins.cSAXS import epics_put
|
||||
|
||||
|
||||
class FlomniOpticsMixin:
|
||||
@@ -16,12 +16,18 @@ class FlomniOpticsMixin:
|
||||
return param.get(var)
|
||||
|
||||
def feye_out(self):
|
||||
fshclose()
|
||||
dev.omnyfsh.fshclose()
|
||||
self.foptics_in()
|
||||
self.flomnigui_show_xeyealign()
|
||||
self.xrayeye_update_frame()
|
||||
if self.OMNYTools.yesno("Did the direct beam on the xray eye disappear?"):
|
||||
print("excellent.")
|
||||
else:
|
||||
print("Aborting. With visible parts of the direct beam on the xray eye, it cannot be removed.")
|
||||
return
|
||||
feyex_out = self._get_user_param_safe("feyex", "out")
|
||||
umv(dev.feyex, feyex_out)
|
||||
|
||||
epics_put("XOMNYI-XEYE-ACQ:0", 2)
|
||||
# move rotation stage to zero to avoid problems with wires
|
||||
umv(dev.fsamroy, 0)
|
||||
# umv(dev.fttrx1, 9.2)
|
||||
@@ -32,16 +38,39 @@ class FlomniOpticsMixin:
|
||||
|
||||
feyex_in = self._get_user_param_safe("feyex", "in")
|
||||
feyey_in = self._get_user_param_safe("feyey", "in")
|
||||
umv(dev.feyex, feyex_in, dev.feyey, feyey_in)
|
||||
#self.align.update_frame()
|
||||
|
||||
current_feyex = dev.feyex.readback.get()
|
||||
current_feyey = dev.feyey.readback.get()
|
||||
|
||||
# check if both are close enough (within 0.01)
|
||||
if np.isclose(current_feyex, feyex_in, atol=0.01) and np.isclose(current_feyey, feyey_in, atol=0.01):
|
||||
# both already in position → do nothing
|
||||
pass
|
||||
else:
|
||||
# move both axes to the desired "in" positions
|
||||
umv(dev.feyex, feyex_in, dev.feyey, feyey_in)
|
||||
|
||||
self.xrayeye_update_frame()
|
||||
|
||||
def _ffzp_in(self):
|
||||
foptx_in = self._get_user_param_safe("foptx", "in")
|
||||
fopty_in = self._get_user_param_safe("fopty", "in")
|
||||
umv(dev.foptx, foptx_in)
|
||||
umv(
|
||||
dev.fopty, fopty_in
|
||||
) # for 7.2567 keV and 150 mu, 60 nm fzp, loptz 83.6000 for propagation 1.4 mm
|
||||
|
||||
current_foptx = dev.foptx.readback.get()
|
||||
current_fopty = dev.fopty.readback.get()
|
||||
|
||||
tol = 0.003
|
||||
|
||||
# if either axis is outside the tolerance → move both
|
||||
need_move_optics = (
|
||||
not np.isclose(current_foptx, foptx_in, atol=tol) or
|
||||
not np.isclose(current_fopty, fopty_in, atol=tol)
|
||||
)
|
||||
|
||||
if need_move_optics:
|
||||
umv(dev.foptx, foptx_in, dev.fopty, fopty_in) # for 7.2567 keV and 150 mu, 60 nm fzp, loptz 83.6000 for propagation 1.4 mm
|
||||
else:
|
||||
print("FZP is already at the in position.")
|
||||
|
||||
def ffzp_in(self):
|
||||
"""
|
||||
@@ -84,19 +113,85 @@ class FlomniOpticsMixin:
|
||||
# umv(dev.losax, -1.4850, dev.losay, -0.1930)
|
||||
# umv(dev.losaz, 1.0000)
|
||||
# 7.2, 150
|
||||
|
||||
fosax_in = self._get_user_param_safe("fosax", "in")
|
||||
fosay_in = self._get_user_param_safe("fosay", "in")
|
||||
fosaz_in = self._get_user_param_safe("fosaz", "in")
|
||||
|
||||
# tighten limits
|
||||
dev.fosax.limits = [fosax_in - 0.1, fosax_in + 0.1]
|
||||
dev.fosay.limits = [fosay_in - 0.1, fosay_in + 0.1]
|
||||
dev.fosaz.limits = [fosaz_in - 0.1, fosaz_in + 0.1]
|
||||
umv(dev.fosax, fosax_in, dev.fosay, fosay_in)
|
||||
umv(dev.fosaz, fosaz_in)
|
||||
|
||||
current_fosax = dev.fosax.readback.get()
|
||||
current_fosay = dev.fosay.readback.get()
|
||||
current_fosaz = dev.fosaz.readback.get()
|
||||
|
||||
# tolerance
|
||||
tol = 0.003
|
||||
|
||||
need_move_osa = (
|
||||
not np.isclose(current_fosax, fosax_in, atol=tol) or
|
||||
not np.isclose(current_fosay, fosay_in, atol=tol) or
|
||||
not np.isclose(current_fosaz, fosaz_in, atol=tol)
|
||||
)
|
||||
|
||||
if need_move_osa:
|
||||
umv(dev.fosax, fosax_in, dev.fosay, fosay_in)
|
||||
umv(dev.fosaz, fosaz_in)
|
||||
else:
|
||||
print("OSA is already at the IN position.")
|
||||
|
||||
# 11 kev
|
||||
# umv(dev.losax, -1.161000, dev.losay, -0.196)
|
||||
# umv(dev.losaz, 1.0000)
|
||||
|
||||
def _check_eye_out_and_optics_in(self, tol=0.003):
|
||||
# --- expected IN positions ---
|
||||
foptx_in = self._get_user_param_safe("foptx", "in")
|
||||
fopty_in = self._get_user_param_safe("fopty", "in")
|
||||
foptz_in = self._get_user_param_safe("foptz", "in")
|
||||
|
||||
# --- expected OUT condition for the X-ray eye ---
|
||||
# eye is OUT when it is *not within tolerance* of its IN position
|
||||
feyex_out = self._get_user_param_safe("feyex", "out")
|
||||
|
||||
# --- current positions ---
|
||||
cx_feyex = dev.feyex.readback.get()
|
||||
|
||||
cx_foptx = dev.foptx.readback.get()
|
||||
cx_fopty = dev.fopty.readback.get()
|
||||
cx_foptz = dev.foptz.readback.get()
|
||||
|
||||
# --- check eye OUT ---
|
||||
eye_out = (
|
||||
np.isclose(cx_feyex, feyex_out, atol=tol)
|
||||
)
|
||||
|
||||
# --- check optics IN ---
|
||||
optics_in = (
|
||||
np.isclose(cx_foptx, foptx_in, atol=tol) and
|
||||
np.isclose(cx_fopty, fopty_in, atol=tol) and
|
||||
np.isclose(cx_foptz, foptz_in, atol=tol)
|
||||
)
|
||||
|
||||
fosax_in = self._get_user_param_safe("fosax", "in")
|
||||
fosay_in = self._get_user_param_safe("fosay", "in")
|
||||
fosaz_in = self._get_user_param_safe("fosaz", "in")
|
||||
|
||||
cx_fosax = dev.fosax.readback.get()
|
||||
cx_fosay = dev.fosay.readback.get()
|
||||
cx_fosaz = dev.fosaz.readback.get()
|
||||
|
||||
osa_in = (
|
||||
np.isclose(cx_fosax, fosax_in, atol=tol) and
|
||||
np.isclose(cx_fosay, fosay_in, atol=tol) and
|
||||
np.isclose(cx_fosaz, fosaz_in, atol=tol)
|
||||
)
|
||||
|
||||
return eye_out and optics_in and osa_in
|
||||
|
||||
|
||||
def fosa_out(self):
|
||||
self.ensure_fheater_up()
|
||||
curtain_is_triggered = dev.foptz.controller.fosaz_light_curtain_is_triggered()
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import builtins
|
||||
import time
|
||||
|
||||
# from csaxs_bec.bec_ipython_client.plugins.cSAXS import epics_get, epics_put, fshopen, fshclose
|
||||
|
||||
@@ -31,6 +32,7 @@ class flomniGuiTools:
|
||||
self.gui.flomni.raise_window()
|
||||
else:
|
||||
self.gui.new("flomni")
|
||||
time.sleep(1)
|
||||
|
||||
def flomnigui_stop_gui(self):
|
||||
self.gui.flomni.hide()
|
||||
@@ -101,7 +103,8 @@ class flomniGuiTools:
|
||||
# dev.cam_flomni_overview.stop_live_mode()
|
||||
# dev.cam_flomni_gripper.stop_live_mode()
|
||||
# dev.cam_xeye.live_mode = False
|
||||
self.gui.flomni.delete_all()
|
||||
if hasattr(self.gui, "flomni"):
|
||||
self.gui.flomni.delete_all()
|
||||
self.progressbar = None
|
||||
self.text_box = None
|
||||
|
||||
@@ -207,7 +210,16 @@ class flomniGuiTools:
|
||||
main_progress_ring.set_value(progress)
|
||||
subtomo_progress_ring.set_value(subtomo_progress)
|
||||
|
||||
text = f"Progress report:\n Tomo type: ....................... {self.progress['tomo_type']}\n Projection: ...................... {self.progress['projection']:.0f}\n Total projections expected ....... {self.progress['total_projections']}\n Angle: ........................... {self.progress['angle']}\n Current subtomo: ................. {self.progress['subtomo']}\n Current projection within subtomo: {self.progress['subtomo_projection']}\n Total projections per subtomo: ... {self.progress['subtomo_total_projections']}"
|
||||
text = (
|
||||
f"Progress report:\n"
|
||||
f" Tomo type: {self.progress['tomo_type']}\n"
|
||||
f" Projection: {self.progress['projection']:.0f}\n"
|
||||
f" Total projections expected {self.progress['total_projections']:.1f}\n"
|
||||
f" Angle: {self.progress['angle']:.1f}\n"
|
||||
f" Current subtomo: {self.progress['subtomo']}\n"
|
||||
f" Current projection within subtomo: {self.progress['subtomo_projection']}\n"
|
||||
f" Total projections per subtomo: {int(self.progress['subtomo_total_projections'])}"
|
||||
)
|
||||
self.progressbar.set_center_label(text)
|
||||
|
||||
|
||||
|
||||
@@ -231,10 +231,6 @@ class XrayEyeAlign:
|
||||
fovx = self._xray_fov_xy[0] * self.PIXEL_CALIBRATION * 1000 / 2
|
||||
fovy = self._xray_fov_xy[1] * self.PIXEL_CALIBRATION * 1000 / 2
|
||||
|
||||
self.tomo_rotate(0)
|
||||
|
||||
umv(dev.rtx, 0)
|
||||
|
||||
if keep_shutter_open:
|
||||
if self.flomni.OMNYTools.yesno("Close the shutter now?", "y"):
|
||||
dev.omnyfsh.fshclose()
|
||||
@@ -251,8 +247,11 @@ class XrayEyeAlign:
|
||||
|
||||
print("Automatically loading new alignment parameters from xray eye alignment.\n")
|
||||
|
||||
self.flomni.read_alignment_offset()
|
||||
self.flomni.read_alignment_offset(get_data_from_gui=True)
|
||||
|
||||
self.tomo_rotate(0)
|
||||
|
||||
umv(dev.rtx, 0)
|
||||
print("You are ready to remove the xray eye and start ptychography scans.")
|
||||
|
||||
def write_output(self):
|
||||
|
||||
@@ -852,18 +852,6 @@ class OMNY(
|
||||
def sample_name(self):
|
||||
return dev.omny_samples.get_sample_name_in_samplestage()
|
||||
|
||||
def write_to_spec_log(self, content):
|
||||
try:
|
||||
with open(
|
||||
os.path.expanduser(
|
||||
"~/Data10/specES1/log-files/specES1_started_2022_11_30_1313.log"
|
||||
),
|
||||
"a",
|
||||
) as log_file:
|
||||
log_file.write(content)
|
||||
except Exception:
|
||||
logger.warning("Failed to write to spec log file (omny web page).")
|
||||
|
||||
def write_to_scilog(self, content, tags: list = None):
|
||||
try:
|
||||
if tags is not None:
|
||||
@@ -1288,7 +1276,6 @@ class OMNY(
|
||||
f"{str(datetime.datetime.now())}: omny scan projection at angle {angle}, scan"
|
||||
f" number {bec.queue.next_scan_number}.\n"
|
||||
)
|
||||
self.write_to_spec_log(log_message)
|
||||
# self.write_to_scilog(log_message, ["BEC_scans", self.sample_name])
|
||||
scans.omny_fermat_scan(
|
||||
fovx=self.fovx,
|
||||
|
||||
@@ -48,7 +48,7 @@ class OMNYOpticsMixin:
|
||||
dev.oeyez.controller.socket_put_confirmed("axspeed[7]=10000")
|
||||
|
||||
def oeye_out(self):
|
||||
fshclose()
|
||||
dev.omnyfsh.fshclose()
|
||||
if self.OMNYTools.yesno("Did you move in the optics?"):
|
||||
umv(dev.oeyez, -2)
|
||||
self._oeyey_mv(-60.3)
|
||||
|
||||
@@ -227,7 +227,7 @@ ftransy:
|
||||
readoutPriority: baseline
|
||||
connectionTimeout: 20
|
||||
userParameter:
|
||||
sensor_voltage: -2.4
|
||||
sensor_voltage: -1.1
|
||||
ftransz:
|
||||
description: Sample transer Z
|
||||
deviceClass: csaxs_bec.devices.omny.galil.fgalil_ophyd.FlomniGalilMotor
|
||||
@@ -344,6 +344,9 @@ rtx:
|
||||
description: flomni rt
|
||||
deviceClass: csaxs_bec.devices.omny.rt.rt_flomni_ophyd.RtFlomniMotor
|
||||
deviceConfig:
|
||||
limits:
|
||||
- -200
|
||||
- 200
|
||||
axis_Id: A
|
||||
host: mpc2844.psi.ch
|
||||
port: 2222
|
||||
@@ -361,6 +364,9 @@ rty:
|
||||
description: flomni rt
|
||||
deviceClass: csaxs_bec.devices.omny.rt.rt_flomni_ophyd.RtFlomniMotor
|
||||
deviceConfig:
|
||||
limits:
|
||||
- -100
|
||||
- 100
|
||||
axis_Id: B
|
||||
host: mpc2844.psi.ch
|
||||
port: 2222
|
||||
@@ -376,6 +382,9 @@ rtz:
|
||||
description: flomni rt
|
||||
deviceClass: csaxs_bec.devices.omny.rt.rt_flomni_ophyd.RtFlomniMotor
|
||||
deviceConfig:
|
||||
limits:
|
||||
- -100
|
||||
- 100
|
||||
axis_Id: C
|
||||
host: mpc2844.psi.ch
|
||||
port: 2222
|
||||
|
||||
@@ -394,7 +394,7 @@ class RtFlomniController(Controller):
|
||||
val = float(self.socket_put_and_receive(f"j{axis_number}").strip())
|
||||
return val
|
||||
|
||||
def laser_tracker_check_signalstrength(self):
|
||||
def laser_tracker_check_signalstrength(self, verbose=True):
|
||||
if not self.laser_tracker_check_enabled():
|
||||
returnval = "disabled"
|
||||
else:
|
||||
@@ -405,9 +405,10 @@ class RtFlomniController(Controller):
|
||||
rtx = self.device_manager.devices.rtx
|
||||
min_signal = rtx.user_parameter.get("min_signal")
|
||||
low_signal = rtx.user_parameter.get("low_signal")
|
||||
print(f"low signal: {low_signal}")
|
||||
print(f"min signal: {min_signal}")
|
||||
print(f"signal: {signal}")
|
||||
if verbose:
|
||||
print(f"low signal: {low_signal}")
|
||||
print(f"min signal: {min_signal}")
|
||||
print(f"signal: {signal}")
|
||||
if signal < min_signal:
|
||||
time.sleep(1)
|
||||
if signal < min_signal:
|
||||
@@ -621,6 +622,18 @@ class RtFlomniSetpointSignal(RtSetpointSignal):
|
||||
"The interferometer feedback is not running. Either it is turned off or and"
|
||||
" interferometer error occured."
|
||||
)
|
||||
|
||||
tracker_status = self.parent.controller.laser_tracker_check_signalstrength()
|
||||
|
||||
if tracker_status == "toolow":
|
||||
print(
|
||||
"The interferometer signal is too low for movements. Realignment required."
|
||||
)
|
||||
raise RtError(
|
||||
"The interferometer signal is too low for movements. Realignment required."
|
||||
)
|
||||
|
||||
|
||||
self.set_with_feedback_disabled(val)
|
||||
|
||||
def set_with_feedback_disabled(self, val):
|
||||
|
||||
@@ -48,6 +48,7 @@ class OMNYFastShutter(PSIDeviceBase, Device):
|
||||
def fshopen(self):
|
||||
"""Open the fast shutter."""
|
||||
if self._check_if_cSAXS_shutter_exists_in_config():
|
||||
self.shutter.put(1)
|
||||
return self.device_manager.devices["fsh"].fshopen()
|
||||
else:
|
||||
self.shutter.put(1)
|
||||
@@ -55,6 +56,7 @@ class OMNYFastShutter(PSIDeviceBase, Device):
|
||||
def fshclose(self):
|
||||
"""Close the fast shutter."""
|
||||
if self._check_if_cSAXS_shutter_exists_in_config():
|
||||
self.shutter.put(0)
|
||||
return self.device_manager.devices["fsh"].fshclose()
|
||||
else:
|
||||
self.shutter.put(0)
|
||||
|
||||
@@ -50,16 +50,15 @@ Manually move the gripper to a transfer position
|
||||
After the sample transfer the sample stage moved to the measurement position with your new sample. The Xray eye will automatically move in and the shutter will open. You may already see the sample in the omny xeye interface running on the windows computer.
|
||||
If you see your sample already at the approximately correct height, you can skip steps 1 to 3. Otherwise adjust the height:
|
||||
|
||||
1. `flomni.rt_feedback_disable()` disable the closed loop operation to allow movement of coarse stages
|
||||
1. `flomni.feedback_disable()` disable the closed loop operation to allow movement of coarse stages
|
||||
1. `umvr(dev.fsamy, 0.01)`, attention: unit <mm>, move the sample stage relative up (positive) or down (negative) until the sample is approximately vertically centered in xray eye screen
|
||||
1. `flomni.xrayeye_update_frame()` will update the current image on the xray eye screen
|
||||
1. `flomni.xrayeye_alignment_start()` start the coarse alignment of the sample by measuring (clicking in the X-ray eye software) the sample position at 0, 45, 90, 135, 180 degrees. Then use the matlab routine `SPEC_ptycho_align.m` to fit this data.
|
||||
1. `flomni.read_alignment_offset()` read the generated alignment data.
|
||||
1. `flomni.xrayeye_alignment_start()` start the coarse alignment of the sample by measuring (clicking in the X-ray eye software) the sample position at 0, 45, 90, 135, 180 degrees. The GUI will present a fit of this data, which is automatically loaded to BEC for aligning the sample.
|
||||
|
||||
#### Fine alignment
|
||||
|
||||
After the xrayeyealign, a fine alignment needs to be performed using ptychography.
|
||||
_To bypass the fine alignment: `feye_out`_
|
||||
_To bypass the fine alignment: `flomni.feye_out`_
|
||||
|
||||
|
||||
1. `flomni.tomo_parameters()` Adjust the ptychographic scan parameters for performing an alignment scan. Typically FOVX = FOVX(Xrayeye)+20 mu, shell step = beamsize/2.5, number of projections and tomo mode are ignored in the alignment scans.
|
||||
@@ -71,13 +70,13 @@ _To bypass the fine alignment: `feye_out`_
|
||||
Now that the sample is aligned, the tomographic measurement can be performed.
|
||||
1. `flomni.tomo_parameters()` adjust the scan parameters for the tomographic scan. This includes the parameters for ptychographic scans of projections plus the strategy for angular sampling. The vertical shift adjusts the field of view, up (positive) or down (negative). After adjusting the numbers, type again `flomni.tomo_parameters()` and verify that they are correct.
|
||||
1. `flomni.tomo_scan_projection(angle)` perform a ptychographic scan at the rotation angle <angle>. Launch the tomographic measurement by `flomni.tomo_scan()`.
|
||||
1. Before changing sample, verify that all subtomograms were completely acquired using the `tomo_recons matlab` script.
|
||||
1. Before changing sample, verify that all subtomograms were completely acquired using the tomo_reconstruction matlab script.
|
||||
|
||||
#### If something went wrong…
|
||||
|
||||
A __single projection__ is to be repeated use
|
||||
`flomni.tomo_scan_projection(<angle>)`. The target angle of scans can be found in the second column of the file in
|
||||
`~/Data10/specES1/dat-files/omni_scannumbers.txt`
|
||||
`~/data/raw/logs/tomography_scannumbers.txt`
|
||||
|
||||
To continue an __interrupted tomography scan__:
|
||||
|
||||
|
||||
@@ -26,7 +26,7 @@ The effective position of the axis of rotation shifts with sample thickness or m
|
||||
1. `dev.lsamx` and `dev.lsamy` will print current position and the center value. Update the center value by
|
||||
`dev.lsamx.update_user_parameter({'center':8.69})`
|
||||
`dev.lsamy.update_user_parameter({'center':8.69})`
|
||||
1. close the shutter: `fshclose()`
|
||||
1. close the shutter: `dev.omnyfsh.fshclose()`
|
||||
|
||||
#### X-ray eye alignment
|
||||
|
||||
|
||||
Reference in New Issue
Block a user