style: compact the control panels
Vertical-space pass: samcam merges exposure+gain onto one row, ABR and monochromator tighten their grids (energy now displayed in keV, DAQ API stays eV), beam-mark's clear button shares the readings row, the data collection pages move Run/Abort under the last configurable row and the tab area becomes QTabBar+QStackedWidget, the raster grid table gets a fixed height, and the automation panel drops its own title since the dock title bar already says it. Control panels start expanded via default_collapsed=False. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -92,32 +92,38 @@ class AbrTweakWidget(QWidget):
|
||||
super().__init__(parent)
|
||||
|
||||
grid_layout = QGridLayout(self)
|
||||
grid_layout.setColumnStretch(0, 0)
|
||||
grid_layout.setColumnStretch(1, 0)
|
||||
grid_layout.setColumnStretch(2, 1)
|
||||
|
||||
# Span all 4 grid columns (the ABR buttons row uses 4), otherwise the
|
||||
# banner renders narrower than the neighboring panels.
|
||||
grid_layout.addWidget(TitleLabel("ABR meas. pos.", self, collapsible=True), 0, 0, 1, 4)
|
||||
grid_layout.addWidget(TitleLabel("ABR meas. pos.", self, collapsible=True, default_collapsed=False), 0, 0, 1, 2)
|
||||
|
||||
self._abr_buttons = AbrTweakButtons(DEFAULT_ABR_STEP_UM / 1000, parent=self)
|
||||
grid_layout.addWidget(self._abr_buttons, 1, 0, 1, 4)
|
||||
grid_layout.addWidget(self._abr_buttons, 1, 0)
|
||||
self._abr_buttons.abr_tweak.connect(self.abr_button_pressed)
|
||||
|
||||
grid_layout.addWidget(QLabel("Step", parent=self), 2, 0)
|
||||
self._step_um = NumberLineEdit(1, 1000, DEFAULT_ABR_STEP_UM, 0, parent=self)
|
||||
grid_layout.addWidget(self._step_um, 2, 1)
|
||||
grid_layout.addWidget(QLabel("μm", parent=self), 2, 2)
|
||||
# Step + actions as a column BESIDE the GM rows instead of below —
|
||||
# the rows left plenty of dead width.
|
||||
side = QWidget(self)
|
||||
side_grid = QGridLayout(side)
|
||||
side_grid.setContentsMargins(0, 0, 0, 0)
|
||||
side_grid.addWidget(QLabel("Step", parent=side), 0, 0)
|
||||
self._step_um = NumberLineEdit(1, 1000, DEFAULT_ABR_STEP_UM, 0, parent=side)
|
||||
side_grid.addWidget(self._step_um, 0, 1)
|
||||
side_grid.addWidget(QLabel("μm", parent=side), 0, 2)
|
||||
self._step_um.newValue.connect(self._abr_buttons.set_step)
|
||||
|
||||
save_button = QPushButton("Save ABR pos.")
|
||||
grid_layout.addWidget(save_button, 3, 0, 1, 3)
|
||||
side_grid.addWidget(save_button, 1, 0, 1, 3)
|
||||
save_button.pressed.connect(self.save_button_pressed)
|
||||
|
||||
goto_button = QPushButton("Go to meas.")
|
||||
grid_layout.addWidget(goto_button, 4, 0, 1, 3)
|
||||
side_grid.addWidget(goto_button, 2, 0, 1, 3)
|
||||
goto_button.pressed.connect(self.goto_button_pressed)
|
||||
|
||||
# ~80% of the width the grid handed it; the freed space goes to the
|
||||
# GM rows (column 0 takes all stretch).
|
||||
side.setMaximumWidth(150)
|
||||
grid_layout.setColumnStretch(0, 1)
|
||||
grid_layout.addWidget(side, 1, 1)
|
||||
|
||||
@Slot()
|
||||
def goto_button_pressed(self):
|
||||
self.abr_goto_meas.emit()
|
||||
|
||||
@@ -1,18 +1,16 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import copy
|
||||
import time
|
||||
from datetime import datetime
|
||||
|
||||
from aarecommon.config.logger import setup_logger
|
||||
from aarecommon.models.automation import AutomationProgress, StepStatus, WorkflowStateKind
|
||||
from PySide6.QtCore import QTimer, Slot
|
||||
from PySide6.QtWidgets import QLabel, QVBoxLayout, QWidget
|
||||
from PySide6.QtCore import Qt, QTimer, Slot
|
||||
from PySide6.QtWidgets import QHBoxLayout, QLabel, QVBoxLayout, QWidget
|
||||
|
||||
from aare.gui.constants import LOGGER_NAME
|
||||
from aare.gui.styles import (
|
||||
AUTOMATION_HINT_TEXT,
|
||||
AUTOMATION_TITLE_TEXT,
|
||||
CARD_BORDER,
|
||||
FAINT_TEXT,
|
||||
FONT_BODY,
|
||||
@@ -49,7 +47,6 @@ class AutomationProgressWidget(QWidget):
|
||||
self._progress: AutomationProgress | None = None
|
||||
self._gui_samples_in_queue: int | None = None
|
||||
self._labels: dict[WorkflowStateKind, QLabel] = {}
|
||||
self._title_label: QLabel | None = None
|
||||
self._stats_label: QLabel | None = None
|
||||
self._is_paused = False
|
||||
self._refresh_timer = QTimer(self)
|
||||
@@ -59,36 +56,45 @@ class AutomationProgressWidget(QWidget):
|
||||
self.clear()
|
||||
|
||||
def _setup_ui(self) -> None:
|
||||
# No title label: the dock's title bar already says it.
|
||||
layout = QVBoxLayout(self)
|
||||
layout.setContentsMargins(10, 10, 10, 10)
|
||||
layout.setSpacing(10)
|
||||
|
||||
self._title_label = QLabel("Automation progress")
|
||||
self._title_label.setStyleSheet(
|
||||
f"font-size: {FONT_TITLE}; font-weight: 700; color: {AUTOMATION_TITLE_TEXT}; margin-bottom: 2px;"
|
||||
)
|
||||
layout.addWidget(self._title_label)
|
||||
|
||||
self._stats_label = QLabel()
|
||||
self._stats_label.setStyleSheet(
|
||||
f"color: {AUTOMATION_HINT_TEXT}; font-size: {FONT_LABEL}; font-weight: 700; "
|
||||
f"background-color: {SURFACE}; border: 1px solid {CARD_BORDER}; "
|
||||
"border-radius: 8px; padding: 10px;"
|
||||
"padding: 10px;"
|
||||
)
|
||||
self._stats_label.setWordWrap(True)
|
||||
layout.addWidget(self._stats_label)
|
||||
|
||||
# Stats left, automation run-state card right ("||" paused / "▶"
|
||||
# running — ASCII bars: fancier pause glyphs are missing from the
|
||||
# beamline console fonts).
|
||||
self._state_label = QLabel()
|
||||
self._state_label.setAlignment(Qt.AlignmentFlag.AlignCenter)
|
||||
|
||||
top_row = QHBoxLayout()
|
||||
top_row.setSpacing(10)
|
||||
top_row.addWidget(self._stats_label, 2)
|
||||
top_row.addWidget(self._state_label, 1)
|
||||
layout.addLayout(top_row)
|
||||
self._update_state_label()
|
||||
|
||||
steps_row = QHBoxLayout()
|
||||
steps_row.setSpacing(6)
|
||||
for step in (
|
||||
WorkflowStateKind.MOUNT,
|
||||
WorkflowStateKind.LOOP_CENTRE,
|
||||
WorkflowStateKind.RASTER,
|
||||
WorkflowStateKind.DATA_COLLECTION,
|
||||
WorkflowStateKind.FINAL,
|
||||
):
|
||||
label = QLabel()
|
||||
label.setWordWrap(True)
|
||||
layout.addWidget(label)
|
||||
steps_row.addWidget(label, 1)
|
||||
self._labels[step] = label
|
||||
layout.addLayout(steps_row)
|
||||
|
||||
layout.addStretch()
|
||||
|
||||
@@ -142,7 +148,7 @@ class AutomationProgressWidget(QWidget):
|
||||
@staticmethod
|
||||
def _style_for_status(status: StepStatus) -> str:
|
||||
base = (
|
||||
"padding: 10px 12px; border-radius: 10px; "
|
||||
"padding: 10px 12px; "
|
||||
f"font-size: {FONT_BODY}; border: 1px solid transparent;"
|
||||
)
|
||||
|
||||
@@ -219,32 +225,38 @@ class AutomationProgressWidget(QWidget):
|
||||
return
|
||||
self.set_progress(self._progress)
|
||||
|
||||
def _update_state_label(self) -> None:
|
||||
if self._is_paused:
|
||||
colors = (
|
||||
f"background-color: {STEP_PAUSED_BG}; color: {STEP_PAUSED_TEXT}; "
|
||||
f"border: 1px solid {STEP_PAUSED_BORDER};"
|
||||
)
|
||||
text = "|| paused"
|
||||
else:
|
||||
colors = (
|
||||
f"background-color: {STEP_ACTIVE_BG}; color: {STEP_ACTIVE_TEXT}; "
|
||||
f"border: 1px solid {STEP_ACTIVE_BORDER};"
|
||||
)
|
||||
text = "▶ running"
|
||||
self._state_label.setText(text)
|
||||
self._state_label.setStyleSheet(
|
||||
f"font-size: {FONT_TITLE}; font-weight: 700; padding: 10px; " + colors
|
||||
)
|
||||
|
||||
@Slot(bool)
|
||||
def set_running(self, running: bool) -> None:
|
||||
self._is_paused = not running
|
||||
self._update_state_label()
|
||||
|
||||
if self._progress is None:
|
||||
return
|
||||
|
||||
progress = copy.deepcopy(self._progress)
|
||||
|
||||
final_step = next(
|
||||
(step for step in progress.steps if step.step == WorkflowStateKind.FINAL), None
|
||||
)
|
||||
|
||||
if self._is_paused:
|
||||
self._refresh_timer.stop()
|
||||
if final_step is not None:
|
||||
final_step.status = StepStatus.PAUSED
|
||||
final_step.message = "Automation paused"
|
||||
else:
|
||||
if final_step is not None and final_step.status == StepStatus.PAUSED:
|
||||
final_step.status = StepStatus.PENDING
|
||||
final_step.message = ""
|
||||
if self._has_live_timing(progress):
|
||||
self._refresh_timer.start()
|
||||
elif self._has_live_timing(self._progress):
|
||||
self._refresh_timer.start()
|
||||
|
||||
self.set_progress(progress)
|
||||
self.set_progress(self._progress)
|
||||
|
||||
@Slot(int)
|
||||
def set_samples_in_queue(self, count: int) -> None:
|
||||
@@ -318,5 +330,3 @@ class AutomationProgressWidget(QWidget):
|
||||
label.setText(f"{icon} <b>{title}</b>{duration_str}{message}{error_str}")
|
||||
label.setStyleSheet(self._style_for_status(step_state.status))
|
||||
|
||||
if self._title_label is not None:
|
||||
self._title_label.setText("Automation progress")
|
||||
|
||||
@@ -12,8 +12,9 @@ class BeamMarkWidget(QWidget):
|
||||
super().__init__(parent)
|
||||
|
||||
grid_layout = QGridLayout(self)
|
||||
grid_layout.setVerticalSpacing(2)
|
||||
|
||||
grid_layout.addWidget(section_title("Beam mark (image)", self), 0, 0, 1, 5)
|
||||
grid_layout.addWidget(section_title("Beam mark (image)", self), 0, 0, 1, 6)
|
||||
|
||||
self.x = QLabel("0")
|
||||
self.y = QLabel("0")
|
||||
@@ -24,8 +25,10 @@ class BeamMarkWidget(QWidget):
|
||||
grid_layout.addWidget(self.y, 1, 3)
|
||||
grid_layout.addWidget(QLabel("pxl"), 1, 4)
|
||||
|
||||
# Shares the readings row instead of a full-width row below.
|
||||
clear_button = QPushButton("Clear marks")
|
||||
grid_layout.addWidget(clear_button, 2, 0, 1, 5)
|
||||
clear_button.setFixedWidth(90)
|
||||
grid_layout.addWidget(clear_button, 1, 5)
|
||||
clear_button.pressed.connect(self.clear_button_pressed)
|
||||
|
||||
@Slot()
|
||||
|
||||
@@ -2,7 +2,16 @@ from aarecommon.math.diffraction_geometry import DiffractionGeometry
|
||||
from aarecommon.math.sample_geometry import SampleGeometryModel
|
||||
from aarecommon.models.models import DAQStatusModel
|
||||
from PySide6.QtCore import Signal, Slot
|
||||
from PySide6.QtWidgets import QFrame, QPushButton, QTabWidget, QVBoxLayout, QWidget
|
||||
from PySide6.QtWidgets import (
|
||||
QFrame,
|
||||
QHBoxLayout,
|
||||
QPushButton,
|
||||
QSizePolicy,
|
||||
QStackedWidget,
|
||||
QTabBar,
|
||||
QVBoxLayout,
|
||||
QWidget,
|
||||
)
|
||||
|
||||
from aare.gui.panels.file_path_panel import FilePathPanel
|
||||
from aare.gui.panels.fluorescence_data_collection import FluorescenceDataCollectionPanel
|
||||
@@ -11,7 +20,6 @@ from aare.gui.panels.raster_data_collection import RasterDataCollectionPanel
|
||||
from aare.gui.panels.rotation_data_collection import RotationDataCollectionPanel
|
||||
from aare.gui.panels.smart_rotation_panel import SimpleRotationSettingsPanel
|
||||
from aare.gui.scan_logic.raster_grid_manager import RasterGridManager
|
||||
from aare.gui.styles import ABORT_TEXT
|
||||
from aare.gui.widgets.title_label import TitleLabel, tighten_column
|
||||
|
||||
|
||||
@@ -42,39 +50,72 @@ class DataCollectionSettings(QFrame):
|
||||
self.manual_sample_panel = ManualSamplePanel(self)
|
||||
v_layout.addWidget(self.manual_sample_panel)
|
||||
|
||||
self._tab_widget = QTabWidget()
|
||||
# QTabBar + QStackedWidget instead of QTabWidget: the loop-centering
|
||||
# button row must sit BETWEEN the tab bar and the pages, which a
|
||||
# QTabWidget cannot host.
|
||||
self._tab_bar = QTabBar(self)
|
||||
self._stack = QStackedWidget(self)
|
||||
|
||||
self.raster = RasterDataCollectionPanel(
|
||||
parent=self, raster_mgr=raster_mgr, diffraction=diffraction
|
||||
)
|
||||
self._tab_widget.addTab(self.raster, "Raster scan")
|
||||
|
||||
self.screening = RotationDataCollectionPanel(parent=self, diffraction=diffraction)
|
||||
self._tab_widget.addTab(self.screening, "Rotation")
|
||||
|
||||
self.simple = SimpleRotationSettingsPanel(parent=self)
|
||||
self._tab_widget.addTab(self.simple, "Simple")
|
||||
|
||||
self.fluo = FluorescenceDataCollectionPanel(parent=self)
|
||||
self._tab_widget.addTab(self.fluo, "XRF")
|
||||
for panel, label in (
|
||||
(self.raster, "Raster scan"),
|
||||
(self.screening, "Rotation"),
|
||||
(self.simple, "Simple"),
|
||||
(self.fluo, "XRF"),
|
||||
):
|
||||
self._stack.addWidget(panel)
|
||||
self._tab_bar.addTab(label)
|
||||
|
||||
# Ex-"Loop centering" panel buttons; always visible, whatever the tab.
|
||||
self.find_tip = QPushButton("ML Loop Centring", parent=self)
|
||||
self.bounding_box = QPushButton("Make Raster Grid", parent=self)
|
||||
centering_row = QWidget(self)
|
||||
centering_layout = QHBoxLayout(centering_row)
|
||||
centering_layout.setContentsMargins(0, 0, 0, 0)
|
||||
centering_layout.addWidget(self.find_tip)
|
||||
centering_layout.addWidget(self.bounding_box)
|
||||
|
||||
# Pane frame carries the border QTabWidget::pane used to draw
|
||||
# (#expConfigPane rule in styles.py).
|
||||
pane = QFrame(self)
|
||||
pane.setObjectName("expConfigPane")
|
||||
pane_layout = QVBoxLayout(pane)
|
||||
# No bottom padding: the pages' own bottom margins breathe inside the
|
||||
# border, and the Abort button should hug the pane.
|
||||
pane_layout.setContentsMargins(6, 6, 6, 0)
|
||||
pane_layout.addWidget(centering_row)
|
||||
pane_layout.addWidget(self._stack)
|
||||
|
||||
# Own container: TitleLabel collapse hides its siblings, so without it
|
||||
# "Exp. Config." would also swallow the dataset path and abort button.
|
||||
exp_config = QWidget(self)
|
||||
exp_config_layout = QVBoxLayout(exp_config)
|
||||
exp_config_layout.setContentsMargins(0, 0, 0, 0)
|
||||
exp_config_layout.addWidget(TitleLabel("Exp. Config.", exp_config, collapsible=True))
|
||||
exp_config_layout.addWidget(self._tab_widget)
|
||||
exp_config_layout.setSpacing(0) # tab bar flush on the pane, like QTabWidget
|
||||
exp_config_layout.addWidget(
|
||||
TitleLabel(
|
||||
"Experiment configuration", exp_config, collapsible=True, default_collapsed=False
|
||||
)
|
||||
)
|
||||
exp_config_layout.addWidget(self._tab_bar)
|
||||
exp_config_layout.addWidget(pane)
|
||||
v_layout.addWidget(exp_config)
|
||||
|
||||
abort_button = QPushButton("Abort measurement", parent=self)
|
||||
abort_button.setStyleSheet(f"color: {ABORT_TEXT};")
|
||||
abort_button.clicked.connect(self.cancel_button_clicked)
|
||||
v_layout.addWidget(abort_button)
|
||||
# Stretch after the button: abort sits snug under the tabs instead of
|
||||
# being pinned to the bottom of the fixed-height column.
|
||||
# Abort lives inside each tab now, under that tab's action buttons;
|
||||
# all four feed the same cancel signal.
|
||||
for panel in (self.raster, self.screening, self.simple, self.fluo):
|
||||
panel.abort_button.clicked.connect(self.cancel_button_clicked)
|
||||
v_layout.addStretch()
|
||||
tighten_column(v_layout)
|
||||
# Abort hugs the pane: undo the uniform bottom margin tighten_column
|
||||
# just gave the Exp. Config. group.
|
||||
m = exp_config_layout.contentsMargins()
|
||||
exp_config_layout.setContentsMargins(m.left(), m.top(), m.right(), 0)
|
||||
|
||||
raster_mgr.update_filename(self.file_path_panel.filename)
|
||||
self.screening.update_filename(self.file_path_panel.filename)
|
||||
@@ -86,11 +127,27 @@ class DataCollectionSettings(QFrame):
|
||||
self.file_path_panel.path_updated.connect(self.simple.update_filename)
|
||||
self._sample_id = None
|
||||
|
||||
self._tab_widget.currentChanged.connect(self._on_tab_changed)
|
||||
self._tab_bar.currentChanged.connect(self._stack.setCurrentIndex)
|
||||
self._tab_bar.currentChanged.connect(self._on_tab_changed)
|
||||
self._tab_bar.currentChanged.connect(self._sync_stack_height)
|
||||
self._sync_stack_height(self._tab_bar.currentIndex())
|
||||
|
||||
@Slot(int)
|
||||
def _sync_stack_height(self, idx: int):
|
||||
# QStackedWidget's sizeHint is its TALLEST page, which left a dead gap
|
||||
# above the Abort button on shorter tabs. Ignored vertical policy on
|
||||
# hidden pages makes the stack track only the current page's height.
|
||||
for i in range(self._stack.count()):
|
||||
page = self._stack.widget(i)
|
||||
vertical = (
|
||||
QSizePolicy.Policy.Preferred if i == idx else QSizePolicy.Policy.Ignored
|
||||
)
|
||||
page.setSizePolicy(QSizePolicy.Policy.Preferred, vertical)
|
||||
self._stack.adjustSize()
|
||||
|
||||
@Slot()
|
||||
def switch_to_raster(self):
|
||||
self._tab_widget.setCurrentIndex(0)
|
||||
self._tab_bar.setCurrentIndex(0)
|
||||
|
||||
@Slot()
|
||||
def cancel_button_clicked(self):
|
||||
@@ -103,7 +160,7 @@ class DataCollectionSettings(QFrame):
|
||||
self.simple.update_daq_status(s)
|
||||
if s.sample is not None and s.sample.db_id != self._sample_id:
|
||||
self._sample_id = s.sample.db_id
|
||||
self._tab_widget.setCurrentIndex(0)
|
||||
self._tab_bar.setCurrentIndex(0)
|
||||
|
||||
@Slot(int)
|
||||
def _on_tab_changed(self, idx: int):
|
||||
|
||||
@@ -2,7 +2,7 @@ from aarecommon.models.models import FluorescenceSpectrumParameterModel
|
||||
from PySide6.QtCore import Signal, Slot
|
||||
from PySide6.QtWidgets import QCheckBox, QGridLayout, QLabel, QPushButton, QWidget
|
||||
|
||||
from aare.gui.styles import GO_TEXT
|
||||
from aare.gui.styles import ABORT_TEXT, GO_TEXT
|
||||
from aare.gui.widgets.number_line_edit import NumberLineEdit
|
||||
|
||||
|
||||
@@ -38,6 +38,11 @@ class FluorescenceDataCollectionPanel(QWidget):
|
||||
self.run_btn.setStyleSheet(f"color: {GO_TEXT};")
|
||||
lay.addWidget(self.run_btn, 4, 0, 1, 3)
|
||||
|
||||
# Per-tab Abort (DataCollectionSettings wires it to the DAQ cancel).
|
||||
self.abort_button = QPushButton("Abort measurement", self)
|
||||
self.abort_button.setStyleSheet(f"color: {ABORT_TEXT};")
|
||||
lay.addWidget(self.abort_button, 5, 0, 1, 3)
|
||||
|
||||
self.run_btn.clicked.connect(self._emit_params)
|
||||
|
||||
@Slot()
|
||||
|
||||
@@ -13,29 +13,31 @@ class MonochromatorPanel(QWidget):
|
||||
super().__init__(parent)
|
||||
|
||||
grid_layout = QGridLayout(self)
|
||||
grid_layout.addWidget(TitleLabel("Monochromator", self, collapsible=True), 0, 0, 1, 2)
|
||||
grid_layout.addWidget(TitleLabel("Monochromator", self, collapsible=True, default_collapsed=False), 0, 0, 1, 3)
|
||||
|
||||
self.mono_pitch_scan_button = QPushButton("Mono Pitch Scan", parent=self)
|
||||
self.mono_pitch_scan_button.clicked.connect(self.mono_pitch_scan.emit)
|
||||
grid_layout.addWidget(self.mono_pitch_scan_button, 1, 0, 1, 2)
|
||||
grid_layout.addWidget(self.mono_pitch_scan_button, 1, 0, 1, 3)
|
||||
|
||||
# One row (label | value | button) instead of three — vertical space.
|
||||
# Display in keV; the DAQ API stays in eV (converted on emit).
|
||||
grid_layout.addWidget(QLabel("Energy", parent=self), 2, 0)
|
||||
|
||||
self.energy_spin = QDoubleSpinBox(parent=self)
|
||||
self.energy_spin.setDecimals(3)
|
||||
self.energy_spin.setRange(1000.0, 30000.0)
|
||||
self.energy_spin.setSingleStep(100.0)
|
||||
self.energy_spin.setSuffix(" eV")
|
||||
self.energy_spin.setValue(12000.0)
|
||||
grid_layout.addWidget(self.energy_spin, 3, 0)
|
||||
self.energy_spin.setRange(1.0, 30.0)
|
||||
self.energy_spin.setSingleStep(0.1)
|
||||
self.energy_spin.setSuffix(" keV")
|
||||
self.energy_spin.setValue(12.0)
|
||||
grid_layout.addWidget(self.energy_spin, 2, 1)
|
||||
|
||||
self.change_energy_button = QPushButton("Change Energy", parent=self)
|
||||
self.change_energy_button.clicked.connect(self._emit_change_energy)
|
||||
grid_layout.addWidget(self.change_energy_button, 3, 1)
|
||||
grid_layout.addWidget(self.change_energy_button, 2, 2)
|
||||
|
||||
@Slot()
|
||||
def _emit_change_energy(self):
|
||||
self.change_energy.emit(float(self.energy_spin.value()))
|
||||
self.change_energy.emit(float(self.energy_spin.value()) * 1000.0)
|
||||
|
||||
@Slot(DAQStatusModel)
|
||||
def update_daq_status(self, _status: DAQStatusModel):
|
||||
|
||||
@@ -7,15 +7,13 @@ from PySide6.QtWidgets import (
|
||||
QLabel,
|
||||
QMessageBox,
|
||||
QPushButton,
|
||||
QSizePolicy,
|
||||
QSlider,
|
||||
QSpacerItem,
|
||||
)
|
||||
|
||||
from aare.gui.constants import LOGGER_NAME
|
||||
from aare.gui.panels.scan_settings_panel import ScanSettingsPanel
|
||||
from aare.gui.scan_logic.raster_grid_manager import RasterGridManager, RasterGridMetric
|
||||
from aare.gui.styles import GO_TEXT
|
||||
from aare.gui.styles import ABORT_TEXT, GO_TEXT
|
||||
from aare.gui.widgets.number_line_edit import DbOverrideLineEdit
|
||||
from aare.gui.widgets.raster_grid_table import RasterGridTable
|
||||
|
||||
@@ -131,11 +129,6 @@ class RasterDataCollectionPanel(ScanSettingsPanel):
|
||||
self._table = RasterGridTable(raster_mgr)
|
||||
self._layout.addWidget(self._table, 9, 0, 1, 5)
|
||||
|
||||
horizontal_spacer = QSpacerItem(
|
||||
40, 20, QSizePolicy.Policy.Minimum, QSizePolicy.Policy.Expanding
|
||||
)
|
||||
self._layout.addItem(horizontal_spacer, 10, 0, 1, 5)
|
||||
|
||||
self._layout.addWidget(QLabel("Measurement time", parent=self), 11, 0)
|
||||
self.total_time = QLabel(f"{self._total_time} min 0 s")
|
||||
self.total_time.setAlignment(Qt.AlignmentFlag.AlignRight | Qt.AlignmentFlag.AlignVCenter)
|
||||
@@ -152,6 +145,11 @@ class RasterDataCollectionPanel(ScanSettingsPanel):
|
||||
self.auto_button.setStyleSheet(f"color: {GO_TEXT};")
|
||||
self.auto_button.clicked.connect(self._on_evaluate_auto_clicked)
|
||||
self._layout.addWidget(self.auto_button, 13, 0, 1, 5)
|
||||
|
||||
# Per-tab Abort (DataCollectionSettings wires it to the DAQ cancel).
|
||||
self.abort_button = QPushButton("Abort measurement")
|
||||
self.abort_button.setStyleSheet(f"color: {ABORT_TEXT};")
|
||||
self._layout.addWidget(self.abort_button, 14, 0, 1, 5)
|
||||
self._reset_to_defaults()
|
||||
self.update_grid_scan_size()
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@ from PySide6.QtWidgets import QComboBox, QLabel, QMessageBox, QPushButton
|
||||
|
||||
from aare.gui.constants import LOGGER_NAME
|
||||
from aare.gui.panels.scan_settings_panel import ScanSettingsPanel
|
||||
from aare.gui.styles import GO_TEXT
|
||||
from aare.gui.styles import ABORT_TEXT, GO_TEXT
|
||||
from aare.gui.widgets.number_line_edit import DbOverrideLineEdit, NumberLineEdit
|
||||
|
||||
logger = setup_logger(LOGGER_NAME)
|
||||
@@ -164,6 +164,11 @@ class RotationDataCollectionPanel(ScanSettingsPanel):
|
||||
self.measurement_button.setStyleSheet(f"color: {GO_TEXT};")
|
||||
self.measurement_button.clicked.connect(self.run_measurement)
|
||||
self._layout.addWidget(self.measurement_button, 16, 0, 1, 6)
|
||||
|
||||
# Per-tab Abort (DataCollectionSettings wires it to the DAQ cancel).
|
||||
self.abort_button = QPushButton("Abort measurement")
|
||||
self.abort_button.setStyleSheet(f"color: {ABORT_TEXT};")
|
||||
self._layout.addWidget(self.abort_button, 17, 0, 1, 6)
|
||||
self._reset_to_defaults()
|
||||
|
||||
@Slot()
|
||||
|
||||
@@ -4,6 +4,7 @@ from PySide6.QtWidgets import (
|
||||
QCheckBox,
|
||||
QComboBox,
|
||||
QDoubleSpinBox,
|
||||
QGridLayout,
|
||||
QHBoxLayout,
|
||||
QLabel,
|
||||
QLineEdit,
|
||||
@@ -36,32 +37,28 @@ class SamcamPanel(QWidget):
|
||||
# Create layout
|
||||
layout = QVBoxLayout()
|
||||
|
||||
layout.addWidget(TitleLabel("Sample camera", self, collapsible=True))
|
||||
layout.addWidget(TitleLabel("Sample camera", self, collapsible=True, default_collapsed=False))
|
||||
|
||||
# Exposure control
|
||||
exposure_layout = QHBoxLayout()
|
||||
exposure_label = QLabel("Exposure (s):")
|
||||
# Exposure + gain share one row to save vertical space.
|
||||
exposure_gain_layout = QHBoxLayout()
|
||||
self.exposure_spinbox = QDoubleSpinBox()
|
||||
self.exposure_spinbox.setRange(0, 1.0) # Adjust range as needed
|
||||
self.exposure_spinbox.setSingleStep(0.001)
|
||||
self.exposure_spinbox.setStyleSheet(f"QDoubleSpinBox {{ background-color: {INPUT_BG}; }}")
|
||||
self.exposure_spinbox.setDecimals(3)
|
||||
|
||||
self.exposure_spinbox.valueChanged.connect(self._changed)
|
||||
exposure_layout.addWidget(exposure_label)
|
||||
exposure_layout.addWidget(self.exposure_spinbox)
|
||||
|
||||
# Gain control
|
||||
gain_layout = QHBoxLayout()
|
||||
gain_label = QLabel("Gain:")
|
||||
self.gain_spinbox = QDoubleSpinBox()
|
||||
self.gain_spinbox.setRange(0, 1000) # Adjust range as needed
|
||||
self.gain_spinbox.setSingleStep(1)
|
||||
self.gain_spinbox.setDecimals(1)
|
||||
self.gain_spinbox.setStyleSheet(f"QDoubleSpinBox {{ background-color: {INPUT_BG}; }}")
|
||||
self.gain_spinbox.valueChanged.connect(self._changed)
|
||||
gain_layout.addWidget(gain_label)
|
||||
gain_layout.addWidget(self.gain_spinbox)
|
||||
|
||||
exposure_gain_layout.addWidget(QLabel("Exposure (s):"))
|
||||
exposure_gain_layout.addWidget(self.exposure_spinbox)
|
||||
exposure_gain_layout.addWidget(QLabel("Gain:"))
|
||||
exposure_gain_layout.addWidget(self.gain_spinbox)
|
||||
|
||||
# Persist the current gain/exposure as the beam-location preset for the
|
||||
# current zoom (only meaningful in beam-location mode).
|
||||
@@ -86,56 +83,53 @@ class SamcamPanel(QWidget):
|
||||
screenshot_message_layout.addWidget(screenshot_message_label)
|
||||
screenshot_message_layout.addWidget(self.screenshot_message_edit)
|
||||
|
||||
self.screenshot_button = QPushButton("Take screenshot")
|
||||
self.screenshot_button = QPushButton("Save samcam image")
|
||||
self.screenshot_button.clicked.connect(self._request_screenshot)
|
||||
|
||||
# Show detections checkbox
|
||||
detections_layout = QHBoxLayout()
|
||||
# Overlay checkboxes, two columns to save vertical space; related
|
||||
# toggles share a row.
|
||||
self.show_detections_checkbox = QCheckBox("Show ML detections")
|
||||
self.show_detections_checkbox.setChecked(True) # Default to checked
|
||||
self.show_detections_checkbox.toggled.connect(self.show_detections_changed.emit)
|
||||
detections_layout.addWidget(self.show_detections_checkbox)
|
||||
|
||||
# Show detection polygons checkbox
|
||||
detection_polygons_layout = QHBoxLayout()
|
||||
self.show_detection_polygons_checkbox = QCheckBox("Show ML polygons")
|
||||
self.show_detection_polygons_checkbox.setChecked(True)
|
||||
self.show_detection_polygons_checkbox.toggled.connect(
|
||||
self.show_detection_polygons_changed.emit
|
||||
)
|
||||
detection_polygons_layout.addWidget(self.show_detection_polygons_checkbox)
|
||||
|
||||
# Show target point checkbox
|
||||
target_point_layout = QHBoxLayout()
|
||||
self.show_target_point_checkbox = QCheckBox("Show target point")
|
||||
self.show_target_point_checkbox.setChecked(True)
|
||||
self.show_target_point_checkbox.toggled.connect(self.show_target_point_changed.emit)
|
||||
target_point_layout.addWidget(self.show_target_point_checkbox)
|
||||
|
||||
# Show target coordinates checkbox
|
||||
target_coords_layout = QHBoxLayout()
|
||||
self.show_target_coordinates_checkbox = QCheckBox("Show target coordinates")
|
||||
self.show_target_coordinates_checkbox.setChecked(True)
|
||||
self.show_target_coordinates_checkbox.toggled.connect(
|
||||
self.show_target_coordinates_changed.emit
|
||||
)
|
||||
target_coords_layout.addWidget(self.show_target_coordinates_checkbox)
|
||||
|
||||
# Show legend checkbox
|
||||
legend_layout = QHBoxLayout()
|
||||
self.show_overlay_legend_checkbox = QCheckBox("Show overlay legend")
|
||||
self.show_overlay_legend_checkbox.setChecked(True)
|
||||
self.show_overlay_legend_checkbox.toggled.connect(self.show_overlay_legend_changed.emit)
|
||||
legend_layout.addWidget(self.show_overlay_legend_checkbox)
|
||||
|
||||
# Compact legend checkbox
|
||||
compact_legend_layout = QHBoxLayout()
|
||||
self.compact_overlay_legend_checkbox = QCheckBox("Compact legend")
|
||||
self.compact_overlay_legend_checkbox.setChecked(False)
|
||||
self.compact_overlay_legend_checkbox.toggled.connect(
|
||||
self.compact_overlay_legend_changed.emit
|
||||
)
|
||||
compact_legend_layout.addWidget(self.compact_overlay_legend_checkbox)
|
||||
|
||||
checkbox_grid = QGridLayout()
|
||||
for i, checkbox in enumerate(
|
||||
(
|
||||
self.show_detections_checkbox,
|
||||
self.show_detection_polygons_checkbox,
|
||||
self.show_target_point_checkbox,
|
||||
self.show_target_coordinates_checkbox,
|
||||
self.show_overlay_legend_checkbox,
|
||||
self.compact_overlay_legend_checkbox,
|
||||
)
|
||||
):
|
||||
checkbox_grid.addWidget(checkbox, i // 2, i % 2)
|
||||
|
||||
# Target color
|
||||
target_color_layout = QHBoxLayout()
|
||||
@@ -148,18 +142,14 @@ class SamcamPanel(QWidget):
|
||||
target_color_layout.addWidget(self.target_color_combo)
|
||||
|
||||
# Add controls to main layout
|
||||
layout.addLayout(exposure_layout)
|
||||
layout.addLayout(gain_layout)
|
||||
layout.addWidget(self.save_beam_location_button)
|
||||
layout.addLayout(exposure_gain_layout)
|
||||
samcam_buttons_layout = QHBoxLayout()
|
||||
samcam_buttons_layout.addWidget(self.save_beam_location_button)
|
||||
samcam_buttons_layout.addWidget(self.screenshot_button)
|
||||
layout.addLayout(samcam_buttons_layout)
|
||||
layout.addLayout(screenshot_filename_layout)
|
||||
layout.addLayout(screenshot_message_layout)
|
||||
layout.addWidget(self.screenshot_button)
|
||||
layout.addLayout(detections_layout)
|
||||
layout.addLayout(detection_polygons_layout)
|
||||
layout.addLayout(target_point_layout)
|
||||
layout.addLayout(target_coords_layout)
|
||||
layout.addLayout(legend_layout)
|
||||
layout.addLayout(compact_legend_layout)
|
||||
layout.addLayout(checkbox_grid)
|
||||
layout.addLayout(target_color_layout)
|
||||
self.setLayout(layout)
|
||||
|
||||
|
||||
@@ -63,10 +63,15 @@ class ScanSettingsPanel(QWidget):
|
||||
# before, so they are unaffected by the wrapping.
|
||||
outer = QVBoxLayout(self)
|
||||
outer.setContentsMargins(0, 0, 0, 0)
|
||||
outer.setSpacing(0)
|
||||
outer.addWidget(self._build_source_toggle())
|
||||
|
||||
grid_host = QWidget(self)
|
||||
self._layout = QGridLayout(grid_host)
|
||||
# Toggle-to-grid gap = one grid row gap (top). Bottom 3 + the column's
|
||||
# 3px spacing = one row gap between the last button and Abort too.
|
||||
m = self._layout.contentsMargins()
|
||||
self._layout.setContentsMargins(m.left(), 6, m.right(), 3)
|
||||
outer.addWidget(grid_host)
|
||||
|
||||
self._layout.addWidget(QLabel("High resolution", parent=self), 0, 0)
|
||||
|
||||
@@ -8,7 +8,7 @@ from PySide6.QtWidgets import QGridLayout, QLabel, QPushButton, QSizePolicy, QSp
|
||||
|
||||
from aare.gui.constants import LOGGER_NAME
|
||||
from aare.gui.panels.rotation_data_collection import add_data_to_path
|
||||
from aare.gui.styles import GO_TEXT, STATUS_ALERT
|
||||
from aare.gui.styles import ABORT_TEXT, GO_TEXT, STATUS_ALERT
|
||||
from aare.gui.widgets.number_line_edit import NumberLineEdit
|
||||
|
||||
logger = setup_logger(LOGGER_NAME)
|
||||
@@ -44,6 +44,10 @@ class SimpleRotationSettingsPanel(QWidget):
|
||||
self._prev_params = SimpleScanParameters()
|
||||
|
||||
self._layout = QGridLayout(self)
|
||||
# Top margin 0 like the Raster/Rotation pages (their toggle row sits
|
||||
# at margin 0), so the gap under the ML-centring row matches.
|
||||
m = self._layout.contentsMargins()
|
||||
self._layout.setContentsMargins(m.left(), 0, m.right(), 3)
|
||||
|
||||
# Visible resolution (entry)
|
||||
self._layout.addWidget(QLabel("Visible resolution", parent=self), 0, 0)
|
||||
@@ -83,133 +87,138 @@ class SimpleRotationSettingsPanel(QWidget):
|
||||
self._layout.addWidget(QLabel("K", parent=self), 4, 4)
|
||||
self.temp_enter.newValue.connect(self.set_temperature)
|
||||
|
||||
# Run + Abort directly under the last configurable row; the read-only
|
||||
# block below is reference info, not something to scroll past to act.
|
||||
self.run_rotation_button = QPushButton("Run rotation", parent=self)
|
||||
self.run_rotation_button.setStyleSheet(f"color: {GO_TEXT};")
|
||||
self.run_rotation_button.clicked.connect(self.run_measurement)
|
||||
self._layout.addWidget(self.run_rotation_button, 5, 0, 1, 6)
|
||||
|
||||
self.abort_button = QPushButton("Abort measurement", parent=self)
|
||||
self.abort_button.setStyleSheet(f"color: {ABORT_TEXT};")
|
||||
self._layout.addWidget(self.abort_button, 6, 0, 1, 6)
|
||||
|
||||
# Calculated labels
|
||||
self._layout.addWidget(QLabel("Target resolution", parent=self), 5, 0)
|
||||
self._layout.addWidget(QLabel("Target resolution", parent=self), 7, 0)
|
||||
self.target_res_label = QLabel("--", parent=self)
|
||||
self.target_res_label.setAlignment(
|
||||
Qt.AlignmentFlag.AlignRight | Qt.AlignmentFlag.AlignVCenter
|
||||
)
|
||||
self._layout.addWidget(self.target_res_label, 5, 1, 1, 3)
|
||||
self._layout.addWidget(QLabel("Å", parent=self), 5, 4)
|
||||
self._layout.addWidget(self.target_res_label, 7, 1, 1, 3)
|
||||
self._layout.addWidget(QLabel("Å", parent=self), 7, 4)
|
||||
|
||||
self._layout.addWidget(QLabel("Image time", parent=self), 6, 0)
|
||||
self._layout.addWidget(QLabel("Image time", parent=self), 8, 0)
|
||||
self.image_time_label = QLabel("--", parent=self)
|
||||
self.image_time_label.setAlignment(
|
||||
Qt.AlignmentFlag.AlignRight | Qt.AlignmentFlag.AlignVCenter
|
||||
)
|
||||
self._layout.addWidget(self.image_time_label, 6, 1, 1, 3)
|
||||
self._layout.addWidget(QLabel("s", parent=self), 6, 4)
|
||||
self._layout.addWidget(self.image_time_label, 8, 1, 1, 3)
|
||||
self._layout.addWidget(QLabel("s", parent=self), 8, 4)
|
||||
|
||||
self._layout.addWidget(QLabel("Transmission", parent=self), 7, 0)
|
||||
self._layout.addWidget(QLabel("Transmission", parent=self), 9, 0)
|
||||
self.transmission_label = QLabel("--", parent=self)
|
||||
self.transmission_label.setAlignment(
|
||||
Qt.AlignmentFlag.AlignRight | Qt.AlignmentFlag.AlignVCenter
|
||||
)
|
||||
self._layout.addWidget(self.transmission_label, 7, 1, 1, 3)
|
||||
self._layout.addWidget(QLabel("%", parent=self), 7, 4)
|
||||
self._layout.addWidget(self.transmission_label, 9, 1, 1, 3)
|
||||
self._layout.addWidget(QLabel("%", parent=self), 9, 4)
|
||||
|
||||
self._layout.addWidget(QLabel("Detector distance", parent=self), 8, 0)
|
||||
self._layout.addWidget(QLabel("Detector distance", parent=self), 10, 0)
|
||||
self.dtz_label = QLabel("--", parent=self)
|
||||
self.dtz_label.setAlignment(Qt.AlignmentFlag.AlignRight | Qt.AlignmentFlag.AlignVCenter)
|
||||
self._layout.addWidget(self.dtz_label, 8, 1, 1, 3)
|
||||
self._layout.addWidget(QLabel("mm", parent=self), 8, 4)
|
||||
self._layout.addWidget(self.dtz_label, 10, 1, 1, 3)
|
||||
self._layout.addWidget(QLabel("mm", parent=self), 10, 4)
|
||||
|
||||
self._layout.addWidget(QLabel("Target Dose", parent=self), 9, 0)
|
||||
self._layout.addWidget(QLabel("Target Dose", parent=self), 11, 0)
|
||||
self.target_dose_label = QLabel("--", parent=self)
|
||||
self.target_dose_label.setAlignment(
|
||||
Qt.AlignmentFlag.AlignRight | Qt.AlignmentFlag.AlignVCenter
|
||||
)
|
||||
self._layout.addWidget(self.target_dose_label, 9, 1, 1, 3)
|
||||
self._layout.addWidget(QLabel("MGy", parent=self), 9, 4)
|
||||
self._layout.addWidget(self.target_dose_label, 11, 1, 1, 3)
|
||||
self._layout.addWidget(QLabel("MGy", parent=self), 11, 4)
|
||||
|
||||
self._layout.addWidget(QLabel("Calculated Dose Rate", parent=self), 10, 0)
|
||||
self._layout.addWidget(QLabel("Calculated Dose Rate", parent=self), 12, 0)
|
||||
self.calculated_dose_rate_label = QLabel("--", parent=self)
|
||||
self.calculated_dose_rate_label.setAlignment(
|
||||
Qt.AlignmentFlag.AlignRight | Qt.AlignmentFlag.AlignVCenter
|
||||
)
|
||||
self._layout.addWidget(self.calculated_dose_rate_label, 10, 1, 1, 3)
|
||||
self._layout.addWidget(QLabel("MGy s<sup>-1</sup>", parent=self), 10, 4)
|
||||
self._layout.addWidget(self.calculated_dose_rate_label, 12, 1, 1, 3)
|
||||
self._layout.addWidget(QLabel("MGy s<sup>-1</sup>", parent=self), 12, 4)
|
||||
|
||||
self._layout.addWidget(QLabel("Wilson B Factor", parent=self), 11, 0)
|
||||
self._layout.addWidget(QLabel("Wilson B Factor", parent=self), 13, 0)
|
||||
self.wilson_b_label = QLabel("--", parent=self)
|
||||
self.wilson_b_label.setAlignment(
|
||||
Qt.AlignmentFlag.AlignRight | Qt.AlignmentFlag.AlignVCenter
|
||||
)
|
||||
self._layout.addWidget(self.wilson_b_label, 11, 1, 1, 3)
|
||||
self._layout.addWidget(QLabel("Å<sup>2</sup>", parent=self), 11, 4)
|
||||
self._layout.addWidget(self.wilson_b_label, 13, 1, 1, 3)
|
||||
self._layout.addWidget(QLabel("Å<sup>2</sup>", parent=self), 13, 4)
|
||||
|
||||
self._layout.addWidget(QLabel("Crystal Size x", parent=self), 12, 0)
|
||||
self._layout.addWidget(QLabel("Crystal Size x", parent=self), 14, 0)
|
||||
self.xtal_x_label = QLabel("--", parent=self)
|
||||
self.xtal_x_label.setAlignment(Qt.AlignmentFlag.AlignRight | Qt.AlignmentFlag.AlignVCenter)
|
||||
self._layout.addWidget(self.xtal_x_label, 12, 1, 1, 3)
|
||||
self._layout.addWidget(QLabel("um", parent=self), 12, 4)
|
||||
|
||||
self._layout.addWidget(QLabel("Crystal Size y", parent=self), 13, 0)
|
||||
self.xtal_y_label = QLabel("--", parent=self)
|
||||
self.xtal_y_label.setAlignment(Qt.AlignmentFlag.AlignRight | Qt.AlignmentFlag.AlignVCenter)
|
||||
self._layout.addWidget(self.xtal_y_label, 13, 1, 1, 3)
|
||||
self._layout.addWidget(QLabel("um", parent=self), 13, 4)
|
||||
|
||||
self._layout.addWidget(QLabel("Crystal Size z", parent=self), 14, 0)
|
||||
self.xtal_z_label = QLabel("--", parent=self)
|
||||
self.xtal_z_label.setAlignment(Qt.AlignmentFlag.AlignRight | Qt.AlignmentFlag.AlignVCenter)
|
||||
self._layout.addWidget(self.xtal_z_label, 14, 1, 1, 3)
|
||||
self._layout.addWidget(self.xtal_x_label, 14, 1, 1, 3)
|
||||
self._layout.addWidget(QLabel("um", parent=self), 14, 4)
|
||||
|
||||
self._layout.addWidget(QLabel("Calculated Dose (xtal size)", parent=self), 15, 0)
|
||||
self._layout.addWidget(QLabel("Crystal Size y", parent=self), 15, 0)
|
||||
self.xtal_y_label = QLabel("--", parent=self)
|
||||
self.xtal_y_label.setAlignment(Qt.AlignmentFlag.AlignRight | Qt.AlignmentFlag.AlignVCenter)
|
||||
self._layout.addWidget(self.xtal_y_label, 15, 1, 1, 3)
|
||||
self._layout.addWidget(QLabel("um", parent=self), 15, 4)
|
||||
|
||||
self._layout.addWidget(QLabel("Crystal Size z", parent=self), 16, 0)
|
||||
self.xtal_z_label = QLabel("--", parent=self)
|
||||
self.xtal_z_label.setAlignment(Qt.AlignmentFlag.AlignRight | Qt.AlignmentFlag.AlignVCenter)
|
||||
self._layout.addWidget(self.xtal_z_label, 16, 1, 1, 3)
|
||||
self._layout.addWidget(QLabel("um", parent=self), 16, 4)
|
||||
|
||||
self._layout.addWidget(QLabel("Calculated Dose (xtal size)", parent=self), 17, 0)
|
||||
self.xtal_size_dose_label = QLabel("--", parent=self)
|
||||
self.xtal_size_dose_label.setAlignment(
|
||||
Qt.AlignmentFlag.AlignRight | Qt.AlignmentFlag.AlignVCenter
|
||||
)
|
||||
self._layout.addWidget(self.xtal_size_dose_label, 15, 1, 1, 3)
|
||||
self._layout.addWidget(QLabel("MGy", parent=self), 15, 4)
|
||||
self._layout.addWidget(self.xtal_size_dose_label, 17, 1, 1, 3)
|
||||
self._layout.addWidget(QLabel("MGy", parent=self), 17, 4)
|
||||
|
||||
self._layout.addWidget(QLabel("X-ray Wavelength", parent=self), 16, 0)
|
||||
self._layout.addWidget(QLabel("X-ray Wavelength", parent=self), 18, 0)
|
||||
self.wavelength_label = QLabel("--", parent=self)
|
||||
self.wavelength_label.setAlignment(
|
||||
Qt.AlignmentFlag.AlignRight | Qt.AlignmentFlag.AlignVCenter
|
||||
)
|
||||
self._layout.addWidget(self.wavelength_label, 16, 1, 1, 3)
|
||||
self._layout.addWidget(QLabel("Å", parent=self), 16, 4)
|
||||
self._layout.addWidget(self.wavelength_label, 18, 1, 1, 3)
|
||||
self._layout.addWidget(QLabel("Å", parent=self), 18, 4)
|
||||
|
||||
self._layout.addWidget(QLabel("Flux", parent=self), 17, 0)
|
||||
self._layout.addWidget(QLabel("Flux", parent=self), 19, 0)
|
||||
self.flux_label = QLabel("--", parent=self)
|
||||
self.flux_label.setAlignment(Qt.AlignmentFlag.AlignRight | Qt.AlignmentFlag.AlignVCenter)
|
||||
self._layout.addWidget(self.flux_label, 17, 1, 1, 3)
|
||||
self._layout.addWidget(QLabel("x 10<sup>9</sup> ph s<sup>-1</sup>", parent=self), 17, 4)
|
||||
self._layout.addWidget(self.flux_label, 19, 1, 1, 3)
|
||||
self._layout.addWidget(QLabel("x 10<sup>9</sup> ph s<sup>-1</sup>", parent=self), 19, 4)
|
||||
|
||||
self._layout.addWidget(QLabel("Beam Size", parent=self), 18, 0)
|
||||
self._layout.addWidget(QLabel("Beam Size", parent=self), 20, 0)
|
||||
self.beam_size_label = QLabel("--", parent=self)
|
||||
self.beam_size_label.setAlignment(
|
||||
Qt.AlignmentFlag.AlignRight | Qt.AlignmentFlag.AlignVCenter
|
||||
)
|
||||
self._layout.addWidget(self.beam_size_label, 18, 1, 1, 3)
|
||||
self._layout.addWidget(QLabel("um<sup>2</sup>", parent=self), 18, 4)
|
||||
self._layout.addWidget(self.beam_size_label, 20, 1, 1, 3)
|
||||
self._layout.addWidget(QLabel("um<sup>2</sup>", parent=self), 20, 4)
|
||||
|
||||
self._layout.addWidget(QLabel("Calculated Dose", parent=self), 19, 0)
|
||||
self._layout.addWidget(QLabel("Calculated Dose", parent=self), 21, 0)
|
||||
self.calculated_dose_label = QLabel("--", parent=self)
|
||||
self.calculated_dose_label.setAlignment(
|
||||
Qt.AlignmentFlag.AlignRight | Qt.AlignmentFlag.AlignVCenter
|
||||
)
|
||||
self._layout.addWidget(self.calculated_dose_label, 19, 1, 1, 3)
|
||||
self._layout.addWidget(QLabel("MGy", parent=self), 19, 4)
|
||||
self._layout.addWidget(self.calculated_dose_label, 21, 1, 1, 3)
|
||||
self._layout.addWidget(QLabel("MGy", parent=self), 21, 4)
|
||||
|
||||
self._layout.addWidget(QLabel("Total measurement time", parent=self), 20, 0)
|
||||
self._layout.addWidget(QLabel("Total measurement time", parent=self), 22, 0)
|
||||
self.total_time = QLabel(f"{self.total_time_s} min 0 s")
|
||||
self.total_time.setAlignment(Qt.AlignmentFlag.AlignRight | Qt.AlignmentFlag.AlignVCenter)
|
||||
self._layout.addWidget(self.total_time, 20, 1, 1, 3)
|
||||
self._layout.addWidget(self.total_time, 22, 1, 1, 3)
|
||||
|
||||
# add vertical stretch between detector distance and the run button
|
||||
# Vertical stretch below everything (surplus space sink).
|
||||
self._layout.addItem(
|
||||
QSpacerItem(0, 0, QSizePolicy.Policy.Minimum, QSizePolicy.Policy.Expanding), 21, 0, 1, 6
|
||||
QSpacerItem(0, 0, QSizePolicy.Policy.Minimum, QSizePolicy.Policy.Expanding), 23, 0, 1, 6
|
||||
)
|
||||
|
||||
# Run rotation button
|
||||
self.run_rotation_button = QPushButton("Run rotation", parent=self)
|
||||
self.run_rotation_button.setStyleSheet(f"color: {GO_TEXT};")
|
||||
self.run_rotation_button.clicked.connect(self.run_measurement)
|
||||
self._layout.addWidget(self.run_rotation_button, 22, 0, 1, 6)
|
||||
|
||||
@Slot(DAQStatusModel)
|
||||
def update_daq_status(self, s: DAQStatusModel):
|
||||
self._d = s
|
||||
|
||||
@@ -33,8 +33,10 @@ class RasterGridTable(QTableWidget):
|
||||
header.setSectionResizeMode(i, QHeaderView.ResizeMode.ResizeToContents)
|
||||
header.setSectionResizeMode(4, QHeaderView.ResizeMode.Stretch)
|
||||
|
||||
# Set minimum height
|
||||
self.setMinimumHeight(100)
|
||||
# Exactly 5 rows of space; more grids scroll inside the table.
|
||||
header_height = self.horizontalHeader().sizeHint().height()
|
||||
row_height = self.verticalHeader().defaultSectionSize()
|
||||
self.setFixedHeight(header_height + 3 * row_height + 1 * self.frameWidth())
|
||||
|
||||
# Connect to raster manager signals
|
||||
self._raster_mgr.completed_grid_updated.connect(self.refresh_table)
|
||||
|
||||
Reference in New Issue
Block a user