Skip to content
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
- In the new Instrument View, added reset buttons for the contour and integration range sliders.
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,8 @@ def setup(self):

# Update counts with default total range
self.update_integration_range(self._integration_limits, True)
self.full_integration_limits = self._integration_limits
self.full_counts_limits = self._counts_limits

@property
def workspace(self) -> Workspace2D:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,12 @@ def on_integration_limits_updated(self) -> None:
self._model.integration_limits = self._view.get_integration_limits()
self.set_view_integration_limits()

def on_integration_limits_reset_clicked(self) -> None:
self._model.integration_limits = self._model.full_integration_limits
self._view.set_integration_range_limits(self._model.full_integration_limits)
self._view.set_integration_min_max_boxes(self._model.full_integration_limits)
self.set_view_integration_limits()

def set_view_integration_limits(self) -> None:
self._detector_mesh[self._counts_label] = self._model.detector_counts

Expand All @@ -149,6 +155,12 @@ def on_contour_limits_updated(self) -> None:
self._model.counts_limits = self._view.get_contour_limits()
self.set_view_contour_limits()

def on_contour_range_reset_clicked(self) -> None:
self._model.counts_limits = self._model.full_counts_limits
self._view.set_contour_range_limits(self._model.full_counts_limits)
self._view.set_contour_min_max_boxes(self._model.full_counts_limits)
self.set_view_contour_limits()

def set_view_contour_limits(self) -> None:
self._view.set_plotter_scalar_bar_range(self._model.counts_limits, self._counts_label)

Expand Down
44 changes: 30 additions & 14 deletions qt/python/instrumentview/instrumentview/FullInstrumentViewWindow.py
Original file line number Diff line number Diff line change
Expand Up @@ -182,12 +182,15 @@ def __init__(self, parent=None, off_screen=False):
self.set_relative_detector_angle(None)

self._integration_limit_group_box = QGroupBox("Time of Flight")
self._integration_limit_min_edit, self._integration_limit_max_edit, self._integration_limit_slider = self._add_min_max_group_box(
self._integration_limit_group_box
)
(
self._integration_limit_min_edit,
self._integration_limit_max_edit,
self._integration_limit_slider,
self._integration_limit_reset,
) = self._add_min_max_group_box(self._integration_limit_group_box)
self._contour_range_group_box = QGroupBox("Contour Range")
self._contour_range_min_edit, self._contour_range_max_edit, self._contour_range_slider = self._add_min_max_group_box(
self._contour_range_group_box
self._contour_range_min_edit, self._contour_range_max_edit, self._contour_range_slider, self._contour_range_reset = (
self._add_min_max_group_box(self._contour_range_group_box)
)

projection_group_box = QGroupBox("Projection")
Expand Down Expand Up @@ -356,7 +359,7 @@ def cache_camera_position(self) -> None:
self._projection_camera_map[self.current_selected_projection()] = self.main_plotter.camera_position
self._parallel_scales[self.current_selected_projection()] = self.main_plotter.camera.parallel_scale

def _add_min_max_group_box(self, parent_box: QGroupBox) -> tuple[QLineEdit, QLineEdit, QDoubleRangeSlider]:
def _add_min_max_group_box(self, parent_box: QGroupBox) -> tuple[QLineEdit, QLineEdit, QDoubleRangeSlider, QPushButton]:
"""Creates a minimum and a maximum box (with labels) inside the given group box. The callbacks will be attached to textEdited
signal of the boxes"""
min_hbox = QHBoxLayout()
Expand All @@ -370,6 +373,9 @@ def _add_min_max_group_box(self, parent_box: QGroupBox) -> tuple[QLineEdit, QLin
max_edit = QLineEdit()
max_edit.setValidator(QDoubleValidator(0, max_float_64, 4, self))
max_hbox.addWidget(max_edit)
reset_hbox = QHBoxLayout()
reset_button = QPushButton("Reset")
reset_hbox.addWidget(reset_button)

slider = QDoubleRangeSlider(Qt.Orientation.Horizontal, parent=parent_box)
slider.setRange(0, 1)
Expand All @@ -379,23 +385,31 @@ def _add_min_max_group_box(self, parent_box: QGroupBox) -> tuple[QLineEdit, QLin
root_hbox = QHBoxLayout()
root_hbox.addLayout(min_hbox)
root_hbox.addLayout(max_hbox)
root_hbox.addLayout(reset_hbox)

root_vbox = QVBoxLayout()
root_vbox.addLayout(slider_hbox)
root_vbox.addLayout(root_hbox)
parent_box.setLayout(root_vbox)

return (min_edit, max_edit, slider)
return (min_edit, max_edit, slider, reset_button)

def set_contour_min_max_boxes(self, limits: tuple[float, float]) -> None:
self._set_min_max_edit_boxes(self._contour_range_min_edit, self._contour_range_max_edit, limits)

def set_integration_min_max_boxes(self, limits: tuple[float, float]) -> None:
self._set_min_max_edit_boxes(self._integration_limit_min_edit, self._integration_limit_max_edit, limits)

def _set_min_max_edit_boxes(self, min_edit: QLineEdit, max_edit: QLineEdit, limits: tuple[float, float]) -> None:
min, max = limits

def _add_connections_to_edits_and_slider(self, min_edit: QLineEdit, max_edit: QLineEdit, slider, presenter_callback: Callable):
def format_float(value):
return f"{value:.4f}".rstrip("0").rstrip(".")

def set_edits(limits):
min, max = limits
min_edit.setText(format_float(min))
max_edit.setText(format_float(max))
min_edit.setText(format_float(min))
max_edit.setText(format_float(max))

def _add_connections_to_edits_and_slider(self, min_edit: QLineEdit, max_edit: QLineEdit, slider, presenter_callback: Callable):
def set_slider(callled_from_min):
def wrapped():
try:
Expand All @@ -413,7 +427,7 @@ def wrapped():
return wrapped

# Connections to sync sliders and edits
slider.valueChanged.connect(set_edits)
slider.valueChanged.connect(lambda lims: self._set_min_max_edit_boxes(min_edit, max_edit, lims))
min_edit.editingFinished.connect(set_slider(callled_from_min=True))
max_edit.editingFinished.connect(set_slider(callled_from_min=False))

Expand Down Expand Up @@ -467,9 +481,11 @@ def subscribe_presenter(self, presenter) -> None:

def setup_connections_to_presenter(self) -> None:
self._projection_combo_box.currentIndexChanged.connect(self._presenter.update_plotter)
self._clear_point_picked_detectors.clicked.connect((self._presenter.on_clear_point_picked_detectors_clicked))
self._clear_point_picked_detectors.clicked.connect(self._presenter.on_clear_point_picked_detectors_clicked)
self._contour_range_slider.sliderReleased.connect(self._presenter.on_contour_limits_updated)
self._contour_range_reset.clicked.connect(self._presenter.on_contour_range_reset_clicked)
self._integration_limit_slider.sliderReleased.connect(self._presenter.on_integration_limits_updated)
self._integration_limit_reset.clicked.connect(self._presenter.on_integration_limits_reset_clicked)
self._units_combo_box.currentIndexChanged.connect(self._presenter.on_unit_option_selected)
self._export_workspace_button.clicked.connect(self._presenter.on_export_workspace_clicked)
self._sum_spectra_checkbox.clicked.connect(self._presenter.on_sum_spectra_checkbox_clicked)
Expand Down
24 changes: 23 additions & 1 deletion qt/python/instrumentview/instrumentview/test/test_presenter.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@

import unittest
from unittest import mock
from unittest.mock import MagicMock
from unittest.mock import MagicMock, PropertyMock
from enum import Enum


Expand Down Expand Up @@ -470,6 +470,28 @@ def test_create_and_add_monitor_mesh(self):
self._presenter._create_and_add_monitor_mesh()
self._mock_view.add_rgba_mesh.assert_called_once()

@mock.patch.object(FullInstrumentViewModel, "integration_limits", new_callable=PropertyMock)
def test_on_integration_limits_reset_clicked(self, mock_integration_limits):
"""Test on_integration_limits_reset_clicked resets to full range."""
self._model.full_integration_limits = (0.0, 1000.0)
self._model._integration_limits = (200, 300)
self._presenter.on_integration_limits_reset_clicked()
mock_integration_limits.assert_called_once_with((0.0, 1000.0))
self._mock_view.set_integration_range_limits.assert_called_once_with((0.0, 1000.0))
self._mock_view.set_integration_min_max_boxes.assert_called_once_with((0.0, 1000.0))

@mock.patch("instrumentview.FullInstrumentViewPresenter.FullInstrumentViewPresenter.set_view_contour_limits")
@mock.patch.object(FullInstrumentViewModel, "counts_limits", new_callable=PropertyMock)
def test_on_contour_range_reset_clicked(self, mock_counts_limits, mock_set_view_contour):
"""Test on_contour_range_reset_clicked resets to full range."""
self._model.full_counts_limits = (0, 100)
self._model._counts_limits = (1, 2)
self._presenter.on_contour_range_reset_clicked()
mock_counts_limits.assert_called_once_with((0, 100))
mock_set_view_contour.assert_called_once()
self._mock_view.set_contour_range_limits.assert_called_once_with((0, 100))
self._mock_view.set_contour_min_max_boxes.assert_called_once_with((0, 100))


if __name__ == "__main__":
unittest.main()