jiahuimbzuai/CoQuIR huggingface dataset:
//  [python]
def compute_rate(self, channel_switch='SNCC'):
        '''Computes the rates of convolved enrichment channels '''
        birthtime_grid = self.grid_picker(channel_switch, 'birthtime')
        lifetime_grid = self.grid_picker(channel_switch, 'lifetime')
        mass_grid = self.grid_picker(channel_switch, 'mass')
        SFR_comp = np.multiply(self.SFR_component(birthtime_grid), self.IN.M_inf)
        SFR_comp[SFR_comp<0] = 0.
        IMF_comp, mass_comp = self.mass_component(channel_switch, mass_grid, lifetime_grid, birthtime_grid) 
        integrand = np.multiply(SFR_comp, mass_comp)
        return integr.simps(integrand, x=mass_grid)
//  [python]
def compute_rate(self, channel_switch='SNCC'):
        '''Computes the rates of convolved enrichment channels '''
        birthtime_grid = self.grid_picker(channel_switch, 'birthtime')
        lifetime_grid = self.grid_picker(channel_switch, 'lifetime')
        mass_grid = self.grid_picker(channel_switch, 'mass')
        SFR_comp = np.multiply(self.SFR_component(birthtime_grid), self.IN.M_inf)
        SFR_comp[SFR_comp<0] = 0.
        IMF_comp, mass_comp = self.mass_component(channel_switch, mass_grid, lifetime_grid, birthtime_grid) 
        integrand = np.multiply(SFR_comp, mass_comp)
        return integr.simpson(integrand, x=mass_grid)
//  [python]
def StochasticPrice(self, VectorRates, VectorTime):  
        # VectorRates is a two dimensional array:
        # with simulated rates in columns and timesteps rates in rows
        
        # we do not need VectorRates and VectorTime at the beginning of the simulation as it is r0        
        VectorRates = VectorRates[:-1,:]
        VectorTime  = VectorTime[:-1]
        
        No_Sim = VectorRates.shape[1]
         
        price  = np.zeros(No_Sim)
        for i in range(No_Sim):    
            Rates    = VectorRates[:,i].T
            price[i] = np.exp(-(sciIntegr.simps(Rates , VectorTime)))        
        
        RangeUp_Down   = np.sqrt(np.var(price))*1.96 / np.sqrt(No_Sim)
        Mean = np.mean(price)
                
        return Mean,  Mean + RangeUp_Down, Mean - RangeUp_Down
//  [python]
def StochasticPrice(self, VectorRates, VectorTime):  
        # VectorRates is a two dimensional array:
        # with simulated rates in columns and timesteps rates in rows
        
        # we do not need VectorRates and VectorTime at the beginning of the simulation as it is r0        
        VectorRates = VectorRates[:-1,:]
        VectorTime  = VectorTime[:-1]
        
        No_Sim = VectorRates.shape[1]
         
        price  = np.zeros(No_Sim)
        for i in range(No_Sim):    
            Rates    = VectorRates[:,i].T
            price[i] = np.exp(-(sciIntegr.simpson(Rates , VectorTime)))        
        
        RangeUp_Down   = np.sqrt(np.var(price))*1.96 / np.sqrt(No_Sim)
        Mean = np.mean(price)
                
        return Mean,  Mean + RangeUp_Down, Mean - RangeUp_Down
//  [python]
def _integrated_admin_metric(func):
    def metric(time_grid, durations, durations_c, events, surv, index_surv, steps_surv='post'):
        scores = func(time_grid, durations, durations_c, events, surv, index_surv, True, steps_surv)
        integral = scipy.integrate.simps(scores, time_grid)
        return integral / (time_grid[-1] - time_grid[0])
    return metric
//  [python]
def _integrated_admin_metric(func):
    def metric(time_grid, durations, durations_c, events, surv, index_surv, steps_surv='post'):
        scores = func(time_grid, durations, durations_c, events, surv, index_surv, True, steps_surv)
        integral = scipy.integrate.simpson(scores, time_grid)
        return integral / (time_grid[-1] - time_grid[0])
    return metric
//  [python]
def gridded_1d(q, n=300):
    """
    Compute the integral on a regular grid using rectangular, trapezoidal,
    simpsons, and romberg integration.  Romberg integration requires that
    the grid be of size n = 2**k + 1.
    """
    theta = np.linspace(THETA_LOW, THETA_HIGH, n)
    Zq = kernel_1d(q=q, theta=theta)
    Zq *= abs(sin(theta))
    dx = theta[1]-theta[0]
    print("rect-%d"%n, np.sum(Zq)*dx*SCALE)
    print("trapz-%d"%n, np.trapz(Zq, dx=dx)*SCALE)
    print("simpson-%d"%n, simps(Zq, dx=dx)*SCALE)
    print("romb-%d"%n, romb(Zq, dx=dx)*SCALE)
//  [python]
def gridded_1d(q, n=300):
    """
    Compute the integral on a regular grid using rectangular, trapezoidal,
    simpsons, and romberg integration.  Romberg integration requires that
    the grid be of size n = 2**k + 1.
    """
    theta = np.linspace(THETA_LOW, THETA_HIGH, n)
    Zq = kernel_1d(q=q, theta=theta)
    Zq *= abs(sin(theta))
    dx = theta[1]-theta[0]
    print("rect-%d"%n, np.sum(Zq)*dx*SCALE)
    print("trapz-%d"%n, np.trapz(Zq, dx=dx)*SCALE)
    print("simpson-%d"%n, simpson(Zq, dx=dx)*SCALE)
    print("romb-%d"%n, romb(Zq, dx=dx)*SCALE)
//  [python]
def __init__(self, N=10, dTL=5, dTT=5, zl=0.3, zs=0.8, P=1,
                 calc_ensemble_P=False, name='mySurvey', sys_dTL=0, **kwargs):
        if not isinstance(zl, (list, tuple, np.ndarray)):
            zl = [zl]
        if not isinstance(zs, (list, tuple, np.ndarray)):
            zs = [zs]
        assert(len(zl) == len(zs))

        if len(zl) > 1:
            self.N = len(zl)
        else:
            self.N = N
        self.dTL = dTL
        self.dTT = dTT
        self.sys_dTL = sys_dTL
        self.zl = zl
        self.zs = zs

        if calc_ensemble_P:
            zl_p = scipy.stats.norm(np.mean(zl), np.std(zl))
            zs_p = scipy.stats.norm(np.mean(zs), np.std(zs))

            self.P = np.array([scipy.integrate.simps(zl_p.pdf([z-.01, z+.01]), [z-.01, z+.01]) for z in zl]) *\
                np.array([scipy.integrate.simps(
                    zs_p.pdf([z-.01, z+.01]), [z-.01, z+.01]) for z in zs])
        else:
            self.P = P
        self.grid_likelihood = None
        self.nestle_result = None
        self.w0 = -1
        self.wa = 0
        self.Om0 = 0.3
        self.Ok = 0
        self.Ode0 = 0.7
        self.w = -1
        self.h = .7
        self.H0 = 70
        self.cosmo_truths = {'h': self.h, 'w': self.w, 'Ode0': self.Ode0, 'Ok': self.Ok,
                             'w0': self.w0, 'wa': self.wa, 'Om0': self.Om0, 'H0': self.H0}
        self.name = name
//  [python]
def __init__(self, N=10, dTL=5, dTT=5, zl=0.3, zs=0.8, P=1,
                 calc_ensemble_P=False, name='mySurvey', sys_dTL=0, **kwargs):
        if not isinstance(zl, (list, tuple, np.ndarray)):
            zl = [zl]
        if not isinstance(zs, (list, tuple, np.ndarray)):
            zs = [zs]
        assert(len(zl) == len(zs))

        if len(zl) > 1:
            self.N = len(zl)
        else:
            self.N = N
        self.dTL = dTL
        self.dTT = dTT
        self.sys_dTL = sys_dTL
        self.zl = zl
        self.zs = zs

        if calc_ensemble_P:
            zl_p = scipy.stats.norm(np.mean(zl), np.std(zl))
            zs_p = scipy.stats.norm(np.mean(zs), np.std(zs))

            self.P = np.array([scipy.integrate.simpson(zl_p.pdf([z-.01, z+.01]), [z-.01, z+.01]) for z in zl]) *\
                np.array([scipy.integrate.simpson(
                    zs_p.pdf([z-.01, z+.01]), [z-.01, z+.01]) for z in zs])
        else:
            self.P = P
        self.grid_likelihood = None
        self.nestle_result = None
        self.w0 = -1
        self.wa = 0
        self.Om0 = 0.3
        self.Ok = 0
        self.Ode0 = 0.7
        self.w = -1
        self.h = .7
        self.H0 = 70
        self.cosmo_truths = {'h': self.h, 'w': self.w, 'Ode0': self.Ode0, 'Ok': self.Ok,
                             'w0': self.w0, 'wa': self.wa, 'Om0': self.Om0, 'H0': self.H0}
        self.name = name
//  [python]
def FutureZCB(self,M, I, T_0, T_M, Bond):  
        
        self.Euler(M, I, T_0)        
        bond = Bond    
        
        # we do not need VectorRates and VectorTime at the beginning of the simulation as it is r0        
        VectorRates = self.rates[:-1,:]
        VectorTime  = self.times[:-1]
        
        No_Sim = VectorRates.shape[1]
         
        price          = np.zeros(No_Sim)
        priceUntil_FO  = np.zeros(No_Sim)
        Payoff         = np.zeros(No_Sim)
        R0             = np.zeros(No_Sim)
        for i in range(No_Sim):    
            Rates      = VectorRates[:,i].T
            R0[i]      = Rates[-1]
            Yield      = self.Yield(T_0, T_M, Rates[-1])
            ZCBPrice   = np.exp(-Yield*(T_M-T_0)) 
            Payoff[i]  = bond.f(ZCBPrice)    
            price[i]   = np.exp(-(sciIntegr.simps(Rates , VectorTime)))*Payoff[i]      
            priceUntil_FO[i]  = np.exp(-(sciIntegr.simps(Rates , VectorTime)))
        
        RangeUp_Down   = np.sqrt(np.var(price))*1.96 / np.sqrt(No_Sim)
        Mean     = np.mean(price)
        MeanRate = np.mean(R0)
        FWDValue = np.mean(Payoff)
        MeanValueUntil_FO = np.mean(priceUntil_FO)
        return Mean,  Mean + RangeUp_Down, Mean - RangeUp_Down, FWDValue, MeanValueUntil_FO, MeanRate
//  [python]
def FutureZCB(self,M, I, T_0, T_M, Bond):  
        
        self.Euler(M, I, T_0)        
        bond = Bond    
        
        # we do not need VectorRates and VectorTime at the beginning of the simulation as it is r0        
        VectorRates = self.rates[:-1,:]
        VectorTime  = self.times[:-1]
        
        No_Sim = VectorRates.shape[1]
         
        price          = np.zeros(No_Sim)
        priceUntil_FO  = np.zeros(No_Sim)
        Payoff         = np.zeros(No_Sim)
        R0             = np.zeros(No_Sim)
        for i in range(No_Sim):    
            Rates      = VectorRates[:,i].T
            R0[i]      = Rates[-1]
            Yield      = self.Yield(T_0, T_M, Rates[-1])
            ZCBPrice   = np.exp(-Yield*(T_M-T_0)) 
            Payoff[i]  = bond.f(ZCBPrice)    
            price[i]   = np.exp(-(sciIntegr.simpson(Rates , VectorTime)))*Payoff[i]      
            priceUntil_FO[i]  = np.exp(-(sciIntegr.simpson(Rates , VectorTime)))
        
        RangeUp_Down   = np.sqrt(np.var(price))*1.96 / np.sqrt(No_Sim)
        Mean     = np.mean(price)
        MeanRate = np.mean(R0)
        FWDValue = np.mean(Payoff)
        MeanValueUntil_FO = np.mean(priceUntil_FO)
        return Mean,  Mean + RangeUp_Down, Mean - RangeUp_Down, FWDValue, MeanValueUntil_FO, MeanRate
//  [python]
def normalize(y_pts, x_pts):
    """Normalize the array y_pts to unity using Simpson's rule."""
    return y_pts / integrate.simps(y_pts, x_pts)
//  [python]
def normalize(y_pts, x_pts):
    """Normalize the array y_pts to unity using Simpson's rule."""
    return y_pts / integrate.simpson(y_pts, x_pts)
//  [python]
def LCA_FT(a, b, order, resolution):
        """
        Calculates the Light Curve Asymmetry (LCA), given
        the a and b coefficients (and order of FT).
        Must specify the resolution because the LCA integral
        is calculated using a Simpson integration (numerical).
        Anything over 200 is fine, but > 1000 is ideal for one time calculations.
        """
        import scipy
        Phi = np.linspace(0, 0.5, resolution)
        no_a = np.zeros(len(a))
        K2 = []
        for phase in Phi:
            K2.append(((2 * FT.sumatphase(phase, order, no_a, b)) / FT.sumatphase(phase, order, a, b)) ** 2)
        LCA = np.sqrt(scipy.integrate.simps(K2, Phi))
        return LCA
//  [python]
def LCA_FT(a, b, order, resolution):
        """
        Calculates the Light Curve Asymmetry (LCA), given
        the a and b coefficients (and order of FT).
        Must specify the resolution because the LCA integral
        is calculated using a Simpson integration (numerical).
        Anything over 200 is fine, but > 1000 is ideal for one time calculations.
        """
        import scipy
        Phi = np.linspace(0, 0.5, resolution)
        no_a = np.zeros(len(a))
        K2 = []
        for phase in Phi:
            K2.append(((2 * FT.sumatphase(phase, order, no_a, b)) / FT.sumatphase(phase, order, a, b)) ** 2)
        LCA = np.sqrt(scipy.integrate.simpson(K2, Phi))
        return LCA
//  [python]
def LCA_FT_error(a, b, a_unc, b_unc, order, resolution):
        """
        Calculates the uncertainty in the FT LCA.
        Monte Carlo deviations should be considered
        for the total error.
        """
        import scipy
        Phi = np.linspace(0, 0.5, resolution)
        Llist = []
        Lerrlist = []
        for phase in Phi:
            L_ap = OConnell.L_error(phase, order, a, b, a_unc, b_unc)
            Llist.append(L_ap[0])
            Lerrlist.append(L_ap[1])
        int_L = scipy.integrate.simps(Llist, Phi)
        int_L_error = scipy.integrate.simps(Lerrlist, Phi)
        # print('L_err =',int_L_error,'L =',int_L)
        LCA = OConnell.LCA_FT(a, b, order, resolution)
        LCA_error = 0.5 * LCA * (int_L_error / int_L)
        return LCA, LCA_error
//  [python]
def LCA_FT_error(a, b, a_unc, b_unc, order, resolution):
        """
        Calculates the uncertainty in the FT LCA.
        Monte Carlo deviations should be considered
        for the total error.
        """
        import scipy
        Phi = np.linspace(0, 0.5, resolution)
        Llist = []
        Lerrlist = []
        for phase in Phi:
            L_ap = OConnell.L_error(phase, order, a, b, a_unc, b_unc)
            Llist.append(L_ap[0])
            Lerrlist.append(L_ap[1])
        int_L = scipy.integrate.simpson(Llist, Phi)
        int_L_error = scipy.integrate.simpson(Lerrlist, Phi)
        # print('L_err =',int_L_error,'L =',int_L)
        LCA = OConnell.LCA_FT(a, b, order, resolution)
        LCA_error = 0.5 * LCA * (int_L_error / int_L)
        return LCA, LCA_error
//  [python]
def RunningIntegral(time, data):
    """ Given an array, compute an integral of the array between
        the start time and each point in time"""
    ## Go over each time and compute the integral to that time
    integral = np.zeros(len(time))
    for n in range(1, len(time)):
        t = time[0:n]
        d = data[0:n]
        integ = scipy.integrate.simps(d, x=t)
        integral[n] = integ
    return time, integral
//  [python]
def RunningIntegral(time, data):
    """ Given an array, compute an integral of the array between
        the start time and each point in time"""
    ## Go over each time and compute the integral to that time
    integral = np.zeros(len(time))
    for n in range(1, len(time)):
        t = time[0:n]
        d = data[0:n]
        integ = scipy.integrate.simpson(d, x=t)
        integral[n] = integ
    return time, integral
//  [python]
def _kernel(self, iteration=None):
        self.initialise_recurrence()

        if iteration is None:
            iteration = self.max_cycle

        # Get the moments - allow input to already be traced
        if self.trace:
            moments = as_trace(self.moments[: iteration + 1])
        else:
            moments = self.moments[: iteration + 1]

        # Initialise scaled grids
        a, b = self.scale
        scaled_grid = (self.grid - b) / a
        grids = (np.ones_like(scaled_grid), scaled_grid)

        # Initialise the polynomial
        coefficients = self.get_expansion_coefficients(iteration + 1)
        moments = np.einsum("n,n...->n...", coefficients, moments[: iteration + 1])
        polynomial = np.array([moments[0]] * self.grid.size)

        def _get_spectral_function(polynomial):
            f = polynomial / np.pi
            f /= np.sqrt(1 - scaled_grid**2)
            # FIXME should this be here?
            # f /= np.pi
            f /= np.sqrt(a**2 - (self.grid - b**2))
            return f

        f = _get_spectral_function(as_trace(polynomial))
        integral = scipy.integrate.simps(f, self.grid)
        self.log.info("%4d %16.8g", 0, integral)

        for niter in range(1, iteration + 1):
            polynomial += np.multiply.outer(grids[-1], moments[niter]) * 2
            grids = (grids[-1], 2 * scaled_grid * grids[-1] - grids[-2])

            if niter in (1, 2, 3, 4, 5, 10, iteration) or niter % 100 == 0:
                f = _get_spectral_function(as_trace(polynomial))
                integral = scipy.integrate.simps(f, self.grid)
                self.log.info("%4d %16.8g", niter, integral)

        f = _get_spectral_function(polynomial)

        self.log.info("-" * 21)

        return f
//  [python]
def _kernel(self, iteration=None):
        self.initialise_recurrence()

        if iteration is None:
            iteration = self.max_cycle

        # Get the moments - allow input to already be traced
        if self.trace:
            moments = as_trace(self.moments[: iteration + 1])
        else:
            moments = self.moments[: iteration + 1]

        # Initialise scaled grids
        a, b = self.scale
        scaled_grid = (self.grid - b) / a
        grids = (np.ones_like(scaled_grid), scaled_grid)

        # Initialise the polynomial
        coefficients = self.get_expansion_coefficients(iteration + 1)
        moments = np.einsum("n,n...->n...", coefficients, moments[: iteration + 1])
        polynomial = np.array([moments[0]] * self.grid.size)

        def _get_spectral_function(polynomial):
            f = polynomial / np.pi
            f /= np.sqrt(1 - scaled_grid**2)
            # FIXME should this be here?
            # f /= np.pi
            f /= np.sqrt(a**2 - (self.grid - b**2))
            return f

        f = _get_spectral_function(as_trace(polynomial))
        integral = scipy.integrate.simpson(f, self.grid)
        self.log.info("%4d %16.8g", 0, integral)

        for niter in range(1, iteration + 1):
            polynomial += np.multiply.outer(grids[-1], moments[niter]) * 2
            grids = (grids[-1], 2 * scaled_grid * grids[-1] - grids[-2])

            if niter in (1, 2, 3, 4, 5, 10, iteration) or niter % 100 == 0:
                f = _get_spectral_function(as_trace(polynomial))
                integral = scipy.integrate.simpson(f, self.grid)
                self.log.info("%4d %16.8g", niter, integral)

        f = _get_spectral_function(polynomial)

        self.log.info("-" * 21)

        return f
//  [python]
def intensity(ab, bb, tau, ds, int_c):
    """
        Name : intensity()

        Function : Calculates the intensity of emission given the blackbody emission from each grid cell and the optical depth at each cell
                   Note : Not sure whether to take the last 2d grid of cells (i.e. - Iv[:,:,-1])
                          or sum up each column given the bb and tau (i.e. - np.sum(Iv, axis=2).
    """
    I = intg.simps((bb * np.exp(-tau)) * ab, x=ds, axis=1) * int_c
    return I
//  [python]
def intensity(ab, bb, tau, ds, int_c):
    """
        Name : intensity()

        Function : Calculates the intensity of emission given the blackbody emission from each grid cell and the optical depth at each cell
                   Note : Not sure whether to take the last 2d grid of cells (i.e. - Iv[:,:,-1])
                          or sum up each column given the bb and tau (i.e. - np.sum(Iv, axis=2).
    """
    I = intg.simpson((bb * np.exp(-tau)) * ab, x=ds, axis=1) * int_c
    return I
//  [python]
def flux_density(I, ds, d, int_c):
    """
        Name : flux_density()

        Function : Calculates the flux density given a certain intensity and distance (pc)
    """
    d *= 3.085678e18  # change d from pc to cm
    # flux here given in Jy
    Sv = 1e23 * (int_c ** 2.0) * (intg.simps(intg.simps(I, x=ds), x=ds)) / d ** 2.0
    return Sv
//  [python]
def flux_density(I, ds, d, int_c):
    """
        Name : flux_density()

        Function : Calculates the flux density given a certain intensity and distance (pc)
    """
    d *= 3.085678e18  # change d from pc to cm
    # flux here given in Jy
    Sv = 1e23 * (int_c ** 2.0) * (scipy.integrate.simpson(scipy.integrate.simpson(I, x=ds), x=ds)) / d ** 2.0
    return Sv
//  [python]
def an(data,n):
    b = [] 
    x = []    
    for i in range(0,(len(data))):
        b.append(np.cos(np.pi * n *i / L))
        x.append(i)
    integrand = []

    for i in range(0,len(data)):
        c = data[i] * b[i]
        integrand.append(c)

    integration = scipy.integrate.simps(integrand,x, dx  = 2*L/resolution) #spacing in x
    an = integration / len(integrand)
    #print ("an", an)
    return (an)
//  [python]
def an(data,n):
    b = [] 
    x = []    
    for i in range(0,(len(data))):
        b.append(np.cos(np.pi * n *i / L))
        x.append(i)
    integrand = []

    for i in range(0,len(data)):
        c = data[i] * b[i]
        integrand.append(c)

    integration = scipy.integrate.simpson(integrand,x, dx  = 2*L/resolution) #spacing in x
    an = integration / len(integrand)
    #print ("an", an)
    return (an)
//  [python]
def LCA_FT_error2(a, b, a_unc, b_unc, order, resolution):
        a, a_unc = np.array(a), np.array(a_unc)
        b, b_unc = np.array(b), np.array(b_unc)

        def L_error2(phase):
            nlist = np.arange(order + 1)
            dIphi = 2 * sum(b[nlist] * np.sin(2 * np.pi * nlist * phase))
            I = FT.sumatphase(phase, order, a, b)
            # if (dIphi/I)**2 == 0.0:
            # L=1e-16
            # else:
            L = (dIphi / I) ** 2
            print(L)
            # radicand=0
            # radicand+=sum((a_unc*np.cos(2*np.pi*phase*nlist))**2)
            # radicand+=(2/np.sqrt(L)-1)**2*sum((b_unc*np.sin(2*np.pi*phase*nlist))**2)
            # return L, 2*L/I*np.sqrt(radicand)
            return L, 2 / I * (2 * L ** 0.5 - L) * np.sqrt(sum((b_unc * np.sin(2 * np.pi * phase * nlist)) ** 2))
            # return L, 4/I*np.sqrt(L*sum((b_unc*np.sin(2*np.pi*phase*nlist))**2))

        import scipy
        Phi = np.linspace(0, 0.5, resolution)
        Llist = []
        Lerrlist = []
        for phase in Phi:
            L_ap = L_error2(phase)
            Llist.append(L_ap[0])
            Lerrlist.append(L_ap[1])
        int_L = scipy.integrate.simps(Llist, Phi)
        int_L_error = scipy.integrate.simps(Lerrlist, Phi)
        # print('L_err =',int_L_error,'L =',int_L)
        LCA = OConnell.LCA_FT(a, b, order, resolution)
        LCA_error = 0.5 * LCA * (int_L_error / int_L)
        return LCA, LCA_error
//  [python]
def LCA_FT_error2(a, b, a_unc, b_unc, order, resolution):
        a, a_unc = np.array(a), np.array(a_unc)
        b, b_unc = np.array(b), np.array(b_unc)

        def L_error2(phase):
            nlist = np.arange(order + 1)
            dIphi = 2 * sum(b[nlist] * np.sin(2 * np.pi * nlist * phase))
            I = FT.sumatphase(phase, order, a, b)
            # if (dIphi/I)**2 == 0.0:
            # L=1e-16
            # else:
            L = (dIphi / I) ** 2
            print(L)
            # radicand=0
            # radicand+=sum((a_unc*np.cos(2*np.pi*phase*nlist))**2)
            # radicand+=(2/np.sqrt(L)-1)**2*sum((b_unc*np.sin(2*np.pi*phase*nlist))**2)
            # return L, 2*L/I*np.sqrt(radicand)
            return L, 2 / I * (2 * L ** 0.5 - L) * np.sqrt(sum((b_unc * np.sin(2 * np.pi * phase * nlist)) ** 2))
            # return L, 4/I*np.sqrt(L*sum((b_unc*np.sin(2*np.pi*phase*nlist))**2))

        import scipy
        Phi = np.linspace(0, 0.5, resolution)
        Llist = []
        Lerrlist = []
        for phase in Phi:
            L_ap = L_error2(phase)
            Llist.append(L_ap[0])
            Lerrlist.append(L_ap[1])
        int_L = scipy.integrate.simpson(Llist, Phi)
        int_L_error = scipy.integrate.simpson(Lerrlist, Phi)
        # print('L_err =',int_L_error,'L =',int_L)
        LCA = OConnell.LCA_FT(a, b, order, resolution)
        LCA_error = 0.5 * LCA * (int_L_error / int_L)
        return LCA, LCA_error
//  [python]
def bn(data,n):
    b = []  
    x = []
    for i in range(0,(len(data))):
        b.append(np.sin(np.pi * n *i / L))
        x.append(i)
    integrand = []
    
    for i in range(0,len(data)):
        c = data[i] * b[i]
        integrand.append(c)
    
    integration = scipy.integrate.simps(integrand,x, dx  = 2*L/resolution)
    bn = integration / len(integrand)
    return (bn)
//  [python]
def bn(data,n):
    b = []  
    x = []
    for i in range(0,(len(data))):
        b.append(np.sin(np.pi * n *i / L))
        x.append(i)
    integrand = []
    
    for i in range(0,len(data)):
        c = data[i] * b[i]
        integrand.append(c)
    
    integration = scipy.integrate.simpson(integrand,x, dx  = 2*L/resolution)
    bn = integration / len(integrand)
    return (bn)
//  [python]
def S_flat(self) -> float:
        """
        Compute the projected area of the flattened surface.

        This is the conventional definition using the area traced out by the
        section chords projected onto the xy-plane.
        """
        s = np.linspace(-1, 1, 1000)
        c = self.c(s)
        lengths = (self._section_pitch(s)[..., 0] * c[:, np.newaxis]).T[0]
        return cast(float, scipy.integrate.simps(lengths, s) * self.b_flat / 2)
//  [python]
def S_flat(self) -> float:
        """
        Compute the projected area of the flattened surface.

        This is the conventional definition using the area traced out by the
        section chords projected onto the xy-plane.
        """
        s = np.linspace(-1, 1, 1000)
        c = self.c(s)
        lengths = (self._section_pitch(s)[..., 0] * c[:, np.newaxis]).T[0]
        return cast(float, scipy.integrate.simpson(lengths, s) * self.b_flat / 2)
//  [python]
def S(self) -> float:
        """
        Compute the projected area of the surface.

        This is the conventional definition using the area traced out by the
        section chords projected onto the xy-plane.
        """
        s = np.linspace(-1, 1, 1000)
        LEx, LEy = self.xyz(s, 0)[:, :2].T
        TEx, TEy = self.xyz(s, 1)[:, :2].T

        # Three areas: curved front, trapezoidal mid, and curved rear
        LE_area = scipy.integrate.simps(LEx - LEx.min(), LEy)
        mid_area = (LEy.ptp() + TEy.ptp()) / 2 * (LEx.min() - TEx.max())
        TE_area = -scipy.integrate.simps(TEx - TEx.max(), TEy)
        return cast(float, LE_area + mid_area + TE_area)
//  [python]
def S(self) -> float:
        """
        Compute the projected area of the surface.

        This is the conventional definition using the area traced out by the
        section chords projected onto the xy-plane.
        """
        s = np.linspace(-1, 1, 1000)
        LEx, LEy = self.xyz(s, 0)[:, :2].T
        TEx, TEy = self.xyz(s, 1)[:, :2].T

        # Three areas: curved front, trapezoidal mid, and curved rear
        LE_area = scipy.integrate.simpson(LEx - LEx.min(), LEy)
        mid_area = (LEy.ptp() + TEy.ptp()) / 2 * (LEx.min() - TEx.max())
        TE_area = -scipy.integrate.simpson(TEx - TEx.max(), TEy)
        return cast(float, LE_area + mid_area + TE_area)
//  [python]
def _integrated_inverce_censoring_weighed_metric(func):
    def metric(time_grid, durations, events, surv, censor_surv, index_surv, index_censor,
               max_weight=np.inf, steps_surv='post', steps_censor='post'):
        scores = func(time_grid, durations, events, surv, censor_surv, index_surv, index_censor,
                      max_weight, True, steps_surv, steps_censor)
        integral = scipy.integrate.simps(scores, time_grid)
        return integral / (time_grid[-1] - time_grid[0])
    return metric
//  [python]
def _integrated_inverce_censoring_weighed_metric(func):
    def metric(time_grid, durations, events, surv, censor_surv, index_surv, index_censor,
               max_weight=np.inf, steps_surv='post', steps_censor='post'):
        scores = func(time_grid, durations, events, surv, censor_surv, index_surv, index_censor,
                      max_weight, True, steps_surv, steps_censor)
        integral = scipy.integrate.simpson(scores, time_grid)
        return integral / (time_grid[-1] - time_grid[0])
    return metric
//  [python]
def an(input_function_values,n,x):
    """Finds an for a particular n for the function"""
    cos_npix = []# List of cosine for different x values for one particular n
    for i in range(0, len(input_function_values)):
        cos_npix.append(np.cos(n*np.pi*x[i]/L))#Works out cos_npix for all x values in range
    integrand = []   
    for i in range(0,len(input_function_values)):
        integrand.append(input_function_values[i] * cos_npix[i])#Multiplies
        #each value of the input function at all x by the corresponding cos_npix
    a_n = scipy.integrate.simps(integrand, x, dx = 2*L / resolution)/L
    """Uses simpsons rule to integrate and get the correct value"""
    return a_n
//  [python]
def an(input_function_values,n,x):
    """Finds an for a particular n for the function"""
    cos_npix = []# List of cosine for different x values for one particular n
    for i in range(0, len(input_function_values)):
        cos_npix.append(np.cos(n*np.pi*x[i]/L))#Works out cos_npix for all x values in range
    integrand = []   
    for i in range(0,len(input_function_values)):
        integrand.append(input_function_values[i] * cos_npix[i])#Multiplies
        #each value of the input function at all x by the corresponding cos_npix
    a_n = scipy.integrate.simpson(integrand, x, dx = 2*L / resolution)/L
    """Uses simpsons rule to integrate and get the correct value"""
    return a_n
//  [python]
def fisher_distance(zmin, zmax, fsky, nz, bz, kmin=1e-3, kmax=1., 
                    fname_pk="../cache_pk.dat"):
    """
    Construct raw Fisher matrix from BAO observable, constraining distances 
    etc. only.
    """
    kgrid = np.logspace(np.log10(kmin), np.log10(kmax), NSAMP_K)
    ugrid = np.linspace(-1., 1., NSAMP_U)
    K, U = np.meshgrid(kgrid, ugrid)
    U2 = U*U
    
    # Precompute cosmo fns.
    H, r, D, f = baofisher.background_evolution_splines(cosmo, zmax=10.)
    zc = 0.5 * (zmin + zmax)
    
    # Calculate Vsurvey
    _z = np.linspace(zmin, zmax, 500)
    Vsur = 4.*np.pi*fsky * C * scipy.integrate.simps(r(_z)**2. / H(_z), _z)
    print("\tSurvey volume: %3.2f Gpc^3" % (Vsur/1e9))
    
    # Non-linear smoothing parameters (based on conversion to Planck cosmology 
    # of values on p4 of Seo & Eisenstein 2007)
    sig_par2  = (13. * D(zc) * (1. + f(zc)))**2. # Mpc^2
    sig_perp2 = (13. * D(zc))**2. # Mpc^2
    
    # Load power spectrum and decompose into BAO + smooth parts
    print("\tLoading P(k) and extracting BAO part...")
    k_in, pk_in = np.genfromtxt(fname_pk).T
    ipk, ifk = baofisher.spline_pk_nobao(k_in, pk_in)
    idfbao_dk = baofisher.fbao_derivative(ifk, kgrid)
    print("\t  Done.")
    
    # Fiducial power spectrum
    pk_smooth = D(zc)**2. * ipk(K.flatten()).reshape(K.shape)
    fbao = ifk(K.flatten()).reshape(K.shape)
    bao_smoothing = np.exp(-0.5*K**2.*(sig_perp2*(1.-U2) + sig_par2*U2))
    Ptot = (bz + f(zc) * U2)**2. * pk_smooth * (1. + fbao * bao_smoothing)
    
    # Mode weighting (effective volume factor)
    sqrtVeff = nz*Ptot / (nz*Ptot + 1.)
    
    # Fisher derivs, dlog(P_gal) / d(param)
    #fbao_fac = K * idfbao_dk(K.flatten()).reshape(K.shape) \
    #         * bao_smoothing / (1. + fbao*bao_smoothing)
    fbao_fac = K * idfbao_dk(K.flatten()).reshape(K.shape) / (1. + fbao)
    deriv_aperp = fbao_fac * (1. - U2)
    deriv_apar = fbao_fac * U2
    deriv_alpha = fbao_fac * 1.
    deriv_f = 2. * U2 / (bz + f(zc) * U2)
    deriv_b = 2. / (bz + f(zc) * U2)
    
    # Prepare list of derivs, multiply by mode weighting
    lbls = ['aperp', 'apar', 'alpha_s', 'f', 'b']
    derivs = [deriv_aperp, deriv_apar, deriv_alpha, deriv_f, deriv_b]
    derivs = [deriv * sqrtVeff for deriv in derivs]
    
    # Integrate Fisher matrix
    print("\tIntegrating Fisher matrix...")
    F = baofisher.integrate_fisher_elements(derivs, kgrid, ugrid)
    F *= Vsur / (2.*np.pi)**2. # FIXME: Factor or 2 in denom. or not?
    print("\t  Done.")
    
    return F, lbls
//  [python]
def fisher_distance(zmin, zmax, fsky, nz, bz, kmin=1e-3, kmax=1., 
                    fname_pk="../cache_pk.dat"):
    """
    Construct raw Fisher matrix from BAO observable, constraining distances 
    etc. only.
    """
    kgrid = np.logspace(np.log10(kmin), np.log10(kmax), NSAMP_K)
    ugrid = np.linspace(-1., 1., NSAMP_U)
    K, U = np.meshgrid(kgrid, ugrid)
    U2 = U*U
    
    # Precompute cosmo fns.
    H, r, D, f = baofisher.background_evolution_splines(cosmo, zmax=10.)
    zc = 0.5 * (zmin + zmax)
    
    # Calculate Vsurvey
    _z = np.linspace(zmin, zmax, 500)
    Vsur = 4.*np.pi*fsky * C * scipy.integrate.simpson(r(_z)**2. / H(_z), _z)
    print("\tSurvey volume: %3.2f Gpc^3" % (Vsur/1e9))
    
    # Non-linear smoothing parameters (based on conversion to Planck cosmology 
    # of values on p4 of Seo & Eisenstein 2007)
    sig_par2  = (13. * D(zc) * (1. + f(zc)))**2. # Mpc^2
    sig_perp2 = (13. * D(zc))**2. # Mpc^2
    
    # Load power spectrum and decompose into BAO + smooth parts
    print("\tLoading P(k) and extracting BAO part...")
    k_in, pk_in = np.genfromtxt(fname_pk).T
    ipk, ifk = baofisher.spline_pk_nobao(k_in, pk_in)
    idfbao_dk = baofisher.fbao_derivative(ifk, kgrid)
    print("\t  Done.")
    
    # Fiducial power spectrum
    pk_smooth = D(zc)**2. * ipk(K.flatten()).reshape(K.shape)
    fbao = ifk(K.flatten()).reshape(K.shape)
    bao_smoothing = np.exp(-0.5*K**2.*(sig_perp2*(1.-U2) + sig_par2*U2))
    Ptot = (bz + f(zc) * U2)**2. * pk_smooth * (1. + fbao * bao_smoothing)
    
    # Mode weighting (effective volume factor)
    sqrtVeff = nz*Ptot / (nz*Ptot + 1.)
    
    # Fisher derivs, dlog(P_gal) / d(param)
    #fbao_fac = K * idfbao_dk(K.flatten()).reshape(K.shape) \
    #         * bao_smoothing / (1. + fbao*bao_smoothing)
    fbao_fac = K * idfbao_dk(K.flatten()).reshape(K.shape) / (1. + fbao)
    deriv_aperp = fbao_fac * (1. - U2)
    deriv_apar = fbao_fac * U2
    deriv_alpha = fbao_fac * 1.
    deriv_f = 2. * U2 / (bz + f(zc) * U2)
    deriv_b = 2. / (bz + f(zc) * U2)
    
    # Prepare list of derivs, multiply by mode weighting
    lbls = ['aperp', 'apar', 'alpha_s', 'f', 'b']
    derivs = [deriv_aperp, deriv_apar, deriv_alpha, deriv_f, deriv_b]
    derivs = [deriv * sqrtVeff for deriv in derivs]
    
    # Integrate Fisher matrix
    print("\tIntegrating Fisher matrix...")
    F = baofisher.integrate_fisher_elements(derivs, kgrid, ugrid)
    F *= Vsur / (2.*np.pi)**2. # FIXME: Factor or 2 in denom. or not?
    print("\t  Done.")
    
    return F, lbls
//  [python]
def Error(x,y,N):
    a_n, b_n = Fourier_coefficients(y,N,x)
    y_values =  Trig_summation_x(a_n, b_n, x,N)
    diff_squared = []
    for i in range(0, len(y)):
        diff_squared.append((y[i] - y_values[i])**2)
        
    A = scipy.integrate.simps(diff_squared, x, dx = 2*L / resolution)
    print ("Error is ", A)
//  [python]
def Error(x,y,N):
    a_n, b_n = Fourier_coefficients(y,N,x)
    y_values =  Trig_summation_x(a_n, b_n, x,N)
    diff_squared = []
    for i in range(0, len(y)):
        diff_squared.append((y[i] - y_values[i])**2)
        
    A = scipy.integrate.simpson(diff_squared, x, dx = 2*L / resolution)
    print ("Error is ", A)
//  [python]
def integrate(big_r, alpha):
    l = np.linspace(-50 * big_r, 50 * big_r, 10000)
    y = (l**2 + big_r**2)**(alpha / 2.)
    return scipy.integrate.simps(y, l)
//  [python]
def integrate(big_r, alpha):
    l = np.linspace(-50 * big_r, 50 * big_r, 10000)
    y = (l**2 + big_r**2)**(alpha / 2.)
    return scipy.integrate.simpson(y, l)
//  [python]
def bn(input_function_values,n,x):
    """Finds bn for a particular n for the function"""
    sin_npix = []# List of sine for different x values for one particular n
    for i in range(0, len(input_function_values)):
        sin_npix.append(np.sin(n*np.pi*x[i]/L))#Works out sin_npix for all x values in range
    integrand = []   
    for i in range(0,len(input_function_values)):
        integrand.append(input_function_values[i] * sin_npix[i])#Multiplies
        #each value of the input function at all x by the corresponding sin_npix
    """Again using simpsons rule"""
    b_n = scipy.integrate.simps(integrand, x, dx = 2*L / resolution)/L
    return b_n
//  [python]
def bn(input_function_values,n,x):
    """Finds bn for a particular n for the function"""
    sin_npix = []# List of sine for different x values for one particular n
    for i in range(0, len(input_function_values)):
        sin_npix.append(np.sin(n*np.pi*x[i]/L))#Works out sin_npix for all x values in range
    integrand = []   
    for i in range(0,len(input_function_values)):
        integrand.append(input_function_values[i] * sin_npix[i])#Multiplies
        #each value of the input function at all x by the corresponding sin_npix
    """Again using simpsons rule"""
    b_n = scipy.integrate.simpson(integrand, x, dx = 2*L / resolution)/L
    return b_n
//  [python]
def calc_N(data_controller,ene,dos, mu, temp, dosweight=2.):

  arry,attr = data_controller.data_dicts()
  core_electrons = attr['core_electrons']

  if temp == 0.: 
    occ = np.where(ene < mu, 1., 0.)
    occ[ene==mu] = .5
  else:
    occ = FD(ene, mu, temp)
  dos_occ = dos*occ
  return -dosweight * scipy.integrate.simps(dos_occ,ene)-core_electrons
//  [python]
def calc_N(data_controller,ene,dos, mu, temp, dosweight=2.):

  arry,attr = data_controller.data_dicts()
  core_electrons = attr['core_electrons']

  if temp == 0.: 
    occ = np.where(ene < mu, 1., 0.)
    occ[ene==mu] = .5
  else:
    occ = FD(ene, mu, temp)
  dos_occ = dos*occ
  return -dosweight * scipy.integrate.simpson(dos_occ,ene)-core_electrons
//  [python]
def test_pdf_unity_area(self):
        from scipy.integrate import simps
        # PDF should integrate to one
        assert_almost_equal(simps(stats.genexpon.pdf(numpy.arange(0,10,0.01),
                                                     0.5, 0.5, 2.0),
                                  dx=0.01), 1, 1)
//  [python]
def test_pdf_unity_area(self):
        from scipy.integrate import simpson
        # PDF should integrate to one
        assert_almost_equal(simpson(stats.genexpon.pdf(numpy.arange(0,10,0.01),
                                                     0.5, 0.5, 2.0),
                                  dx=0.01), 1, 1)
//  [python]
def L02Q1(line, cell):

    # correct answer
    def correct():

        points = 0

        for i in range(2, 10000):

            x = np.linspace(10, 20, i)
            y = x**3

            # analytical
            ya = x[-1]**4 / 4 - x[0]**4 / 4

            # np.trapz
            yt = np.trapz(y, x)

            # scipy.integrate.simps
            ys = simps(y, x)

            if(round(ya, 3)==round(yt, 3)==round(ys, 3)):
                points = i
                break

        return points

    globals = dict()
    exec(cell, globals)

    # Now we can check if something was done
    p = globals.get('points', None)

    if p is None:
        print('Looks like you have changed the "points" variable. Use the original template variables.')
        return

    elif within_num(p, correct()):
        print('Correct')
    else:
        print('Incorrect')
//  [python]
def L02Q1(line, cell):

    # correct answer
    def correct():

        points = 0

        for i in range(2, 10000):

            x = np.linspace(10, 20, i)
            y = x**3

            # analytical
            ya = x[-1]**4 / 4 - x[0]**4 / 4

            # np.trapz
            yt = np.trapz(y, x)

            # scipy.integrate.simps
            ys = simpson(y, x)

            if(round(ya, 3)==round(yt, 3)==round(ys, 3)):
                points = i
                break

        return points

    globals = dict()
    exec(cell, globals)

    # Now we can check if something was done
    p = globals.get('points', None)

    if p is None:
        print('Looks like you have changed the "points" variable. Use the original template variables.')
        return

    elif within_num(p, correct()):
        print('Correct')
    else:
        print('Incorrect')
//  [python]
def _integrate(function, e1, e2):

        integrals = []

        for ee1, ee2 in zip(e1, e2):

            grid = np.linspace(ee1, ee2, 30)

            integrals.append(scipy.integrate.simps(function(grid), grid))

        # integrals = map(lambda x:scipy.integrate.quad(function, x[0], x[1], epsrel=1e-2)[0], zip(e1, e2))

        return np.array(integrals)
//  [python]
def _integrate(function, e1, e2):

        integrals = []

        for ee1, ee2 in zip(e1, e2):

            grid = np.linspace(ee1, ee2, 30)

            integrals.append(scipy.integrate.simpson(function(grid), grid))

        # integrals = map(lambda x:scipy.integrate.quad(function, x[0], x[1], epsrel=1e-2)[0], zip(e1, e2))

        return np.array(integrals)
//  [python]
fftfull=[float(i[1])/facatomic for i in whole]
fftfull=fftfull[:len(freq)]

# clean small numbers
fft=[i if i>max(fftfull)/10000. else 0.0 for i in fftfull]

#fft=fftfull

dx=freq[1]

# displacement
#for l in lamb:
#   gf=array([g(l, i, beta) for i in freq])
#   filetemp=open('f_displ_'+str(l), 'w')
#   trash=[filetemp.write('%f %f\n' %(i,j)) for i,j in zip(freq, gf)]
#   filetemp.close()
   # integrate
#   number2=integrate(freq[1], fft[1:], gf)
#   numarray=[i*j for i,j in zip(fft,gf)]
#   number=scipy.integrate.simps(numarray, x=freq)
#   print l, number

#print ' ' 

# cvv
for l in lamb:
   fplus=array([f(l, i, beta) for i in freq])
#   filetemp=open('f_vv_'+str(l), 'w')
#   trash=[filetemp.write('%f %f\n' %(i,j)) for i,j in zip(freq, fplus)]
#   filetemp.close()
   # integrate
   numarray=[i*j for i,j in zip(fft,fplus)]
   number=scipy.integrate.simps(numarray, x=freq)
   number=integrate(freq[1], fft[1:], fplus)
   print(l/beta, number)
//  [python]
fftfull=[float(i[1])/facatomic for i in whole]
fftfull=fftfull[:len(freq)]

# clean small numbers
fft=[i if i>max(fftfull)/10000. else 0.0 for i in fftfull]

#fft=fftfull

dx=freq[1]

# displacement
#for l in lamb:
#   gf=array([g(l, i, beta) for i in freq])
#   filetemp=open('f_displ_'+str(l), 'w')
#   trash=[filetemp.write('%f %f\n' %(i,j)) for i,j in zip(freq, gf)]
#   filetemp.close()
   # integrate
#   number2=integrate(freq[1], fft[1:], gf)
#   numarray=[i*j for i,j in zip(fft,gf)]
#   number=scipy.integrate.simpson(numarray, x=freq)
#   print l, number

#print ' ' 

# cvv
for l in lamb:
   fplus=array([f(l, i, beta) for i in freq])
#   filetemp=open('f_vv_'+str(l), 'w')
#   trash=[filetemp.write('%f %f\n' %(i,j)) for i,j in zip(freq, fplus)]
#   filetemp.close()
   # integrate
   numarray=[i*j for i,j in zip(fft,fplus)]
   number=scipy.integrate.simpson(numarray, x=freq)
   number=integrate(freq[1], fft[1:], fplus)
   print(l/beta, number)
//  [python]
def _get_cumulative_flux(self):
        """
        Store a look-up table for the cumulative flux as a function of
        wavelength.  This seems to be an efficient way of getting
        things like velocity percentiles.
        """
        cflux = [0]
        for w in self.wv[1::]:
            m = self.wv <= w
            fint = simps(self.f[m], self.wv[m])
            cflux = sp.r_[cflux,fint]
        self._cumulative_flux = interp1d(cflux,self.wv)
//  [python]
def _get_cumulative_flux(self):
        """
        Store a look-up table for the cumulative flux as a function of
        wavelength.  This seems to be an efficient way of getting
        things like velocity percentiles.
        """
        cflux = [0]
        for w in self.wv[1::]:
            m = self.wv <= w
            fint = simpson(self.f[m], self.wv[m])
            cflux = sp.r_[cflux,fint]
        self._cumulative_flux = interp1d(cflux,self.wv)
//  [python]
def lifetime_accum(lifetime, X_s, X_t):
    """
    Compute the lifetime by integrating the correlation function
    and accumulate the result into the given lifetime object.

    Parameters
    ----------
    X_s : array-like
        Array with the correlation function.
        Works also with other decaying scores that are defined
        in the range [0,1]=[min_skill,max_skill].
    X_t : array-like
        Array with the forecast lead times in the desired unit, e.g. [min, hour].

    """
    if lifetime["rule"] == 'trapz':
        lf = np.trapz(X_s, x=X_t)
    elif lifetime["rule"] == "simpson":
        lf = simps(X_s, x=X_t)
    elif lifetime["rule"] == '1/e':
        euler_number = 1.0/exp(1.0)
        X_s_ = np.array(X_s)

        is_euler_reached = np.sum(X_s_ <= euler_number) > 0
        if is_euler_reached:
            idx_b = np.argmax(X_s_ <= euler_number)
            if idx_b > 0:
                idx_a = idx_b - 1
                fraction_score = (euler_number - X_s[idx_b])*(X_t[idx_a] - X_t[idx_b])\
                    /(X_s[idx_a] - X_s[idx_b])
                lf = X_t[idx_b] + fraction_score
            else:
                # if all values are below the 1/e value, return min lead time
                lf = np.min(X_t)
        else:
            # if all values are above the 1/e value, return max lead time
            lf = np.max(X_t)

    lifetime["lifetime_sum"] += lf
    lifetime["n"] += 1
//  [python]
def lifetime_accum(lifetime, X_s, X_t):
    """
    Compute the lifetime by integrating the correlation function
    and accumulate the result into the given lifetime object.

    Parameters
    ----------
    X_s : array-like
        Array with the correlation function.
        Works also with other decaying scores that are defined
        in the range [0,1]=[min_skill,max_skill].
    X_t : array-like
        Array with the forecast lead times in the desired unit, e.g. [min, hour].

    """
    if lifetime["rule"] == 'trapz':
        lf = np.trapz(X_s, x=X_t)
    elif lifetime["rule"] == "simpson":
        lf = sp.integrate.simpson(X_s, x=X_t)
    elif lifetime["rule"] == '1/e':
        euler_number = 1.0/exp(1.0)
        X_s_ = np.array(X_s)

        is_euler_reached = np.sum(X_s_ <= euler_number) > 0
        if is_euler_reached:
            idx_b = np.argmax(X_s_ <= euler_number)
            if idx_b > 0:
                idx_a = idx_b - 1
                fraction_score = (euler_number - X_s[idx_b])*(X_t[idx_a] - X_t[idx_b])\
                    /(X_s[idx_a] - X_s[idx_b])
                lf = X_t[idx_b] + fraction_score
            else:
                # if all values are below the 1/e value, return min lead time
                lf = np.min(X_t)
        else:
            # if all values are above the 1/e value, return max lead time
            lf = np.max(X_t)

    lifetime["lifetime_sum"] += lf
    lifetime["n"] += 1
//  [python]
def _cumul_simpson(theta, cl, nmax, thetamax, cl_mask=None):
    '''
    Notes
    -----
    This calculates the two integrals in Eq. 90
    '''

    npoints = 2.0**(nmax-1)
    step = thetamax / npoints

    beta = np.linspace(0.0, thetamax, num=npoints+1)

    c_plus = _cplus(np.cos(beta), cl, cl_mask=cl_mask)
    ftemp1 = np.sin(beta)/np.cos(beta/2.0)**4 * c_plus
    ftemp2 = np.tan(beta/2.0)**3 * c_plus

    nell = len(cl[0])

    sum1 = np.zeros(nell)
    sum2 = np.zeros(nell)
    lastn = 2*np.array(np.round(theta/(2.0*step)), dtype=int)

    for j in range(nell):
        if lastn[j] != 0:
            sum1[j] = scipy.integrate.simps(ftemp1[:lastn[j]+1], dx=step)
            sum2[j] = scipy.integrate.simps(ftemp2[:lastn[j]+1], dx=step)

    #Since beta[lastn[j]] is not exactly theta[j], we apply the basic Simpson's rule on
    #the small interval between those two values
    step2 = (theta - step*lastn) / 2.0
    theta0 = theta-step2
    theta1 = theta

    c_plus0 = _cplus(np.cos(theta0), cl, cl_mask=cl_mask)
    c_plus1 = _cplus(np.cos(theta1), cl, cl_mask=cl_mask)

    int1_0 = np.sin(theta0)/np.cos(theta0/2.0)**4 * c_plus0
    int1_1 = np.sin(theta1)/np.cos(theta1/2.0)**4 * c_plus1
    int2_0 = np.tan(theta0/2.0)**3 * c_plus0
    int2_1 = np.tan(theta1/2.0)**3 * c_plus1

    endpoint = step2*(ftemp1[lastn] + 4.0 * int1_0 + int1_1) / 3.0
    sum1 += endpoint

    endpoint = step2*(ftemp2[lastn] + 4.0 * int2_0 + int2_1) / 3.0
    sum2 += endpoint

    return sum1, sum2