diff --git a/csaxs_bec/bec_ipython_client/plugins/LamNI/extra_tomo.py b/csaxs_bec/bec_ipython_client/plugins/LamNI/extra_tomo.py index 7a42fb6..fbae06c 100644 --- a/csaxs_bec/bec_ipython_client/plugins/LamNI/extra_tomo.py +++ b/csaxs_bec/bec_ipython_client/plugins/LamNI/extra_tomo.py @@ -208,4 +208,4 @@ class DataDrivenLamNI(LamNI): shapes = [data.shape for data in self.tomo_data.values()] if len(set(shapes)) > 1: - raise ValueError(f"Tomo data file has entries of inconsistent lengths: {shapes}.") \ No newline at end of file + raise ValueError(f"Tomo data file has entries of inconsistent lengths: {shapes}.") diff --git a/csaxs_bec/bec_ipython_client/plugins/LamNI/lamni.py b/csaxs_bec/bec_ipython_client/plugins/LamNI/lamni.py index 849a69a..3063ada 100644 --- a/csaxs_bec/bec_ipython_client/plugins/LamNI/lamni.py +++ b/csaxs_bec/bec_ipython_client/plugins/LamNI/lamni.py @@ -250,6 +250,10 @@ class LamNI(LamNIAlignmentMixin, LamNIOpticsMixin, LamniGuiTools): aligner.gui.hide_crosshair() except Exception as gui_exc: # pylint: disable=broad-except logger.warning(f"Failed to hide XRayEye alignment crosshair: {gui_exc}") + try: + aligner.gui.set_dap_params_forwarding(False) + except Exception as gui_exc: # pylint: disable=broad-except + logger.warning(f"Failed to disable XRayEye DAP parameter forwarding: {gui_exc}") raise exc # ── Reset manual shifts if needed ───────────────────────────── @@ -1219,4 +1223,4 @@ class LamNI(LamNIAlignmentMixin, LamNIOpticsMixin, LamniGuiTools): print(f"{angle},{voltage1},{voltage2}") time.sleep(.3) - print("Finished") \ No newline at end of file + print("Finished") diff --git a/csaxs_bec/bec_ipython_client/plugins/LamNI/lamni_alignment_mixin.py b/csaxs_bec/bec_ipython_client/plugins/LamNI/lamni_alignment_mixin.py index b0c44d8..a7ee1fb 100644 --- a/csaxs_bec/bec_ipython_client/plugins/LamNI/lamni_alignment_mixin.py +++ b/csaxs_bec/bec_ipython_client/plugins/LamNI/lamni_alignment_mixin.py @@ -209,11 +209,29 @@ class LamNIAlignmentMixin: tomo_fit_xray_eye = np.zeros((2, 3)) params_x = _dev.omny_xray_gui.fit_params_x.get() + params_y = _dev.omny_xray_gui.fit_params_y.get() + for label, params in (("x", params_x), ("y", params_y)): + if ( + not isinstance(params, dict) + or not {"SineModel_0_amplitude", "SineModel_0_shift", "LinearModel_1_intercept"} + <= params.keys() + ): + raise RuntimeError( + f"No converged DAP sinusoidal fit available for the {label} axis " + f"(omny_xray_gui.fit_params_{label} did not return the expected " + "named parameters -- got " + f"{type(params).__name__ if not isinstance(params, dict) else 'a dict missing keys'}). " + "This means the fit hasn't converged / DAP forwarding hasn't produced " + "a result yet, not that the correction data is missing. Wait for the " + "fit to converge in the XRayEye GUI's Fit tab, or use " + "read_xray_eye_correction() to reload from the archived text files " + "instead." + ) + tomo_fit_xray_eye[0][0] = params_x["SineModel_0_amplitude"] tomo_fit_xray_eye[0][1] = params_x["SineModel_0_shift"] tomo_fit_xray_eye[0][2] = params_x["LinearModel_1_intercept"] - params_y = _dev.omny_xray_gui.fit_params_y.get() tomo_fit_xray_eye[1][0] = params_y["SineModel_0_amplitude"] tomo_fit_xray_eye[1][1] = params_y["SineModel_0_shift"] tomo_fit_xray_eye[1][2] = params_y["LinearModel_1_intercept"] @@ -348,4 +366,4 @@ class LamNIAlignmentMixin: shift_y = corr_pos_y[-1] print(f"Additional correction {label}: x={shift_x}, y={shift_y}") - return (shift_x, shift_y) \ No newline at end of file + return (shift_x, shift_y) diff --git a/csaxs_bec/bec_ipython_client/plugins/LamNI/lamni_optics_mixin.py b/csaxs_bec/bec_ipython_client/plugins/LamNI/lamni_optics_mixin.py index 6e2afa0..2c4b036 100644 --- a/csaxs_bec/bec_ipython_client/plugins/LamNI/lamni_optics_mixin.py +++ b/csaxs_bec/bec_ipython_client/plugins/LamNI/lamni_optics_mixin.py @@ -242,7 +242,10 @@ class LamNIOpticsMixin: self._lfzp_in() if "rtx" in dev and dev.rtx.enabled: + print("Re-establishing interferometer feedback...") + _t0 = time.time() dev.rtx.controller.feedback_enable_with_reset() + print(f"Interferometer feedback re-established ({time.time() - _t0:.1f} s).") def loptics_in(self): """Move in the LamNI optics (FZP + OSA).""" @@ -261,7 +264,10 @@ class LamNIOpticsMixin: if "rtx" in dev and dev.rtx.enabled: time.sleep(1) + print("Re-establishing interferometer feedback...") + _t0 = time.time() dev.rtx.controller.feedback_enable_with_reset() + print(f"Interferometer feedback re-established ({time.time() - _t0:.1f} s).") def lcs_in(self): pass diff --git a/csaxs_bec/bec_ipython_client/plugins/LamNI/test_correctionfile.txt b/csaxs_bec/bec_ipython_client/plugins/LamNI/test_correctionfile.txt new file mode 100644 index 0000000..250af33 --- /dev/null +++ b/csaxs_bec/bec_ipython_client/plugins/LamNI/test_correctionfile.txt @@ -0,0 +1,25 @@ +num_elements = 8 +corr_pos_x[0] = 0.5 +corr_pos_y[0] = -0.3 +corr_angle[0] = 0.0 +corr_pos_x[1] = 0.8 +corr_pos_y[1] = 0.1 +corr_angle[1] = 45.0 +corr_pos_x[2] = 0.6 +corr_pos_y[2] = 0.9 +corr_angle[2] = 90.0 +corr_pos_x[3] = -0.2 +corr_pos_y[3] = 1.1 +corr_angle[3] = 135.0 +corr_pos_x[4] = -0.7 +corr_pos_y[4] = 0.4 +corr_angle[4] = 180.0 +corr_pos_x[5] = -0.9 +corr_pos_y[5] = -0.5 +corr_angle[5] = 225.0 +corr_pos_x[6] = -0.3 +corr_pos_y[6] = -1.0 +corr_angle[6] = 270.0 +corr_pos_x[7] = 0.4 +corr_pos_y[7] = -0.8 +corr_angle[7] = 315.0 \ No newline at end of file diff --git a/csaxs_bec/bec_ipython_client/plugins/LamNI/thingstotest.txt b/csaxs_bec/bec_ipython_client/plugins/LamNI/thingstotest.txt deleted file mode 100644 index 9c53203..0000000 --- a/csaxs_bec/bec_ipython_client/plugins/LamNI/thingstotest.txt +++ /dev/null @@ -1,37 +0,0 @@ -1. Things to test -Progress persistence - -Start tomo_scan(), let a few projections run, restart the BEC client mid-scan, confirm client.get_global_var("tomo_progress") still shows heartbeat/tomo_start_time from before the restart -After ~10 projections, confirm CLI output shows a real ETA (not "N/A") — the threshold is projection > 9 -Confirm the GUI progress display (lamnigui_show_progress()) shows a real start time / ETA, not "N/A" -Force a gap between projections (pause, or simulate an interlock) and confirm the "Detected a X gap... excluding Y from ETA" message appears and accumulated_idle_time grows -Call lamni.tomo_progress_reset(), confirm it clears and prints confirmation - -Correction persistence - -lamni.read_additional_correction(), restart the client, confirm lamni.corr_pos_x/corr_pos_y/corr_angle (+ _2) still hold the loaded values -lamni.reset_correction() / reset_correction_2() — confirm they clear to [] and that clears persist across a restart too -Confirm lamni.compute_additional_correction(angle) still returns sensible values after a restart - -X-ray eye alignment (full run) - -Run lamni.xrayeye_alignment_start() end-to-end -Crosshair appears at the FZP centre after step 0, stays put through all angle steps, disappears at completion -Ctrl-C mid-alignment — confirm the crosshair still disappears (abort path) -Confirm dev.fsh physically opens/closes correctly (not a leftover omnyfsh reference anywhere) -Open the resulting xrayeye_alignmentvalues_.h5: check alignment_values (9,2), alignment_images has real frames, roi_pixel_data has one row per submit, alignment_fit is (3,8) -Confirm the old plain-text file is still written unchanged alongside it -keep_shutter_open=True path still prompts and closes correctly -Watch specifically for whether click positions land where expected (the un-verified /2 pixel-calibration question) - -Burst mode - -Set lamni.frames_per_trigger = N (N>1), run one projection, confirm the detector actually acquires N frames per point -Confirm tomo_parameters() shows and lets you edit it -Confirm 0, negative, non-int, or bool raise ValueError -Confirm leaving it unset still behaves as 1 (no behavior change for existing scans) - -Regression - -extra_tomo.py: exercise MagLamNI.rotate_slowly() — confirm no more AttributeError on self.align -One full short tomo_scan() end-to-end, to confirm none of the above broke the main scan path \ No newline at end of file diff --git a/csaxs_bec/bec_ipython_client/plugins/LamNI/x_ray_eye_align.py b/csaxs_bec/bec_ipython_client/plugins/LamNI/x_ray_eye_align.py index f4e3134..6049ace 100644 --- a/csaxs_bec/bec_ipython_client/plugins/LamNI/x_ray_eye_align.py +++ b/csaxs_bec/bec_ipython_client/plugins/LamNI/x_ray_eye_align.py @@ -43,8 +43,13 @@ class XrayEyeAlign: directions. """ - # Pixel calibration: multiply pixel coordinate by this to get mm - PIXEL_CALIBRATION = 0.2 / 218 # mm/pixel (0.2 mm FOV, 218 px) + # Pixel calibration in mm/pixel (multiply pixel values to get mm). + # The live value is read from the cam_xeye device's ``pixel_calibration`` + # user parameter (see the ``pixel_calibration`` property, matching the + # FlOMNI side); this constant is only the fallback used when that + # device/parameter is unavailable. + PIXEL_CALIBRATION_DEFAULT = 0.2 / 218 # mm/pixel (0.2 mm FOV, 218 px) + PIXEL_CALIBRATION_USER_PARAM = "pixel_calibration" def __init__(self, client, lamni: LamNI) -> None: self.client = client @@ -64,10 +69,14 @@ class XrayEyeAlign: # fresh alignment run should do -- see the start of align() below. # alignment_values[k] = [x_mm, y_mm] # k=0 : FZP centre - # k=1 : sample at 0° (reference; shift_xy computed from k=0 vs k=1) - # k=2 : sample at 45° + # k=1 : sample at 0°, pre-shift (used only to compute shift_xy, + # the base shift to scan centre -- NOT one of the 8 + # angle-fit points used in write_output()) + # k=2 : sample at 0°, post-shift/at scan centre (first real + # angle-fit point; reference for all offsets below) + # k=3 : sample at 45° # ... - # k=8 : sample at 315° + # k=9 : sample at 315° self.alignment_values: dict[int, list[float]] = {} self.alignment_images = [] @@ -80,6 +89,23 @@ class XrayEyeAlign: """Return the live XRayEye RPC handle stored by LamniGuiTools.""" return self.lamni.xeyegui + @property + def pixel_calibration(self) -> float: + """Pixel calibration in mm/pixel. + + Reads the ``pixel_calibration`` user parameter from the cam_xeye + device; falls back to ``PIXEL_CALIBRATION_DEFAULT`` if the device or + parameter is unavailable. Matches the FlOMNI side, which moved from a + hardcoded constant to this camera-sourced value. + """ + try: + mm_per_pixel = dev.cam_xeye.user_parameter.get(self.PIXEL_CALIBRATION_USER_PARAM) + except Exception: + mm_per_pixel = None + if mm_per_pixel is None: + return self.PIXEL_CALIBRATION_DEFAULT + return float(mm_per_pixel) + # ------------------------------------------------------------------ # Helpers # ------------------------------------------------------------------ @@ -118,7 +144,7 @@ class XrayEyeAlign: dev.cam_xeye.live_mode_enabled.put(True) self.gui.on_live_view_enabled(True) dev.fsh.fshopen() - time.sleep(0.5) + time.sleep(1) # store the image: the relevant frame for any submit that follows, # since the shutter is closed again (unless keep_shutter_open) by # the time the user actually clicks submit @@ -150,6 +176,37 @@ class XrayEyeAlign: # Main alignment procedure # ------------------------------------------------------------------ + def _wait_for_dap_fit(self, timeout: float = 30.0, poll_interval: float = 1.0) -> bool: + """Poll ``omny_xray_gui.fit_params_x``/``fit_params_y`` until both report + a converged DAP fit, or *timeout* seconds have passed. + + Returns True if a converged fit was seen, False on timeout. Either way, + the caller (read_xray_eye_correction_from_gui) does its own check and + raises a clear error if the fit still isn't ready -- this just avoids + giving up after an arbitrary fixed sleep when the DAP service is simply + running a bit slower than usual. + """ + required_keys = {"SineModel_0_amplitude", "SineModel_0_shift", "LinearModel_1_intercept"} + t0 = time.time() + while time.time() - t0 < timeout: + params_x = dev.omny_xray_gui.fit_params_x.get() + params_y = dev.omny_xray_gui.fit_params_y.get() + if ( + isinstance(params_x, dict) + and required_keys <= params_x.keys() + and isinstance(params_y, dict) + and required_keys <= params_y.keys() + ): + print(f"DAP fit converged after {time.time() - t0:.1f} s.") + return True + time.sleep(poll_interval) + print( + f"DAP fit did not report converged parameters within {timeout:.0f} s -- " + "proceeding anyway; the next step will raise a clear error if it's " + "still not ready." + ) + return False + def align(self, keep_shutter_open: bool = False): """Run the full LamNI X-ray eye alignment. @@ -177,6 +234,7 @@ class XrayEyeAlign: then load fit parameters into the global variable store. """ self.lamni.lamnigui_show_xeyealign() + self.gui.set_dap_params_forwarding(True) self.send_message("Getting things ready. Please wait...") # Actual start of a fresh alignment run -- see the comment in @@ -209,14 +267,8 @@ class XrayEyeAlign: k = 0 while True: if dev.omny_xray_gui.submit.get() == 1: - val_x = ( - getattr(dev.omny_xray_gui, f"xval_x_{k}").get() - * self.PIXEL_CALIBRATION - ) - val_y = ( - getattr(dev.omny_xray_gui, f"yval_y_{k}").get() - * self.PIXEL_CALIBRATION - ) + val_x = getattr(dev.omny_xray_gui, f"xval_x_{k}").get() * self.pixel_calibration + val_y = getattr(dev.omny_xray_gui, f"yval_y_{k}").get() * self.pixel_calibration self.alignment_values[k] = [val_x, val_y] print( f"Clicked position {k}: " @@ -382,8 +434,8 @@ class XrayEyeAlign: # ------------------------------------------------------------------ self.write_output() - fovx = self._xray_fov_xy[0] * self.PIXEL_CALIBRATION * 1000 / 2 - fovy = self._xray_fov_xy[1] * self.PIXEL_CALIBRATION * 1000 / 2 + fovx = self._xray_fov_xy[0] * self.pixel_calibration * 1000 / 2 + fovy = self._xray_fov_xy[1] * self.pixel_calibration * 1000 / 2 print( f"Largest FOV from X-ray eye alignment:\n" f" fovx = {fovx:.0f} um, fovy = {fovy:.0f} um" @@ -394,14 +446,20 @@ class XrayEyeAlign: ) self.client.set_global_var("tomo_fov_offset", self.shift_xy) - # Switch GUI to fit tab and wait for DAP to finish fitting + # Switch GUI to fit tab and wait for DAP to finish fitting. + # A fixed sleep isn't reliable here -- how long the DAP service + # takes to fit and forward a result varies -- so poll the actual + # signal state instead of guessing a duration. self.lamni.lamnigui_show_xeyealign_fittab() - print("Waiting 5 s for DAP sinusoidal fit to converge...") - time.sleep(5) + print("Waiting for DAP sinusoidal fit to converge...") + self._wait_for_dap_fit(timeout=30) # Read fit parameters from the GUI into the global variable store print("Loading new alignment parameters from X-ray eye GUI fit.") - self.lamni.read_xray_eye_correction_from_gui() + try: + self.lamni.read_xray_eye_correction_from_gui() + finally: + self.gui.set_dap_params_forwarding(False) if keep_shutter_open: answer = input("Close the shutter now? [Y/n]: ").strip().lower() @@ -446,10 +504,19 @@ class XrayEyeAlign: def write_output(self): """Compute x/y offsets for each angle and push them to the GUI fit tab. - Offsets are the displacement of the sample from its position at 0 deg - (k=1 is the reference): - x_offset[i] = (x_at_0deg - x_at_angle_i) * 1000 [um] - y_offset[i] = (y_at_angle_i - y_at_0deg) * 1000 [um] + Offsets are the displacement of the sample at each angle from the FZP + centre (k=0) -- matching FlOMNI's own reference point + (self.alignment_values[0] - self.alignment_values[k]). The FZP centre + is the only point in the whole procedure that's independent of + rotation angle, so it's the only valid zero-reference: using one of + the 8 angle points as the reference instead (as earlier versions of + this method did, first via an off-by-one at k=1, then via k=2) forces + that one point's own offset to be exactly zero by construction -- not + because the sample happens to be centred there, but because + subtracting a value from itself is always zero -- which biases the + whole sinusoidal fit rather than measuring it. + x_offset[i] = (x_at_FZP - x_at_angle_i) * 1000 [um] + y_offset[i] = (y_at_angle_i - y_at_FZP) * 1000 [um] The array passed to submit_fit_array has shape (3, 8): row 0: angles [0, 45, ..., 315] @@ -467,14 +534,10 @@ class XrayEyeAlign: os.makedirs(os.path.dirname(file), exist_ok=True) with open(file, "w") as f: f.write("angle\thorizontal\tvertical\n") - for k in range(1, 9): - angle_deg = LAMNI_ALIGNMENT_ANGLES[k - 1] - x_off = ( - self.alignment_values[1][0] - self.alignment_values[k][0] - ) * 1000 - y_off = ( - self.alignment_values[k][1] - self.alignment_values[1][1] - ) * 1000 + for k in range(2, 10): + angle_deg = LAMNI_ALIGNMENT_ANGLES[k - 2] + x_off = (self.alignment_values[0][0] - self.alignment_values[k][0]) * 1000 + y_off = (self.alignment_values[k][1] - self.alignment_values[0][1]) * 1000 f.write(f"{angle_deg}\t{x_off:.4f}\t{y_off:.4f}\n") print( f" Angle {angle_deg:3d} deg: " @@ -484,14 +547,14 @@ class XrayEyeAlign: angles = np.array(LAMNI_ALIGNMENT_ANGLES, dtype=float) x_offsets = np.array( [ - (self.alignment_values[1][0] - self.alignment_values[k][0]) * 1000 - for k in range(1, 9) + (self.alignment_values[0][0] - self.alignment_values[k][0]) * 1000 + for k in range(2, 10) ] ) y_offsets = np.array( [ - (self.alignment_values[k][1] - self.alignment_values[1][1]) * 1000 - for k in range(1, 9) + (self.alignment_values[k][1] - self.alignment_values[0][1]) * 1000 + for k in range(2, 10) ] ) data = np.array([angles, x_offsets, y_offsets]) diff --git a/csaxs_bec/bec_ipython_client/plugins/flomni/flomni.py b/csaxs_bec/bec_ipython_client/plugins/flomni/flomni.py index 89c0689..7fc83f1 100644 --- a/csaxs_bec/bec_ipython_client/plugins/flomni/flomni.py +++ b/csaxs_bec/bec_ipython_client/plugins/flomni/flomni.py @@ -3761,7 +3761,12 @@ class Flomni( csaxs_bec_basepath.parent / "bec_ipython_client" / "plugins" / "flomni" / logo_file_rel ).resolve() print(logo_file) - bec.messaging.scilog.new().add_attachment(logo_file, width=200).add_text( + scilog = getattr(bec.messaging, "scilog", None) + if scilog is None or not getattr(scilog, "_enabled", False): + logger.warning("SciLog is not enabled; skipping PDF report entry.") + return + + scilog.new().add_attachment(logo_file, width=200).add_text( content.replace("\n", "
") ).add_tags("tomoscan").send() diff --git a/csaxs_bec/bec_ipython_client/plugins/omny/omny_general_tools.py b/csaxs_bec/bec_ipython_client/plugins/omny/omny_general_tools.py index 6aa48f9..40bcd48 100644 --- a/csaxs_bec/bec_ipython_client/plugins/omny/omny_general_tools.py +++ b/csaxs_bec/bec_ipython_client/plugins/omny/omny_general_tools.py @@ -10,6 +10,7 @@ import termios import threading import time import tty +import re from pathlib import Path import epics @@ -323,11 +324,13 @@ class PtychoReconstructor: with open(json_file, "w") as f: json.dump(json_content, f, indent=4) - class TomoIDManager: """Registers a tomography measurement in the OMNY sample database and returns its assigned tomo ID. + Falls back to tomo ID 0 for non-production accounts (e.g. test + accounts like "gac-x01dc") which the server rejects. + Usage: id_manager = TomoIDManager() tomo_id = id_manager.register( @@ -341,11 +344,14 @@ class TomoIDManager: ) """ - # OMNY_URL = "https://omny.web.psi.ch/samples/newmeasurement.php" OMNY_URL = "https://v1p0zyg2w9n2k9c1.myfritz.net/samples/newmeasurement.php" - OMNY_USER = "" - OMNY_PASSWORD = "" TMP_FILE = "~/currsamplesnr.txt" + FALLBACK_TOMO_ID = 0 + + @staticmethod + def _is_valid_eaccount(eaccount: str) -> bool: + """True for real e-accounts (e.g. "e12345"), False for test accounts.""" + return bool(re.fullmatch(r"e\d{5}", eaccount.strip())) def register( self, @@ -359,18 +365,16 @@ class TomoIDManager: ) -> int: """Register a new measurement and return the assigned tomo ID. - Args: - sample_name (str): Name of the sample. - date (str): Date string (e.g. "2024-03-08"). - eaccount (str): E-account identifier. - scan_number (int): First scan number of the measurement. - setup (str): Setup name (e.g. "lamni"). - additional_info (str): Any additional sample information. - user (str): User name. - - Returns: - int: The tomo ID assigned by the OMNY database. + Returns FALLBACK_TOMO_ID (0) if the account is not a real e-account + or if the server cannot be reached / returns an unusable response. """ + if not self._is_valid_eaccount(eaccount): + logger.warning( + f"Account '{eaccount}' is not a valid e-account; " + f"skipping OMNY registration, using tomo ID {self.FALLBACK_TOMO_ID}." + ) + return self.FALLBACK_TOMO_ID + url = ( f"{self.OMNY_URL}" f"?sample={sample_name}" @@ -381,25 +385,20 @@ class TomoIDManager: f"&additional={additional_info}" f"&user={user}" ) - # subprocess.run( - # f"wget --user={self.OMNY_USER} --password={self.OMNY_PASSWORD}" - # f" -q -O {self.TMP_FILE} '{url}'", - # shell=True, - # ) - # print(url) + tmp_file = os.path.expanduser(self.TMP_FILE) - result = subprocess.run(f"wget -q -O {tmp_file} '{url}'", shell=True) - if result.returncode != 0: - raise OMNYToolsError( - f"wget failed (exit code {result.returncode}) fetching tomo ID from {self.OMNY_URL}" - ) try: + result = subprocess.run(f"wget -q -O {tmp_file} '{url}'", shell=True, timeout=30) + if result.returncode != 0: + raise OMNYToolsError( + f"wget failed (exit code {result.returncode}) fetching tomo ID from {self.OMNY_URL}" + ) with open(tmp_file) as f: content = f.read().strip() return int(content) - except FileNotFoundError as exc: - raise OMNYToolsError(f"wget did not produce output file {tmp_file}") from exc - except ValueError as exc: - raise OMNYToolsError( - f"Unexpected response from tomo ID server, got: {content!r}" - ) from exc \ No newline at end of file + except (subprocess.TimeoutExpired, FileNotFoundError, ValueError, OMNYToolsError) as exc: + logger.warning( + f"Could not obtain tomo ID from OMNY database ({exc}); " + f"falling back to tomo ID {self.FALLBACK_TOMO_ID}." + ) + return self.FALLBACK_TOMO_ID \ No newline at end of file diff --git a/csaxs_bec/device_configs/ptycho_lamni.yaml b/csaxs_bec/device_configs/ptycho_lamni.yaml index ad2143f..900e0f9 100644 --- a/csaxs_bec/device_configs/ptycho_lamni.yaml +++ b/csaxs_bec/device_configs/ptycho_lamni.yaml @@ -298,20 +298,10 @@ cam_xeye: onFailure: buffer readOnly: false readoutPriority: async + userParameter: + pixel_calibration: 0.0009174311926605505 # mm/pixel (= 0.2 / 218) -# ############################################################ -# ########## OMNY / flOMNI / LamNI fast shutter ############## -# ############################################################ -omnyfsh: - description: omnyfsh connects to fast shutter at X12 if device fsh exists - deviceClass: csaxs_bec.devices.omny.shutter.OMNYFastShutter - deviceConfig: {} - enabled: true - onFailure: buffer - readOnly: false - readoutPriority: baseline - -############################################################ + ############################################################ #################### GUI Signals ########################### ############################################################ omny_xray_gui: @@ -321,13 +311,4 @@ omny_xray_gui: enabled: true onFailure: buffer readOnly: false - readoutPriority: on_request - -# calculated_signal: -# description: Calculated signal from alignment for fit -# deviceClass: ophyd_devices.ComputedSignal -# deviceConfig: -# compute_method: "def just_rand():\n return 42" -# enabled: true -# readOnly: false -# readoutPriority: baseline \ No newline at end of file + readoutPriority: on_request \ No newline at end of file diff --git a/csaxs_bec/device_configs/simulated_omny/simulated_flomni.yaml b/csaxs_bec/device_configs/simulated_omny/simulated_flomni.yaml index aed27b4..06b1ce4 100644 --- a/csaxs_bec/device_configs/simulated_omny/simulated_flomni.yaml +++ b/csaxs_bec/device_configs/simulated_omny/simulated_flomni.yaml @@ -16,6 +16,18 @@ # omny_panda, omny_xray_gui. ############################################################ +############################################################ +#################### GUI Signals ########################### +############################################################ +omny_xray_gui: + description: Gui signals + deviceClass: csaxs_bec.devices.omny.xray_epics_gui.OMNYXRayAlignGUI + deviceConfig: {} + enabled: true + onFailure: buffer + readOnly: false + readoutPriority: on_request + ############################################################ #################### flOMNI Galil motors ################### ############################################################ diff --git a/csaxs_bec/device_configs/simulated_omny/simulated_lamni.yaml b/csaxs_bec/device_configs/simulated_omny/simulated_lamni.yaml index cb2ad85..e2459d2 100644 --- a/csaxs_bec/device_configs/simulated_omny/simulated_lamni.yaml +++ b/csaxs_bec/device_configs/simulated_omny/simulated_lamni.yaml @@ -136,7 +136,7 @@ lsamrot: sign: 1 sim_stppermm: 50154.32099 sim_encpermm: 36000 - sim_velocity: 12 + sim_velocity: 48 #4x than hw sim_initial_position: 0 deviceTags: - lamni @@ -328,7 +328,8 @@ cam_xeye: onFailure: buffer readOnly: false readoutPriority: async - + userParameter: + pixel_calibration: 0.0009174311926605505 # mm/pixel (= 0.2 / 218) ddg1: description: Simulated main delay generator for triggering deviceClass: csaxs_bec.devices.sim.simulated_beamline_devices.SimulatedDDG1 @@ -347,3 +348,15 @@ fsh: onFailure: raise enabled: true readoutPriority: monitored + +############################################################ +#################### GUI Signals ########################### +############################################################ +omny_xray_gui: + description: Gui signals + deviceClass: csaxs_bec.devices.omny.xray_epics_gui.OMNYXRayAlignGUI + deviceConfig: {} + enabled: true + onFailure: buffer + readOnly: false + readoutPriority: on_request \ No newline at end of file