diff --git a/csaxs_bec/bec_ipython_client/plugins/flomni/x_ray_eye_align.py b/csaxs_bec/bec_ipython_client/plugins/flomni/x_ray_eye_align.py index 732dbd9..a1e2717 100644 --- a/csaxs_bec/bec_ipython_client/plugins/flomni/x_ray_eye_align.py +++ b/csaxs_bec/bec_ipython_client/plugins/flomni/x_ray_eye_align.py @@ -70,14 +70,26 @@ class XrayEyeAlign: # so a second submission at step==1 is treated as the real angle-0 # fit point instead of triggering another height correction. self._height_centered = False + # Raw pixel coords + ROI size collected at each submit: + # [[step_k, x_px, y_px, w_px, h_px, image_idx], ...] + # image_idx refers to alignment_images[image_idx], i.e. the last + # frame captured before that submit (shutter is closed at submit time). + self.roi_pixel_data = [] - def _save_alignment_data(self, file_path: str): - os.makedirs(os.path.dirname(file_path), exist_ok=True) - with h5py.File(os.path.expanduser(file_path), "w") as f: + def _save_alignment_data(self, file_path: str, fit_data: np.ndarray | None = None): + expanded = os.path.expanduser(file_path) + os.makedirs(os.path.dirname(expanded), exist_ok=True) + with h5py.File(expanded, "w") as f: f.create_dataset( "alignment_values", data=np.array(list(self.alignment_values.values())) ) f.create_dataset("alignment_images", data=np.array(self.alignment_images)) + if self.roi_pixel_data: + ds = f.create_dataset("roi_pixel_data", data=np.array(self.roi_pixel_data)) + ds.attrs["columns"] = ["step_k", "x_px", "y_px", "w_px", "h_px", "image_idx"] + if fit_data is not None: + ds = f.create_dataset("alignment_fit", data=fit_data) + ds.attrs["rows"] = ["angles_deg", "offsets_um", "zeros"] def update_frame(self, keep_shutter_open=False): if self.flomni._flomnigui_check_attribute_not_exists("xeyegui"): @@ -220,6 +232,20 @@ class XrayEyeAlign: # reset submit channel dev.omny_xray_gui.submit.set(0) + # Raw pixel position and ROI size at submit time. + # The relevant image is the last captured frame (shutter is + # closed by the time the user clicks submit). + _raw_x = getattr(dev.omny_xray_gui, f"xval_x_{k}").get() + _raw_y = getattr(dev.omny_xray_gui, f"yval_y_{k}").get() + _raw_w = getattr(dev.omny_xray_gui, f"width_x_{k}").get() + _raw_h = getattr(dev.omny_xray_gui, f"width_y_{k}").get() + _img_idx = len(self.alignment_images) - 1 + print( + f" Submit k={k}: px x={_raw_x:.1f} y={_raw_y:.1f} " + f"w={_raw_w:.1f} h={_raw_h:.1f} img={_img_idx}" + ) + self.roi_pixel_data.append([k, _raw_x, _raw_y, _raw_w, _raw_h, _img_idx]) + # Controls whether `k` advances to the next step below. Left # True except for the height-centering submission, which # reuses k==1 for a second, real submission afterwards. @@ -252,9 +278,8 @@ class XrayEyeAlign: self.gui.show_crosshair() self.send_message( - "Adjust sample height with the arrows if needed, then mark " - "the sample and submit - height will be centered automatically" - ) + "Submit height. Use arrows if far off." + ) self.gui.enable_submit_button(True) self.movement_buttons_enabled(True, True) @@ -373,37 +398,22 @@ class XrayEyeAlign: ) def write_output(self): - file = os.path.expanduser("~/data/raw/logs/xrayeye_alignmentvalues/xrayeye_alignmentvalues") timestamp = time.strftime("%Y%m%d_%H%M%S") - self._save_alignment_data(file + f"_image_data_{timestamp}.h5") - if not os.path.exists(file): - os.makedirs(os.path.dirname(file), exist_ok=True) + file_h5 = f"~/data/raw/logs/xrayeye_alignmentvalues/xrayeye_alignmentvalues_{timestamp}.h5" - with open(file, "w") as alignment_values_file: - alignment_values_file.write("angle\thorizontal\n") + fovx_offsets = np.zeros(5) + for k in range(1, 6): + fovx_offset = self.alignment_values[0] - self.alignment_values[k] + fovx_offsets[k - 1] = fovx_offset + print(f"Alignment number {k}, value x {fovx_offset}") - # Initialize an empty list to store fovx values - fovx_list = [] - fovx_offsets = np.zeros(5) # holds offsets for k = 1..5 - - for k in range(1, 6): - fovx_offset = self.alignment_values[0] - self.alignment_values[k] - fovx_offsets[k - 1] = fovx_offset # store in array - - fovx_x = (k - 1) * 45 - fovx_list.append([fovx_x, fovx_offset * 1000]) # Append the data to the list - - print(f"Alignment number {k}, value x {fovx_offset}") - alignment_values_file.write(f"{fovx_x}\t{fovx_offset * 1000}\n") - - # Now build final numpy array: - data = np.array( - [ - [0, 45, 90, 135, 180], # angles - fovx_offsets * 1000, # fovx_offset values - [0, 0, 0, 0, 0], - ] - ) + data = np.array( + [ + [0, 45, 90, 135, 180], # angles + fovx_offsets * 1000, # fovx_offset values + [0, 0, 0, 0, 0], + ] + ) + self._save_alignment_data(file_h5, fit_data=data) self.gui.submit_fit_array(data) - print(f"fit submited with {data}") - # self.flomni.flomnigui_show_xeyealign_fittab() \ No newline at end of file + print(f"fit submited with {data}") \ No newline at end of file