Skip to content
10 changes: 5 additions & 5 deletions mantidimaging/core/io/saver.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
from ..utility.version_check import CheckVersion

if TYPE_CHECKING:
from ..data.dataset import StrictDataset
from ..data.dataset import Dataset
from ..data.imagestack import ImageStack
from ..utility.data_containers import Indices

Expand Down Expand Up @@ -180,7 +180,7 @@ def image_save(images: ImageStack,
return names


def nexus_save(dataset: StrictDataset, path: str, sample_name: str, save_as_float: bool) -> None:
def nexus_save(dataset: Dataset, path: str, sample_name: str, save_as_float: bool) -> None:
"""
Uses information from a StrictDataset to create a NeXus file.
:param dataset: The dataset to save as a NeXus file.
Expand All @@ -202,7 +202,7 @@ def nexus_save(dataset: StrictDataset, path: str, sample_name: str, save_as_floa
nexus_file.close()


def _nexus_save(nexus_file: h5py.File, dataset: StrictDataset, sample_name: str, save_as_float: bool) -> None:
def _nexus_save(nexus_file: h5py.File, dataset: Dataset, sample_name: str, save_as_float: bool) -> None:
"""
Takes a NeXus file and writes the StrictDataset information to it.
:param nexus_file: The NeXus file.
Expand Down Expand Up @@ -255,7 +255,7 @@ def _nexus_save(nexus_file: h5py.File, dataset: StrictDataset, sample_name: str,
_save_recon_to_nexus(nexus_file, recon, dataset.sample.filenames[0])


def _save_processed_data_to_nexus(nexus_file: h5py.File, dataset: StrictDataset, rotation_angle: h5py.Dataset,
def _save_processed_data_to_nexus(nexus_file: h5py.File, dataset: Dataset, rotation_angle: h5py.Dataset,
image_key: h5py.Dataset, save_as_float: bool) -> None:
data = nexus_file.create_group(NEXUS_PROCESSED_DATA_PATH)
data["rotation_angle"] = rotation_angle
Expand All @@ -270,7 +270,7 @@ def _save_processed_data_to_nexus(nexus_file: h5py.File, dataset: StrictDataset,
process.create_dataset("version", data=np.bytes_(package_version))


def _save_image_stacks_to_nexus(dataset: StrictDataset, data_group: h5py.Group, save_as_float: bool) -> None:
def _save_image_stacks_to_nexus(dataset: Dataset, data_group: h5py.Group, save_as_float: bool) -> None:
combined_data_shape = (sum([len(arr) for arr in dataset.nexus_arrays]), ) + dataset.nexus_arrays[0].shape[1:]

index = 0
Expand Down
15 changes: 7 additions & 8 deletions mantidimaging/eyes_tests/base_eyes.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
from PyQt5.QtWidgets import QMainWindow, QMenu, QWidget, QApplication

from mantidimaging.core.data import ImageStack
from mantidimaging.core.data.dataset import StrictDataset, MixedDataset
from mantidimaging.core.data.dataset import StrictDataset, Dataset
from mantidimaging.core.io.loader import loader
from mantidimaging.core.utility.data_containers import Indices
from mantidimaging.eyes_tests.eyes_manager import EyesManager
Expand Down Expand Up @@ -118,16 +118,15 @@ def _load_strict_data_set(self, set_180: bool = False):

return vis

def _create_mixed_dataset(self) -> MixedDataset:
mixed_dataset = MixedDataset(stacks=[generate_images()], name="a-mixed-dataset")

self.imaging.presenter.model.add_dataset_to_model(mixed_dataset)
self.imaging.presenter.create_mixed_dataset_tree_view_items(mixed_dataset)
self.imaging.presenter.create_mixed_dataset_stack_windows(mixed_dataset)
def _create_new_dataset(self) -> Dataset:
new_dataset = Dataset(sample=generate_images(), name="new")
self.imaging.presenter.create_strict_dataset_stack_windows(new_dataset)
self.imaging.presenter.create_strict_dataset_tree_view_items(new_dataset)
self.imaging.presenter.model.add_dataset_to_model(new_dataset)

QApplication.sendPostedEvents()

return mixed_dataset
return new_dataset

def _get_top_level_widget(cls, widget_type):
for widget in cls.app.topLevelWidgets():
Expand Down
35 changes: 5 additions & 30 deletions mantidimaging/eyes_tests/main_window_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -94,44 +94,19 @@ def test_clicking_tab_changes_tree_view_selection(self):

self.check_target()

def test_move_stack_dialog_when_both_strict(self):
def test_move_within_dataset(self):
sample_vis = self._load_strict_data_set()
self._load_strict_data_set()

self.imaging.presenter._set_tree_view_selection_with_id(sample_vis.id)

self.imaging._move_stack()
self.check_target(self.imaging.move_stack_dialog)

def test_move_stack_dialog_strict_to_mixed(self):
sample_vis = self._load_strict_data_set()
mixed_ds = self._create_mixed_dataset()

self.imaging.presenter._set_tree_view_selection_with_id(sample_vis.id)

self.imaging._move_stack()
self.imaging.move_stack_dialog.datasetSelector.setCurrentText(mixed_ds.name)
self.check_target(self.imaging.move_stack_dialog)

def test_move_stack_dialog_mixed_to_strict(self):
mixed_ds = self._create_mixed_dataset()
def test_move_to_another_dataset(self):
sample_vis = self._load_strict_data_set()
strict_ds_id = self.imaging.presenter.model.get_parent_dataset(sample_vis.id)
strict_ds = self.imaging.get_dataset(strict_ds_id)

self.imaging.presenter._set_tree_view_selection_with_id(mixed_ds.all[0].id)
new_dataset = self._create_new_dataset()

self.imaging.presenter._set_tree_view_selection_with_id(sample_vis.id)
self.imaging._move_stack()
self.imaging.move_stack_dialog.datasetSelector.setCurrentText(strict_ds.name)
self.check_target(self.imaging.move_stack_dialog)
self.imaging.move_stack_dialog.datasetSelector.setCurrentText(new_dataset.name)

def test_move_stack_dialog_both_mixed(self):
mixed_ds_1 = self._create_mixed_dataset()
mixed_ds_2 = self._create_mixed_dataset()
mixed_ds_2.name = "other-mixed-ds-name"

self.imaging.presenter._set_tree_view_selection_with_id(mixed_ds_1.all[0].id)

self.imaging._move_stack()
self.imaging.move_stack_dialog.datasetSelector.setCurrentText(mixed_ds_2.name)
self.check_target(self.imaging.move_stack_dialog)
11 changes: 4 additions & 7 deletions mantidimaging/eyes_tests/nexus_save_dialog_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,21 +2,18 @@
# SPDX - License - Identifier: GPL-3.0-or-later
from __future__ import annotations

from typing import NamedTuple
from unittest import mock
from uuid import UUID, uuid4

from mantidimaging.core.data.dataset import Dataset
from mantidimaging.eyes_tests.base_eyes import BaseEyesTest


class NexusSaveDialogTest(BaseEyesTest):

def test_save_dialog_opens_with_dataset(self):
TestTuple = NamedTuple('TestTuple', [('id', UUID), ('name', str)])
dataset_list = [TestTuple(uuid4(), 'Test Dataset')]
with mock.patch("mantidimaging.gui.windows.main.MainWindowView.strict_dataset_list",
new_callable=mock.PropertyMock) as mock_dataset_list:
mock_dataset_list.return_value = dataset_list
with mock.patch("mantidimaging.gui.windows.main.MainWindowPresenter.datasets",
new_callable=mock.PropertyMock) as mock_datasets:
mock_datasets.return_value = [Dataset(name='Test Dataset')]
self.imaging.actionSaveNeXusFile.trigger()

self.check_target(widget=self.imaging.nexus_save_dialog)
6 changes: 0 additions & 6 deletions mantidimaging/gui/widgets/dataset_selector/presenter.py
Original file line number Diff line number Diff line change
Expand Up @@ -97,9 +97,3 @@ def do_select_eligible_stack(self) -> None:
if "dark" not in name and "flat" not in name and "180deg" not in name:
self.view.setCurrentIndex(i)
break

@property
def current_is_strict(self) -> bool:
if self.current_dataset is None:
return False
return self.view.main_window.is_dataset_strict(self.current_dataset)
Original file line number Diff line number Diff line change
Expand Up @@ -117,12 +117,3 @@ def test_do_reload_datasets_by_dataset_type(self):
self.view.addItem.assert_any_call(self.img1.name, self.img1.id)
self.view.addItem.assert_any_call(self.img2.name, self.img2.id)
self.view.addItem.assert_any_call(self.img3.name, self.img3.id)

def test_current_is_strict(self):
self.presenter.current_dataset = "current-dataset-id"
self.assertEqual(self.presenter.current_is_strict, self.view.main_window.is_dataset_strict.return_value)
self.view.main_window.is_dataset_strict.assert_called_once_with(self.presenter.current_dataset)

def test_current_is_strict_returns_false_when_current_is_none(self):
self.presenter.current_dataset = None
self.assertFalse(self.presenter.current_is_strict)
3 changes: 0 additions & 3 deletions mantidimaging/gui/widgets/dataset_selector/test/view_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,3 @@ def test_try_to_select_relevant_stack(self):
self.view.try_to_select_relevant_stack("flat")
self.assertEqual(self.view.currentIndex(), 0)
self.assertEqual(self.view.currentText(), "flat_0001")

def test_current_is_strict(self):
self.assertEqual(self.view.current_is_strict(), self.presenter.current_is_strict)
3 changes: 0 additions & 3 deletions mantidimaging/gui/widgets/dataset_selector/view.py
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,3 @@ def try_to_select_relevant_stack(self, name: str) -> None:

def select_eligible_stack(self) -> None:
self.presenter.notify(Notification.SELECT_ELIGIBLE_STACK)

def current_is_strict(self) -> bool:
return self.presenter.current_is_strict
32 changes: 10 additions & 22 deletions mantidimaging/gui/windows/main/model.py
Original file line number Diff line number Diff line change
Expand Up @@ -87,13 +87,13 @@ def do_images_saving(self, images_id: uuid.UUID, output_dir: str, name_prefix: s
images.filenames = filenames
return True

def do_nexus_saving(self, dataset_id: uuid.UUID, path: str, sample_name: str, save_as_float: bool) -> bool:
def do_nexus_saving(self, dataset_id: uuid.UUID, path: str, sample_name: str, save_as_float: bool) -> None:
dataset = self.datasets.get(dataset_id)
if isinstance(dataset, StrictDataset):
saver.nexus_save(dataset, path, sample_name, save_as_float)
return True
else:
raise RuntimeError(f"Failed to get StrictDataset with ID {dataset_id}")
if not dataset:
raise RuntimeError(f"Failed to get Dataset with ID {dataset_id}")
if not dataset.sample:
raise RuntimeError(f"Dataset with ID {dataset_id} does not have a sample")
saver.nexus_save(dataset, path, sample_name, save_as_float)

def get_existing_180_id(self, dataset_id: uuid.UUID) -> uuid.UUID | None:
"""
Expand Down Expand Up @@ -187,9 +187,9 @@ def remove_container(self, container_id: uuid.UUID) -> list[uuid.UUID]:
for dataset in self.datasets.values():
if container_id in dataset:
proj_180_id = None
# If we're deleting a sample from a StrictDataset then any linked 180 projection will also be
# If we're deleting a sample then any linked 180 projection will also be
# deleted
if isinstance(dataset, StrictDataset) and dataset.proj180deg:
if dataset.proj180deg:
assert dataset.sample is not None
if dataset.sample.id == container_id:
proj_180_id = dataset.proj180deg.id
Expand Down Expand Up @@ -222,13 +222,13 @@ def images(self) -> list[ImageStack]:
def proj180s(self) -> list[ImageStack]:
proj180s = []
for dataset in self.datasets.values():
if isinstance(dataset, StrictDataset) and dataset.proj180deg is not None:
if dataset.proj180deg is not None:
proj180s.append(dataset.proj180deg)
return proj180s

def get_parent_dataset(self, member_id: uuid.UUID) -> uuid.UUID:
"""
Takes the ID of an image stack and returns the ID of its parent strict dataset.
Takes the ID of an image stack and returns the ID of its parent dataset.
:param member_id: The ID of the image stack.
:return: The ID of the parent dataset if found.
"""
Expand Down Expand Up @@ -256,15 +256,3 @@ def recon_list_ids(self) -> list[uuid.UUID]:

def get_recon_list_id(self, parent_id: uuid.UUID) -> uuid.UUID:
return self.datasets[parent_id].recons.id

def is_dataset_strict(self, ds_id: uuid.UUID) -> bool:
"""
:param ds_id: The dataset ID
:return: True if the dataset is Strict, False otherwise
"""
for ds in self.datasets.values():
if ds.id == ds_id:
if isinstance(ds, StrictDataset):
return True
return False
raise RuntimeError(f"Unable to find dataset with ID {ds_id}")
10 changes: 6 additions & 4 deletions mantidimaging/gui/windows/main/nexus_save_dialog.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,12 @@
from __future__ import annotations
import os
import uuid
from collections.abc import Iterable

from PyQt5.QtWidgets import QDialogButtonBox, QFileDialog, QRadioButton

from mantidimaging.core.data.dataset import Dataset
from mantidimaging.gui.mvp_base import BaseDialogView
from mantidimaging.gui.windows.main.presenter import DatasetId

NXS_EXT = ".nxs"

Expand All @@ -18,7 +19,7 @@ class NexusSaveDialog(BaseDialogView):
floatRadioButton: QRadioButton
intRadioButton: QRadioButton

def __init__(self, parent, dataset_list: list[DatasetId]):
def __init__(self, parent, dataset_list: Iterable[Dataset]):
super().__init__(parent, 'gui/ui/nexus_save_dialog.ui')

self.browseButton.clicked.connect(self._set_save_path)
Expand All @@ -32,9 +33,10 @@ def __init__(self, parent, dataset_list: list[DatasetId]):

self.selected_dataset = None

def _create_dataset_lists(self, dataset_list):
def _create_dataset_lists(self, dataset_list: Iterable[Dataset]):
if dataset_list:
self.dataset_uuids, dataset_names = zip(*dataset_list, strict=True)
self.dataset_uuids = [ds.id for ds in dataset_list]
dataset_names = [ds.name for ds in dataset_list]
self.datasetNames.addItems(dataset_names)

def accept(self) -> None:
Expand Down
16 changes: 0 additions & 16 deletions mantidimaging/gui/windows/main/presenter.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,11 +40,6 @@ class StackId(NamedTuple):
name: str


class DatasetId(NamedTuple):
id: uuid.UUID
name: str


logger = getLogger(__name__)


Expand Down Expand Up @@ -419,14 +414,6 @@ def stack_visualiser_list(self) -> list[StackId]:
def datasets(self) -> Iterable[Dataset]:
return self.model.datasets.values()

@property
def strict_dataset_list(self) -> list[DatasetId]:
datasets = [
DatasetId(dataset.id, dataset.name) for dataset in self.model.datasets.values()
if isinstance(dataset, StrictDataset)
]
return sorted(datasets, key=lambda x: x.name)

@property
def all_dataset_ids(self) -> Iterable[uuid.UUID]:
return self.model.datasets.keys()
Expand Down Expand Up @@ -843,9 +830,6 @@ def _create_strict_dataset_stack_name(stack_type: str, dataset_name: str) -> str
"""
return f"{stack_type} {dataset_name}"

def is_dataset_strict(self, ds_id: uuid.UUID) -> bool:
return self.model.is_dataset_strict(ds_id)

def do_update_UI(self) -> None:
if settings.value('use_os_defaults', defaultValue='True') == 'True':
extra_style = settings.value('extra_style_default')
Expand Down
18 changes: 2 additions & 16 deletions mantidimaging/gui/windows/main/test/model_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -522,33 +522,19 @@ def test_do_nexus_saving_fails_from_no_dataset(self):
self.model.do_nexus_saving("bad-dataset-id", "path", "sample-name", True)

def test_do_nexus_saving_fails_from_wrong_dataset(self):
md = MixedDataset()
md = Dataset() # no sample
self.model.add_dataset_to_model(md)

with self.assertRaises(RuntimeError):
self.model.do_nexus_saving(md.id, "path", "sample-name", True)

@mock.patch("mantidimaging.gui.windows.main.model.saver.nexus_save")
def test_do_nexus_save_success(self, nexus_save):
sd = StrictDataset(sample=generate_images())
sd = Dataset(sample=generate_images())
self.model.add_dataset_to_model(sd)
path = "path"
sample_name = "sample-name"
save_as_float = True

self.model.do_nexus_saving(sd.id, path, sample_name, save_as_float)
nexus_save.assert_called_once_with(sd, path, sample_name, save_as_float)

def test_is_dataset_strict_returns_true(self):
strict_ds = StrictDataset(sample=generate_images())
self.model.add_dataset_to_model(strict_ds)
self.assertTrue(self.model.is_dataset_strict(strict_ds.id))

def test_is_dataset_strict_returns_false(self):
mixed_ds = MixedDataset(stacks=[generate_images()])
self.model.add_dataset_to_model(mixed_ds)
self.assertFalse(self.model.is_dataset_strict(mixed_ds.id))

def test_is_dataset_strict_raises(self):
with self.assertRaises(RuntimeError):
self.model.is_dataset_strict(uuid.uuid4())
9 changes: 5 additions & 4 deletions mantidimaging/gui/windows/main/test/nexus_save_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
from unittest import mock

from mantidimaging.gui.windows.main.nexus_save_dialog import NexusSaveDialog
from mantidimaging.gui.windows.main.presenter import DatasetId
from mantidimaging.test_helpers import start_qapplication


Expand Down Expand Up @@ -62,11 +61,13 @@ def test_save_enabled(self):
def test_dataset_lists_creation(self):
dataset_id = "dataset-id"
dataset_name = "dataset-name"
ds = mock.Mock(id=dataset_id)
ds.name = dataset_name
self.nexus_save_dialog.datasetNames = mock.Mock()
self.nexus_save_dialog._create_dataset_lists([DatasetId(dataset_id, dataset_name)])
self.nexus_save_dialog._create_dataset_lists([ds])

self.assertEqual(self.nexus_save_dialog.dataset_uuids, (dataset_id, ))
self.nexus_save_dialog.datasetNames.addItems.assert_called_once_with((dataset_name, ))
self.assertEqual(self.nexus_save_dialog.dataset_uuids, [dataset_id])
self.nexus_save_dialog.datasetNames.addItems.assert_called_once_with([dataset_name])

@mock.patch("mantidimaging.gui.windows.main.nexus_save_dialog.QFileDialog.getSaveFileName")
def test_set_save_path_adds_extension(self, get_save_file_name_mock):
Expand Down
Loading
Loading