diff --git a/common/pyproject.toml b/common/pyproject.toml index 91ee788d..22916052 100644 --- a/common/pyproject.toml +++ b/common/pyproject.toml @@ -8,7 +8,7 @@ dependencies = [ "pydantic==2.11.4", "numpy==2.2.5", "jfjoch_client==1.0.0rc51", - "aareDB==0.1.1a8" + "aareDB==0.1.1a9" ] [lint] diff --git a/common/src/aaredaqlib/models.py b/common/src/aaredaqlib/models.py index 6ec3874f..685b5c92 100644 --- a/common/src/aaredaqlib/models.py +++ b/common/src/aaredaqlib/models.py @@ -1,6 +1,7 @@ from enum import Enum from typing import Annotated, Literal, Tuple, List, Optional +from aareDBclient.models.data_collection_parameters import DataCollectionParameters from pydantic import BaseModel, Field from aaredaqlib.coordinate import Coordinate @@ -44,6 +45,7 @@ class SampleShortInfo(BaseModel): puck_name: str dewar_name: str sample_name: str + aaredb_params: Optional[DataCollectionParameters] = None user: str = "" pin: Annotated[int, Field(ge=1, le=16)] location: DewarAddress | None = None diff --git a/daq/src/aaredaq/aaredb.py b/daq/src/aaredaq/aaredb.py index 4230f64a..0af75885 100644 --- a/daq/src/aaredaq/aaredb.py +++ b/daq/src/aaredaq/aaredb.py @@ -92,7 +92,8 @@ class AareWrapper: location=dewar_address, priority=1.0 if s.priority is None else s.priority, comment=s.comments, - mount_count=s.mount_count or 0 + mount_count=s.mount_count or 0, + aaredb_params=s.data_collection_parameters ) ) return SampleShortInfoList(s=ret) diff --git a/daq/src/aaredaq/daq.py b/daq/src/aaredaq/daq.py index 05859229..e2869127 100644 --- a/daq/src/aaredaq/daq.py +++ b/daq/src/aaredaq/daq.py @@ -795,7 +795,7 @@ class AareDAQ: light=self.light, cryojet_K=self.__devs.cryojet_temp, shutter_open=self.__devs.shutter, - flux_ph_s=3.0e12, + flux_ph_s=self.__devs.flux, sample_camera=self.__devs.samcam_settings, name=self.__bl, transmission=self.__devs.transmission.get(), diff --git a/daq/src/aaredaq/devices.py b/daq/src/aaredaq/devices.py index 66eaf7a2..a2c31331 100644 --- a/daq/src/aaredaq/devices.py +++ b/daq/src/aaredaq/devices.py @@ -48,6 +48,8 @@ class BeamlineDevices: self.__collimator = PV(f"{BEAMLINE}-ES-COL:TRY1") + self.__bpm = PV(f"{BEAMLINE}-OP-XBPM1:SumAll:MeanValue_RBV") + self.aerotech = aerotech.Abr(beamline) self.aerotech.reload_programs() @@ -263,3 +265,9 @@ class BeamlineDevices: def samcam_settings(self, settings: SampleCameraSettings): print(settings) self.sample_cam.setup(settings.gain, settings.exposure) + + @property + def flux(self) -> float: + # Very approximate value - to be changed + # 2 nA -> 4e11 ph/s + return self.__bpm.value / 2.0 * 4e11 \ No newline at end of file diff --git a/gui/src/aaregui/main_window.py b/gui/src/aaregui/main_window.py index ebf425cc..71fd322f 100644 --- a/gui/src/aaregui/main_window.py +++ b/gui/src/aaregui/main_window.py @@ -21,6 +21,7 @@ from aaregui.panels.data_collection_settings import DataCollectionSettings from aaregui.panels.sample_queue_panel import SampleQueuePanel from aaregui.panels.tell_sample_panel import TellSamplePanel from aaregui.scan_logic.raster_grid_manager import RasterGridManager +from aaregui.scan_logic.sample_mount_logic import SampleMountLogic from aaregui.threads.camera_thread import SampleCameraThread from aaregui.threads.daq_worker import DAQWorker from aaregui.threads.jfjoch_viewer import JFJochDBusClient @@ -111,6 +112,8 @@ class MainWindow(QMainWindow): self.tell_samples_dock.setAllowedAreas(Qt.DockWidgetArea.BottomDockWidgetArea) self.addDockWidget(Qt.DockWidgetArea.BottomDockWidgetArea, self.tell_samples_dock) + self.sample_logic = SampleMountLogic() + self.job_list_dock = QDockWidget("Automation list", self) self.job_list_dock.setWidget(self.job_list_panel) self.job_list_dock.setAllowedAreas(Qt.DockWidgetArea.BottomDockWidgetArea) @@ -126,20 +129,6 @@ class MainWindow(QMainWindow): self.daq = DAQWorker(base_url=self.__base_url, token=self.__token) self.daq.spreadsheet.connect(self.tell_samples.new_sample_list) - self.daq.update.connect(self.beamline.omega_panel.update_daq_status) - self.daq.update.connect(self.beamline.smargon_panel.update_daq_status) - self.daq.update.connect(self.beamline.beam_size.update_daq_status) - self.daq.update.connect(self.beamline.beam_center.update_daq_status) - self.daq.update.connect(self.data_collection.update_daq_status) - self.daq.update.connect(self.beamline.illumination_panel.update_daq_status) - self.daq.update.connect(self.raster.update_daq_status) - self.daq.update.connect(self.camera_image.update_daq_status) - self.daq.update.connect(self.tell_samples.update_daq_status) - 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.update.connect(self.beamline.zoom_panel.update_daq_status) - self.daq.update.connect(self.beamline.beam_mark.update_daq_status) self.daq.raster_scan_completed.connect(self.raster.grid_scan_completed) @@ -218,6 +207,24 @@ class MainWindow(QMainWindow): self.raster.file_ready.connect(self.viewer.load_file) self.raster.image_selected.connect(self.viewer.load_image) + self.sample_logic.sample_changed.connect(self.data_collection.file_path_panel.update_sample) + + self.daq.update.connect(self.beamline.omega_panel.update_daq_status) + self.daq.update.connect(self.beamline.smargon_panel.update_daq_status) + self.daq.update.connect(self.beamline.beam_size.update_daq_status) + self.daq.update.connect(self.beamline.beam_center.update_daq_status) + self.daq.update.connect(self.data_collection.update_daq_status) + self.daq.update.connect(self.beamline.illumination_panel.update_daq_status) + self.daq.update.connect(self.raster.update_daq_status) + self.daq.update.connect(self.camera_image.update_daq_status) + self.daq.update.connect(self.tell_samples.update_daq_status) + 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.update.connect(self.beamline.zoom_panel.update_daq_status) + self.daq.update.connect(self.beamline.beam_mark.update_daq_status) + self.daq.update.connect(self.sample_logic.update_daq_status) + def create_menu_bar(self): """Create a menu bar with File->Quit and Help->About.""" # Main menu bar diff --git a/gui/src/aaregui/panels/beam_size_panel.py b/gui/src/aaregui/panels/beam_size_panel.py index 785399c7..59fd54cd 100644 --- a/gui/src/aaregui/panels/beam_size_panel.py +++ b/gui/src/aaregui/panels/beam_size_panel.py @@ -16,10 +16,10 @@ class BeamSizeWidget(QWidget): grid_layout.addWidget(TitleLabel("Beam size", self), 0, 0, 1, 5) - self.x = NumberLineEdit(1, 40.0, 10, parent=self) + self.x = NumberLineEdit(1, 400.0, 10, parent=self) self.x.newValue.connect(self.beam_size_edited) - self.y = NumberLineEdit(1, 40.0, 10, parent=self) + self.y = NumberLineEdit(1, 400.0, 10, parent=self) self.y.newValue.connect(self.beam_size_edited) grid_layout.addWidget(QLabel("x:"), 1, 0) diff --git a/gui/src/aaregui/panels/data_collection_settings.py b/gui/src/aaregui/panels/data_collection_settings.py index 1968da6c..3a32e7d7 100644 --- a/gui/src/aaregui/panels/data_collection_settings.py +++ b/gui/src/aaregui/panels/data_collection_settings.py @@ -69,4 +69,3 @@ class DataCollectionSettings(QFrame): def update_daq_status(self, s: DAQStatusModel): self.raster.update_daq_status(s) self.screening.update_daq_status(s) - self.file_path_panel.update_daq_status(s) diff --git a/gui/src/aaregui/panels/file_path_panel.py b/gui/src/aaregui/panels/file_path_panel.py index e98229c8..31809a3b 100644 --- a/gui/src/aaregui/panels/file_path_panel.py +++ b/gui/src/aaregui/panels/file_path_panel.py @@ -4,7 +4,7 @@ from datetime import datetime from PySide6.QtCore import Signal, Slot, Qt from PySide6.QtWidgets import QWidget, QGridLayout, QLabel, QLineEdit, QSpinBox, QCheckBox -from aaredaqlib.models import DAQStatusModel +from aaredaqlib.models import SampleShortInfo from aaregui.widgets.title_label import TitleLabel @@ -34,12 +34,25 @@ class FilePathPanel(QWidget): grid_layout.addWidget(QLabel("Directory", parent=self), 2, 0) self.directory_edit = QLineEdit("{date}/{puck}/{pos}", parent=self) self.directory_edit.setStyleSheet("background-color: rgb(255, 255, 255);") - self.directory_edit.setToolTip("Provide subdirectory for your files, you can use \"{date}\" as macro for date.") + self.directory_edit.setToolTip("Provide subdirectory for your files. The following macros are allowed:
" + "{date} - date in format yyyymmdd
" + "{puck} - puck name
" + "{pos} - pin position in puck
" + "{sample} - sample name
" + "{sample_id} - sample id
" + "{prefix} - file prefix value") grid_layout.addWidget(self.directory_edit, 2, 1) grid_layout.addWidget(QLabel("File prefix", parent=self), 3, 0) self.file_prefix_edit = QLineEdit("{sample}", parent=self) self.file_prefix_edit.setStyleSheet("background-color: rgb(255, 255, 255);") + self.file_prefix_edit.setToolTip("Provide file prefix for your files. The following macros are allowed:
" + "{date} - date in format yyyymmdd
" + "{puck} - puck name
" + "{pos} - pin position in puck
" + "{sample} - sample name
" + "{sample_id} - sample id") + grid_layout.addWidget(self.file_prefix_edit, 3, 1) grid_layout.addWidget(QLabel("Run number", parent=self), 4, 0) @@ -72,6 +85,8 @@ class FilePathPanel(QWidget): file_prefix = self.file_prefix_edit.text() run_number = self.run_number_edit.value() + dir_name = dir_name.replace('{prefix}', file_prefix) + if dir_name == "": self.__filename = "" elif dir_name[-1] == "/": @@ -120,22 +135,21 @@ class FilePathPanel(QWidget): def filename(self) -> str: return self.__filename - @Slot(DAQStatusModel) - def update_daq_status(self, status: DAQStatusModel): - if status.sample is None: + @Slot(SampleShortInfo) + def update_sample(self, sample: SampleShortInfo): + if sample is None: self.__sample_id = -1 self.__sample_name = "sample" self.__dewar_pos = "None" self.__puck_name = "Manual" self.__puck_pos = 99 else: - self.__sample_name = status.sample.sample_name - self.__dewar_pos = status.sample.loc_str() - self.__puck_name = status.sample.puck_name - self.__puck_pos = status.sample.pin - self.update_filename() + self.__sample_name = sample.sample_name + self.__dewar_pos = sample.loc_str() + self.__puck_name = sample.puck_name + self.__puck_pos = sample.pin + self.run_number_edit.setValue(1) + if sample.aaredb_params is not None and sample.aaredb_params.directory is not None: + self.directory_edit.setText(sample.aaredb_params.directory) - sample_id_old = self.__sample_id - self.__sample_id = status.sample.db_id - if self.__sample_id != sample_id_old: - self.run_number_edit.setValue(1) \ No newline at end of file + self.update_filename() diff --git a/gui/src/aaregui/scan_logic/sample_mount_logic.py b/gui/src/aaregui/scan_logic/sample_mount_logic.py new file mode 100644 index 00000000..03ecaa88 --- /dev/null +++ b/gui/src/aaregui/scan_logic/sample_mount_logic.py @@ -0,0 +1,18 @@ +from PySide6.QtCore import QObject, Slot, Signal + +from aaredaqlib.models import DAQStatusModel, SampleShortInfo + + +class SampleMountLogic(QObject): + sample_changed = Signal(SampleShortInfo) + + def __init__(self, parent=None): + super().__init__(parent) + self.__sample = None + + @Slot(DAQStatusModel) + def update_daq_status(self, s: DAQStatusModel): + if s.sample != self.__sample: + self.sample_changed.emit(s.sample) + + self.__sample = s.sample