From 796f088fbf968f862cd0053fe04701f4ca4dfd03 Mon Sep 17 00:00:00 2001 From: Cammille Carinan <cammille.carinan@xfel.eu> Date: Fri, 21 May 2021 19:54:39 +0200 Subject: [PATCH] Try adding more tests --- src/toolbox_scs/base/knife_edge.py | 15 ++++-------- src/toolbox_scs/base/tests/test_knife_edge.py | 24 +++++++++++++++---- 2 files changed, 25 insertions(+), 14 deletions(-) diff --git a/src/toolbox_scs/base/knife_edge.py b/src/toolbox_scs/base/knife_edge.py index 0b64fee..e46cf6c 100644 --- a/src/toolbox_scs/base/knife_edge.py +++ b/src/toolbox_scs/base/knife_edge.py @@ -1,5 +1,5 @@ import numpy as np -from scipy.special import erfc +from scipy import special from scipy.optimize import curve_fit @@ -19,15 +19,13 @@ def knife_edge_base(positions, intensities, axisRange=None, p0=None): # Prepare arrays positions, intensities = prepare_arrays(positions, intensities, axisRange) - # Estimate a linear slope fitting the data to determine the erfc to use - slope = covariance(positions, intensities) / np.var(positions) - func = generate_erfc(sign=np.sign(slope) * -1) + # Estimate initial fitting params if p0 is None: p0 = [np.mean(positions), 0.1, np.max(intensities) / 2, 0] # Fit try: - popt, pcov = curve_fit(func, positions, intensities, p0=p0) + popt, pcov = curve_fit(erfc, positions, intensities, p0=p0) except (TypeError, RuntimeError): print("Fit did not converge.") popt, pcov = (None, None) @@ -76,8 +74,5 @@ def covariance(a: np.ndarray, b: np.ndarray): return np.cov(a, b)[0][1] -def generate_erfc(sign): - def func(x, x0, w0, a, b): - return a * erfc(sign * np.sqrt(2) * (x - x0) / w0) + b - - return func +def erfc(x, x0, w0, a, b): + return a * special.erfc(np.sqrt(2) * (x - x0) / w0) + b diff --git a/src/toolbox_scs/base/tests/test_knife_edge.py b/src/toolbox_scs/base/tests/test_knife_edge.py index a1cd9ae..1f06990 100644 --- a/src/toolbox_scs/base/tests/test_knife_edge.py +++ b/src/toolbox_scs/base/tests/test_knife_edge.py @@ -1,7 +1,7 @@ import numpy as np import pytest -from ..knife_edge import prepare_arrays, range_mask +from ..knife_edge import erfc, knife_edge_base, prepare_arrays, range_mask def test_range_mask(): @@ -58,7 +58,7 @@ def test_prepare_arrays_nans(): assert intensities.shape == (size,) # Test finite motors and signals with NaNs - signal_nan = with_values(signal, value=np.nan, num=20) + signal_nan = _with_values(signal, value=np.nan, num=20) positions, intensities = prepare_arrays(motor, signal_nan) assert positions.shape == (size-20,) assert np.isfinite(positions).all() @@ -66,7 +66,7 @@ def test_prepare_arrays_nans(): assert np.isfinite(intensities).all() # Test finite signals and motors with NaNs - motor_nan = with_values(motor, value=np.nan, num=3) + motor_nan = _with_values(motor, value=np.nan, num=3) positions, intensities = prepare_arrays(motor_nan, signal) assert positions.shape == ((trains-3) * pulses,) assert np.isfinite(positions).all() @@ -91,7 +91,23 @@ def test_prepare_arrays_size(): assert intensities.shape == (size,) -def with_values(array, value, num=5): +def test_knife_edge_base(): + p0 = [0, -1.5, 1, 0] + x = np.linspace(-3, 3) + y = erfc(x, *p0) + noise = y * np.random.normal(0, .02, y.shape) # 2% error + eff_y = (y + noise).reshape(1, -1) + + # Test noisy data + popt, _ = knife_edge_base(x, eff_y) + np.testing.assert_allclose(p0, popt, atol=1e-1) + + # Test flipped data + popt, _ = knife_edge_base(x, eff_y[::-1]) + np.testing.assert_allclose(p0, popt, atol=1e-1) + + +def _with_values(array, value, num=5): copy = array.astype(np.float) copy.ravel()[np.random.choice(copy.size, num, replace=False)] = value return copy -- GitLab