# encoding: utf-8
"""
circstat.py -- Circular statistics functions
Exported namespace: mean, std, var
Note: all functions take an array of radian-angle values on [0, 2*pi] as input.
Written by Joe Monaco, 4/17/2007
Center for Theoretical Neuroscience
Copyright (c) 2007 Columbia University. All rights reserved.
This software is provided AS IS under the terms of the Open Source MIT License.
See http://www.opensource.org/licenses/mit-license.php.
"""
# Library imports
from numpy import ones, dot, sin, cos, empty, arange, pi
from scipy.stats import histogram
# Package imports
from .radians import xy_to_rad
def mean(theta, w=None):
"""First circular moment
Input: theta - array of radian angle values
w - optional weighting if angle values are binned
Returns: scalar circular mean of theta
See: http://en.wikipedia.org/wiki/Directional_statistics
"""
sz = theta.shape[0]
if w is None:
w = ones(sz, 'd')
elif w.size != sz:
raise ValueError, 'weight array size mismatch'
s_bar = dot(w, sin(theta))
c_bar = dot(w, cos(theta))
return xy_to_rad(c_bar, s_bar)
def std(theta):
"""Sample circular deviation
Input: theta - array of radian angle values
Returns: circular standard deviation
"""
return (var(theta))**0.5
def var(theta, Nbins=360):
"""Sample circular variance, second moment
Calculated using the minimum variance method with moving cut points.
See: Weber RO (1997). J. Appl. Meteorol. 36(10), 1403-1415.
Input: theta - array of radian angle values
numbins - number of intervals across [0, 2pi] to minimize
Returns: circular variance
"""
N = len(theta)
delta_t = 2 * pi / Nbins
lims = (0, 2 * pi)
x = arange(delta_t, 2*pi + delta_t, delta_t)
n, xmin, w, extra = histogram(theta, numbins=Nbins, defaultlimits=lims)
tbar = empty((Nbins,), 'd')
S = empty((Nbins,), 'd')
s2 = empty((Nbins,), 'd')
tbar[0] = (x*n).sum() / N # A1
S[0] = ((x**2)*n).sum() / (N - 1) # A2
s2[0] = S[0] - N * (tbar[0]**2) / (N - 1) # A3
for k in xrange(1, Nbins):
tbar[k] = tbar[k-1] + (2*pi) * n[k-1] / N # A4
S[k] = S[k-1] + (2*pi) * (2*pi + 2*x[k-1]) * n[k-1] / (N - 1) # A5
s2[k] = S[k] - N * (tbar[k]**2) / (N - 1) # A6
return s2.min()