Compare commits
4 Commits
fix/smarac
...
lamni_comm
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5e914c0a46 | ||
|
|
2b48fb084b | ||
|
|
c0c77648d4 | ||
|
|
3c50781101 |
@@ -12,7 +12,6 @@ from bec_lib.pdf_writer import PDFWriter
|
|||||||
from typeguard import typechecked
|
from typeguard import typechecked
|
||||||
|
|
||||||
from csaxs_bec.bec_ipython_client.plugins.omny.omny_general_tools import (
|
from csaxs_bec.bec_ipython_client.plugins.omny.omny_general_tools import (
|
||||||
BeamlineChecker,
|
|
||||||
OMNYTools,
|
OMNYTools,
|
||||||
PtychoReconstructor,
|
PtychoReconstructor,
|
||||||
TomoIDManager,
|
TomoIDManager,
|
||||||
@@ -40,7 +39,6 @@ class LamNI(LamNIOpticsMixin, LamniGuiTools):
|
|||||||
self.init = LaMNIInitStages(client)
|
self.init = LaMNIInitStages(client)
|
||||||
|
|
||||||
# Extracted collaborators
|
# Extracted collaborators
|
||||||
self.bl_chk = BeamlineChecker(client)
|
|
||||||
self.reconstructor = PtychoReconstructor(self.ptycho_reconstruct_foldername)
|
self.reconstructor = PtychoReconstructor(self.ptycho_reconstruct_foldername)
|
||||||
self.tomo_id_manager = TomoIDManager()
|
self.tomo_id_manager = TomoIDManager()
|
||||||
self.OMNYTools = OMNYTools(self.client)
|
self.OMNYTools = OMNYTools(self.client)
|
||||||
@@ -61,20 +59,6 @@ class LamNI(LamNIOpticsMixin, LamniGuiTools):
|
|||||||
self.progress["total_projections"] = 1
|
self.progress["total_projections"] = 1
|
||||||
self.progress["angle"] = 0
|
self.progress["angle"] = 0
|
||||||
|
|
||||||
# ------------------------------------------------------------------
|
|
||||||
# Beamline checks — delegated to BeamlineChecker
|
|
||||||
# ------------------------------------------------------------------
|
|
||||||
|
|
||||||
@property
|
|
||||||
def beamline_checks_enabled(self):
|
|
||||||
return self.bl_chk.checks_enabled
|
|
||||||
|
|
||||||
@beamline_checks_enabled.setter
|
|
||||||
def beamline_checks_enabled(self, val: bool):
|
|
||||||
self.bl_chk.checks_enabled = val
|
|
||||||
|
|
||||||
def get_beamline_checks_enabled(self):
|
|
||||||
self.bl_chk.print_status()
|
|
||||||
|
|
||||||
# ------------------------------------------------------------------
|
# ------------------------------------------------------------------
|
||||||
# Special angles
|
# Special angles
|
||||||
@@ -552,7 +536,6 @@ class LamNI(LamNIOpticsMixin, LamniGuiTools):
|
|||||||
print(f"Starting LamNI scan for angle {angle} in subtomo {subtomo_number}")
|
print(f"Starting LamNI scan for angle {angle} in subtomo {subtomo_number}")
|
||||||
self._print_progress()
|
self._print_progress()
|
||||||
while not successful:
|
while not successful:
|
||||||
self.bl_chk.start()
|
|
||||||
if not self.special_angles:
|
if not self.special_angles:
|
||||||
self._current_special_angles = []
|
self._current_special_angles = []
|
||||||
if self._current_special_angles:
|
if self._current_special_angles:
|
||||||
@@ -579,10 +562,9 @@ class LamNI(LamNIOpticsMixin, LamniGuiTools):
|
|||||||
for scan_nr in range(start_scan_number, end_scan_number):
|
for scan_nr in range(start_scan_number, end_scan_number):
|
||||||
self._write_tomo_scan_number(scan_nr, angle, subtomo_number)
|
self._write_tomo_scan_number(scan_nr, angle, subtomo_number)
|
||||||
|
|
||||||
if self.bl_chk.stop() and not error_caught:
|
#todo here bl chk, if ok then successfull true
|
||||||
successful = True
|
successful = True
|
||||||
else:
|
|
||||||
self.bl_chk.wait_until_recovered()
|
|
||||||
|
|
||||||
def _golden(self, ii, howmany_sorted, maxangle=360, reverse=False):
|
def _golden(self, ii, howmany_sorted, maxangle=360, reverse=False):
|
||||||
"""Return the ii-th golden ratio angle within sorted bunches and its subtomo number."""
|
"""Return the ii-th golden ratio angle within sorted bunches and its subtomo number."""
|
||||||
|
|||||||
@@ -15,7 +15,11 @@ from csaxs_bec.bec_ipython_client.plugins.cSAXS import cSAXSBeamlineChecks
|
|||||||
from csaxs_bec.bec_ipython_client.plugins.flomni.flomni_optics_mixin import FlomniOpticsMixin
|
from csaxs_bec.bec_ipython_client.plugins.flomni.flomni_optics_mixin import FlomniOpticsMixin
|
||||||
from csaxs_bec.bec_ipython_client.plugins.flomni.x_ray_eye_align import XrayEyeAlign
|
from csaxs_bec.bec_ipython_client.plugins.flomni.x_ray_eye_align import XrayEyeAlign
|
||||||
from csaxs_bec.bec_ipython_client.plugins.flomni.gui_tools import flomniGuiTools
|
from csaxs_bec.bec_ipython_client.plugins.flomni.gui_tools import flomniGuiTools
|
||||||
from csaxs_bec.bec_ipython_client.plugins.omny.omny_general_tools import OMNYTools
|
from csaxs_bec.bec_ipython_client.plugins.omny.omny_general_tools import (
|
||||||
|
OMNYTools,
|
||||||
|
PtychoReconstructor,
|
||||||
|
TomoIDManager,
|
||||||
|
)
|
||||||
|
|
||||||
logger = bec_logger.logger
|
logger = bec_logger.logger
|
||||||
|
|
||||||
@@ -65,9 +69,6 @@ class FlomniError(Exception):
|
|||||||
# print("Please expicitely confirm y or n.")
|
# print("Please expicitely confirm y or n.")
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class FlomniInitStagesMixin:
|
class FlomniInitStagesMixin:
|
||||||
|
|
||||||
def flomni_init_stages(self):
|
def flomni_init_stages(self):
|
||||||
@@ -1159,18 +1160,12 @@ class Flomni(
|
|||||||
super().__init__()
|
super().__init__()
|
||||||
self.client = client
|
self.client = client
|
||||||
self.device_manager = client.device_manager
|
self.device_manager = client.device_manager
|
||||||
self.check_shutter = False
|
|
||||||
self.check_light_available = False
|
|
||||||
self.check_fofb = False
|
|
||||||
self._check_msgs = []
|
|
||||||
self.tomo_id = -1
|
self.tomo_id = -1
|
||||||
self.special_angles = []
|
self.special_angles = []
|
||||||
self.special_angle_repeats = 20
|
self.special_angle_repeats = 20
|
||||||
self.special_angle_tolerance = 20
|
self.special_angle_tolerance = 20
|
||||||
self._current_special_angles = []
|
self._current_special_angles = []
|
||||||
self._beam_is_okay = True
|
self._beam_is_okay = True
|
||||||
self._stop_beam_check_event = None
|
|
||||||
self.beam_check_thread = None
|
|
||||||
self.corr_pos_y = []
|
self.corr_pos_y = []
|
||||||
self.corr_angle_y = []
|
self.corr_angle_y = []
|
||||||
self.corr_pos_y_2 = []
|
self.corr_pos_y_2 = []
|
||||||
@@ -1184,6 +1179,8 @@ class Flomni(
|
|||||||
self.progress["angle"] = 0
|
self.progress["angle"] = 0
|
||||||
self.progress["tomo_type"] = 0
|
self.progress["tomo_type"] = 0
|
||||||
self.OMNYTools = OMNYTools(self.client)
|
self.OMNYTools = OMNYTools(self.client)
|
||||||
|
self.reconstructor = PtychoReconstructor(self.ptycho_reconstruct_foldername)
|
||||||
|
self.tomo_id_manager = TomoIDManager()
|
||||||
self.align = XrayEyeAlign(self.client, self)
|
self.align = XrayEyeAlign(self.client, self)
|
||||||
self.set_client(client)
|
self.set_client(client)
|
||||||
|
|
||||||
@@ -1215,27 +1212,6 @@ class Flomni(
|
|||||||
def axis_id_to_numeric(self, axis_id) -> int:
|
def axis_id_to_numeric(self, axis_id) -> int:
|
||||||
return ord(axis_id.lower()) - 97
|
return ord(axis_id.lower()) - 97
|
||||||
|
|
||||||
def get_beamline_checks_enabled(self):
|
|
||||||
print(
|
|
||||||
f"Shutter: {self.check_shutter}\nFOFB: {self.check_fofb}\nLight available:"
|
|
||||||
f" {self.check_light_available}"
|
|
||||||
)
|
|
||||||
|
|
||||||
@property
|
|
||||||
def beamline_checks_enabled(self):
|
|
||||||
return {
|
|
||||||
"shutter": self.check_shutter,
|
|
||||||
"fofb": self.check_fofb,
|
|
||||||
"light available": self.check_light_available,
|
|
||||||
}
|
|
||||||
|
|
||||||
@beamline_checks_enabled.setter
|
|
||||||
def beamline_checks_enabled(self, val: bool):
|
|
||||||
self.check_shutter = val
|
|
||||||
self.check_light_available = val
|
|
||||||
self.check_fofb = val
|
|
||||||
self.get_beamline_checks_enabled()
|
|
||||||
|
|
||||||
def set_special_angles(self, angles: list, repeats: int = 20, tolerance: float = 0.5):
|
def set_special_angles(self, angles: list, repeats: int = 20, tolerance: float = 0.5):
|
||||||
"""Set the special angles for a tomo
|
"""Set the special angles for a tomo
|
||||||
|
|
||||||
@@ -1379,6 +1355,7 @@ class Flomni(
|
|||||||
@ptycho_reconstruct_foldername.setter
|
@ptycho_reconstruct_foldername.setter
|
||||||
def ptycho_reconstruct_foldername(self, val: str):
|
def ptycho_reconstruct_foldername(self, val: str):
|
||||||
self.client.set_global_var("ptycho_reconstruct_foldername", val)
|
self.client.set_global_var("ptycho_reconstruct_foldername", val)
|
||||||
|
self.reconstructor.folder_name = val # keep reconstructor in sync
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def tomo_angle_stepsize(self):
|
def tomo_angle_stepsize(self):
|
||||||
@@ -1486,7 +1463,6 @@ class Flomni(
|
|||||||
if 0 <= angle < 180.05:
|
if 0 <= angle < 180.05:
|
||||||
print(f"Starting flOMNI scan for angle {angle}")
|
print(f"Starting flOMNI scan for angle {angle}")
|
||||||
while not successful:
|
while not successful:
|
||||||
self._start_beam_check()
|
|
||||||
try:
|
try:
|
||||||
start_scan_number = bec.queue.next_scan_number
|
start_scan_number = bec.queue.next_scan_number
|
||||||
self.tomo_scan_projection(angle)
|
self.tomo_scan_projection(angle)
|
||||||
@@ -1499,11 +1475,9 @@ class Flomni(
|
|||||||
error_caught = True
|
error_caught = True
|
||||||
else:
|
else:
|
||||||
raise exc
|
raise exc
|
||||||
|
#todo here was if blchk success, then setting to success true
|
||||||
if self._was_beam_okay() and not error_caught:
|
successful = True
|
||||||
successful = True
|
|
||||||
else:
|
|
||||||
self._wait_for_beamline_checks()
|
|
||||||
end_scan_number = bec.queue.next_scan_number
|
end_scan_number = bec.queue.next_scan_number
|
||||||
for scan_nr in range(start_scan_number, end_scan_number):
|
for scan_nr in range(start_scan_number, end_scan_number):
|
||||||
self._write_tomo_scan_number(scan_nr, angle, 0)
|
self._write_tomo_scan_number(scan_nr, angle, 0)
|
||||||
@@ -1592,7 +1566,7 @@ class Flomni(
|
|||||||
print(f"Starting flOMNI scan for angle {angle} in subtomo {subtomo_number}")
|
print(f"Starting flOMNI scan for angle {angle} in subtomo {subtomo_number}")
|
||||||
self._print_progress()
|
self._print_progress()
|
||||||
while not successful:
|
while not successful:
|
||||||
self._start_beam_check()
|
self.bl_chk._bl_chk_start()
|
||||||
if not self.special_angles:
|
if not self.special_angles:
|
||||||
self._current_special_angles = []
|
self._current_special_angles = []
|
||||||
if self._current_special_angles:
|
if self._current_special_angles:
|
||||||
@@ -1615,10 +1589,10 @@ class Flomni(
|
|||||||
else:
|
else:
|
||||||
raise exc
|
raise exc
|
||||||
|
|
||||||
if self._was_beam_okay() and not error_caught:
|
if self.bl_chk._bl_chk_stop() and not error_caught:
|
||||||
successful = True
|
successful = True
|
||||||
else:
|
else:
|
||||||
self._wait_for_beamline_checks()
|
self.bl_chk._bl_chk_wait_until_recovered()
|
||||||
end_scan_number = bec.queue.next_scan_number
|
end_scan_number = bec.queue.next_scan_number
|
||||||
for scan_nr in range(start_scan_number, end_scan_number):
|
for scan_nr in range(start_scan_number, end_scan_number):
|
||||||
self._write_tomo_scan_number(scan_nr, angle, subtomo_number)
|
self._write_tomo_scan_number(scan_nr, angle, subtomo_number)
|
||||||
@@ -1770,13 +1744,15 @@ class Flomni(
|
|||||||
self, samplename, date, eaccount, scan_number, setup, sample_additional_info, user
|
self, samplename, date, eaccount, scan_number, setup, sample_additional_info, user
|
||||||
):
|
):
|
||||||
"""Add a sample to the omny sample database. This also retrieves the tomo id."""
|
"""Add a sample to the omny sample database. This also retrieves the tomo id."""
|
||||||
subprocess.run(
|
return self.tomo_id_manager.register(
|
||||||
f"wget --user=omny --password=samples -q -O /tmp/currsamplesnr.txt 'https://omny.web.psi.ch/samples/newmeasurement.php?sample={samplename}&date={date}&eaccount={eaccount}&scannr={scan_number}&setup={setup}&additional={sample_additional_info}&user={user}'",
|
sample_name=samplename,
|
||||||
shell=True,
|
date=date,
|
||||||
|
eaccount=eaccount,
|
||||||
|
scan_number=scan_number,
|
||||||
|
setup=setup,
|
||||||
|
additional_info=sample_additional_info,
|
||||||
|
user=user,
|
||||||
)
|
)
|
||||||
with open("/tmp/currsamplesnr.txt") as tomo_number_file:
|
|
||||||
tomo_number = int(tomo_number_file.read())
|
|
||||||
return tomo_number
|
|
||||||
|
|
||||||
def _at_each_angle(self, angle: float) -> None:
|
def _at_each_angle(self, angle: float) -> None:
|
||||||
if "flomni_at_each_angle" in builtins.__dict__:
|
if "flomni_at_each_angle" in builtins.__dict__:
|
||||||
@@ -1838,19 +1814,11 @@ class Flomni(
|
|||||||
def tomo_reconstruct(self, base_path="~/Data10/specES1"):
|
def tomo_reconstruct(self, base_path="~/Data10/specES1"):
|
||||||
"""write the tomo reconstruct file for the reconstruction queue"""
|
"""write the tomo reconstruct file for the reconstruction queue"""
|
||||||
bec = builtins.__dict__.get("bec")
|
bec = builtins.__dict__.get("bec")
|
||||||
base_path = os.path.expanduser(base_path)
|
self.reconstructor.write(
|
||||||
ptycho_queue_path = Path(os.path.join(base_path, self.ptycho_reconstruct_foldername))
|
scan_list=self._current_scan_list,
|
||||||
ptycho_queue_path.mkdir(parents=True, exist_ok=True)
|
next_scan_number=bec.queue.next_scan_number,
|
||||||
|
base_path=base_path,
|
||||||
# pylint: disable=undefined-variable
|
|
||||||
last_scan_number = bec.queue.next_scan_number - 1
|
|
||||||
ptycho_queue_file = os.path.abspath(
|
|
||||||
os.path.join(ptycho_queue_path, f"scan_{last_scan_number:05d}.dat")
|
|
||||||
)
|
)
|
||||||
with open(ptycho_queue_file, "w") as queue_file:
|
|
||||||
scans = " ".join([str(scan) for scan in self._current_scan_list])
|
|
||||||
queue_file.write(f"p.scan_number {scans}\n")
|
|
||||||
queue_file.write("p.check_nextscan_started 1\n")
|
|
||||||
|
|
||||||
def _write_tomo_scan_number(self, scan_number: int, angle: float, subtomo_number: int) -> None:
|
def _write_tomo_scan_number(self, scan_number: int, angle: float, subtomo_number: int) -> None:
|
||||||
tomo_scan_numbers_file = os.path.expanduser(
|
tomo_scan_numbers_file = os.path.expanduser(
|
||||||
@@ -2101,4 +2069,4 @@ if __name__ == "__main__":
|
|||||||
builtins.__dict__["bec"] = bec
|
builtins.__dict__["bec"] = bec
|
||||||
builtins.__dict__["umv"] = umv
|
builtins.__dict__["umv"] = umv
|
||||||
flomni = Flomni(bec)
|
flomni = Flomni(bec)
|
||||||
flomni.start_x_ray_eye_alignment()
|
flomni.start_x_ray_eye_alignment()
|
||||||
@@ -2,6 +2,7 @@ import builtins
|
|||||||
import datetime
|
import datetime
|
||||||
import fcntl
|
import fcntl
|
||||||
import os
|
import os
|
||||||
|
import socket
|
||||||
import subprocess
|
import subprocess
|
||||||
import sys
|
import sys
|
||||||
import termios
|
import termios
|
||||||
@@ -10,6 +11,7 @@ import time
|
|||||||
import tty
|
import tty
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
|
||||||
|
import epics
|
||||||
import numpy as np
|
import numpy as np
|
||||||
from bec_lib import bec_logger
|
from bec_lib import bec_logger
|
||||||
from rich import box
|
from rich import box
|
||||||
@@ -26,7 +28,8 @@ if builtins.__dict__.get("bec") is not None:
|
|||||||
|
|
||||||
def umv(*args):
|
def umv(*args):
|
||||||
return scans.umv(*args, relative=False)
|
return scans.umv(*args, relative=False)
|
||||||
|
def umvr(*args):
|
||||||
|
return scans.umv(*args, relative=True)
|
||||||
|
|
||||||
class OMNYToolsError(Exception):
|
class OMNYToolsError(Exception):
|
||||||
pass
|
pass
|
||||||
@@ -156,199 +159,6 @@ class OMNYTools:
|
|||||||
|
|
||||||
import socket
|
import socket
|
||||||
|
|
||||||
class BeamlineChecker:
|
|
||||||
"""Monitors beamline health during scans.
|
|
||||||
|
|
||||||
Runs checks in a background thread and blocks scan progress
|
|
||||||
until beam conditions are restored if they fail.
|
|
||||||
|
|
||||||
Usage:
|
|
||||||
checker = BeamlineChecker(client)
|
|
||||||
checker._bl_chk_start()
|
|
||||||
# ... run scan ...
|
|
||||||
beam_was_ok = checker._bl_chk_stop()
|
|
||||||
if not beam_was_ok:
|
|
||||||
checker._bl_chk_wait_until_recovered()
|
|
||||||
"""
|
|
||||||
|
|
||||||
def __init__(self, client):
|
|
||||||
self.client = client
|
|
||||||
self.check_shutter = True
|
|
||||||
self.check_light_available = True
|
|
||||||
self.check_fofb = True
|
|
||||||
self._beam_is_okay = True
|
|
||||||
self._stop_event = None
|
|
||||||
self._thread = None
|
|
||||||
self._local_network_warned = False
|
|
||||||
self._check_msgs = []
|
|
||||||
|
|
||||||
# ------------------------------------------------------------------
|
|
||||||
# Public control interface
|
|
||||||
# ------------------------------------------------------------------
|
|
||||||
|
|
||||||
def bl_chk_status(self):
|
|
||||||
"""Print and return the current enabled/disabled state of all checks."""
|
|
||||||
if self._is_local_network():
|
|
||||||
print("Beamline checks cannot be performed on this network (129.129.98.x) — skipping.")
|
|
||||||
return {}
|
|
||||||
status = {
|
|
||||||
"shutter": self.check_shutter,
|
|
||||||
"fofb": self.check_fofb,
|
|
||||||
"light available": self.check_light_available,
|
|
||||||
}
|
|
||||||
print(
|
|
||||||
f"Shutter: {self.check_shutter}\n"
|
|
||||||
f"FOFB: {self.check_fofb}\n"
|
|
||||||
f"Light available: {self.check_light_available}"
|
|
||||||
)
|
|
||||||
return status
|
|
||||||
|
|
||||||
def bl_chk_enable_all(self):
|
|
||||||
"""Enable all beamline checks."""
|
|
||||||
self.check_shutter = True
|
|
||||||
self.check_light_available = True
|
|
||||||
self.check_fofb = True
|
|
||||||
self.bl_chk_status()
|
|
||||||
|
|
||||||
def bl_chk_disable_all(self):
|
|
||||||
"""Disable all beamline checks."""
|
|
||||||
self.check_shutter = False
|
|
||||||
self.check_light_available = False
|
|
||||||
self.check_fofb = False
|
|
||||||
self.bl_chk_status()
|
|
||||||
|
|
||||||
def bl_chk_enable_shutter(self):
|
|
||||||
"""Enable the shutter check."""
|
|
||||||
self.check_shutter = True
|
|
||||||
self.bl_chk_status()
|
|
||||||
|
|
||||||
def bl_chk_disable_shutter(self):
|
|
||||||
"""Disable the shutter check."""
|
|
||||||
self.check_shutter = False
|
|
||||||
self.bl_chk_status()
|
|
||||||
|
|
||||||
def bl_chk_enable_fofb(self):
|
|
||||||
"""Enable the fast orbit feedback check."""
|
|
||||||
self.check_fofb = True
|
|
||||||
self.bl_chk_status()
|
|
||||||
|
|
||||||
def bl_chk_disable_fofb(self):
|
|
||||||
"""Disable the fast orbit feedback check."""
|
|
||||||
self.check_fofb = False
|
|
||||||
self.bl_chk_status()
|
|
||||||
|
|
||||||
def bl_chk_enable_light(self):
|
|
||||||
"""Enable the light available check."""
|
|
||||||
self.check_light_available = True
|
|
||||||
self.bl_chk_status()
|
|
||||||
|
|
||||||
def bl_chk_disable_light(self):
|
|
||||||
"""Disable the light available check."""
|
|
||||||
self.check_light_available = False
|
|
||||||
self.bl_chk_status()
|
|
||||||
|
|
||||||
def _bl_chk_start(self):
|
|
||||||
"""Start the background beam check thread."""
|
|
||||||
self._beam_is_okay = True
|
|
||||||
self._stop_event = threading.Event()
|
|
||||||
self._thread = threading.Thread(target=self._poll, daemon=True)
|
|
||||||
self._thread.start()
|
|
||||||
|
|
||||||
def _bl_chk_stop(self) -> bool:
|
|
||||||
"""Stop the background thread and return whether beam was okay throughout."""
|
|
||||||
self._stop_event.set()
|
|
||||||
self._thread.join()
|
|
||||||
return self._beam_is_okay
|
|
||||||
|
|
||||||
def _bl_chk_wait_until_recovered(self):
|
|
||||||
"""Block until all beamline checks pass again, logging to SciLog."""
|
|
||||||
self._log_failure_to_scilog()
|
|
||||||
while True:
|
|
||||||
self._beam_is_okay = True
|
|
||||||
self._check_msgs = self._run_checks()
|
|
||||||
if self._beam_is_okay:
|
|
||||||
break
|
|
||||||
self._print_msgs()
|
|
||||||
time.sleep(1)
|
|
||||||
self._log_recovery_to_scilog()
|
|
||||||
|
|
||||||
# ------------------------------------------------------------------
|
|
||||||
# Internal
|
|
||||||
# ------------------------------------------------------------------
|
|
||||||
|
|
||||||
def _is_local_network(self) -> bool:
|
|
||||||
"""Return True if running on the 129.129.98.x subnet."""
|
|
||||||
try:
|
|
||||||
hostname = socket.gethostname()
|
|
||||||
ip = socket.gethostbyname(hostname)
|
|
||||||
return ip.startswith("129.129.98.")
|
|
||||||
except Exception:
|
|
||||||
return False
|
|
||||||
|
|
||||||
def _run_checks(self) -> list:
|
|
||||||
if self._is_local_network():
|
|
||||||
if not self._local_network_warned:
|
|
||||||
print("Beamline checks cannot be performed on this network (129.129.98.x) — skipping.")
|
|
||||||
self._local_network_warned = True
|
|
||||||
return []
|
|
||||||
msgs = []
|
|
||||||
dev = builtins.__dict__.get("dev")
|
|
||||||
try:
|
|
||||||
if self.check_shutter:
|
|
||||||
val = dev.x12sa_es1_shutter_status.read(cached=True)
|
|
||||||
if val["value"].lower() != "open":
|
|
||||||
self._beam_is_okay = False
|
|
||||||
msgs.append("Check beam failed: Shutter is closed.")
|
|
||||||
if self.check_light_available:
|
|
||||||
val = dev.sls_machine_status.read(cached=True)
|
|
||||||
if val["value"] not in ["Light Available", "Light-Available"]:
|
|
||||||
self._beam_is_okay = False
|
|
||||||
msgs.append("Check beam failed: Light not available.")
|
|
||||||
if self.check_fofb:
|
|
||||||
val = dev.sls_fast_orbit_feedback.read(cached=True)
|
|
||||||
if val["value"] != "running":
|
|
||||||
self._beam_is_okay = False
|
|
||||||
msgs.append("Check beam failed: Fast orbit feedback is not running.")
|
|
||||||
except Exception:
|
|
||||||
logger.warning("Failed to check beam.")
|
|
||||||
return msgs
|
|
||||||
|
|
||||||
def _poll(self):
|
|
||||||
while not self._stop_event.is_set():
|
|
||||||
self._check_msgs = self._run_checks()
|
|
||||||
if not self._beam_is_okay:
|
|
||||||
self._stop_event.set()
|
|
||||||
time.sleep(1)
|
|
||||||
|
|
||||||
def _print_msgs(self):
|
|
||||||
for msg in self._check_msgs:
|
|
||||||
logger.warning(msg)
|
|
||||||
|
|
||||||
def _log_failure_to_scilog(self):
|
|
||||||
self._print_msgs()
|
|
||||||
try:
|
|
||||||
bec = builtins.__dict__.get("bec")
|
|
||||||
msg = bec.logbook.LogbookMessage()
|
|
||||||
msg.add_text(
|
|
||||||
"<p><mark class='pen-red'><strong>Beamline checks failed at"
|
|
||||||
f" {str(datetime.datetime.now())}: {''.join(self._check_msgs)}</strong></mark></p>"
|
|
||||||
).add_tag(["BEC", "beam_check"])
|
|
||||||
self.client.logbook.send_logbook_message(msg)
|
|
||||||
except Exception:
|
|
||||||
logger.warning("Failed to send beam failure update to SciLog.")
|
|
||||||
|
|
||||||
def _log_recovery_to_scilog(self):
|
|
||||||
try:
|
|
||||||
bec = builtins.__dict__.get("bec")
|
|
||||||
msg = bec.logbook.LogbookMessage()
|
|
||||||
msg.add_text(
|
|
||||||
"<p><mark class='pen-red'><strong>Operation resumed at"
|
|
||||||
f" {str(datetime.datetime.now())}.</strong></mark></p>"
|
|
||||||
).add_tag(["BEC", "beam_check"])
|
|
||||||
self.client.logbook.send_logbook_message(msg)
|
|
||||||
except Exception:
|
|
||||||
logger.warning("Failed to send beam recovery update to SciLog.")
|
|
||||||
|
|
||||||
class PtychoReconstructor:
|
class PtychoReconstructor:
|
||||||
"""Writes ptychography reconstruction queue files after each scan projection.
|
"""Writes ptychography reconstruction queue files after each scan projection.
|
||||||
|
|
||||||
@@ -389,6 +199,10 @@ class PtychoReconstructor:
|
|||||||
name the queue file.
|
name the queue file.
|
||||||
base_path (str): Root path under which the queue folder lives.
|
base_path (str): Root path under which the queue folder lives.
|
||||||
"""
|
"""
|
||||||
|
if not self._accounts_match():
|
||||||
|
logger.warning("Active BEC account does not match system user — skipping queue file write.")
|
||||||
|
return
|
||||||
|
|
||||||
base_path = os.path.expanduser(base_path)
|
base_path = os.path.expanduser(base_path)
|
||||||
queue_path = Path(os.path.join(base_path, self.folder_name))
|
queue_path = Path(os.path.join(base_path, self.folder_name))
|
||||||
queue_path.mkdir(parents=True, exist_ok=True)
|
queue_path.mkdir(parents=True, exist_ok=True)
|
||||||
|
|||||||
Reference in New Issue
Block a user