Skip to content

Commit

Permalink
Move File -> Load 180 Projection to Add / Replace Stack dialog (#2403)
Browse files Browse the repository at this point in the history
  • Loading branch information
samtygier-stfc authored Nov 21, 2024
2 parents d056e76 + 68f80e6 commit c7980a2
Show file tree
Hide file tree
Showing 9 changed files with 8 additions and 162 deletions.
30 changes: 0 additions & 30 deletions mantidimaging/gui/test/gui_system_loading_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -64,36 +64,6 @@ def _click_stack_selector(cls):
def test_load_images(self):
self._load_images()

@mock.patch("mantidimaging.gui.windows.main.MainWindowView._get_file_name")
def test_load_180(self, mocked_select_file):
path_180 = Path(LOAD_SAMPLE).parents[1] / "180deg" / "IMAT_Flower_180deg_000000.tif"
mocked_select_file.return_value = path_180
self.assertEqual(len(self.main_window.presenter.get_active_stack_visualisers()), 0)
self._load_data_set()
stacks = self.main_window.presenter.get_active_stack_visualisers()
self.assertEqual(len(self.main_window.presenter.get_active_stack_visualisers()), 5)

# Remove existing 180
proj180deg_entry = self.main_window.dataset_tree_widget.findItems("180", Qt.MatchFlag.MatchRecursive)
self.assertEqual(len(proj180deg_entry), 1)
self.main_window.dataset_tree_widget.setCurrentItem(proj180deg_entry[0])
self.main_window._delete_container()

self.assertFalse(stacks[0].presenter.images.has_proj180deg())
self.assertEqual(len(self.main_window.presenter.get_active_stack_visualisers()), 4)

# load new 180
QTimer.singleShot(SHORT_DELAY, lambda: self._click_stack_selector())
self.main_window.actionLoad180deg.trigger()

wait_until(lambda: len(self.main_window.presenter.get_active_stack_visualisers()) == 5)

stacks_after = self.main_window.presenter.get_active_stack_visualisers()
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:
for line in log_file:
Expand Down
15 changes: 7 additions & 8 deletions mantidimaging/gui/ui/main_window.ui
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,6 @@
<addaction name="actionSampleLoadLog"/>
<addaction name="actionShutterCounts"/>
<addaction name="actionLoadProjectionAngles"/>
<addaction name="actionLoad180deg"/>
<addaction name="separator"/>
<addaction name="actionSaveImages"/>
<addaction name="actionSaveNeXusFile"/>
Expand Down Expand Up @@ -191,13 +190,13 @@
</property>
</action>
<action name="actionShutterCounts">
<property name="enabled">
<bool>false</bool>
</property>
<property name="text">
<string>Load ShutterCounts file for stack...</string>
</property>
</action>
<property name="enabled">
<bool>false</bool>
</property>
<property name="text">
<string>Load ShutterCounts file for stack...</string>
</property>
</action>
<action name="actionLoad180deg">
<property name="enabled">
<bool>false</bool>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ def __init__(self, parent, dataset_id: uuid.UUID, dataset_name: str):
self._dataset_id = dataset_id

self.imageTypeComboBox.addItems(
["Sample", "Flat Before", "Flat After", "Dark Before", "Dark After", "Recon", "Images"])
["Sample", "Flat Before", "Flat After", "Dark Before", "Dark After", "Recon", "Images", "Proj 180"])

self.datasetNameText.setText(dataset_name)
self.chooseFileButton.clicked.connect(self.choose_file_path)
Expand Down
17 changes: 0 additions & 17 deletions mantidimaging/gui/windows/main/model.py
Original file line number Diff line number Diff line change
Expand Up @@ -112,23 +112,6 @@ def get_existing_180_id(self, dataset_id: uuid.UUID) -> uuid.UUID | None:
return dataset.proj180deg.id
return None

def add_180_deg_to_dataset(self, dataset_id: uuid.UUID, _180_deg_file: str) -> ImageStack:
"""
Loads the 180 projection and adds this to a given Dataset ID.
:param dataset_id: The ID of the Dataset.
:param _180_deg_file: The location of the 180 projection.
:return: The loaded 180 ImageStack object.
"""
dataset = self.datasets.get(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")

_180_deg = loader.load_stack_from_group(FilenameGroup.from_file(_180_deg_file))
dataset.proj180deg = _180_deg
return _180_deg

def add_projection_angles_to_sample(self, images_id: uuid.UUID, proj_angles: ProjectionAngles) -> None:
images = self.get_images_by_uuid(images_id)
if images is None:
Expand Down
9 changes: 0 additions & 9 deletions mantidimaging/gui/windows/main/presenter.py
Original file line number Diff line number Diff line change
Expand Up @@ -398,15 +398,6 @@ def get_stack_with_images(self, images: ImageStack) -> StackVisualiserView:
return sv
raise RuntimeError(f"Did not find stack {images} in stacks! Stacks: {self.stack_visualisers.items()}")

def add_180_deg_file_to_dataset(self, dataset_id: uuid.UUID, _180_deg_file: str) -> None:
"""
Loads a 180 file then adds it to the dataset, creates a stack window, and updates the dataset tree view.
:param dataset_id: The ID of the dataset to update.
:param _180_deg_file: The filename for the 180 file.
"""
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)

Expand Down
24 changes: 0 additions & 24 deletions mantidimaging/gui/windows/main/test/model_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -217,30 +217,6 @@ def test_add_log_to_sample_no_stack(self, load_log: mock.Mock):

stack_mock.assert_called_with(images_id)

@mock.patch('mantidimaging.core.io.loader.load_stack_from_group')
def test_add_180_deg_to_dataset(self, load: mock.Mock):
_180_file = "180 file"
dataset_id = "id"
self.model.datasets[dataset_id] = dataset_mock = StrictDataset(sample=generate_images())
load.return_value = _180_stack = generate_images()
self.model.add_180_deg_to_dataset(dataset_id=dataset_id, _180_deg_file=_180_file)

load_arg = load.call_args[0][0]
self.assertEqual(load_arg.first_file().name, _180_file)
self.assertEqual(_180_stack, dataset_mock.proj180deg)

@mock.patch('mantidimaging.core.io.loader.load')
def test_add_180_deg_to_dataset_no_dataset(self, load: mock.Mock):
"""
Test in add_180_deg_to_stack when get_images_by_uuid returns None
"""
_180_file = "180 file"
dataset_id = "id"
self.assertRaises(RuntimeError,
self.model.add_180_deg_to_dataset,
dataset_id=dataset_id,
_180_deg_file=_180_file)

def test_add_projection_angles_to_sample_no_stack(self):
proj_angles = ProjectionAngles(np.arange(0, 10))
images_id = "id"
Expand Down
24 changes: 0 additions & 24 deletions mantidimaging/gui/windows/main/test/presenter_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -259,30 +259,6 @@ def test_get_stack_with_images_failure(self):
with self.assertRaises(RuntimeError):
self.presenter.get_stack_with_images(generate_images())

def test_add_first_180_deg_to_dataset(self):
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_images_to_existing_dataset = mock.Mock()

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):
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.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.assertNotIn(existing_180_stack, self.presenter.stack_visualisers)
self.view.model_changed.emit.assert_called_once()

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)
Expand Down
24 changes: 0 additions & 24 deletions mantidimaging/gui/windows/main/test/view_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,28 +43,6 @@ def test_execute_save(self):

self.presenter.notify.assert_called_once_with(PresNotification.IMAGE_FILE_SAVE)

@mock.patch("mantidimaging.gui.windows.main.view.DatasetSelectorDialog")
@mock.patch("mantidimaging.gui.windows.main.view.QFileDialog.getOpenFileName")
def test_load_180_deg_dialog(self, get_open_file_name: mock.Mock, dataset_selector_dialog: mock.Mock):
dataset_selector_dialog.return_value.exec.return_value = QDialog.DialogCode.Accepted
dataset_id = "dataset-id"
dataset_selector_dialog.return_value.selected_id = dataset_id
selected_file = "~/home/test/directory/selected_file.tif"
get_open_file_name.return_value = (selected_file, None)
_180_dataset = mock.MagicMock()
self.presenter.add_180_deg_file_to_dataset.return_value = _180_dataset

self.view.load_180_deg_dialog()

dataset_selector_dialog.assert_called_once_with(main_window=self.view,
title='Dataset Selector',
message="Which dataset is the 180 projection being loaded for?")
get_open_file_name.assert_called_once_with(caption="180 Degree Image",
filter="Image File (*.tif *.tiff);;All (*.*)",
initialFilter="Image File (*.tif *.tiff)")
self.presenter.add_180_deg_file_to_dataset.assert_called_once_with(dataset_id=dataset_id,
_180_deg_file=selected_file)

def test_execute_load(self):
self.view.execute_image_file_load()

Expand Down Expand Up @@ -214,7 +192,6 @@ def test_update_shortcuts_with_presenter_with_no_stacks(self):
def _update_shortcuts_test(self, original_state, has_stacks):
self.view.actionSaveImages.setEnabled(original_state)
self.view.actionSampleLoadLog.setEnabled(original_state)
self.view.actionLoad180deg.setEnabled(original_state)
self.view.actionLoadProjectionAngles.setEnabled(original_state)
self.view.menuWorkflow.setEnabled(original_state)
self.view.menuImage.setEnabled(original_state)
Expand All @@ -223,7 +200,6 @@ def _update_shortcuts_test(self, original_state, has_stacks):

self.assertEqual(has_stacks, self.view.actionSaveImages.isEnabled())
self.assertEqual(has_stacks, self.view.actionSampleLoadLog.isEnabled())
self.assertEqual(has_stacks, self.view.actionLoad180deg.isEnabled())
self.assertEqual(has_stacks, self.view.actionLoadProjectionAngles.isEnabled())
self.assertEqual(has_stacks, self.view.menuWorkflow.isEnabled())
self.assertEqual(has_stacks, self.view.menuImage.isEnabled())
Expand Down
25 changes: 0 additions & 25 deletions mantidimaging/gui/windows/main/view.py
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,6 @@ class MainWindowView(BaseMainWindowView):
actionSampleLoadLog: QAction
actionShutterCounts: QAction
actionLoadProjectionAngles: QAction
actionLoad180deg: QAction
actionLoadDataset: QAction
actionLoadImages: QAction
actionLoadNeXusFile: QAction
Expand Down Expand Up @@ -188,7 +187,6 @@ def setup_shortcuts(self) -> None:
self.actionLoadNeXusFile.triggered.connect(self.show_nexus_load_dialog)
self.actionSampleLoadLog.triggered.connect(self.load_sample_log_dialog)
self.actionShutterCounts.triggered.connect(self.load_shuttercounts_dialog)
self.actionLoad180deg.triggered.connect(self.load_180_deg_dialog)
self.actionLoadProjectionAngles.triggered.connect(self.load_projection_angles)
self.actionSaveImages.triggered.connect(self.show_image_save_dialog)
self.actionSaveNeXusFile.triggered.connect(self.show_nexus_save_dialog)
Expand Down Expand Up @@ -232,7 +230,6 @@ def update_shortcuts(self) -> None:
self.actionSaveNeXusFile.setEnabled(has_datasets)
self.actionSampleLoadLog.setEnabled(has_datasets)
self.actionShutterCounts.setEnabled(has_datasets)
self.actionLoad180deg.setEnabled(has_datasets)
self.actionLoadProjectionAngles.setEnabled(has_datasets)
self.menuWorkflow.setEnabled(has_datasets)
self.menuImage.setEnabled(has_datasets)
Expand Down Expand Up @@ -347,28 +344,6 @@ def load_shuttercounts_dialog(self) -> None:
if self.spectrum_viewer:
self.spectrum_viewer.handle_shuttercount_change()

def load_180_deg_dialog(self) -> None:
dataset_selector = DatasetSelectorDialog(main_window=self,
title="Dataset Selector",
message="Which dataset is the 180 projection being loaded for?")
# Was closed without accepting (e.g. via x button or ESC)
if QDialog.DialogCode.Accepted != dataset_selector.exec():
return
dataset_to_add_180_deg_to = dataset_selector.selected_id

if dataset_to_add_180_deg_to is None:
QMessageBox.critical(self, "Error", "No dataset selected.")
return

# Open file dialog
selected_file = self._get_file_name("180 Degree Image", "Image File (*.tif *.tiff)")

# Cancel/Close was clicked
if selected_file == "":
return

self.presenter.add_180_deg_file_to_dataset(dataset_id=dataset_to_add_180_deg_to, _180_deg_file=selected_file)

LOAD_PROJECTION_ANGLES_DIALOG_MESSAGE = "Which stack are the projection angles in DEGREES being loaded for?"
LOAD_PROJECTION_ANGLES_FILE_DIALOG_CAPTION = "File with projection angles in DEGREES"

Expand Down

0 comments on commit c7980a2

Please sign in to comment.