1 """
2 LMfit-py provides a Least-Squares Minimization routine and
3 class with a simple, flexible approach to parameterizing a
4 model for fitting to data. Named Parameters can be held
5 fixed or freely adjusted in the fit, or held between lower
6 and upper bounds. If the separate asteval module has been
7 installed, parameters can be constrained as a simple
8 mathematical expression of other Parameters.
9
10 version: 0.7.2
11 last update: 20-June-2013
12 License: BSD
13 Author: Matthew Newville <newville@cars.uchicago.edu>
14 Center for Advanced Radiation Sources,
15 The University of Chicago
16
17 Changes applied to lmfit and uncertainties to make it work with sigproc:
18
19 fixed uncertainties import to accomodate its place in the ivs repository
20 uncertainties.umath
21 import uncertainties -> from ivs.sigproc.lmfit import uncertainties
22
23 uncertainties.unumpy.__init__:
24 from uncertainties.unumpy import core -> import core
25 uncertainties.unumpy -> ivs.sigproc.lmfit.uncertainties.unumpy
26
27 uncertainties.unumpy.core:
28 import uncertainties -> from ivs.sigproc.lmfit import uncertainties
29
30 uncertainties.unumpy.ulinalg
31 from uncertainties import __author__ -> from ivs.sigproc.lmfit.uncertainties import __author__
32 from uncertainties.unumpy import core -> import core
33
34 Delete all tests as they are not nessesary at all.
35 uncertainties.unumpy.test_unumpy, uncertainties.unumpy.test_ulinalg,
36 uncertainties.test_umath, uncertainties.test_uncertainties
37
38 """
39 __version__ = '0.7.2'
40 from .minimizer import minimize, Minimizer, MinimizerException, make_paras_and_func
41 from .parameter import Parameter, Parameters
42 from .confidence import conf_interval, conf_interval2d, ConfidenceInterval
43 from .printfuncs import (fit_report, ci_report,
44 report_fit, report_ci, report_errors)
45
46 from . import uncertainties
47 from .uncertainties import ufloat, correlated_values
48
49
50
51
52
53 import re
54 import numpy as np
55 from cc.ivs.aux import decorators
59 """
60 Checks if the given parameters can be kicked and returns the good ones in a list.
61 """
62 if pnames == None:
63 pnames = self.keys()
64 kick_pars = []
65 for key in pnames:
66 if self[key].can_kick():
67 kick_pars.append(key)
68 return kick_pars
69
72 """
73 Kicks the given parameters to a new value chosen from the uniform
74 distribution between max and min value.
75 """
76 if pnames == None:
77 pnames = self.can_kick()
78 for key in pnames:
79 self[key].kick()
80
83 """
84 Allow easy access to the parameter attributes like value ect.
85 fx. all values can be reached with Parameters.value
86 """
87 if name in ['name', 'value', 'min', 'max', 'vary', 'expr',
88 'stderr', 'mcerr', 'cierr', 'correl']:
89 return [getattr(p, name) for n, p in self.items()]
90 else:
91 raise AttributeError
92
93 @decorators.extend(Parameter)
94 -def __init__(self, name=None, value=None, vary=True,
95 min=None, max=None, expr=None):
96 self.name = name
97 self._val = value
98 self.user_value = value
99 self.init_value = value
100 self.min = min
101 self.max = max
102 self.vary = vary
103 self.expr = expr
104 self.deps = None
105 self.stderr = None
106 self.correl = {}
107 self.cierr = {}
108 self.mcerr = None
109 if self.max is not None and value > self.max:
110 self._val = self.max
111 if self.min is not None and value < self.min:
112 self._val = self.min
113 self.from_internal = lambda val: val
114
117 """
118 Returns True is the parameter can be kicked (has defined min and max)
119 """
120 return self.min != None and self.max != None and \
121 np.isfinite(self.min) and np.isfinite(self.max)
122
125 """
126 Kick the starting value to a random value between min and max
127 """
128 value = np.random.uniform(low=self.min, high=self.max)
129 self._val = value
130 self.user_value = value
131
134 """
135 Allow to reach any cierr directly with coded attribute name (fx. ci95),
136 Allow to get min and max with the bounds attribute
137 Allow to obtain procentual error
138 """
139 ciexpr = r"^ci(\d\d+?)$"
140 errexpr = r"(stderr|mcerr)pc"
141 if name == 'bounds':
142 return (self.min, self.max)
143 if re.match(ciexpr, name):
144 ci = '0.' + str(re.findall(ciexpr, name)[0])
145 if ci in self.cierr:
146 return self.cierr[ci]
147 else:
148 return (np.nan, np.nan)
149 if re.match(errexpr, name):
150 error = getattr( self, str(re.findall(errexpr, name)[0]) )
151 if error == None or self.value == 0. or np.isnan(self.value):
152 return np.nan
153 else:
154 return abs(error/self.value * 100.)
155 else:
156 raise AttributeError('%s not assigned'%(name))
157
158 @decorators.extend(Minimizer)
160 "Start the actual fitting"
161 engine = engine.lower()
162
163
164 scal_min = dict(powel='Powell', cg='CG', newton='Newton-CG',
165 cobyla='COBYLA', slsqp='SLSQP')
166 if engine in ['powell', 'cg', 'newton', 'cobyla', 'slsqp']:
167 engine = scal_min[engine]
168 self.scalar_minimize(method=engine, **kwargs)
169
170
171 elif engine == 'anneal':
172 self.anneal(**kwargs)
173 elif engine == 'lbfgsb':
174 self.lbfgsb(**kwargs)
175 elif engine == 'fmin' or engine == 'nelder':
176 self.fmin(**kwargs)
177 else:
178 self.leastsq(**kwargs)
179
182 """
183 Calculates all cis, and returns the cis in a structured dict as:
184 ci = {pname = {'0.95'=(lower, upper), '0.66'=(lower, upper)} }
185 """
186 out = {}
187 for p in self.p_names:
188
189 lower = self.calc_ci(p, -1)
190 upper = self.calc_ci(p, 1)
191
192 o = {}
193 for s, l, u in zip(self.sigmas, lower, upper):
194 o[s] = (l[1], u[1])
195 out[p] = o
196
197 if self.trace:
198 self.trace_dict = map_trace_to_names(self.trace_dict,
199 self.minimizer.params)
200
201 return out
202
203
204
205
206 __xall__ = ['minimize', 'Minimizer', 'Parameter', 'Parameters',
207 'conf_interval', 'conf_interval2d', 'make_paras_and_func',
208 'fit_report', 'ci_report', 'report_errors',
209 'report_fit', 'report_ci', 'ufloat',
210 'correlated_values']
211