diff --git a/daq/src/aaredaq/daq.py b/daq/src/aaredaq/daq.py index 26f6bf5f..bef9ec82 100644 --- a/daq/src/aaredaq/daq.py +++ b/daq/src/aaredaq/daq.py @@ -704,6 +704,9 @@ class AareDAQ: self.__cfg.state_busy = False raise e + def close_shutter(self): + self.__devs.shutter = False + @property def beamline_status(self) -> BeamlineStatus: return BeamlineStatus( diff --git a/daq/src/aaredaq/server.py b/daq/src/aaredaq/server.py index 7be3b63a..f5830e2e 100644 --- a/daq/src/aaredaq/server.py +++ b/daq/src/aaredaq/server.py @@ -109,6 +109,12 @@ async def clear_beam_center(token: str = Depends(oauth2_scheme)): daq.clear_mark_beam() return "OK" +@app.post("/shutter/close") +async def close_shutter(token: str = Depends(oauth2_scheme)): + auth.check_jwt_rw(cfg, auth.parse_token(token)) + daq.close_shutter() + return "OK" + async def get_image(token: str = Depends(oauth2_scheme)): auth.check_jwt_ro(cfg, auth.parse_token(token)) diff --git a/gui/src/aaregui/main_window.py b/gui/src/aaregui/main_window.py index f36827b3..e5822574 100644 --- a/gui/src/aaregui/main_window.py +++ b/gui/src/aaregui/main_window.py @@ -166,6 +166,7 @@ class MainWindow(QMainWindow): self.status_bar.dewar_exchange.connect(self.daq.dewar_exchange) self.status_bar.sample_exchange.connect(self.daq.sample_exchange) self.status_bar.sample_alignment.connect(self.daq.sample_alignment) + self.status_bar.close_shutter.connect(self.daq.close_shutter) def create_menu_bar(self): """Create a menu bar with File->Quit and Help->About.""" diff --git a/gui/src/aaregui/panels/helical_scan_panel.py b/gui/src/aaregui/panels/helical_scan_panel.py index 735d3f35..4b470689 100644 --- a/gui/src/aaregui/panels/helical_scan_panel.py +++ b/gui/src/aaregui/panels/helical_scan_panel.py @@ -38,53 +38,53 @@ class HelicalDataCollectionPanel(QWidget): self.high_res_enter = NumberLineEdit( 0.5, 10, decimals=2, default=2.0, parent=self ) - grid_layout.addWidget(self.high_res_enter, 0, 1, 1, 3) - grid_layout.addWidget(QLabel("Å", parent=self), 0, 4) + grid_layout.addWidget(self.high_res_enter, 0, 1) + grid_layout.addWidget(QLabel("Å", parent=self), 0, 2) + grid_layout.addWidget(QLabel("Detector distance", parent=self), 1, 0) self.dtz_enter = NumberLineEdit(60, 1000, decimals=2, default=120, parent=self) - grid_layout.addWidget(self.dtz_enter, 1, 1, 1, 3) - grid_layout.addWidget(QLabel("mm", parent=self), 1, 4) + grid_layout.addWidget(self.dtz_enter, 1, 1) + grid_layout.addWidget(QLabel("mm", parent=self), 1, 2) grid_layout.addWidget(QLabel("Beam transmission", parent=self), 2, 0) self.transmission_enter = NumberLineEdit( 0, 1.0, decimals=4, default=1.0, parent=self ) - grid_layout.addWidget(self.transmission_enter, 2, 1, 1, 3) + grid_layout.addWidget(self.transmission_enter, 2, 1) - - start_button = QPushButton("Save start point", parent=self) - start_button.clicked.connect(self.set_start_point_curr) - grid_layout.addWidget(start_button, 3, 0, 1, 3) - - end_button = QPushButton("Save end point", parent=self) - end_button.clicked.connect(self.set_end_point_curr) - grid_layout.addWidget(end_button, 4, 0, 1, 3) - - grid_layout.addWidget(QLabel("Start angle", parent=self), 5, 0) + grid_layout.addWidget(QLabel("Start angle", parent=self), 3, 0) self.start_angle = NumberLineEdit(-720, 719.0, 0, decimals=3, parent=self) - grid_layout.addWidget(self.start_angle, 5, 1) - grid_layout.addWidget(QLabel("°", parent=self), 5, 2) + grid_layout.addWidget(self.start_angle, 3, 1) + grid_layout.addWidget(QLabel("°", parent=self), 3, 2) - grid_layout.addWidget(QLabel("Total angle", parent=self), 6, 0) + grid_layout.addWidget(QLabel("Total angle", parent=self), 4, 0) self.total_angle = NumberLineEdit( 0, 999.0, self.__total_angle, decimals=3, parent=self ) - grid_layout.addWidget(self.total_angle, 6, 1) - grid_layout.addWidget(QLabel("°", parent=self), 6, 2) + grid_layout.addWidget(self.total_angle, 4, 1) + grid_layout.addWidget(QLabel("°", parent=self), 4, 2) - grid_layout.addWidget(QLabel("Image angle", parent=self), 7, 0) + grid_layout.addWidget(QLabel("Image angle", parent=self), 5, 0) self.image_angle = NumberLineEdit( 0, 10.0, self.__image_angle, decimals=3, parent=self ) - grid_layout.addWidget(self.image_angle, 7, 1) - grid_layout.addWidget(QLabel("°", parent=self), 7, 2) + grid_layout.addWidget(self.image_angle, 5, 1) + grid_layout.addWidget(QLabel("°", parent=self), 5, 2) - grid_layout.addWidget(QLabel("Image time", parent=self), 8, 0) + grid_layout.addWidget(QLabel("Image time", parent=self), 6, 0) self.image_time_enter = NumberLineEdit( 0.0005, 10.0, self.__image_time, decimals=4, parent=self ) - grid_layout.addWidget(self.image_time_enter, 8, 1) - grid_layout.addWidget(QLabel("s", parent=self), 8, 2) + grid_layout.addWidget(self.image_time_enter, 6, 1) + grid_layout.addWidget(QLabel("s", parent=self), 6, 2) + + start_button = QPushButton("Save start point", parent=self) + start_button.clicked.connect(self.set_start_point_curr) + grid_layout.addWidget(start_button, 7, 0, 1, 3) + + end_button = QPushButton("Save end point", parent=self) + end_button.clicked.connect(self.set_end_point_curr) + grid_layout.addWidget(end_button, 8, 0, 1, 3) horizontal_spacer = QSpacerItem( 40, 20, QSizePolicy.Policy.Minimum, QSizePolicy.Policy.Expanding diff --git a/gui/src/aaregui/threads/daq_worker.py b/gui/src/aaregui/threads/daq_worker.py index 18ffa0d0..592a4a26 100644 --- a/gui/src/aaregui/threads/daq_worker.py +++ b/gui/src/aaregui/threads/daq_worker.py @@ -116,6 +116,10 @@ class DAQWorker(QObject): def light(self, v: int): self.generic_put(f"beamline/light?val={v:d}") + @Slot() + def close_shutter(self): + self.generic_post("shutter/close") + @Slot() def alc_background(self): self.generic_post("alc/background") diff --git a/gui/src/aaregui/widgets/status_bar.py b/gui/src/aaregui/widgets/status_bar.py index ffefaa34..cbfd9dee 100644 --- a/gui/src/aaregui/widgets/status_bar.py +++ b/gui/src/aaregui/widgets/status_bar.py @@ -1,5 +1,5 @@ from PySide6.QtCore import Signal, Slot, QPoint -from PySide6.QtWidgets import QStatusBar, QDialog, QMenu +from PySide6.QtWidgets import QStatusBar, QDialog, QMenu, QLabel from aaredaqlib.models import TokenData, BeamlineStateEnum, DAQStatusModel, SessionsStateEnum from aaregui.widgets.clickable_label import ClickableLabel @@ -14,6 +14,7 @@ class StatusBar(QStatusBar): force_session = Signal() end_session = Signal() + close_shutter = Signal() def __init__(self, token: TokenData, parent=None): super().__init__(parent) @@ -30,6 +31,11 @@ class StatusBar(QStatusBar): self.session_label = ClickableLabel(parent=self) self.session_label.clicked.connect(self.show_session_menu) + self.shutter_label = ClickableLabel(parent=self) + self.shutter_label.clicked.connect(self.show_shutter_menu) + + self.addPermanentWidget(self.shutter_label) + self.addPermanentWidget(self.pgroup_label) self.addPermanentWidget(self.pgroup_label) self.addPermanentWidget(self.state_label) self.addPermanentWidget(self.busy_label) @@ -38,6 +44,11 @@ class StatusBar(QStatusBar): @Slot(DAQStatusModel) def update_daq_status(self, status: DAQStatusModel): + if status.bl.shutter_open: + self.shutter_label.setText(f"""Shutter: Open ⬤ """) + else: + self.shutter_label.setText(f"""Shutter: Closed ⬤ """) + if status.session.current_pgroup is not None: self.pgroup_label.setText(f"""p-group: {status.session.current_pgroup} """) else: @@ -111,6 +122,17 @@ class StatusBar(QStatusBar): menu.exec() + def show_shutter_menu(self): + menu = QMenu(self) + action_1 = menu.addAction("Close shutter") + action_1.triggered.connect(self.close_shutter_clicked) + + label_geometry = self.shutter_label.geometry() + menu.move(self.mapToGlobal(label_geometry.topLeft()) - QPoint(0, menu.sizeHint().height())) + menu.setFixedWidth(label_geometry.width()) + + menu.exec() + def show_state_menu(self): menu = QMenu(self) @@ -142,6 +164,9 @@ class StatusBar(QStatusBar): def dl(self): self.dewar_exchange.emit() + def close_shutter_clicked(self): + self.close_shutter.emit() + def show_change_dialog(self): dialog = PGroupDialog() if dialog.exec() == QDialog.DialogCode.Accepted: