-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- add ConfigurationHandler to handle updating the config state upon s…
…ignals from the UI (#78) - remove obsolete remove_files.py
- Loading branch information
Showing
5 changed files
with
169 additions
and
40 deletions.
There are no files selected for viewing
83 changes: 83 additions & 0 deletions
83
reflectivity_ui/interfaces/event_handlers/configuration_handler.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,83 @@ | ||
from PyQt5.QtCore import Qt | ||
from PyQt5.QtWidgets import QSpinBox, QCheckBox, QDoubleSpinBox | ||
|
||
from reflectivity_ui.interfaces.configuration import Configuration | ||
|
||
|
||
class ConfigurationHandler: | ||
""" | ||
Handles updating the configuration state upon changes in the UI | ||
""" | ||
|
||
def __init__(self, main_window): | ||
self.main_window = main_window | ||
self.ui = main_window.ui | ||
self.connect_config_events() | ||
|
||
def config_setter_factory(self, config_name: str, is_checkbox: bool): | ||
""" | ||
Generate anonymous functions to serve as callback when any of the global configurations | ||
(`Configuration` class variables) are updated in the UI. | ||
Each callback will be associated to one configuration parameter. Upon invoked, | ||
the `Configuration` class variable value will be updated. | ||
Parameters | ||
---------- | ||
config_name: str | ||
Name of the Configuration variable to update | ||
is_checkbox: bool | ||
True if the widget type is QCheckBox | ||
""" | ||
|
||
def config_setter(value: int | float): | ||
if is_checkbox: | ||
bool_value = value == Qt.CheckState.Checked | ||
setattr(Configuration, config_name, bool_value) | ||
else: | ||
setattr(Configuration, config_name, value) | ||
|
||
return config_setter | ||
|
||
def connect_config_events(self): | ||
widget_names = [ | ||
"final_rebin_checkbox", | ||
"q_rebin_spinbox", | ||
"normalize_to_unity_checkbox", | ||
"normalization_q_cutoff_spinbox", | ||
"global_fit_checkbox", | ||
"polynomial_stitching_degree_spinbox", | ||
"polynomial_stitching_points_spinbox", | ||
"polynomial_stitching_checkbox", | ||
"fanReflectivity", | ||
"sample_size_spinbox", | ||
"bandwidth_spinbox", | ||
] | ||
config_names = [ | ||
"do_final_rebin", | ||
"final_rebin_step", | ||
"normalize_to_unity", | ||
"total_reflectivity_q_cutoff", | ||
"global_stitching", | ||
"polynomial_stitching_degree", | ||
"polynomial_stitching_points", | ||
"polynomial_stitching", | ||
"use_constant_q", | ||
"sample_size", | ||
"wl_bandwidth", | ||
] | ||
|
||
for widget_name, config_name in zip(widget_names, config_names): | ||
# get the widget signal to connect | ||
widget = getattr(self.ui, widget_name) | ||
is_checkbox = False | ||
if isinstance(widget, (QSpinBox, QDoubleSpinBox)): | ||
signal_name = "valueChanged" | ||
elif isinstance(widget, QCheckBox): | ||
is_checkbox = True | ||
signal_name = "stateChanged" | ||
else: | ||
raise ValueError(f"{type(widget)} not supported by ConfigurationHandler") | ||
signal = getattr(widget, signal_name) | ||
# connect the signal to the updater | ||
signal.connect(self.config_setter_factory(config_name, is_checkbox)) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file was deleted.
Oops, something went wrong.
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,84 @@ | ||
# local imports | ||
from reflectivity_ui.interfaces.configuration import Configuration | ||
from reflectivity_ui.interfaces.data_handling.data_set import NexusData, CrossSectionData | ||
from reflectivity_ui.interfaces.main_window import MainWindow | ||
|
||
# third party imports | ||
import pytest | ||
|
||
# standard library imports | ||
|
||
|
||
def _initialize_test_data(main_window): | ||
"""Add one run with two cross-sections to the data manager""" | ||
config = Configuration() | ||
nexus_data = NexusData("file/path", config) | ||
off_off = CrossSectionData("Off_Off", config) | ||
on_off = CrossSectionData("On_Off", config) | ||
nexus_data.cross_sections["Off_Off"] = off_off | ||
nexus_data.cross_sections["On_Off"] = on_off | ||
main_window.data_manager._nexus_data = nexus_data | ||
main_window.data_manager.set_channel(0) | ||
main_window.data_manager.add_active_to_reduction() | ||
|
||
|
||
def _assert_configuration_value(main_window, param_name, gold_value): | ||
"""Check parameter value through the data hierarchy""" | ||
assert getattr(main_window.data_manager.active_channel.configuration, param_name) is gold_value | ||
for nexus_data in main_window.data_manager.reduction_list: | ||
assert getattr(nexus_data.configuration, param_name) is gold_value | ||
for xs_data in nexus_data.cross_sections.values(): | ||
assert getattr(xs_data.configuration, param_name) is gold_value | ||
|
||
|
||
def _assert_configuration_float_value(main_window, param_name, gold_value): | ||
"""Check float parameter value through the data hierarchy""" | ||
assert getattr(main_window.data_manager.active_channel.configuration, param_name) == pytest.approx(gold_value) | ||
for nexus_data in main_window.data_manager.reduction_list: | ||
assert getattr(nexus_data.configuration, param_name) == pytest.approx(gold_value) | ||
for xs_data in nexus_data.cross_sections.values(): | ||
assert getattr(xs_data.configuration, param_name) == pytest.approx(gold_value) | ||
|
||
|
||
@pytest.mark.parametrize( | ||
"widget, config_param", | ||
[ | ||
("final_rebin_checkbox", "do_final_rebin"), | ||
("normalize_to_unity_checkbox", "normalize_to_unity"), | ||
("global_fit_checkbox", "global_stitching"), | ||
("polynomial_stitching_checkbox", "polynomial_stitching"), | ||
("fanReflectivity", "use_constant_q"), | ||
], | ||
) | ||
def test_global_checkboxes(qtbot, widget, config_param): | ||
"""Test that UI global config checkbox changes get propagated to all configuration levels""" | ||
main_window = MainWindow() | ||
qtbot.addWidget(main_window) | ||
_initialize_test_data(main_window) | ||
|
||
getattr(main_window.ui, widget).setChecked(True) | ||
_assert_configuration_value(main_window, config_param, True) | ||
|
||
getattr(main_window.ui, widget).setChecked(False) | ||
_assert_configuration_value(main_window, config_param, False) | ||
|
||
|
||
@pytest.mark.parametrize( | ||
"widget, config_param, gold_value", | ||
[ | ||
("q_rebin_spinbox", "final_rebin_step", 0.01), | ||
("normalization_q_cutoff_spinbox", "total_reflectivity_q_cutoff", 0.02), | ||
("polynomial_stitching_degree_spinbox", "polynomial_stitching_degree", 2), | ||
("polynomial_stitching_points_spinbox", "polynomial_stitching_points", 5), | ||
("sample_size_spinbox", "sample_size", 15.0), | ||
("bandwidth_spinbox", "wl_bandwidth", 2.5), | ||
], | ||
) | ||
def test_global_spinboxes(qtbot, widget, config_param, gold_value): | ||
"""Test that UI global config spinbox changes get propagated to all configuration levels""" | ||
main_window = MainWindow() | ||
qtbot.addWidget(main_window) | ||
_initialize_test_data(main_window) | ||
|
||
getattr(main_window.ui, widget).setValue(gold_value) | ||
_assert_configuration_float_value(main_window, config_param, gold_value) |