Jupyter-friendly Python frontend for MINUIT2 C++ library for function minimization and error analysis
—
Utility classes and functions for accessing fit results, parameter information, warnings, and performing common operations. These provide structured access to minimization results and helper functions.
Data classes that store and provide access to minimization results.
class FMin:
"""Function minimum information object."""
fval: float # Function value at minimum
edm: float # Estimated distance to minimum
tolerance: float # Convergence tolerance used
nfcn: int # Number of function calls
ncalls: int # Total number of calls (alias for nfcn)
errordef: float # Error definition used
is_valid: bool # Whether minimum is valid
has_valid_parameters: bool # Whether parameters are valid
has_accurate_covar: bool # Whether covariance is accurate
has_posdef_covar: bool # Whether covariance is positive definite
has_made_posdef_covar: bool # Whether covariance was forced positive definite
hesse_failed: bool # Whether HESSE failed
has_covariance: bool # Whether covariance matrix exists
is_above_max_edm: bool # Whether EDM is above maximum
has_reached_call_limit: bool # Whether call limit was reached
algorithm: str # Algorithm used for minimization
def __str__(self) -> str:
"""String representation of fit results."""
def __repr__(self) -> str:
"""Detailed representation for debugging."""Classes for accessing individual parameter data and collections.
class Param:
"""Single parameter information object."""
number: int # Parameter index
name: str # Parameter name
value: float # Parameter value
error: float # Parabolic error
is_const: bool # Whether parameter is constant
is_fixed: bool # Whether parameter is fixed
has_limits: bool # Whether parameter has limits
has_lower_limit: bool # Whether parameter has lower limit
has_upper_limit: bool # Whether parameter has upper limit
lower_limit: float # Lower limit value
upper_limit: float # Upper limit value
merror: Optional[MError] # Minos error information (if available)
def __str__(self) -> str:
"""String representation of parameter."""
class Params:
"""Collection of parameter objects with dict-like and list-like access."""
def __len__(self) -> int:
"""Number of parameters."""
def __getitem__(self, key) -> Param:
"""Access parameter by name or index."""
def __iter__(self):
"""Iterate over parameters."""
def __str__(self) -> str:
"""Tabular string representation."""Classes for asymmetric error information from MINOS algorithm.
class MError:
"""Minos error information object."""
name: str # Parameter name
number: int # Parameter index
lower: float # Lower error (negative)
upper: float # Upper error (positive)
is_valid: bool # Whether Minos succeeded
lower_valid: bool # Whether lower error is valid
upper_valid: bool # Whether upper error is valid
at_lower_limit: bool # Whether lower error hit parameter limit
at_upper_limit: bool # Whether upper error hit parameter limit
at_lower_max_fcn: bool # Whether lower error hit function call limit
at_upper_max_fcn: bool # Whether upper error hit function call limit
lower_new_min: bool # Whether new minimum found during lower scan
upper_new_min: bool # Whether new minimum found during upper scan
nfcn: int # Number of function calls used
min: float # Parameter value at minimum
def __str__(self) -> str:
"""String representation of Minos errors."""
class MErrors:
"""Collection of Minos error objects with dict-like access."""
def __len__(self) -> int:
"""Number of parameters with Minos errors."""
def __getitem__(self, key) -> MError:
"""Access Minos error by parameter name or index."""
def __iter__(self):
"""Iterate over Minos errors."""
def __contains__(self, key) -> bool:
"""Check if parameter has Minos error."""Classes for covariance and correlation matrices with convenient access methods.
class Matrix:
"""Matrix representation for covariance and correlation matrices."""
def __init__(self, data):
"""
Initialize matrix.
Args:
data: Matrix data (2D array-like)
"""
def __getitem__(self, key):
"""Access matrix elements by parameter name or index."""
def __array__(self) -> np.ndarray:
"""Convert to numpy array."""
def correlation(self):
"""
Convert covariance matrix to correlation matrix.
Returns:
Matrix: Correlation matrix
"""
def __str__(self) -> str:
"""Formatted string representation."""Views that provide array-like access to parameter properties.
class ValueView:
"""Array-like view of parameter values."""
def __getitem__(self, key):
"""Get parameter value by name or index."""
def __setitem__(self, key, value):
"""Set parameter value by name or index."""
def __len__(self) -> int:
"""Number of parameters."""
class ErrorView:
"""Array-like view of parameter errors."""
def __getitem__(self, key):
"""Get parameter error by name or index."""
def __setitem__(self, key, value):
"""Set parameter error by name or index."""
class FixedView:
"""Array-like view of parameter fixed status."""
def __getitem__(self, key) -> bool:
"""Get parameter fixed status by name or index."""
def __setitem__(self, key, value):
"""Set parameter fixed status by name or index."""
class LimitView:
"""Array-like view of parameter limits."""
def __getitem__(self, key):
"""Get parameter limits by name or index."""
def __setitem__(self, key, value):
"""Set parameter limits by name or index."""Helper functions for common operations and function introspection.
def describe(func, annotations=None):
"""
Describe function signature and parameter information.
Args:
func: Function to describe
annotations: Optional type annotations dictionary
Returns:
Namespace: Object with parameter information including:
- name: function name
- var: list of parameter names
- pos: positional parameter names
- varargs: varargs parameter name (if any)
- varkw: varkw parameter name (if any)
- annotations: type annotations
"""
def make_func_code(names, varargs=None, varkw=None):
"""
Create function code object with specified parameter names.
Args:
names: Parameter names (list of strings)
varargs: Variable args parameter name (optional)
varkw: Variable keyword args parameter name (optional)
Returns:
types.CodeType: Function code object
"""
def make_with_signature(func, names, annotations=None):
"""
Create function with specific signature from existing function.
Args:
func: Original function
names: Parameter names for new signature
annotations: Type annotations (optional)
Returns:
callable: Function with modified signature
"""
def merge_signatures(callables):
"""
Merge signatures of multiple callables.
Args:
callables: Sequence of callable objects
Returns:
Tuple: (merged_parameter_names, parameter_mappings)
"""
def gradient(func, x, eps=None):
"""
Numerical gradient computation.
Args:
func: Function to differentiate
x: Point at which to compute gradient
eps: Step size (optional, auto-selected if None)
Returns:
np.ndarray: Gradient vector
"""
def is_positive_definite(matrix):
"""
Check if matrix is positive definite.
Args:
matrix: Matrix to check (2D array-like)
Returns:
bool: True if matrix is positive definite
"""Warning classes used throughout iminuit for different types of issues.
class IMinuitWarning(RuntimeWarning):
"""Generic iminuit warning."""
class HesseFailedWarning(IMinuitWarning):
"""HESSE algorithm failure warning."""
class PerformanceWarning(UserWarning):
"""Warning about performance issues."""from iminuit import Minuit
# After fitting
m = Minuit(cost_function, x=1, y=2)
m.migrad()
m.hesse()
# Access function minimum information
fmin = m.fmin
print(f"Function value: {fmin.fval}")
print(f"Is valid: {fmin.is_valid}")
print(f"Has accurate covariance: {fmin.has_accurate_covar}")
print(f"Function calls: {fmin.nfcn}")
# Print formatted summary
print(fmin)# Access individual parameters
params = m.params
for param in params:
print(f"{param.name}: {param.value} ± {param.error}")
if param.has_limits:
print(f" Limits: [{param.lower_limit}, {param.upper_limit}]")
# Access specific parameter
x_param = params['x']
print(f"Parameter x: value={x_param.value}, error={x_param.error}")
# Check parameter status
if x_param.is_fixed:
print("Parameter x is fixed")# Run Minos to get asymmetric errors
m.minos()
# Access Minos errors
merrors = m.merrors
for name, merror in merrors.items():
print(f"{name}: {merror.lower:+.3f} / {merror.upper:+.3f}")
if not merror.is_valid:
print(f" Warning: Minos failed for {name}")
# Check specific parameter
if 'x' in merrors:
x_merror = merrors['x']
print(f"x Minos errors: {x_merror.lower} / +{x_merror.upper}")# Access covariance matrix
if m.covariance is not None:
cov = m.covariance
print("Covariance matrix:")
print(cov)
# Convert to correlation matrix
corr = cov.correlation()
print("Correlation matrix:")
print(corr)
# Access specific elements
print(f"Cov(x,y) = {cov['x', 'y']}")
print(f"Corr(x,y) = {corr['x', 'y']}")# Array-like access to parameter properties
print(f"Parameter values: {dict(m.values)}")
print(f"Parameter errors: {dict(m.errors)}")
print(f"Fixed parameters: {[p for p in m.parameters if m.fixed[p]]}")
# Modify parameters through views
m.values['x'] = 1.5 # Set parameter value
m.errors['x'] = 0.1 # Set parameter error
m.fixed['y'] = True # Fix parameter
m.limits['x'] = (0, 10) # Set parameter limitsfrom iminuit.util import describe
def my_function(x, y, z=1, *args, **kwargs):
return x + y + z
# Describe function signature
desc = describe(my_function)
print(f"Function name: {desc.name}")
print(f"Parameters: {desc.var}")
print(f"Positional: {desc.pos}")
print(f"Varargs: {desc.varargs}")
print(f"Varkw: {desc.varkw}")from iminuit.util import gradient
import numpy as np
def quadratic(x):
return x[0]**2 + 2*x[1]**2
# Compute numerical gradient
x = np.array([1.0, 2.0])
grad = gradient(quadratic, x)
print(f"Gradient at {x}: {grad}")
# Custom step size
grad_custom = gradient(quadratic, x, eps=1e-6)
print(f"Gradient with custom eps: {grad_custom}")from iminuit.util import is_positive_definite
import numpy as np
# Check if covariance matrix is positive definite
if m.covariance is not None:
is_valid = is_positive_definite(m.covariance)
print(f"Covariance is positive definite: {is_valid}")
# Check custom matrix
test_matrix = np.array([[2, 1], [1, 2]])
print(f"Test matrix is positive definite: {is_positive_definite(test_matrix)}")import warnings
from iminuit.util import HesseFailedWarning, PerformanceWarning
# Catch iminuit-specific warnings
with warnings.catch_warnings():
warnings.simplefilter("error", HesseFailedWarning)
try:
m.hesse()
except HesseFailedWarning:
print("HESSE algorithm failed!")
# Filter performance warnings
warnings.filterwarnings("ignore", category=PerformanceWarning)from iminuit.util import make_with_signature
def generic_function(*args):
return sum(x**2 for x in args)
# Create function with specific parameter names
named_function = make_with_signature(generic_function, ['a', 'b', 'c'])
# Now can use with parameter names
m = Minuit(named_function, a=1, b=2, c=3)Install with Tessl CLI
npx tessl i tessl/pypi-iminuit