DAQ: Added auto-centering
This commit is contained in:
+65
-34
@@ -322,6 +322,40 @@ class AareDAQ:
|
||||
else:
|
||||
return None
|
||||
|
||||
def __auto_center(self, grid: RasterGridRequest) -> CompletedRasterGrid | None:
|
||||
sample = self.sample
|
||||
if sample is None:
|
||||
raise Exception("Sample must be mounted to auto center")
|
||||
|
||||
self.__devs.aerotech.move(grid.omega_deg, wait=True)
|
||||
old_prefix = grid.file_prefix
|
||||
r = self.__ml_bounding_box(sample.db_id, grid.file_prefix)
|
||||
if r is not None:
|
||||
grid.smargon = r.smargon
|
||||
grid.grid_size_mm = r.grid_size_mm
|
||||
grid.n_x = r.n_x
|
||||
grid.n_y = r.n_y
|
||||
grid.file_prefix = f"{old_prefix}_{grid.omega_deg}deg"
|
||||
|
||||
res1 = self.__raster(grid)
|
||||
|
||||
# self.__devs.aerotech.move(grid.omega_deg + 90, wait=True)
|
||||
self.__set_state(BeamlineStateEnum.SampleAlignment)
|
||||
return res1
|
||||
else:
|
||||
return None
|
||||
|
||||
def auto_center(self, grid: RasterGridRequest) -> CompletedRasterGrid | None:
|
||||
try:
|
||||
self.__cfg.try_set_busy(timeout=360)
|
||||
result = self.__auto_center(grid)
|
||||
self.__cfg.state_busy = False
|
||||
return result
|
||||
except Exception as e:
|
||||
self.__set_state(BeamlineStateEnum.SampleAlignment)
|
||||
self.__cfg.state_busy = False
|
||||
raise e
|
||||
|
||||
def __raster(self, r: RasterGridRequest) -> CompletedRasterGrid:
|
||||
max_time = r.exp_time_s * r.n_y * r.n_x + 60
|
||||
self.__cfg.dtz = r.dtz
|
||||
@@ -367,11 +401,13 @@ class AareDAQ:
|
||||
self.__devs.smargon.target = save_smargon_position
|
||||
return CompletedRasterGrid(request=copy.deepcopy(r), result=result)
|
||||
|
||||
def measure_raster(self, r: RasterGridRequest) -> CompletedRasterGrid:
|
||||
max_time = r.exp_time_s * r.n_y * r.n_x + 60
|
||||
self.__cfg.try_set_busy(timeout=ceil(max_time + 360))
|
||||
def measure_raster(self, r: RasterGridRequest, auto: bool) -> CompletedRasterGrid:
|
||||
self.__cfg.try_set_busy(timeout=ceil(360))
|
||||
try:
|
||||
result = self.__raster(r)
|
||||
if auto:
|
||||
result = self.__auto_center(r)
|
||||
else:
|
||||
result = self.__raster(r)
|
||||
self.__set_state(BeamlineStateEnum.SampleAlignment)
|
||||
self.__cfg.state_busy = False
|
||||
return result
|
||||
@@ -565,7 +601,7 @@ class AareDAQ:
|
||||
def listen_changes(self) -> redis.client.PubSub:
|
||||
return self.__cfg.listen_changes()
|
||||
|
||||
def __ml_bounding_box(self, sample_id: int | None = None, filename: str | None = None, move: bool = False) -> BoundingBoxModel | None:
|
||||
def __ml_bounding_box(self, sample_id: int | None = None, filename: str | None = None) -> RasterGridRequest | None:
|
||||
time.sleep(0.2) # Just to be sure image is stable
|
||||
#curr_image = self.camera_image
|
||||
#box = self.__mlbox.predict(curr_image)
|
||||
@@ -574,42 +610,37 @@ class AareDAQ:
|
||||
if box 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
|
||||
x1, y1, x2, y2 = box
|
||||
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)
|
||||
if move:
|
||||
geom = self.sample_geometry
|
||||
coord = geom.picture_to_smargon(Coordinate(x=x1, y=y1))
|
||||
self.__devs.smargon.target = SmargonCoordinate(sh_mm=coord)
|
||||
self.__devs.smargon.wait(60)
|
||||
return BoundingBoxModel(bottom_x=x1, bottom_y=y1, top_x=x2, top_y=y2)
|
||||
|
||||
def ml_bounding_box(self, sample_id: int | None = None, filename: str | None = None, move: bool = False) -> RasterGridRequest | None:
|
||||
geom = self.sample_geometry
|
||||
|
||||
start_coord = geom.picture_to_smargon(Coordinate(x=x1, y=y1))
|
||||
grid_size = Coordinate(x=geom.beam_size_mm.x * 0.8, y=geom.beam_size_mm.y * 0.8)
|
||||
n_x = abs(ceil((x2 - x1) * geom.pixel_in_mm / grid_size.x))
|
||||
n_y = abs(ceil((y2 - y1) * geom.pixel_in_mm / grid_size.y))
|
||||
|
||||
return RasterGridRequest(
|
||||
exp_time_s=0.02,
|
||||
transmission=1.0,
|
||||
smargon= SmargonCoordinate(chi_deg = geom.smargon.chi_deg,
|
||||
phi_deg= geom.smargon.phi_deg,
|
||||
sh_mm=start_coord),
|
||||
n_x=n_x,
|
||||
n_y=n_y,
|
||||
grid_size_mm= grid_size,
|
||||
omega_deg=geom.omega_deg
|
||||
)
|
||||
|
||||
def ml_bounding_box(self, sample_id: int | None = None, filename: str | None = None) -> RasterGridRequest | None:
|
||||
try:
|
||||
self.__cfg.try_set_busy(timeout=360)
|
||||
ml_box = self.__ml_bounding_box(sample_id, filename, move)
|
||||
r = None
|
||||
if ml_box is not None:
|
||||
geom = self.sample_geometry
|
||||
|
||||
start_coord = geom.picture_to_smargon(Coordinate(x=ml_box.bottom_x, y=ml_box.bottom_y))
|
||||
grid_size = Coordinate(x=geom.beam_size_mm.x * 0.8, y=geom.beam_size_mm.y * 0.8)
|
||||
n_x = abs(ceil((ml_box.top_x - ml_box.bottom_x) * geom.pixel_in_mm / grid_size.x))
|
||||
n_y = abs(ceil((ml_box.top_y - ml_box.bottom_y) * geom.pixel_in_mm / grid_size.y))
|
||||
|
||||
r = RasterGridRequest(
|
||||
exp_time_s=0.05,
|
||||
smargon= SmargonCoordinate(chi_deg = geom.smargon.chi_deg,
|
||||
phi_deg= geom.smargon.phi_deg,
|
||||
sh_mm=start_coord),
|
||||
n_x=n_x,
|
||||
n_y=n_y,
|
||||
grid_size_mm= grid_size,
|
||||
omega_deg=geom.omega_deg
|
||||
)
|
||||
r = self.__ml_bounding_box(sample_id, filename)
|
||||
self.__cfg.state_busy = False
|
||||
return r
|
||||
except Exception:
|
||||
@@ -748,7 +779,7 @@ class AareDAQ:
|
||||
|
||||
self.__devs.aerotech.move(0, wait=True)
|
||||
|
||||
self.__ml_bounding_box(sample.db_id, f"bb_raster_0", move=True)
|
||||
self.__ml_bounding_box(sample.db_id, f"bb_raster_0")
|
||||
|
||||
self.__raster(
|
||||
RasterGridRequest(
|
||||
@@ -763,7 +794,7 @@ class AareDAQ:
|
||||
|
||||
self.__devs.aerotech.move(90, wait=True)
|
||||
|
||||
self.__ml_bounding_box(sample.db_id, f"bb_raster_90", move=True)
|
||||
self.__ml_bounding_box(sample.db_id, f"bb_raster_90")
|
||||
|
||||
self.__raster(
|
||||
RasterGridRequest(
|
||||
|
||||
@@ -289,9 +289,9 @@ async def beam_location(token: str = Depends(oauth2_scheme)):
|
||||
|
||||
# Scans
|
||||
@app.post("/scan/raster")
|
||||
async def raster(val: RasterGridRequest, token: str = Depends(oauth2_scheme)) -> CompletedRasterGrid:
|
||||
async def raster(val: RasterGridRequest, auto: bool = False, token: str = Depends(oauth2_scheme)) -> CompletedRasterGrid:
|
||||
auth.check_jwt_rw(cfg, auth.parse_token(token))
|
||||
return daq.measure_raster(val)
|
||||
return daq.measure_raster(val, auto)
|
||||
|
||||
|
||||
@app.post("/scan/rotation")
|
||||
|
||||
@@ -201,6 +201,7 @@ class MainWindow(QMainWindow):
|
||||
|
||||
self.sample_camera.evaluate_grid.connect(self.raster.run_grid_scan)
|
||||
self.data_collection.raster.evaluate_grid.connect(self.raster.run_grid_scan)
|
||||
self.data_collection.raster.evaluate_grid_auto.connect(self.raster.run_grid_scan_auto)
|
||||
|
||||
self.sample_camera.clear_evaluated_grids.connect(self.raster.clear_completed_grids)
|
||||
self.sample_camera.clear_grid.connect(self.raster.clear_active_grid)
|
||||
@@ -222,6 +223,7 @@ class MainWindow(QMainWindow):
|
||||
self.data_collection.cancel.connect(self.daq.cancel)
|
||||
|
||||
self.raster.grid_scan.connect(self.daq.raster_scan)
|
||||
self.raster.grid_scan_auto.connect(self.daq.raster_scan_auto)
|
||||
self.data_collection.screening.rotation_scan.connect(self.daq.standard_scan)
|
||||
|
||||
self.raster.grid_scan_size_changed.connect(self.data_collection.raster.grid_scan_size_change)
|
||||
|
||||
@@ -13,6 +13,7 @@ class RasterDataCollectionPanel(ScanSettingsPanel):
|
||||
grid_size_updated = Signal(float, float)
|
||||
exp_time_updated = Signal(float)
|
||||
evaluate_grid = Signal()
|
||||
evaluate_grid_auto = Signal()
|
||||
grid_metric_updated = Signal(RasterGridMetric)
|
||||
raster_alpha_changed = Signal(int)
|
||||
|
||||
@@ -114,6 +115,11 @@ class RasterDataCollectionPanel(ScanSettingsPanel):
|
||||
self.start_button.clicked.connect(self.evaluate_grid)
|
||||
self._layout.addWidget(self.start_button, 11, 0, 1, 5)
|
||||
|
||||
self.auto_button = QPushButton("Feeling lucky")
|
||||
self.auto_button.setStyleSheet("color: rgb(78, 154, 6);")
|
||||
self.auto_button.clicked.connect(self.evaluate_grid_auto)
|
||||
self._layout.addWidget(self.auto_button, 12, 0, 1, 5)
|
||||
|
||||
self.update_grid_scan_size()
|
||||
|
||||
@Slot(float)
|
||||
|
||||
@@ -73,7 +73,10 @@ def normalize_angle(angle_deg: float) -> float:
|
||||
|
||||
class RasterGridManager(QObject):
|
||||
grid_updated = Signal()
|
||||
|
||||
grid_scan = Signal(RasterGridRequest)
|
||||
grid_scan_auto = Signal(RasterGridRequest)
|
||||
|
||||
grid_scan_size_changed = Signal(int, int, float, float)
|
||||
completed_grid_updated = Signal()
|
||||
|
||||
@@ -309,6 +312,10 @@ class RasterGridManager(QObject):
|
||||
grid = copy.deepcopy(self.__active_grid)
|
||||
self.grid_scan.emit(grid)
|
||||
|
||||
@Slot()
|
||||
def run_grid_scan_auto(self):
|
||||
grid = copy.deepcopy(self.__active_grid)
|
||||
self.grid_scan_auto.emit(grid)
|
||||
|
||||
def spot_ice_ratio(self, obj):
|
||||
if obj.spots_ice is None or obj.spots_low_res is None or obj.spots_low_res <= 0:
|
||||
|
||||
@@ -250,13 +250,46 @@ class DAQWorker(QObject):
|
||||
self.raster_scan_completed.emit(reply)
|
||||
return
|
||||
|
||||
request = QNetworkRequest(QUrl(f"{self.__base_url}/scan/raster"))
|
||||
request = QNetworkRequest(QUrl(f"{self.__base_url}/scan/raster?auto=false"))
|
||||
request.setRawHeader(b"Authorization", f"Bearer {self.__token}".encode("utf-8"))
|
||||
request.setRawHeader(b"Content-Type", b"application/json")
|
||||
body = r.model_dump_json()
|
||||
reply = self.__net_manager.post(request, QByteArray(body.encode("utf-8")))
|
||||
reply.finished.connect(lambda: self.handle_raster_scan_response(reply))
|
||||
|
||||
@Slot(RasterGridRequest)
|
||||
def raster_scan_auto(self, r: RasterGridRequest):
|
||||
self.run_number_incremented.emit()
|
||||
if self.__base_url is None:
|
||||
print(f"POST /scan/raster: {r.model_dump_json()}")
|
||||
image_number = r.get_image_number()
|
||||
new_copy = copy.deepcopy(r)
|
||||
|
||||
images = []
|
||||
for i in range(image_number):
|
||||
images.append(ScanResultImagesInner(
|
||||
number=i,
|
||||
efficiency=1.0,
|
||||
bkg=random.gauss(3.0, 0.1),
|
||||
spots=random.randint(0, 250),
|
||||
index=random.randint(0, 1),
|
||||
mos=random.uniform(0, 0.1),
|
||||
b=random.uniform(15.0, 80.0)
|
||||
))
|
||||
|
||||
reply = CompletedRasterGrid(request=new_copy,
|
||||
result=ScanResult(file_prefix=r.file_prefix, images=images))
|
||||
self.raster_scan_completed.emit(reply)
|
||||
return
|
||||
|
||||
request = QNetworkRequest(QUrl(f"{self.__base_url}/scan/raster?auto=true"))
|
||||
request.setRawHeader(b"Authorization", f"Bearer {self.__token}".encode("utf-8"))
|
||||
request.setRawHeader(b"Content-Type", b"application/json")
|
||||
body = r.model_dump_json()
|
||||
reply = self.__net_manager.post(request, QByteArray(body.encode("utf-8")))
|
||||
reply.finished.connect(lambda: self.handle_raster_scan_response(reply))
|
||||
|
||||
|
||||
@Slot()
|
||||
def load_spreadsheet(self):
|
||||
if self.__base_url is None:
|
||||
|
||||
Reference in New Issue
Block a user