From fe0933eb60ba1465f5b457c0d6adc635b90dc372 Mon Sep 17 00:00:00 2001 From: Sam Tygier Date: Tue, 13 Aug 2024 17:40:04 +0100 Subject: [PATCH 1/6] When replacing a sample in a dataset, delete the 180 proj --- mantidimaging/gui/windows/main/presenter.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/mantidimaging/gui/windows/main/presenter.py b/mantidimaging/gui/windows/main/presenter.py index 1c5e3296d0d..eab59856124 100644 --- a/mantidimaging/gui/windows/main/presenter.py +++ b/mantidimaging/gui/windows/main/presenter.py @@ -792,6 +792,9 @@ def _add_images_to_existing_strict_dataset(self, dataset: StrictDataset, new_ima else: # the image type already exists in the dataset and needs to be replaced prev_images_id = getattr(dataset, image_attr).id + if image_attr == "sample" and dataset.proj180deg: + self._delete_stack(dataset.proj180deg.id) + self.remove_item_from_tree_view(dataset.proj180deg.id) self.replace_child_item_id(dataset.id, prev_images_id, new_images.id) self._delete_stack(prev_images_id) From 6a5af516d8082335c8ed59dcdf8ae127bbbc206e Mon Sep 17 00:00:00 2001 From: Sam Tygier Date: Tue, 13 Aug 2024 17:42:36 +0100 Subject: [PATCH 2/6] MainWindowModel: Restore load_image_stack method, needed by AddImagesToDatasetDialog --- mantidimaging/gui/windows/main/model.py | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/mantidimaging/gui/windows/main/model.py b/mantidimaging/gui/windows/main/model.py index 91479f9fa0e..36dd68c2b45 100644 --- a/mantidimaging/gui/windows/main/model.py +++ b/mantidimaging/gui/windows/main/model.py @@ -61,13 +61,17 @@ def load(im_param: ImageParameters) -> ImageStack: return ds def load_images_into_mixed_dataset(self, file_path: str, progress: Progress) -> MixedDataset: - group = FilenameGroup.from_file(Path(file_path)) - group.find_all_files() - images = loader.load_stack_from_group(group, progress) + images = self.load_image_stack(file_path, progress) sd = MixedDataset(stacks=[images], name=images.name) self.datasets[sd.id] = sd return sd + def load_image_stack(self, file_path: str, progress: Progress) -> ImageStack: + group = FilenameGroup.from_file(Path(file_path)) + group.find_all_files() + images = loader.load_stack_from_group(group, progress) + return images + def do_images_saving(self, images_id: uuid.UUID, output_dir: str, name_prefix: str, image_format: str, overwrite: bool, pixel_depth: str, progress: Progress) -> bool: images = self.get_images_by_uuid(images_id) From 544281c6c34cdcaaf35bdea44e35e42e5f9917de Mon Sep 17 00:00:00 2001 From: Sam Tygier Date: Tue, 13 Aug 2024 17:41:35 +0100 Subject: [PATCH 3/6] System test for replacing a stack in a dataset --- .../gui/test/gui_system_loading_test.py | 24 +++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/mantidimaging/gui/test/gui_system_loading_test.py b/mantidimaging/gui/test/gui_system_loading_test.py index 42349efc8e0..74e51fc6613 100644 --- a/mantidimaging/gui/test/gui_system_loading_test.py +++ b/mantidimaging/gui/test/gui_system_loading_test.py @@ -224,3 +224,27 @@ def test_func() -> bool: self.assertEqual(image_shape, [128, 128]) self.assertEqual(image_count, expected_count) self.assertEqual(len(sample.real_projection_angles().value), expected_count) + + @mock.patch("mantidimaging.gui.windows.main.MainWindowView._get_file_name") + def test_replace_image_stack(self, mocked_select_file): + new_stack = Path(LOAD_SAMPLE).parents[1] / "Flat_Before/" / "IMAT_Flower_Flat_Before_000000.tif" + mocked_select_file.return_value = new_stack + self.assertEqual(len(self.main_window.presenter.get_active_stack_visualisers()), 0) + self._load_data_set() + self.assertEqual(len(self.main_window.presenter.get_active_stack_visualisers()), 5) + self.assertEqual(100, list(self.main_window.presenter.datasets)[0].sample.data.shape[0]) + + self.main_window.dataset_tree_widget.topLevelItem(0).setSelected(True) + + self.main_window._add_images_to_existing_dataset() + QTest.qWait(SHORT_DELAY) + + with mock.patch( + "mantidimaging.gui.windows.add_images_to_dataset_dialog.view.QFileDialog.getOpenFileName") as gofn: + gofn.return_value = (str(new_stack), None) + self.main_window.add_to_dataset_dialog.chooseFileButton.click() + + self.main_window.add_to_dataset_dialog.accepted.emit() + QTest.qWait(SHORT_DELAY) + + self.assertEqual(20, list(self.main_window.presenter.datasets)[0].sample.data.shape[0]) From d40618562a830b936a6847ae8ca0bd9270e11550 Mon Sep 17 00:00:00 2001 From: Sam Tygier Date: Tue, 13 Aug 2024 17:45:53 +0100 Subject: [PATCH 4/6] Release notes --- docs/release_notes/next/fix-2315-add-replace-stack | 1 + 1 file changed, 1 insertion(+) create mode 100644 docs/release_notes/next/fix-2315-add-replace-stack diff --git a/docs/release_notes/next/fix-2315-add-replace-stack b/docs/release_notes/next/fix-2315-add-replace-stack new file mode 100644 index 00000000000..61fbda624a0 --- /dev/null +++ b/docs/release_notes/next/fix-2315-add-replace-stack @@ -0,0 +1 @@ +#2315: Fix adding or replacing a stack within a dataset From c7f58155693690a174155232fb39e7c35a86bb26 Mon Sep 17 00:00:00 2001 From: Sam Tygier Date: Thu, 15 Aug 2024 14:01:23 +0100 Subject: [PATCH 5/6] Add consistency check for TestGuiSystemLoading --- .../gui/test/gui_system_loading_test.py | 49 ++++++++++++++++++- 1 file changed, 48 insertions(+), 1 deletion(-) diff --git a/mantidimaging/gui/test/gui_system_loading_test.py b/mantidimaging/gui/test/gui_system_loading_test.py index 74e51fc6613..682a4e06448 100644 --- a/mantidimaging/gui/test/gui_system_loading_test.py +++ b/mantidimaging/gui/test/gui_system_loading_test.py @@ -235,6 +235,7 @@ def test_replace_image_stack(self, mocked_select_file): self.assertEqual(100, list(self.main_window.presenter.datasets)[0].sample.data.shape[0]) self.main_window.dataset_tree_widget.topLevelItem(0).setSelected(True) + self._check_datasets_consistent() self.main_window._add_images_to_existing_dataset() QTest.qWait(SHORT_DELAY) @@ -246,5 +247,51 @@ def test_replace_image_stack(self, mocked_select_file): self.main_window.add_to_dataset_dialog.accepted.emit() QTest.qWait(SHORT_DELAY) - + self._check_datasets_consistent() self.assertEqual(20, list(self.main_window.presenter.datasets)[0].sample.data.shape[0]) + + def _check_datasets_consistent(self, show_datasets=False) -> None: + print("_check_datasets_consistent") + if show_datasets: + print("Main window datasets") + for k, v in self.main_window.presenter.model.datasets.items(): + print(" dataset:", k) + for image_stack in v.all: + print(" ", image_stack.id, image_stack.name) + print("Main window visualisers/tabs") + for vis in self.main_window.presenter.get_active_stack_visualisers(): + print(" ", vis.id, vis.name) + print("Main window treeview") + for i in range(self.main_window.dataset_tree_widget.topLevelItemCount()): + tree_ds = self.main_window.dataset_tree_widget.topLevelItem(i) + print(f" dataset: {tree_ds.id} {tree_ds.text(0)}") + for j in range(tree_ds.childCount()): + tree_is = tree_ds.child(j) + print(f" {tree_is.id} {tree_is.text(0)}") + + # Datasets + open_dataset_ids = list(self.main_window.presenter.model.datasets.keys()) + self.assertEqual(len(open_dataset_ids), len(set(open_dataset_ids))) + image_stack_ids = self.main_window.presenter.model.image_ids + self.assertEqual(len(image_stack_ids), len(set(image_stack_ids))) + + # Visualisers/Tabs + visualiser_ids = [vis.id for vis in self.main_window.presenter.get_active_stack_visualisers()] + self.assertEqual(len(visualiser_ids), len(set(visualiser_ids))) + self.assertEqual(len(visualiser_ids), len(image_stack_ids)) + for visualiser_id in visualiser_ids: + self.assertIn(visualiser_id, image_stack_ids) + + #Tree view + tree_datasets = [ + self.main_window.dataset_tree_widget.topLevelItem(i) + for i in range(self.main_window.dataset_tree_widget.topLevelItemCount()) + ] + tree_image_stack_ids = [] + self.assertEqual(len(open_dataset_ids), len(tree_datasets)) + for tree_dataset in tree_datasets: + self.assertIn(tree_dataset.id, open_dataset_ids) + for i in range(tree_dataset.childCount()): + tree_image_stack_ids.append(tree_dataset.child(i).id) + self.assertEqual(len(tree_image_stack_ids), len(set(tree_image_stack_ids))) + self.assertEqual(len(tree_image_stack_ids), len(image_stack_ids)) From ccfc1d0bcb204c604a411525af3e0c9214d9b62b Mon Sep 17 00:00:00 2001 From: Sam Tygier Date: Thu, 15 Aug 2024 15:03:17 +0100 Subject: [PATCH 6/6] TestGuiSystemLoading additional consistency checking --- mantidimaging/gui/test/gui_system_loading_test.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/mantidimaging/gui/test/gui_system_loading_test.py b/mantidimaging/gui/test/gui_system_loading_test.py index 682a4e06448..dd4dc4a02aa 100644 --- a/mantidimaging/gui/test/gui_system_loading_test.py +++ b/mantidimaging/gui/test/gui_system_loading_test.py @@ -28,6 +28,7 @@ def setUp(self) -> None: def tearDown(self) -> None: self._close_image_stacks() + self._check_datasets_consistent() super().tearDown() self.assertFalse(self.main_window.isVisible()) @@ -43,6 +44,7 @@ def test_func() -> bool: return (current_stacks - initial_stacks) >= 1 wait_until(test_func, max_retry=600) + self._check_datasets_consistent() @classmethod def _click_stack_selector(cls): @@ -89,6 +91,7 @@ def test_load_180(self, mocked_select_file): self.assertEqual(len(stacks_after), 5) self.assertIn(stacks[0], stacks_after) self.assertTrue(stacks[0].presenter.images.has_proj180deg()) + self._check_datasets_consistent() def _get_log_angle(self, log_path): with open(log_path) as log_file: