This commit is contained in:
@@ -14,7 +14,7 @@ from aaredaqlib.models import (
|
||||
PuckLoadedInfo,
|
||||
SampleShortInfoList,
|
||||
DAQStatusModel, BeamlineStatus, SessionStatus, SampleCameraSettings, AutofocusSettings, )
|
||||
from aaredaqlib.raster_grid import RasterGridRequest
|
||||
from aaredaqlib.raster_grid import RasterGridRequest, CompletedRasterGrid
|
||||
from aaredaqlib.rotation_scan import RotationScanRequest
|
||||
from aaredaqlib.sample_geometry import SampleGeometryModel
|
||||
|
||||
@@ -252,13 +252,14 @@ class AareDAQ:
|
||||
self.__devs.aerotech.reset()
|
||||
self.__devs.smargon.target = save_smargon_position
|
||||
|
||||
def measure_raster(self, r: RasterGridRequest):
|
||||
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))
|
||||
try:
|
||||
self.__raster(r)
|
||||
self.__set_state(BeamlineStateEnum.SampleAlignment)
|
||||
self.__cfg.state_busy = False
|
||||
return CompletedRasterGrid(request=r)
|
||||
except Exception as e:
|
||||
self.__cfg.state_busy = False
|
||||
raise e
|
||||
|
||||
@@ -7,7 +7,7 @@ import uvicorn
|
||||
from aaredaqlib.coordinate import SmargonCoordinate, Coordinate
|
||||
from aaredaqlib.models import SampleShortInfo, DAQStatusModel, BeamlineStateEnum, BeamlineSettingsModel, \
|
||||
SampleShortInfoList, SessionStatus, SampleCameraSettings, AutofocusSettings
|
||||
from aaredaqlib.raster_grid import RasterGridRequest
|
||||
from aaredaqlib.raster_grid import RasterGridRequest, CompletedRasterGrid
|
||||
from aaredaqlib.rotation_scan import RotationScanRequest
|
||||
from aaredaqlib.sample_geometry import SampleGeometryModel
|
||||
from fastapi import FastAPI, Depends
|
||||
@@ -232,10 +232,9 @@ async def sample_alignment(token: str = Depends(oauth2_scheme)):
|
||||
|
||||
# Scans
|
||||
@app.post("/scan/raster")
|
||||
async def raster(val: RasterGridRequest, token: str = Depends(oauth2_scheme)):
|
||||
async def raster(val: RasterGridRequest, token: str = Depends(oauth2_scheme)) -> CompletedRasterGrid:
|
||||
auth.check_jwt_rw(cfg, auth.parse_token(token))
|
||||
daq.measure_raster(val)
|
||||
return "OK"
|
||||
return daq.measure_raster(val)
|
||||
|
||||
|
||||
@app.post("/scan/rotation")
|
||||
|
||||
@@ -138,6 +138,8 @@ class MainWindow(QMainWindow):
|
||||
self.daq.update.connect(self.beamline.abr_tweak.update_daq_status)
|
||||
self.daq.update.connect(self.status_bar.update_daq_status)
|
||||
self.daq.update.connect(self.beamline.samcam.update_daq_status)
|
||||
self.daq.raster_scan_completed.connect(self.raster.grid_scan_completed)
|
||||
|
||||
self.beamline.samcam.changed.connect(self.daq.samcam_settings)
|
||||
self.beamline.state_panel.sample_exchange.clicked.connect(self.daq.sample_exchange)
|
||||
self.beamline.state_panel.sample_alignment.clicked.connect(self.daq.sample_alignment)
|
||||
@@ -179,6 +181,7 @@ class MainWindow(QMainWindow):
|
||||
self.camera_image.evaluate_grid.connect(self.raster.run_grid_scan)
|
||||
self.data_collection.raster.evaluate_grid.connect(self.raster.run_grid_scan)
|
||||
|
||||
self.camera_image.clear_evaluated_grids.connect(self.raster.clear_completed_grids)
|
||||
self.camera_image.clear_grid.connect(self.raster.clear_active_grid)
|
||||
self.daq.run_number_incremented.connect(self.data_collection.file_path_panel.increment_run_number)
|
||||
|
||||
@@ -193,7 +196,7 @@ class MainWindow(QMainWindow):
|
||||
self.data_collection.raster.exp_time_updated.connect(self.raster.update_exposure_time)
|
||||
self.data_collection.raster.transmission_updated.connect(self.raster.update_transmission)
|
||||
self.data_collection.raster.dtz_updated.connect(self.raster.update_dtz)
|
||||
|
||||
self.data_collection.raster.grid_metric_updated.connect(self.raster.metric)
|
||||
self.raster.grid_scan.connect(self.daq.raster_scan)
|
||||
self.data_collection.screening.rotation_scan.connect(self.daq.standard_scan)
|
||||
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
from PySide6.QtCore import Signal, Slot, Qt
|
||||
from PySide6.QtWidgets import QWidget, QGridLayout, QLabel, QSizePolicy, QSpacerItem, QPushButton, QHBoxLayout
|
||||
from PySide6.QtWidgets import QWidget, QGridLayout, QLabel, QSizePolicy, QSpacerItem, QPushButton, QHBoxLayout, \
|
||||
QComboBox
|
||||
|
||||
from aaredaqlib.diffraction_geometry import DiffractionGeometry
|
||||
from aaregui.panels.scan_settings_panel import ScanSettingsPanel
|
||||
from aaregui.scan_logic.raster_grid_manager import RasterGridManager
|
||||
from aaregui.scan_logic.raster_grid_manager import RasterGridManager, RasterGridMetric
|
||||
from aaregui.widgets.number_line_edit import NumberLineEdit
|
||||
|
||||
|
||||
@@ -11,6 +12,7 @@ class RasterDataCollectionPanel(ScanSettingsPanel):
|
||||
grid_size_updated = Signal(float, float)
|
||||
exp_time_updated = Signal(float)
|
||||
evaluate_grid = Signal()
|
||||
grid_metric_updated = Signal(RasterGridMetric)
|
||||
|
||||
def __init__(self, raster_mgr :RasterGridManager,
|
||||
diffraction: DiffractionGeometry,
|
||||
@@ -72,15 +74,28 @@ class RasterDataCollectionPanel(ScanSettingsPanel):
|
||||
|
||||
self._layout.addWidget(QLabel("μm", parent=self), 6, 4)
|
||||
|
||||
self.metric_combo = QComboBox()
|
||||
self._layout.addWidget(QLabel("Metric", parent=self), 7, 0)
|
||||
|
||||
self.metric_combo.addItem("Background estimate", RasterGridMetric.BKG)
|
||||
self.metric_combo.addItem("Spot count", RasterGridMetric.SPOTS)
|
||||
self.metric_combo.addItem("Indexing result", RasterGridMetric.INDEXING)
|
||||
self.metric_combo.addItem("Mosaicity", RasterGridMetric.MOS)
|
||||
self.metric_combo.addItem("B-factor", RasterGridMetric.BFACTOR)
|
||||
|
||||
self._layout.addWidget(self.metric_combo, 7, 1, 1, 3)
|
||||
|
||||
self.metric_combo.currentIndexChanged.connect(self.metric_changed)
|
||||
|
||||
horizontal_spacer = QSpacerItem(
|
||||
40, 20, QSizePolicy.Policy.Minimum, QSizePolicy.Policy.Expanding
|
||||
)
|
||||
self._layout.addItem(horizontal_spacer, 7, 0, 1, 4)
|
||||
self._layout.addItem(horizontal_spacer, 8, 0, 1, 4)
|
||||
|
||||
self.start_button = QPushButton("Evaluate grid")
|
||||
self.start_button.setStyleSheet("color: rgb(78, 154, 6);")
|
||||
self.start_button.clicked.connect(self.evaluate_grid)
|
||||
self._layout.addWidget(self.start_button, 8, 0, 1, 5)
|
||||
self._layout.addWidget(self.start_button, 9, 0, 1, 5)
|
||||
|
||||
self.update_grid_scan_size()
|
||||
|
||||
@@ -106,4 +121,7 @@ class RasterDataCollectionPanel(ScanSettingsPanel):
|
||||
self.n_x_label.setText(str(self.__n_x))
|
||||
self.size_x_label.setText(f"{self.__size_x * self.__n_x:.1f}")
|
||||
self.n_y_label.setText(str(self.__n_y))
|
||||
self.size_y_label.setText(f"{self.__size_y * self.__n_y:.1f}")
|
||||
self.size_y_label.setText(f"{self.__size_y * self.__n_y:.1f}")
|
||||
|
||||
def metric_changed(self, _: int):
|
||||
self.grid_metric_updated.emit(self.metric_combo.currentData())
|
||||
@@ -1,4 +1,5 @@
|
||||
import math
|
||||
from enum import Enum
|
||||
|
||||
from PySide6.QtCore import QObject, Signal, Slot, QPointF
|
||||
from PySide6.QtGui import QPainter, QPen, QColor, QBrush
|
||||
@@ -9,6 +10,17 @@ from aaredaqlib.coordinate import Coordinate, SmargonCoordinate
|
||||
from aaredaqlib.models import DAQStatusModel
|
||||
from aaredaqlib.raster_grid import RasterGridRequest, CompletedRasterGrid
|
||||
|
||||
class RasterGridMetric(Enum):
|
||||
BKG = 0
|
||||
SPOTS = 1
|
||||
INDEXING = 2
|
||||
MOS = 3
|
||||
BFACTOR = 4
|
||||
|
||||
class GridPointInfo:
|
||||
filename: str
|
||||
det_img: int
|
||||
bkg_estimate: float
|
||||
|
||||
def float_to_viridis_brush(value: float, alpha: int = 127) -> QBrush:
|
||||
"""
|
||||
@@ -65,6 +77,8 @@ class RasterGridManager(QObject):
|
||||
super().__init__()
|
||||
self.__geom = geom
|
||||
|
||||
self.__metric = RasterGridMetric.SPOTS
|
||||
|
||||
self.__start_point : QPointF = QPointF(0, 0)
|
||||
self.__active_grid : RasterGridRequest = RasterGridRequest(
|
||||
n_x= 0,
|
||||
@@ -188,25 +202,38 @@ class RasterGridManager(QObject):
|
||||
def draw_grid(self, painter: QPainter):
|
||||
self._draw_grid(painter, self.__active_grid)
|
||||
for i in self.__completed_grids:
|
||||
self._draw_grid(painter, i.request, i.spot_count)
|
||||
v = None
|
||||
match self.__metric:
|
||||
case RasterGridMetric.BKG:
|
||||
v = i.bkg_estimate
|
||||
case RasterGridMetric.SPOTS:
|
||||
v = i.spot_count
|
||||
case RasterGridMetric.INDEXING:
|
||||
v = i.indexed
|
||||
case RasterGridMetric.MOS:
|
||||
v = i.mosaicity
|
||||
case RasterGridMetric.BFACTOR:
|
||||
v = i.b_factor
|
||||
self._draw_grid(painter, i.request, v)
|
||||
|
||||
def _draw_grid(self, painter: QPainter, grid: RasterGridRequest, values: List[float] | List[int] | None = None):
|
||||
if not self._is_grid_visible(grid):
|
||||
return
|
||||
|
||||
painter.setPen(QPen(QColor(114, 159, 207), 2, Qt.PenStyle.SolidLine))
|
||||
if values is not None:
|
||||
painter.setPen(Qt.PenStyle.NoPen)
|
||||
min_value = min((x for x in values if not math.isnan(x)), default=0)
|
||||
max_value = max((x for x in values if not math.isnan(x)), default=1)
|
||||
else:
|
||||
painter.setPen(QPen(QColor(114, 159, 207), 2, Qt.PenStyle.SolidLine))
|
||||
min_value = 0
|
||||
max_value = 1
|
||||
|
||||
g = grid.grid_size_pxl(self.__geom)
|
||||
c0 = grid.start_pxl(self.__geom)
|
||||
for x in range(self.__active_grid.n_x):
|
||||
for y in range(self.__active_grid.n_y):
|
||||
pxl = x + y * self.__active_grid.n_x
|
||||
for x in range(grid.n_x):
|
||||
for y in range(grid.n_y):
|
||||
pxl = x + y * grid.n_x
|
||||
if values is None or len(values) <= pxl or math.isnan(values[pxl]):
|
||||
painter.setBrush(Qt.BrushStyle.NoBrush)
|
||||
else:
|
||||
@@ -230,4 +257,8 @@ class RasterGridManager(QObject):
|
||||
|
||||
@Slot(str)
|
||||
def update_filename(self, filename: str):
|
||||
self.__active_grid.file_prefix = filename
|
||||
self.__active_grid.file_prefix = filename
|
||||
|
||||
@Slot(RasterGridMetric)
|
||||
def metric(self, r: RasterGridMetric):
|
||||
self.__metric = r
|
||||
|
||||
@@ -1,11 +1,15 @@
|
||||
import copy
|
||||
import random
|
||||
|
||||
from PySide6.QtCore import Signal, QUrl, Slot, QTimer, QObject, QByteArray
|
||||
from PySide6.QtNetwork import QNetworkAccessManager, QNetworkRequest, QNetworkReply
|
||||
|
||||
from aaredaqlib.models import DAQStatusModel, SampleShortInfoList, SampleShortInfo, SampleCameraSettings, \
|
||||
AutofocusSettings
|
||||
from aaredaqlib.coordinate import SmargonCoordinate, Coordinate
|
||||
from aaredaqlib.raster_grid import RasterGridRequest
|
||||
from aaredaqlib.raster_grid import RasterGridRequest, CompletedRasterGrid
|
||||
from aaredaqlib.rotation_scan import RotationScanRequest
|
||||
import numpy as np
|
||||
|
||||
SPREADHSEET_FREQUENCY = 25 # Every 5 seconds
|
||||
|
||||
@@ -17,6 +21,7 @@ class DAQWorker(QObject):
|
||||
auth_error = Signal()
|
||||
automated_scan_done = Signal(int, bool) # sample ID, success
|
||||
run_number_incremented = Signal()
|
||||
raster_scan_completed = Signal(CompletedRasterGrid)
|
||||
|
||||
def __init__(self, base_url: str | None, token: str, parent=None):
|
||||
super().__init__(parent)
|
||||
@@ -186,10 +191,39 @@ class DAQWorker(QObject):
|
||||
self.run_number_incremented.emit()
|
||||
self.generic_post("scan/rotation", r.model_dump_json())
|
||||
|
||||
def handle_raster_scan_response(self, reply: QNetworkReply):
|
||||
try:
|
||||
response_data = self.handle_response(reply)
|
||||
parsed_response = CompletedRasterGrid.model_validate_json(response_data)
|
||||
self.raster_scan_completed.emit(parsed_response)
|
||||
except Exception as e:
|
||||
print(e)
|
||||
self.http_error.emit(str(e))
|
||||
|
||||
@Slot(RasterGridRequest)
|
||||
def raster_scan(self, r: RasterGridRequest):
|
||||
self.run_number_incremented.emit()
|
||||
self.generic_post("scan/raster", r.model_dump_json())
|
||||
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)
|
||||
|
||||
reply = CompletedRasterGrid(request=new_copy,
|
||||
bkg_estimate=[random.gauss(3.0, 0.1) for _ in range(image_number)],
|
||||
spot_count=[random.randint(0, 250) for _ in range(image_number)],
|
||||
indexed=[random.randint(0, 1) for _ in range(image_number)],
|
||||
mosaicity=[random.uniform(0, 0.1) for _ in range(image_number)],
|
||||
b_factor=[random.uniform(15.0, 80.0) for _ in range(image_number)])
|
||||
|
||||
self.raster_scan_completed.emit(reply)
|
||||
return
|
||||
|
||||
request = QNetworkRequest(QUrl(f"{self.__base_url}/scan/raster"))
|
||||
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):
|
||||
|
||||
@@ -41,6 +41,7 @@ class SampleCameraImageLabel(QGraphicsView):
|
||||
|
||||
evaluate_grid = Signal()
|
||||
clear_grid = Signal()
|
||||
clear_evaluated_grids = Signal()
|
||||
|
||||
zoom_change = Signal(int)
|
||||
set_omega = Signal(float)
|
||||
@@ -194,10 +195,12 @@ class SampleCameraImageLabel(QGraphicsView):
|
||||
|
||||
scene_pos = self.mapToScene(event.pos())
|
||||
|
||||
menu.addSection("Grid")
|
||||
|
||||
if self.__raster_mgr.is_part_of_active_grid(scene_pos):
|
||||
menu.addSection("Grid")
|
||||
delete_action = menu.addAction("Delete")
|
||||
evaluate_action = menu.addAction("Evaluate")
|
||||
delete_action = menu.addAction("Delete grid")
|
||||
evaluate_action = menu.addAction("Evaluate grid")
|
||||
delete_completed_action = menu.addAction("Delete completed grids")
|
||||
|
||||
action = menu.exec_(self.mapToGlobal(event.pos()))
|
||||
|
||||
@@ -212,6 +215,8 @@ class SampleCameraImageLabel(QGraphicsView):
|
||||
self.clear_grid.emit()
|
||||
elif action == evaluate_action:
|
||||
self.evaluate_grid.emit()
|
||||
elif action == delete_completed_action:
|
||||
self.clear_evaluated_grids.emit()
|
||||
elif action == grab_action:
|
||||
self.__screenshot_with_dialog(overlay=False)
|
||||
elif action == grab_with_overlay_action:
|
||||
|
||||
Reference in New Issue
Block a user