DAQ: updated raster COM calculation to send crystal size, b_factor and res estimate to daq status and to do COM on both y and x scans

This commit is contained in:
2025-10-07 13:16:02 +02:00
parent 8cf7cb01ca
commit 3519072651
+78 -20
View File
@@ -593,23 +593,65 @@ class AareDAQ:
print("COM by low res spots")
result_array = self.create_quality_filtered_array(images, 'spots_low_res', min_spots=None,
min_efficiency=1.0, min_background=None)
if r.n_x == 1:
print('vertical scan')
max_image = max(images, key=lambda img: img.spots_low_res)
new_y = max_image.ny
com = (0, new_y)
else:
print('horizontal scan')
com = ndimage.center_of_mass(result_array)
print('horizontal scan')
com = ndimage.center_of_mass(result_array)
print(f"Center of mass: {com}")
try:
labeled_array, num_objects = ndimage.label(result_array)
areas = ndimage.sum(np.ones_like(result_array, dtype=np.int32), labeled_array,
index=range(1, num_objects + 1))
largest_idx = int(np.argmax(areas)) + 1 # +1 because labels start at 1
largest_area = int(areas[largest_idx - 1])
print(f"Largest object label: {largest_idx}, area (px): {largest_area}")
# Optional: get bounding box of largest object
object_mask = labeled_array == largest_idx
rows = np.any(object_mask, axis=1)
cols = np.any(object_mask, axis=0)
row_min, row_max = np.where(rows)[0][[0, -1]]
col_min, col_max = np.where(cols)[0][[0, -1]]
print(f"Largest bbox: width={col_max - col_min}, height={row_max - row_min}")
print(
f"Largest bbox: width={(col_max - col_min) * r.grid_size_mm.x}, y={(row_max - row_min) * r.grid_size_mm.y}")
if r.n_x == 1:
if self.crystal_size is None:
self.crystal_size = CrystalSize(x=0,y=0,z=0)
crystal_size = self.crystal_size
crystal_size = CrystalSize(x=crystal_size.x, y=crystal_size.y,
z=(col_max - col_min) * r.grid_size_mm.y * 1000)
else:
crystal_size = CrystalSize(x=(row_max - row_min) * r.grid_size_mm.x * 1000,
y=(col_max - col_min) * r.grid_size_mm.y * 1000,
z=0)
except Exception as e:
crystal_size = CrystalSize(x=0, y=0, z=0)
self.crystal_size = crystal_size
if r.n_x == 1 and (np.isnan(com[1]) or np.isnan(com[0])):
print('vertical scan')
try:
max_image = max(images, key=lambda img: img.spots_low_res)
com = (0, max_image.ny)
except:
print("no spots")
if np.isnan(com[1]) or np.isnan(com[0]):
print("Center of mass is nan")
com = None
grid_mm_x = None
grid_mm_y = None
best_res = None
best_b_factor = None
else:
grid_mm_x = com[0] * r.grid_size_mm.x
@@ -620,29 +662,45 @@ class AareDAQ:
cx, cy = com[::-1] # com=(y, x) -> (x, y), rounded once
start_x, end_x = round(cx - 1), round(cx + 1)
start_y, end_y = round(cy - 1), round(cy + 1)
print(f"range x {start_x} {end_x}, y {start_y} {end_y}")
# Collect images in the 3x3 neighborhood around the center
res_list = [img for img in images
if start_x <= img.nx <= end_x and start_y <= img.ny <= end_y]
print(res_list)
# Best by res, skipping None
best_res = max((img for img in res_list if img.res is not None),
key=lambda img: img.res,
default=None)
print(f"Best res: {best_res}")
best_b_factor = min((img for img in res_list if img.b is not None),
key=lambda img: img.b,
default=None)
print(f"Best b: {best_b_factor}")
for image in images:
if image.nx == round(com[0]) and image.ny == round(com[1]):
print(f"com found for image: {image.number}")
try:
if best_res is not None and best_res.res is not None:
# store the numeric resolution on the config/session so it appears in status
self.__cfg.last_best_res = float(best_res.res)
else:
self.__cfg.last_best_res = None
except Exception as e:
# Don't break the flow if best_res cannot be published
self.__cfg.last_best_res = None
try:
if best_res is not None and best_res.res is not None:
# store the numeric resolution on the config/session so it appears in status
print(f"best res: {best_res.res}")
self.last_best_res = float(best_res.res)
else:
print(f'res is None')
self.last_best_res = None
except Exception as e:
print(f'error with last_best_res {e}')
self.last_best_res = None
try:
if best_b_factor is not None and best_b_factor.b is not None:
print(f"best res: {best_res.b}")
self.last_best_b_factor = float(best_b_factor.b)
else:
print(f'last_best_b_factor is None')
self.last_best_b_factor = None
except Exception as e:
print(f'error with last_best_b_factor {e}')
self.last_best_b_factor = None
if com is not None and grid_mm_x is not None and grid_mm_y is not None:
new_delta_mm = self.sample_geometry.smargon_nudge(Coordinate(x=grid_mm_x, y=grid_mm_y))