DAQ: updated ALC to use updated mlbox.py and to give more information to the DB
This commit is contained in:
+96
-57
@@ -785,18 +785,19 @@ class AareDAQ:
|
||||
time.sleep(0.2) # Just to be sure image is stable
|
||||
#curr_image = self.camera_image
|
||||
#box = self.__mlbox.predict(curr_image)
|
||||
bgr_image = cv2.cvtColor(self.camera_image, cv2.COLOR_RGB2BGR)
|
||||
box = self.__mlbox.predict(bgr_image, pref_class=(3,0))
|
||||
if box is None:
|
||||
curr_image = cv2.cvtColor(self.camera_image, cv2.COLOR_RGB2BGR)
|
||||
m = self.__mlbox.predict(curr_image, preferred_class=(3,0))
|
||||
if m is None:
|
||||
if filename is not None:
|
||||
cv2.imwrite(f"{filename}_no_detection.jpg", bgr_image)
|
||||
self.__aare.upload_image(sample_id, f"{filename}_no_detection", bgr_image)
|
||||
cv2.imwrite(f"{filename}_no_detection.jpg", curr_image)
|
||||
self.__aare.upload_image(sample_id, f"{filename}_no_detection", curr_image)
|
||||
return None
|
||||
_, x1, y1, x2, y2 = box
|
||||
x1, y1, x2, y2 = m.box.top_x, m.box.top_y, m.box.bottom_x, m.box.bottom_y
|
||||
|
||||
if filename is not None:
|
||||
cv2.rectangle(bgr_image, (int(x1), int(y1)), (int(x2), int(y2)), (0, 255, 0), 2)
|
||||
cv2.imwrite(f"{filename}.jpg", bgr_image)
|
||||
self.__aare.upload_image(sample_id, filename, bgr_image)
|
||||
cv2.rectangle(curr_image, (int(x1), int(y1)), (int(x2), int(y2)), (0, 255, 0), 2)
|
||||
cv2.imwrite(f"{filename}.jpg", curr_image)
|
||||
self.__aare.upload_image(sample_id, filename, curr_image)
|
||||
|
||||
geom = self.sample_geometry
|
||||
|
||||
@@ -817,41 +818,74 @@ class AareDAQ:
|
||||
omega_deg=geom.omega_deg
|
||||
)
|
||||
|
||||
def __ml_loop_centre_box(self, sample_id: int | None = None, filename: str | None = None) -> SmargonCoordinate | None:
|
||||
time.sleep(0.2) # Just to be sure image is stable
|
||||
def __ml_loop_centre_box(self, sample_id: int | None = None, filename: str | None = None) -> tuple[SmargonCoordinate | None, int| None, list[int] | None]:
|
||||
#time.sleep(0.2) # Just to be sure image is stable
|
||||
bgr_image = cv2.cvtColor(self.camera_image, cv2.COLOR_RGB2BGR)
|
||||
box = self.__mlbox.predict(bgr_image, filename)
|
||||
boxes = self.__mlbox.predict_all_best(bgr_image, overlap_with_pin = 0.5, confidence_min=0.3)
|
||||
|
||||
if box is None:
|
||||
if boxes is None:
|
||||
if filename is not None:
|
||||
#cv2.imwrite(f"{filename}_no_detection.jpg", bgr_image)
|
||||
self.__aare.upload_image(sample_id, f"{filename}_no_detection", bgr_image)
|
||||
return None
|
||||
return None, None, None
|
||||
|
||||
cls, x1, y1, x2, y2 = box
|
||||
classes: list[int] = []
|
||||
pin = None
|
||||
centre_x, centre_y = None, None
|
||||
for box in boxes.boxes.values():
|
||||
if box and box.cls is not None:
|
||||
classes.append(int(box.cls.value))
|
||||
if int(box.cls.value) == 1:
|
||||
pin=box
|
||||
|
||||
best_box = self.__mlbox.get_preferred_class_box(boxes, (2,3,0,1))
|
||||
if best_box is None or best_box.box is None or best_box.cls is None:
|
||||
return None, None, classes if classes else None
|
||||
|
||||
|
||||
cls = int(best_box.cls.value)
|
||||
x1 = best_box.box.top_x
|
||||
y1 = best_box.box.top_y
|
||||
x2 = best_box.box.bottom_x
|
||||
y2 = best_box.box.bottom_y
|
||||
|
||||
if filename is not None:
|
||||
#cv2.rectangle(bgr_image, (int(x1), int(y1)), (int(x2), int(y2)), (0, 255, 0), 2)
|
||||
#cv2.imwrite(f"{filename}.jpg", bgr_image)
|
||||
self.__aare.upload_image(sample_id, filename, bgr_image)
|
||||
|
||||
geom = self.sample_geometry
|
||||
|
||||
if cls == 0: # loop_all
|
||||
centre_y = y1 + (y2 - y1)/2
|
||||
centre_x = x1
|
||||
if y1 + y2 <= x1 + x2:
|
||||
centre_y = y1 + (y2 - y1) / 2
|
||||
centre_x = x1
|
||||
elif pin:
|
||||
position_dict = self.__mlbox.check_box_relation(pin, best_box)
|
||||
if position_dict["overlap_y"] and position_dict["overlap_x"]:
|
||||
centre_y = y1 + (y2 - y1) / 2
|
||||
centre_x = x1
|
||||
cls = 1
|
||||
logger.debug("significant overlap between pin and loop_all not picked up by ML")
|
||||
else:
|
||||
centre_y = y2 if position_dict["top"] else y1
|
||||
centre_x = x1 + (x2 - x1) / 2
|
||||
else:
|
||||
centre_y = y1
|
||||
centre_x = x1 + (x2 - x1) / 2
|
||||
|
||||
elif cls == 1: # pin
|
||||
centre_y = y1 + (y2 - y1)/2
|
||||
centre_x = x1
|
||||
|
||||
elif cls == 2 or cls == 3: #crystal or loop_face
|
||||
centre_y = y1 + (y2 - y1)/2
|
||||
centre_x = x1 + (x2 - x1)/2
|
||||
|
||||
else:
|
||||
print(f"unknown box class {cls}")
|
||||
return None
|
||||
return None, cls, classes if classes else None
|
||||
|
||||
coord = geom.picture_to_smargon(Coordinate(x=centre_x, y=centre_y))
|
||||
return SmargonCoordinate(sh_mm=coord)
|
||||
return SmargonCoordinate(sh_mm=coord), cls, classes
|
||||
|
||||
def ml_bounding_box(self, sample_id: int | None = None, filename: str | None = None) -> RasterGridRequest | None:
|
||||
try:
|
||||
@@ -1014,71 +1048,74 @@ class AareDAQ:
|
||||
def __loop_center_sequence(self, sample_id: int | None = None) -> bool:
|
||||
self.__set_state(BeamlineStateEnum.SampleAlignment)
|
||||
self.__devs.lamp_light = 2.5
|
||||
|
||||
found_classes_count: dict[int, int] = {0:0, 1:0, 2:0, 3:0}
|
||||
|
||||
try:
|
||||
i = 0
|
||||
self.__cfg.zoom_mode = ZoomModeEnum.LoopCenter
|
||||
zoom_settings = self.__cfg.zoom_settings.z
|
||||
for zoom_value in zoom_settings:
|
||||
|
||||
for zoom_iter, zoom_value in enumerate(zoom_settings):
|
||||
exposure = zoom_settings[zoom_value].exposure
|
||||
gain = zoom_settings[zoom_value].gain
|
||||
max_attempt = 2
|
||||
attempt = 0
|
||||
found = 0
|
||||
angles = (0, -90)
|
||||
|
||||
base_angles = (0, 45, 90) if (zoom_iter % 2 == 0) else (90, 45, 0)
|
||||
if sample_id is not None:
|
||||
self.save_screenshot_db(sample_id, f"pre_alc")
|
||||
|
||||
while attempt < max_attempt:
|
||||
logger.debug('new loop center settings')
|
||||
self.__devs.samcam_settings = SampleCameraSettings(exposure=exposure, gain=gain)
|
||||
self.__devs.zoom_sync(zoom_value)
|
||||
logger.debug(f'zoom={zoom_value},gain={gain}, exp={exposure}')
|
||||
|
||||
found_flag = False
|
||||
found_angle = None
|
||||
targets_found_this_attempt = 0
|
||||
exp = int(exposure * 1000)
|
||||
gn = int(gain)
|
||||
self.__devs.zoom_sync(zoom_value)
|
||||
logger.debug(f'zoom={zoom_value},gain={gn}, exp={exp}ms')
|
||||
|
||||
for loop, angle in enumerate(angles):
|
||||
found_flag = False
|
||||
found_angle: int | None = None
|
||||
targets_found_this_attempt = 0
|
||||
|
||||
for angle in base_angles:
|
||||
logger.debug(f"Moving to new omega: {angle}")
|
||||
# if sample_id is not None and i == 0:
|
||||
# self.save_screenshot_db(sample_id, f"pre_alc_{sample_id}_{angle}_{zoom_value:.0f}_{exp}_{gn}")
|
||||
time_to_move_aerotech= time.perf_counter()
|
||||
self.__devs.aerotech.move(angle, wait=True)
|
||||
logger.info(f"time to move: {time.perf_counter()-time_to_move_aerotech}")
|
||||
#time.sleep(0.1)
|
||||
filename = None
|
||||
if sample_id is not None:
|
||||
filename = f"{sample_id}_{angle}_{zoom_value:.0f}_{exp}_{gn}"
|
||||
|
||||
target = self.__ml_loop_centre_box(sample_id, filename)
|
||||
filename = f"{sample_id}_{angle}_{zoom_value:.0f}_{exp}_{gn}" if sample_id is not None else None
|
||||
|
||||
if target is not None:
|
||||
try:
|
||||
target, cls, classes = self.__ml_loop_centre_box(sample_id, filename)
|
||||
except:
|
||||
target, cls, classes = None, None, None
|
||||
|
||||
if target is None:
|
||||
continue
|
||||
|
||||
if classes:
|
||||
for c in classes:
|
||||
found_classes_count[int(c)] += 1
|
||||
|
||||
if cls is not None and cls != 1:
|
||||
targets_found_this_attempt += 1
|
||||
found_flag = True
|
||||
found_angle = angle
|
||||
found += 1
|
||||
targets_found_this_attempt += 1
|
||||
time_to_move_smargon = time.perf_counter()
|
||||
self.__devs.smargon.target = target
|
||||
self.__devs.smargon.wait(60)
|
||||
logger.info(f"time to move smargon: {time.perf_counter() - time_to_move_smargon}")
|
||||
|
||||
if sample_id is not None:
|
||||
self.__aare.sample_centered(self.__cfg.current_sample)
|
||||
self.save_screenshot_db(sample_id, f"{sample_id}_{angle}_{zoom_value:.0f}_{exp}_{gn}")
|
||||
|
||||
time_to_move_smargon = time.perf_counter()
|
||||
self.__devs.smargon.target = target
|
||||
self.__devs.smargon.wait(60)
|
||||
logger.info(f"time to move smargon: {time.perf_counter() - time_to_move_smargon}")
|
||||
|
||||
if targets_found_this_attempt == 0:
|
||||
raise LoopCenteringFailed
|
||||
|
||||
else:
|
||||
if found >= 3 or targets_found_this_attempt >= 3:
|
||||
logger.debug(f"sucessfully found {found} or {targets_found_this_attempt} targets in {attempt} attempts")
|
||||
if targets_found_this_attempt >= len(base_angles):
|
||||
logger.debug(f"sucessfully found {targets_found_this_attempt} targets in attempt {attempt + 1} ")
|
||||
break
|
||||
if found_flag is not None and found_angle is not None:
|
||||
logger.debug(f"found a target at angle {found_angle} in attempt {attempt}")
|
||||
angles = (found_angle, found_angle + 45, found_angle + 90)
|
||||
logger.debug(f"found a target at angle {found_angle} in attempt {attempt + 1}")
|
||||
base_angles = (found_angle, found_angle + 45, found_angle + 90)
|
||||
attempt += 1
|
||||
logger.debug(f"attempt {attempt} of {max_attempt}")
|
||||
if attempt >= max_attempt:
|
||||
@@ -1086,8 +1123,11 @@ class AareDAQ:
|
||||
|
||||
#i += 1
|
||||
logger.debug("alc success")
|
||||
#self.face_detection_sequence()
|
||||
self.__aare.sample_centered(self.__cfg.current_sample)
|
||||
if sample_id is not None:
|
||||
self.save_screenshot_db(sample_id, f"{sample_id}_centered")
|
||||
return True
|
||||
|
||||
except Exception as e:
|
||||
logger.info(f"Error in loop centering: {e}")
|
||||
return False
|
||||
@@ -1097,7 +1137,6 @@ class AareDAQ:
|
||||
try:
|
||||
self.__cfg.try_set_busy(timeout=360)
|
||||
if not self.__loop_center_sequence(sample_id):
|
||||
self.__aare.alc_failed(self.sample)
|
||||
raise LoopCenteringFailed
|
||||
self.__cfg.state_busy = False
|
||||
|
||||
|
||||
Reference in New Issue
Block a user