diff --git a/invisible_cities/core/fit_functions.py b/invisible_cities/core/fit_functions.py index 500bfaa6b..debdab8b9 100644 --- a/invisible_cities/core/fit_functions.py +++ b/invisible_cities/core/fit_functions.py @@ -158,8 +158,8 @@ def fit(func, x, y, seed=(), fit_range=None, **kwargs): Returns ------- fitted_fun : FitFunction - Extended function containing fit parameters (fitf, vals, errors, chi2, pval, - cov) and full_output from curve_fit and leastsq (infodict, mesg and ier). + Extended function containing fit parameters (fitf, vals, errors, chi2, pval, + cov) and full_output from curve_fit and leastsq (infodict, mesg and ier). Examples diff --git a/invisible_cities/core/fit_functions_test.py b/invisible_cities/core/fit_functions_test.py index e99196b2e..0a9270567 100644 --- a/invisible_cities/core/fit_functions_test.py +++ b/invisible_cities/core/fit_functions_test.py @@ -18,7 +18,6 @@ from hypothesis.strategies import floats from . testing_utils import float_arrays from . testing_utils import random_length_float_arrays -from .. evm.ic_containers import FitFunction from . import core_functions as core from . import fit_functions as fitf diff --git a/invisible_cities/reco/icaro_components.py b/invisible_cities/reco/icaro_components.py index 300ac675f..38f81fc0c 100644 --- a/invisible_cities/reco/icaro_components.py +++ b/invisible_cities/reco/icaro_components.py @@ -1,15 +1,12 @@ import numpy as np import pandas as pd -from typing import Optional from ..types.symbols import KrFitFunction from .. evm.ic_containers import FitFunction from .. core.fit_functions import polynom, expo -def lin_seed(x : np.array, - y : np.array): - +def lin_seed(x : np.array, y : np.array): ''' Estimate the seed for a linear fit. @@ -25,26 +22,20 @@ def lin_seed(x : np.array, seed : tuple Seed parameters (intercept, slope) for the linear fit. ''' - x0, x1 = x.min(), x.max() y0, y1 = y.min(), y.max() if x1 == x0: # If same x value, set slope to 0 and use the mean value of y as interceipt b = 0 a = y.mean() - else: b = (y1 - y0) / (x1 - x0) a = y0 - b * x0 - seed = a, b - - return seed - + return a, b -def expo_seed(x : np.array, - y : np.array): +def expo_seed(x : np.array, y : np.array): ''' Estimate the seed for an exponential fit. @@ -60,9 +51,7 @@ def expo_seed(x : np.array, seed : tuple Seed parameters (constant, mean) for the exponential fit. ''' - x, y = zip(*sorted(zip(x, y))) - const = y[0] if const <= 0 or y[-1] <= 0: @@ -74,18 +63,10 @@ def expo_seed(x : np.array, return seed -def select_fit_variables(fittype : KrFitFunction, - dst : pd.DataFrame): - +def select_fit_variables(fittype : KrFitFunction, dst : pd.DataFrame): ''' Select the data for fitting based on the specified fit type. - NOTES: Since x axis (DT) is never altered, maybe we can just - return the y values. However, when we implement the binned fit, - the profile could be done here (?) so it would make sense to - always provide both x and y. We could rename parameters and have - fittype (binned / unbinned) and fitfunction (lin, expo, log-lin...) - Parameters ---------- fittype : KrFitFunction @@ -100,7 +81,6 @@ def select_fit_variables(fittype : KrFitFunction, y_data : pd.Series The dependent variable data prepared for fitting. ''' - if fittype is KrFitFunction.linear : return dst.DT, dst.S2e elif fittype is KrFitFunction.expo : return dst.DT, dst.S2e elif fittype is KrFitFunction.log_lin: return dst.DT, -np.log(dst.S2e) @@ -123,17 +103,15 @@ def get_function_and_seed_lt(fittype : KrFitFunction): seed_function : function The seed function corresponding to the specified fit type. ''' - linear_function = lambda x, y0, slope: polynom(x, y0, slope) expo_function = lambda x, e0, lt: expo (x, e0, -lt) - if fittype is KrFitFunction.linear: return linear_function, lin_seed - elif fittype is KrFitFunction.log_lin: return linear_function, lin_seed - elif fittype is KrFitFunction.expo: return expo_function, expo_seed + if fittype is KrFitFunction.linear: return linear_function, lin_seed + elif fittype is KrFitFunction.log_lin: return linear_function, lin_seed + elif fittype is KrFitFunction.expo: return expo_function, expo_seed def transform_parameters(fit_output : FitFunction): - ''' Transform the parameters obtained from the fitting output into EO and LT. When using log_lin fit, we need to convert the intermediate variables into @@ -154,7 +132,6 @@ def transform_parameters(fit_output : FitFunction): cov : float Transformed covariance value. ''' - par = fit_output.values err = fit_output.errors cov = fit_output.cov[0, 1] @@ -164,10 +141,8 @@ def transform_parameters(fit_output : FitFunction): E0 = np.exp(-a) s_E0 = np.abs(E0 * u_a) - lt = 1 / b s_lt = np.abs(lt**2 * u_b) - cov = E0 * lt**2 * cov # Not sure about this par = [ E0, lt] diff --git a/invisible_cities/reco/icaro_components_test.py b/invisible_cities/reco/icaro_components_test.py index 3d9472d63..2f2c6b5df 100644 --- a/invisible_cities/reco/icaro_components_test.py +++ b/invisible_cities/reco/icaro_components_test.py @@ -3,7 +3,6 @@ import numpy as np import numpy.testing as npt import pandas as pd -import pandas.testing as pdt import scipy.optimize as so from hypothesis import given, settings @@ -23,6 +22,7 @@ def test_lin_function_output_values(x_min, x_max, a, b): x = np.array([x_min, x_max]) y = a + b * x a_test, b_test = icarcomp.lin_seed(x, y) + assert np.isclose(a_test, a) assert np.isclose(b_test, b) @@ -35,20 +35,19 @@ def test_expo_seed_output_values(zmin, zmax, elt, e0): x = np.array( [ zmin, zmax ] ) y = e0 * np.exp( - x / elt ) e0_test, elt_test = icarcomp.expo_seed(x, y) + assert np.isclose(e0_test, e0, rtol=0.1) assert np.isclose(elt_test, elt, rtol=0.1) @pytest.fixture def sample_df(): - - data = { - 'DT' : [10, 20, 30, 40, 50], - 'S2e': [50, 45, 42, 41, 41] - } + data = {'DT' : [10, 20, 30, 40, 50], + 'S2e': [50, 45, 42, 41, 41]} return pd.DataFrame(data) -def test_select_fit_variables(sample_df): + +def test_select_fit_variables(sample_df): x_linear, y_linear = icarcomp.select_fit_variables(KrFitFunction.linear, sample_df) x_expo, y_expo = icarcomp.select_fit_variables(KrFitFunction.expo, sample_df) x_log_lin, y_log_lin = icarcomp.select_fit_variables(KrFitFunction.log_lin, sample_df) @@ -69,7 +68,6 @@ def test_select_fit_variables(sample_df): floats (min_value = 1e3, max_value = 1e5), floats (min_value = 5e3, max_value = 1e5)) def test_get_function_and_seed_lt_with_data(x_min, x_max, steps, e0, lt): - x = np.linspace(x_min, x_max, steps) y = expo(x, e0, lt) @@ -81,7 +79,6 @@ def test_get_function_and_seed_lt_with_data(x_min, x_max, steps, e0, lt): popt_expo, _ = so.curve_fit(fit_func_expo, x, y, p0=seed_func_expo (x, y)) popt_log_lin, _ = so.curve_fit(fit_func_log_lin, x, y, p0=seed_func_log_lin(x, y)) - assert np.isclose(popt_lin[0], popt_expo[0], rtol=1e-1) # The interceipt should be close between lin and expo assert not np.isclose(popt_lin[1], popt_expo[1], rtol=1e-1) # The "lifetime" should be different between lin and expo @@ -89,13 +86,10 @@ def test_get_function_and_seed_lt_with_data(x_min, x_max, steps, e0, lt): assert np.isclose(popt_lin[1], popt_log_lin[1], rtol=1e-10) # inputs: s2e or -log(s2e)) so both parameters should be the same # for the purpose of testing this function - @given(floats(min_value=1, max_value=1e5), floats(min_value=10, max_value=1e5)) def test_transform_parameters(a, b): - - errors = 0.2*np.array([a, b]) - + errors = 0.2*np.array([a, b]) fit_output = FitFunction(values=[a, b], errors=errors, cov=np.array([[0.04, 0.02], [0.02, 0.04]]), fn=None, chi2=None, pvalue=None, infodict=None, mesg=None, ier=None)