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 diff --git a/mantidimaging/gui/test/gui_system_loading_test.py b/mantidimaging/gui/test/gui_system_loading_test.py index 42349efc8e0..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: @@ -224,3 +227,74 @@ 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._check_datasets_consistent() + + 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._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)) 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) 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)