def VonMisesFisher_sample(phi0, theta0, sigma0, size=None):
    """ Draw a sample from the Von-Mises Fisher distribution.

    Parameters
    ----------
    phi0, theta0 : float or array-like
        Spherical-polar coordinates of the center of the distribution.

    sigma0 : float
        Width of the distribution.

    size : int, tuple, array-like
        number of samples to draw.

    Returns
    -------
    phi, theta : float or array_like
        Spherical-polar coordinates of sample from distribution.
    """
    n0 = cartesian_from_polar(phi0, theta0)
    M = rotation_matrix([0, 0, 1], n0)

    x = numpy.random.uniform(size=size)
    phi = numpy.random.uniform(size=size) * 2 * numpy.pi
    theta = numpy.arccos(1 + sigma0**2 *
                         numpy.log(1 + (numpy.exp(-2 / sigma0**2) - 1) * x))
    n = cartesian_from_polar(phi, theta)

    x = M.dot(n)
    phi, theta = polar_from_cartesian(x)

    return phi, theta
def VonMisesFisher_distribution(phi, theta, phi0, theta0, sigma0):
    """ Von-Mises Fisher distribution function.


    Parameters
    ----------
    phi, theta : float or array_like
        Spherical-polar coordinates to evaluate function at.

    phi0, theta0 : float or array-like
        Spherical-polar coordinates of the center of the distribution.

    sigma0 : float
        Width of the distribution.

    Returns
    -------
    float or array_like
        log-probability of the vonmises fisher distribution.

    Notes
    -----
    Wikipedia:
        https://en.wikipedia.org/wiki/Von_Mises-Fisher_distribution
    """
    x = cartesian_from_polar(phi, theta)
    x0 = cartesian_from_polar(phi0, theta0)
    norm = -numpy.log(4 * numpy.pi * sigma0**2) - logsinh(1. / sigma0**2)
    return norm + numpy.tensordot(x, x0, axes=[[0], [0]]) / sigma0**2
def test_rotation_matrix():
    numpy.random.seed(seed=0)

    theta = numpy.random.rand(10, 2)*numpy.pi
    phi = numpy.random.rand(10, 2)*2*numpy.pi
    for (p1, p2), (t1, t2) in zip(phi, theta):
        n1 = utils.cartesian_from_polar(p1, t1)
        n2 = utils.cartesian_from_polar(p2, t2)
        M = utils.rotation_matrix(n1, n2)
        assert_allclose(M.dot(n1), n2)
        assert_allclose(M.T.dot(n2), n1)

    M = utils.rotation_matrix(n1, n1)
    assert_allclose(M, numpy.identity(3))
def VonMises_std(phi, theta):
    """ Von-Mises sample standard deviation.

    Parameters
    ----------
    phi, theta : array-like
        Spherical-polar coordinate samples to compute mean from.

    Returns
    -------
        solution for

        ..math:: 1/tanh(x) - 1/x = R,

        where

        ..math:: R = || \sum_i^N x_i || / N

    Notes
    -----
    Wikipedia:
        https://en.wikipedia.org/wiki/Von_Mises-Fisher_distribution#Estimation_of_parameters
        but re-parameterised for sigma rather than kappa.
    """
    x = cartesian_from_polar(phi, theta)
    S = numpy.sum(x, axis=-1)
    R = S.dot(S)**0.5 / x.shape[-1]

    def f(s):
        return 1 / numpy.tanh(s) - 1. / s - R

    kappa = scipy.optimize.brentq(f, 1e-8, 1e8)
    sigma = kappa**-0.5
    return sigma
def VonMises_mean(phi, theta):
    """ Von-Mises sample mean.

    Parameters
    ----------
    phi, theta : array-like
        Spherical-polar coordinate samples to compute mean from.

    Returns
    -------
    float

        ..math::
            \sum_i^N x_i / || \sum_i^N x_i ||

    Notes
    -----
    Wikipedia:
        https://en.wikipedia.org/wiki/Von_Mises-Fisher_distribution#Estimation_of_parameters
    """
    x = cartesian_from_polar(phi, theta)
    S = numpy.sum(x, axis=-1)
    phi, theta = polar_from_cartesian(S)
    return phi, theta
def test_cartesian_from_polar_array():
    cart1 = utils.cartesian_from_polar(*test_polar.T)
    assert_allclose(test_cartesian.T, cart1)
def test_cartesian_from_polar_scalar():
    for ang, cart0 in zip(test_polar, test_cartesian):
        cart1 = utils.cartesian_from_polar(*ang)
        assert_allclose(cart0, cart1)
 def g(phi, theta):
     return f(phi, theta) * cartesian_from_polar(phi, theta)[i]