1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 """ Data.py - Functions to load data from Matlab files and to
23 interpolate the frequency and magnitude of the maxima.
24
25 """
26
27 __all__ = ['LoadMatlabData', 'InterpolateMaxima']
28
29 import scipy.io
30 from scipy import optimize, linalg
31 import numpy
32 from numpy import sign, diff
33
34 from wiat.util import calculate_interval_in_cents
35
37 """ Load data from a matlab file. All variable name in the names tuple are
38 fetched and returned .
39
40 Example::
41
42 >>> import os
43 >>> import numpy
44 >>> import wiat
45 >>> f,z = wiat.Data.load_from_mat(('freqs','z'),
46 ... os.path.join(wiat.MEASUREMENTDIR,'20080412Ztoneholeless.mat'))
47 >>> numpy.size(f) == numpy.size(z)
48 True
49
50
51 @param names: A tuple containing variable names to get from the Matlab
52 file.
53 @param filename: the path to the Matlab file
54 @return: a list of the extracted arrays. None if the name do not exist.
55 """
56
57 try:
58 data = scipy.io.loadmat(filename)
59 except IOError, arg:
60 print arg
61 raise IOError(arg)
62
63 ret = []
64 for name in names:
65 if not data.has_key(name):
66 print 'Warning: no such variable %s in Matlab file %s'\
67 %(name,filename)
68 ret.append(data.get(name))
69 return ret
70
72 " Class for fiting an equation of the form M{y = ax**2 + bx + c} "
75
77 c = self.C
78 return c[0]*f**2+c[1]*f+c[2]
79
81 """ Fit the parabola passing through 3 points with 3 equations
82
83 M{y1 = a * x1**2 + b*x1 + c}
84 M{y2 = a * x2**2 + b*x2 + c}
85 M{y3 = a * x3**2 + b*x3 + c}
86
87 """
88 self.px = px
89 self.py = py
90 B = py
91 tmp = numpy.array([px**2, px, [1.,1.,1.]])
92 A = numpy.array([tmp[:,0], tmp[:,1], tmp[:,2]])
93 self.C = scipy.linalg.solve(A, B)
94
97
100
102 """ position of vertical axis of symmetry: h = -b / 2a """
103 return - self.C[1] / (2*self.C[0])
104
106 """ value of parabola on axis of symmetry: k = (4ac - b**2) / 4a """
107 return (4*self.C[0]*self.C[2] - self.C[1]**2) / (4 * self.C[0])
108
110 """ Find the maxima in the data and interpolate with Parbola to find the
111 frequency and amplitude of the maxima.
112
113 Results that are noisy are likely to pose problems to the algorithm.
114
115 @param fmin: minimal frequency we are interested in, useful to avoid
116 low frequency noise to infect the results.
117 """
118
119 derivative = diff(abs(Z))
120 signarray = sign(derivative)
121 crossing = diff(signarray)
122 indices = crossing.nonzero()
123
124 maximalist = []
125
126 for i in indices[0]:
127 if f[i] < fmin:
128 continue
129
130
131
132
133
134
135
136
137
138
139
140
141 if abs(Z[i]) > 1.:
142
143 while True:
144 if abs(Z[i-1]) > abs(Z[i]):
145 i = i - 1
146 elif abs(Z[i+1]) > abs(Z[i]):
147 i = i + 1
148 else:
149 break
150
151 P = __Parabola()
152 P.fit_points(f[i-1:i+2], abs(Z[i-1:i+2]))
153
154
155
156 if maximalist != []:
157 if abs(calculate_interval_in_cents(P.xc(), maximalist[-1][0]))\
158 < 300.:
159 if P.yc() > maximalist[-1][1]:
160 maximalist.pop()
161 else:
162 continue
163
164
165 maximalist.append( ( P.xc(), P.yc() ) )
166 return maximalist
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226