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 to b.
  • 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']