diff --git a/mantidimaging/core/data/dataset.py b/mantidimaging/core/data/dataset.py index 3d2d5cfb416..60c49d160cb 100644 --- a/mantidimaging/core/data/dataset.py +++ b/mantidimaging/core/data/dataset.py @@ -184,6 +184,8 @@ def set_stack_by_type_name(self, file_type_name: str, image_stack: ImageStack) - self.add_recon(image_stack) elif file_type_name == "IMAGES": self.stacks.append(image_stack) + elif file_type_name == "SINOGRAMS": + self._sinograms = image_stack else: file_type = getattr(FILE_TYPES, file_type_name) self.set_stack(file_type, image_stack) @@ -218,15 +220,14 @@ def _get_stack_data_type(stack_id: uuid.UUID, dataset: Dataset) -> str: return "Recon" if stack_id in [stack.id for stack in dataset._stacks]: return "Images" - if isinstance(dataset, StrictDataset): - if dataset.sample is not None and stack_id == dataset.sample.id: - return "Sample" - if dataset.flat_before is not None and stack_id == dataset.flat_before.id: - return "Flat Before" - if dataset.flat_after is not None and stack_id == dataset.flat_after.id: - return "Flat After" - if dataset.dark_before is not None and stack_id == dataset.dark_before.id: - return "Dark Before" - if dataset.dark_after is not None and stack_id == dataset.dark_after.id: - return "Dark After" + if dataset.sample is not None and stack_id == dataset.sample.id: + return "Sample" + if dataset.flat_before is not None and stack_id == dataset.flat_before.id: + return "Flat Before" + if dataset.flat_after is not None and stack_id == dataset.flat_after.id: + return "Flat After" + if dataset.dark_before is not None and stack_id == dataset.dark_before.id: + return "Dark Before" + if dataset.dark_after is not None and stack_id == dataset.dark_after.id: + return "Dark After" raise RuntimeError(f"No stack with ID {stack_id} found in dataset {dataset.id}") diff --git a/mantidimaging/gui/windows/main/model.py b/mantidimaging/gui/windows/main/model.py index 459474f92c8..ec73528afb5 100644 --- a/mantidimaging/gui/windows/main/model.py +++ b/mantidimaging/gui/windows/main/model.py @@ -140,9 +140,6 @@ def raise_error_when_images_not_found(self, images_id: uuid.UUID) -> NoReturn: def raise_error_when_parent_dataset_not_found(self, images_id: uuid.UUID) -> NoReturn: raise RuntimeError(f"Failed to find dataset containing ImageStack with ID {images_id}") - def raise_error_when_parent_strict_dataset_not_found(self, images_id: uuid.UUID) -> NoReturn: - raise RuntimeError(f"Failed to find strict dataset containing ImageStack with ID {images_id}") - def add_log_to_sample(self, images_id: uuid.UUID, log_file: Path) -> None: images = self.get_images_by_uuid(images_id) if images is None: @@ -237,19 +234,6 @@ def get_parent_dataset(self, member_id: uuid.UUID) -> uuid.UUID: return dataset.id self.raise_error_when_parent_dataset_not_found(member_id) - def add_recon_to_dataset(self, recon_data: ImageStack, stack_id: uuid.UUID) -> uuid.UUID: - """ - Adds a recon to a dataset using recon data and an ID from one of the stacks in the dataset. - :param recon_data: The recon data. - :param stack_id: The ID of one of the member stacks. - :return: The ID of the parent dataset if found. - """ - for dataset in self.datasets.values(): - if stack_id in dataset: - dataset.recons.append(recon_data) - return dataset.id - self.raise_error_when_parent_strict_dataset_not_found(stack_id) - @property def recon_list_ids(self) -> list[uuid.UUID]: return [dataset.recons.id for dataset in self.datasets.values()] diff --git a/mantidimaging/gui/windows/main/presenter.py b/mantidimaging/gui/windows/main/presenter.py index e27dd8e0e83..c2b23b16703 100644 --- a/mantidimaging/gui/windows/main/presenter.py +++ b/mantidimaging/gui/windows/main/presenter.py @@ -91,7 +91,7 @@ def notify(self, signal: Notification, **baggage): elif signal == Notification.SHOW_ADD_STACK_DIALOG: self._show_add_stack_to_dataset_dialog(**baggage) elif signal == Notification.DATASET_ADD: - self._add_images_to_existing_dataset() + self.handle_add_images_to_existing_dataset_from_dialog() elif signal == Notification.TAB_CLICKED: self._on_tab_clicked(**baggage) elif signal == Notification.SHOW_MOVE_STACK_DIALOG: @@ -235,11 +235,8 @@ def add_alternative_180_if_required(self, dataset: Dataset) -> None: dataset.sample.projection_angles().value) if diff <= THRESHOLD_180 or self.view.ask_to_use_closest_to_180(diff): _180_arr = np.reshape(closest_projection, (1, ) + closest_projection.shape).copy() - dataset.proj180deg = ImageStack(_180_arr, name=f"{dataset.name}_180") - - self.add_child_item_to_tree_view(dataset.id, dataset.proj180deg.id, "180") - sample_vis = self.get_stack_visualiser(dataset.sample.id) - self._create_and_tabify_stack_window(dataset.proj180deg, sample_vis) + proj180deg = ImageStack(_180_arr, name=f"{dataset.name}_180") + self.add_images_to_existing_dataset(dataset.id, proj180deg, "proj_180") def create_dataset_stack_visualisers(self, dataset: Dataset) -> StackVisualiserView: """ @@ -412,33 +409,8 @@ def add_180_deg_file_to_dataset(self, dataset_id: uuid.UUID, _180_deg_file: str) :param dataset_id: The ID of the dataset to update. :param _180_deg_file: The filename for the 180 file. """ - existing_180_id = self.model.get_existing_180_id(dataset_id) - _180_deg = self.model.add_180_deg_to_dataset(dataset_id, _180_deg_file) - stack = self.create_single_tabbed_images_stack(_180_deg) - stack.raise_() - - if existing_180_id is None: - self.add_child_item_to_tree_view(dataset_id, _180_deg.id, "180") - else: - self.replace_child_item_id(dataset_id, existing_180_id, _180_deg.id) - self._delete_stack_visualiser(existing_180_id) - - self.view.model_changed.emit() - - def replace_child_item_id(self, dataset_id: uuid.UUID, prev_id: uuid.UUID, new_id: uuid.UUID) -> None: - """ - Replaces the ID in an existing child item. - :param dataset_id: The ID of the parent dataset. - :param prev_id: The previous ID of the tree view item. - :param new_id: The new ID that should be given to the tree view item. - """ - dataset_item = self.view.get_dataset_tree_view_item(dataset_id) - for i in range(dataset_item.childCount()): - child = dataset_item.child(i) - if child.id == prev_id: - child._id = new_id - return - raise RuntimeError(f"Failed to get tree view item with ID {prev_id}") + proj180deg = self.model.add_180_deg_to_dataset(dataset_id, _180_deg_file) + self.add_images_to_existing_dataset(dataset_id, proj180deg, "proj_180") def add_projection_angles_to_sample(self, stack_id: uuid.UUID, proj_angles: ProjectionAngles) -> None: self.model.add_projection_angles_to_sample(stack_id, proj_angles) @@ -532,31 +504,6 @@ def _remove_recon_item_from_tree_view(recon_group, uuid_remove: uuid.UUID) -> bo return True return False - def add_child_item_to_tree_view(self, parent_id: uuid.UUID, child_id: uuid.UUID, child_name: str) -> None: - """ - Adds a child item to the tree view. - :param parent_id: The ID of the parent dataset. - :param child_id: The ID of the corresponding ImageStack object. - :param child_name: The name that should appear in the tree view. - """ - dataset_item = self.view.get_dataset_tree_view_item(parent_id) - self.view.create_child_tree_item(dataset_item, child_id, child_name) - - def add_recon_item_to_tree_view(self, parent_id: uuid.UUID, child_id: uuid.UUID, name: str) -> None: - """ - Adds a recon item to the tree view. - :param parent_id: The ID of the parent dataset. - :param child_id: The ID of the corresponding ImageStack object. - :param name: The name to display for the recon in the tree view. - """ - dataset_item = self.view.get_dataset_tree_view_item(parent_id) - - recon_group = self.view.get_recon_group(dataset_item) - if not recon_group: - recon_group = self.view.add_recon_group(dataset_item, self.model.get_recon_list_id(parent_id)) - - self.view.create_child_tree_item(recon_group, child_id, name) - def add_stack_to_dictionary(self, stack: StackVisualiserView) -> None: self.stack_visualisers[stack.id] = stack @@ -610,10 +557,8 @@ def _add_recon_to_dataset(self, recon_data: ImageStack, stack_id: uuid.UUID) -> :param recon_data: The recon data. :param stack_id: The ID of one of the stacks in the dataset that the recon data should be added to. """ - parent_id = self.model.add_recon_to_dataset(recon_data, stack_id) - self.view.create_new_stack(recon_data) - self.add_recon_item_to_tree_view(parent_id, recon_data.id, recon_data.name) - self.view.model_changed.emit() + parent_id = self.model.get_parent_dataset(stack_id) + self.add_images_to_existing_dataset(parent_id, recon_data, "Recon") def add_sinograms_to_dataset_and_update_view(self, sino_stack: ImageStack, original_stack_id: uuid.UUID) -> None: """ @@ -622,26 +567,7 @@ def add_sinograms_to_dataset_and_update_view(self, sino_stack: ImageStack, origi :param original_stack_id: The ID of a stack in the dataset. """ parent_id = self.model.get_parent_dataset(original_stack_id) - prev_sino = self.model.datasets[parent_id].sinograms - if prev_sino is not None: - self._delete_stack_visualiser(prev_sino.id) - self.model.datasets[parent_id].sinograms = sino_stack - self._add_sinograms_to_tree_view(sino_stack.id, parent_id) - self.create_single_tabbed_images_stack(sino_stack) - self.view.model_changed.emit() - - def _add_sinograms_to_tree_view(self, sino_id: uuid.UUID, parent_id: uuid.UUID) -> None: - """ - Adds a sinograms item to the tree view or updates the id of an existing one. - :param parent_id: The ID of the parent dataset. - :param sino_id: The ID of the corresponding ImageStack object. - """ - dataset_item = self.view.get_dataset_tree_view_item(parent_id) - sinograms_item = self.view.get_sinograms_item(dataset_item) - if sinograms_item is None: - self.view.create_child_tree_item(dataset_item, sino_id, self.view.sino_text) - else: - sinograms_item._id = sino_id + self.add_images_to_existing_dataset(parent_id, sino_stack, "Sinograms") def _show_add_stack_to_dataset_dialog(self, container_id: uuid.UUID) -> None: """ @@ -665,7 +591,7 @@ def _show_move_stack_dialog(self, stack_id: uuid.UUID) -> None: stack_data_type = _get_stack_data_type(stack_id, dataset) self.view.show_move_stack_dialog(dataset_id, stack_id, dataset.name, stack_data_type) - def _add_images_to_existing_dataset(self) -> None: + def handle_add_images_to_existing_dataset_from_dialog(self) -> None: """ Adds / replaces images to an existing dataset. Updates the tree view and deletes the previous stack if necessary. @@ -673,30 +599,20 @@ def _add_images_to_existing_dataset(self) -> None: assert self.view.add_to_dataset_dialog is not None dataset_id = self.view.add_to_dataset_dialog.dataset_id - dataset = self.get_dataset(dataset_id) - assert dataset is not None - new_images = self.view.add_to_dataset_dialog.presenter.images images_type = self.view.add_to_dataset_dialog.images_type - dataset.set_stack_by_type_name(images_type, new_images) + self.add_images_to_existing_dataset(dataset_id, new_images, images_type) + def add_images_to_existing_dataset(self, dataset_id: uuid.UUID, new_images: ImageStack, images_type: str): + dataset = self.get_dataset(dataset_id) + assert dataset is not None + dataset.set_stack_by_type_name(images_type, new_images) self.create_single_tabbed_images_stack(new_images) self.update_dataset_tree() self._close_unused_visualisers() self.view.model_changed.emit() - def _add_images_to_existing_strict_dataset(self, dataset: Dataset, new_images: ImageStack, stack_type: str) -> None: - """ - Adds or replaces images in a StrictDataset and updates the tree view if required. - :param dataset: The StrictDataset to change. - :param new_images: The new images to add. - """ - image_attr = stack_type.replace(" ", "_").lower() - new_images.name = self._create_strict_dataset_stack_name(stack_type, dataset.name) - setattr(dataset, image_attr, new_images) - self.update_dataset_tree() - def _close_unused_visualisers(self): visualisers = set(self.stack_visualisers.keys()) stacks = {stack.id for stack in self.get_all_stacks()} @@ -723,9 +639,10 @@ def _move_stack(self, origin_dataset_id: uuid.UUID, stack_id: uuid.UUID, destina f"Unable to find destination dataset with ID {destination_dataset_id} when attempting to move stack") stack_to_move = self.get_stack(stack_id) + stack_to_move.name = self._create_strict_dataset_stack_name(destination_stack_type, destination_dataset.name) + origin_dataset.delete_stack(stack_id) - self._add_images_to_existing_strict_dataset(destination_dataset, stack_to_move, destination_stack_type) - self._close_unused_visualisers() + self.add_images_to_existing_dataset(destination_dataset_id, stack_to_move, destination_stack_type) @staticmethod def _create_strict_dataset_stack_name(stack_type: str, dataset_name: str) -> str: diff --git a/mantidimaging/gui/windows/main/test/model_test.py b/mantidimaging/gui/windows/main/test/model_test.py index 8c830286f82..be4c4afa093 100644 --- a/mantidimaging/gui/windows/main/test/model_test.py +++ b/mantidimaging/gui/windows/main/test/model_test.py @@ -22,8 +22,6 @@ class MainWindowModelTest(unittest.TestCase): def setUp(self): self.model = MainWindowModel() - self.model_class_name = f"{self.model.__module__}.{self.model.__class__.__name__}" - self.stack_list_property = f"{self.model_class_name}.stack_list" def _add_mock_image(self): dataset_mock = mock.Mock() @@ -416,17 +414,6 @@ def test_image_ids(self): self.model.add_dataset_to_model(ds) self.assertListEqual(all_ids, self.model.image_ids) - def test_add_recon_to_dataset(self): - sample = generate_images() - sample_id = sample.id - ds = StrictDataset(sample=sample) - - recon = generate_images() - self.model.add_dataset_to_model(ds) - parent_id = self.model.add_recon_to_dataset(recon, sample_id) - self.assertIn(recon, ds.all) - assert parent_id == ds.id - def test_proj180s(self): ds1 = StrictDataset(sample=generate_images()) @@ -443,10 +430,6 @@ def test_proj180s(self): self.assertListEqual(self.model.proj180s, proj180s) - def test_exception_when_dataset_for_recons_not_found(self): - with self.assertRaises(RuntimeError): - self.model.add_recon_to_dataset(generate_images(), "bad-id") - def test_get_parent_strict_dataset_success(self): ds = StrictDataset(sample=generate_images()) self.model.add_dataset_to_model(ds) diff --git a/mantidimaging/gui/windows/main/test/presenter_test.py b/mantidimaging/gui/windows/main/test/presenter_test.py index 221990b14ad..be3fe749fb4 100644 --- a/mantidimaging/gui/windows/main/test/presenter_test.py +++ b/mantidimaging/gui/windows/main/test/presenter_test.py @@ -11,7 +11,7 @@ import numpy as np from parameterized import parameterized -from mantidimaging.core.data.dataset import StrictDataset, MixedDataset, Dataset +from mantidimaging.core.data.dataset import Dataset from mantidimaging.core.utility.data_containers import ProjectionAngles from mantidimaging.gui.dialogs.async_task import TaskWorkerThread from mantidimaging.gui.windows.image_load_dialog import ImageLoadDialog @@ -28,7 +28,6 @@ def setUp(self): self.presenter = MainWindowPresenter(self.view) self.dataset, self.images = generate_standard_dataset(shape=(10, 5, 5)) self.presenter.model = self.model = mock.create_autospec(MainWindowModel, datasets={}) - self.model.get_recons_id = mock.Mock() self.view.create_stack_window.return_value = mock.Mock() self.view.model_changed = mock.Mock() @@ -138,10 +137,6 @@ def test_create_new_stack_images(self): self.presenter._create_lone_stack_window(images) self.assertEqual(1, len(self.presenter.stack_visualisers)) - @mock.patch("mantidimaging.gui.windows.main.presenter.QApplication") - def test_create_new_stack_images_focuses_newest_tab(self, mock_QApp): - pass - def test_create_new_stack_with_180_in_sample(self): self.dataset.proj180deg = generate_images(shape=(1, 20, 20)) self.dataset.proj180deg.filenames = ["filename"] @@ -160,9 +155,8 @@ def test_create_recon_windows(self): self.presenter.create_dataset_stack_visualisers(self.dataset) self.assertEqual(8, len(self.presenter.stack_visualisers)) - @mock.patch("mantidimaging.gui.windows.main.presenter.MainWindowPresenter.add_child_item_to_tree_view") - @mock.patch("mantidimaging.gui.windows.main.presenter.MainWindowPresenter.get_stack_visualiser") - def test_create_new_stack_dataset_and_use_threshold_180(self, mock_get_stack, mock_add_child): + def test_create_new_stack_dataset_and_use_threshold_180(self): + self.model.datasets[self.dataset.id] = self.dataset self.dataset.sample.set_projection_angles( ProjectionAngles(np.linspace(0, np.pi, self.dataset.sample.num_images))) @@ -172,6 +166,7 @@ def test_create_new_stack_dataset_and_use_threshold_180(self, mock_get_stack, mo self.presenter.add_alternative_180_if_required(self.dataset) def test_threshold_180_is_separate_data(self): + self.model.datasets[self.dataset.id] = self.dataset self.dataset.sample.set_projection_angles( ProjectionAngles(np.linspace(0, np.pi, self.dataset.sample.num_images))) @@ -271,53 +266,29 @@ def test_get_stack_with_images_failure(self): self.presenter.get_stack_with_images(generate_images()) def test_add_first_180_deg_to_dataset(self): - dataset_id = "dataset-id" + self.model.datasets[self.dataset.id] = self.dataset filename_for_180 = "path/to/180" self.model.get_existing_180_id.return_value = None self.model.add_180_deg_to_dataset.return_value = _180_deg = generate_images((1, 200, 200)) - self.presenter.add_child_item_to_tree_view = mock.Mock() + self.presenter.add_images_to_existing_dataset = mock.Mock() - self.presenter.add_180_deg_file_to_dataset(dataset_id, filename_for_180) - self.model.add_180_deg_to_dataset.assert_called_once_with(dataset_id, filename_for_180) - self.presenter.add_child_item_to_tree_view.assert_called_once_with(dataset_id, _180_deg.id, "180") - self.view.model_changed.emit.assert_called_once() + self.presenter.add_180_deg_file_to_dataset(self.dataset.id, filename_for_180) + self.model.add_180_deg_to_dataset.assert_called_once_with(self.dataset.id, filename_for_180) + self.presenter.add_images_to_existing_dataset.assert_called_once_with(self.dataset.id, _180_deg, "proj_180") def test_replace_180_deg_in_dataset(self): - dataset_id = "dataset-id" + self.model.datasets[self.dataset.id] = self.dataset + dataset_id = self.dataset.id filename_for_180 = "path/to/180" self.model.get_existing_180_id.return_value = existing_180_id = "prev-id" self.presenter.stack_visualisers[existing_180_id] = existing_180_stack = mock.Mock() self.model.add_180_deg_to_dataset.return_value = _180_deg = generate_images((1, 200, 200)) - self.presenter.replace_child_item_id = mock.Mock() self.presenter.add_180_deg_file_to_dataset(dataset_id, filename_for_180) self.model.add_180_deg_to_dataset.assert_called_once_with(dataset_id, filename_for_180) - self.presenter.replace_child_item_id.assert_called_once_with(dataset_id, existing_180_id, _180_deg.id) self.assertNotIn(existing_180_stack, self.presenter.stack_visualisers) self.view.model_changed.emit.assert_called_once() - def test_replace_child_item_id_success(self): - dataset_tree_item_mock = self.view.get_dataset_tree_view_item.return_value - dataset_tree_item_mock.childCount.return_value = 1 - child_item_mock = dataset_tree_item_mock.child.return_value - child_item_mock.id = id_to_replace = "id-to-replace" - - dataset_id = "dataset-id" - new_id = "new-id" - - self.presenter.replace_child_item_id(dataset_id, id_to_replace, new_id) - self.view.get_dataset_tree_view_item.assert_called_once_with(dataset_id) - dataset_tree_item_mock.childCount.assert_called_once() - dataset_tree_item_mock.child.assert_called_once_with(0) - assert child_item_mock._id == new_id - - def test_replace_child_item_id_failure(self): - dataset_tree_item_mock = self.view.get_dataset_tree_view_item.return_value - dataset_tree_item_mock.childCount.return_value = 1 - - with self.assertRaises(RuntimeError): - self.presenter.replace_child_item_id("dataset-id", "bad-id", "new-id") - def test_add_projection_angles_to_stack(self): id, angles = "doesn't-exist", ProjectionAngles(np.ndarray([1])) self.presenter.add_projection_angles_to_sample(id, angles) @@ -440,38 +411,31 @@ def test_focus_tab_with_id_in_dataset(self): def test_add_recon(self): recon = generate_images() - stack_id = "stack-id" - parent_id = "parent-id" - self.model.add_recon_to_dataset.return_value = parent_id - self.presenter.add_recon_item_to_tree_view = mock.Mock() + recon.name = "New recon" + stack_id = self.dataset.sample.id + self.model.datasets[self.dataset.id] = self.dataset + self.model.get_parent_dataset.return_value = self.dataset.id self.presenter.notify(Notification.ADD_RECON, recon_data=recon, stack_id=stack_id) - self.model.add_recon_to_dataset.assert_called_once_with(recon, stack_id) - self.presenter.add_recon_item_to_tree_view.assert_called_with(parent_id, recon.id, recon.name) - self.view.create_new_stack.assert_called_once_with(recon) + + self.view.create_stack_window.assert_called_once_with(recon) self.view.model_changed.emit.assert_called_once() + self.assertIn(recon.id, self.dataset) + last_add_widget_call = self.view.add_item_to_dataset_tree_widget.mock_calls[-1][1] + self.assertEqual(last_add_widget_call[:2], ("New recon", recon.id)) def test_dataset_list(self): - dataset_1 = StrictDataset(sample=generate_images()) + dataset_1 = Dataset(sample=generate_images()) dataset_1.name = "dataset-1" - dataset_2 = StrictDataset(sample=generate_images()) + dataset_2 = Dataset(sample=generate_images()) dataset_2.name = "dataset-2" - mixed_dataset = MixedDataset(stacks=[generate_images()]) + mixed_dataset = Dataset(stacks=[generate_images()]) self.model.datasets = {"id1": dataset_1, "id2": dataset_2, "id3": mixed_dataset} dataset_list = list(self.presenter.datasets) assert len(dataset_list) == 3 - def test_add_child_item_to_tree_view(self): - dataset_item_mock = self.view.get_dataset_tree_view_item.return_value - dataset_item_mock.id = dataset_id = "dataset-id" - - child_id = "child-id" - child_name = "180" - self.presenter.add_child_item_to_tree_view(dataset_id, child_id, child_name) - self.view.create_child_tree_item.assert_called_once_with(dataset_item_mock, child_id, child_name) - @mock.patch("mantidimaging.gui.windows.main.presenter.MainWindowPresenter.create_dataset_stack_visualisers") @mock.patch("mantidimaging.gui.windows.main.presenter.MainWindowPresenter._open_window_if_not_open") def test_on_stack_load_done_success(self, _, _1): @@ -500,7 +464,7 @@ def test_on_dataset_load_done_success(self, command_line_args): @patch("mantidimaging.gui.windows.main.presenter.find_projection_closest_to_180") def test_no_need_for_alternative_180(self, find_180_mock: mock.Mock): - dataset = StrictDataset(sample=generate_images()) + dataset = Dataset(sample=generate_images()) dataset.proj180deg = generate_images((1, 20, 20)) dataset.proj180deg.filenames = ["filename"] @@ -509,7 +473,7 @@ def test_no_need_for_alternative_180(self, find_180_mock: mock.Mock): def test_create_mixed_dataset_stack_windows(self): n_stacks = 3 - dataset = MixedDataset(stacks=[generate_images() for _ in range(n_stacks)], name="cool-name") + dataset = Dataset(stacks=[generate_images() for _ in range(n_stacks)], name="cool-name") self.create_stack_mocks(dataset) self.presenter.create_dataset_stack_visualisers(dataset) assert len(self.presenter.stack_visualisers) == n_stacks @@ -528,44 +492,6 @@ def test_tabify_stack_window_to_item_in_list(self): self.presenter._tabify_stack_window(new_stack) self.view.tabifyDockWidget.assert_called_once_with(other_stack, new_stack) - def test_add_recon_item_to_tree_view_first_item(self): - dataset_item_mock = self.view.get_dataset_tree_view_item.return_value - dataset_item_mock.id = parent_id = "parent-id" - child_id = "child-id" - name = "Recon" - recon_group_mock = self.view.add_recon_group.return_value - self.model.get_recon_list_id.return_value = recons_id = "recons-id" - self.view.get_recon_group.return_value = None - - self.presenter.add_recon_item_to_tree_view(parent_id, child_id, name) - self.view.get_dataset_tree_view_item.assert_called_once_with(parent_id) - self.model.get_recon_list_id.assert_called_once_with(parent_id) - self.view.add_recon_group.assert_called_once_with(dataset_item_mock, recons_id) - self.view.create_child_tree_item.assert_called_once_with(recon_group_mock, child_id, name) - - def test_add_recon_item_to_tree_view_additional_item(self): - parent_id = "parent-id" - dataset_item_mock = self.view.get_dataset_tree_view_item.return_value - child_id = "child-id" - recon_group_mock = self.view.get_recon_group.return_value - name = "Recon_2" - - self.presenter.add_recon_item_to_tree_view(parent_id, child_id, name) - self.view.get_dataset_tree_view_item.assert_called_once_with(parent_id) - self.view.get_recon_group.assert_called_once_with(dataset_item_mock) - self.view.create_child_tree_item.assert_called_once_with(recon_group_mock, child_id, name) - - def test_add_recon_item_to_tree_view_first_item_with_multiple_recons(self): - child_id = "child-id" - name = "Recon" - recon_group_mock = self.view.add_recon_group.return_value - self.view.get_recon_group.return_value = None - - self.presenter.add_recon_item_to_tree_view("parent-id", child_id, name) - - self.view.add_recon_group.assert_called_once() - self.view.create_child_tree_item.assert_called_once_with(recon_group_mock, child_id, name) - def test_cant_focus_on_recon_group(self): self.presenter.stack_visualisers = {} self.presenter.stack_visualisers["stack-id"] = stack_mock = mock.Mock() @@ -578,48 +504,24 @@ def test_cant_focus_on_recon_group(self): def test_add_sinograms_to_dataset_with_no_sinograms_and_update_view(self): sinograms = generate_images() - ds = StrictDataset(sample=generate_images()) + ds = Dataset(sample=generate_images()) self.model.datasets[ds.id] = ds self.model.get_parent_dataset.return_value = ds.id - dataset_item_mock = self.view.get_dataset_tree_view_item.return_value - dataset_item_mock.id = ds.id self.view.get_sinograms_item.return_value = None self.presenter.create_single_tabbed_images_stack = mock.Mock() - self.presenter._delete_stack_visualiser = mock.Mock() + self.presenter._close_unused_visualisers = mock.Mock() self.presenter.add_sinograms_to_dataset_and_update_view(sinograms, ds.sample.id) + self.model.get_parent_dataset.assert_called_once_with(ds.sample.id) - self.presenter._delete_stack_visualiser.assert_not_called() + self.presenter._close_unused_visualisers.assert_called_once() self.assertIs(ds.sinograms, sinograms) - self.view.get_dataset_tree_view_item.assert_called_once_with(ds.id) - self.view.get_sinograms_item.assert_called_once_with(dataset_item_mock) - self.view.create_child_tree_item.assert_called_once_with(dataset_item_mock, sinograms.id, self.view.sino_text) + last_add_widget_call = self.view.add_item_to_dataset_tree_widget.mock_calls[-1][1] + self.assertEqual(last_add_widget_call[:2], ("Sinograms", sinograms.id)) self.presenter.create_single_tabbed_images_stack.assert_called_once_with(sinograms) self.view.model_changed.emit.assert_called_once() - def test_add_sinograms_to_dataset_with_existing_sinograms_and_update_view(self): - new_sinograms = generate_images() - ds = StrictDataset(sample=generate_images()) - self.model.datasets[ds.id] = ds - self.model.get_parent_dataset.return_value = ds.id - ds.sinograms = existing_sinograms = generate_images() - - dataset_item_mock = self.view.get_dataset_tree_view_item.return_value - dataset_item_mock.id = ds.id - sinograms_item_mock = self.view.get_sinograms_item.return_value - self.presenter.create_single_tabbed_images_stack = mock.Mock() - self.presenter._delete_stack_visualiser = mock.Mock() - - self.presenter.add_sinograms_to_dataset_and_update_view(new_sinograms, ds.sample.id) - self.presenter._delete_stack_visualiser.assert_called_once_with(existing_sinograms.id) - self.assertIs(ds.sinograms, new_sinograms) - self.view.get_dataset_tree_view_item.assert_called_once_with(ds.id) - self.view.get_sinograms_item.assert_called_once_with(dataset_item_mock) - assert sinograms_item_mock._id == new_sinograms.id - self.presenter.create_single_tabbed_images_stack.assert_called_once_with(new_sinograms) - self.view.model_changed.emit.assert_called_once() - def test_remove_item_from_recon_group_but_keep_group(self): top_level_item_mock = mock.Mock() self.view.dataset_tree_widget.topLevelItemCount.return_value = 1 @@ -693,8 +595,8 @@ def test_save_nexus_file(self, start_async_mock: mock.Mock): busy=True) def test_get_dataset(self): - test_ds = StrictDataset(sample=generate_images()) - other_ds = StrictDataset(sample=generate_images()) + test_ds = Dataset(sample=generate_images()) + other_ds = Dataset(sample=generate_images()) self.model.datasets[test_ds.id] = test_ds self.model.datasets[other_ds.id] = other_ds @@ -702,7 +604,7 @@ def test_get_dataset(self): self.assertEqual(result, test_ds) def test_get_dataset_not_found(self): - ds = StrictDataset(sample=generate_images()) + ds = Dataset(sample=generate_images()) incorrect_id = uuid.uuid4() self.model.datasets[ds.id] = ds @@ -750,7 +652,7 @@ def test_add_new_stack_to_dataset(self, images_type): elif images_type in ["Recon", "Images"]: treeview_label = new_images.name - self.presenter._add_images_to_existing_dataset() + self.presenter.handle_add_images_to_existing_dataset_from_dialog() self.assertIn(call(treeview_label, new_images.id, mock_top_item), self.view.add_item_to_dataset_tree_widget.mock_calls) @@ -814,14 +716,14 @@ def test_select_recon_item(self): def test_all_stack_ids(self): mixed_stacks = [generate_images() for _ in range(5)] - mixed_dataset = MixedDataset(stacks=mixed_stacks) + mixed_dataset = Dataset(stacks=mixed_stacks) strict_stacks = [generate_images() for _ in range(5)] - strict_dataset = StrictDataset(sample=strict_stacks[0], - flat_before=strict_stacks[1], - flat_after=strict_stacks[2], - dark_before=strict_stacks[3], - dark_after=strict_stacks[4]) + strict_dataset = Dataset(sample=strict_stacks[0], + flat_before=strict_stacks[1], + flat_after=strict_stacks[2], + dark_before=strict_stacks[3], + dark_after=strict_stacks[4]) all_ids = [stack.id for stack in mixed_stacks] + [stack.id for stack in strict_stacks] self.model.datasets[mixed_dataset.id] = mixed_dataset @@ -831,7 +733,7 @@ def test_all_stack_ids(self): def test_show_move_stack_dialog(self): sample = generate_images() - ds = StrictDataset(sample=sample) + ds = Dataset(sample=sample) ds.name = dataset_name = "dataset-name" self.presenter.get_dataset_id_for_stack = mock.Mock(return_value=ds.id) self.presenter.get_dataset = mock.Mock(return_value=ds) @@ -846,63 +748,63 @@ def test_show_move_stack_dialog_raises(self): self.presenter._show_move_stack_dialog("stack-id") def test_move_stack_raises_when_origin_dataset_not_found(self): - self.presenter.get_dataset = mock.Mock(side_effect=[None, StrictDataset(sample=generate_images())]) + self.presenter.get_dataset = mock.Mock(side_effect=[None, Dataset(sample=generate_images())]) with self.assertRaises(RuntimeError): self.presenter._move_stack("origin-dataset-id", "stack-id", "Flat After", "destination-dataset-id") def test_move_stack_raises_when_destination_dataset_not_found(self): - self.presenter.get_dataset = mock.Mock(side_effect=[StrictDataset(sample=generate_images()), None]) + self.presenter.get_dataset = mock.Mock(side_effect=[Dataset(sample=generate_images()), None]) with self.assertRaises(RuntimeError): self.presenter._move_stack("origin-dataset-id", "stack-id", "Flat After", "destination-dataset-id") def test_stack_moved_to_recon(self): stack_to_move = generate_images() - origin_dataset = MixedDataset(stacks=[stack_to_move]) - destination_dataset = MixedDataset() - destination_dataset_id = destination_dataset.id + origin_dataset = Dataset(stacks=[stack_to_move]) + destination_dataset = Dataset() + self.model.datasets[origin_dataset.id] = origin_dataset + self.model.datasets[destination_dataset.id] = destination_dataset self.presenter.get_stack = mock.Mock(return_value=stack_to_move) self.presenter.remove_item_from_tree_view = mock.Mock() - self.presenter._add_images_to_existing_strict_dataset = mock.Mock() - self.presenter.get_dataset = mock.Mock(side_effect=[origin_dataset, destination_dataset]) + self.presenter.add_images_to_existing_dataset = mock.Mock() self.presenter.notify(Notification.MOVE_STACK, origin_dataset_id=origin_dataset.id, stack_id=stack_to_move.id, destination_stack_type=RECON_TEXT, - destination_dataset_id=destination_dataset_id) + destination_dataset_id=destination_dataset.id) self.presenter.get_stack.assert_called_once_with(stack_to_move.id) - self.presenter._add_images_to_existing_strict_dataset.assert_called_once_with( - destination_dataset, stack_to_move, RECON_TEXT) + self.presenter.add_images_to_existing_dataset.assert_called_once_with(destination_dataset.id, stack_to_move, + RECON_TEXT) self.assertNotIn(stack_to_move, origin_dataset) def test_stack_moved_to_mixed_dataset_images(self): stack_to_move = generate_images() - origin_dataset = StrictDataset(sample=stack_to_move) - destination_dataset = MixedDataset() - destination_dataset_id = destination_dataset.id + origin_dataset = Dataset(sample=stack_to_move) + destination_dataset = Dataset() + self.model.datasets[origin_dataset.id] = origin_dataset + self.model.datasets[destination_dataset.id] = destination_dataset - self.presenter.get_dataset = mock.Mock(side_effect=[origin_dataset, destination_dataset]) self.presenter.get_stack = mock.Mock(return_value=stack_to_move) self.presenter.remove_item_from_tree_view = mock.Mock() - self.presenter._add_images_to_existing_strict_dataset = mock.Mock() + self.presenter.add_images_to_existing_dataset = mock.Mock() - self.presenter._move_stack(origin_dataset.id, stack_to_move.id, "Images", destination_dataset_id) + self.presenter._move_stack(origin_dataset.id, stack_to_move.id, "Images", destination_dataset.id) self.presenter.get_stack.assert_called_once_with(stack_to_move.id) - self.presenter._add_images_to_existing_strict_dataset.assert_called_once_with( - destination_dataset, stack_to_move, "Images") + self.presenter.add_images_to_existing_dataset.assert_called_once_with(destination_dataset.id, stack_to_move, + "Images") self.assertNotIn(stack_to_move, origin_dataset) def test_move_stack_to_strict_dataset(self): stack_to_move = generate_images() - origin_dataset = MixedDataset(stacks=[stack_to_move]) - destination_dataset = StrictDataset(sample=generate_images()) - self.presenter.get_dataset = mock.Mock(side_effect=[origin_dataset, destination_dataset]) + origin_dataset = Dataset(stacks=[stack_to_move]) + destination_dataset = Dataset(sample=generate_images()) + self.model.datasets[origin_dataset.id] = origin_dataset + self.model.datasets[destination_dataset.id] = destination_dataset self.presenter.get_stack = mock.Mock(return_value=stack_to_move) - self.presenter.remove_item_from_tree_view = mock.Mock() self.presenter.update_dataset_tree = mock.Mock() self.view.move_stack_dialog = mock.Mock() @@ -914,7 +816,8 @@ def test_move_stack_to_strict_dataset(self): self.presenter.get_stack.assert_called_once_with(stack_to_move.id) self.presenter.update_dataset_tree.assert_called_once() - self.assertNotIn(stack_to_move, origin_dataset) + self.assertIn(stack_to_move, destination_dataset.all) + self.assertNotIn(stack_to_move, origin_dataset.all) assert stack_to_move.name == new_stack_name def test_update_dataset_tree_no_datasets(self): diff --git a/mantidimaging/gui/windows/main/view.py b/mantidimaging/gui/windows/main/view.py index cbcb430af93..7cce5eeab41 100644 --- a/mantidimaging/gui/windows/main/view.py +++ b/mantidimaging/gui/windows/main/view.py @@ -656,17 +656,6 @@ def new_dataset_tree_widget_item(title: str, id: uuid.UUID, dataset_tree_item.setText(0, title) return dataset_tree_item - def create_dataset_tree_widget_item(self, title: str, id: uuid.UUID) -> QTreeDatasetWidgetItem: - dataset_tree_item = QTreeDatasetWidgetItem(self.dataset_tree_widget, id) - dataset_tree_item.setText(0, title) - return dataset_tree_item - - @staticmethod - def create_child_tree_item(parent: QTreeDatasetWidgetItem, dataset_id: uuid.UUID, name: str) -> None: - child = QTreeDatasetWidgetItem(parent, dataset_id) - child.setText(0, name) - parent.addChild(child) - @staticmethod def get_sinograms_item(parent: QTreeDatasetWidgetItem) -> QTreeDatasetWidgetItem | None: """ @@ -679,10 +668,6 @@ def get_sinograms_item(parent: QTreeDatasetWidgetItem) -> QTreeDatasetWidgetItem return child return None - def add_item_to_tree_view(self, item: QTreeWidgetItem) -> None: - self.dataset_tree_widget.insertTopLevelItem(self.dataset_tree_widget.topLevelItemCount(), item) - item.setExpanded(True) - def _open_tree_menu(self, position: QPoint) -> None: """ Opens the tree view menu.