Example #1
0
def setup_legendre_transform(b):
    """
    Compute a set of matrices containing coefficients to be used in a discrete Legendre transform.
    
    The discrete Legendre transform of a data vector s[k] (k=0, ..., 2b-1) is defined as

    s_hat(l, m) = sum_{k=0}^{2b-1} P_l^m(cos(beta_k)) s[k]
    for l = 0, ..., b-1 and -l <= m <= l,
    where P_l^m is the associated Legendre function of degree l and order m,
    beta_k = ...

    Computing Fourier Transforms and Convolutions on the 2-Sphere
    J.R. Driscoll, D.M. Healy

    FFTs for the 2-Sphere–Improvements and Variations
    D.M. Healy, Jr., D.N. Rockmore, P.J. Kostelec, and S. Moore

    :param b: bandwidth of the transform
    :return: lt, an array of shape (N, 2b), containing samples of the Legendre functions,
     where N is the number of spectral points for a signal of bandwidth b.
    """
    dim = np.sum(np.arange(b) * 2 + 1)
    lt = np.empty((2 * b, dim))

    beta, _ = S2.linspace(b, grid_type='Driscoll-Healy')
    sample_points = np.cos(beta)

    # TODO move quadrature weight computation to S2.py
    weights = [(1. / b) * np.sin(np.pi * j * 0.5 / b) * np.sum([
        1. / (2 * l + 1) * np.sin((2 * l + 1) * np.pi * j * 0.5 / b)
        for l in range(b)
    ]) for j in range(2 * b)]
    weights = np.array(weights)

    zeros = np.zeros_like(sample_points)
    i = 0
    for l in range(b):
        for m in range(-l, l + 1):
            # Z = np.sqrt(((2 * l + 1) * factorial(l - m)) / float(4 * np.pi * factorial(l + m))) * np.pi / 2
            # lt[i, :] = lpmv(m, l, sample_points) * weights * Z

            # The spherical harmonics code appears to be more stable than the (unnormalized) associated Legendre
            # function code.
            # (Note: the spherical harmonics evaluated at alpha=0 is the associated Legendre function))
            lt[:,
               i] = csh(l, m, beta, zeros,
                        normalization='seismology').real * weights * np.pi / 2

            i += 1

    return lt
Example #2
0
def linspace(b, grid_type='SOFT'):
    """
    Compute a linspace on the 3-sphere.

    Since S3 is ismorphic to SO(3), we use the grid grid_type from:
    FFTs on the Rotation Group
    Peter J. Kostelec and Daniel N. Rockmore
    http://www.cs.dartmouth.edu/~geelong/soft/03-11-060.pdf
    :param b:
    :return:
    """
    # alpha = 2 * np.pi * np.arange(2 * b) / (2. * b)
    # beta = np.pi * (2 * np.arange(2 * b) + 1) / (4. * b)
    # gamma = 2 * np.pi * np.arange(2 * b) / (2. * b)

    beta, alpha = S2.linspace(b, grid_type)

    # According to this paper:
    # "Sampling sets and quadrature formulae on the rotation group"
    # We can just tack a sampling grid for S^1 to a sampling grid for S^2 to get a sampling grid for SO(3).
    gamma = 2 * np.pi * np.arange(2 * b) / (2. * b)

    return alpha, beta, gamma