Esempio n. 1
0
    def find_initial_cor(self) -> Tuple[int, ScalarCoR]:
        if self.images is None:
            return 0, ScalarCoR(0)

        first_slice_to_recon = self.images.height // 2
        cor = ScalarCoR(self.images.h_middle)
        return first_slice_to_recon, cor
 def setUp(self, model) -> None:
     self.view = mock.MagicMock()
     self.model = model.return_value
     self.recon_params = ReconstructionParameters("", "", 0, ScalarCoR(2),
                                                  Degrees(2), 2, 2)
     self.presenter = CORInspectionDialogPresenter(self.view,
                                                   th.generate_images(), 5,
                                                   ScalarCoR(2),
                                                   self.recon_params, False)
Esempio n. 3
0
    def test_get_me_a_cor(self):
        self.assertEqual(15, self.model.get_me_a_cor(cor=15))

        self.model.data_model.clear_results()
        self.model.last_cor = ScalarCoR(26)
        self.assertEqual(26, self.model.get_me_a_cor().value)

        self.model.data_model.set_precalculated(ScalarCoR(150), Degrees(1.5))
        self.model.preview_slice_idx = 5
        cor = self.model.get_me_a_cor()

        # expected cor value obtained by running the test
        self.assertAlmostEqual(149.86, cor.value, delta=1e-2)
    def test_init_sets_get_title(self):
        with mock.patch(
                "mantidimaging.gui.dialogs.cor_inspection.CORInspectionDialogModel"
        ):
            presenter = CORInspectionDialogPresenter(self.view,
                                                     th.generate_images(), 5,
                                                     ScalarCoR(2),
                                                     self.recon_params, True)
            assert "Iterations" in presenter.get_title(ImageType.CURRENT)

            presenter = CORInspectionDialogPresenter(self.view,
                                                     th.generate_images(), 5,
                                                     ScalarCoR(2),
                                                     self.recon_params, False)
            assert "COR" in presenter.get_title(ImageType.CURRENT)
Esempio n. 5
0
    def test_adjust_cor(self):
        images = generate_images()
        m = CORInspectionDialogModel(
            images, 5, ScalarCoR(20),
            ReconstructionParameters('FBP_CUDA', 'ram-lak'), False)
        m.centre_value = 5
        m.step = 1

        m.adjust(ImageType.CURRENT)
        self.assertEqual(m.centre_value, 5)
        self.assertEqual(m.step, 0.5)

        m.adjust(ImageType.LESS)
        self.assertEqual(m.centre_value, 4.5)
        self.assertEqual(m.step, 0.5)

        m.adjust(ImageType.CURRENT)
        self.assertEqual(m.centre_value, 4.5)
        self.assertEqual(m.step, 0.25)

        m.adjust(ImageType.MORE)
        self.assertEqual(m.centre_value, 4.75)
        self.assertEqual(m.step, 0.25)

        m.adjust(ImageType.CURRENT)
        self.assertEqual(m.centre_value, 4.75)
        self.assertEqual(m.step, 0.125)
Esempio n. 6
0
def find_center(images: Images,
                progress: Progress) -> Tuple[ScalarCoR, Degrees]:
    # assume the ROI is the full image, i.e. the slices are ALL rows of the image
    slices = np.arange(images.height)
    shift = pu.create_array((images.height, ))

    search_range = get_search_range(images.width)
    min_correlation_error = pu.create_array((len(search_range), images.height))
    shared_search_range = pu.create_array((len(search_range), ),
                                          dtype=np.int32)
    shared_search_range[:] = np.asarray(search_range, dtype=np.int32)
    _calculate_correlation_error(images, shared_search_range,
                                 min_correlation_error, progress)

    # Originally the output of do_search is stored in dimensions
    # corresponding to (search_range, square sum). This is awkward to navigate
    # we transpose store to make the array hold (square sum, search range)
    # so that each store[row] accesses the information for the row's square sum across all search ranges
    _find_shift(images, search_range, min_correlation_error, shift)

    par = np.polyfit(slices, shift, deg=1)
    m = par[0]
    q = par[1]
    LOG.debug(f"m={m}, q={q}")
    theta = Degrees(np.rad2deg(np.arctan(0.5 * m)))
    offset = np.round(m * images.height * 0.5 + q) * 0.5
    LOG.info(f"found offset: {-offset} and tilt {theta}")
    return ScalarCoR(images.h_middle + -offset), theta
Esempio n. 7
0
    def test_set_precalculated(self):
        self.model.data_model._points = [
            Point(50, 1),
            Point(40, 2),
            Point(30, 3),
            Point(20, 4)
        ]

        # a line with a slope of 'below' gives 4 degree tilt
        expected_slope = -0.06992681194351041
        self.model.set_precalculated(ScalarCoR(1000.0), Degrees(4.0))
        cor, angle, slope = self.model.get_results()
        self.assertEqual(cor.value, 1000.0)
        self.assertEqual(angle.value, 4.0)
        self.assertEqual(slope.value, expected_slope)

        # pre-calculated by hand
        expected_cors_with_this_gradient = [
            996.5036594028245, 997.2029275222595, 997.9021956416947,
            998.6014637611298
        ]
        for i, point in enumerate(self.model.data_model._points):
            self.assertEqual(point.cor, expected_cors_with_this_gradient[i])

        some_cor = self.model.data_model.get_cor_from_regression(1555)

        self.assertEqual(some_cor, 891.2638074278414)
def find_center(images: Images,
                progress: Progress) -> Tuple[ScalarCoR, Degrees]:
    # assume the ROI is the full image, i.e. the slices are ALL rows of the image
    slices = np.arange(images.height)
    with pu.temp_shared_array((images.height, )) as shift:
        # this is the area that is looked into for the shift after overlapping the images
        search_range = get_search_range(images.width)

        func = shared_mem.create_partial(do_search,
                                         shared_mem.fwd_index_only,
                                         image_width=images.width,
                                         p0=images.projection(0),
                                         p180=np.fliplr(
                                             images.proj180deg.data[0]),
                                         search_range=search_range)
        shared_mem.execute(shift,
                           func,
                           progress=progress,
                           msg="Finding correlation on row")
        par = np.polyfit(slices, shift, deg=1)
        m = par[0]
        q = par[1]
        LOG.debug(f"m={m}, q={q}")
        theta = Degrees(np.rad2deg(np.arctan(0.5 * m)))
        offset = np.round(m * images.height * 0.5 + q) * 0.5
        LOG.info(f"found offset: {-offset} and tilt {theta}")
        return ScalarCoR(images.h_middle + -offset), theta
Esempio n. 9
0
 def test_current_cor(self):
     images = generate_images()
     m = CORInspectionDialogModel(images, 5, ScalarCoR(20), ReconstructionParameters('FBP_CUDA', 'ram-lak'))
     m.centre_cor = 5
     m.cor_step = 1
     self.assertEqual(m.cor(ImageType.LESS), 4)
     self.assertEqual(m.cor(ImageType.CURRENT), 5)
     self.assertEqual(m.cor(ImageType.MORE), 6)
Esempio n. 10
0
 def __init__(self, data_model: CorTiltPointQtModel):
     self.stack: Optional['StackVisualiserView'] = None
     self._preview_projection_idx = 0
     self._preview_slice_idx = 0
     self._selected_row = 0
     self.data_model = data_model
     self._last_result = None
     self._last_cor = ScalarCoR(0.0)
Esempio n. 11
0
 def test_construct(self):
     images = generate_images()
     m = CORInspectionDialogModel(
         images, 5, ScalarCoR(20),
         ReconstructionParameters('FBP_CUDA', 'ram-lak'), False)
     npt.assert_equal(m.sino, images.sino(5))
     self.assertEqual(m.cor_extents, (0, 9))
     self.assertEqual(m.proj_angles.value.shape, (10, ))
Esempio n. 12
0
    def test_divide_iters_step(self):
        images = generate_images()
        m = CORInspectionDialogModel(
            images, 5, ScalarCoR(20),
            ReconstructionParameters('FBP_CUDA', 'ram-lak'), True)
        m.step = 11

        m._divide_step()
        self.assertEqual(m.step, 5)
Esempio n. 13
0
 def recon_params(self) -> ReconstructionParameters:
     return ReconstructionParameters(
         algorithm=self.algorithm_name,
         filter_name=self.filter_name,
         num_iter=self.num_iter,
         cor=ScalarCoR(self.rotation_centre),
         tilt=Degrees(self.tilt),
         pixel_size=self.pixel_size,
         max_projection_angle=self.max_proj_angle)
Esempio n. 14
0
    def test_iters_mode_init(self):
        images = generate_images()
        m = CORInspectionDialogModel(
            images, 5, ScalarCoR(20),
            ReconstructionParameters('FBP_CUDA', 'ram-lak'), True)

        self.assertEqual(m.centre_value, INIT_ITERS_CENTRE_VALUE)
        self.assertEqual(m.step, INIT_ITERS_STEP)
        self.assertEqual(m._recon_preview, m._recon_iters_preview)
        self.assertEqual(m._divide_step, m._divide_iters_step)
Esempio n. 15
0
 def test_recon_params(self, recon_params_mock):
     self.view.recon_params()
     recon_params_mock.assert_called_once_with(
         algorithm=self.algorithmName.currentText.return_value,
         filter_name=self.filterName.currentText.return_value,
         num_iter=self.numIter.value.return_value,
         cor=ScalarCoR(self.resultCor.value.return_value),
         tilt=Degrees(self.resultTilt.value.return_value),
         pixel_size=self.pixelSize.value.return_value,
         max_projection_angle=self.maxProjAngle.value.return_value)
Esempio n. 16
0
    def test_cor_mode_init(self):
        images = generate_images()
        initial_cor = ScalarCoR(20)
        m = CORInspectionDialogModel(
            images, 5, initial_cor,
            ReconstructionParameters('FBP_CUDA', 'ram-lak'), False)

        self.assertEqual(m.centre_value, initial_cor.value)
        self.assertEqual(m.step, images.width * 0.05)
        self.assertEqual(m._recon_preview, m._recon_cor_preview)
        self.assertEqual(m._divide_step, m._divide_cor_step)
Esempio n. 17
0
    def test_recon_iters_preview(self, replace_mock):
        images = generate_images()
        m = CORInspectionDialogModel(
            images, 5, ScalarCoR(20),
            ReconstructionParameters('FBP_CUDA', 'ram-lak'), True)

        m.reconstructor = Mock()
        m.recon_preview(ImageType.CURRENT)
        replace_mock.assert_called_once_with(m.recon_params, num_iter=100)
        m.reconstructor.single_sino.assert_called_once_with(
            m.sino, m.initial_cor, m.proj_angles, replace_mock.return_value)
Esempio n. 18
0
    def test_initial_select_data(self):
        test_cor = ScalarCoR(50)
        test_tilt = Degrees(1.5)
        self.model.preview_projection_idx = 150
        self.model.preview_slice_idx = 150
        self.model.set_precalculated(test_cor, test_tilt)

        self.model.initial_select_data(self.stack)

        self.assertNotEqual(test_cor, self.model.last_cor)
        self.assertNotEqual(test_tilt, self.model.tilt_angle)
        self.assertEqual(0, self.model.preview_projection_idx)
        self.assertEqual(64, self.model.preview_slice_idx)
    def test_do_refine_selected_cor_declined(self, mock_corview):
        self.presenter.model.preview_slice_idx = 155
        self.presenter.model.last_cor = ScalarCoR(314)
        self.presenter.do_preview_reconstruct_slice = mock.Mock()

        mock_dialog = mock.Mock()
        mock_corview.return_value = mock_dialog

        self.presenter._do_refine_selected_cor()

        mock_corview.assert_called_once()
        mock_dialog.exec.assert_called_once()
        self.presenter.do_preview_reconstruct_slice.assert_not_called()
Esempio n. 20
0
    def test_set_results(self):
        cor_val = 20
        tilt_val = 30
        slope_val = 40
        cor = ScalarCoR(cor_val)
        tilt = Degrees(tilt_val)
        slope = Slope(slope_val)

        self.view.set_results(cor, tilt, slope)
        self.resultCor.setValue.assert_called_once_with(cor_val)
        self.resultTilt.setValue.assert_called_once_with(tilt_val)
        self.resultSlope.setValue.assert_called_once_with(slope_val)
        self.image_view.set_tilt.assert_called_once_with(tilt)
Esempio n. 21
0
    def test_do_reconstruct_slice(self, mock_get_reconstructor_for):
        mock_reconstructor = mock.Mock()
        mock_reconstructor.single_sino = mock.Mock()
        mock_get_reconstructor_for.return_value = mock_reconstructor
        self.presenter.model.preview_slice_idx = 0
        self.presenter.model.last_cor = ScalarCoR(150)
        self.presenter.model.data_model._cached_gradient = None

        self.presenter.do_reconstruct_slice()
        self.view.update_sinogram.assert_called_once()
        self.view.update_recon_preview.assert_called_once()

        mock_get_reconstructor_for.assert_called_once()
        mock_reconstructor.single_sino.assert_called_once()
    def test_do_preview_reconstruct_slice(self, mock_start_async_task_view):

        recon_params = ReconstructionParameters("FBP", "ram-lak", 10)
        self.view.recon_params.return_value = recon_params

        self.presenter.model.preview_slice_idx = 0
        self.presenter.model.last_cor = ScalarCoR(150)
        self.presenter.model.data_model._cached_gradient = None

        self.presenter.do_preview_reconstruct_slice()

        self.view.update_sinogram.assert_called_once()
        mock_start_async_task_view.assert_called_once()
        self.view.recon_params.assert_called_once()
    def test_do_refine_selected_cor_accepted(self, mock_corview):
        self.presenter.model.preview_slice_idx = 155
        self.presenter.model.last_cor = ScalarCoR(314)
        self.presenter.do_preview_reconstruct_slice = mock.Mock()
        mock_dialog = mock.Mock()
        mock_dialog.exec.return_value = mock_corview.Accepted
        mock_corview.return_value = mock_dialog

        self.presenter._do_refine_selected_cor()

        self.presenter.model.data_model.set_cor_at_slice.assert_called_once()
        self.assertEqual(self.presenter.model.last_cor, mock_dialog.optimal_rotation_centre)
        mock_corview.assert_called_once()
        mock_dialog.exec.assert_called_once()
        self.presenter.do_preview_reconstruct_slice.assert_called_once()
Esempio n. 24
0
    def test_iterations(self):
        images = generate_images()
        m = CORInspectionDialogModel(
            images, 5, ScalarCoR(20),
            ReconstructionParameters('FBP_CUDA', 'ram-lak'), True)

        m.adjust(ImageType.LESS)
        self.assertEqual(m.centre_value, 50)
        self.assertEqual(m.step, 50)

        m.adjust(ImageType.CURRENT)
        self.assertEqual(m.centre_value, 50)
        self.assertEqual(m.step, 25)

        m.adjust(ImageType.MORE)
        self.assertEqual(m.centre_value, 75)
        self.assertEqual(m.step, 25)
Esempio n. 25
0
    def test_run_preview_recon(self, mock_get_reconstructor_for):
        mock_reconstructor = mock.Mock()
        mock_reconstructor.single_sino = mock.Mock()
        mock_get_reconstructor_for.return_value = mock_reconstructor

        expected_idx = 5
        expected_sino = self.model.images.sino(expected_idx)
        expected_cor = ScalarCoR(15)
        expected_recon_params = ReconstructionParameters("FBP_CUDA", "ram-lak")
        self.model.run_preview_recon(expected_idx, expected_cor,
                                     expected_recon_params)

        mock_get_reconstructor_for.assert_called_once_with(
            expected_recon_params.algorithm)
        assert_called_once_with(mock_reconstructor.single_sino, expected_sino,
                                expected_cor,
                                self.model.images.projection_angles(),
                                expected_recon_params)
    def test_do_reconstruct_slice(self, mock_get_reconstructor_for):
        mock_reconstructor = mock.Mock()
        mock_reconstructor.single_sino = mock.Mock()
        mock_reconstructor.single_sino.return_value = np.random.rand(128, 128)
        mock_get_reconstructor_for.return_value = mock_reconstructor

        recon_params = ReconstructionParameters("FBP", "ram-lak", 10)
        self.view.recon_params.return_value = recon_params

        self.presenter.model.preview_slice_idx = 0
        self.presenter.model.last_cor = ScalarCoR(150)
        self.presenter.model.data_model._cached_gradient = None

        self.presenter.do_preview_reconstruct_slice()
        self.view.update_sinogram.assert_called_once()
        self.view.update_recon_preview.assert_called_once()
        self.view.recon_params.assert_called_once()

        mock_get_reconstructor_for.assert_called_once()
        mock_reconstructor.single_sino.assert_called_once()
Esempio n. 27
0
 def set_last_cor(self, cor):
     self.model.last_cor = ScalarCoR(cor)
class ReconWindowPresenterTest(unittest.TestCase):
    def setUp(self):
        # Mock view
        self.make_view()

        self.presenter = ReconstructWindowPresenter(self.view, None)

        # Mock stack
        self.sv_view = mock.create_autospec(StackVisualiserView)

        data = Images(data=np.ndarray(shape=(128, 10, 128), dtype=np.float32))
        data.pixel_size = TEST_PIXEL_SIZE
        self.sv_view.presenter = StackVisualiserPresenter(self.sv_view, data)

        self.presenter.model.initial_select_data(self.sv_view)
        self.view.get_stack_visualiser = mock.Mock(return_value=self.sv_view)

        import uuid
        self.uuid = uuid.uuid4()

    def make_view(self):
        self.view = mock.create_autospec(ReconstructWindowView)
        self.view.filterName = mock.Mock()
        self.view.filterNameLabel = mock.Mock()
        self.view.numIter = mock.Mock()
        self.view.numIterLabel = mock.Mock()

    @mock.patch('mantidimaging.gui.windows.recon.model.get_reconstructor_for')
    def test_set_stack_uuid(self, mock_get_reconstructor_for):
        # reset the model data
        self.presenter.model.initial_select_data(None)

        mock_reconstructor = mock.Mock()
        mock_reconstructor.single_sino = mock.Mock()
        mock_reconstructor.single_sino.return_value = np.random.rand(128, 128)
        mock_get_reconstructor_for.return_value = mock_reconstructor

        recon_params = ReconstructionParameters("FBP", "ram-lak", 10)
        self.view.recon_params.return_value = recon_params

        # first-time selecting this data after reset
        self.presenter.set_stack_uuid(self.uuid)
        self.view.get_stack_visualiser.assert_called_once_with(self.uuid)

        self.view.update_projection.assert_called_once()
        self.view.clear_cor_table.assert_called_once()
        self.view.update_projection.assert_called_once()
        self.view.update_sinogram.assert_called_once()
        self.view.update_recon_preview.assert_called_once()
        mock_get_reconstructor_for.assert_called_once()
        mock_reconstructor.single_sino.assert_called_once()
        self.view.recon_params.assert_called_once()

        # calling again with the same stack shouldn't re-do everything
        self.presenter.set_stack_uuid(self.uuid)
        self.assertEqual(self.view.get_stack_visualiser.call_count, 2)
        self.view.get_stack_visualiser.assert_has_calls([mock.call(self.uuid), mock.call(self.uuid)])

        self.view.update_projection.assert_called_once()
        self.view.clear_cor_table.assert_called_once()
        self.view.update_projection.assert_called_once()
        self.view.update_sinogram.assert_called_once()
        self.view.update_recon_preview.assert_called_once()
        mock_get_reconstructor_for.assert_called_once()
        mock_reconstructor.single_sino.assert_called_once()

    @mock.patch('mantidimaging.gui.windows.recon.model.get_reconstructor_for')
    def test_set_stack_uuid_updates_rotation_centre_and_pixel_size(self, _):
        self.presenter.model.stack = None
        # first-time selecting this data after reset
        self.presenter.set_stack_uuid(self.uuid)

        self.assertEqual(64.0, self.view.rotation_centre)
        self.assertEqual(TEST_PIXEL_SIZE, self.view.pixel_size)

    def test_set_projection_preview_index(self):
        self.presenter.set_preview_projection_idx(5)
        self.assertEqual(self.presenter.model.preview_projection_idx, 5)
        self.view.update_projection.assert_called_once()

    @mock.patch('mantidimaging.gui.windows.recon.model.get_reconstructor_for')
    def test_set_slice_preview_index(self, mock_get_reconstructor_for):
        mock_reconstructor = mock.Mock()
        mock_reconstructor.single_sino = mock.Mock()
        mock_reconstructor.single_sino.return_value = np.random.rand(128, 128)
        mock_get_reconstructor_for.return_value = mock_reconstructor

        recon_params = ReconstructionParameters("FBP", "ram-lak", 10)
        self.view.recon_params.return_value = recon_params

        self.presenter.set_preview_slice_idx(5)
        self.assertEqual(self.presenter.model.preview_slice_idx, 5)
        self.view.update_projection.assert_called_once()
        self.view.update_sinogram.assert_called_once()
        self.view.update_recon_preview.assert_called_once()
        self.view.recon_params.assert_called_once()

        mock_get_reconstructor_for.assert_called_once()
        mock_reconstructor.single_sino.assert_called_once()

    @mock.patch('mantidimaging.gui.windows.recon.model.ReconstructWindowModel.get_me_a_cor', return_value=ScalarCoR(15))
    def test_do_add_manual_cor_table_row(self, mock_get_me_a_cor):
        self.presenter.model.selected_row = 0
        self.presenter.model.preview_slice_idx = 15

        self.presenter.notify(PresNotification.ADD_COR)
        self.view.add_cor_table_row.assert_called_once_with(self.presenter.model.selected_row, 0, 15)
        mock_get_me_a_cor.assert_called_once()

    @mock.patch('mantidimaging.gui.windows.recon.model.get_reconstructor_for')
    def test_do_reconstruct_slice(self, mock_get_reconstructor_for):
        mock_reconstructor = mock.Mock()
        mock_reconstructor.single_sino = mock.Mock()
        mock_reconstructor.single_sino.return_value = np.random.rand(128, 128)
        mock_get_reconstructor_for.return_value = mock_reconstructor

        recon_params = ReconstructionParameters("FBP", "ram-lak", 10)
        self.view.recon_params.return_value = recon_params

        self.presenter.model.preview_slice_idx = 0
        self.presenter.model.last_cor = ScalarCoR(150)
        self.presenter.model.data_model._cached_gradient = None

        self.presenter.do_preview_reconstruct_slice()
        self.view.update_sinogram.assert_called_once()
        self.view.update_recon_preview.assert_called_once()
        self.view.recon_params.assert_called_once()

        mock_get_reconstructor_for.assert_called_once()
        mock_reconstructor.single_sino.assert_called_once()

    @mock.patch('mantidimaging.gui.windows.recon.model.get_reconstructor_for')
    def test_do_reconstruct_slice_raises(self, mock_get_reconstructor_for):
        mock_get_reconstructor_for.side_effect = ValueError
        mock_reconstructor = mock.Mock()
        mock_reconstructor.single_sino = mock.Mock()
        mock_get_reconstructor_for.return_value = mock_reconstructor
        self.presenter.model.preview_slice_idx = 0
        self.presenter.model.last_cor = ScalarCoR(150)
        self.presenter.model.data_model._cached_gradient = None

        self.presenter.do_preview_reconstruct_slice()
        self.view.update_sinogram.assert_called_once()
        self.view.show_error_dialog.assert_called_once()
        mock_get_reconstructor_for.assert_called_once()

        self.view.update_recon_preview.assert_not_called()
        mock_reconstructor.single_sino.assert_not_called()

    @mock.patch('mantidimaging.gui.windows.recon.presenter.start_async_task_view')
    def test_do_reconstruct_volume(self, mock_async_task):
        self.presenter.do_reconstruct_volume()
        # kind of a pointless test, but at least it might capture some parameter change
        mock_async_task.assert_called_once_with(self.view, self.presenter.model.run_full_recon,
                                                self.presenter._on_volume_recon_done,
                                                {'recon_params': self.view.recon_params()})

    @mock.patch('mantidimaging.gui.windows.recon.presenter.CORInspectionDialogView')
    def test_do_refine_selected_cor_declined(self, mock_corview):
        self.presenter.model.preview_slice_idx = 155
        self.presenter.model.last_cor = ScalarCoR(314)
        self.presenter.do_preview_reconstruct_slice = mock.Mock()

        mock_dialog = mock.Mock()
        mock_corview.return_value = mock_dialog

        self.presenter._do_refine_selected_cor()

        mock_corview.assert_called_once()
        mock_dialog.exec.assert_called_once()
        self.presenter.do_preview_reconstruct_slice.assert_not_called()

    @mock.patch('mantidimaging.gui.windows.recon.presenter.CORInspectionDialogView')
    def test_do_refine_selected_cor_accepted(self, mock_corview):
        self.presenter.model.preview_slice_idx = 155
        self.presenter.model.last_cor = ScalarCoR(314)
        self.presenter.do_preview_reconstruct_slice = mock.Mock()
        mock_dialog = mock.Mock()
        mock_dialog.exec.return_value = mock_corview.Accepted
        mock_corview.return_value = mock_dialog

        self.presenter._do_refine_selected_cor()

        self.presenter.model.data_model.set_cor_at_slice.assert_called_once()
        self.assertEqual(self.presenter.model.last_cor, mock_dialog.optimal_rotation_centre)
        mock_corview.assert_called_once()
        mock_dialog.exec.assert_called_once()
        self.presenter.do_preview_reconstruct_slice.assert_called_once()

    @mock.patch('mantidimaging.gui.windows.recon.presenter.CORInspectionDialogView')
    def test_do_refine_iterations_declined(self, mock_corview):
        self.presenter._do_refine_iterations()

        mock_corview.assert_called_once()
        mock_corview.return_value.exec.assert_called_once()

    @mock.patch('mantidimaging.gui.windows.recon.presenter.CORInspectionDialogView')
    def test_do_refine_iterations_accepted(self, mock_corview):
        mock_dialog = mock_corview.return_value
        mock_dialog.exec.return_value = mock_corview.Accepted
        mock_dialog.optimal_iterations = iters = 25

        self.presenter._do_refine_iterations()

        mock_corview.assert_called_once()
        mock_corview.return_value.exec.assert_called_once()
        assert self.view.num_iter == iters

    def test_do_cor_fit(self):
        self.presenter.do_preview_reconstruct_slice = mock.Mock()
        self.presenter.do_update_projection = mock.Mock()

        self.presenter.do_cor_fit()

        self.view.set_results.assert_called_once()
        self.presenter.do_update_projection.assert_called_once()
        self.presenter.do_preview_reconstruct_slice.assert_called_once()

    def test_set_precalculated_cor_tilt(self):
        self.view.rotation_centre = 150
        self.view.tilt = 1
        self.presenter.do_preview_reconstruct_slice = mock.Mock()
        self.presenter.do_update_projection = mock.Mock()
        self.presenter.model.data_model.iter_points.return_value = [Point(0, 0)]

        self.presenter.do_calculate_cors_from_manual_tilt()

        self.presenter.model.data_model.iter_points.assert_called_once()
        self.view.set_table_point.assert_called_once()
        self.assertTrue(self.presenter.model.has_results)
        self.view.set_results.assert_called_once()
        self.presenter.do_update_projection.assert_called_once()
        self.presenter.do_preview_reconstruct_slice.assert_called_once()

    @mock.patch('mantidimaging.gui.windows.recon.presenter.start_async_task_view')
    def test_auto_find_correlation(self, mock_start_async: mock.Mock):
        self.presenter.notify(PresNotification.AUTO_FIND_COR_CORRELATE)
        mock_start_async.assert_called_once()
        mock_first_call = mock_start_async.call_args[0]
        self.assertEqual(self.presenter.view, mock_first_call[0])
        self.assertEqual(self.presenter.model.auto_find_correlation, mock_first_call[1])
        self.view.set_correlate_buttons_enabled.assert_called_once_with(False)

    @mock.patch('mantidimaging.gui.windows.recon.presenter.start_async_task_view')
    def test_auto_find_correlation_failed_due_to_180_deg_shape(self, mock_start_async: mock.MagicMock):
        images = mock.MagicMock()
        images.height = 10
        images.width = 10
        images.proj180deg.height = 20
        images.proj180deg.width = 20
        self.view = mock.MagicMock()
        self.presenter.view = self.view
        self.view.main_window.get_images_from_stack_uuid = mock.MagicMock(return_value=images)

        self.presenter.notify(PresNotification.AUTO_FIND_COR_CORRELATE)

        mock_start_async.assert_called_once()
        completed_function = mock_start_async.call_args[0][2]

        task = mock.MagicMock()
        task.result = None
        task.error = ValueError("Task Error")
        completed_function(task)

        self.view.warn_user.assert_called_once_with(
            "Failure!",
            "Finding the COR failed, likely caused by the selected stack's 180 degree projection being a different "
            "shape. \n\n Error: Task Error \n\n Suggestion: Use crop coordinates to resize the 180 degree "
            "projection to (10, 10)")

    def test_do_stack_reconstruct_slice(self):
        self.presenter._get_reconstruct_slice = mock.Mock()
        self.presenter._get_reconstruct_slice.return_value = test_data = np.ndarray(shape=(200, 250), dtype=np.float32)
        self.presenter.do_stack_reconstruct_slice()
        self.view.show_recon_volume.assert_called_once()
        np.array_equal(self.view.show_recon_volume.call_args[0][0].data, test_data)

    def test_do_stack_reconstruct_slice_raises(self):
        self.presenter._get_reconstruct_slice = mock.Mock()
        self.presenter._get_reconstruct_slice.side_effect = ValueError
        self.presenter.do_stack_reconstruct_slice()
        self.view.show_recon_volume.assert_not_called()
        self.view.show_error_dialog.assert_called_once()

    def test_proj_180_degree_shape_matches_images_where_they_match(self):
        images = mock.MagicMock()
        images.height = 10
        images.width = 10
        images.proj180deg.height = 10
        images.proj180deg.width = 10
        has_proj180deg = mock.MagicMock(return_value=True)
        images.has_proj180deg = has_proj180deg

        self.assertTrue(self.presenter.proj_180_degree_shape_matches_images(images))

    def test_proj_180_degree_shape_matches_images_where_they_dont_match(self):
        images = mock.MagicMock()
        images.height = 10
        images.width = 10
        images.proj180deg.height = 20
        images.proj180deg.width = 20
        has_proj180deg = mock.MagicMock(return_value=True)
        images.has_proj180deg = has_proj180deg

        self.assertFalse(self.presenter.proj_180_degree_shape_matches_images(images))

    def test_proj_180_degree_shape_matches_images_where_no_180_present(self):
        images = mock.MagicMock()
        has_proj180deg = mock.MagicMock(return_value=False)
        images.has_proj180deg = has_proj180deg

        self.assertFalse(self.presenter.proj_180_degree_shape_matches_images(images))
Esempio n. 29
0
 def do_calculate_cors_from_manual_tilt(self):
     cor = ScalarCoR(self.view.rotation_centre)
     tilt = Degrees(self.view.tilt)
     self._set_precalculated_cor_tilt(cor, tilt)
Esempio n. 30
0
 def get_cor_for_slice_from_regression(self) -> ScalarCoR:
     return ScalarCoR(self.data_model.get_cor_from_regression(self.preview_slice_idx))