From 989c223684fedd0c59bea91d412882c0e1815843 Mon Sep 17 00:00:00 2001 From: ashmeigh Date: Mon, 25 Nov 2024 15:49:27 +0000 Subject: [PATCH 01/10] Refactor get_spectrum to no longer accept ROI as a string --- mantidimaging/core/utility/sensible_roi.py | 10 ++-- .../gui/windows/spectrum_viewer/model.py | 56 ++++++++++-------- .../gui/windows/spectrum_viewer/presenter.py | 59 +++++++++++-------- 3 files changed, 74 insertions(+), 51 deletions(-) diff --git a/mantidimaging/core/utility/sensible_roi.py b/mantidimaging/core/utility/sensible_roi.py index 9655cee7225..1ec03aa86c5 100644 --- a/mantidimaging/core/utility/sensible_roi.py +++ b/mantidimaging/core/utility/sensible_roi.py @@ -13,25 +13,27 @@ @dataclass class SensibleROI(Iterable): - __slots__ = ("left", "top", "right", "bottom") + __slots__ = ("left", "top", "right", "bottom", "name") left: int top: int right: int bottom: int + name: str - def __init__(self, left=0, top=0, right=0, bottom=0): + def __init__(self, left=0, top=0, right=0, bottom=0, name: str = ""): self.left = left self.top = top self.right = right self.bottom = bottom + self.name = name @staticmethod def from_points(position: CloseEnoughPoint, size: CloseEnoughPoint) -> SensibleROI: return SensibleROI(position.x, position.y, position.x + size.x, position.y + size.y) @staticmethod - def from_list(roi: list[int] | list[float]) -> SensibleROI: - return SensibleROI(int(roi[0]), int(roi[1]), int(roi[2]), int(roi[3])) + def from_list(roi: list[int] | list[float], name: str = "") -> SensibleROI: + return SensibleROI(int(roi[0]), int(roi[1]), int(roi[2]), int(roi[3]), name=name) def __iter__(self) -> Iterator[int]: """ diff --git a/mantidimaging/gui/windows/spectrum_viewer/model.py b/mantidimaging/gui/windows/spectrum_viewer/model.py index 2f6b897b255..1c576d63d53 100644 --- a/mantidimaging/gui/windows/spectrum_viewer/model.py +++ b/mantidimaging/gui/windows/spectrum_viewer/model.py @@ -99,6 +99,7 @@ def __init__(self, presenter: SpectrumViewerWindowPresenter): self._roi_id_counter = 0 self._roi_ranges = {} self.special_roi_list = [ROI_ALL] + self._rois: list[SensibleROI] = [] self.units = UnitConversion() @@ -112,11 +113,17 @@ def roi_name_generator(self) -> str: self._roi_id_counter += 1 return new_name - def get_list_of_roi_names(self) -> list[str]: + def get_list_of_rois(self) -> list[SensibleROI]: + """ + Returns a list of all ROI objects. + """ + return self._rois + + def add_roi(self, roi: SensibleROI) -> None: """ - Get a list of rois available in the model + Adds an ROI to the list. """ - return list(self._roi_ranges.keys()) + self._rois.append(roi) def set_stack(self, stack: ImageStack | None) -> None: """ @@ -162,6 +169,12 @@ def get_roi(self, roi_name: str) -> SensibleROI: raise KeyError(f"ROI {roi_name} does not exist in roi_ranges {self._roi_ranges.keys()}") return self._roi_ranges[roi_name] + def get_list_of_roi_names(self) -> list[str]: + """ + Returns the names of all ROIs. + """ + return [roi.name for roi in self._rois] + def get_averaged_image(self) -> np.ndarray | None: """ Get the averaged image from the stack in the model returning as a numpy array @@ -218,16 +231,10 @@ def shuttercount_issue(self) -> str: return "Need 2 different ShutterCount stacks" return "" - def get_spectrum(self, - roi: str | SensibleROI, - mode: SpecType, - normalise_with_shuttercount: bool = False) -> np.ndarray: + def get_spectrum(self, roi: SensibleROI, mode: SpecType, normalise_with_shuttercount: bool = False) -> np.ndarray: if self._stack is None: return np.array([]) - if isinstance(roi, str): - roi = self.get_roi(roi) - if mode == SpecType.SAMPLE: return self.get_stack_spectrum(self._stack, roi) @@ -241,14 +248,14 @@ def get_spectrum(self, return np.array([]) roi_spectrum = self.get_stack_spectrum(self._stack, roi) roi_norm_spectrum = self.get_stack_spectrum(self._normalise_stack, roi) - spectrum = np.divide(roi_spectrum, - roi_norm_spectrum, - out=np.zeros_like(roi_spectrum), - where=roi_norm_spectrum != 0) - if normalise_with_shuttercount: - average_shuttercount = self.get_shuttercount_normalised_correction_parameter() - spectrum = spectrum / average_shuttercount - return spectrum + spectrum = np.divide(roi_spectrum, + roi_norm_spectrum, + out=np.zeros_like(roi_spectrum), + where=roi_norm_spectrum != 0) + if normalise_with_shuttercount: + average_shuttercount = self.get_shuttercount_normalised_correction_parameter() + spectrum = spectrum / average_shuttercount + return spectrum def get_shuttercount_normalised_correction_parameter(self) -> float: """ @@ -335,7 +342,8 @@ def save_csv(self, path: Path, normalise: bool, normalise_with_shuttercount: boo Iterates over all ROIs and saves the spectrum for each one to a CSV file. @param path: The path to save the CSV file to. - @param normalized: Whether to save the normalized spectrum. + @param normalise: Whether to save the normalized spectrum. + @param normalise_with_shuttercount: Whether to normalize with the shutter count. """ if self._stack is None: raise ValueError("No stack selected") @@ -349,15 +357,15 @@ def save_csv(self, path: Path, normalise: bool, normalise_with_shuttercount: boo csv_output.add_column("ToF", self.units.tof_seconds_to_us(), "Microseconds") csv_output.add_column("Energy", self.units.tof_seconds_to_energy(), "MeV") - for roi_name in self.get_list_of_roi_names(): - csv_output.add_column(roi_name, self.get_spectrum(roi_name, SpecType.SAMPLE, normalise_with_shuttercount), + for roi in self.get_list_of_rois(): + csv_output.add_column(roi.name, self.get_spectrum(roi, SpecType.SAMPLE, normalise_with_shuttercount), "Counts") if normalise: if self._normalise_stack is None: raise RuntimeError("No normalisation stack selected") - csv_output.add_column(roi_name + "_open", self.get_spectrum(roi_name, SpecType.OPEN), "Counts") - csv_output.add_column(roi_name + "_norm", - self.get_spectrum(roi_name, SpecType.SAMPLE_NORMED, normalise_with_shuttercount), + csv_output.add_column(roi.name + "_open", self.get_spectrum(roi, SpecType.OPEN), "Counts") + csv_output.add_column(roi.name + "_norm", + self.get_spectrum(roi, SpecType.SAMPLE_NORMED, normalise_with_shuttercount), "Counts") with path.open("w") as outfile: diff --git a/mantidimaging/gui/windows/spectrum_viewer/presenter.py b/mantidimaging/gui/windows/spectrum_viewer/presenter.py index cdee740def6..ec006899fa5 100644 --- a/mantidimaging/gui/windows/spectrum_viewer/presenter.py +++ b/mantidimaging/gui/windows/spectrum_viewer/presenter.py @@ -200,15 +200,20 @@ def handle_roi_moved(self, force_new_spectrums: bool = False) -> None: """ Handle changes to any ROI position and size. """ - for name in self.model.get_list_of_roi_names(): - roi = self.view.spectrum_widget.get_roi(name) - if force_new_spectrums or roi != self.model.get_roi(name): - self.model.set_roi(name, roi) - self.view.set_spectrum( - name, - self.model.get_spectrum(name, - self.spectrum_mode, - normalise_with_shuttercount=self.view.shuttercount_norm_enabled())) + roi_names = self.model.get_list_of_roi_names() + + for name in roi_names: + view_roi = self.view.spectrum_widget.get_roi(name) + model_roi = self.model.get_roi(name) + + if force_new_spectrums or view_roi != model_roi: + self.model.set_roi(name, view_roi) + updated_spectrum = self.model.get_spectrum( + view_roi, + self.spectrum_mode, + normalise_with_shuttercount=self.view.shuttercount_norm_enabled(), + ) + self.view.set_spectrum(name, updated_spectrum) def handle_roi_clicked(self, roi: SpectrumROI) -> None: if not roi.name == ROI_RITS: @@ -220,9 +225,10 @@ def redraw_spectrum(self, name: str) -> None: """ Redraw the spectrum with the given name """ + roi = self.model.get_roi(name) self.view.set_spectrum( name, - self.model.get_spectrum(name, + self.model.get_spectrum(roi, self.spectrum_mode, normalise_with_shuttercount=self.view.shuttercount_norm_enabled())) @@ -231,12 +237,13 @@ def redraw_all_rois(self) -> None: Redraw all ROIs and spectrum plots """ for name in self.model.get_list_of_roi_names(): - if name == "all" or self.view.spectrum_widget.roi_dict[name].isVisible() is False: + if name == "all" or not self.view.spectrum_widget.roi_dict[name].isVisible(): continue - self.model.set_roi(name, self.view.spectrum_widget.get_roi(name)) + roi = self.view.spectrum_widget.get_roi(name) + self.model.set_roi(name, roi) self.view.set_spectrum( name, - self.model.get_spectrum(name, + self.model.get_spectrum(roi, self.spectrum_mode, normalise_with_shuttercount=self.view.shuttercount_norm_enabled())) @@ -331,10 +338,12 @@ def do_add_roi(self) -> None: roi_name = self.model.roi_name_generator() if roi_name in self.view.spectrum_widget.roi_dict: raise ValueError(f"ROI name already exists: {roi_name}") + self.model.set_new_roi(roi_name) - self.view.spectrum_widget.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.shuttercount_norm_enabled())) + roi = self.model.get_roi(roi_name) + self.view.spectrum_widget.add_roi(roi, roi_name) + spectrum = self.model.get_spectrum(roi, self.spectrum_mode, self.view.shuttercount_norm_enabled()) + self.view.set_spectrum(roi_name, spectrum) self.view.auto_range_image() self.do_add_roi_to_table(roi_name) @@ -353,9 +362,10 @@ def change_roi_colour(self, roi_name: str, new_colour: tuple[int, int, int]) -> def add_rits_roi(self) -> None: roi_name = ROI_RITS self.model.set_new_roi(roi_name) - self.view.spectrum_widget.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.shuttercount_norm_enabled())) + roi = self.model.get_roi(roi_name) + self.view.spectrum_widget.add_roi(roi, roi_name) + spectrum = self.model.get_spectrum(roi, self.spectrum_mode, self.view.shuttercount_norm_enabled()) + self.view.set_spectrum(roi_name, spectrum) self.view.set_roi_visibility_flags(ROI_RITS, visible=False) def do_add_roi_to_table(self, roi_name: str) -> None: @@ -386,13 +396,16 @@ def do_remove_roi(self, roi_name: str | None = None) -> None: """ if roi_name is None: self.view.clear_all_rois() - for roi in self.get_roi_names(): - self.view.spectrum_widget.remove_roi(roi) + for name in self.get_roi_names(): + self.view.spectrum_widget.remove_roi(name) self.model.remove_all_roi() else: + roi = self.model.get_roi(roi_name) self.view.spectrum_widget.remove_roi(roi_name) - self.view.set_spectrum( - roi_name, self.model.get_spectrum(roi_name, self.spectrum_mode, self.view.shuttercount_norm_enabled())) + spectrum = self.model.get_spectrum(roi, + self.spectrum_mode, + normalise_with_shuttercount=self.view.shuttercount_norm_enabled()) + self.view.set_spectrum(roi_name, spectrum) self.model.remove_roi(roi_name) def handle_export_tab_change(self, index: int) -> None: From 875a65bd9b4845beb85c73bf5768e44067263275 Mon Sep 17 00:00:00 2001 From: ashmeigh Date: Tue, 26 Nov 2024 08:31:36 +0000 Subject: [PATCH 02/10] first draft --- mantidimaging/core/utility/sensible_roi.py | 10 ++- .../gui/windows/spectrum_viewer/model.py | 72 +++++++++---------- .../gui/windows/spectrum_viewer/presenter.py | 9 ++- .../spectrum_viewer/spectrum_widget.py | 11 +++ 4 files changed, 59 insertions(+), 43 deletions(-) diff --git a/mantidimaging/core/utility/sensible_roi.py b/mantidimaging/core/utility/sensible_roi.py index 1ec03aa86c5..9655cee7225 100644 --- a/mantidimaging/core/utility/sensible_roi.py +++ b/mantidimaging/core/utility/sensible_roi.py @@ -13,27 +13,25 @@ @dataclass class SensibleROI(Iterable): - __slots__ = ("left", "top", "right", "bottom", "name") + __slots__ = ("left", "top", "right", "bottom") left: int top: int right: int bottom: int - name: str - def __init__(self, left=0, top=0, right=0, bottom=0, name: str = ""): + def __init__(self, left=0, top=0, right=0, bottom=0): self.left = left self.top = top self.right = right self.bottom = bottom - self.name = name @staticmethod def from_points(position: CloseEnoughPoint, size: CloseEnoughPoint) -> SensibleROI: return SensibleROI(position.x, position.y, position.x + size.x, position.y + size.y) @staticmethod - def from_list(roi: list[int] | list[float], name: str = "") -> SensibleROI: - return SensibleROI(int(roi[0]), int(roi[1]), int(roi[2]), int(roi[3]), name=name) + def from_list(roi: list[int] | list[float]) -> SensibleROI: + return SensibleROI(int(roi[0]), int(roi[1]), int(roi[2]), int(roi[3])) def __iter__(self) -> Iterator[int]: """ diff --git a/mantidimaging/gui/windows/spectrum_viewer/model.py b/mantidimaging/gui/windows/spectrum_viewer/model.py index 1c576d63d53..11aa7083da6 100644 --- a/mantidimaging/gui/windows/spectrum_viewer/model.py +++ b/mantidimaging/gui/windows/spectrum_viewer/model.py @@ -113,17 +113,11 @@ def roi_name_generator(self) -> str: self._roi_id_counter += 1 return new_name - def get_list_of_rois(self) -> list[SensibleROI]: - """ - Returns a list of all ROI objects. - """ - return self._rois - - def add_roi(self, roi: SensibleROI) -> None: + def get_list_of_roi_names(self) -> list[str]: """ - Adds an ROI to the list. + Get a list of rois available in the model """ - self._rois.append(roi) + return list(self._roi_ranges.keys()) def set_stack(self, stack: ImageStack | None) -> None: """ @@ -169,12 +163,6 @@ def get_roi(self, roi_name: str) -> SensibleROI: raise KeyError(f"ROI {roi_name} does not exist in roi_ranges {self._roi_ranges.keys()}") return self._roi_ranges[roi_name] - def get_list_of_roi_names(self) -> list[str]: - """ - Returns the names of all ROIs. - """ - return [roi.name for roi in self._rois] - def get_averaged_image(self) -> np.ndarray | None: """ Get the averaged image from the stack in the model returning as a numpy array @@ -248,14 +236,14 @@ def get_spectrum(self, roi: SensibleROI, mode: SpecType, normalise_with_shutterc return np.array([]) roi_spectrum = self.get_stack_spectrum(self._stack, roi) roi_norm_spectrum = self.get_stack_spectrum(self._normalise_stack, roi) - spectrum = np.divide(roi_spectrum, - roi_norm_spectrum, - out=np.zeros_like(roi_spectrum), - where=roi_norm_spectrum != 0) - if normalise_with_shuttercount: - average_shuttercount = self.get_shuttercount_normalised_correction_parameter() - spectrum = spectrum / average_shuttercount - return spectrum + spectrum = np.divide(roi_spectrum, + roi_norm_spectrum, + out=np.zeros_like(roi_spectrum), + where=roi_norm_spectrum != 0) + if normalise_with_shuttercount: + average_shuttercount = self.get_shuttercount_normalised_correction_parameter() + spectrum = spectrum / average_shuttercount + return spectrum def get_shuttercount_normalised_correction_parameter(self) -> float: """ @@ -337,19 +325,29 @@ def has_stack(self) -> bool: """ return self._stack is not None - def save_csv(self, path: Path, normalise: bool, normalise_with_shuttercount: bool = False) -> None: + def save_csv(self, + path: Path, + rois: dict[str, SensibleROI], + normalise: bool, + normalise_with_shuttercount: bool = False) -> None: """ Iterates over all ROIs and saves the spectrum for each one to a CSV file. - @param path: The path to save the CSV file to. - @param normalise: Whether to save the normalized spectrum. - @param normalise_with_shuttercount: Whether to normalize with the shutter count. + Args: + path (Path): The path to save the CSV file to. + rois (dict[str, SensibleROI]): A dictionary mapping ROI names to SensibleROI objects. + normalise (bool): Whether to save the normalized spectrum. + normalise_with_shuttercount (bool): Whether to normalize using shutter count correction. """ + if self._stack is None: raise ValueError("No stack selected") + if not rois: + raise ValueError("No ROIs provided") csv_output = CSVOutput() csv_output.add_column("ToF_index", np.arange(self._stack.data.shape[0]), "Index") + self.tof_data = self.get_stack_time_of_flight() if self.tof_data is not None: self.units.set_data_to_convert(self.tof_data) @@ -357,20 +355,22 @@ def save_csv(self, path: Path, normalise: bool, normalise_with_shuttercount: boo csv_output.add_column("ToF", self.units.tof_seconds_to_us(), "Microseconds") csv_output.add_column("Energy", self.units.tof_seconds_to_energy(), "MeV") - for roi in self.get_list_of_rois(): - csv_output.add_column(roi.name, self.get_spectrum(roi, SpecType.SAMPLE, normalise_with_shuttercount), - "Counts") + for roi_name, roi in rois.items(): + sample_spectrum = self.get_spectrum(roi, SpecType.SAMPLE, normalise_with_shuttercount) + csv_output.add_column(roi_name, sample_spectrum, "Counts") + if normalise: if self._normalise_stack is None: raise RuntimeError("No normalisation stack selected") - csv_output.add_column(roi.name + "_open", self.get_spectrum(roi, SpecType.OPEN), "Counts") - csv_output.add_column(roi.name + "_norm", - self.get_spectrum(roi, SpecType.SAMPLE_NORMED, normalise_with_shuttercount), - "Counts") - with path.open("w") as outfile: + open_spectrum = self.get_spectrum(roi, SpecType.OPEN) + norm_spectrum = self.get_spectrum(roi, SpecType.SAMPLE_NORMED, normalise_with_shuttercount) + + csv_output.add_column(f"{roi_name}_open", open_spectrum, "Counts") + csv_output.add_column(f"{roi_name}_norm", norm_spectrum, "Counts") + + with path.open("w", encoding="utf-8") as outfile: csv_output.write(outfile) - self.save_roi_coords(self.get_roi_coords_filename(path)) def save_single_rits_spectrum(self, path: Path, error_mode: ErrorMode) -> None: """ diff --git a/mantidimaging/gui/windows/spectrum_viewer/presenter.py b/mantidimaging/gui/windows/spectrum_viewer/presenter.py index ec006899fa5..e4c2603ec70 100644 --- a/mantidimaging/gui/windows/spectrum_viewer/presenter.py +++ b/mantidimaging/gui/windows/spectrum_viewer/presenter.py @@ -270,7 +270,14 @@ def handle_export_csv(self) -> None: if path.suffix != ".csv": path = path.with_suffix(".csv") - self.model.save_csv(path, self.spectrum_mode == SpecType.SAMPLE_NORMED, self.view.shuttercount_norm_enabled()) + rois = { + roi.name: roi.as_sensible_roi() + for roi in self.view.spectrum_widget.roi_dict.values() if isinstance(roi, SpectrumROI)} + + self.model.save_csv(path=path, + rois=rois, + normalise=self.spectrum_mode == SpecType.SAMPLE_NORMED, + normalise_with_shuttercount=self.view.shuttercount_norm_enabled()) def handle_rits_export(self) -> None: """ diff --git a/mantidimaging/gui/windows/spectrum_viewer/spectrum_widget.py b/mantidimaging/gui/windows/spectrum_viewer/spectrum_widget.py index 227bfac29bd..169d042f359 100644 --- a/mantidimaging/gui/windows/spectrum_viewer/spectrum_widget.py +++ b/mantidimaging/gui/windows/spectrum_viewer/spectrum_widget.py @@ -110,6 +110,17 @@ def adjust_spec_roi(self, roi: SensibleROI) -> None: def rename_roi(self, new_name: str) -> None: self._name = new_name + def as_sensible_roi(self) -> SensibleROI: + """ + Converts the SpectrumROI to a SensibleROI object. + """ + pos = self.pos() + size = self.size() + left, top = int(pos.x()), int(pos.y()) + width, height = int(size.width()), int(size.height()) + right = left + width + bottom = top + height + return SensibleROI(left, top, right, bottom) class SpectrumWidget(QWidget): """ From 1f284706e86f9a4a63bbdb16d637fa29ca8ff031 Mon Sep 17 00:00:00 2001 From: ashmeigh Date: Tue, 26 Nov 2024 18:01:24 +0000 Subject: [PATCH 03/10] Added tests --- .../gui/windows/spectrum_viewer/model.py | 2 - .../spectrum_viewer/spectrum_widget.py | 9 ++- .../spectrum_viewer/test/model_test.py | 62 +++++++++++-------- 3 files changed, 41 insertions(+), 32 deletions(-) diff --git a/mantidimaging/gui/windows/spectrum_viewer/model.py b/mantidimaging/gui/windows/spectrum_viewer/model.py index 11aa7083da6..c18a0fd2e11 100644 --- a/mantidimaging/gui/windows/spectrum_viewer/model.py +++ b/mantidimaging/gui/windows/spectrum_viewer/model.py @@ -339,7 +339,6 @@ def save_csv(self, normalise (bool): Whether to save the normalized spectrum. normalise_with_shuttercount (bool): Whether to normalize using shutter count correction. """ - if self._stack is None: raise ValueError("No stack selected") if not rois: @@ -347,7 +346,6 @@ def save_csv(self, csv_output = CSVOutput() csv_output.add_column("ToF_index", np.arange(self._stack.data.shape[0]), "Index") - self.tof_data = self.get_stack_time_of_flight() if self.tof_data is not None: self.units.set_data_to_convert(self.tof_data) diff --git a/mantidimaging/gui/windows/spectrum_viewer/spectrum_widget.py b/mantidimaging/gui/windows/spectrum_viewer/spectrum_widget.py index 169d042f359..ce67e2a753a 100644 --- a/mantidimaging/gui/windows/spectrum_viewer/spectrum_widget.py +++ b/mantidimaging/gui/windows/spectrum_viewer/spectrum_widget.py @@ -114,13 +114,12 @@ def as_sensible_roi(self) -> SensibleROI: """ Converts the SpectrumROI to a SensibleROI object. """ - pos = self.pos() - size = self.size() - left, top = int(pos.x()), int(pos.y()) - width, height = int(size.width()), int(size.height()) + left, top = self.pos + width, height = self.size right = left + width bottom = top + height - return SensibleROI(left, top, right, bottom) + return SensibleROI.from_list([left, top, right, bottom]) + class SpectrumWidget(QWidget): """ diff --git a/mantidimaging/gui/windows/spectrum_viewer/test/model_test.py b/mantidimaging/gui/windows/spectrum_viewer/test/model_test.py index e98f050a498..d9993cf8a4f 100644 --- a/mantidimaging/gui/windows/spectrum_viewer/test/model_test.py +++ b/mantidimaging/gui/windows/spectrum_viewer/test/model_test.py @@ -97,22 +97,20 @@ def test_get_averaged_image_range(self): def test_get_spectrum(self): stack, spectrum = self._set_sample_stack() - - model_spec = self.model.get_spectrum("roi", SpecType.SAMPLE) + roi = SensibleROI(left=0, top=0, right=12, bottom=11) + model_spec = self.model.get_spectrum(roi, SpecType.SAMPLE) self.assertEqual(model_spec.shape, (10, )) npt.assert_array_equal(model_spec, spectrum) def test_get_normalised_spectrum(self): stack, spectrum = self._set_sample_stack() - normalise_stack = ImageStack(np.ones([10, 11, 12]) * 2) self.model.set_normalise_stack(normalise_stack) - - model_open_spec = self.model.get_spectrum("roi", SpecType.OPEN) + roi = SensibleROI(left=0, top=0, right=12, bottom=11) + model_open_spec = self.model.get_spectrum(roi, SpecType.OPEN) self.assertEqual(model_open_spec.shape, (10, )) self.assertTrue(np.all(model_open_spec == 2)) - - model_norm_spec = self.model.get_spectrum("roi", SpecType.SAMPLE_NORMED) + model_norm_spec = self.model.get_spectrum(roi, SpecType.SAMPLE_NORMED) self.assertEqual(model_norm_spec.shape, (10, )) npt.assert_array_equal(model_norm_spec, spectrum / 2) @@ -122,8 +120,8 @@ def test_get_normalised_spectrum_zeros(self): normalise_stack = ImageStack(np.ones([10, 11, 12]) * 2) normalise_stack.data[5] = 0 self.model.set_normalise_stack(normalise_stack) - - model_norm_spec = self.model.get_spectrum("roi", SpecType.SAMPLE_NORMED) + roi = SensibleROI(left=0, top=0, right=12, bottom=11) + model_norm_spec = self.model.get_spectrum(roi, SpecType.SAMPLE_NORMED) expected_spec = spectrum / 2 expected_spec[5] = 0 self.assertEqual(model_norm_spec.shape, (10, )) @@ -134,8 +132,8 @@ def test_get_normalised_spectrum_different_size(self): normalise_stack = ImageStack(np.ones([10, 11, 13])) self.model.set_normalise_stack(normalise_stack) - - error_spectrum = self.model.get_spectrum("all", SpecType.SAMPLE_NORMED) + roi = SensibleROI(left=0, top=0, right=13, bottom=11) + error_spectrum = self.model.get_spectrum(roi, SpecType.SAMPLE_NORMED) np.testing.assert_array_equal(error_spectrum, np.array([])) def test_normalise_issue(self): @@ -168,12 +166,12 @@ def test_get_spectrum_roi(self): stack, spectrum = self._set_sample_stack() stack.data[:, :, 6:] *= 2 - self.model.set_roi('roi', SensibleROI.from_list([0, 0, 3, 3])) - model_spec = self.model.get_spectrum("roi", SpecType.SAMPLE) + roi = SensibleROI.from_list([0, 0, 3, 3]) + model_spec = self.model.get_spectrum(roi, SpecType.SAMPLE) npt.assert_array_equal(model_spec, spectrum) - self.model.set_roi('roi', SensibleROI.from_list([6, 0, 6 + 3, 3])) - model_spec = self.model.get_spectrum("roi", SpecType.SAMPLE) + roi = SensibleROI.from_list([6, 0, 6 + 3, 3]) + model_spec = self.model.get_spectrum(roi, SpecType.SAMPLE) npt.assert_array_equal(model_spec, spectrum * 2) def test_get_stack_spectrum(self): @@ -191,11 +189,15 @@ def test_save_csv(self): stack.data *= 2 self.model.set_normalise_stack(None) + roi_all = SensibleROI.from_list([0, 0, 12, 11]) + roi_specific = SensibleROI.from_list([0, 0, 3, 3]) + rois = {"all": roi_all, "roi": roi_specific} + mock_stream, mock_path = self._make_mock_path_stream() with mock.patch.object(self.model, "save_roi_coords"): - self.model.save_csv(mock_path, False) + self.model.save_csv(mock_path, rois=rois, normalise=False) - mock_path.open.assert_called_once_with("w") + mock_path.open.assert_called_once_with("w", encoding="utf-8") self.assertIn("# ToF_index,all,roi", mock_stream.captured[0]) self.assertIn("# Index,Counts,Counts", mock_stream.captured[1]) self.assertIn("0.0,0.0,0.0", mock_stream.captured[2]) @@ -320,8 +322,12 @@ def test_save_csv_norm_missing_stack(self): stack, _ = self._set_sample_stack() stack.data *= 2 self.model.set_normalise_stack(None) + + roi_all = SensibleROI.from_list([0, 0, 12, 11]) + rois = {"all": roi_all} + with self.assertRaises(RuntimeError): - self.model.save_csv(mock.Mock(), True) + self.model.save_csv(mock.Mock(), rois=rois, normalise=True) def test_save_csv_norm(self): self._set_sample_stack() @@ -329,15 +335,17 @@ def test_save_csv_norm(self): open_stack = ImageStack(np.ones([10, 11, 12]) * 2) self.model.set_normalise_stack(open_stack) + roi_all = SensibleROI.from_list([0, 0, 12, 11]) + roi_specific = SensibleROI.from_list([0, 0, 3, 3]) + rois = {"all": roi_all, "roi": roi_specific} + mock_stream, mock_path = self._make_mock_path_stream() with mock.patch.object(self.model, "save_roi_coords"): - self.model.save_csv(mock_path, True) + self.model.save_csv(path=mock_path, rois=rois, normalise=True, normalise_with_shuttercount=False) - mock_path.open.assert_called_once_with("w") + mock_path.open.assert_called_once_with("w", encoding="utf-8") self.assertIn("# ToF_index,all,all_open,all_norm,roi,roi_open,roi_norm", mock_stream.captured[0]) self.assertIn("# Index,Counts,Counts,Counts,Counts,Counts,Counts", mock_stream.captured[1]) - self.assertIn("0.0,0.0,2.0,0.0,0.0,2.0,0.0", mock_stream.captured[2]) - self.assertIn("1.0,1.0,2.0,0.5,1.0,2.0,0.5", mock_stream.captured[3]) self.assertTrue(mock_stream.is_closed) def test_save_csv_norm_with_tof_loaded(self): @@ -346,17 +354,21 @@ def test_save_csv_norm_with_tof_loaded(self): stack.data[:, :, :5] *= 2 self.model.set_normalise_stack(norm) + roi_all = SensibleROI.from_list([0, 0, 12, 11]) + roi_specific = SensibleROI.from_list([0, 0, 3, 3]) + rois = {"all": roi_all, "roi": roi_specific} + mock_stream, mock_path = self._make_mock_path_stream() with mock.patch.object(self.model, "save_roi_coords"): - self.model.save_csv(mock_path, True) + self.model.save_csv(path=mock_path, rois=rois, normalise=True, normalise_with_shuttercount=False) - mock_path.open.assert_called_once_with("w") + mock_path.open.assert_called_once_with("w", encoding="utf-8") self.assertIn("# ToF_index,Wavelength,ToF,Energy,all,all_open,all_norm,roi,roi_open,roi_norm", mock_stream.captured[0]) self.assertIn("# Index,Angstrom,Microseconds,MeV,Counts,Counts,Counts", mock_stream.captured[1]) self.assertIn("0.0,0.0,0.0,inf,0.0,2.0,0.0,0.0,2.0,0.0", mock_stream.captured[2]) self.assertIn( - "1.0,7.064346392065392,100000.0,2.9271405738026552,1.4166666666666667,2.0,0.7083333333333334,1.4166666666666667,2.0,0.7083333333333334", + "1.0,7.064346392065392,100000.0,2.9271405738026552,1.4166666666666667,2.0,0.7083333333333334,2.0,2.0,1.0", mock_stream.captured[3]) self.assertTrue(mock_stream.is_closed) From d40e09da187798dbdb670044756e6d2a5cce60fa Mon Sep 17 00:00:00 2001 From: ashmeigh Date: Wed, 27 Nov 2024 13:33:12 +0000 Subject: [PATCH 04/10] fixing test --- mantidimaging/gui/windows/spectrum_viewer/presenter.py | 7 ++++--- .../gui/windows/spectrum_viewer/test/presenter_test.py | 4 +++- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/mantidimaging/gui/windows/spectrum_viewer/presenter.py b/mantidimaging/gui/windows/spectrum_viewer/presenter.py index e4c2603ec70..ce3ba47cd9c 100644 --- a/mantidimaging/gui/windows/spectrum_viewer/presenter.py +++ b/mantidimaging/gui/windows/spectrum_viewer/presenter.py @@ -272,10 +272,11 @@ def handle_export_csv(self) -> None: rois = { roi.name: roi.as_sensible_roi() - for roi in self.view.spectrum_widget.roi_dict.values() if isinstance(roi, SpectrumROI)} + for roi in self.view.spectrum_widget.roi_dict.values() if isinstance(roi, SpectrumROI) + } - self.model.save_csv(path=path, - rois=rois, + self.model.save_csv(path, + rois, normalise=self.spectrum_mode == SpecType.SAMPLE_NORMED, normalise_with_shuttercount=self.view.shuttercount_norm_enabled()) diff --git a/mantidimaging/gui/windows/spectrum_viewer/test/presenter_test.py b/mantidimaging/gui/windows/spectrum_viewer/test/presenter_test.py index d6cd7383119..9d043e193b6 100644 --- a/mantidimaging/gui/windows/spectrum_viewer/test/presenter_test.py +++ b/mantidimaging/gui/windows/spectrum_viewer/test/presenter_test.py @@ -211,7 +211,9 @@ def test_handle_export_csv(self, path_name: str, mock_save_csv: mock.Mock, mock_ self.presenter.handle_export_csv() self.view.get_csv_filename.assert_called_once() - mock_save_csv.assert_called_once_with(Path("/fake/path.csv"), False, False) + mock_save_csv.assert_called_once_with(Path("/fake/path.csv"), {}, + normalise=False, + normalise_with_shuttercount=False) @parameterized.expand(["/fake/path", "/fake/path.dat"]) @mock.patch("mantidimaging.gui.windows.spectrum_viewer.model.SpectrumViewerWindowModel.save_rits_roi") From 70a583fb24a00f922f433f5b73ff2101f8409c79 Mon Sep 17 00:00:00 2001 From: ashmeigh Date: Wed, 27 Nov 2024 15:55:42 +0000 Subject: [PATCH 05/10] fixing changes --- .../gui/windows/spectrum_viewer/model.py | 3 +- .../gui/windows/spectrum_viewer/presenter.py | 17 +++++------ .../spectrum_viewer/spectrum_widget.py | 6 ++-- .../spectrum_viewer/test/model_test.py | 6 ++-- .../spectrum_viewer/test/presenter_test.py | 29 +++++++++++++++---- 5 files changed, 40 insertions(+), 21 deletions(-) diff --git a/mantidimaging/gui/windows/spectrum_viewer/model.py b/mantidimaging/gui/windows/spectrum_viewer/model.py index c18a0fd2e11..fdc630877d4 100644 --- a/mantidimaging/gui/windows/spectrum_viewer/model.py +++ b/mantidimaging/gui/windows/spectrum_viewer/model.py @@ -99,7 +99,6 @@ def __init__(self, presenter: SpectrumViewerWindowPresenter): self._roi_id_counter = 0 self._roi_ranges = {} self.special_roi_list = [ROI_ALL] - self._rois: list[SensibleROI] = [] self.units = UnitConversion() @@ -367,7 +366,7 @@ def save_csv(self, csv_output.add_column(f"{roi_name}_open", open_spectrum, "Counts") csv_output.add_column(f"{roi_name}_norm", norm_spectrum, "Counts") - with path.open("w", encoding="utf-8") as outfile: + with path.open("w") as outfile: csv_output.write(outfile) def save_single_rits_spectrum(self, path: Path, error_mode: ErrorMode) -> None: diff --git a/mantidimaging/gui/windows/spectrum_viewer/presenter.py b/mantidimaging/gui/windows/spectrum_viewer/presenter.py index ce3ba47cd9c..25767415528 100644 --- a/mantidimaging/gui/windows/spectrum_viewer/presenter.py +++ b/mantidimaging/gui/windows/spectrum_viewer/presenter.py @@ -270,15 +270,14 @@ def handle_export_csv(self) -> None: if path.suffix != ".csv": path = path.with_suffix(".csv") - rois = { - roi.name: roi.as_sensible_roi() - for roi in self.view.spectrum_widget.roi_dict.values() if isinstance(roi, SpectrumROI) - } - - self.model.save_csv(path, - rois, - normalise=self.spectrum_mode == SpecType.SAMPLE_NORMED, - normalise_with_shuttercount=self.view.shuttercount_norm_enabled()) + rois = {roi.name: roi.as_sensible_roi() for roi in self.view.spectrum_widget.roi_dict.values()} + + self.model.save_csv( + path=path, + rois=rois, + normalise=self.spectrum_mode == SpecType.SAMPLE_NORMED, + normalise_with_shuttercount=self.view.shuttercount_norm_enabled(), + ) def handle_rits_export(self) -> None: """ diff --git a/mantidimaging/gui/windows/spectrum_viewer/spectrum_widget.py b/mantidimaging/gui/windows/spectrum_viewer/spectrum_widget.py index ce67e2a753a..72a30206038 100644 --- a/mantidimaging/gui/windows/spectrum_viewer/spectrum_widget.py +++ b/mantidimaging/gui/windows/spectrum_viewer/spectrum_widget.py @@ -114,8 +114,10 @@ def as_sensible_roi(self) -> SensibleROI: """ Converts the SpectrumROI to a SensibleROI object. """ - left, top = self.pos - width, height = self.size + pos = self.pos() + size = self.size() + left, top = pos + width, height = size right = left + width bottom = top + height return SensibleROI.from_list([left, top, right, bottom]) diff --git a/mantidimaging/gui/windows/spectrum_viewer/test/model_test.py b/mantidimaging/gui/windows/spectrum_viewer/test/model_test.py index d9993cf8a4f..fa4f2072c08 100644 --- a/mantidimaging/gui/windows/spectrum_viewer/test/model_test.py +++ b/mantidimaging/gui/windows/spectrum_viewer/test/model_test.py @@ -197,7 +197,7 @@ def test_save_csv(self): with mock.patch.object(self.model, "save_roi_coords"): self.model.save_csv(mock_path, rois=rois, normalise=False) - mock_path.open.assert_called_once_with("w", encoding="utf-8") + mock_path.open.assert_called_once_with("w") self.assertIn("# ToF_index,all,roi", mock_stream.captured[0]) self.assertIn("# Index,Counts,Counts", mock_stream.captured[1]) self.assertIn("0.0,0.0,0.0", mock_stream.captured[2]) @@ -343,7 +343,7 @@ def test_save_csv_norm(self): with mock.patch.object(self.model, "save_roi_coords"): self.model.save_csv(path=mock_path, rois=rois, normalise=True, normalise_with_shuttercount=False) - mock_path.open.assert_called_once_with("w", encoding="utf-8") + mock_path.open.assert_called_once_with("w") self.assertIn("# ToF_index,all,all_open,all_norm,roi,roi_open,roi_norm", mock_stream.captured[0]) self.assertIn("# Index,Counts,Counts,Counts,Counts,Counts,Counts", mock_stream.captured[1]) self.assertTrue(mock_stream.is_closed) @@ -362,7 +362,7 @@ def test_save_csv_norm_with_tof_loaded(self): with mock.patch.object(self.model, "save_roi_coords"): self.model.save_csv(path=mock_path, rois=rois, normalise=True, normalise_with_shuttercount=False) - mock_path.open.assert_called_once_with("w", encoding="utf-8") + mock_path.open.assert_called_once_with("w") self.assertIn("# ToF_index,Wavelength,ToF,Energy,all,all_open,all_norm,roi,roi_open,roi_norm", mock_stream.captured[0]) self.assertIn("# Index,Angstrom,Microseconds,MeV,Counts,Counts,Counts", mock_stream.captured[1]) diff --git a/mantidimaging/gui/windows/spectrum_viewer/test/presenter_test.py b/mantidimaging/gui/windows/spectrum_viewer/test/presenter_test.py index 9d043e193b6..000974c7ae6 100644 --- a/mantidimaging/gui/windows/spectrum_viewer/test/presenter_test.py +++ b/mantidimaging/gui/windows/spectrum_viewer/test/presenter_test.py @@ -201,19 +201,38 @@ def test_handle_export_csv_none(self, mock_save_csv: mock.Mock): @parameterized.expand(["/fake/path", "/fake/path.csv"]) @mock.patch("mantidimaging.gui.windows.spectrum_viewer.model.SpectrumViewerWindowModel.shuttercount_issue") @mock.patch("mantidimaging.gui.windows.spectrum_viewer.model.SpectrumViewerWindowModel.save_csv") - def test_handle_export_csv(self, path_name: str, mock_save_csv: mock.Mock, mock_shuttercount_issue): + def test_handle_export_csv(self, path_name: str, mock_save_csv: mock.Mock, mock_shuttercount_issue: mock.Mock): self.view.get_csv_filename = mock.Mock(return_value=Path(path_name)) self.view.shuttercount_norm_enabled.return_value = False mock_shuttercount_issue.return_value = "Something wrong" self.presenter.model.set_stack(generate_images()) + roi_all = SensibleROI.from_list([0, 0, 12, 11]) + roi_specific = SensibleROI.from_list([0, 0, 3, 3]) + mock_roi_all = mock.Mock(spec=SpectrumROI, name="ROI_ALL", as_sensible_roi=mock.Mock(return_value=roi_all)) + mock_roi_all.name = "all" + mock_roi_specific = mock.Mock(spec=SpectrumROI, + name="ROI_SPECIFIC", + as_sensible_roi=mock.Mock(return_value=roi_specific)) + mock_roi_specific.name = "roi" + + self.view.spectrum_widget.roi_dict = { + "all": mock_roi_all, + "roi": mock_roi_specific, + } self.presenter.handle_export_csv() - self.view.get_csv_filename.assert_called_once() - mock_save_csv.assert_called_once_with(Path("/fake/path.csv"), {}, - normalise=False, - normalise_with_shuttercount=False) + expected_rois = { + "all": roi_all, + "roi": roi_specific, + } + mock_save_csv.assert_called_once_with( + path=Path("/fake/path.csv"), + rois=expected_rois, + normalise=False, + normalise_with_shuttercount=False, + ) @parameterized.expand(["/fake/path", "/fake/path.dat"]) @mock.patch("mantidimaging.gui.windows.spectrum_viewer.model.SpectrumViewerWindowModel.save_rits_roi") From f04592f641043e1b6d2fc67d9f0d96bcb1563952 Mon Sep 17 00:00:00 2001 From: ashmeigh Date: Thu, 28 Nov 2024 09:21:55 +0000 Subject: [PATCH 06/10] clean up of code --- .../gui/windows/spectrum_viewer/model.py | 26 ++++++------- .../gui/windows/spectrum_viewer/presenter.py | 39 ++++++++----------- .../spectrum_viewer/test/model_test.py | 16 ++++---- .../spectrum_viewer/test/presenter_test.py | 31 +++------------ 4 files changed, 42 insertions(+), 70 deletions(-) diff --git a/mantidimaging/gui/windows/spectrum_viewer/model.py b/mantidimaging/gui/windows/spectrum_viewer/model.py index fdc630877d4..79c657e07bb 100644 --- a/mantidimaging/gui/windows/spectrum_viewer/model.py +++ b/mantidimaging/gui/windows/spectrum_viewer/model.py @@ -331,12 +331,9 @@ def save_csv(self, normalise_with_shuttercount: bool = False) -> None: """ Iterates over all ROIs and saves the spectrum for each one to a CSV file. + @param path: The path to save the CSV file to. + @param normalized: Whether to save the normalized spectrum. - Args: - path (Path): The path to save the CSV file to. - rois (dict[str, SensibleROI]): A dictionary mapping ROI names to SensibleROI objects. - normalise (bool): Whether to save the normalized spectrum. - normalise_with_shuttercount (bool): Whether to normalize using shutter count correction. """ if self._stack is None: raise ValueError("No stack selected") @@ -345,6 +342,7 @@ def save_csv(self, csv_output = CSVOutput() csv_output.add_column("ToF_index", np.arange(self._stack.data.shape[0]), "Index") + self.tof_data = self.get_stack_time_of_flight() if self.tof_data is not None: self.units.set_data_to_convert(self.tof_data) @@ -353,22 +351,22 @@ def save_csv(self, csv_output.add_column("Energy", self.units.tof_seconds_to_energy(), "MeV") for roi_name, roi in rois.items(): - sample_spectrum = self.get_spectrum(roi, SpecType.SAMPLE, normalise_with_shuttercount) - csv_output.add_column(roi_name, sample_spectrum, "Counts") + csv_output.add_column(roi_name, self.get_spectrum(roi, SpecType.SAMPLE, normalise_with_shuttercount), + "Counts") if normalise: if self._normalise_stack is None: raise RuntimeError("No normalisation stack selected") - - open_spectrum = self.get_spectrum(roi, SpecType.OPEN) - norm_spectrum = self.get_spectrum(roi, SpecType.SAMPLE_NORMED, normalise_with_shuttercount) - - csv_output.add_column(f"{roi_name}_open", open_spectrum, "Counts") - csv_output.add_column(f"{roi_name}_norm", norm_spectrum, "Counts") - + csv_output.add_column(f"{roi_name}_open", self.get_spectrum(roi, SpecType.OPEN), "Counts") + csv_output.add_column(f"{roi_name}_norm", + self.get_spectrum(roi, SpecType.SAMPLE_NORMED, normalise_with_shuttercount), + "Counts") with path.open("w") as outfile: csv_output.write(outfile) + roi_coords_filename = self.get_roi_coords_filename(path) + self.save_roi_coords(roi_coords_filename) + def save_single_rits_spectrum(self, path: Path, error_mode: ErrorMode) -> None: """ Saves the spectrum for the RITS ROI to a RITS file. diff --git a/mantidimaging/gui/windows/spectrum_viewer/presenter.py b/mantidimaging/gui/windows/spectrum_viewer/presenter.py index 25767415528..fd491bee306 100644 --- a/mantidimaging/gui/windows/spectrum_viewer/presenter.py +++ b/mantidimaging/gui/windows/spectrum_viewer/presenter.py @@ -200,20 +200,16 @@ def handle_roi_moved(self, force_new_spectrums: bool = False) -> None: """ Handle changes to any ROI position and size. """ - roi_names = self.model.get_list_of_roi_names() - - for name in roi_names: + for name in self.model.get_list_of_roi_names(): view_roi = self.view.spectrum_widget.get_roi(name) - model_roi = self.model.get_roi(name) - - if force_new_spectrums or view_roi != model_roi: + if force_new_spectrums or view_roi != self.model.get_roi(name): self.model.set_roi(name, view_roi) - updated_spectrum = self.model.get_spectrum( + spectrum = self.model.get_spectrum( view_roi, self.spectrum_mode, normalise_with_shuttercount=self.view.shuttercount_norm_enabled(), ) - self.view.set_spectrum(name, updated_spectrum) + self.view.set_spectrum(name, spectrum) def handle_roi_clicked(self, roi: SpectrumROI) -> None: if not roi.name == ROI_RITS: @@ -266,18 +262,18 @@ def handle_export_csv(self) -> None: path = self.view.get_csv_filename() if path is None: return - if path.suffix != ".csv": path = path.with_suffix(".csv") - rois = {roi.name: roi.as_sensible_roi() for roi in self.view.spectrum_widget.roi_dict.values()} + rois = { + roi.name: roi.as_sensible_roi() + for roi in self.view.spectrum_widget.roi_dict.values() if isinstance(roi, SpectrumROI) + } - self.model.save_csv( - path=path, - rois=rois, - normalise=self.spectrum_mode == SpecType.SAMPLE_NORMED, - normalise_with_shuttercount=self.view.shuttercount_norm_enabled(), - ) + self.model.save_csv(path, + rois, + normalise=self.spectrum_mode == SpecType.SAMPLE_NORMED, + normalise_with_shuttercount=self.view.shuttercount_norm_enabled()) def handle_rits_export(self) -> None: """ @@ -367,12 +363,11 @@ def change_roi_colour(self, roi_name: str, new_colour: tuple[int, int, int]) -> self.view.on_visibility_change() def add_rits_roi(self) -> None: - roi_name = ROI_RITS - self.model.set_new_roi(roi_name) - roi = self.model.get_roi(roi_name) - self.view.spectrum_widget.add_roi(roi, roi_name) - spectrum = self.model.get_spectrum(roi, self.spectrum_mode, self.view.shuttercount_norm_enabled()) - self.view.set_spectrum(roi_name, spectrum) + self.model.set_new_roi(ROI_RITS) + roi = self.model.get_roi(ROI_RITS) + self.view.spectrum_widget.add_roi(roi, ROI_RITS) + self.view.set_spectrum(ROI_RITS, + self.model.get_spectrum(roi, self.spectrum_mode, self.view.shuttercount_norm_enabled())) self.view.set_roi_visibility_flags(ROI_RITS, visible=False) def do_add_roi_to_table(self, roi_name: str) -> None: diff --git a/mantidimaging/gui/windows/spectrum_viewer/test/model_test.py b/mantidimaging/gui/windows/spectrum_viewer/test/model_test.py index fa4f2072c08..debe030d328 100644 --- a/mantidimaging/gui/windows/spectrum_viewer/test/model_test.py +++ b/mantidimaging/gui/windows/spectrum_viewer/test/model_test.py @@ -346,6 +346,8 @@ def test_save_csv_norm(self): mock_path.open.assert_called_once_with("w") self.assertIn("# ToF_index,all,all_open,all_norm,roi,roi_open,roi_norm", mock_stream.captured[0]) self.assertIn("# Index,Counts,Counts,Counts,Counts,Counts,Counts", mock_stream.captured[1]) + self.assertIn("0.0,0.0,2.0,0.0,0.0,2.0,0.0", mock_stream.captured[2]) + self.assertIn("1.0,1.0,2.0,0.5,1.0,2.0,0.5", mock_stream.captured[3]) self.assertTrue(mock_stream.is_closed) def test_save_csv_norm_with_tof_loaded(self): @@ -354,22 +356,20 @@ def test_save_csv_norm_with_tof_loaded(self): stack.data[:, :, :5] *= 2 self.model.set_normalise_stack(norm) - roi_all = SensibleROI.from_list([0, 0, 12, 11]) - roi_specific = SensibleROI.from_list([0, 0, 3, 3]) - rois = {"all": roi_all, "roi": roi_specific} + roi = SensibleROI.from_list([0, 0, 12, 11]) + rois = {"single_roi": roi} mock_stream, mock_path = self._make_mock_path_stream() with mock.patch.object(self.model, "save_roi_coords"): self.model.save_csv(path=mock_path, rois=rois, normalise=True, normalise_with_shuttercount=False) mock_path.open.assert_called_once_with("w") - self.assertIn("# ToF_index,Wavelength,ToF,Energy,all,all_open,all_norm,roi,roi_open,roi_norm", + self.assertIn("# ToF_index,Wavelength,ToF,Energy,single_roi,single_roi_open,single_roi_norm", mock_stream.captured[0]) self.assertIn("# Index,Angstrom,Microseconds,MeV,Counts,Counts,Counts", mock_stream.captured[1]) - self.assertIn("0.0,0.0,0.0,inf,0.0,2.0,0.0,0.0,2.0,0.0", mock_stream.captured[2]) - self.assertIn( - "1.0,7.064346392065392,100000.0,2.9271405738026552,1.4166666666666667,2.0,0.7083333333333334,2.0,2.0,1.0", - mock_stream.captured[3]) + self.assertIn("0.0,0.0,0.0,inf,0.0,2.0,0.0", mock_stream.captured[2]) + self.assertIn("1.0,7.064346392065392,100000.0,2.9271405738026552,1.4166666666666667,2.0,0.7083333333333334", + mock_stream.captured[3]) self.assertTrue(mock_stream.is_closed) def test_WHEN_roi_name_generator_called_THEN_correct_names_returned_visible_to_model(self): diff --git a/mantidimaging/gui/windows/spectrum_viewer/test/presenter_test.py b/mantidimaging/gui/windows/spectrum_viewer/test/presenter_test.py index 000974c7ae6..a1257406bdb 100644 --- a/mantidimaging/gui/windows/spectrum_viewer/test/presenter_test.py +++ b/mantidimaging/gui/windows/spectrum_viewer/test/presenter_test.py @@ -201,38 +201,17 @@ def test_handle_export_csv_none(self, mock_save_csv: mock.Mock): @parameterized.expand(["/fake/path", "/fake/path.csv"]) @mock.patch("mantidimaging.gui.windows.spectrum_viewer.model.SpectrumViewerWindowModel.shuttercount_issue") @mock.patch("mantidimaging.gui.windows.spectrum_viewer.model.SpectrumViewerWindowModel.save_csv") - def test_handle_export_csv(self, path_name: str, mock_save_csv: mock.Mock, mock_shuttercount_issue: mock.Mock): + def test_handle_export_csv(self, path_name: str, mock_save_csv: mock.Mock, mock_shuttercount_issue): self.view.get_csv_filename = mock.Mock(return_value=Path(path_name)) self.view.shuttercount_norm_enabled.return_value = False mock_shuttercount_issue.return_value = "Something wrong" - self.presenter.model.set_stack(generate_images()) - roi_all = SensibleROI.from_list([0, 0, 12, 11]) - roi_specific = SensibleROI.from_list([0, 0, 3, 3]) - mock_roi_all = mock.Mock(spec=SpectrumROI, name="ROI_ALL", as_sensible_roi=mock.Mock(return_value=roi_all)) - mock_roi_all.name = "all" - mock_roi_specific = mock.Mock(spec=SpectrumROI, - name="ROI_SPECIFIC", - as_sensible_roi=mock.Mock(return_value=roi_specific)) - mock_roi_specific.name = "roi" - - self.view.spectrum_widget.roi_dict = { - "all": mock_roi_all, - "roi": mock_roi_specific, - } - self.presenter.handle_export_csv() + self.view.get_csv_filename.assert_called_once() - expected_rois = { - "all": roi_all, - "roi": roi_specific, - } - mock_save_csv.assert_called_once_with( - path=Path("/fake/path.csv"), - rois=expected_rois, - normalise=False, - normalise_with_shuttercount=False, - ) + mock_save_csv.assert_called_once_with(Path("/fake/path.csv"), {}, + normalise=False, + normalise_with_shuttercount=False) @parameterized.expand(["/fake/path", "/fake/path.dat"]) @mock.patch("mantidimaging.gui.windows.spectrum_viewer.model.SpectrumViewerWindowModel.save_rits_roi") From 22ff8bba028f0aa7e0bbde49971ca8f364d4da99 Mon Sep 17 00:00:00 2001 From: ashmeigh Date: Thu, 28 Nov 2024 09:53:06 +0000 Subject: [PATCH 07/10] changes to test remove further code --- .../gui/windows/spectrum_viewer/model.py | 6 ++--- .../gui/windows/spectrum_viewer/presenter.py | 22 ++++++++----------- .../spectrum_viewer/test/model_test.py | 15 +++++++------ 3 files changed, 19 insertions(+), 24 deletions(-) diff --git a/mantidimaging/gui/windows/spectrum_viewer/model.py b/mantidimaging/gui/windows/spectrum_viewer/model.py index 79c657e07bb..b288703aa4f 100644 --- a/mantidimaging/gui/windows/spectrum_viewer/model.py +++ b/mantidimaging/gui/windows/spectrum_viewer/model.py @@ -363,9 +363,7 @@ def save_csv(self, "Counts") with path.open("w") as outfile: csv_output.write(outfile) - - roi_coords_filename = self.get_roi_coords_filename(path) - self.save_roi_coords(roi_coords_filename) + self.save_roi_coords(self.get_roi_coords_filename(path)) def save_single_rits_spectrum(self, path: Path, error_mode: ErrorMode) -> None: """ @@ -585,4 +583,4 @@ def set_tof_unit_mode_for_stack(self) -> None: self.presenter.change_selected_menu_option("Time of Flight (\u03BCs)") else: self.tof_mode = ToFUnitMode.WAVELENGTH - self.presenter.change_selected_menu_option("Wavelength") + self.presenter.change_selected_menu_option("Wavelength") \ No newline at end of file diff --git a/mantidimaging/gui/windows/spectrum_viewer/presenter.py b/mantidimaging/gui/windows/spectrum_viewer/presenter.py index fd491bee306..68c2cf3d54c 100644 --- a/mantidimaging/gui/windows/spectrum_viewer/presenter.py +++ b/mantidimaging/gui/windows/spectrum_viewer/presenter.py @@ -260,20 +260,16 @@ def handle_button_enabled(self) -> None: def handle_export_csv(self) -> None: path = self.view.get_csv_filename() - if path is None: + if not path: return - if path.suffix != ".csv": - path = path.with_suffix(".csv") + path = path.with_suffix(".csv") if path.suffix != ".csv" else path + rois = {roi.name: roi.as_sensible_roi() for roi in self.view.spectrum_widget.roi_dict.values()} - rois = { - roi.name: roi.as_sensible_roi() - for roi in self.view.spectrum_widget.roi_dict.values() if isinstance(roi, SpectrumROI) - } - - self.model.save_csv(path, - rois, - normalise=self.spectrum_mode == SpecType.SAMPLE_NORMED, - normalise_with_shuttercount=self.view.shuttercount_norm_enabled()) + self.model.save_csv( + path, + rois, + normalise=self.spectrum_mode == SpecType.SAMPLE_NORMED, + normalise_with_shuttercount=self.view.shuttercount_norm_enabled(),) def handle_rits_export(self) -> None: """ @@ -476,4 +472,4 @@ def check_action(action: QAction, param: bool) -> None: def convert_spinbox_roi_to_SensibleROI(self, spinboxes: dict[str, QSpinBox]) -> SensibleROI: roi_iter_order = ["Left", "Top", "Right", "Bottom"] new_points = [spinboxes[prop].value() for prop in roi_iter_order] - return SensibleROI.from_list(new_points) + return SensibleROI.from_list(new_points) \ No newline at end of file diff --git a/mantidimaging/gui/windows/spectrum_viewer/test/model_test.py b/mantidimaging/gui/windows/spectrum_viewer/test/model_test.py index debe030d328..355a7bd4d5b 100644 --- a/mantidimaging/gui/windows/spectrum_viewer/test/model_test.py +++ b/mantidimaging/gui/windows/spectrum_viewer/test/model_test.py @@ -356,20 +356,21 @@ def test_save_csv_norm_with_tof_loaded(self): stack.data[:, :, :5] *= 2 self.model.set_normalise_stack(norm) - roi = SensibleROI.from_list([0, 0, 12, 11]) - rois = {"single_roi": roi} + roi_all = SensibleROI.from_list([0, 0, 12, 11]) # Define an ROI + rois = {"all": roi_all} # Provide ROIs to the method mock_stream, mock_path = self._make_mock_path_stream() with mock.patch.object(self.model, "save_roi_coords"): - self.model.save_csv(path=mock_path, rois=rois, normalise=True, normalise_with_shuttercount=False) + self.model.save_csv(mock_path, rois=rois, normalise=True, normalise_with_shuttercount=False) mock_path.open.assert_called_once_with("w") - self.assertIn("# ToF_index,Wavelength,ToF,Energy,single_roi,single_roi_open,single_roi_norm", - mock_stream.captured[0]) + self.assertIn("# ToF_index,Wavelength,ToF,Energy,all,all_open,all_norm", mock_stream.captured[0]) self.assertIn("# Index,Angstrom,Microseconds,MeV,Counts,Counts,Counts", mock_stream.captured[1]) self.assertIn("0.0,0.0,0.0,inf,0.0,2.0,0.0", mock_stream.captured[2]) - self.assertIn("1.0,7.064346392065392,100000.0,2.9271405738026552,1.4166666666666667,2.0,0.7083333333333334", - mock_stream.captured[3]) + self.assertIn( + "1.0,7.064346392065392,100000.0,2.9271405738026552,1.4166666666666667,2.0,0.7083333333333334", + mock_stream.captured[3] + ) self.assertTrue(mock_stream.is_closed) def test_WHEN_roi_name_generator_called_THEN_correct_names_returned_visible_to_model(self): From 828a98e2e242137ded848e335c7af86c4a1017aa Mon Sep 17 00:00:00 2001 From: ashmeigh Date: Thu, 28 Nov 2024 10:34:27 +0000 Subject: [PATCH 08/10] fixing yapf --- mantidimaging/gui/windows/spectrum_viewer/model.py | 2 +- mantidimaging/gui/windows/spectrum_viewer/presenter.py | 5 +++-- .../gui/windows/spectrum_viewer/test/model_test.py | 6 ++---- 3 files changed, 6 insertions(+), 7 deletions(-) diff --git a/mantidimaging/gui/windows/spectrum_viewer/model.py b/mantidimaging/gui/windows/spectrum_viewer/model.py index b288703aa4f..952b26df072 100644 --- a/mantidimaging/gui/windows/spectrum_viewer/model.py +++ b/mantidimaging/gui/windows/spectrum_viewer/model.py @@ -583,4 +583,4 @@ def set_tof_unit_mode_for_stack(self) -> None: self.presenter.change_selected_menu_option("Time of Flight (\u03BCs)") else: self.tof_mode = ToFUnitMode.WAVELENGTH - self.presenter.change_selected_menu_option("Wavelength") \ No newline at end of file + self.presenter.change_selected_menu_option("Wavelength") diff --git a/mantidimaging/gui/windows/spectrum_viewer/presenter.py b/mantidimaging/gui/windows/spectrum_viewer/presenter.py index 68c2cf3d54c..99ef0c83027 100644 --- a/mantidimaging/gui/windows/spectrum_viewer/presenter.py +++ b/mantidimaging/gui/windows/spectrum_viewer/presenter.py @@ -269,7 +269,8 @@ def handle_export_csv(self) -> None: path, rois, normalise=self.spectrum_mode == SpecType.SAMPLE_NORMED, - normalise_with_shuttercount=self.view.shuttercount_norm_enabled(),) + normalise_with_shuttercount=self.view.shuttercount_norm_enabled(), + ) def handle_rits_export(self) -> None: """ @@ -472,4 +473,4 @@ def check_action(action: QAction, param: bool) -> None: def convert_spinbox_roi_to_SensibleROI(self, spinboxes: dict[str, QSpinBox]) -> SensibleROI: roi_iter_order = ["Left", "Top", "Right", "Bottom"] new_points = [spinboxes[prop].value() for prop in roi_iter_order] - return SensibleROI.from_list(new_points) \ No newline at end of file + return SensibleROI.from_list(new_points) diff --git a/mantidimaging/gui/windows/spectrum_viewer/test/model_test.py b/mantidimaging/gui/windows/spectrum_viewer/test/model_test.py index 355a7bd4d5b..86fa5103293 100644 --- a/mantidimaging/gui/windows/spectrum_viewer/test/model_test.py +++ b/mantidimaging/gui/windows/spectrum_viewer/test/model_test.py @@ -367,10 +367,8 @@ def test_save_csv_norm_with_tof_loaded(self): self.assertIn("# ToF_index,Wavelength,ToF,Energy,all,all_open,all_norm", mock_stream.captured[0]) self.assertIn("# Index,Angstrom,Microseconds,MeV,Counts,Counts,Counts", mock_stream.captured[1]) self.assertIn("0.0,0.0,0.0,inf,0.0,2.0,0.0", mock_stream.captured[2]) - self.assertIn( - "1.0,7.064346392065392,100000.0,2.9271405738026552,1.4166666666666667,2.0,0.7083333333333334", - mock_stream.captured[3] - ) + self.assertIn("1.0,7.064346392065392,100000.0,2.9271405738026552,1.4166666666666667,2.0,0.7083333333333334", + mock_stream.captured[3]) self.assertTrue(mock_stream.is_closed) def test_WHEN_roi_name_generator_called_THEN_correct_names_returned_visible_to_model(self): From e4f8aee9415db6a086f4a350172bffa2dc0e5dc0 Mon Sep 17 00:00:00 2001 From: ashmeigh Date: Thu, 28 Nov 2024 11:02:56 +0000 Subject: [PATCH 09/10] add test --- mantidimaging/gui/windows/spectrum_viewer/test/model_test.py | 4 ++-- .../gui/windows/spectrum_viewer/test/spectrum_test.py | 5 +++++ 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/mantidimaging/gui/windows/spectrum_viewer/test/model_test.py b/mantidimaging/gui/windows/spectrum_viewer/test/model_test.py index 86fa5103293..cf7edf888a4 100644 --- a/mantidimaging/gui/windows/spectrum_viewer/test/model_test.py +++ b/mantidimaging/gui/windows/spectrum_viewer/test/model_test.py @@ -356,8 +356,8 @@ def test_save_csv_norm_with_tof_loaded(self): stack.data[:, :, :5] *= 2 self.model.set_normalise_stack(norm) - roi_all = SensibleROI.from_list([0, 0, 12, 11]) # Define an ROI - rois = {"all": roi_all} # Provide ROIs to the method + roi_all = SensibleROI.from_list([0, 0, 12, 11]) + rois = {"all": roi_all} mock_stream, mock_path = self._make_mock_path_stream() with mock.patch.object(self.model, "save_roi_coords"): diff --git a/mantidimaging/gui/windows/spectrum_viewer/test/spectrum_test.py b/mantidimaging/gui/windows/spectrum_viewer/test/spectrum_test.py index 65b3add07a9..fee63dbf2a7 100644 --- a/mantidimaging/gui/windows/spectrum_viewer/test/spectrum_test.py +++ b/mantidimaging/gui/windows/spectrum_viewer/test/spectrum_test.py @@ -42,6 +42,11 @@ def test_WHEN_colour_is_not_valid_THEN_roi_colour_is_unchanged(self): self.spectrum_roi.onChangeColor() self.assertEqual(self.spectrum_roi.colour, (0, 0, 0, 255)) + def test_WHEN_as_sensible_roi_called_THEN_correct_sensible_roi_returned(self): + sensible_roi = self.spectrum_roi.as_sensible_roi() + self.assertEqual((sensible_roi.left, sensible_roi.top, sensible_roi.right, sensible_roi.bottom), + (10, 20, 30, 40)) + @mock_versions @start_qapplication From 5312953811401472568e59001b3828f6fd23f945 Mon Sep 17 00:00:00 2001 From: ashmeigh Date: Thu, 28 Nov 2024 16:10:53 +0000 Subject: [PATCH 10/10] fixed test --- .../gui/windows/spectrum_viewer/test/model_test.py | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/mantidimaging/gui/windows/spectrum_viewer/test/model_test.py b/mantidimaging/gui/windows/spectrum_viewer/test/model_test.py index cf7edf888a4..75ec40cdfc6 100644 --- a/mantidimaging/gui/windows/spectrum_viewer/test/model_test.py +++ b/mantidimaging/gui/windows/spectrum_viewer/test/model_test.py @@ -357,18 +357,20 @@ def test_save_csv_norm_with_tof_loaded(self): self.model.set_normalise_stack(norm) roi_all = SensibleROI.from_list([0, 0, 12, 11]) - rois = {"all": roi_all} + rois = {"all": roi_all, "roi": roi_all} mock_stream, mock_path = self._make_mock_path_stream() with mock.patch.object(self.model, "save_roi_coords"): self.model.save_csv(mock_path, rois=rois, normalise=True, normalise_with_shuttercount=False) mock_path.open.assert_called_once_with("w") - self.assertIn("# ToF_index,Wavelength,ToF,Energy,all,all_open,all_norm", mock_stream.captured[0]) + self.assertIn("# ToF_index,Wavelength,ToF,Energy,all,all_open,all_norm,roi,roi_open,roi_norm", + mock_stream.captured[0]) self.assertIn("# Index,Angstrom,Microseconds,MeV,Counts,Counts,Counts", mock_stream.captured[1]) - self.assertIn("0.0,0.0,0.0,inf,0.0,2.0,0.0", mock_stream.captured[2]) - self.assertIn("1.0,7.064346392065392,100000.0,2.9271405738026552,1.4166666666666667,2.0,0.7083333333333334", - mock_stream.captured[3]) + self.assertIn("0.0,0.0,0.0,inf,0.0,2.0,0.0,0.0,2.0,0.0", mock_stream.captured[2]) + self.assertIn( + "1.0,7.064346392065392,100000.0,2.9271405738026552,1.4166666666666667,2.0,0.7083333333333334,1.4166666666666667,2.0,0.7083333333333334", + mock_stream.captured[3]) self.assertTrue(mock_stream.is_closed) def test_WHEN_roi_name_generator_called_THEN_correct_names_returned_visible_to_model(self):