Source code for vega.minimizer

import iminuit
import time
import copy
from sys import stdout


[docs]class Minimizer: """Class for handling the interface to the minimizer. """ def __init__(self, chi2_func, sample_params): """ Parameters ---------- chi2_func : function Function that takes dictionary of params and returns a chi^2 value sample_params : dict Dictionary with the sample params config """ self.chi2_func = chi2_func self._names = sample_params['limits'].keys() self._sample_params = sample_params self._config = {} self._run_flag = False
[docs] def chi2(self, *pars): """Wrapper of chi2 function for iminuit. Returns ------- float chi^2 """ sample_params = {par: pars[i] for i, par in enumerate(self._names)} return self.chi2_func(sample_params)
[docs] def minimize(self, params=None): """Minimize the chi2. Parameters ---------- params : dict, optional Dictionary of sample parameters, used to change starting value and/or fix parameters, by default None """ t0 = time.time() params_init = copy.deepcopy(self._sample_params['values']) errors = copy.deepcopy(self._sample_params['errors']) limits = copy.deepcopy(self._sample_params['limits']) fixed = copy.deepcopy(self._sample_params['fix']) def write_settings(params, name, out_container): if name in params: for par, val in params[name].items(): out_container[par] = val if params is not None: write_settings(params, 'values', params_init) write_settings(params, 'errors', errors) write_settings(params, 'limits', limits) write_settings(params, 'fix', fixed) # Do an initial "fast" minimization over biases bias_flag = bool(len([par for par in self._names if 'bias' in par])) if bias_flag: mig_init = iminuit.Minuit(self.chi2, name=self._names, **params_init) for name in self._names: mig_init.errors[name] = errors[name] mig_init.limits[name] = limits[name] mig_init.fixed[name] = fixed[name] for name in self._names: if 'bias' not in name: mig_init.fixed[name] = True mig_init.errordef = 1 mig_init.print_level = 1 mig_init.migrad() print(mig_init.fmin) print(mig_init.params) for param, value in mig_init.values.to_dict().items(): params_init[param] = value # Do the actual minimization self._minuit = iminuit.Minuit(self.chi2, name=self._names, **params_init) for name in self._names: self._minuit.errors[name] = errors[name] self._minuit.limits[name] = limits[name] self._minuit.fixed[name] = fixed[name] self._minuit.errordef = 1 self._minuit.print_level = 1 self._minuit.migrad() print(self._minuit.fmin) print(self._minuit.params) print("INFO: minimized in {}".format(time.time()-t0)) stdout.flush() self._run_flag = True
@property def params(self): if not self._run_flag: print('Run Minimizer.minimize() before asking for results') raise RuntimeError('Tried to access minimization results before minimization.') return self._minuit.params @property def values(self): if not self._run_flag: print('Run Minimizer.minimize() before asking for results') raise RuntimeError('Tried to access minimization results before minimization.') return dict(self._minuit.values.to_dict()) @property def errors(self): if not self._run_flag: print('Run Minimizer.minimize() before asking for results') raise RuntimeError('Tried to access minimization results before minimization.') return dict(self._minuit.errors.to_dict()) @property def covariance(self): if not self._run_flag: print('Run Minimizer.minimize() before asking for results') raise RuntimeError('Tried to access minimization results before minimization.') return self._minuit.covariance @property def fmin(self): if not self._run_flag: print('Run Minimizer.minimize() before asking for results') raise RuntimeError('Tried to access minimization results before minimization.') return self._minuit.fmin @property def minuit(self): if not self._run_flag: print('Run Minimizer.minimize() before asking for results') raise RuntimeError('Tried to access minimization results before minimization.') return self._minuit