def test_rotate_by_angles():
    before = np.array([1.,0.,0.])
    theta = -np.pi/3. # upwards
    phi = np.pi/3.
    after = rotate_by_angles(before, theta, phi)
    assert_almost_equal(after, np.array((0.25, np.sqrt(3)/4., np.sqrt(3)/2.)))
    
    before = np.array([0., 1., 0.])
    theta = np.pi/3.
    phi = np.pi/4.
    after = rotate_by_angles(before, theta, phi)
    assert_almost_equal(after, np.array((-np.sqrt(2.)/2., np.sqrt(2)/2., 0.)))

    # test stacking of vectors
    before = np.array([[1., 0., 0.], [0., 0., 1.]]).T # shape (2, 3)
    theta = -np.pi/3.
    phi = np.pi/3.
    after = rotate_by_angles(before, theta, phi)
    assert_almost_equal(after, 
        np.array([[0.25, np.sqrt(3)/4., np.sqrt(3)/2.],
                  [np.sin(-np.pi/3.) * np.cos(np.pi/3.), -0.75, .5]]).T)
def vmf_rvs(mu, k, n_pts=1):
    '''Simulate a  Fisher distribution. From Statistical Analysis of
    Spherical Data, 1987, section 3.6.2'''
    size = (n_pts, 2)
    R = np.random.uniform(size=size)
    R_0 = R[...,0]
    R_1 = R[...,1]
    l = np.exp(-2 * k)
    colat = 2 * np.arcsin(np.sqrt(-np.log(R_0 * (1 - l) + l) / (2 * k)))
    longit = 2 * np.pi * R_1
    
    pts = convert_polar_to_cartesian(colat, longit)
    #print mean_dir(pts.T)
    alpha, beta = convert_cartesian_to_polar(mu)
    return rotate_by_angles(pts, alpha, beta).T