GUI: Manual sample panel (WIP)

This commit is contained in:
2025-06-29 11:10:50 +02:00
parent b1c4feaee2
commit 043a5eef45
6 changed files with 152 additions and 21 deletions
+12
View File
@@ -177,6 +177,11 @@ class AareDAQ:
raise
def create_sample(self, target: SampleShortInfo):
curr_sample = self.__cfg.current_sample
if curr_sample is not None and curr_sample.location is not None:
raise Exception("Sample from TELL is loaded")
self.__aare.create_manual_sample(target)
self.__cfg.current_sample = target
@@ -839,3 +844,10 @@ class AareDAQ:
if self.__cfg.state == BeamlineStateEnum.DataCollection:
self.__devs.aerotech.stop()
self.__jfjoch.cancel()
def anneal(self, time_s: float):
self.__cfg.set_busy(BeamlineStateEnum.SampleAlignment)
try:
self.__devs.anneal(time_s)
finally:
self.__cfg.state_busy = False
+9 -1
View File
@@ -1,3 +1,5 @@
import time
from epics import PV
from aaredaqlib.beamline import MXBeamline
@@ -47,6 +49,7 @@ class BeamlineDevices:
self.bsy = MyMotor(f"{BEAMLINE}-ES-BS:TRY1")
self.__bpm = PV(f"{BEAMLINE}-OP-XBPM1:SumAll:MeanValue_RBV")
self.__anneal = PV(f"{BEAMLINE}-ES-ANN:SET_POS")
self.aerotech = aerotech.Abr(beamline)
@@ -339,4 +342,9 @@ class BeamlineDevices:
# 2 nA -> 4e11 ph/s
if self.transmission.get() is None:
return 0.0
return self.transmission.get() * self.__bpm.value / 2.0 * 4e11
return self.transmission.get() * self.__bpm.value / 2.0 * 4e11
def anneal(self, value: float):
self.__anneal.put(1)
time.sleep(value)
self.__anneal.put(0)
+6
View File
@@ -98,6 +98,12 @@ async def save_abr_meas_pos(token: str = Depends(oauth2_scheme)):
daq.save_abr_meas_pos()
return "OK"
@app.post("/beamline/anneal")
async def anneal(time_s: float, token: str = Depends(oauth2_scheme)):
auth.check_jwt_rw(cfg, auth.parse_token(token))
daq.anneal(time_s)
return "OK"
@app.post("/beamline/goto_abr_meas_pos")
async def goto_abr_meas_pos(token: str = Depends(oauth2_scheme)):
auth.check_jwt_rw(cfg, auth.parse_token(token))
+18
View File
@@ -18,6 +18,7 @@ from aaredaqlib.sample_geometry import SampleGeometryModel
from aaregui.panels.beamline_controls import BeamlineControls
from aaregui.panels.data_collection_settings import DataCollectionSettings
from aaregui.panels.manual_sample_panel import ManualSamplePanel
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
@@ -121,6 +122,13 @@ class MainWindow(QMainWindow):
self.job_list_dock.setAllowedAreas(Qt.DockWidgetArea.BottomDockWidgetArea)
self.addDockWidget(Qt.DockWidgetArea.BottomDockWidgetArea, self.job_list_dock)
self.manual_sample_panel = ManualSamplePanel()
self.manual_sample_dock = QDockWidget("Manual sample", self)
self.manual_sample_dock.setWidget(self.manual_sample_panel)
self.manual_sample_dock.setAllowedAreas(Qt.DockWidgetArea.BottomDockWidgetArea)
self.addDockWidget(Qt.DockWidgetArea.BottomDockWidgetArea, self.manual_sample_dock)
self.setCentralWidget(top_widget)
self.setWindowTitle("AareGUI")
@@ -228,11 +236,14 @@ class MainWindow(QMainWindow):
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)
self.daq.update.connect(self.manual_sample_panel.update_daq_status)
self.daq.standard_scan_completed.connect(self.rotation.scan_completed)
self.daq.automated_scan_done.connect(self.job_list_panel.automated_scan_done)
self.daq.raster_scan_completed.connect(self.raster.grid_scan_completed)
self.manual_sample_panel.sample_manual.connect(self.daq.sample_manual)
def create_menu_bar(self):
"""Create a menu bar with File->Quit and Help->About."""
# Main menu bar
@@ -262,6 +273,13 @@ class MainWindow(QMainWindow):
show_job_list_action.triggered.connect(lambda: self.job_list_dock.setVisible(show_job_list_action.isChecked()))
view_menu.addAction(show_job_list_action)
show_manual_sample_action = QAction("Show manual sample", self)
show_manual_sample_action.setCheckable(True)
show_manual_sample_action.setChecked(True)
show_manual_sample_action.triggered.connect(self.manual_sample_dock.setVisible)
# When dock visibility changes, update the action's checked state
show_manual_sample_action.triggered.connect(lambda: self.manual_sample_dock.setVisible(show_job_list_action.isChecked()))
view_menu.addAction(show_manual_sample_action)
# Help menu
help_menu = menu_bar.addMenu("Help")
about_action = QAction("About", self) # Action for 'About'
+99 -17
View File
@@ -1,41 +1,123 @@
from PySide6.QtCore import Signal, Slot
from PySide6.QtWidgets import QWidget, QGridLayout, QLabel, QTextEdit, QPushButton
from PySide6.QtWidgets import QWidget, QGridLayout, QLabel, QTextEdit, QPushButton, QCheckBox, QLineEdit
from aareDBclient import DataCollectionParameters
from aaredaqlib.models import SampleShortInfo
from aaredaqlib.models import SampleShortInfo, DAQStatusModel
from aaregui.widgets.number_line_edit import NumberLineEdit
from aaregui.widgets.title_label import TitleLabel
class OmegaPanel(QWidget):
class ManualSamplePanel(QWidget):
sample_manual = Signal(SampleShortInfo)
sample_clear = Signal()
def __init__(self, parent=None):
super().__init__(parent)
self.__sample = SampleShortInfo(
db_id = -1,
puck_name="",
dewar_name="",
sample_name="Manual",
pin=0
)
self.__sample_name = "Lyso"
self.__pgroup = "p16371"
grid_layout = QGridLayout(self)
grid_layout.addWidget(TitleLabel("Manual sample", self), 0, 0, 1, 2)
grid_layout.addWidget(TitleLabel("Manual sample", self), 0, 0, 1, 3)
grid_layout.addWidget(QLabel("Name"), 1, 0)
self._text_name = QTextEdit(self.__sample.sample_name)
grid_layout.addWidget(QLabel("Sample"), 1, 0)
self._text_name = QLineEdit(self.__sample_name)
grid_layout.addWidget(self._text_name, 1, 1)
self._text_name.textChanged.connect(self._name_changed)
self._text_name.setStyleSheet("background-color: rgb(255, 255, 255);")
# Unit cell parameters
self._unit_cell = QCheckBox("Provide unit cell")
grid_layout.addWidget(self._unit_cell, 2, 1)
# a, b, c parameters (in Ångströms)
grid_layout.addWidget(QLabel("a"), 3, 0)
self._text_a = NumberLineEdit(5, 1000, 39, parent=self)
grid_layout.addWidget(self._text_a, 3, 1)
grid_layout.addWidget(QLabel("Å"), 3, 2)
grid_layout.addWidget(QLabel("b"), 4, 0)
self._text_b = NumberLineEdit(5, 1000, 78, parent=self)
grid_layout.addWidget(self._text_b, 4, 1)
grid_layout.addWidget(QLabel("Å"), 4, 2)
grid_layout.addWidget(QLabel("c"), 5, 0)
self._text_c = NumberLineEdit(5, 1000, 78, parent=self)
grid_layout.addWidget(self._text_c, 5, 1)
grid_layout.addWidget(QLabel("Å"), 5, 2)
# alpha, beta, gamma parameters (in degrees)
grid_layout.addWidget(QLabel("α"), 6, 0)
self._text_alpha = NumberLineEdit(30, 330, 90, parent=self)
grid_layout.addWidget(self._text_alpha, 6, 1)
grid_layout.addWidget(QLabel("°"), 6, 2)
grid_layout.addWidget(QLabel("β"), 7, 0)
self._text_beta = NumberLineEdit(30, 330, 90, parent=self)
grid_layout.addWidget(self._text_beta, 7, 1)
grid_layout.addWidget(QLabel("°"), 7, 2)
grid_layout.addWidget(QLabel("γ"), 8, 0)
self._text_gamma = NumberLineEdit(30, 330, 90, parent=self)
grid_layout.addWidget(self._text_gamma, 8, 1)
grid_layout.addWidget(QLabel("°"), 8, 2)
grid_layout.addWidget(QLabel("SG"), 9, 0)
self._text_sg = NumberLineEdit(1, 250, 1, 0, parent=self)
grid_layout.addWidget(self._text_sg, 9, 1)
self._add_button = QPushButton("Add")
grid_layout.addWidget(self._add_button, 2, 0, 1 ,2)
grid_layout.addWidget(self._add_button, 10, 0, 1, 3)
self._add_button.clicked.connect(self._add_clicked)
self._unit_cell.toggled.connect(self._unit_cell_toggled)
self._unit_cell_toggled(False)
@Slot(bool)
def _unit_cell_toggled(self, checked: bool):
if checked:
self._text_a.setEnabled(True)
self._text_b.setEnabled(True)
self._text_c.setEnabled(True)
self._text_alpha.setEnabled(True)
self._text_beta.setEnabled(True)
self._text_gamma.setEnabled(True)
self._text_sg.setEnabled(True)
else:
self._text_a.setEnabled(False)
self._text_b.setEnabled(False)
self._text_c.setEnabled(False)
self._text_alpha.setEnabled(False)
self._text_beta.setEnabled(False)
self._text_gamma.setEnabled(False)
self._text_sg.setEnabled(False)
@Slot(str)
def _name_vhanged(self, s: str):
self.__sample.sample_name = s
def _name_changed(self, s: str):
self.__sample_name = s
@Slot()
def _add_clicked(self):
self.sample_manual.emit(self.__sample)
data_processing = None
if self._unit_cell.isChecked():
data_processing = DataCollectionParameters(
spacegroupnumber=int(self._text_sg.value),
cellparameters=f"{self._text_a.value:.2f} {self._text_b.value:.2f} {self._text_c.value:.2f} {self._text_alpha.value:.2f} {self._text_beta.value:.2f} {self._text_gamma.value:.2f}"
)
s = SampleShortInfo(
db_id=-1,
puck_name="",
dewar_name="",
sample_name=self.__sample_name,
pin=1,
aaredb_params=data_processing,
user=self.__pgroup,
)
self.sample_manual.emit(s)
@Slot(DAQStatusModel)
def update_daq_status(self, s: DAQStatusModel):
self.__pgroup = s.session.current_pgroup
+8 -3
View File
@@ -111,9 +111,14 @@ class TellSamplePanel(QFrame):
self.table_model.updateCurrentSample(current_puck=None, current_sample=None)
else:
try:
self.curr_sample_label.setText(
f"Current sample: <b>{sample.sample_name} ({sample.location.segment}{sample.location.pos}-{sample.pin})</b>"
)
if sample.location is None:
self.curr_sample_label.setText(
f"Current sample: <b>{sample.sample_name} (Manual mount)</b>"
)
else:
self.curr_sample_label.setText(
f"Current sample: <b>{sample.sample_name} ({sample.location.segment}{sample.location.pos}-{sample.pin})</b>"
)
self.table_model.updateCurrentSample(
current_puck=sample.puck_name, current_sample=sample.db_id
)