diff --git a/docs/release_notes/next/feature-1957-rits-roi b/docs/release_notes/next/feature-1957-rits-roi new file mode 100644 index 00000000000..bdcc93f94df --- /dev/null +++ b/docs/release_notes/next/feature-1957-rits-roi @@ -0,0 +1,2 @@ +#1957 : ROI support for RITS export + diff --git a/mantidimaging/gui/windows/spectrum_viewer/model.py b/mantidimaging/gui/windows/spectrum_viewer/model.py index 26852b30d24..583b220c1b2 100644 --- a/mantidimaging/gui/windows/spectrum_viewer/model.py +++ b/mantidimaging/gui/windows/spectrum_viewer/model.py @@ -20,6 +20,9 @@ LOG = getLogger(__name__) +ROI_ALL = "all" +ROI_RITS = "rits_roi" + class SpecType(Enum): SAMPLE = 1 @@ -44,7 +47,7 @@ def __init__(self, presenter: 'SpectrumViewerWindowPresenter'): self.presenter = presenter self._roi_id_counter = 0 self._roi_ranges = {} - self.default_roi_list = ["all"] + self.special_roi_list = [ROI_ALL] def roi_name_generator(self) -> str: """ @@ -77,7 +80,7 @@ def set_stack(self, stack: Optional[ImageStack]) -> None: return self._roi_id_counter = 0 self.tof_range = (0, stack.data.shape[0] - 1) - self.set_new_roi(self.default_roi_list[0]) + self.set_new_roi(ROI_ALL) def set_new_roi(self, name: str) -> None: """ @@ -198,9 +201,6 @@ def save_rits(self, path: Path, normalized: bool) -> None: if self._stack is None: raise ValueError("No stack selected") - # Default_roi will likely need updating once UI is implemented - default_roi = self.default_roi_list[0] - tof = self.get_stack_time_of_flight() if tof is None: raise ValueError("No Time of Flights for sample. Make sure spectra log has been loaded") @@ -208,11 +208,11 @@ def save_rits(self, path: Path, normalized: bool) -> None: # RITS expects ToF in μs tof *= 1e6 - transmission_error = np.zeros_like(tof) + transmission_error = np.full_like(tof, 0.1) if normalized: if self._normalise_stack is None: raise RuntimeError("No normalisation stack selected") - transmission = self.get_spectrum(default_roi, SpecType.SAMPLE_NORMED) + transmission = self.get_spectrum(ROI_RITS, SpecType.SAMPLE_NORMED) self.export_spectrum_to_rits(path, tof, transmission, transmission_error) else: LOG.error("Data is not normalised to open beam. This will not export to a valid RITS format") @@ -266,8 +266,8 @@ def remove_roi(self, roi_name) -> None: @param roi_name: The name of the ROI to remove """ if roi_name in self._roi_ranges.keys(): - if roi_name in self.default_roi_list: - raise RuntimeError("Cannot remove the 'all' or 'roi' ROIs") + if roi_name in self.special_roi_list: + raise RuntimeError(f"Cannot remove ROI: {roi_name}") del self._roi_ranges[roi_name] else: raise KeyError( @@ -283,14 +283,14 @@ def rename_roi(self, old_name: str, new_name: str) -> None: @raises RuntimeError: If the ROI is 'all' """ if old_name in self._roi_ranges.keys() and new_name not in self._roi_ranges.keys(): - if old_name == self.default_roi_list[0]: - raise RuntimeError("Cannot rename the 'all' ROI") + if old_name in self.special_roi_list: + raise RuntimeError(f"Cannot remove ROI: {old_name}") self._roi_ranges[new_name] = self._roi_ranges.pop(old_name) else: raise KeyError(f"Cannot rename {old_name} to {new_name} Available:{self._roi_ranges.keys()}") def remove_all_roi(self) -> None: """ - Remove all ROIs from the model excluding default ROI 'all' + Remove all ROIs from the model """ - self._roi_ranges = {key: value for key, value in self._roi_ranges.items() if key in self.default_roi_list} + self._roi_ranges = {} diff --git a/mantidimaging/gui/windows/spectrum_viewer/presenter.py b/mantidimaging/gui/windows/spectrum_viewer/presenter.py index 3796921f4d3..a8096f6c9e0 100644 --- a/mantidimaging/gui/windows/spectrum_viewer/presenter.py +++ b/mantidimaging/gui/windows/spectrum_viewer/presenter.py @@ -8,7 +8,7 @@ from logging import getLogger from mantidimaging.core.data.dataset import StrictDataset from mantidimaging.gui.mvp_base import BasePresenter -from mantidimaging.gui.windows.spectrum_viewer.model import SpectrumViewerWindowModel, SpecType +from mantidimaging.gui.windows.spectrum_viewer.model import SpectrumViewerWindowModel, SpecType, ROI_RITS if TYPE_CHECKING: from mantidimaging.gui.windows.spectrum_viewer.view import SpectrumViewerWindowView # pragma: no cover @@ -75,6 +75,7 @@ def handle_sample_change(self, uuid: Optional['UUID']) -> None: self.model.set_normalise_stack(norm_stack) self.do_add_roi() + self.add_rits_roi() self.view.set_normalise_error(self.model.normalise_issue()) self.show_new_sample() @@ -205,6 +206,13 @@ def do_add_roi(self) -> None: self.view.auto_range_image() self.do_add_roi_to_table(roi_name) + def add_rits_roi(self) -> None: + roi_name = ROI_RITS + self.model.set_new_roi(roi_name) + self.view.spectrum.add_roi(self.model.get_roi(roi_name), roi_name) + self.view.set_spectrum(roi_name, self.model.get_spectrum(roi_name, self.spectrum_mode)) + self.view.set_roi_alpha(0, ROI_RITS) + def do_add_roi_to_table(self, roi_name: str) -> None: """ Add a given ROI to the table by ROI name @@ -224,7 +232,7 @@ def rename_roi(self, old_name: str, new_name: str) -> None: self.view.spectrum.rename_roi(old_name, new_name) self.model.rename_roi(old_name, new_name) - def do_remove_roi(self, roi_name=None) -> None: + def do_remove_roi(self, roi_name: str | None = None) -> None: """ Remove a given ROI from the table by ROI name or all ROIs from the table if no name is passed as an argument diff --git a/mantidimaging/gui/windows/spectrum_viewer/roi_table_model.py b/mantidimaging/gui/windows/spectrum_viewer/roi_table_model.py index 95fe83d9b08..abbb2dd5dc3 100644 --- a/mantidimaging/gui/windows/spectrum_viewer/roi_table_model.py +++ b/mantidimaging/gui/windows/spectrum_viewer/roi_table_model.py @@ -91,6 +91,9 @@ def row_data(self, row: int) -> list: """ return self._data[row] + def __getitem__(self, item: int) -> list: + return self.row_data(item) + def column_data(self, column: int) -> list: """ Return data from selected column diff --git a/mantidimaging/gui/windows/spectrum_viewer/spectrum_widget.py b/mantidimaging/gui/windows/spectrum_viewer/spectrum_widget.py index e9d0da14331..f7ff2cd6cf4 100644 --- a/mantidimaging/gui/windows/spectrum_viewer/spectrum_widget.py +++ b/mantidimaging/gui/windows/spectrum_viewer/spectrum_widget.py @@ -87,7 +87,7 @@ def __init__(self) -> None: self.nextRow() self.spectrum = self.addPlot() - self.spectrum_data_dict: dict[str, np.ndarray] = {} + self.spectrum_data_dict: dict[str, np.ndarray | None] = {} self.nextRow() self._tof_range_label = self.addLabel() diff --git a/mantidimaging/gui/windows/spectrum_viewer/test/model_test.py b/mantidimaging/gui/windows/spectrum_viewer/test/model_test.py index 3e02f037681..5c9d8bcc585 100644 --- a/mantidimaging/gui/windows/spectrum_viewer/test/model_test.py +++ b/mantidimaging/gui/windows/spectrum_viewer/test/model_test.py @@ -283,7 +283,7 @@ def test_WHEN_remove_all_rois_called_THEN_all_but_default_rois_removed(self): self.model.set_new_roi("new_roi_2") self.assertListEqual(self.model.get_list_of_roi_names(), ["all", "new_roi", "new_roi_2"]) self.model.remove_all_roi() - self.assertListEqual(self.model.get_list_of_roi_names(), ["all"]) + self.assertListEqual(self.model.get_list_of_roi_names(), []) def test_WHEN_roi_renamed_THEN_roi_name_changed_in_list_of_roi_names(self): self.model.set_stack(generate_images()) diff --git a/mantidimaging/gui/windows/spectrum_viewer/test/presenter_test.py b/mantidimaging/gui/windows/spectrum_viewer/test/presenter_test.py index 5dbaf9137ad..6dab80a7e69 100644 --- a/mantidimaging/gui/windows/spectrum_viewer/test/presenter_test.py +++ b/mantidimaging/gui/windows/spectrum_viewer/test/presenter_test.py @@ -256,4 +256,4 @@ def test_WHEN_do_remove_roi_called_with_no_arguments_THEN_all_rois_removed(self) self.presenter.do_add_roi() self.assertEqual(["all", "roi", "roi_1", "roi_2"], self.presenter.model.get_list_of_roi_names()) self.presenter.do_remove_roi() - self.assertEqual(["all"], self.presenter.model.get_list_of_roi_names()) + self.assertEqual([], self.presenter.model.get_list_of_roi_names()) diff --git a/mantidimaging/gui/windows/spectrum_viewer/view.py b/mantidimaging/gui/windows/spectrum_viewer/view.py index 9a1aa45dd39..cc34f436dc3 100644 --- a/mantidimaging/gui/windows/spectrum_viewer/view.py +++ b/mantidimaging/gui/windows/spectrum_viewer/view.py @@ -11,6 +11,7 @@ from mantidimaging.core.utility import finder from mantidimaging.gui.mvp_base import BaseMainWindowView from mantidimaging.gui.widgets.dataset_selector import DatasetSelectorWidgetView +from .model import ROI_RITS from .presenter import SpectrumViewerWindowPresenter, ExportMode from mantidimaging.gui.widgets import RemovableRowTableView from .spectrum_widget import SpectrumWidget @@ -142,19 +143,22 @@ def on_visibility_change(self) -> None: """ When the visibility of an ROI is changed, update the visibility of the ROI in the spectrum widget """ - for roi_item in range(self.roi_table_model.rowCount()): - if self.presenter.export_mode == ExportMode.ROI_MODE: - roi_name, _, roi_visible = self.roi_table_model.row_data(roi_item) + if self.presenter.export_mode == ExportMode.ROI_MODE: + for roi_name, _, roi_visible in self.roi_table_model: if roi_visible is False: self.set_roi_alpha(0, roi_name) else: self.set_roi_alpha(255, roi_name) self.presenter.redraw_spectrum(roi_name) - else: - roi_name, _, _ = self.roi_table_model.row_data(roi_item) + else: + for roi_name, _, _ in self.roi_table_model: self.set_roi_alpha(0, roi_name) - return + if self.presenter.export_mode == ExportMode.IMAGE_MODE: + self.set_roi_alpha(255, ROI_RITS) + self.presenter.redraw_spectrum(ROI_RITS) + else: + self.set_roi_alpha(0, ROI_RITS) @property def roi_table_model(self) -> TableModel: @@ -209,9 +213,7 @@ def set_spectrum(self, name: str, spectrum_data: 'np.ndarray'): self.spectrum.spectrum_data_dict[name] = spectrum_data self.spectrum.spectrum.clearPlots() - for key, value in self.spectrum.spectrum_data_dict.items(): - if key in self.spectrum.roi_dict: - self.spectrum.spectrum.plot(value, name=key, pen=self.spectrum.roi_dict[key].colour) + self.show_visible_spectrums() def clear(self) -> None: self.spectrum.spectrum_data_dict = {} @@ -252,14 +254,15 @@ def set_roi_alpha(self, alpha: float, roi_name: str) -> None: """ self.spectrum.set_roi_alpha(roi_name, alpha) if alpha == 0: - self.spectrum.spectrum_data_dict[roi_name] = np.zeros(self.spectrum.spectrum_data_dict[roi_name].shape) - else: - self.spectrum.spectrum_data_dict[roi_name] = self.spectrum.spectrum_data_dict[roi_name] + self.spectrum.spectrum_data_dict[roi_name] = None self.spectrum.spectrum.clearPlots() self.spectrum.spectrum.update() + self.show_visible_spectrums() + + def show_visible_spectrums(self): for key, value in self.spectrum.spectrum_data_dict.items(): - if key in self.spectrum.roi_dict: + if value is not None and key in self.spectrum.roi_dict: self.spectrum.spectrum.plot(value, name=key, pen=self.spectrum.roi_dict[key].colour) def add_roi_table_row(self, name: str, colour: tuple[int, int, int]):