jiahuimbzuai/CoQuIR huggingface dataset:
//  [python]
def cumulative_integral(
        self, integration_type: INTEGRATION_TYPE_OPTS = "trapz"
    ) -> NumpyRealNumberArray:
        """Cumulative integration starting at t=0 and ending at each frame_end.

        If start_time > 0, the triangular area between (t=0, 0) and
        (t=start_time, dataobj value at 0th frame) will be added to each
        cumulative integral.

        Args:
            integration_type: rect (rectangular) or trapz (trapezoidal).

        Returns:
            cumulative integral, with same shape as dataobj

        Raises:
            ValueError: invalid integration type
        """
        if self.has_gaps():
            warnings.warn(
                (
                    "TemporalObject has time gaps between frames. "
                    "Make sure that gaps do not mask important temporal dynamics."
                ),
                RuntimeWarning,
                stacklevel=2,
            )
            if integration_type == "rect":
                warnings.warn(
                    (
                        "Rectangular integration is not available for "
                        "TemporalObjects with time gaps between frames. "
                        "Changing to trapezoidal integration."
                    ),
                    RuntimeWarning,
                    stacklevel=2,
                )
                integration_type = "trapz"

        # if start_time > 0, then we assume activity linearly increased from 0
        # to values attained in first frame
        initial = self.start_time * self.dataobj[..., 0] / 2
        res: NumpyRealNumberArray

        if integration_type == "rect":
            res = (
                np.cumsum(self.dataobj * self.frame_duration, axis=-1)
                + initial[..., np.newaxis]
            )
        elif integration_type == "trapz":
            res = (
                cumulative_trapezoid(self.dataobj, self.frame_mid, axis=-1, initial=0)
                + initial[..., np.newaxis]
            )
        else:
            raise ValueError("integration_type" + integration_type + "is invalid")
        return res
//  [python]
def test_linear_momentum_radiated(self):
        # check with what it should be
        from mayawaves.coalescence import Coalescence
        coalescence = Coalescence(os.path.join(self.CURR_DIR,
                                               'resources/radiative_quantities_resources/D11_q2_a1_0.0_0.0_0.4_a2_0.0_0.0_0.4_m282.35.h5'))

        radiation_bundle = coalescence.radiationbundle
        radiation_sphere = radiation_bundle.radiation_spheres[75]
        radiation_mode = radiation_sphere.modes[(2, 2)]
        generated_linear_momentum_radiated = radiation_mode.linear_momentum_radiated

        dP_dt_radiated = radiation_mode.dP_dt_radiated
        time = radiation_mode.time
        expected_linear_momentum_radiated = scipy.integrate.cumtrapz(dP_dt_radiated, time, initial=0,
                                                                                 axis=0)

        self.assertTrue(np.all(expected_linear_momentum_radiated == generated_linear_momentum_radiated))
//  [python]
def test_linear_momentum_radiated(self):
        # check with what it should be
        from mayawaves.coalescence import Coalescence
        coalescence = Coalescence(os.path.join(self.CURR_DIR,
                                               'resources/radiative_quantities_resources/D11_q2_a1_0.0_0.0_0.4_a2_0.0_0.0_0.4_m282.35.h5'))

        radiation_bundle = coalescence.radiationbundle
        radiation_sphere = radiation_bundle.radiation_spheres[75]
        radiation_mode = radiation_sphere.modes[(2, 2)]
        generated_linear_momentum_radiated = radiation_mode.linear_momentum_radiated

        dP_dt_radiated = radiation_mode.dP_dt_radiated
        time = radiation_mode.time
        expected_linear_momentum_radiated = scipy.integrate.cumulative_trapezoid(dP_dt_radiated, time, initial=0,
                                                                                 axis=0)

        self.assertTrue(np.all(expected_linear_momentum_radiated == generated_linear_momentum_radiated))
//  [python]
def _initialize_attributes(self):
        from scipy.integrate import trapz
        if trapz(self._yy, self.xx) != 1:
            logger.debug('Supplied PDF for {} is not normalised, normalising.'.format(self.name))
        self._yy /= trapz(self._yy, self.xx)
        self.YY = np.cumsum(self._yy * np.diff(self.xx))
        self.YY = np.insert(self.YY, 0, 0)
        self.YY = self.YY / self.YY[-1]
        # Need last element of cumulative distribution to be exactly one.
        self.YY[-1] = 1
        self.probability_density = interp1d(x=self.xx, y=self._yy, bounds_error=False, fill_value=0)
        self.cumulative_distribution = interp1d(x=self.xx, y=self.YY, bounds_error=False, fill_value=(0, 1))
        self.inverse_cumulative_distribution = interp1d(x=self.YY, y=self.xx, bounds_error=True)
//  [python]
def _initialize_attributes(self):
        from scipy.integrate import cumulative_trapezoid
        if np.trapz(self._yy, self.xx) != 1:
            logger.debug('Supplied PDF for {} is not normalised, normalising.'.format(self.name))
        self._yy /= np.trapz(self._yy, self.xx)
        self.YY = cumulative_trapezoid(self._yy, self.xx, initial=0)
        # Need last element of cumulative distribution to be exactly one.
        self.YY[-1] = 1
        self.probability_density = interp1d(x=self.xx, y=self._yy, bounds_error=False, fill_value=0)
        self.cumulative_distribution = interp1d(x=self.xx, y=self.YY, bounds_error=False, fill_value=(0, 1))
        self.inverse_cumulative_distribution = interp1d(x=self.YY, y=self.xx, bounds_error=True)
//  [python]
def inverse_transform(self, X: FDataGrid, y: None = None) -> FDataGrid:
        r"""
        Compute the inverse SRSF transform.

        Given the srsf and the initial value the original function can be
        obtained as :footcite:`srivastava+klassen_2016_functionala`:

        .. math::
            f(t) = f(a) + \int_{a}^t q(t)|q(t)|dt

        where :math:`q(t)=SRSF(f(t))`.

        If it is applied this inverse transformation without fitting the
        estimator it is assumed that :math:`f(a)=0`.

        Args:
            X: SRSF to be transformed.
            y: Present for API conventions.

        Returns:
            Functions in the original space.

        Raises:
            ValueError: If functions are multidimensional.
        """
        check_fdata_dimensions(
            X,
            dim_domain=1,
            dim_codomain=1,
        )

        stored_initial_value = getattr(self, 'initial_value_', None)

        if self.initial_value is None and stored_initial_value is None:
            raise AttributeError(
                "When initial_value=None is expected a "
                "previous transformation of the data to "
                "store the initial values to apply in the "
                "inverse transformation. Also it is possible "
                "to fix these values setting the attribute"
                "initial value without a previous "
                "transformation.",
            )

        if self.output_points is None:
            output_points = X.grid_points[0]
        else:
            output_points = np.asarray(self.output_points)

        data_matrix = X(output_points)

        data_matrix *= np.abs(data_matrix)

        f_data_matrix = scipy.integrate.cumtrapz(
            data_matrix,
            x=output_points,
            axis=1,
            initial=0,
        )

        # If the transformer was fitted, sum the initial value
        if self.initial_value is None:
            f_data_matrix += self.initial_value_
        else:
            f_data_matrix += self.initial_value

        return X.copy(data_matrix=f_data_matrix, grid_points=output_points)
//  [python]
def inverse_transform(self, X: FDataGrid, y: None = None) -> FDataGrid:
        r"""
        Compute the inverse SRSF transform.

        Given the srsf and the initial value the original function can be
        obtained as :footcite:`srivastava+klassen_2016_functionala`:

        .. math::
            f(t) = f(a) + \int_{a}^t q(t)|q(t)|dt

        where :math:`q(t)=SRSF(f(t))`.

        If it is applied this inverse transformation without fitting the
        estimator it is assumed that :math:`f(a)=0`.

        Args:
            X: SRSF to be transformed.
            y: Present for API conventions.

        Returns:
            Functions in the original space.

        Raises:
            ValueError: If functions are multidimensional.
        """
        check_fdata_dimensions(
            X,
            dim_domain=1,
            dim_codomain=1,
        )

        stored_initial_value = getattr(self, 'initial_value_', None)

        if self.initial_value is None and stored_initial_value is None:
            raise AttributeError(
                "When initial_value=None is expected a "
                "previous transformation of the data to "
                "store the initial values to apply in the "
                "inverse transformation. Also it is possible "
                "to fix these values setting the attribute"
                "initial value without a previous "
                "transformation.",
            )

        if self.output_points is None:
            output_points = X.grid_points[0]
        else:
            output_points = np.asarray(self.output_points)

        data_matrix = X(output_points)

        data_matrix *= np.abs(data_matrix)

        f_data_matrix = scipy.integrate.cumulative_trapezoid(
            data_matrix,
            x=output_points,
            axis=1,
            initial=0,
        )

        # If the transformer was fitted, sum the initial value
        if self.initial_value is None:
            f_data_matrix += self.initial_value_
        else:
            f_data_matrix += self.initial_value

        return X.copy(data_matrix=f_data_matrix, grid_points=output_points)
//  [python]
def __call__(self, theta, hyper_deriv=None):
        """Evaluate the log-probability of the variables.
        
        Parameters
        ----------
        theta : array
            The parameters to find the log-probability of.
        """
        if hyper_deriv is not None:
            return 0.0
        theta = scipy.asarray(theta)
        if (scipy.sort(theta) != theta).all() or (theta < self.lb).any() or (theta > self.ub).any():
            return -scipy.inf
        else:
            return (
                scipy.log(scipy.misc.factorial(self.num_var)) -
                self.num_var * scipy.log(self.ub - self.lb)
            )
//  [python]
def __call__(self, theta, hyper_deriv=None):
        """Evaluate the log-probability of the variables.
        
        Parameters
        ----------
        theta : array
            The parameters to find the log-probability of.
        """
        if hyper_deriv is not None:
            return 0.0
        theta = scipy.asarray(theta)
        if (scipy.sort(theta) != theta).all() or (theta < self.lb).any() or (theta > self.ub).any():
            return -scipy.inf
        else:
            return (
                scipy.log(scipy.special.factorial(self.num_var)) -
                self.num_var * scipy.log(self.ub - self.lb)
            )
//  [python]
def calc_sigma2_nu(r, cmass, nu, g):
    """ Calculate the 3D Jeans integration:
    .. math::
    sigma2(r0) nu(r0) g(r_0) =  int_r0^\infty G M(r) nu(r) g(r) / r^2 dr

    where:
    - G is the gravitational constant
    - M(r) is the enclosed radius at radius r in Msun
    - nu(r) is the 3D light profile
    - g(r) is the anistropy integral

    Parameters
    ----------
    r: array of N float
        The 3D radius in kpc
    cmass: array of N float
        The cumulative mass in Msun
    nu: array of N float
        The 3D light profile
    g: array of N float
        The anistropy integral
    """
    G = const.G.to_value(u.kpc**3 / u.Msun / u.s**2)
    inte = cmass * G * nu * g / r**2

    # check if r is equally spaced
    dr = r[1] - r[0]
    if np.any(np.abs(np.diff(r) - dr) > 1e-6):
        return integrate.trapz(
            inte[::-1], x=r[::-1], axis=-1)[::-1] / g
    else:
        return integrate.trapz(
            inte[::-1], dx=dr, axis=-1)[::-1] / g
//  [python]
def calc_sigma2_nu(r, cmass, nu, g):
    """ Calculate the 3D Jeans integration:
    .. math::
    sigma2(r0) nu(r0) g(r_0) =  int_r0^\infty G M(r) nu(r) g(r) / r^2 dr

    where:
    - G is the gravitational constant
    - M(r) is the enclosed radius at radius r in Msun
    - nu(r) is the 3D light profile
    - g(r) is the anistropy integral

    Parameters
    ----------
    r: array of N float
        The 3D radius in kpc
    cmass: array of N float
        The cumulative mass in Msun
    nu: array of N float
        The 3D light profile
    g: array of N float
        The anistropy integral
    """
    G = const.G.to_value(u.kpc**3 / u.Msun / u.s**2)
    inte = cmass * G * nu * g / r**2

    # check if r is equally spaced
    dr = r[1] - r[0]
    if np.any(np.abs(np.diff(r) - dr) > 1e-6):
        return integrate.cumulative_trapezoid(
            inte[::-1], x=r[::-1], initial=0)[::-1] / g
    else:
        return integrate.cumulative_trapezoid(
            inte[::-1], dx=dr, initial=0)[::-1] / g
//  [python]
def K(dim=4, dfn=7, dfd=np.inf):
    r"""
    Determine the polynomial K in:

        Worsley, K.J. (1994). 'Local maxima and the expected Euler
        characteristic of excursion sets of \chi^2, F and t fields.' Advances in
        Applied Probability, 26:13-42.

    If dfd=inf, return the limiting polynomial.
    """
    def lbinom(n, j):
        return gammaln(n+1) - gammaln(j+1) - gammaln(n-j+1)

    m = dfd
    n = dfn
    D = dim
    k = np.arange(D)
    coef = 0
    for j in range(int(np.floor((D-1)/2.)+1)):
        if np.isfinite(m):
            t = (gammaln((m+n-D)/2.+j) - 
                 gammaln(j+1) -
                 gammaln((m+n-D)/2.))
            t += lbinom(m-1, k-j) - k * np.log(m)
        else:
            _t = np.power(2., -j) / (factorial(k-j) * factorial(j))
            t = np.log(_t)
            t[np.isinf(_t)] = -np.inf
        t += lbinom(n-1, D-1-j-k) 
        coef += (-1)**(D-1) * factorial(D-1) * np.exp(t) * np.power(-1.*n, k) 
    return np.poly1d(coef[::-1])
//  [python]
def K(dim=4, dfn=7, dfd=np.inf):
    r"""
    Determine the polynomial K in:

        Worsley, K.J. (1994). 'Local maxima and the expected Euler
        characteristic of excursion sets of \chi^2, F and t fields.' Advances in
        Applied Probability, 26:13-42.

    If dfd=inf, return the limiting polynomial.
    """
    def lbinom(n, j):
        return gammaln(n+1) - gammaln(j+1) - gammaln(n-j+1)

    m = dfd
    n = dfn
    D = dim
    k = np.arange(D)
    coef = 0
    for j in range(int(np.floor((D-1)/2.)+1)):
        if np.isfinite(m):
            t = (gammaln((m+n-D)/2.+j) - 
                 gammaln(j+1) -
                 gammaln((m+n-D)/2.))
            t += lbinom(m-1, k-j) - k * np.log(m)
        else:
            _t = np.power(2., -j) / (scipy.special.factorial(k-j) * scipy.special.factorial(j))
            t = np.log(_t)
            t[np.isinf(_t)] = -np.inf
        t += lbinom(n-1, D-1-j-k) 
        coef += (-1)**(D-1) * scipy.special.factorial(D-1) * np.exp(t) * np.power(-1.*n, k) 
    return np.poly1d(coef[::-1])
//  [python]
def compute_A2_nonlocal(Q, microstructure):

    margin = 4  # this number must be higher for small grains, because
    # the FT of gamma is wider, so is the integrand of ReF. It means that using the long range version
    # is not recommanded for small grains
    # this value should be adaptive

    maxq = margin * Q

    k = 12  # number of samples. This should be adaptive depending on the size/wavelength
    n = 2**k
    nQ = n // margin
    q = np.linspace(0, maxq, n + 1)

    assert q[nQ] == Q

    # start with the imaginary part - Eq (70)
    y = 2 * q * microstructure.ft_autocorrelation_function(2 * q)

    # integrate from 0 to 2Q (for Q in 0 to qmax)
    # take the real part to avoid warnings... but this remains to be explored
    primitive = scipy.integrate.trapz(y.real, 2 * q.real, initial=0)

    ImF = - 1 / (2 * (2 * np.pi)**1.5) * q * primitive

    # continue with the real part. Eq (71) is much more difficult to compute than the imaginary part
    # because of the principal value, but Torquato 2021, suppmat gives a hint with Eq S111.
    # here: M = maxq

    with np.errstate(invalid='ignore'):
        y1 = ImF / ((Q + q) * q)
        y1[0] = 0  # remove the singularity in 0

        y2 = (ImF - ImF[nQ]) / (Q**2 - q**2)

        y2[nQ] = (y2[nQ - 1] + y2[nQ + 1]) / 2   # remove the singularity in Q

    y = y1 + y2

    asymptotic_integral = (ImF[nQ] - Q / maxq * ImF[-1]) * np.log(np.abs((maxq + Q) / (maxq - Q)))

    ReF = - 2 / np.pi * Q * scipy.integrate.romb(y.real, maxq / n) - 1 / np.pi * asymptotic_integral

    gamma_3_2 = 0.5 * np.sqrt(np.pi)
    A2 = - (2 * np.pi) / (2**1.5 * gamma_3_2) * (ReF + 1j * ImF[nQ])  # the factor is from eq 67

    # check ImF(Q)
    # q = np.linspace(0, 2 * Q, n + 1)
    # y = q * microstructure.ft_autocorrelation_funscipyction(q)
    # ImFQ_direct = - 1 / (2 * (2 * np.pi)**1.5) * Q * scipy.integrate.romb(y, 2 * Q / n)
    # print(ImF[nQ], ImFQ_direct)

    return A2
//  [python]
def compute_A2_nonlocal(Q, microstructure):

    margin = 4  # this number must be higher for small grains, because
    # the FT of gamma is wider, so is the integrand of ReF. It means that using the long range version
    # is not recommanded for small grains
    # this value should be adaptive

    maxq = margin * Q

    k = 12  # number of samples. This should be adaptive depending on the size/wavelength
    n = 2**k
    nQ = n // margin
    q = np.linspace(0, maxq, n + 1)

    assert q[nQ] == Q

    # start with the imaginary part - Eq (70)
    y = 2 * q * microstructure.ft_autocorrelation_function(2 * q)

    # integrate from 0 to 2Q (for Q in 0 to qmax)
    # take the real part to avoid warnings... but this remains to be explored
    primitive = scipy.integrate.cumulative_trapezoid(y.real, 2 * q.real, initial=0)

    ImF = - 1 / (2 * (2 * np.pi)**1.5) * q * primitive

    # continue with the real part. Eq (71) is much more difficult to compute than the imaginary part
    # because of the principal value, but Torquato 2021, suppmat gives a hint with Eq S111.
    # here: M = maxq

    with np.errstate(invalid='ignore'):
        y1 = ImF / ((Q + q) * q)
        y1[0] = 0  # remove the singularity in 0

        y2 = (ImF - ImF[nQ]) / (Q**2 - q**2)

        y2[nQ] = (y2[nQ - 1] + y2[nQ + 1]) / 2   # remove the singularity in Q

    y = y1 + y2

    asymptotic_integral = (ImF[nQ] - Q / maxq * ImF[-1]) * np.log(np.abs((maxq + Q) / (maxq - Q)))

    ReF = - 2 / np.pi * Q * scipy.integrate.romb(y.real, maxq / n) - 1 / np.pi * asymptotic_integral

    gamma_3_2 = 0.5 * np.sqrt(np.pi)
    A2 = - (2 * np.pi) / (2**1.5 * gamma_3_2) * (ReF + 1j * ImF[nQ])  # the factor is from eq 67

    # check ImF(Q)
    # q = np.linspace(0, 2 * Q, n + 1)
    # y = q * microstructure.ft_autocorrelation_funscipyction(q)
    # ImFQ_direct = - 1 / (2 * (2 * np.pi)**1.5) * Q * scipy.integrate.romb(y, 2 * Q / n)
    # print(ImF[nQ], ImFQ_direct)

    return A2
//  [python]
def Nl(ll):
    return np.sqrt(2.0 * sm.factorial(ll-2) / sm.factorial(ll+2))
//  [python]
def Nl(ll):
    return np.sqrt(2.0 * sp.special.factorial(ll-2) / sp.special.factorial(ll+2))
//  [python]
def poisson_pdf(k,l):
    return (l**k)*np.exp(-l)/misc.factorial(k)
//  [python]
def poisson_pdf(k,l):
    return (l**k)*np.exp(-l)/scipy.special.factorial(k)
//  [python]
def createSphrHarm(mu, omega, lMax=8):
    sphArray = np.zeros((lMax + 1, lMax + 1, len(mu)))
    for l in range(lMax + 1):
        for m in range(lMax + 1):
            # loop over legendre order
            for i, (mmu, om) in enumerate(zip(mu, omega)):
                try:
                    C = (2 * l + 1) * float(msc.factorial(l - m)) / \
                        float(msc.factorial(l + m))
                    #sphArray[m, l, i] = np.real(C ** (0.5) * spc.lpmv(m, l, mmu) * np.exp(complex(om * m)))
                    sphArray[m, l, i] = np.real(C ** (0.5) * spc.lpmv(m, l, mmu) * np.cos(om * m))
                    #sphArray[m, l, i] = spc.sph_harm(m, l, mmu, om).real
                except:
                    pass
    return sphArray
//  [python]
def createSphrHarm(mu, omega, lMax=8):
    sphArray = np.zeros((lMax + 1, lMax + 1, len(mu)))
    for l in range(lMax + 1):
        for m in range(lMax + 1):
            # loop over legendre order
            for i, (mmu, om) in enumerate(zip(mu, omega)):
                try:
                    C = (2 * l + 1) * float(spc.factorial(l - m)) / \
                        float(spc.factorial(l + m))
                    #sphArray[m, l, i] = np.real(C ** (0.5) * spc.lpmv(m, l, mmu) * np.exp(complex(om * m)))
                    sphArray[m, l, i] = np.real(C ** (0.5) * spc.lpmv(m, l, mmu) * np.cos(om * m))
                    #sphArray[m, l, i] = spc.sph_harm(m, l, mmu, om).real
                except:
                    pass
    return sphArray
//  [python]
def test_infer_independent(self):
        em = _TestPolynomialModel(independent_key="S", dependent_key="A365", mu_degree=1, scale_degree=1)
        em.theta_fitted = [0, 2, 0.1, 1, 3]
        pst = em.infer_independent(y=1, lower=0, upper=20, steps=876)

        assert len(pst.eti_x) == len(pst.eti_pdf)
        assert len(pst.hdi_x) == len(pst.hdi_pdf)
        assert tuple(pst.eti_x[[0, -1]]) == (0, 20)
        assert tuple(pst.hdi_x[[0, -1]]) == (0, 20)
        assert numpy.isclose(scipy.integrate.cumtrapz(pst.eti_pdf, pst.eti_x)[-1], 1, atol=0.0001)
        assert numpy.isclose(scipy.integrate.cumtrapz(pst.hdi_pdf, pst.hdi_x)[-1], 1, atol=0.0001)
        assert pst.eti_lower == pst.hdi_lower == 0
        assert pst.eti_upper == pst.hdi_upper == 20
        assert pst.eti_prob == 1
        assert pst.hdi_prob == 1

        # check trimming to [2.5,97.5] interval
        pst = em.infer_independent(y=[1, 2], lower=0, upper=20, steps=1775, ci_prob=0.95)

        assert len(pst.eti_x) == len(pst.eti_pdf)
        assert len(pst.hdi_x) == len(pst.hdi_pdf)
        assert numpy.isclose(pst.eti_prob, 0.95, atol=0.0001)
        assert numpy.isclose(pst.hdi_prob, 0.95, atol=0.0001)
        assert numpy.isclose(
            scipy.integrate.cumtrapz(pst.eti_pdf, pst.eti_x)[-1], 0.95, atol=0.0001
        )
        assert numpy.isclose(
            scipy.integrate.cumtrapz(pst.hdi_pdf, pst.hdi_x)[-1], 0.95, atol=0.0001
        )
        assert pst.eti_lower == pst.eti_x[0]
        assert pst.eti_upper == pst.eti_x[-1]
        assert pst.hdi_lower == pst.hdi_x[0]
        assert pst.hdi_upper == pst.hdi_x[-1]

        # check that error are raised by wrong input
        with pytest.raises(ValueError):
            em.infer_independent(y=1, lower=0, upper=20, steps=1000, ci_prob=(-1))
        with pytest.raises(ValueError):
            em.infer_independent(y=1, lower=0, upper=20, steps=1000, ci_prob=(97.5))
        pass
//  [python]
def test_infer_independent(self):
        em = _TestPolynomialModel(independent_key="S", dependent_key="A365", mu_degree=1, scale_degree=1)
        em.theta_fitted = [0, 2, 0.1, 1, 3]
        pst = em.infer_independent(y=1, lower=0, upper=20, steps=876)

        assert len(pst.eti_x) == len(pst.eti_pdf)
        assert len(pst.hdi_x) == len(pst.hdi_pdf)
        assert tuple(pst.eti_x[[0, -1]]) == (0, 20)
        assert tuple(pst.hdi_x[[0, -1]]) == (0, 20)
        assert numpy.isclose(scipy.integrate.cumulative_trapezoid(pst.eti_pdf, pst.eti_x)[-1], 1, atol=0.0001)
        assert numpy.isclose(scipy.integrate.cumulative_trapezoid(pst.hdi_pdf, pst.hdi_x)[-1], 1, atol=0.0001)
        assert pst.eti_lower == pst.hdi_lower == 0
        assert pst.eti_upper == pst.hdi_upper == 20
        assert pst.eti_prob == 1
        assert pst.hdi_prob == 1

        # check trimming to [2.5,97.5] interval
        pst = em.infer_independent(y=[1, 2], lower=0, upper=20, steps=1775, ci_prob=0.95)

        assert len(pst.eti_x) == len(pst.eti_pdf)
        assert len(pst.hdi_x) == len(pst.hdi_pdf)
        assert numpy.isclose(pst.eti_prob, 0.95, atol=0.0001)
        assert numpy.isclose(pst.hdi_prob, 0.95, atol=0.0001)
        assert numpy.isclose(
            scipy.integrate.cumulative_trapezoid(pst.eti_pdf, pst.eti_x)[-1], 0.95, atol=0.0001
        )
        assert numpy.isclose(
            scipy.integrate.cumulative_trapezoid(pst.hdi_pdf, pst.hdi_x)[-1], 0.95, atol=0.0001
        )
        assert pst.eti_lower == pst.eti_x[0]
        assert pst.eti_upper == pst.eti_x[-1]
        assert pst.hdi_lower == pst.hdi_x[0]
        assert pst.hdi_upper == pst.hdi_x[-1]

        # check that error are raised by wrong input
        with pytest.raises(ValueError):
            em.infer_independent(y=1, lower=0, upper=20, steps=1000, ci_prob=(-1))
        with pytest.raises(ValueError):
            em.infer_independent(y=1, lower=0, upper=20, steps=1000, ci_prob=(97.5))
        pass
//  [python]
def buildSFpyrlevs(self, lodft, log_rad, angle, Xrcos, Yrcos, ht):
		if (ht <=1):
			lo0 = np.fft.ifft2(np.fft.ifftshift(lodft))
			coeff = [lo0.real]
		
		else:
			#shift by 1 octave
			Xrcos = Xrcos - np.log2(2)

			# ==================== Orientation bandpass =======================
			himask = self.pointOp(log_rad, Yrcos, Xrcos)

			lutsize = 1024
			Xcosn = np.pi * np.array(range(-(2*lutsize+1),(lutsize+2)))/lutsize
			order = self.nbands - 1
			const = (2**(2*order) * sc.factorial(order)**2) / (self.nbands * sc.factorial(2*order))
			Ycosn = np.sqrt(const) * (np.cos(Xcosn)**order)

			M, N = np.shape(lodft)
			orients = np.zeros((int(self.nbands), M, N))
			for b in range(int(self.nbands)):
				anglemask = self.pointOp(angle, Ycosn, Xcosn + (np.pi*b)/self.nbands).astype(np.complex)
				banddft = (np.complex(0,-1)**order) * lodft
				banddft *= anglemask
				banddft *= himask
				orients[b, :, :] = np.fft.ifft2(np.fft.ifftshift(banddft)).real

			# ================== Subsample lowpass ============================
			dims = np.array(lodft.shape)
			
			lostart = np.ceil((dims+0.5)/2) - np.ceil((np.ceil((dims-0.5)/2)+0.5)/2)
			loend = lostart + np.ceil((dims-0.5)/2)

			lostart = lostart.astype(int)
			loend = loend.astype(int)

			log_rad = log_rad[lostart[0]:loend[0], lostart[1]:loend[1]]
			angle = angle[lostart[0]:loend[0], lostart[1]:loend[1]]
			lodft = lodft[lostart[0]:loend[0], lostart[1]:loend[1]]
			YIrcos = np.abs(np.sqrt(1 - Yrcos*Yrcos))
			lomask = self.pointOp(log_rad, YIrcos, Xrcos)

			lodft = lomask * lodft

			coeff = self.buildSFpyrlevs(lodft, log_rad, angle, Xrcos, Yrcos, ht-1)
			coeff.insert(0, orients)
		return coeff
//  [python]
def buildSFpyrlevs(self, lodft, log_rad, angle, Xrcos, Yrcos, ht):
		if (ht <=1):
			lo0 = np.fft.ifft2(np.fft.ifftshift(lodft))
			coeff = [lo0.real]
		
		else:
			#shift by 1 octave
			Xrcos = Xrcos - np.log2(2)

			# ==================== Orientation bandpass =======================
			himask = self.pointOp(log_rad, Yrcos, Xrcos)

			lutsize = 1024
			Xcosn = np.pi * np.array(range(-(2*lutsize+1),(lutsize+2)))/lutsize
			order = self.nbands - 1
			const = (2**(2*order) * sc.special.factorial(order)**2) / (self.nbands * sc.special.factorial(2*order))
			Ycosn = np.sqrt(const) * (np.cos(Xcosn)**order)

			M, N = np.shape(lodft)
			orients = np.zeros((int(self.nbands), M, N))
			for b in range(int(self.nbands)):
				anglemask = self.pointOp(angle, Ycosn, Xcosn + (np.pi*b)/self.nbands).astype(np.complex)
				banddft = (np.complex(0,-1)**order) * lodft
				banddft *= anglemask
				banddft *= himask
				orients[b, :, :] = np.fft.ifft2(np.fft.ifftshift(banddft)).real

			# ================== Subsample lowpass ============================
			dims = np.array(lodft.shape)
			
			lostart = np.ceil((dims+0.5)/2) - np.ceil((np.ceil((dims-0.5)/2)+0.5)/2)
			loend = lostart + np.ceil((dims-0.5)/2)

			lostart = lostart.astype(int)
			loend = loend.astype(int)

			log_rad = log_rad[lostart[0]:loend[0], lostart[1]:loend[1]]
			angle = angle[lostart[0]:loend[0], lostart[1]:loend[1]]
			lodft = lodft[lostart[0]:loend[0], lostart[1]:loend[1]]
			YIrcos = np.abs(np.sqrt(1 - Yrcos*Yrcos))
			lomask = self.pointOp(log_rad, YIrcos, Xrcos)

			lodft = lomask * lodft

			coeff = self.buildSFpyrlevs(lodft, log_rad, angle, Xrcos, Yrcos, ht-1)
			coeff.insert(0, orients)
		return coeff
//  [python]
def reconSFPyrLevs(self, coeff, log_rad, Xrcos, Yrcos, angle):
		if (len(coeff) == 1):
			return np.fft.fftshift(np.fft.fft2(coeff[0]))
		else:
			Xrcos = Xrcos - 1
    		
			# ========================== Orientation residue==========================
			himask = self.pointOp(log_rad, Yrcos, Xrcos)

			lutsize = 1024
			Xcosn = np.pi * np.array(range(-(2*lutsize+1),(lutsize+2)))/lutsize
			order = self.nbands - 1
			const = np.power(2, 2*order) * np.square(sc.factorial(order)) / (self.nbands * sc.factorial(2*order))
			Ycosn = np.sqrt(const) * np.power(np.cos(Xcosn), order)

			orientdft = np.zeros(coeff[0][0].shape, 'complex')

			for b in range(int(self.nbands)):
				anglemask = self.pointOp(angle, Ycosn, Xcosn + (np.pi*b)/self.nbands)
				banddft = np.fft.fftshift(np.fft.fft2(coeff[0][b]))
				orientdft += ((np.complex(0,1)**(order)) * banddft * anglemask * himask)

			# ============== Lowpass component are upsampled and convoluted ============
			dims = np.array(coeff[0][0].shape)
			
			lostart = np.ceil((dims+0.5)/2) - np.ceil((np.ceil((dims-0.5)/2)+0.5)/2) 
			loend = lostart + np.ceil((dims-0.5)/2) 

			nlog_rad = log_rad[lostart[0]:loend[0], lostart[1]:loend[1]]
			nangle = angle[lostart[0]:loend[0], lostart[1]:loend[1]]
			YIrcos = np.sqrt(np.abs(1 - Yrcos * Yrcos))
			lomask = self.pointOp(nlog_rad, YIrcos, Xrcos)

			nresdft = self.reconSFPyrLevs(coeff[1:], nlog_rad, Xrcos, Yrcos, nangle)

			res = np.fft.fftshift(np.fft.fft2(nresdft))

			resdft = np.zeros(dims, 'complex')
			resdft[lostart[0]:loend[0], lostart[1]:loend[1]] = nresdft * lomask

			return resdft + orientdft
//  [python]
def reconSFPyrLevs(self, coeff, log_rad, Xrcos, Yrcos, angle):
		if (len(coeff) == 1):
			return np.fft.fftshift(np.fft.fft2(coeff[0]))
		else:
			Xrcos = Xrcos - 1
    		
			# ========================== Orientation residue==========================
			himask = self.pointOp(log_rad, Yrcos, Xrcos)

			lutsize = 1024
			Xcosn = np.pi * np.array(range(-(2*lutsize+1),(lutsize+2)))/lutsize
			order = self.nbands - 1
			const = np.power(2, 2*order) * np.square(sc.special.factorial(order)) / (self.nbands * sc.special.factorial(2*order))
			Ycosn = np.sqrt(const) * np.power(np.cos(Xcosn), order)

			orientdft = np.zeros(coeff[0][0].shape, 'complex')

			for b in range(int(self.nbands)):
				anglemask = self.pointOp(angle, Ycosn, Xcosn + (np.pi*b)/self.nbands)
				banddft = np.fft.fftshift(np.fft.fft2(coeff[0][b]))
				orientdft += ((np.complex(0,1)**(order)) * banddft * anglemask * himask)

			# ============== Lowpass component are upsampled and convoluted ============
			dims = np.array(coeff[0][0].shape)
			
			lostart = np.ceil((dims+0.5)/2) - np.ceil((np.ceil((dims-0.5)/2)+0.5)/2) 
			loend = lostart + np.ceil((dims-0.5)/2) 

			nlog_rad = log_rad[lostart[0]:loend[0], lostart[1]:loend[1]]
			nangle = angle[lostart[0]:loend[0], lostart[1]:loend[1]]
			YIrcos = np.sqrt(np.abs(1 - Yrcos * Yrcos))
			lomask = self.pointOp(nlog_rad, YIrcos, Xrcos)

			nresdft = self.reconSFPyrLevs(coeff[1:], nlog_rad, Xrcos, Yrcos, nangle)

			res = np.fft.fftshift(np.fft.fft2(nresdft))

			resdft = np.zeros(dims, 'complex')
			resdft[lostart[0]:loend[0], lostart[1]:loend[1]] = nresdft * lomask

			return resdft + orientdft
//  [python]
def getBC(N,k):
    a = scipy.misc.factorial(N)
    b = scipy.misc.factorial(N-k)
    c = scipy.misc.factorial(k)
    return a/(b*c)
//  [python]
def getBC(N,k):
    a = scipy.special.factorial(N)
    b = scipy.special.factorial(N-k)
    c = scipy.special.factorial(k)
    return a/(b*c)
//  [python]
def get_diff_coeff(hvec, n=1):
    """
    Helper function to find difference coefficients of an
    derivative on an arbitrary mesh.

    Args:
        hvec (1D array-like): sampling stencil
        n (int): degree of derivative to find
    """
    hvec = np.array(hvec, dtype=np.float)
    acc = len(hvec)
    exp = np.column_stack([np.arange(acc)]*acc)
    a = np.vstack([hvec] * acc) ** exp
    b = np.zeros(acc)
    b[n] = factorial(n)
    return np.linalg.solve(a, b)
//  [python]
def get_diff_coeff(hvec, n=1):
    """
    Helper function to find difference coefficients of an
    derivative on an arbitrary mesh.

    Args:
        hvec (1D array-like): sampling stencil
        n (int): degree of derivative to find
    """
    hvec = np.array(hvec, dtype=np.float)
    acc = len(hvec)
    exp = np.column_stack([np.arange(acc)]*acc)
    a = np.vstack([hvec] * acc) ** exp
    b = np.zeros(acc)
    b[n] = scipy.special.factorial(n)
    return np.linalg.solve(a, b)
//  [python]
def calculate_stress(self, strain):
        """
        Calculate's a given elastic tensor's contribution to the
        stress using Einstein summation

        Args:
            strain (3x3 array-like): matrix corresponding to strain
        """
        strain = np.array(strain)
        if strain.shape == (6,):
            strain = Strain.from_voigt(strain)
        assert strain.shape == (3, 3), "Strain must be 3x3 or voigt-notation"
        lc = string.ascii_lowercase[:self.rank-2]
        lc_pairs = map(''.join, zip(*[iter(lc)]*2))
        einsum_string = "ij" + lc + ',' + ','.join(lc_pairs) + "->ij"
        einsum_args = [self] + [strain] * (self.order - 1)
        stress_matrix = np.einsum(einsum_string, *einsum_args) \
            / factorial(self.order - 1)
        return Stress(stress_matrix)
//  [python]
def calculate_stress(self, strain):
        """
        Calculate's a given elastic tensor's contribution to the
        stress using Einstein summation

        Args:
            strain (3x3 array-like): matrix corresponding to strain
        """
        strain = np.array(strain)
        if strain.shape == (6,):
            strain = Strain.from_voigt(strain)
        assert strain.shape == (3, 3), "Strain must be 3x3 or voigt-notation"
        lc = string.ascii_lowercase[:self.rank-2]
        lc_pairs = map(''.join, zip(*[iter(lc)]*2))
        einsum_string = "ij" + lc + ',' + ','.join(lc_pairs) + "->ij"
        einsum_args = [self] + [strain] * (self.order - 1)
        stress_matrix = np.einsum(einsum_string, *einsum_args) \
            / scipy.special.factorial(self.order - 1)
        return Stress(stress_matrix)
//  [python]
def multinomial(x, n, p):
    x = np.atleast_2d(x)
    return factorial(n) / factorial(x).prod(1) * (p ** x).prod(1)
//  [python]
def setupMLarrs(nHarmonics):
    # We make use of the built in Legendre polynomials from scipy but
    # need to convert from it to the PFSS normalization.  Calculate a 
    # conversion matrix to be used repeatedly later.  Also set up a matrix
    # with the m and l values in a 2D array matching the Legendre poly form
    global mls, logconvPml
    # ml matrix
    mls = np.empty([nHarmonics+1,nHarmonics+1,2])
    for i in range(nHarmonics+1):
        mls[:,i,0] = range(nHarmonics+1) #ms
        mls[i,:,1] = range(nHarmonics+1) #ls
        
    # Conversion matrix doesn't include (-1)^m since have to use log because
    # of higher orders (l+m > 170)
    convPml = np.empty([nHarmonics+1,nHarmonics+1], dtype=np.longdouble)
    convPml = np.sqrt(2. * factorial(mls[:,:,1] - mls[:,:,0]) / factorial(mls[:,:,1] + mls[:,:,0]))
    convPml[0,:] = 1.
    logconvPml = np.log(convPml)
    
    # Replace the higher orders individually
    brokenFac = np.where(mls[:,:,1]+mls[:,:,0] > 170)
    badms = brokenFac[0]
    badls = brokenFac[1]
    for i in range(len(badms)):
        if badms[i] <= badls[i]:
            logconvPml[badms[i],badls[i]] = 0.5*(math.log(2. * math.factorial(badls[i]-badms[i])) -math.log(math.factorial(badls[i]+badms[i])))
//  [python]
def setupMLarrs(nHarmonics):
    # We make use of the built in Legendre polynomials from scipy but
    # need to convert from it to the PFSS normalization.  Calculate a 
    # conversion matrix to be used repeatedly later.  Also set up a matrix
    # with the m and l values in a 2D array matching the Legendre poly form
    global mls, logconvPml
    # ml matrix
    mls = np.empty([nHarmonics+1,nHarmonics+1,2])
    for i in range(nHarmonics+1):
        mls[:,i,0] = range(nHarmonics+1) #ms
        mls[i,:,1] = range(nHarmonics+1) #ls
        
    # Conversion matrix doesn't include (-1)^m since have to use log because
    # of higher orders (l+m > 170)
    convPml = np.empty([nHarmonics+1,nHarmonics+1], dtype=np.longdouble)
    convPml = np.sqrt(2. * scipy.special.factorial(mls[:,:,1] - mls[:,:,0]) / scipy.special.factorial(mls[:,:,1] + mls[:,:,0]))
    convPml[0,:] = 1.
    logconvPml = np.log(convPml)
    
    # Replace the higher orders individually
    brokenFac = np.where(mls[:,:,1]+mls[:,:,0] > 170)
    badms = brokenFac[0]
    badls = brokenFac[1]
    for i in range(len(badms)):
        if badms[i] <= badls[i]:
            logconvPml[badms[i],badls[i]] = 0.5*(math.log(2. * math.factorial(badls[i]-badms[i])) -math.log(math.factorial(badls[i]+badms[i])))
//  [python]
def get_log_factorial(n):
	if n < 100: return np.log(scipy.misc.factorial(n))
	else: return approx_log_fact(n)
//  [python]
def get_log_factorial(n):
	if n < 100: return np.log(scipy.special.factorial(n))
	else: return approx_log_fact(n)
//  [python]
def reconSFPyrLevs(self, coeff, log_rad, Xrcos, Yrcos, angle):
        if (len(coeff) == 1):
            return np.fft.fftshift(np.fft.fft2(coeff[0]))
        else:
            Xrcos = Xrcos - 1

            # ========================== Orientation residue==========================
            himask = self.pointOp(log_rad, Yrcos, Xrcos)

            lutsize = 1024
            Xcosn = np.pi * np.array(range(-(2*lutsize+1),(lutsize+2)))/lutsize
            order = self.nbands - 1
            const = np.power(2, 2*order) * np.square(sc.factorial(order)) / (self.nbands * sc.factorial(2*order))
            Ycosn = np.sqrt(const) * np.power(np.cos(Xcosn), order)

            orientdft = np.zeros(coeff[0][0].shape, 'complex')

            for b in range(int(self.nbands)):
                anglemask = self.pointOp(angle, Ycosn, Xcosn + (np.pi*b)/self.nbands)
                banddft = np.fft.fftshift(np.fft.fft2(coeff[0][b]))
                orientdft += ((np.complex(0,1)**(order)) * banddft * anglemask * himask)

            # ============== Lowpass component are upsampled and convoluted ============
            dims = np.array(coeff[0][0].shape)

            lostart = np.ceil((dims+0.5)/2) - np.ceil((np.ceil((dims-0.5)/2)+0.5)/2)
            loend = lostart + np.ceil((dims-0.5)/2)

            nlog_rad = log_rad[lostart[0]:loend[0], lostart[1]:loend[1]]
            nangle = angle[lostart[0]:loend[0], lostart[1]:loend[1]]
            YIrcos = np.sqrt(np.abs(1 - Yrcos * Yrcos))
            lomask = self.pointOp(nlog_rad, YIrcos, Xrcos)

            nresdft = self.reconSFPyrLevs(coeff[1:], nlog_rad, Xrcos, Yrcos, nangle)

            res = np.fft.fftshift(np.fft.fft2(nresdft))

            resdft = np.zeros(dims, 'complex')
            resdft[lostart[0]:loend[0], lostart[1]:loend[1]] = nresdft * lomask

            return resdft + orientdft
//  [python]
def reconSFPyrLevs(self, coeff, log_rad, Xrcos, Yrcos, angle):
        if (len(coeff) == 1):
            return np.fft.fftshift(np.fft.fft2(coeff[0]))
        else:
            Xrcos = Xrcos - 1

            # ========================== Orientation residue==========================
            himask = self.pointOp(log_rad, Yrcos, Xrcos)

            lutsize = 1024
            Xcosn = np.pi * np.array(range(-(2*lutsize+1),(lutsize+2)))/lutsize
            order = self.nbands - 1
            const = np.power(2, 2*order) * np.square(sc.special.factorial(order)) / (self.nbands * sc.special.factorial(2*order))
            Ycosn = np.sqrt(const) * np.power(np.cos(Xcosn), order)

            orientdft = np.zeros(coeff[0][0].shape, 'complex')

            for b in range(int(self.nbands)):
                anglemask = self.pointOp(angle, Ycosn, Xcosn + (np.pi*b)/self.nbands)
                banddft = np.fft.fftshift(np.fft.fft2(coeff[0][b]))
                orientdft += ((np.complex(0,1)**(order)) * banddft * anglemask * himask)

            # ============== Lowpass component are upsampled and convoluted ============
            dims = np.array(coeff[0][0].shape)

            lostart = np.ceil((dims+0.5)/2) - np.ceil((np.ceil((dims-0.5)/2)+0.5)/2)
            loend = lostart + np.ceil((dims-0.5)/2)

            nlog_rad = log_rad[lostart[0]:loend[0], lostart[1]:loend[1]]
            nangle = angle[lostart[0]:loend[0], lostart[1]:loend[1]]
            YIrcos = np.sqrt(np.abs(1 - Yrcos * Yrcos))
            lomask = self.pointOp(nlog_rad, YIrcos, Xrcos)

            nresdft = self.reconSFPyrLevs(coeff[1:], nlog_rad, Xrcos, Yrcos, nangle)

            res = np.fft.fftshift(np.fft.fft2(nresdft))

            resdft = np.zeros(dims, 'complex')
            resdft[lostart[0]:loend[0], lostart[1]:loend[1]] = nresdft * lomask

            return resdft + orientdft
//  [python]
def buildSFpyrlevs(self, lodft, log_rad, angle, Xrcos, Yrcos, ht):
        if (ht <=1):
            lo0 = np.fft.ifft2(np.fft.ifftshift(lodft))
            coeff = [lo0.real]

        else:
            #shift by 1 octave
            Xrcos = Xrcos - np.log2(2)

            # ==================== Orientation bandpass =======================
            himask = self.pointOp(log_rad, Yrcos, Xrcos)

            lutsize = 1024
            Xcosn = np.pi * np.array(range(-(2*lutsize+1),(lutsize+2)))/lutsize
            order = self.nbands - 1
            const = (2**(2*order) * sc.factorial(order)**2) / (self.nbands * sc.factorial(2*order))
            Ycosn = np.sqrt(const) * (np.cos(Xcosn)**order)

            M, N = np.shape(lodft)
            orients = np.zeros((int(self.nbands), M, N))
            for b in range(int(self.nbands)):
                anglemask = self.pointOp(angle, Ycosn, Xcosn + (np.pi*b)/self.nbands).astype(np.complex)
                banddft = (np.complex(0,-1)**order) * lodft
                banddft *= anglemask
                banddft *= himask
                orients[b, :, :] = np.fft.ifft2(np.fft.ifftshift(banddft)).real

            # ================== Subsample lowpass ============================
            dims = np.array(lodft.shape)

            lostart = np.ceil((dims+0.5)/2) - np.ceil((np.ceil((dims-0.5)/2)+0.5)/2)
            loend = lostart + np.ceil((dims-0.5)/2)

            lostart = lostart.astype(int)
            loend = loend.astype(int)

            log_rad = log_rad[lostart[0]:loend[0], lostart[1]:loend[1]]
            angle = angle[lostart[0]:loend[0], lostart[1]:loend[1]]
            lodft = lodft[lostart[0]:loend[0], lostart[1]:loend[1]]
            YIrcos = np.abs(np.sqrt(1 - Yrcos*Yrcos))
            lomask = self.pointOp(log_rad, YIrcos, Xrcos)

            lodft = lomask * lodft

            coeff = self.buildSFpyrlevs(lodft, log_rad, angle, Xrcos, Yrcos, ht-1)
            coeff.insert(0, orients)
        return coeff
//  [python]
def buildSFpyrlevs(self, lodft, log_rad, angle, Xrcos, Yrcos, ht):
        if (ht <=1):
            lo0 = np.fft.ifft2(np.fft.ifftshift(lodft))
            coeff = [lo0.real]

        else:
            #shift by 1 octave
            Xrcos = Xrcos - np.log2(2)

            # ==================== Orientation bandpass =======================
            himask = self.pointOp(log_rad, Yrcos, Xrcos)

            lutsize = 1024
            Xcosn = np.pi * np.array(range(-(2*lutsize+1),(lutsize+2)))/lutsize
            order = self.nbands - 1
            const = (2**(2*order) * sc.special.factorial(order)**2) / (self.nbands * sc.special.factorial(2*order))
            Ycosn = np.sqrt(const) * (np.cos(Xcosn)**order)

            M, N = np.shape(lodft)
            orients = np.zeros((int(self.nbands), M, N))
            for b in range(int(self.nbands)):
                anglemask = self.pointOp(angle, Ycosn, Xcosn + (np.pi*b)/self.nbands).astype(np.complex)
                banddft = (np.complex(0,-1)**order) * lodft
                banddft *= anglemask
                banddft *= himask
                orients[b, :, :] = np.fft.ifft2(np.fft.ifftshift(banddft)).real

            # ================== Subsample lowpass ============================
            dims = np.array(lodft.shape)

            lostart = np.ceil((dims+0.5)/2) - np.ceil((np.ceil((dims-0.5)/2)+0.5)/2)
            loend = lostart + np.ceil((dims-0.5)/2)

            lostart = lostart.astype(int)
            loend = loend.astype(int)

            log_rad = log_rad[lostart[0]:loend[0], lostart[1]:loend[1]]
            angle = angle[lostart[0]:loend[0], lostart[1]:loend[1]]
            lodft = lodft[lostart[0]:loend[0], lostart[1]:loend[1]]
            YIrcos = np.abs(np.sqrt(1 - Yrcos*Yrcos))
            lomask = self.pointOp(log_rad, YIrcos, Xrcos)

            lodft = lomask * lodft

            coeff = self.buildSFpyrlevs(lodft, log_rad, angle, Xrcos, Yrcos, ht-1)
            coeff.insert(0, orients)
        return coeff
//  [python]
def poissonGammaAnalytic(N,c,a,b,alpha):
    pmfPoisson = np.zeros(N+1)
    q = np.divide(b,b+1)
    den = math.gamma(a)
    for k in range(0,N+1):
        num = np.divide(math.gamma(a+k),scipy.misc.factorial(k))
        pmfPoisson[k] = np.divide(num,den)*np.power(q,a)*np.power(1-q,k)  
    cdfPoisson = np.cumsum(pmfPoisson)
    varAnalytic = c*np.interp(alpha,cdfPoisson,np.linspace(0,N,N+1))
    esAnalytic = util.analyticExpectedShortfall(N,alpha,pmfPoisson,c)
    return pmfPoisson,cdfPoisson,varAnalytic,esAnalytic
//  [python]
def poissonGammaAnalytic(N,c,a,b,alpha):
    pmfPoisson = np.zeros(N+1)
    q = np.divide(b,b+1)
    den = math.gamma(a)
    for k in range(0,N+1):
        num = np.divide(math.gamma(a+k),scipy.special.factorial(k))
        pmfPoisson[k] = np.divide(num,den)*np.power(q,a)*np.power(1-q,k)  
    cdfPoisson = np.cumsum(pmfPoisson)
    varAnalytic = c*np.interp(alpha,cdfPoisson,np.linspace(0,N,N+1))
    esAnalytic = util.analyticExpectedShortfall(N,alpha,pmfPoisson,c)
    return pmfPoisson,cdfPoisson,varAnalytic,esAnalytic