gstlal-inspiral  0.4.2
 All Classes Namespaces Files Functions Variables Pages
curve_fit.py
1 # SciPy license
2 #
3 # Copyright © 2001, 2002 Enthought, Inc.
4 # All rights reserved.
5 
6 # Copyright © 2003-2013 SciPy Developers.
7 # All rights reserved.
8 #
9 # Redistribution and use in source and binary forms, with or without
10 # modification, are permitted provided that the following conditions are met:
11 
12 # Redistributions of source code must retain the above copyright notice, this
13 # list of conditions and the following disclaimer.
14 #
15 # Redistributions in binary form must reproduce the above copyright notice,
16 # this list of conditions and the following disclaimer in the documentation
17 # and/or other materials provided with the distribution.
18 #
19 # Neither the name of Enthought nor the names of the SciPy Developers may be
20 # used to endorse or promote products derived from this software without
21 # specific prior written permission.
22 #
23 # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS “AS IS”
24 # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25 # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26 # ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR
27 # ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28 # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
29 # SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
30 # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
31 # OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
32 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33 #
34 # This is copied from
35 # https://raw.githubusercontent.com/scipy/scipy/v0.10.1/scipy/optimize/minpack.py
36 #
37 # Minor modifications (for compatibility) by Chad Hanna (2014)
38 
39 import warnings
40 
41 from scipy.optimize import _minpack
42 
43 from numpy import atleast_1d, dot, take, triu, shape, eye, \
44  transpose, zeros, product, greater, array, \
45  all, where, isscalar, asarray, inf, abs
46 
47 error = _minpack.error
48 
49 __all__ = ['fsolve', 'leastsq', 'fixed_point', 'curve_fit']
50 
51 def _check_func(checker, argname, thefunc, x0, args, numinputs, output_shape=None):
52  res = atleast_1d(thefunc(*((x0[:numinputs],) + args)))
53  if (output_shape is not None) and (shape(res) != output_shape):
54  if (output_shape[0] != 1):
55  if len(output_shape) > 1:
56  if output_shape[1] == 1:
57  return shape(res)
58  msg = "%s: there is a mismatch between the input and output " \
59  "shape of the '%s' argument" % (checker, argname)
60  func_name = getattr(thefunc, 'func_name', None)
61  if func_name:
62  msg += " '%s'." % func_name
63  else:
64  msg += "."
65  raise TypeError(msg)
66  return shape(res)
67 
68 
69 def fsolve(func, x0, args=(), fprime=None, full_output=0,
70  col_deriv=0, xtol=1.49012e-8, maxfev=0, band=None,
71  epsfcn=0.0, factor=100, diag=None):
72  """
73  Find the roots of a function.
74 
75  Return the roots of the (non-linear) equations defined by
76  ``func(x) = 0`` given a starting estimate.
77 
78  Parameters
79  ----------
80  func : callable f(x, *args)
81  A function that takes at least one (possibly vector) argument.
82  x0 : ndarray
83  The starting estimate for the roots of ``func(x) = 0``.
84  args : tuple
85  Any extra arguments to `func`.
86  fprime : callable(x)
87  A function to compute the Jacobian of `func` with derivatives
88  across the rows. By default, the Jacobian will be estimated.
89  full_output : bool
90  If True, return optional outputs.
91  col_deriv : bool
92  Specify whether the Jacobian function computes derivatives down
93  the columns (faster, because there is no transpose operation).
94 
95  Returns
96  -------
97  x : ndarray
98  The solution (or the result of the last iteration for
99  an unsuccessful call).
100  infodict : dict
101  A dictionary of optional outputs with the keys::
102 
103  * 'nfev': number of function calls
104  * 'njev': number of Jacobian calls
105  * 'fvec': function evaluated at the output
106  * 'fjac': the orthogonal matrix, q, produced by the QR
107  factorization of the final approximate Jacobian
108  matrix, stored column wise
109  * 'r': upper triangular matrix produced by QR factorization of same
110  matrix
111  * 'qtf': the vector (transpose(q) * fvec)
112 
113  ier : int
114  An integer flag. Set to 1 if a solution was found, otherwise refer
115  to `mesg` for more information.
116  mesg : str
117  If no solution is found, `mesg` details the cause of failure.
118 
119  Other Parameters
120  ----------------
121  xtol : float
122  The calculation will terminate if the relative error between two
123  consecutive iterates is at most `xtol`.
124  maxfev : int
125  The maximum number of calls to the function. If zero, then
126  ``100*(N+1)`` is the maximum where N is the number of elements
127  in `x0`.
128  band : tuple
129  If set to a two-sequence containing the number of sub- and
130  super-diagonals within the band of the Jacobi matrix, the
131  Jacobi matrix is considered banded (only for ``fprime=None``).
132  epsfcn : float
133  A suitable step length for the forward-difference
134  approximation of the Jacobian (for ``fprime=None``). If
135  `epsfcn` is less than the machine precision, it is assumed
136  that the relative errors in the functions are of the order of
137  the machine precision.
138  factor : float
139  A parameter determining the initial step bound
140  (``factor * || diag * x||``). Should be in the interval
141  ``(0.1, 100)``.
142  diag : sequence
143  N positive entries that serve as a scale factors for the
144  variables.
145 
146  Notes
147  -----
148  ``fsolve`` is a wrapper around MINPACK's hybrd and hybrj algorithms.
149 
150  """
151  x0 = array(x0, ndmin=1)
152  n = len(x0)
153  if type(args) != type(()): args = (args,)
154  _check_func('fsolve', 'func', func, x0, args, n, (n,))
155  Dfun = fprime
156  if Dfun is None:
157  if band is None:
158  ml, mu = -10,-10
159  else:
160  ml, mu = band[:2]
161  if (maxfev == 0):
162  maxfev = 200*(n + 1)
163  retval = _minpack._hybrd(func, x0, args, full_output, xtol,
164  maxfev, ml, mu, epsfcn, factor, diag)
165  else:
166  _check_func('fsolve', 'fprime', Dfun, x0, args, n, (n,n))
167  if (maxfev == 0):
168  maxfev = 100*(n + 1)
169  retval = _minpack._hybrj(func, Dfun, x0, args, full_output,
170  col_deriv, xtol, maxfev, factor,diag)
171 
172  errors = {0:["Improper input parameters were entered.",TypeError],
173  1:["The solution converged.", None],
174  2:["The number of calls to function has "
175  "reached maxfev = %d." % maxfev, ValueError],
176  3:["xtol=%f is too small, no further improvement "
177  "in the approximate\n solution "
178  "is possible." % xtol, ValueError],
179  4:["The iteration is not making good progress, as measured "
180  "by the \n improvement from the last five "
181  "Jacobian evaluations.", ValueError],
182  5:["The iteration is not making good progress, "
183  "as measured by the \n improvement from the last "
184  "ten iterations.", ValueError],
185  'unknown': ["An error occurred.", TypeError]}
186 
187  info = retval[-1] # The FORTRAN return value
188  if (info != 1 and not full_output):
189  if info in [2,3,4,5]:
190  msg = errors[info][0]
191  warnings.warn(msg, RuntimeWarning)
192  else:
193  try:
194  raise errors[info][1](errors[info][0])
195  except KeyError:
196  raise errors['unknown'][1](errors['unknown'][0])
197 
198  if full_output:
199  try:
200  return retval + (errors[info][0],) # Return all + the message
201  except KeyError:
202  return retval + (errors['unknown'][0],)
203  else:
204  return retval[0]
205 
206 
207 def leastsq(func, x0, args=(), Dfun=None, full_output=0,
208  col_deriv=0, ftol=1.49012e-8, xtol=1.49012e-8,
209  gtol=0.0, maxfev=0, epsfcn=0.0, factor=100, diag=None):
210  """
211  Minimize the sum of squares of a set of equations.
212 
213  ::
214 
215  x = arg min(sum(func(y)**2,axis=0))
216  y
217 
218  Parameters
219  ----------
220  func : callable
221  should take at least one (possibly length N vector) argument and
222  returns M floating point numbers.
223  x0 : ndarray
224  The starting estimate for the minimization.
225  args : tuple
226  Any extra arguments to func are placed in this tuple.
227  Dfun : callable
228  A function or method to compute the Jacobian of func with derivatives
229  across the rows. If this is None, the Jacobian will be estimated.
230  full_output : bool
231  non-zero to return all optional outputs.
232  col_deriv : bool
233  non-zero to specify that the Jacobian function computes derivatives
234  down the columns (faster, because there is no transpose operation).
235  ftol : float
236  Relative error desired in the sum of squares.
237  xtol : float
238  Relative error desired in the approximate solution.
239  gtol : float
240  Orthogonality desired between the function vector and the columns of
241  the Jacobian.
242  maxfev : int
243  The maximum number of calls to the function. If zero, then 100*(N+1) is
244  the maximum where N is the number of elements in x0.
245  epsfcn : float
246  A suitable step length for the forward-difference approximation of the
247  Jacobian (for Dfun=None). If epsfcn is less than the machine precision,
248  it is assumed that the relative errors in the functions are of the
249  order of the machine precision.
250  factor : float
251  A parameter determining the initial step bound
252  (``factor * || diag * x||``). Should be in interval ``(0.1, 100)``.
253  diag : sequence
254  N positive entries that serve as a scale factors for the variables.
255 
256  Returns
257  -------
258  x : ndarray
259  The solution (or the result of the last iteration for an unsuccessful
260  call).
261  cov_x : ndarray
262  Uses the fjac and ipvt optional outputs to construct an
263  estimate of the jacobian around the solution. ``None`` if a
264  singular matrix encountered (indicates very flat curvature in
265  some direction). This matrix must be multiplied by the
266  residual standard deviation to get the covariance of the
267  parameter estimates -- see curve_fit.
268  infodict : dict
269  a dictionary of optional outputs with the key s::
270 
271  - 'nfev' : the number of function calls
272  - 'fvec' : the function evaluated at the output
273  - 'fjac' : A permutation of the R matrix of a QR
274  factorization of the final approximate
275  Jacobian matrix, stored column wise.
276  Together with ipvt, the covariance of the
277  estimate can be approximated.
278  - 'ipvt' : an integer array of length N which defines
279  a permutation matrix, p, such that
280  fjac*p = q*r, where r is upper triangular
281  with diagonal elements of nonincreasing
282  magnitude. Column j of p is column ipvt(j)
283  of the identity matrix.
284  - 'qtf' : the vector (transpose(q) * fvec).
285 
286  mesg : str
287  A string message giving information about the cause of failure.
288  ier : int
289  An integer flag. If it is equal to 1, 2, 3 or 4, the solution was
290  found. Otherwise, the solution was not found. In either case, the
291  optional output variable 'mesg' gives more information.
292 
293  Notes
294  -----
295  "leastsq" is a wrapper around MINPACK's lmdif and lmder algorithms.
296 
297  cov_x is a Jacobian approximation to the Hessian of the least squares
298  objective function.
299  This approximation assumes that the objective function is based on the
300  difference between some observed target data (ydata) and a (non-linear)
301  function of the parameters `f(xdata, params)` ::
302 
303  func(params) = ydata - f(xdata, params)
304 
305  so that the objective function is ::
306 
307  min sum((ydata - f(xdata, params))**2, axis=0)
308  params
309 
310  """
311  x0 = array(x0, ndmin=1)
312  n = len(x0)
313  if type(args) != type(()):
314  args = (args,)
315  m = _check_func('leastsq', 'func', func, x0, args, n)[0]
316  if n > m:
317  raise TypeError('Improper input: N=%s must not exceed M=%s' % (n,m))
318  if Dfun is None:
319  if (maxfev == 0):
320  maxfev = 200*(n + 1)
321  retval = _minpack._lmdif(func, x0, args, full_output, ftol, xtol,
322  gtol, maxfev, epsfcn, factor, diag)
323  else:
324  if col_deriv:
325  _check_func('leastsq', 'Dfun', Dfun, x0, args, n, (n,m))
326  else:
327  _check_func('leastsq', 'Dfun', Dfun, x0, args, n, (m,n))
328  if (maxfev == 0):
329  maxfev = 100*(n + 1)
330  retval = _minpack._lmder(func, Dfun, x0, args, full_output, col_deriv,
331  ftol, xtol, gtol, maxfev, factor, diag)
332 
333  errors = {0:["Improper input parameters.", TypeError],
334  1:["Both actual and predicted relative reductions "
335  "in the sum of squares\n are at most %f" % ftol, None],
336  2:["The relative error between two consecutive "
337  "iterates is at most %f" % xtol, None],
338  3:["Both actual and predicted relative reductions in "
339  "the sum of squares\n are at most %f and the "
340  "relative error between two consecutive "
341  "iterates is at \n most %f" % (ftol,xtol), None],
342  4:["The cosine of the angle between func(x) and any "
343  "column of the\n Jacobian is at most %f in "
344  "absolute value" % gtol, None],
345  5:["Number of calls to function has reached "
346  "maxfev = %d." % maxfev, ValueError],
347  6:["ftol=%f is too small, no further reduction "
348  "in the sum of squares\n is possible.""" % ftol, ValueError],
349  7:["xtol=%f is too small, no further improvement in "
350  "the approximate\n solution is possible." % xtol, ValueError],
351  8:["gtol=%f is too small, func(x) is orthogonal to the "
352  "columns of\n the Jacobian to machine "
353  "precision." % gtol, ValueError],
354  'unknown':["Unknown error.", TypeError]}
355 
356  info = retval[-1] # The FORTRAN return value
357 
358  if (info not in [1,2,3,4] and not full_output):
359  if info in [5,6,7,8]:
360  warnings.warn(errors[info][0], RuntimeWarning)
361  else:
362  try:
363  raise errors[info][1](errors[info][0])
364  except KeyError:
365  raise errors['unknown'][1](errors['unknown'][0])
366 
367  mesg = errors[info][0]
368  if full_output:
369  cov_x = None
370  if info in [1,2,3,4]:
371  from numpy.dual import inv
372  from numpy.linalg import LinAlgError
373  perm = take(eye(n),retval[1]['ipvt']-1,0)
374  r = triu(transpose(retval[1]['fjac'])[:n,:])
375  R = dot(r, perm)
376  try:
377  cov_x = inv(dot(transpose(R),R))
378  except LinAlgError:
379  pass
380  return (retval[0], cov_x) + retval[1:-1] + (mesg, info)
381  else:
382  return (retval[0], info)
383 
384 def _general_function(params, xdata, ydata, function):
385  return function(xdata, *params) - ydata
386 
387 def _weighted_general_function(params, xdata, ydata, function, weights):
388  return weights * (function(xdata, *params) - ydata)
389 
390 def curve_fit(f, xdata, ydata, p0=None, sigma=None, **kw):
391  """
392  Use non-linear least squares to fit a function, f, to data.
393 
394  Assumes ``ydata = f(xdata, *params) + eps``
395 
396  Parameters
397  ----------
398  f : callable
399  The model function, f(x, ...). It must take the independent
400  variable as the first argument and the parameters to fit as
401  separate remaining arguments.
402  xdata : An N-length sequence or an (k,N)-shaped array
403  for functions with k predictors.
404  The independent variable where the data is measured.
405  ydata : N-length sequence
406  The dependent data --- nominally f(xdata, ...)
407  p0 : None, scalar, or M-length sequence
408  Initial guess for the parameters. If None, then the initial
409  values will all be 1 (if the number of parameters for the function
410  can be determined using introspection, otherwise a ValueError
411  is raised).
412  sigma : None or N-length sequence
413  If not None, it represents the standard-deviation of ydata.
414  This vector, if given, will be used as weights in the
415  least-squares problem.
416 
417  Returns
418  -------
419  popt : array
420  Optimal values for the parameters so that the sum of the squared error
421  of ``f(xdata, *popt) - ydata`` is minimized
422  pcov : 2d array
423  The estimated covariance of popt. The diagonals provide the variance
424  of the parameter estimate.
425 
426  See Also
427  --------
428  leastsq
429 
430  Notes
431  -----
432  The algorithm uses the Levenburg-Marquardt algorithm through `leastsq`.
433  Additional keyword arguments are passed directly to that algorithm.
434 
435  Examples
436  --------
437  >>> import numpy as np
438  >>> from scipy.optimize import curve_fit
439  >>> def func(x, a, b, c):
440  ... return a*np.exp(-b*x) + c
441 
442  >>> x = np.linspace(0,4,50)
443  >>> y = func(x, 2.5, 1.3, 0.5)
444  >>> yn = y + 0.2*np.random.normal(size=len(x))
445 
446  >>> popt, pcov = curve_fit(func, x, yn)
447 
448  """
449  if p0 is None:
450  # determine number of parameters by inspecting the function
451  import inspect
452  args, varargs, varkw, defaults = inspect.getargspec(f)
453  if len(args) < 2:
454  msg = "Unable to determine number of fit parameters."
455  raise ValueError(msg)
456  if 'self' in args:
457  p0 = [1.0] * (len(args)-2)
458  else:
459  p0 = [1.0] * (len(args)-1)
460 
461  if isscalar(p0):
462  p0 = array([p0])
463 
464  args = (xdata, ydata, f)
465  if sigma is None:
466  func = _general_function
467  else:
468  func = _weighted_general_function
469  args += (1.0/asarray(sigma),)
470 
471  # Remove full_output from kw, otherwise we're passing it in twice.
472  return_full = kw.pop('full_output', False)
473  res = leastsq(func, p0, args=args, full_output=1, **kw)
474  (popt, pcov, infodict, errmsg, ier) = res
475 
476  if ier not in [1,2,3,4]:
477  msg = "Optimal parameters not found: " + errmsg
478  raise RuntimeError(msg)
479 
480  if (len(ydata) > len(p0)) and pcov is not None:
481  s_sq = (func(popt, *args)**2).sum()/(len(ydata)-len(p0))
482  pcov = pcov * s_sq
483  else:
484  pcov = inf
485 
486  if return_full:
487  return popt, pcov, infodict, errmsg, ier
488  else:
489  return popt, pcov
490 
491 def check_gradient(fcn, Dfcn, x0, args=(), col_deriv=0):
492  """Perform a simple check on the gradient for correctness.
493 
494  """
495 
496  x = atleast_1d(x0)
497  n = len(x)
498  x = x.reshape((n,))
499  fvec = atleast_1d(fcn(x,*args))
500  m = len(fvec)
501  fvec = fvec.reshape((m,))
502  ldfjac = m
503  fjac = atleast_1d(Dfcn(x,*args))
504  fjac = fjac.reshape((m,n))
505  if col_deriv == 0:
506  fjac = transpose(fjac)
507 
508  xp = zeros((n,), float)
509  err = zeros((m,), float)
510  fvecp = None
511  _minpack._chkder(m, n, x, fvec, fjac, ldfjac, xp, fvecp, 1, err)
512 
513  fvecp = atleast_1d(fcn(xp,*args))
514  fvecp = fvecp.reshape((m,))
515  _minpack._chkder(m, n, x, fvec, fjac, ldfjac, xp, fvecp, 2, err)
516 
517  good = (product(greater(err, 0.5), axis=0))
518 
519  return (good, err)
520 
521 
522 # Steffensen's Method using Aitken's Del^2 convergence acceleration.
523 def fixed_point(func, x0, args=(), xtol=1e-8, maxiter=500):
524  """Find the point where func(x) == x
525 
526  Given a function of one or more variables and a starting point, find a
527  fixed-point of the function: i.e. where func(x)=x.
528 
529  Uses Steffensen's Method using Aitken's Del^2 convergence acceleration.
530  See Burden, Faires, "Numerical Analysis", 5th edition, pg. 80
531 
532  Examples
533  --------
534  >>> from numpy import sqrt, array
535  >>> from scipy.optimize import fixed_point
536  >>> def func(x, c1, c2):
537  return sqrt(c1/(x+c2))
538  >>> c1 = array([10,12.])
539  >>> c2 = array([3, 5.])
540  >>> fixed_point(func, [1.2, 1.3], args=(c1,c2))
541  array([ 1.4920333 , 1.37228132])
542 
543  """
544  if not isscalar(x0):
545  x0 = asarray(x0)
546  p0 = x0
547  for iter in range(maxiter):
548  p1 = func(p0, *args)
549  p2 = func(p1, *args)
550  d = p2 - 2.0 * p1 + p0
551  p = where(d == 0, p2, p0 - (p1 - p0)*(p1 - p0) / d)
552  relerr = where(p0 == 0, p, (p-p0)/p0)
553  if all(abs(relerr) < xtol):
554  return p
555  p0 = p
556  else:
557  p0 = x0
558  for iter in range(maxiter):
559  p1 = func(p0, *args)
560  p2 = func(p1, *args)
561  d = p2 - 2.0 * p1 + p0
562  if d == 0.0:
563  return p2
564  else:
565  p = p0 - (p1 - p0)*(p1 - p0) / d
566  if p0 == 0:
567  relerr = p
568  else:
569  relerr = (p - p0)/p0
570  if abs(relerr) < xtol:
571  return p
572  p0 = p
573  msg = "Failed to converge after %d iterations, value is %s" % (maxiter, p)
574  raise RuntimeError(msg)
575