From 311103bf5ee818f340f0ffcef9ecb20b49d9cdc4 Mon Sep 17 00:00:00 2001 From: Sam Tygier Date: Tue, 21 Sep 2021 16:23:24 +0100 Subject: [PATCH 1/7] Add Algotom to the dependencies --- conda/meta.yaml | 1 + environment-dev.yml | 1 + environment.yml | 1 + 3 files changed, 3 insertions(+) diff --git a/conda/meta.yaml b/conda/meta.yaml index 8fd45c40ef5..8a341cff72e 100644 --- a/conda/meta.yaml +++ b/conda/meta.yaml @@ -39,6 +39,7 @@ requirements: - cil-astra=21.2.* - ccpi-regulariser=20.9 - tomophantom=1.4.* + - algotom=1.0.* build: number: 1 diff --git a/environment-dev.yml b/environment-dev.yml index aa0f6d65df1..99a74e79465 100644 --- a/environment-dev.yml +++ b/environment-dev.yml @@ -5,6 +5,7 @@ channels: - astra-toolbox/label/dev - conda-forge - ccpi + - algotom dependencies: - mantidimaging - pip diff --git a/environment.yml b/environment.yml index 3d9eb375371..9342cdd1c44 100644 --- a/environment.yml +++ b/environment.yml @@ -5,6 +5,7 @@ channels: - astra-toolbox/label/dev - conda-forge - ccpi + - algotom # Dependencies that can be installed with conda should be in conda/meta.yaml dependencies: - mantidimaging From bd3b272ec420c01f9abd7250c1f547db01b70e21 Mon Sep 17 00:00:00 2001 From: Sam Tygier Date: Tue, 21 Sep 2021 16:27:38 +0100 Subject: [PATCH 2/7] Move remove_all_stripe and remove_large_stripe to algotom --- .../core/operations/remove_all_stripe/remove_all_stripe.py | 4 ++-- .../operations/remove_large_stripe/remove_large_stripe.py | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/mantidimaging/core/operations/remove_all_stripe/remove_all_stripe.py b/mantidimaging/core/operations/remove_all_stripe/remove_all_stripe.py index 98dc10b1591..be4e768f5fb 100644 --- a/mantidimaging/core/operations/remove_all_stripe/remove_all_stripe.py +++ b/mantidimaging/core/operations/remove_all_stripe/remove_all_stripe.py @@ -5,7 +5,7 @@ from mantidimaging.core.data.images import Images from PyQt5.QtWidgets import QSpinBox, QDoubleSpinBox -from sarepy.prep.stripe_removal_original import remove_all_stripe +from algotom.prep.removal import remove_all_stripe from mantidimaging.core.operations.base_filter import BaseFilter, FilterGroup from mantidimaging.core.parallel import shared as ps @@ -16,7 +16,7 @@ class RemoveAllStripesFilter(BaseFilter): """Stripe and ring artifact removal. Remove all types of stripe artifacts by combining algorithm 6, 5, and 3 in Vo et al., Optics Express 28396 (2018). - Source: https://github.com/nghia-vo/sarepy + Source: https://github.com/algotom/algotom Intended to be used on: Sinograms diff --git a/mantidimaging/core/operations/remove_large_stripe/remove_large_stripe.py b/mantidimaging/core/operations/remove_large_stripe/remove_large_stripe.py index 33459e33d94..f9df57ca381 100644 --- a/mantidimaging/core/operations/remove_large_stripe/remove_large_stripe.py +++ b/mantidimaging/core/operations/remove_large_stripe/remove_large_stripe.py @@ -4,7 +4,7 @@ from functools import partial from PyQt5.QtWidgets import QSpinBox, QDoubleSpinBox -from sarepy.prep.stripe_removal_original import remove_large_stripe +from algotom.prep.removal import remove_large_stripe from mantidimaging.core.operations.base_filter import BaseFilter, FilterGroup from mantidimaging.core.parallel import shared as ps @@ -16,7 +16,7 @@ class RemoveLargeStripesFilter(BaseFilter): Remove large stripes by: locating stripes, normalizing them to remove full stripes, using the sorting technique to remove partial stripes. - Source: https://github.com/nghia-vo/sarepy + Source: https://github.com/algotom/algotom Intended to be used on: Sinograms When: If stripes artifacts are present that have not been From 1df84ea159d9301d12a9acf5bd978b2b108c8751 Mon Sep 17 00:00:00 2001 From: Sam Tygier Date: Tue, 21 Sep 2021 16:28:56 +0100 Subject: [PATCH 3/7] Use algotom remove_dead_stripe Replaces sarepy remove_unresponsive_and_fluctuating_stripe --- .../operations/remove_dead_stripe/remove_dead_stripe.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/mantidimaging/core/operations/remove_dead_stripe/remove_dead_stripe.py b/mantidimaging/core/operations/remove_dead_stripe/remove_dead_stripe.py index 7c00c3edca2..fc378299e5f 100644 --- a/mantidimaging/core/operations/remove_dead_stripe/remove_dead_stripe.py +++ b/mantidimaging/core/operations/remove_dead_stripe/remove_dead_stripe.py @@ -5,7 +5,7 @@ from mantidimaging.core.data.images import Images from PyQt5.QtWidgets import QDoubleSpinBox, QSpinBox -from sarepy.prep.stripe_removal_original import remove_unresponsive_and_fluctuating_stripe +from algotom.prep.removal import remove_dead_stripe from mantidimaging.core.operations.base_filter import BaseFilter, FilterGroup from mantidimaging.core.parallel import shared as ps @@ -16,7 +16,7 @@ class RemoveDeadStripesFilter(BaseFilter): """Stripe and ring artifact removal. Algorithm 6 in Vo et al., Optics Express 28396 (2018). Remove unresponsive or fluctuating stripes by: locating stripes, correction by interpolation. - Source: https://github.com/nghia-vo/sarepy + Source: https://github.com/algotom/algotom Intended to be used on: Sinograms @@ -32,7 +32,7 @@ class RemoveDeadStripesFilter(BaseFilter): @staticmethod def filter_func(images: Images, snr=3, size=61, cores=None, chunksize=None, progress=None): f = ps.create_partial( - remove_unresponsive_and_fluctuating_stripe, + remove_dead_stripe, ps.return_to_self, snr=snr, size=size, From fbaa964d43ed20831114584497ec93e49e3d943b Mon Sep 17 00:00:00 2001 From: Sam Tygier Date: Tue, 21 Sep 2021 16:30:33 +0100 Subject: [PATCH 4/7] Use algotom remove_stripe_based_filtering and remove_stripe_based_2d_filtering_sorting These replace sarepy remove_stripe_based_filtering_sorting and remove_stripe_based_2d_filtering_sorting. Note that sort is now an flag argument, rather than a seperate function. --- .../remove_stripe_filtering/remove_stripe_filtering.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/mantidimaging/core/operations/remove_stripe_filtering/remove_stripe_filtering.py b/mantidimaging/core/operations/remove_stripe_filtering/remove_stripe_filtering.py index 29546fe1bf1..c547a2ddaa8 100644 --- a/mantidimaging/core/operations/remove_stripe_filtering/remove_stripe_filtering.py +++ b/mantidimaging/core/operations/remove_stripe_filtering/remove_stripe_filtering.py @@ -5,8 +5,7 @@ from mantidimaging.core.data.images import Images from PyQt5.QtWidgets import QSpinBox -from sarepy.prep.stripe_removal_improved import remove_stripe_based_filtering_sorting, \ - remove_stripe_based_2d_filtering_sorting +from algotom.prep.removal import remove_stripe_based_filtering, remove_stripe_based_2d_filtering_sorting from mantidimaging.core.operations.base_filter import BaseFilter, FilterGroup from mantidimaging.core.parallel import shared as ps @@ -17,7 +16,7 @@ class RemoveStripeFilteringFilter(BaseFilter): """Stripe and ring artifact removal. Combination of algorithm 2 and algorithm 3 in Vo et al., Optics Express 28396 (2018). Removing stripes using the filtering and sorting technique. - Source: https://github.com/nghia-vo/sarepy + Source: https://github.com/algotom/algotom Intended to be used on: Sinograms @@ -40,11 +39,12 @@ def filter_func(images: Images, chunksize=None, progress=None): if filtering_dim == 1: - f = ps.create_partial(remove_stripe_based_filtering_sorting, + f = ps.create_partial(remove_stripe_based_filtering, ps.return_to_self, sigma=sigma, size=size, - dim=window_dim) + dim=window_dim, + sort=True) else: f = ps.create_partial(remove_stripe_based_2d_filtering_sorting, ps.return_to_self, From 245ab10381ca9c84810070d5f90aa7f687944efa Mon Sep 17 00:00:00 2001 From: Sam Tygier Date: Tue, 21 Sep 2021 16:32:40 +0100 Subject: [PATCH 5/7] Use algotom remove_stripe_based_fitting Replaces sarepy remove_stripe_based_sorting_fitting. Note that sort is now an flag argument, rather than a seperate function. Also there is no longer a sigma y option, only sigma with acts on x. --- .../remove_stripe_sorting_fitting.py | 43 +++++++------------ .../remove_stripe_sorting_fitting_test.py | 11 ++--- 2 files changed, 19 insertions(+), 35 deletions(-) diff --git a/mantidimaging/core/operations/remove_stripe_sorting_fitting/remove_stripe_sorting_fitting.py b/mantidimaging/core/operations/remove_stripe_sorting_fitting/remove_stripe_sorting_fitting.py index f6596e8e68b..42bf89215b9 100644 --- a/mantidimaging/core/operations/remove_stripe_sorting_fitting/remove_stripe_sorting_fitting.py +++ b/mantidimaging/core/operations/remove_stripe_sorting_fitting/remove_stripe_sorting_fitting.py @@ -5,7 +5,7 @@ from mantidimaging.core.data.images import Images from PyQt5.QtWidgets import QSpinBox -from sarepy.prep.stripe_removal_improved import remove_stripe_based_sorting_fitting +from algotom.prep.removal import remove_stripe_based_fitting from mantidimaging.core.operations.base_filter import BaseFilter, FilterGroup from mantidimaging.core.parallel import shared as ps @@ -16,7 +16,7 @@ class RemoveStripeSortingFittingFilter(BaseFilter): """Stripe and ring artifact removal. Combination of algorithm 3 and 1 in Vo et al., Optics Express 28396 (2018). Remove stripes using the sorting and fitting technique. - Source: https://github.com/nghia-vo/sarepy + Source: https://github.com/algotom/algotom Intended to be used on: Sinograms @@ -30,12 +30,8 @@ class RemoveStripeSortingFittingFilter(BaseFilter): link_histograms = True @staticmethod - def filter_func(images: Images, order=1, sigmax=3, sigmay=3, cores=None, chunksize=None, progress=None): - f = ps.create_partial(remove_stripe_based_sorting_fitting, - ps.return_to_self, - order=order, - sigmax=sigmax, - sigmay=sigmay) + def filter_func(images: Images, order=1, sigma=3, cores=None, chunksize=None, progress=None): + f = ps.create_partial(remove_stripe_based_fitting, ps.return_to_self, order=order, sigma=sigma, sort=True) ps.shared_list = [images.data] ps.execute(f, images.num_projections, progress, cores=cores) @@ -54,28 +50,19 @@ def register_gui(form, on_change, view): default_value=1, form=form, on_change=on_change, - tooltip="Polynomial fit order. Check sarepy for more information") - _, sigmax = add_property_to_form('Sigma X', - Type.INT, - default_value=3, - form=form, - on_change=on_change, - tooltip="Sigma of the Gaussian window in the x-direction") - _, sigmay = add_property_to_form('Sigma Y', - Type.INT, - default_value=3, - form=form, - on_change=on_change, - tooltip="Sigma of the Gaussian window in the y-direction") - - return {'order': order, 'sigmax': sigmax, 'sigmay': sigmay} + tooltip="Polynomial fit order. Check algotom docs for more information") + _, sigma = add_property_to_form('Sigma', + Type.INT, + default_value=3, + form=form, + on_change=on_change, + tooltip="Sigma of the Gaussian window in the x-direction") + + return {'order': order, 'sigma': sigma} @staticmethod - def execute_wrapper(order: QSpinBox, sigmax: QSpinBox, sigmay: QSpinBox): # type: ignore - return partial(RemoveStripeSortingFittingFilter.filter_func, - order=order.value(), - sigmax=sigmax.value(), - sigmay=sigmay.value()) + def execute_wrapper(order: QSpinBox, sigma: QSpinBox): # type: ignore + return partial(RemoveStripeSortingFittingFilter.filter_func, order=order.value(), sigma=sigma.value()) @staticmethod def group_name() -> FilterGroup: diff --git a/mantidimaging/core/operations/remove_stripe_sorting_fitting/test/remove_stripe_sorting_fitting_test.py b/mantidimaging/core/operations/remove_stripe_sorting_fitting/test/remove_stripe_sorting_fitting_test.py index 3a671955083..59312e63bcb 100644 --- a/mantidimaging/core/operations/remove_stripe_sorting_fitting/test/remove_stripe_sorting_fitting_test.py +++ b/mantidimaging/core/operations/remove_stripe_sorting_fitting/test/remove_stripe_sorting_fitting_test.py @@ -31,19 +31,16 @@ def test_execute_wrapper_return_is_runnable(self): """ order = mock.Mock() order.value = mock.Mock(return_value=1) - sigmax = mock.Mock() - sigmax.value = mock.Mock(return_value=2) - sigmay = mock.Mock() - sigmay.value = mock.Mock(return_value=2) + sigma = mock.Mock() + sigma.value = mock.Mock(return_value=2) - execute_func = RemoveStripeSortingFittingFilter.execute_wrapper(order, sigmax, sigmay) + execute_func = RemoveStripeSortingFittingFilter.execute_wrapper(order, sigma) images = th.generate_images() execute_func(images) self.assertEqual(order.value.call_count, 1) - self.assertEqual(sigmax.value.call_count, 1) - self.assertEqual(sigmay.value.call_count, 1) + self.assertEqual(sigma.value.call_count, 1) if __name__ == '__main__': From 47470091865012e9cedf3b465c76dfa10284ac45 Mon Sep 17 00:00:00 2001 From: Sam Tygier Date: Tue, 21 Sep 2021 16:51:08 +0100 Subject: [PATCH 6/7] Release notes and docs --- docs/overview.rst | 2 +- docs/release_notes/next.rst | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/overview.rst b/docs/overview.rst index c77574674e3..2ce83c1b16f 100644 --- a/docs/overview.rst +++ b/docs/overview.rst @@ -3,7 +3,7 @@ Overview Mantid Imaging contains tools for loading data from neutron imaging experiments, preprocessing to enhance images and tomographic reconstruction into 3 dimensional data that can be output for further analysis. -Mantid Imaging makes use of a range of algorithms, some from external tools including `Astra `_ and `Tomopy `_. Many of these are optimised for multithreading and GPU computing. +Mantid Imaging makes use of a range of algorithms, some from external tools including `Astra `_, `Tomopy `_, `Algotom `_ and the `Core Imaging Library `_. Many of these are optimised for multithreading and GPU computing. Mantid Imaging is written in Python and requires a CUDA capable GPU for full functionality. It runs on Linux. See :ref:`Installation` for more details. diff --git a/docs/release_notes/next.rst b/docs/release_notes/next.rst index 36780b6cda5..51309e80099 100644 --- a/docs/release_notes/next.rst +++ b/docs/release_notes/next.rst @@ -7,6 +7,7 @@ New Features ------------ - #1044 : Command line argument to load a dataset +- #1023 : Switch from Sarepy to Algotom Fixes ----- From b3d0ba0a33c8d33e1759fa8dd603e8df834dd5ac Mon Sep 17 00:00:00 2001 From: Sam Tygier Date: Wed, 22 Sep 2021 11:38:55 +0100 Subject: [PATCH 7/7] Explictly set residual=False in remove_dead_stripe The default has changed, so match old behaviour. --- .../operations/remove_dead_stripe/remove_dead_stripe.py | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/mantidimaging/core/operations/remove_dead_stripe/remove_dead_stripe.py b/mantidimaging/core/operations/remove_dead_stripe/remove_dead_stripe.py index fc378299e5f..82494c53ad8 100644 --- a/mantidimaging/core/operations/remove_dead_stripe/remove_dead_stripe.py +++ b/mantidimaging/core/operations/remove_dead_stripe/remove_dead_stripe.py @@ -31,12 +31,7 @@ class RemoveDeadStripesFilter(BaseFilter): @staticmethod def filter_func(images: Images, snr=3, size=61, cores=None, chunksize=None, progress=None): - f = ps.create_partial( - remove_dead_stripe, - ps.return_to_self, - snr=snr, - size=size, - ) + f = ps.create_partial(remove_dead_stripe, ps.return_to_self, snr=snr, size=size, residual=False) ps.shared_list = [images.data] ps.execute(f, images.num_projections, progress, cores=cores) return images