Non-linear least-squares minimization and curve-fitting with enhanced parameter management and confidence interval estimation
—
LMFIT provides comprehensive reporting functions for displaying fit results, parameter values, uncertainties, correlations, and confidence intervals in both human-readable text and HTML formats suitable for notebooks and web applications.
Functions for generating detailed text reports of fit results and confidence intervals.
def fit_report(inpars, modelpars=None, show_correl=True, min_correl=0.1, sort_pars=False):
"""
Generate detailed text report of fit results.
Args:
inpars (Parameters or MinimizerResult): Parameters or result from fit
modelpars (Parameters): Model parameters (for comparison with fit params)
show_correl (bool): Include parameter correlation matrix
min_correl (float): Minimum correlation coefficient to display
sort_pars (bool): Sort parameters alphabetically
Returns:
str: Formatted text report with fit statistics and parameter values
"""
def ci_report(ci, with_offset=True, ndigits=5):
"""
Generate confidence interval report.
Args:
ci (dict): Confidence intervals from conf_interval()
with_offset (bool): Show parameter offsets from best-fit values
ndigits (int): Number of digits for numerical display
Returns:
str: Formatted confidence interval report
"""
def report_fit(params, **kws):
"""
Alias for fit_report() for backwards compatibility.
Args:
params: Parameters or MinimizerResult
**kws: Additional arguments passed to fit_report()
Returns:
str: Formatted fit report
"""
def report_ci(ci):
"""
Alias for ci_report() for backwards compatibility.
Args:
ci (dict): Confidence intervals
Returns:
str: Formatted confidence interval report
"""Functions for generating HTML tables suitable for Jupyter notebooks and web display.
def fitreport_html_table(result, show_correl=True, min_correl=0.1):
"""
Generate HTML table for fit results.
Args:
result (MinimizerResult): Results from minimization
show_correl (bool): Include correlation matrix
min_correl (float): Minimum correlation to display
Returns:
str: HTML table string
"""
def params_html_table(params):
"""
Generate HTML table for Parameters display.
Args:
params (Parameters): Parameters object
Returns:
str: HTML table string for parameters
"""Helper functions for formatting and display customization.
def gformat(val, length=11):
"""
Format numerical values for display.
Args:
val (float): Value to format
length (int): Total field width
Returns:
str: Formatted value string
"""
def getfloat_attr(obj, attr, length=11):
"""
Extract and format floating point attributes from objects.
Args:
obj: Object containing the attribute
attr (str): Attribute name
length (int): Field width for formatting
Returns:
str: Formatted attribute value
"""
def correl_table(params, min_correl=0.1):
"""
Generate correlation matrix table.
Args:
params (Parameters): Parameters with correlation data
min_correl (float): Minimum correlation coefficient to display
Returns:
str: Formatted correlation table
"""
def alphanumeric_sort(s):
"""
Sort strings alphanumerically (natural sorting).
Args:
s (str): String to generate sort key for
Returns:
list: Sort key for natural ordering
"""import numpy as np
from lmfit import minimize, Parameters, fit_report
def exponential_residual(params, x, data):
"""Exponential decay model"""
a = params['amplitude']
t = params['decay_time']
c = params['offset']
model = a * np.exp(-x / t) + c
return model - data
# Generate sample data
x = np.linspace(0, 10, 101)
data = 5.0 * np.exp(-x / 2.0) + 1.0 + np.random.normal(size=101, scale=0.1)
# Set up and perform fit
params = Parameters()
params.add('amplitude', value=10, min=0)
params.add('decay_time', value=1, min=0.1)
params.add('offset', value=1)
result = minimize(exponential_residual, params, args=(x, data))
# Generate comprehensive fit report
report = fit_report(result)
print(report)# Generate report without correlation matrix
report_no_correl = fit_report(result, show_correl=False)
print("Report without correlations:")
print(report_no_correl)
# Show only strong correlations
report_strong_correl = fit_report(result, min_correl=0.5)
print("\nReport with strong correlations only:")
print(report_strong_correl)
# Sort parameters alphabetically
report_sorted = fit_report(result, sort_pars=True)
print("\nReport with sorted parameters:")
print(report_sorted)from lmfit import conf_interval, ci_report
# Calculate confidence intervals
ci = conf_interval(result.minimizer, result)
# Generate confidence interval report
ci_rep = ci_report(ci)
print("Confidence Intervals:")
print(ci_rep)
# Report without parameter offsets
ci_rep_no_offset = ci_report(ci, with_offset=False)
print("\nConfidence intervals (absolute values):")
print(ci_rep_no_offset)
# Custom precision
ci_rep_precise = ci_report(ci, ndigits=8)
print("\nHigh precision confidence intervals:")
print(ci_rep_precise)from lmfit.models import ExponentialModel
# Using Model interface
exp_model = ExponentialModel()
params = exp_model.guess(data, x=x)
model_result = exp_model.fit(data, params, x=x)
# Model results include additional information
print("Model Fit Report:")
print(model_result.fit_report())
# Compare initial and final parameters
print("\nComparison with initial parameters:")
print(fit_report(model_result.params, model_result.init_params))# Generate HTML table for Jupyter notebook display
from IPython.display import HTML, display
html_table = fitreport_html_table(result)
display(HTML(html_table))
# HTML table for parameters only
params_table = params_html_table(result.params)
display(HTML(params_table))def custom_report(result):
"""Create custom fit report with additional information"""
report_lines = []
# Basic fit statistics
report_lines.append("="*50)
report_lines.append("CUSTOM FIT REPORT")
report_lines.append("="*50)
report_lines.append(f"Method: {result.method}")
report_lines.append(f"Function evaluations: {result.nfev}")
report_lines.append(f"Data points: {result.ndata}")
report_lines.append(f"Variables: {result.nvarys}")
report_lines.append(f"Chi-squared: {result.chisqr:.6f}")
report_lines.append(f"Reduced chi-squared: {result.redchi:.6f}")
report_lines.append(f"AIC: {result.aic:.6f}")
report_lines.append(f"BIC: {result.bic:.6f}")
report_lines.append("")
# Parameter values with custom formatting
report_lines.append("PARAMETERS:")
report_lines.append("-"*50)
for name, param in result.params.items():
if param.vary:
stderr_str = f"±{param.stderr:.4f}" if param.stderr else "±N/A"
report_lines.append(f"{name:12s}: {param.value:.6f} {stderr_str}")
else:
report_lines.append(f"{name:12s}: {param.value:.6f} (fixed)")
return "\n".join(report_lines)
# Use custom report
print(custom_report(result))# Save text report to file
with open('fit_results.txt', 'w') as f:
f.write(fit_report(result))
if 'ci' in locals():
f.write('\n\nConfidence Intervals:\n')
f.write(ci_report(ci))
# Save HTML report for web display
html_content = f"""
<!DOCTYPE html>
<html>
<head>
<title>Fit Results</title>
<style>
body {{ font-family: Arial, sans-serif; margin: 20px; }}
table {{ border-collapse: collapse; margin: 20px 0; }}
th, td {{ border: 1px solid #ddd; padding: 8px; text-align: left; }}
th {{ background-color: #f2f2f2; }}
</style>
</head>
<body>
<h1>Fit Results</h1>
{fitreport_html_table(result)}
</body>
</html>
"""
with open('fit_results.html', 'w') as f:
f.write(html_content)def compare_multiple_fits(results_dict):
"""Compare multiple fit results in a single report"""
print("COMPARISON OF MULTIPLE FITS")
print("="*60)
# Header
header = f"{'Model':<15} {'Chi-sq':<12} {'Red Chi-sq':<12} {'AIC':<12} {'BIC':<12}"
print(header)
print("-"*60)
# Results for each fit
for name, result in results_dict.items():
line = f"{name:<15} {result.chisqr:<12.4f} {result.redchi:<12.4f} {result.aic:<12.2f} {result.bic:<12.2f}"
print(line)
print("\nDETAILED REPORTS:")
print("="*60)
# Individual detailed reports
for name, result in results_dict.items():
print(f"\n{name.upper()} FIT:")
print("-"*30)
print(fit_report(result, show_correl=False))
# Example usage with multiple models
from lmfit.models import LinearModel, QuadraticModel
linear_model = LinearModel()
quad_model = QuadraticModel()
linear_result = linear_model.fit(data, x=x)
quad_result = quad_model.fit(data, x=x)
results = {
'Linear': linear_result,
'Quadratic': quad_result,
'Exponential': model_result
}
compare_multiple_fits(results)def parameter_summary_table(results_list, model_names):
"""Create parameter comparison table across multiple fits"""
# Collect all parameter names
all_params = set()
for result in results_list:
all_params.update(result.params.keys())
# Create header
header = f"{'Parameter':<15}"
for name in model_names:
header += f"{name:<15}"
print(header)
print("-" * (15 + 15 * len(model_names)))
# Parameter rows
for param_name in sorted(all_params):
row = f"{param_name:<15}"
for result in results_list:
if param_name in result.params:
param = result.params[param_name]
if param.stderr:
value_str = f"{param.value:.3f}±{param.stderr:.3f}"
else:
value_str = f"{param.value:.3f}"
row += f"{value_str:<15}"
else:
row += f"{'N/A':<15}"
print(row)
# Usage
parameter_summary_table([linear_result, quad_result, model_result],
['Linear', 'Quadratic', 'Exponential'])Install with Tessl CLI
npx tessl i tessl/pypi-lmfit