Browse Source

More work on improved model based harmonic noise removal.

tags/1.6.1
Trevor Irons 5 years ago
parent
commit
8861684ff3
2 changed files with 61 additions and 54 deletions
  1. 56
    49
      akvo/tressel/harmonic.py
  2. 5
    5
      akvo/tressel/mrsurvey.py

+ 56
- 49
akvo/tressel/harmonic.py View File

@@ -109,69 +109,73 @@ def harmonicEuler ( f0, sN, fs, nK, t ):
109 109
     print("building Euler matrix ")
110 110
     A = np.zeros( (len(t),  nK), dtype=np.complex64)
111 111
     for irow, tt in enumerate(t): 
112
-        #A[irow, 0::2] = np.cos( np.arange(nK)*2*np.pi*(f0/fs)*irow )
113
-        #A[irow, 1::2] = np.sin( np.arange(nK)*2*np.pi*(f0/fs)*irow )
114
-        A[irow,:] = np.exp( 1j* np.arange(nK)*2*np.pi*(f0/fs)*irow )
115
-
112
+        A[irow,:] = np.exp(1j* np.arange(1,nK+1) * 2*np.pi* (f0/fs) * irow)
116 113
 
117 114
     v = np.linalg.lstsq(A, sN, rcond=None) # rcond=None) #, rcond=1e-8)
118
-    #v = sclstsq(A, sN) #, rcond=1e-6)
119 115
     alpha = np.real(v[0]) #[0::2]
120 116
     beta  = np.imag(v[0]) #[1::2]
121
-    
122
-    #print("Solving A A.T")
123
-    #v = lin.solve(np.dot(A,A.T).T, sN) #, rcond=1e-6)
124
-    #v = np.dot(A.T, v)
125
-    #v = np.dot(np.linalg.inv(np.dot(A.T, A)), np.dot(A.T, sN))
126
-    #alpha = v[0::2]
127
-    #beta  = v[1::2]
128 117
 
129 118
     amp = np.abs(v[0])     #np.sqrt( alpha**2 + beta**2 )
130 119
     phase = np.angle(v[0]) # np.arctan(- beta/alpha)
131 120
 
132
-    #print("amp:", amp, " phase", phase)
133
-
134 121
     h = np.zeros(len(t))
135 122
     for ik in range(nK):
136
-        h +=  2*amp[ik] * np.cos( 2.*np.pi*ik * (f0/fs) * np.arange(0, len(t), 1 )  + phase[ik] )
123
+        h +=  2*amp[ik] * np.cos( 2.*np.pi*(ik+1) * (f0/fs) * np.arange(0, len(t), 1 )  + phase[ik] )
137 124
 
138
-    #plt.matshow(np.imag(A), aspect='auto')
139
-    #plt.colorbar()
125
+    return sN-h
140 126
 
141
-    #plt.figure()
142
-    #plt.plot(alpha)
143
-    #plt.plot(beta)
144
-    #plt.plot(amp)
127
+def harmonicEuler2 ( f0, f1, sN, fs, nK, t ): 
128
+    """
129
+    Performs inverse calculation of harmonics contaminating a signal. 
130
+    Args:
131
+        f0 = base frequency of the sinusoidal noise 
132
+        sN = signal containing noise 
133
+        fs = sampling frequency
134
+        nK = number of harmonics to calculate 
135
+        t = time samples 
136
+    """
137
+    print("building Euler matrix 2 ")
138
+    A = np.zeros( (len(t),  2*nK), dtype=np.complex64)
139
+    for irow, tt in enumerate(t): 
140
+        A[irow,0:nK]    = np.exp( 1j* np.arange(1,nK+1)*2*np.pi*(f0/fs)*irow )
141
+        A[irow,nK:2*nK] = np.exp( 1j* np.arange(1,nK+1)*2*np.pi*(f1/fs)*irow )
142
+
143
+    v = np.linalg.lstsq(A, sN, rcond=None) # rcond=None) #, rcond=1e-8)
144
+
145
+    amp = np.abs(v[0][0:nK])     
146
+    phase = np.angle(v[0][0:nK]) 
147
+    amp1 = np.abs(v[0][nK:2*nK])     
148
+    phase1 = np.angle(v[0][nK:2*nK]) 
149
+
150
+    h = np.zeros(len(t))
151
+    for ik in range(nK):
152
+        h +=  2*amp[ik]  * np.cos( 2.*np.pi*(ik+1) * (f0/fs) * np.arange(0, len(t), 1 )  + phase[ik] ) + \
153
+              2*amp1[ik] * np.cos( 2.*np.pi*(ik+1) * (f1/fs) * np.arange(0, len(t), 1 )  + phase1[ik] )
145 154
 
146
-    #plt.figure()
147
-    #plt.plot(h)
148
-    #plt.title("modelled noise")
149 155
     return sN-h
150 156
 
151
-def jacobian( f0, sN, fs, nK, t):
157
+def jacEuler( f0, sN, fs, nK, t):
152 158
     print("building Jacobian matrix ")
153
-    A = np.zeros( (len(t),  2*nK) )
154
-    for irow, tt in enumerate(t): 
155
-        #A[irow, 0::2] = np.cos( np.arange(nK)*2*np.pi*(f0/fs)*irow )
156
-        #A[irow, 1::2] = np.sin( np.arange(nK)*2*np.pi*(f0/fs)*irow )
157
-        # brutal 
158
-        for k, ik in enumerate( np.arange(0, 2*nK, 2) ):
159
-            #A[irow, ik  ] = np.cos( k*2*np.pi*(f0/fs)*irow )
160
-            #A[irow, ik+1] = np.sin( k*2*np.pi*(f0/fs)*irow )    
161
-            A[irow, ik  ] = - (2.*np.pi*k*irow * sin((2.*np.pi*irow*f0)/fs)) / fs
162
-            A[irow, ik+1] =   (2.*np.pi*k*irow * cos((2.*np.pi*irow*f0)/fs)) / fs
163
-
159
+    J = np.zeros( (len(t),  nK), dtype=np.complex64 )
160
+    for it, tt in enumerate(t):
161
+        for ik, k in enumerate( np.arange(0, nK) ):
162
+            c = 1j*2.*np.pi*(ik+1.)*it
163
+            J[it, ik] = c*np.exp( c*f0/fs ) / fs 
164
+    #plt.matshow(np.imag(J), aspect='auto')
165
+    #plt.show()
166
+    return J
164 167
 
165 168
 def harmonicNorm ( f0, sN, fs, nK, t ): 
166
-    return np.linalg.norm( harmonicEuler(f0, sN, fs, nK, t))
169
+    return np.linalg.norm( harmonicEuler(f0, sN, fs, nK, t) )
167 170
 
168 171
 def harmonic2Norm ( f0, sN, fs, nK, t ): 
169
-    return np.linalg.norm(harmonic2(f0[0], f0[1], sN, fs, nK, t))
172
+    return np.linalg.norm(harmonicEuler2(f0[0], f0[1], sN, fs, nK, t))
170 173
 
171 174
 def minHarmonic(f0, sN, fs, nK, t):
172 175
     f02 = guessf0(sN, fs)
173 176
     print("minHarmonic", f0, fs, nK, " guess=", f02)
174
-    res = minimize( harmonicNorm, np.array((f0)), args=(sN, fs, nK, t)) #, method='Nelder-Mead' )# jac=None, hess=None, bounds=None )
177
+    # CG, BFGS, Newton-CG, L-BFGS-B, TNC, SLSQP, dogleg, trust-ncg, trust-krylov, trust-exact and trust-constr
178
+    res = minimize( harmonicNorm, np.array((f0)), args=(sN, fs, nK, t)) #, method='CG', jac=jacEuler) #, hess=None, bounds=None )
175 179
     print(res)
176 180
     return harmonicEuler(res.x[0], sN, fs, nK, t)
177 181
 
@@ -181,7 +185,7 @@ def minHarmonic2(f1, f2, sN, fs, nK, t):
181 185
     #methods with bounds, L-BFGS-B, TNC, SLSQP
182 186
     res = minimize( harmonic2Norm, np.array((f1,f2)), args=(sN, fs, nK, t)) #, bounds=((f1-1.,f1+1.0),(f2-1.0,f2+1.0)), method='TNC' )
183 187
     print(res)
184
-    return harmonic2(res.x[0], res.x[1], sN, fs, nK, t) 
188
+    return harmonicEuler2(res.x[0], res.x[1], sN, fs, nK, t) 
185 189
 
186 190
 def guessf0( sN, fs ):
187 191
     S = np.fft.fft(sN)
@@ -198,17 +202,17 @@ if __name__ == "__main__":
198 202
     import matplotlib.pyplot as plt 
199 203
 
200 204
     f0 = 60      # Hz
201
-    f1 = 60      # Hz
205
+    f1 = 62      # Hz
202 206
     delta  = np.random.rand() 
203
-    delta2 = 0 #np.random.rand() 
207
+    delta2 =  np.random.rand() 
204 208
     print("delta", delta)
205 209
     fs = 10000   # GMR 
206 210
     t = np.arange(0, 1, 1/fs)
207
-    phi = np.random.rand() 
208
-    phi2 = 0 # np.random.rand() 
211
+    phi =  np.random.rand() 
212
+    phi2 = np.random.rand() 
209 213
     A =  1.0
210
-    A2 = 0.0 
211
-    A3 = 0.0 
214
+    A2 = 0.25 
215
+    A3 = 1.0 
212 216
     nK = 35
213 217
     T2 = .200
214 218
     sN  = A *np.sin( ( 1*(delta  +f0))*2*np.pi*t + phi ) + \
@@ -223,11 +227,14 @@ if __name__ == "__main__":
223 227
 
224 228
     guessf0(sN, fs)
225 229
 
230
+    # single freq
226 231
     #h = harmonicEuler( f0, sN, fs, nK, t) 
227
-    #h = minHarmonic2( f0, f1, sN, fs, nK, t) 
228
-    #h = harmonic2( f0, f1, sN, fs, nK, t) 
232
+    #h = minHarmonic( f0, sN, fs, nK, t) 
229 233
     
230
-    h = minHarmonic( f0, sN, fs, nK, t) 
234
+    # two freqs 
235
+    h = minHarmonic2( f0, f1, sN, fs, nK, t) 
236
+    #h = harmonic2( f0, f1, sN, fs, nK, t) 
237
+    #h = harmonicEuler2( f0, f1, sN, fs, nK, t) 
231 238
 
232 239
     plt.figure()
233 240
     plt.plot(t, sN, label="sN")

+ 5
- 5
akvo/tressel/mrsurvey.py View File

@@ -542,13 +542,13 @@ class GMRDataProcessor(SNMRDataProcessor):
542 542
                             canvas.ax1.plot( self.DATADICT[pulse]["TIMES"], 1e9*self.DATADICT[pulse][ichan][ipm][istack], \
543 543
                                 label = "orig " +  pulse + " ipm=" + str(ipm) + " istack=" + str(istack) + " rchan="  + str(ichan))
544 544
 
545
-                        #self.DATADICT[pulse][ichan][ipm][istack] = harmonic.minHarmonic( f0, self.DATADICT[pulse][ichan][ipm][istack], self.samp, 40, self.DATADICT[pulse]["TIMES"] ) 
545
+                        self.DATADICT[pulse][ichan][ipm][istack] = harmonic.minHarmonic( f0, self.DATADICT[pulse][ichan][ipm][istack], self.samp, 20, self.DATADICT[pulse]["TIMES"] ) 
546 546
                         #self.DATADICT[pulse][ichan][ipm][istack] = harmonic.minHarmonic2( f0-.25, f0+.25, self.DATADICT[pulse][ichan][ipm][istack], self.samp, 20, self.DATADICT[pulse]["TIMES"] ) 
547 547
 
548 548
                         # plot
549
-                        #if plot:
550
-                        #    canvas.ax1.plot( self.DATADICT[pulse]["TIMES"], 1e9*self.DATADICT[pulse][ichan][ipm][istack], \
551
-                        #        label = pulse + " ipm=" + str(ipm) + " istack=" + str(istack) + " rchan="  + str(ichan))
549
+                        if plot:
550
+                            canvas.ax1.plot( self.DATADICT[pulse]["TIMES"], 1e9*self.DATADICT[pulse][ichan][ipm][istack], \
551
+                                label = pulse + " ipm=" + str(ipm) + " istack=" + str(istack) + " rchan="  + str(ichan))
552 552
 
553 553
                     for ichan in self.DATADICT[pulse]["chan"]:
554 554
                         
@@ -556,7 +556,7 @@ class GMRDataProcessor(SNMRDataProcessor):
556 556
                             canvas.ax2.plot( self.DATADICT[pulse]["TIMES"], 1e9*self.DATADICT[pulse][ichan][ipm][istack], \
557 557
                                 label = "orig " +  pulse + " ipm=" + str(ipm) + " istack=" + str(istack) + " chan="  + str(ichan))
558 558
                         
559
-                        self.DATADICT[pulse][ichan][ipm][istack] = harmonic.minHarmonic( f0, self.DATADICT[pulse][ichan][ipm][istack], self.samp, 40, self.DATADICT[pulse]["TIMES"] ) 
559
+                        self.DATADICT[pulse][ichan][ipm][istack] = harmonic.minHarmonic( f0, self.DATADICT[pulse][ichan][ipm][istack], self.samp, 20, self.DATADICT[pulse]["TIMES"] ) 
560 560
                         #self.DATADICT[pulse][ichan][ipm][istack] = harmonic.minHarmonic2( f0-.25, f0+.25, self.DATADICT[pulse][ichan][ipm][istack], self.samp, 20, self.DATADICT[pulse]["TIMES"] ) 
561 561
                         #self.DATADICT[pulse][ichan][ipm][istack] = harmonic.harmonicEuler( f0, self.DATADICT[pulse][ichan][ipm][istack], self.samp, 20, self.DATADICT[pulse]["TIMES"] ) 
562 562
                

Loading…
Cancel
Save