comparison allan.py @ 0:3dcd4cfd8f82

Import
author Daniele Nicolodi <daniele.nicolodi@obspm.fr>
date Fri, 18 Apr 2014 18:44:54 +0200
parents
children ebc4e1d7c32f
comparison
equal deleted inserted replaced
-1:000000000000 0:3dcd4cfd8f82
1 import numpy as np
2 from scipy import polyfit, polyval
3 import matplotlib.pyplot as plt
4 import numexpr
5
6 __all__ = ['outliers', 'detrend', 'fastdetrend',
7 'adev', 'xadev', 'xmdev', 'xtdev', 'xavar', 'xmvar', ]
8
9
10 def outliers(y, alpha=6, remove=False):
11 """Detect and optionally remove outliers"""
12
13 m = np.mean(y)
14 v = np.var(y)
15
16 outliers = np.abs(y - m) > (alpha * np.sqrt(v))
17
18 if remove:
19 x = lambda z: z.nonzero()[0]
20 y[outliers] = np.interp(x(outliers), x(~outliers), y[~outliers])
21
22 return np.nonzero(outliers)[0]
23
24
25 def detrend(y, order=1):
26 """Detrend"""
27
28 x = np.arange(y.size)
29 p = polyfit(x, y, order)
30 y = y - polyval(p, x)
31 return y
32
33
34 def fastdetrend(y, order=1, downsample=1000):
35 # time base
36 x = np.arange(y.size)
37 # compute detrend polynomial from downsampled data
38 p = polyfit(x[::downsample], y[::downsample], order)
39
40 # construct numexpr expression
41 expr = []
42 args = {'y': y, 'x': x}
43 for i in range(order + 1):
44 expr.append("p%d" % i + "*x" * i)
45 args["p%d" % i] = p[order - i]
46 expr = "y - (%s)" % " + ".join(expr)
47
48 # evaluate expression
49 y = numexpr.evaluate(expr, local_dict=args)
50 return y
51
52
53 def adev(x, tau, sampl=1.0):
54 """Allan deviation"""
55
56 x = np.asarray(x)
57 tau = np.asarray(tau)
58
59 # allocate output vectors
60 adev = np.zeros(tau.size)
61 dadev = np.zeros(tau.size)
62
63 # samples
64 n = x.size
65 # partitioning
66 p = np.floor(tau * sampl).astype(int)
67
68 for i, m in enumerate(p):
69 d = x[0:n - n % m].reshape(-1, m)
70 y = np.mean(d, axis=1)
71 adev[i] = np.sqrt(0.5 * np.mean(np.diff(y)**2))
72 dadev[i] = adev[i] / np.sqrt(y.size)
73
74 return adev, dadev
75
76
77 from _allan import _xmvar, _xmvar2, _xavar
78
79 # Functions to compute Allan deviation and modified Allan deviation
80 # from time error data. For an oscillator described by the equation
81 # v(t) = v0 * cos(2*pi * f0 * t + phi(t)) where f0 is the nominal
82 # oscillator frequency the time deviation is computed as: x(t) =
83 # phi(t) / (2*pi * f0)
84 #
85 # The Symmetricom 5115A phase analyzer outputs data in units of cycles
86 # of the input signal. To obtain time deviation from the data stream
87 # d(t) it is sufficient to compute: x(t) = d(t) / f0 where f0 is the
88 # nominal frequency of the oscillator under test
89
90 def xmvar0(x, tau, tau0=1.0):
91
92 x = np.asarray(x)
93 tau = np.asarray(tau)
94
95 # allocate output vectors
96 mvar = np.zeros(tau.size)
97
98 # partitioning
99 p = (tau // tau0).astype(int)
100
101 for k, m in enumerate(p):
102 mvar[k] = _xmvar(x, m)
103 # c = 0
104 # for j in xrange(x.size - 3 * m + 1):
105 # v = 0
106 # for i in xrange(j, j + m):
107 # v += (x[i + 2 * m] - 2 * x[i + m] + x[i]) / m
108 # c += v*v
109 # mavar[k] = c / (2.0 * m*m * (n - 3 * m + 1))
110
111 return np.sqrt(mvar) / tau0
112
113
114 def xmvar(x, tau, tau0=1.0):
115
116 x = np.asarray(x)
117 tau = np.asarray(tau)
118
119 # partitioning
120 p = (tau // tau0).astype(int)
121
122 return _xmvar2(x, p) / (tau0 * tau0)
123
124
125 def xmdev(x, tau, tau0=1.0):
126
127 return np.sqrt(xmvar(x, tau, tau0))
128
129
130 def xtdev(x, tau, tau0=1.0):
131
132 return np.sqrt(xmvar(x, tau, tau0)) * tau / np.sqrt(3.0)
133
134
135 def xavar(x, tau, tau0=1.0):
136
137 x = np.asarray(x)
138 tau = np.asarray(tau)
139
140 # partitioning
141 p = (tau // tau0).astype(int)
142
143 return _xavar(x, p) / (tau0 * tau0)
144
145
146 def xadev(x, tau, tau0=1.0):
147
148 return np.sqrt(xavar(x, tau, tau0))