diff --git a/README.md b/README.md index 159c8e5..63954ef 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,5 @@ ![GitHub License](https://img.shields.io/github/license/davidkowalk/fitting_toolkit) -![Version](https://img.shields.io/badge/version-1.0.2-green) +![Version](https://img.shields.io/badge/version-1.0.3-green) ![GitHub commit activity](https://img.shields.io/github/commit-activity/m/davidkowalk/fitting_toolkit) ![GitHub Repo stars](https://img.shields.io/github/stars/davidkowalk/fitting_toolkit?style=flat&label=github%20stars) ![PyPI - Downloads](https://img.shields.io/pypi/dm/fitting-toolkit?label=pip%20installs)\ diff --git a/package_description.md b/package_description.md index 7e800da..bee99c2 100644 --- a/package_description.md +++ b/package_description.md @@ -10,7 +10,7 @@ # Fitting Toolkit -This toolkit aims at providing flexible and powerful tools for data analysis and modelling, but remain easy to use. +This toolkit aims at providing flexible and powerful tools for preliminary data analysis and modelling, but remain easy to use. This toolkit is aimed primarily at my peers, students of physics at the university of bonn, and to a degree at professionals within my field. I am optimizing this toolkit to be used on the scale typical of lab courses and homework assignments but if possible it should be powerful enough to run decently sized datasets on an average laptop. This package wraps numpy for fast data management and manipulation, scipy for `curve_fit()` and matplotlib for display options. diff --git a/setup.py b/setup.py index 9aa3537..6366721 100644 --- a/setup.py +++ b/setup.py @@ -9,7 +9,7 @@ setup( name = "fitting_toolkit", - version = "1.0.2", + version = "1.0.3", package_dir={"": "src"}, packages=[""], long_description=description, diff --git a/src/fitting_toolkit.py b/src/fitting_toolkit.py index a91b909..46eac93 100644 --- a/src/fitting_toolkit.py +++ b/src/fitting_toolkit.py @@ -2,6 +2,7 @@ from scipy.special import erf import numpy as np from matplotlib import pyplot as plt +import warnings def generate_thresholds(data, lower_frac=0.15865, upper_frac=0.84135): """ @@ -105,6 +106,11 @@ def curve_fit(model, xdata: np.array, ydata: np.array, yerror = None, resamples raise ValueError(f"x-data and y-data have different lengths and thus cannot be broadcast together.\nx: {np.shape(xdata)}, y: {np.shape(ydata)}") params, cov = sc_curve_fit(f = model, xdata = xdata, ydata = ydata, sigma = yerror, **kwargs) + + if np.inf in cov or -np.inf in cov: + warnings.warn("Covariance matrix includes infinite values. This usually occours due to a non convergent loss function, i.e. an unfittable model. Confidence interval could not be calculated.", RuntimeWarning) + return params, cov, None, None + if not model_axis is None: resampled_points = model_axis elif model_resolution is None: diff --git a/tests/test_functions.py b/tests/test_functions.py index 7e1e953..ae5ddb7 100644 --- a/tests/test_functions.py +++ b/tests/test_functions.py @@ -1,4 +1,5 @@ import unittest +from unittest.mock import patch import numpy as np from src.fitting_toolkit import get_sigma_probability, generate_thresholds, curve_fit from src.fitting_toolkit import plot_fit @@ -58,4 +59,29 @@ def model(x, m, c): self.assertLessEqual(diff[1], sigmas[1]*2) fig, ax = plot_fit(x, y, model, params, lower, upper, yerror=dy) - fig.savefig("./tests/plot.png") \ No newline at end of file + fig.savefig("./tests/plot.png") + + def test_infinite_covariance_warning(self): + + def mock_curve_fit(*args, **kwargs): + """Mock function to simulate infinite covariance matrix in curve_fit.""" + params = np.array([1.0, 1.0]) + cov = np.array([[np.inf, 0], [0, np.inf]]) + return params, cov + + def model(x, a, b): + return a * x + b + + xdata = np.array([1, 2, 3, 4, 5]) + ydata = model(xdata, 2, 1) + yerror = np.array([0.1] * len(xdata)) + + with patch('src.fitting_toolkit.sc_curve_fit', wraps=mock_curve_fit): + with self.assertWarns(RuntimeWarning) as cm: + params, cov, lower_conf, upper_conf = curve_fit( + model, xdata, ydata, yerror=yerror + ) + + self.assertIn("Covariance matrix includes infinite values", str(cm.warning)) + self.assertIsNone(lower_conf) + self.assertIsNone(upper_conf) \ No newline at end of file