diff --git a/src/aare/gui/panels/data_collection_settings.py b/src/aare/gui/panels/data_collection_settings.py index e501dc45..271f5999 100644 --- a/src/aare/gui/panels/data_collection_settings.py +++ b/src/aare/gui/panels/data_collection_settings.py @@ -97,7 +97,7 @@ class DataCollectionSettings(QFrame): energy_row = QWidget(self) energy_layout = QHBoxLayout(energy_row) energy_layout.setContentsMargins(0, 0, 0, 0) - energy_layout.addWidget(QLabel("Energy (keV)", parent=energy_row)) + energy_layout.addWidget(QLabel("Set Energy (keV)", parent=energy_row)) energy_layout.addWidget(self.energy_spin) energy_layout.addWidget(self.change_energy_button) diff --git a/src/aare/gui/panels/monochromator_panel.py b/src/aare/gui/panels/monochromator_panel.py index 6e2efb8e..c4511fa6 100644 --- a/src/aare/gui/panels/monochromator_panel.py +++ b/src/aare/gui/panels/monochromator_panel.py @@ -26,22 +26,28 @@ class MonochromatorPanel(QWidget): self.mono_pitch_scan_button.clicked.connect(self.mono_pitch_scan.emit) grid_layout.addWidget(self.mono_pitch_scan_button, 1, 0, 1, 3) + # Live readout above the setpoint, so "what is" and "what to set" + # stop sharing one ambiguous Energy row. Fed per DAQ tick. + grid_layout.addWidget(QLabel("Current energy / λ", parent=self), 2, 0) + self.current_energy_label = QLabel("—", parent=self) + grid_layout.addWidget(self.current_energy_label, 2, 1, 1, 2) + # One row (label | value | button) instead of three — vertical space. # Display in keV; the DAQ API stays in eV (converted on emit). # Unit lives in the label, not as a spinbox suffix — the suffix ate # field width and sat between the value and the +/- arrow. - grid_layout.addWidget(QLabel("Energy (keV)", parent=self), 2, 0) + grid_layout.addWidget(QLabel("Set Energy (keV)", parent=self), 3, 0) self.energy_spin = QDoubleSpinBox(parent=self) self.energy_spin.setDecimals(3) self.energy_spin.setRange(1.0, 30.0) self.energy_spin.setSingleStep(0.1) self.energy_spin.setValue(12.0) - grid_layout.addWidget(self.energy_spin, 2, 1) + grid_layout.addWidget(self.energy_spin, 3, 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, 2, 2) + grid_layout.addWidget(self.change_energy_button, 3, 2) # TODO(wire backend): no DAQ endpoint exists yet for moving the beam # to the box center — shown disabled as WIP until the operation is @@ -51,12 +57,21 @@ class MonochromatorPanel(QWidget): self.move_beam_to_box_button.setToolTip("Coming soon — not functional yet.") self.move_beam_to_box_button.setEnabled(False) self.move_beam_to_box_button.clicked.connect(self.move_beam_to_box.emit) - grid_layout.addWidget(self.move_beam_to_box_button, 3, 0, 1, 3) + grid_layout.addWidget(self.move_beam_to_box_button, 4, 0, 1, 3) @Slot() def _emit_change_energy(self): self.change_energy.emit(float(self.energy_spin.value()) * 1000.0) @Slot(DAQStatusModel) - def update_daq_status(self, _status: DAQStatusModel): - pass + def update_daq_status(self, status: DAQStatusModel): + energy = status.diffraction.energy_keV + # 0.0 is the server's detector-unavailable fallback, and the + # wavelength property divides by it — guard before touching it. + if not energy: + text = "— / —" + else: + text = f"{energy:.3f} keV / {status.diffraction.wavelength_angstrom:.4f} Å" + # Guarded: runs per DAQ tick (2 Hz), skip the repaint when unchanged. + if self.current_energy_label.text() != text: + self.current_energy_label.setText(text) diff --git a/tests/unit/gui/test_monochromator_panel.py b/tests/unit/gui/test_monochromator_panel.py new file mode 100644 index 00000000..6286645a --- /dev/null +++ b/tests/unit/gui/test_monochromator_panel.py @@ -0,0 +1,16 @@ +from aare.gui.panels.monochromator_panel import MonochromatorPanel + + +def test_current_energy_readout(qtbot, daq_status_factory): + panel = MonochromatorPanel() + qtbot.addWidget(panel) + + status = daq_status_factory() + panel.update_daq_status(status) + assert panel.current_energy_label.text() == "12.000 keV / 1.0332 Å" + + # 0.0 is the server's detector-unavailable fallback; the wavelength + # property divides by energy, so the readout must not touch it. + status.diffraction = status.diffraction.model_copy(update={"energy_keV": 0.0}) + panel.update_daq_status(status) + assert panel.current_energy_label.text() == "— / —"