From 4f2313f2d35fd48b394376702c56a5c7bc7b1080 Mon Sep 17 00:00:00 2001 From: Eric Prestat Date: Fri, 28 Jun 2024 14:40:58 +0100 Subject: [PATCH 1/8] Add remove baseline ui --- hyperspy_gui_traitsui/hyperspy_extension.yaml | 3 + hyperspy_gui_traitsui/tools.py | 81 +++++++++++++++++++ 2 files changed, 84 insertions(+) diff --git a/hyperspy_gui_traitsui/hyperspy_extension.yaml b/hyperspy_gui_traitsui/hyperspy_extension.yaml index 86e8340..61b2c23 100644 --- a/hyperspy_gui_traitsui/hyperspy_extension.yaml +++ b/hyperspy_gui_traitsui/hyperspy_extension.yaml @@ -43,6 +43,9 @@ GUI: hyperspy.Signal1D.remove_background: module: hyperspy_gui_traitsui.tools function: remove_background_traitsui + hyperspy.Signal1D.remove_baseline: + module: hyperspy_gui_traitsui.tools + function: remove_baseline_traitsui hyperspy.SimpleMessage: module: hyperspy_gui_traitsui.messages function: simple_message diff --git a/hyperspy_gui_traitsui/tools.py b/hyperspy_gui_traitsui/tools.py index b29fd4b..b67070c 100644 --- a/hyperspy_gui_traitsui/tools.py +++ b/hyperspy_gui_traitsui/tools.py @@ -449,6 +449,87 @@ def remove_background_traitsui(obj, **kwargs): return obj, {"view": view} +class BaselineRemovalHandler(tu.Handler): + + def close(self, info, is_ok): + # Removes the span selector from the plot + obj = info.object + + # Apply before switching off the selector + if is_ok is True: + self.apply(info) + + if hasattr(obj, 'close'): + obj.close() + + return True + + def close_directly(self, info): + if (info.ui.owner is not None) and self.close(info, False): + info.ui.owner.close() + + def apply(self, info, *args, **kwargs): + """Handles the **Apply** button being clicked. + + """ + obj = info.object + obj.is_ok = True + if hasattr(obj, 'apply'): + obj.apply() + + +@add_display_arg +def remove_baseline_traitsui(obj, **kwargs): + from hyperspy.utils.baseline_removal_tool import algorithms_mapping_splines + view = tu.View( + tu.Group( + 'algorithm', + tu.Item( + 'penalized_spline', + enabled_when="algorithm not in algorithms_mapping_splines", + ), + tu.Group( + 'lam', + 'diff_order', + tu.Item( + 'p', + enabled_when="_enable_p", + ), + tu.Item( + 'lam_1', + enabled_when="_enable_lam_1", + ), + tu.Item( + 'eta', + enabled_when="_enable_eta", + ), + ), + tu.Group( + tu.Item( + 'num_knots', + enabled_when="penalized_spline or algorithm == 'Iterative Reweighted Spline Quantile Regression'", + ), + tu.Item( + 'spline_degree', + enabled_when="penalized_spline or algorithm == 'Iterative Reweighted Spline Quantile Regression'", + ), + tu.Item( + 'symmetric', + enabled_when="algorithm == 'Mixture Model'", + ), + ), + ), + buttons=[OKButton, CancelButton], + handler=BaselineRemovalHandler, + close_result=False, # is_ok=False when using window close button. + title='Baseline removal tool', + resizable=True, + width=300, + ) + return obj, {"view": view} + + + class SpikesRemovalHandler(tu.Handler): def close(self, info, is_ok): From c8e9c71d724c3447a835974c0c7c7d1f2cd74da1 Mon Sep 17 00:00:00 2001 From: Eric Prestat Date: Thu, 1 Aug 2024 15:24:02 +0100 Subject: [PATCH 2/8] Add `poly_order` to `remove_baseline` widget --- hyperspy_gui_traitsui/tools.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/hyperspy_gui_traitsui/tools.py b/hyperspy_gui_traitsui/tools.py index b67070c..5a68861 100644 --- a/hyperspy_gui_traitsui/tools.py +++ b/hyperspy_gui_traitsui/tools.py @@ -480,13 +480,17 @@ def apply(self, info, *args, **kwargs): @add_display_arg def remove_baseline_traitsui(obj, **kwargs): - from hyperspy.utils.baseline_removal_tool import algorithms_mapping_splines view = tu.View( tu.Group( 'algorithm', + # Enabled when a polynomial baseline is selected + tu.Item( + 'poly_order', + enabled_when="_enable_poly_order", + ), tu.Item( 'penalized_spline', - enabled_when="algorithm not in algorithms_mapping_splines", + enabled_when="_enable_penalized_spline", ), tu.Group( 'lam', From 7ed46cb2905722c7c8974176a7cc009116034b09 Mon Sep 17 00:00:00 2001 From: Eric Prestat Date: Sat, 21 Sep 2024 16:55:03 +0100 Subject: [PATCH 3/8] Fix enable parameters --- hyperspy_gui_traitsui/tools.py | 41 +++++++++++++++++++++++----------- 1 file changed, 28 insertions(+), 13 deletions(-) diff --git a/hyperspy_gui_traitsui/tools.py b/hyperspy_gui_traitsui/tools.py index 5a68861..ecc2325 100644 --- a/hyperspy_gui_traitsui/tools.py +++ b/hyperspy_gui_traitsui/tools.py @@ -483,18 +483,15 @@ def remove_baseline_traitsui(obj, **kwargs): view = tu.View( tu.Group( 'algorithm', - # Enabled when a polynomial baseline is selected - tu.Item( - 'poly_order', - enabled_when="_enable_poly_order", - ), - tu.Item( - 'penalized_spline', - enabled_when="_enable_penalized_spline", - ), tu.Group( - 'lam', - 'diff_order', + tu.Item( + 'lam', + enabled_when="_enable_lam", + ), + tu.Item( + 'diff_order', + enabled_when="_enable_diff_order", + ), tu.Item( 'p', enabled_when="_enable_p", @@ -507,20 +504,38 @@ def remove_baseline_traitsui(obj, **kwargs): 'eta', enabled_when="_enable_eta", ), + tu.Item( + 'penalized_spline', + enabled_when="_enable_penalized_spline", + ), + label="Whittaker", + ), + tu.Group( + # Enabled when a polynomial baseline is selected + tu.Item( + 'poly_order', + enabled_when="_enable_poly_order", + ), + label="Polynomial", ), tu.Group( tu.Item( 'num_knots', - enabled_when="penalized_spline or algorithm == 'Iterative Reweighted Spline Quantile Regression'", + enabled_when="_enable_spline_parameters", ), tu.Item( 'spline_degree', - enabled_when="penalized_spline or algorithm == 'Iterative Reweighted Spline Quantile Regression'", + enabled_when="_enable_spline_parameters", ), tu.Item( 'symmetric', enabled_when="algorithm == 'Mixture Model'", ), + tu.Item( + 'quantile', + enabled_when="algorithm == 'Iterative Reweighted Spline Quantile Regression'", + ), + label="Spline", ), ), buttons=[OKButton, CancelButton], From 60e7ee5337d658b71d053b8ff3537d6d5b9b412b Mon Sep 17 00:00:00 2001 From: Eric Prestat Date: Sat, 21 Sep 2024 17:56:05 +0100 Subject: [PATCH 4/8] Add time per pixel --- hyperspy_gui_traitsui/tools.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/hyperspy_gui_traitsui/tools.py b/hyperspy_gui_traitsui/tools.py index ecc2325..de3695a 100644 --- a/hyperspy_gui_traitsui/tools.py +++ b/hyperspy_gui_traitsui/tools.py @@ -481,8 +481,14 @@ def apply(self, info, *args, **kwargs): @add_display_arg def remove_baseline_traitsui(obj, **kwargs): view = tu.View( + 'algorithm', + tu.Item( + '_time_per_pixel', + style='readonly', + label="Time per pixel (ms)", + format_str='%.2f', + ), tu.Group( - 'algorithm', tu.Group( tu.Item( 'lam', From e58ad6dd6a885598fa2ea42cafe9a2db6ca860fc Mon Sep 17 00:00:00 2001 From: Eric Prestat Date: Sun, 22 Sep 2024 10:19:04 +0100 Subject: [PATCH 5/8] Add test --- hyperspy_gui_traitsui/tests/test_tools.py | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/hyperspy_gui_traitsui/tests/test_tools.py b/hyperspy_gui_traitsui/tests/test_tools.py index ba434a8..81892e2 100644 --- a/hyperspy_gui_traitsui/tests/test_tools.py +++ b/hyperspy_gui_traitsui/tests/test_tools.py @@ -25,6 +25,7 @@ BackgroundRemoval, Signal2DCalibration, ) +from hyperspy.utils.baseline_removal_tool import BaselineRemoval from hyperspy_gui_traitsui.tests.utils import KWARGS @@ -69,6 +70,21 @@ def test_remove_background_tool(): assert s.isig[:500.0].data.mean() < 1 +def test_remove_baseline(): + pytest.importorskip("pybaselines") + + s = hs.data.two_gaussians().inav[:5, :5] + s.plot() + + br = BaselineRemoval(s) + br.gui(**KWARGS) + br.algorithm = "Asymmetric Least Squares" + br.algorithm = "Adaptive Smoothness Penalized Least Squares" + br.lam = 1e7 + br.apply() + assert s.isig[:10].data.mean() < 5 + + def test_signal_2d_calibration(): s = hs.signals.Signal2D(np.zeros((100, 100))) s.plot() From d73c7f3649a4387b35d6063be17e359260b522ca Mon Sep 17 00:00:00 2001 From: Eric Prestat Date: Tue, 24 Sep 2024 10:33:51 +0100 Subject: [PATCH 6/8] Add classification methods --- hyperspy_gui_traitsui/tools.py | 70 +++++++++++++++++++++------------- 1 file changed, 44 insertions(+), 26 deletions(-) diff --git a/hyperspy_gui_traitsui/tools.py b/hyperspy_gui_traitsui/tools.py index de3695a..449972e 100644 --- a/hyperspy_gui_traitsui/tools.py +++ b/hyperspy_gui_traitsui/tools.py @@ -452,41 +452,28 @@ def remove_background_traitsui(obj, **kwargs): class BaselineRemovalHandler(tu.Handler): def close(self, info, is_ok): - # Removes the span selector from the plot obj = info.object - - # Apply before switching off the selector - if is_ok is True: - self.apply(info) - - if hasattr(obj, 'close'): - obj.close() - + obj.close() return True - def close_directly(self, info): - if (info.ui.owner is not None) and self.close(info, False): - info.ui.owner.close() - - def apply(self, info, *args, **kwargs): - """Handles the **Apply** button being clicked. - - """ + def apply(self, info): + """Handles the **Apply** button being clicked.""" obj = info.object - obj.is_ok = True - if hasattr(obj, 'apply'): - obj.apply() + obj.apply() @add_display_arg def remove_baseline_traitsui(obj, **kwargs): view = tu.View( - 'algorithm', + tu.Item( + 'algorithm', + label="Method", + ), tu.Item( '_time_per_pixel', style='readonly', label="Time per pixel (ms)", - format_str='%.2f', + format_str='%.3g', ), tu.Group( tu.Group( @@ -522,27 +509,58 @@ def remove_baseline_traitsui(obj, **kwargs): 'poly_order', enabled_when="_enable_poly_order", ), + tu.Item( + 'peak_ratio', + enabled_when="_enable_peak_ratio", + ), label="Polynomial", ), tu.Group( tu.Item( 'num_knots', - enabled_when="_enable_spline_parameters", + enabled_when="_enable_num_knots", ), tu.Item( 'spline_degree', - enabled_when="_enable_spline_parameters", + enabled_when="_enable_spline_degree", ), tu.Item( 'symmetric', - enabled_when="algorithm == 'Mixture Model'", + enabled_when="_enable_symmetric", ), tu.Item( 'quantile', - enabled_when="algorithm == 'Iterative Reweighted Spline Quantile Regression'", + enabled_when="_enable_quantile", ), label="Spline", ), + tu.Group( + tu.Item( + 'smooth_half_window', + enabled_when="_enable_smooth_half_windows", + ), + tu.Item( + 'num_std', + enabled_when="_enable_num_std", + ), + tu.Item( + 'interp_half_window', + enabled_when="_enable_interp_half_window", + ), + tu.Item( + 'half_window', + enabled_when="_enable_half_window", + ), + tu.Item( + 'section', + enabled_when="_enable_section", + ), + tu.Item( + 'segments', + enabled_when="_enable_segments", + ), + label="Classification", + ), ), buttons=[OKButton, CancelButton], handler=BaselineRemovalHandler, From a3755aec47238cc81c0ffb652900a42369dd70c8 Mon Sep 17 00:00:00 2001 From: Eric Prestat Date: Fri, 27 Sep 2024 17:03:46 +0100 Subject: [PATCH 7/8] Simplify handler --- hyperspy_gui_traitsui/tools.py | 29 ++++++++--------------------- 1 file changed, 8 insertions(+), 21 deletions(-) diff --git a/hyperspy_gui_traitsui/tools.py b/hyperspy_gui_traitsui/tools.py index 449972e..17ce56a 100644 --- a/hyperspy_gui_traitsui/tools.py +++ b/hyperspy_gui_traitsui/tools.py @@ -9,7 +9,7 @@ from hyperspy_gui_traitsui.utils import add_display_arg -class SmoothingHandler(tu.Handler): +class GenericHandler(tu.Handler): def close(self, info, is_ok): # Removes the span selector from the plot @@ -263,7 +263,7 @@ def smooth_savitzky_golay_traitsui(obj, **kwargs): # 'line_color', ), kind='live', - handler=SmoothingHandler, + handler=GenericHandler, buttons=OKCancelButtons, title='Savitzky-Golay Smoothing', ) @@ -279,7 +279,7 @@ def smooth_lowess_traitsui(obj, **kwargs): # 'line_color', ), kind='live', - handler=SmoothingHandler, + handler=GenericHandler, buttons=OKCancelButtons, title='Lowess Smoothing',) return obj, {"view": view} @@ -293,7 +293,7 @@ def smooth_tv_traitsui(obj, **kwargs): # 'line_color', ), kind='live', - handler=SmoothingHandler, + handler=GenericHandler, buttons=OKCancelButtons, title='Total Variation Smoothing',) return obj, {"view": view} @@ -307,7 +307,7 @@ def smooth_butterworth(obj, **kwargs): 'order', 'type'), kind='live', - handler=SmoothingHandler, + handler=GenericHandler, buttons=OKCancelButtons, title='Butterworth filter',) return obj, {"view": view} @@ -449,19 +449,6 @@ def remove_background_traitsui(obj, **kwargs): return obj, {"view": view} -class BaselineRemovalHandler(tu.Handler): - - def close(self, info, is_ok): - obj = info.object - obj.close() - return True - - def apply(self, info): - """Handles the **Apply** button being clicked.""" - obj = info.object - obj.apply() - - @add_display_arg def remove_baseline_traitsui(obj, **kwargs): view = tu.View( @@ -537,7 +524,7 @@ def remove_baseline_traitsui(obj, **kwargs): tu.Group( tu.Item( 'smooth_half_window', - enabled_when="_enable_smooth_half_windows", + enabled_when="_enable_smooth_half_window", ), tu.Item( 'num_std', @@ -562,8 +549,8 @@ def remove_baseline_traitsui(obj, **kwargs): label="Classification", ), ), - buttons=[OKButton, CancelButton], - handler=BaselineRemovalHandler, + buttons=OKCancelButtons, + handler=GenericHandler, close_result=False, # is_ok=False when using window close button. title='Baseline removal tool', resizable=True, From 5e3d1acc1e50fd9fd6369d841b4d8cba2df39434 Mon Sep 17 00:00:00 2001 From: Eric Prestat Date: Sun, 22 Sep 2024 13:08:20 +0100 Subject: [PATCH 8/8] Test against dev branch --- .github/workflows/tests.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 81e37f6..1d20b42 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -75,7 +75,8 @@ jobs: - name: Install HyperSpy (RELEASE_next_minor) if: contains( matrix.LABEL, 'RnM') run: | - pip install git+https://github.com/hyperspy/hyperspy.git@RELEASE_next_minor + # pip install git+https://github.com/hyperspy/hyperspy.git@RELEASE_next_minor + pip install "hyperspy[all] @ git+https://github.com/ericpre/hyperspy.git@remove_baselines" - name: Install HyperSpy (RELEASE_next_patch) if: contains( matrix.LABEL, 'RnP')