-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmath_utility.py
180 lines (135 loc) · 4.81 KB
/
math_utility.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
import numpy as np
from cmath import rect, phase
from math import radians, degrees
from scipy.stats import pearsonr
from scipy.stats import chi2
from scipy.signal import butter, lfilter
def cart2pol(x, y):
rho = np.sqrt(x**2 + y**2)
phi = np.arctan2(y, x)
return rho, phi
def pol2cart(rho, phi):
x = rho * np.cos(phi)
y = rho * np.sin(phi)
return x, y
# source: https://rosettacode.org/wiki/Averages/Mean_angle#Python
def mean_angle(deg):
return degrees(phase(sum(rect(1, radians(d)) for d in deg)/len(deg)))
def circ_corrcc(alpha, x):
"""Correlation coefficient between one circular and one linear random
variable.
Args:
alpha: vector
Sample of angles in radians
x: vector
Sample of linear random variable
Returns:
rho: float
Correlation coefficient
pval: float
p-value
Code taken from the Circular Statistics Toolbox for Matlab
By Philipp Berens, 2009
Python adaptation by Etienne Combrisson
"""
if len(alpha) is not len(x):
raise ValueError('The length of alpha and x must be the same')
n = len(alpha)
# Compute correlation coefficent for sin and cos independently
rxs = pearsonr(x, np.sin(alpha))[0]
rxc = pearsonr(x, np.cos(alpha))[0]
rcs = pearsonr(np.sin(alpha), np.cos(alpha))[0]
# Compute angular-linear correlation (equ. 27.47)
rho = np.sqrt((rxc ** 2 + rxs ** 2 - 2 * rxc * rxs * rcs) / (1 - rcs ** 2));
# Compute pvalue
pval = 1 - chi2.cdf(n * rho ** 2, 2);
return rho, pval
def circ_r(alpha, w=None, d=0, axis=0):
"""Computes mean resultant vector length for circular data.
Args:
alpha: array
Sample of angles in radians
Kargs:
w: array, optional, [def: None]
Number of incidences in case of binned angle data
d: radians, optional, [def: 0]
Spacing of bin centers for binned data, if supplied
correction factor is used to correct for bias in
estimation of r
axis: int, optional, [def: 0]
Compute along this dimension
Return:
r: mean resultant length
Code taken from the Circular Statistics Toolbox for Matlab
By Philipp Berens, 2009
Python adaptation by Etienne Combrisson
"""
# alpha = np.array(alpha)
# if alpha.ndim == 1:
# alpha = np.matrix(alpha)
# if alpha.shape[0] is not 1:
# alpha = alpha
if w is None:
w = np.ones(alpha.shape)
elif (alpha.size is not w.size):
raise ValueError("Input dimensions do not match")
# Compute weighted sum of cos and sin of angles:
r = np.multiply(w, np.exp(1j * alpha)).sum(axis=axis)
# Obtain length:
r = np.abs(r) / w.sum(axis=axis)
# For data with known spacing, apply correction factor to
# correct for bias in the estimation of r
if d is not 0:
c = d / 2 / np.sin(d / 2)
r = c * r
return np.array(r)
def circ_rtest(alpha, w=None, d=0):
"""Computes Rayleigh test for non-uniformity of circular data.
H0: the population is uniformly distributed around the circle
HA: the populatoin is not distributed uniformly around the circle
Assumption: the distribution has maximally one mode and the data is
sampled from a von Mises distribution!
Args:
alpha: array
Sample of angles in radians
Kargs:
w: array, optional, [def: None]
Number of incidences in case of binned angle data
d: radians, optional, [def: 0]
Spacing of bin centers for binned data, if supplied
correction factor is used to correct for bias in
estimation of r
Code taken from the Circular Statistics Toolbox for Matlab
By Philipp Berens, 2009
Python adaptation by Etienne Combrisson
"""
alpha = np.array(alpha)
if alpha.ndim == 1:
alpha = np.matrix(alpha)
if alpha.shape[1] > alpha.shape[0]:
alpha = alpha.T
if w is None:
r = circ_r(alpha)
n = len(alpha)
else:
if len(alpha) is not len(w):
raise ValueError("Input dimensions do not match")
r = circ_r(alpha, w, d)
n = w.sum()
# Compute Rayleigh's
R = n * r
# Compute Rayleigh's
z = (R ** 2) / n
# Compute p value using approxation in Zar, p. 617
pval = np.exp(np.sqrt(1 + 4 * n + 4 * (n ** 2 - R ** 2)) - (1 + 2 * n))
return np.squeeze(pval), np.squeeze(z)
def butter_bandpass(lowcut, highcut, fs, order=5):
nyq = 0.5 * fs
low = lowcut / nyq
high = highcut / nyq
b, a = butter(order, [low, high], btype='band')
return b, a
def butter_bandpass_filter(data, lowcut, highcut, fs, order=5):
b, a = butter_bandpass(lowcut, highcut, fs, order=order)
y = lfilter(b, a, data)
return y