diff --git a/src/aare/daq/server.py b/src/aare/daq/server.py index f56e5e70..58c777ad 100644 --- a/src/aare/daq/server.py +++ b/src/aare/daq/server.py @@ -10,6 +10,7 @@ from typing import Any, ClassVar import uvicorn from aarecommon.config.beamline import mx_beamline +from aarecommon.config.config_models import GridscanAnalysisMode from aarecommon.config.logger import get_uvicorn_logging_config, setup_logger from aarecommon.errors.codes import AareErrorCode, export_error_codes_grouped from aarecommon.errors.exception_handler import ( @@ -846,10 +847,10 @@ async def local_contact_restart_device(device: str, token: str = Depends(oauth2_ return result -@app.get("/local_contact/get_gridscan_mode") +@app.get("/local_contact/gridscan_analysis_mode") async def get_gridscan_mode(token: str = Depends(oauth2_scheme)) -> GridscanAnalysisMode: """ - Toggle the TELL blower. Staff only. + Get the gridscan analysis mode Args: token: OAuth2 access token. @@ -859,7 +860,24 @@ async def get_gridscan_mode(token: str = Depends(oauth2_scheme)) -> GridscanAnal """ data = auth.parse_token(token) auth.check_jwt_staff_only(data) - return cfg.get_gridscan_analysis_mode() + return cfg.gridscan_analysis_mode + + +@app.put("/local_contact/gridscan_analysis_mode") +async def set_gridscan_mode(val: GridscanAnalysisMode, token: str = Depends(oauth2_scheme)) -> str: + """ + Set the gridscan analysis mode + + Args: + token: OAuth2 access token. + + Returns: + Dictionary with status and message. + """ + data = auth.parse_token(token) + auth.check_jwt_staff_only(data) + cfg.gridscan_analysis_mode = val + return "OK" @app.post("/local_contact/resync/detector_metadata") diff --git a/src/aare/gui/panels/local_contact_panel.py b/src/aare/gui/panels/local_contact_panel.py index 3361d978..3f12e3aa 100644 --- a/src/aare/gui/panels/local_contact_panel.py +++ b/src/aare/gui/panels/local_contact_panel.py @@ -3,6 +3,7 @@ from __future__ import annotations from collections.abc import Callable from typing import ClassVar +from aarecommon.config.config_models import GridscanAnalysisMode from aarecommon.config.logger import setup_logger from aarecommon.models.models import DAQStatusModel from PySide6.QtCore import QUrl, Slot @@ -616,8 +617,34 @@ class LocalContactPanel(QFrame): button_layout.addWidget(reload_button) button_layout.addStretch(1) + analysis_settings = QGroupBox("Analysis settings", tab) + analysis_settings_layout = QGridLayout(analysis_settings) + form_layout.setContentsMargins(10, 12, 10, 10) + form_layout.setHorizontalSpacing(8) + form_layout.setVerticalSpacing(8) + analysis_choice_label = QLabel("Gridscan analysis mode:", analysis_settings) + find_xtal_button = QPushButton('classic "find_xtal.py"', analysis_settings) + jfj_gs_u_button = QPushButton('Meitian\'s "jfjoch_gridscan_union.py"', analysis_settings) + current_label = QLabel("Current:", analysis_settings) + current_value_label = QLabel("Unknown/default", analysis_settings) + analysis_settings_layout.addWidget(analysis_choice_label, 1, 0) + analysis_settings_layout.addWidget(find_xtal_button, 2, 0) + analysis_settings_layout.addWidget(jfj_gs_u_button, 2, 1) + analysis_settings_layout.addWidget(current_label, 2, 2) + analysis_settings_layout.addWidget(current_value_label, 2, 3) + + find_xtal_button.clicked.connect( + lambda: self._daq.set_gridscan_analysis_mode(GridscanAnalysisMode.FindXtal) + ) + jfj_gs_u_button.clicked.connect( + lambda: self._daq.set_gridscan_analysis_mode(GridscanAnalysisMode.JfjochGridscanUnion) + ) + self._daq.gridscan_analysis_mode.connect(current_value_label.setText) + self._daq.refresh_gridscan_analysis_mode() + layout.addWidget(form_box) layout.addWidget(button_row) + layout.addWidget(analysis_settings) layout.addStretch(1) return tab diff --git a/src/aare/gui/threads/daq_worker.py b/src/aare/gui/threads/daq_worker.py index 81579a2b..7fdd3ffc 100644 --- a/src/aare/gui/threads/daq_worker.py +++ b/src/aare/gui/threads/daq_worker.py @@ -10,6 +10,7 @@ from dataclasses import dataclass from datetime import datetime from typing import ClassVar, Literal, cast +from aarecommon.config.config_models import GridscanAnalysisMode from aarecommon.config.logger import setup_logger from aarecommon.errors.codes import AareErrorCode, AuthErrorCode, export_error_codes from aarecommon.math.coordinate import AerotechCoordinate, SmargonCoordinate @@ -136,6 +137,8 @@ class DAQWorker(QObject): steer_beam_available = Signal(bool) + gridscan_analysis_mode = Signal(str) + def __init__(self, base_url: str | None, token: str, parent=None): """ Initialize the DAQWorker. @@ -1694,6 +1697,24 @@ class DAQWorker(QObject): logger.exception(message) self.local_contact_transfer_error.emit(message) + def refresh_gridscan_analysis_mode(self): + request = QNetworkRequest(QUrl(f"{self._base_url}/local_contact/gridscan_analysis_mode")) + request.setRawHeader(b"Authorization", f"Bearer {self._token}".encode()) + reply = self._net_manager.get(request) + reply.finished.connect( + lambda: self.gridscan_analysis_mode.emit(self.handle_response(reply)) + ) + + def set_gridscan_analysis_mode(self, value: GridscanAnalysisMode): + request = QNetworkRequest( + QUrl(f"{self._base_url}/local_contact/gridscan_analysis_mode?val={value!s}") + ) + request.setRawHeader(b"Authorization", f"Bearer {self._token}".encode()) + request.setRawHeader(b"Content-Type", b"application/json") + body = QByteArray(str(value).encode("utf-8")) + reply = self._net_manager.put(request, body) + reply.finished.connect(lambda: self.refresh_gridscan_analysis_mode()) + @Slot(str, bool) def set_local_contact_simulation(self, device: str, enabled: bool): self.generic_post(f"local_contact/simulate/{device}?enabled={str(enabled).lower()}")