pyerrors.integrate
1import numpy as np 2from .obs import derived_observable, Obs 3from autograd import jacobian 4from scipy.integrate import quad as squad 5 6 7def quad(func, p, a, b, **kwargs): 8 '''Performs a (one-dimensional) numeric integration of f(p, x) from a to b. 9 10 The integration is performed using scipy.integrate.quad(). 11 All parameters that can be passed to scipy.integrate.quad may also be passed to this function. 12 The output is the same as for scipy.integrate.quad, the first element being an Obs. 13 14 Parameters 15 ---------- 16 func : object 17 function to integrate, has to be of the form 18 19 ```python 20 import autograd.numpy as anp 21 22 def func(p, x): 23 return p[0] + p[1] * x + p[2] * anp.sinh(x) 24 ``` 25 where x is the integration variable. 26 p : list of floats or Obs 27 parameters of the function func. 28 a: float or Obs 29 Lower limit of integration (use -numpy.inf for -infinity). 30 b: float or Obs 31 Upper limit of integration (use -numpy.inf for -infinity). 32 All parameters of scipy.integrate.quad 33 34 Returns 35 ------- 36 y : Obs 37 The integral of func from `a` to `b`. 38 abserr : float 39 An estimate of the absolute error in the result. 40 infodict : dict 41 A dictionary containing additional information. 42 Run scipy.integrate.quad_explain() for more information. 43 message 44 A convergence message. 45 explain 46 Appended only with 'cos' or 'sin' weighting and infinite 47 integration limits, it contains an explanation of the codes in 48 infodict['ierlst'] 49 ''' 50 51 Np = len(p) 52 isobs = [True if isinstance(pi, Obs) else False for pi in p] 53 pval = np.array([p[i].value if isobs[i] else p[i] for i in range(Np)],) 54 pobs = [p[i] for i in range(Np) if isobs[i]] 55 56 bounds = [a, b] 57 isobs_b = [True if isinstance(bi, Obs) else False for bi in bounds] 58 bval = np.array([bounds[i].value if isobs_b[i] else bounds[i] for i in range(2)]) 59 bobs = [bounds[i] for i in range(2) if isobs_b[i]] 60 bsign = [-1, 1] 61 62 ifunc = np.vectorize(lambda x: func(pval, x)) 63 64 intpars = squad.__code__.co_varnames[3:3 + len(squad.__defaults__)] 65 ikwargs = {k: kwargs[k] for k in intpars if k in kwargs} 66 67 integration_result = squad(ifunc, bval[0], bval[1], **ikwargs) 68 val = integration_result[0] 69 70 jac = jacobian(func) 71 72 derivint = [] 73 for i in range(Np): 74 if isobs[i]: 75 ifunc = np.vectorize(lambda x: jac(pval, x)[i]) 76 derivint.append(squad(ifunc, bounds[0], bounds[1], **ikwargs)[0]) 77 78 for i in range(2): 79 if isobs_b[i]: 80 derivint.append(bsign[i] * func(pval, bval[i])) 81 82 if len(derivint) == 0: 83 return integration_result 84 85 res = derived_observable(lambda x, **kwargs: 0 * (x[0] + np.finfo(np.float64).eps) * (pval[0] + np.finfo(np.float64).eps) + val, pobs + bobs, man_grad=derivint) 86 87 return (res, *integration_result[1:])
def
quad(func, p, a, b, **kwargs):
8def quad(func, p, a, b, **kwargs): 9 '''Performs a (one-dimensional) numeric integration of f(p, x) from a to b. 10 11 The integration is performed using scipy.integrate.quad(). 12 All parameters that can be passed to scipy.integrate.quad may also be passed to this function. 13 The output is the same as for scipy.integrate.quad, the first element being an Obs. 14 15 Parameters 16 ---------- 17 func : object 18 function to integrate, has to be of the form 19 20 ```python 21 import autograd.numpy as anp 22 23 def func(p, x): 24 return p[0] + p[1] * x + p[2] * anp.sinh(x) 25 ``` 26 where x is the integration variable. 27 p : list of floats or Obs 28 parameters of the function func. 29 a: float or Obs 30 Lower limit of integration (use -numpy.inf for -infinity). 31 b: float or Obs 32 Upper limit of integration (use -numpy.inf for -infinity). 33 All parameters of scipy.integrate.quad 34 35 Returns 36 ------- 37 y : Obs 38 The integral of func from `a` to `b`. 39 abserr : float 40 An estimate of the absolute error in the result. 41 infodict : dict 42 A dictionary containing additional information. 43 Run scipy.integrate.quad_explain() for more information. 44 message 45 A convergence message. 46 explain 47 Appended only with 'cos' or 'sin' weighting and infinite 48 integration limits, it contains an explanation of the codes in 49 infodict['ierlst'] 50 ''' 51 52 Np = len(p) 53 isobs = [True if isinstance(pi, Obs) else False for pi in p] 54 pval = np.array([p[i].value if isobs[i] else p[i] for i in range(Np)],) 55 pobs = [p[i] for i in range(Np) if isobs[i]] 56 57 bounds = [a, b] 58 isobs_b = [True if isinstance(bi, Obs) else False for bi in bounds] 59 bval = np.array([bounds[i].value if isobs_b[i] else bounds[i] for i in range(2)]) 60 bobs = [bounds[i] for i in range(2) if isobs_b[i]] 61 bsign = [-1, 1] 62 63 ifunc = np.vectorize(lambda x: func(pval, x)) 64 65 intpars = squad.__code__.co_varnames[3:3 + len(squad.__defaults__)] 66 ikwargs = {k: kwargs[k] for k in intpars if k in kwargs} 67 68 integration_result = squad(ifunc, bval[0], bval[1], **ikwargs) 69 val = integration_result[0] 70 71 jac = jacobian(func) 72 73 derivint = [] 74 for i in range(Np): 75 if isobs[i]: 76 ifunc = np.vectorize(lambda x: jac(pval, x)[i]) 77 derivint.append(squad(ifunc, bounds[0], bounds[1], **ikwargs)[0]) 78 79 for i in range(2): 80 if isobs_b[i]: 81 derivint.append(bsign[i] * func(pval, bval[i])) 82 83 if len(derivint) == 0: 84 return integration_result 85 86 res = derived_observable(lambda x, **kwargs: 0 * (x[0] + np.finfo(np.float64).eps) * (pval[0] + np.finfo(np.float64).eps) + val, pobs + bobs, man_grad=derivint) 87 88 return (res, *integration_result[1:])
Performs a (one-dimensional) numeric integration of f(p, x) from a to b.
The integration is performed using scipy.integrate.quad(). All parameters that can be passed to scipy.integrate.quad may also be passed to this function. The output is the same as for scipy.integrate.quad, the first element being an Obs.
Parameters
func (object): function to integrate, has to be of the form
import autograd.numpy as anp def func(p, x): return p[0] + p[1] * x + p[2] * anp.sinh(x)
where x is the integration variable.
- p (list of floats or Obs): parameters of the function func.
- a (float or Obs): Lower limit of integration (use -numpy.inf for -infinity).
- b (float or Obs): Upper limit of integration (use -numpy.inf for -infinity).
- All parameters of scipy.integrate.quad
Returns
- y (Obs):
The integral of func from
a
tob
. - abserr (float): An estimate of the absolute error in the result.
- infodict (dict): A dictionary containing additional information. Run scipy.integrate.quad_explain() for more information.
- message: A convergence message.
- explain: Appended only with 'cos' or 'sin' weighting and infinite integration limits, it contains an explanation of the codes in infodict['ierlst']