Browse Source

Addition of DOI metric based on incomplete resolution matrix construction

tags/1.6.1
Trevor Irons 2 years ago
parent
commit
15c297b36f
5 changed files with 288 additions and 175 deletions
  1. 2
    0
      akvo/gui/akvoGUI.py
  2. 91
    59
      akvo/gui/main.ui
  3. 189
    112
      akvo/tressel/invertTA.py
  4. 4
    4
      akvo/tressel/logbarrier.py
  5. 2
    0
      akvo/tressel/nonlinearinv.py

+ 2
- 0
akvo/gui/akvoGUI.py View File

@@ -440,6 +440,8 @@ class ApplicationWindow(QtWidgets.QMainWindow):
440 440
         invDict["T2Bins"]["low"] = T2lo
441 441
         invDict["T2Bins"]["high"] = T2hi
442 442
         invDict["T2Bins"]["number"] = NT2       
443
+        invDict["NonLinearRefinement"] = self.ui.NLButton.isChecked()
444
+        invDict["CalcDOI"] = self.ui.DOIButton.isChecked()
443 445
  
444 446
         node = yaml.YAML()
445 447
         kpo = open( "invert.yml", 'w' )

+ 91
- 59
akvo/gui/main.ui View File

@@ -4143,8 +4143,8 @@ background: dark grey;
4143 4143
               <rect>
4144 4144
                <x>0</x>
4145 4145
                <y>0</y>
4146
-               <width>96</width>
4147
-               <height>26</height>
4146
+               <width>100</width>
4147
+               <height>30</height>
4148 4148
               </rect>
4149 4149
              </property>
4150 4150
              <attribute name="label">
@@ -4156,8 +4156,8 @@ background: dark grey;
4156 4156
               <rect>
4157 4157
                <x>0</x>
4158 4158
                <y>0</y>
4159
-               <width>96</width>
4160
-               <height>26</height>
4159
+               <width>411</width>
4160
+               <height>67</height>
4161 4161
               </rect>
4162 4162
              </property>
4163 4163
              <attribute name="label">
@@ -4255,28 +4255,11 @@ background: dark grey;
4255 4255
                <string>QT Inversion</string>
4256 4256
               </property>
4257 4257
               <layout class="QGridLayout" name="gridLayout_19">
4258
-               <item row="2" column="1">
4259
-                <widget class="QComboBox" name="invChan">
4260
-                 <item>
4261
-                  <property name="text">
4262
-                   <string>Chan. 1</string>
4263
-                  </property>
4264
-                 </item>
4265
-                 <item>
4266
-                  <property name="text">
4267
-                   <string>Chan. 2</string>
4268
-                  </property>
4269
-                 </item>
4270
-                 <item>
4271
-                  <property name="text">
4272
-                   <string>Chan. 3</string>
4273
-                  </property>
4274
-                 </item>
4275
-                 <item>
4276
-                  <property name="text">
4277
-                   <string>Chan. 4</string>
4278
-                  </property>
4279
-                 </item>
4258
+               <item row="5" column="0">
4259
+                <widget class="QLabel" name="label_81">
4260
+                 <property name="text">
4261
+                  <string>initial alpha </string>
4262
+                 </property>
4280 4263
                 </widget>
4281 4264
                </item>
4282 4265
                <item row="4" column="1">
@@ -4307,20 +4290,6 @@ background: dark grey;
4307 4290
                  </item>
4308 4291
                 </widget>
4309 4292
                </item>
4310
-               <item row="3" column="0">
4311
-                <widget class="QLabel" name="label_80">
4312
-                 <property name="text">
4313
-                  <string>T2* model objective</string>
4314
-                 </property>
4315
-                </widget>
4316
-               </item>
4317
-               <item row="4" column="0">
4318
-                <widget class="QLabel" name="label_82">
4319
-                 <property name="text">
4320
-                  <string>Depth model objective</string>
4321
-                 </property>
4322
-                </widget>
4323
-               </item>
4324 4293
                <item row="0" column="1">
4325 4294
                 <widget class="QTextBrowser" name="dataText">
4326 4295
                  <property name="maximumSize">
@@ -4337,7 +4306,28 @@ background: dark grey;
4337 4306
                  </property>
4338 4307
                 </widget>
4339 4308
                </item>
4340
-               <item row="6" column="0" colspan="2">
4309
+               <item row="1" column="0">
4310
+                <widget class="QPushButton" name="invKernelButton">
4311
+                 <property name="text">
4312
+                  <string>Select Kernel</string>
4313
+                 </property>
4314
+                </widget>
4315
+               </item>
4316
+               <item row="3" column="0">
4317
+                <widget class="QLabel" name="label_80">
4318
+                 <property name="text">
4319
+                  <string>T2* model objective</string>
4320
+                 </property>
4321
+                </widget>
4322
+               </item>
4323
+               <item row="4" column="0">
4324
+                <widget class="QLabel" name="label_82">
4325
+                 <property name="text">
4326
+                  <string>Depth model objective</string>
4327
+                 </property>
4328
+                </widget>
4329
+               </item>
4330
+               <item row="11" column="0" colspan="2">
4341 4331
                 <widget class="QPushButton" name="invertButton">
4342 4332
                  <property name="styleSheet">
4343 4333
                   <string notr="true">#invertButton {
@@ -4352,24 +4342,50 @@ background: red;
4352 4342
                  </property>
4353 4343
                 </widget>
4354 4344
                </item>
4355
-               <item row="2" column="0">
4356
-                <widget class="QLabel" name="label_79">
4357
-                 <property name="text">
4358
-                  <string>Data channel</string>
4359
-                 </property>
4345
+               <item row="2" column="1">
4346
+                <widget class="QComboBox" name="invChan">
4347
+                 <item>
4348
+                  <property name="text">
4349
+                   <string>Chan. 1</string>
4350
+                  </property>
4351
+                 </item>
4352
+                 <item>
4353
+                  <property name="text">
4354
+                   <string>Chan. 2</string>
4355
+                  </property>
4356
+                 </item>
4357
+                 <item>
4358
+                  <property name="text">
4359
+                   <string>Chan. 3</string>
4360
+                  </property>
4361
+                 </item>
4362
+                 <item>
4363
+                  <property name="text">
4364
+                   <string>Chan. 4</string>
4365
+                  </property>
4366
+                 </item>
4360 4367
                 </widget>
4361 4368
                </item>
4362
-               <item row="0" column="0">
4363
-                <widget class="QPushButton" name="invDataButton">
4369
+               <item row="6" column="0">
4370
+                <widget class="QRadioButton" name="NLButton">
4371
+                 <property name="toolTip">
4372
+                  <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;The dephased (aka quadrature detected, aka corrected amplitude) inversion introduces non-linearity to the otherwise linear forward operator in that out of phase signals cannot destructively interefere with a real forward operator. Normally this impact is pretty minimal and can be ignored. However, in conductive media this is not always the case. Akvo can perform a non-linear inversion after the linear one to correct for this. The result of the linear inversion is used as an initial model in the non-linear inversion and the same level of regularisation is used. &lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
4373
+                 </property>
4364 4374
                  <property name="text">
4365
-                  <string>Select Data</string>
4375
+                  <string>Non Linear refinement</string>
4376
+                 </property>
4377
+                 <property name="checked">
4378
+                  <bool>true</bool>
4379
+                 </property>
4380
+                 <property name="autoExclusive">
4381
+                  <bool>false</bool>
4366 4382
                  </property>
4367 4383
                 </widget>
4368 4384
                </item>
4369
-               <item row="5" column="0">
4370
-                <widget class="QLabel" name="label_81">
4385
+               <item row="2" column="0">
4386
+                <widget class="QLabel" name="label_79">
4371 4387
                  <property name="text">
4372
-                  <string>initial alpha </string>
4388
+                  <string>Data channel</string>
4373 4389
                  </property>
4374 4390
                 </widget>
4375 4391
                </item>
@@ -4383,13 +4399,6 @@ background: red;
4383 4399
                  </property>
4384 4400
                 </widget>
4385 4401
                </item>
4386
-               <item row="1" column="0">
4387
-                <widget class="QPushButton" name="invKernelButton">
4388
-                 <property name="text">
4389
-                  <string>Select Kernel</string>
4390
-                 </property>
4391
-                </widget>
4392
-               </item>
4393 4402
                <item row="1" column="1">
4394 4403
                 <widget class="QTextEdit" name="kernelText">
4395 4404
                  <property name="maximumSize">
@@ -4406,6 +4415,29 @@ background: red;
4406 4415
                  </property>
4407 4416
                 </widget>
4408 4417
                </item>
4418
+               <item row="0" column="0">
4419
+                <widget class="QPushButton" name="invDataButton">
4420
+                 <property name="text">
4421
+                  <string>Select Data</string>
4422
+                 </property>
4423
+                </widget>
4424
+               </item>
4425
+               <item row="6" column="1">
4426
+                <widget class="QRadioButton" name="DOIButton">
4427
+                 <property name="toolTip">
4428
+                  <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Geophysical inverse problems do not have a true, unambigous depth of investigation. &lt;/p&gt;&lt;p&gt;&lt;br/&gt;&lt;/p&gt;&lt;p&gt;Akvo makes a calculation of the DOI based on a resolution analysis approach. A pseudo 1D total water point spread function is calculated by inverting kronecker delta models at the midpoint of the &lt;span style=&quot; font-style:italic;&quot;&gt;T&lt;/span&gt;&lt;span style=&quot; font-style:italic; vertical-align:sub;&quot;&gt;2&lt;/span&gt;&lt;span style=&quot; font-style:italic; vertical-align:super;&quot;&gt;*&lt;/span&gt; distribution at he same regularisation level as the inversion. The recovered models are summed across the &lt;span style=&quot; font-style:italic;&quot;&gt;T&lt;/span&gt;&lt;span style=&quot; font-style:italic; vertical-align:sub;&quot;&gt;2&lt;/span&gt;&lt;span style=&quot; font-style:italic; vertical-align:super;&quot;&gt;*&lt;/span&gt; space in order to reduce variables in the analysis. hese models are then used as rows in the construction of the point spread function (Model Resolution Matrix). The point spread function is used to identify the point at which the peak depth in the recovered models deviates from the input model by at least 10 %. This is an arbitrary threshold, but is the same one used in[1] &lt;/p&gt;&lt;p&gt;&lt;br/&gt;&lt;/p&gt;&lt;p&gt;[1] Müller-Petke, M., &amp;amp; Yaramanci, U. (2008). Resolution studies for magnetic resonance sounding (MRS) using the singular value decomposition. &lt;span style=&quot; font-style:italic;&quot;&gt;Journal of Applied Geophysics&lt;/span&gt;, &lt;span style=&quot; font-style:italic;&quot;&gt;66&lt;/span&gt;(3-4), 165-175.   &lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
4429
+                 </property>
4430
+                 <property name="text">
4431
+                  <string>Calculate DOI</string>
4432
+                 </property>
4433
+                 <property name="checked">
4434
+                  <bool>true</bool>
4435
+                 </property>
4436
+                 <property name="autoExclusive">
4437
+                  <bool>false</bool>
4438
+                 </property>
4439
+                </widget>
4440
+               </item>
4409 4441
               </layout>
4410 4442
              </widget>
4411 4443
             </item>

+ 189
- 112
akvo/tressel/invertTA.py View File

@@ -7,6 +7,12 @@ from pylab import meshgrid
7 7
 from akvo.tressel.logbarrier import *
8 8
 import yaml,os
9 9
 
10
+import multiprocessing 
11
+import itertools
12
+ 
13
+from scipy.linalg import svd 
14
+
15
+from matplotlib.backends.backend_pdf import PdfPages
10 16
 from matplotlib.colors import LogNorm
11 17
 from matplotlib.colors import LightSource
12 18
 from matplotlib.ticker import ScalarFormatter
@@ -134,46 +140,28 @@ def main():
134 140
         K0[0] = np.concatenate( (K0[0].T, K0[ik].T) ).T
135 141
     K0 = K0[0]
136 142
 
143
+    #np.save("ifaces", ifaces)
144
+    #exit()
145
+
137 146
     #plt.matshow(np.real(K0))
138 147
     #plt.show()
139 148
     #exit()
140 149
 
141
-    ###################    
142
-    # VERY Simple DOI #
150
+    ##########################################################    
151
+    # VERY Simple Sensitivity based calc. of noise per layer #
143 152
     maxq = np.argmax(np.abs(K0), axis=1)
144 153
     maxK = .1 *  np.abs(K0)[ np.arange(0,len(ifaces)-1), maxq ] # 10% water is arbitrary  
145 154
     SNR = maxK / (VS[0][0])
146 155
 
147
-    #SNR[SNR>1] = 1
148
-    SNRidx = len(ifaces)-3 
149
-    while SNR[SNRidx] > SNR[SNRidx+1] and SNRidx > 2:
150
-        SNRidx -= 1
151
-
152
-    #print("IDX", SNRidx)
153
-    #plt.plot(ifaces[0:-1], SNR)
154
-    #plt.plot(ifaces[0:-1][SNRidx], SNR[SNRidx], '.',markersize=12)
155
-    #plt.gca().axhline(y=VS[0][0], xmin=0, xmax=ifaces[-1], color='r')
156
-    #plt.gca().axhline(y=1, xmin=0, xmax=ifaces[-1], color='r')
157
-    #K0T = np.dot(K0, K0.T) 
158
-    #K0T = np.dot(K0, np.dot( VS[0][0]* np.eye(len(ifaces)-1,1), K0.T) )
159
-    #K0T = np.dot(K0, np.dot( 1/(VS[0][0]**2) * np.eye(np.shape(K0)[1]), K0.T) )
160
-    #plt.matshow(0.05 * np.sqrt(K0T))
161
-    #plt.colorbar()
162
-    #plt.plot(ifaces[0:-1], np.diag( 0.01* np.sqrt(K0T))) 
163
-    #print(np.shape(K0T), len(ifaces)-1)
164
-    #plt.show()
165
-    #exit()
166
-
167 156
     ###############################################
168 157
     # Build full kernel
169 158
     ############################################### 
170
-    T2Bins = np.logspace( np.log10(cont["T2Bins"]["low"]), np.log10(cont["T2Bins"]["high"]), cont["T2Bins"]["number"], endpoint=True, base=10)  
171
-    KQT = np.real(buildKQT(np.abs(K0),tg,T2Bins))
172 159
 
173
-    # model resolution matrix 
174
-    np.linalg.svd(KQT)
160
+    T2Bins = np.logspace( np.log10(cont["T2Bins"]["low"]), np.log10(cont["T2Bins"]["high"]), cont["T2Bins"]["number"], endpoint=True, base=10) 
161
+    T2Bins2 = np.append( T2Bins, T2Bins[-1] + (T2Bins[-1]-T2Bins[-2]) )
162
+    NT2 = len(T2Bins)
175 163
 
176
-    exit()
164
+    KQT = np.real(buildKQT(np.abs(K0),tg,T2Bins))
177 165
 
178 166
     ###############################################
179 167
     # Linear Inversion 
@@ -181,66 +169,148 @@ def main():
181 169
     print("Calling inversion", flush=True)
182 170
     inv, ibreak, errn, phim, phid, mkappa, Wd, Wm, alphastar = logBarrier(KQT, np.ravel(V), T2Bins, "lcurve", MAXITER=150, sigma=np.ravel(VS), alpha=1e6, smooth="Smallest" ) 
183 171
 
184
-    ###############################################
185
-    # Non-linear refinement! 
186
-    ###############################################   
187
- 
188
-    KQTc = buildKQT(K0, tg, T2Bins)
189
-    prec = np.abs(np.dot(KQTc, inv))
190
-    phidc = np.linalg.norm(np.dot(Wd,prec-np.ravel(V)))**2
191
-    #PREc = np.reshape( prec, np.shape(V)  )
192
-    print("PHID linear=", errn, "PHID complex=", phidc/len(np.ravel(V)))
193
-    
194
-    res = nl.nonlinearinversion(inv, Wd, KQTc, np.ravel(V), Wm, alphastar )   
195
-    if res.success == True:    
196
-        INVc = np.reshape(res.x, (len(ifaces)-1,cont["T2Bins"]["number"]) )
197
-        prec = np.abs(np.dot(KQTc, res.x))
198
-        phidc = np.linalg.norm(np.dot(Wd,prec-np.ravel(V)))**2
199
-        #PREc = np.reshape( prec, np.shape(V)  )
200
-        print("PHID linear=", errn, "PHID nonlinear=", phidc/len(np.ravel(V)))
201
-   
202
-    # Perform second fit around results of first  
203
-    res = nl.nonlinearinversion(res.x, Wd, KQTc, np.ravel(V), Wm, alphastar )   
204
-    if res.success == True:    
205
-        INVc = np.reshape(res.x, (len(ifaces)-1,cont["T2Bins"]["number"]) )
206
-        prec = np.abs(np.dot(KQTc, res.x))
207
-        phidc = np.linalg.norm(np.dot(Wd,prec-np.ravel(V)))**2
208
-        #PREc = np.reshape( prec, np.shape(V)  )
209
-        print("PHID linear=", errn, "PHID nonlinear=", phidc/len(np.ravel(V)))
210
-
211
-    #plt.matshow(INVc)
212
-    #KQTc = buildKQT(K0,tg,T2Bins)
213
-
214
-    #plt.matshow(PREc, cmap='Blues')
215
-    #plt.gca().set_title("complex predicted")
216
-    #plt.colorbar()
217
-
218
-    ###############################################
219
-    # Appraise
220
-    ###############################################
221
-
222 172
 
223
-
224
-
225
- 
173
+    ####################
174
+    # Summary plots    #
175
+    ####################
176
+    
226 177
     pre = np.dot(KQT,inv) 
227 178
     PRE = np.reshape( pre, np.shape(V)  )
228 179
     plt.matshow(PRE, cmap='Blues')
229
-    plt.gca().set_title("predicted")
180
+    plt.gca().set_title("linear predicted")
230 181
     plt.colorbar()
231 182
 
232 183
     DIFF = (PRE-V) / VS
233 184
     md = np.max(np.abs(DIFF))
234 185
     plt.matshow(DIFF, cmap=cmocean.cm.balance, vmin=-md, vmax=md)
235
-    plt.gca().set_title("misfit / $\widehat{\sigma}$")
186
+    plt.gca().set_title("linear misfit / $\widehat{\sigma}$")
236 187
     plt.colorbar()
237 188
     
238 189
     plt.matshow(V, cmap='Blues')
239 190
     plt.gca().set_title("observed")
240 191
     plt.colorbar()
241 192
 
193
+    ###############################################
194
+    # Non-linear refinement! 
195
+    ###############################################   
196
+
197
+    nonLinearRefinement = cont['NonLinearRefinement']
198
+    if nonLinearRefinement: 
199
+
200
+        KQTc = buildKQT(K0, tg, T2Bins)
201
+        prec = np.abs(np.dot(KQTc, inv))
202
+        phidc = np.linalg.norm(np.dot(Wd,prec-np.ravel(V)))**2
203
+        print("PHID forward linear=", errn, "PHID forward nonlinear=", phidc/len(np.ravel(V)))
204
+    
205
+        res = nl.nonlinearinversion(inv, Wd, KQTc, np.ravel(V), Wm, alphastar )   
206
+        if res.success == True:    
207
+            INVc = np.reshape(res.x, (len(ifaces)-1,cont["T2Bins"]["number"]) )
208
+            prec = np.abs(np.dot(KQTc, res.x))
209
+            phidc = np.linalg.norm(np.dot(Wd,prec-np.ravel(V)))**2
210
+            PREc = np.reshape( prec, np.shape(V)  )
211
+            print("PHID linear=", errn, "PHID nonlinear=", phidc/len(np.ravel(V)))
212
+
213
+        while phidc/len(np.ravel(V)) > errn:  
214
+            phidc_old = phidc/len(np.ravel(V))
215
+            #alphastar *= .9 
216
+            res = nl.nonlinearinversion(res.x, Wd, KQTc, np.ravel(V), Wm, alphastar )   
217
+            if res.success == True:    
218
+                INVc = np.reshape(res.x, (len(ifaces)-1,cont["T2Bins"]["number"]) )
219
+                prec = np.abs(np.dot(KQTc, res.x))
220
+                phidc = np.linalg.norm(np.dot(Wd,prec-np.ravel(V)))**2
221
+                PREc = np.reshape( prec, np.shape(V)  )
222
+                print("PHID linear=", errn, "PHID nonlinear=", phidc/len(np.ravel(V)))
223
+            else:
224
+                break
225
+
226
+            if phidc_old - phidc/len(np.ravel(V)) < 0.005:
227
+                print("Not making progress reducing misfit in nonlinear refinement")
228
+                break
229
+    
230
+        plt.matshow(PREc, cmap='Blues')
231
+        plt.gca().set_title("nonlinear predicted")
232
+        plt.colorbar()
233
+
234
+        DIFFc = (PREc-V) / VS
235
+        md = np.max(np.abs(DIFF))
236
+        plt.matshow(DIFFc, cmap=cmocean.cm.balance, vmin=-md, vmax=md)
237
+        plt.gca().set_title("nonlinear misfit / $\widehat{\sigma}$")
238
+        plt.colorbar()
239
+ 
240
+    ###############################################
241
+    # Appraise DOI using simplified MRM 
242
+    ###############################################
243
+
244
+    CalcDOI = cont['CalcDOI']
245
+
246
+    if CalcDOI:
247
+    
248
+        pdf = PdfPages('resolution_analysis' + '.pdf' )
249
+        MRM = np.zeros((len(ifaces)-1, len(ifaces)-1))
250
+
251
+    #with multiprocessing.Pool() as pool: 
252
+    #    invresults = pool.starmap(invert, zip(itertools.repeat(Time), GT[0:ni], GD[0:ni], SIG[0:ni], itertools.repeat(sys.argv[3]) )) 
253
+ 
254
+        # This could be parallelized 
255
+        for ilay in range(len(ifaces)-1):
256
+            iDeltaT2 = len(T2Bins)//2
257
+            deltaMod = np.zeros( (len(ifaces)-1, len(T2Bins)) )
258
+            deltaMod[ilay][iDeltaT2] = 0.3
259
+            dV = np.dot(KQT, np.ravel(deltaMod)) 
260
+            # invert 
261
+            dinv, dibreak, derrn = logBarrier(KQT, dV, T2Bins, "single", MAXITER=1, sigma=np.ravel(VS), alpha=alphastar, smooth="Smallest" ) 
262
+            print("Sum dinv from", str(ifaces[ilay]), "to", str(ifaces[ilay+1]), "=", np.sum(dinv))
263
+    
264
+            DINV = np.reshape(dinv, (len(ifaces)-1,cont["T2Bins"]["number"]) )
265
+            MRM[ilay,:] = np.sum(DINV, axis=1)
266
+
267
+            Y,X = meshgrid( ifaces, T2Bins2 )
268
+            fig = plt.figure( figsize=(pc2in(20.0),pc2in(22.)) )
269
+            ax1 = fig.add_axes( [.2,.15,.6,.7] )
270
+            im = ax1.pcolor(X, Y, DINV.T, cmap=cmocean.cm.tempo, shading='auto')
271
+            ax1.plot( T2Bins[iDeltaT2], (ifaces[ilay]+ifaces[ilay+1])/2, 's', markersize=6, markeredgecolor='black') #, markerfacecolor=None )  
272
+            im.set_edgecolor('face')
273
+            ax1.set_xlabel(u"$T_2^*$ (ms)")
274
+            ax1.set_ylabel(u"depth (m)")
275
+            ax1.set_xlim( T2Bins2[0], T2Bins2[-1] )
276
+            ax1.set_ylim( ifaces[-1], ifaces[0] )
277
+
278
+            ax2 = ax1.twiny()
279
+            ax2.plot( np.sum(DINV, axis=1), (ifaces[1:]+ifaces[0:-1])/2 ,  color='red' )
280
+            ax2.set_xlabel(u"total water (m$^3$/m$^3$)")
281
+            ax2.set_ylim( ifaces[-1], ifaces[0] )
282
+            ax2.xaxis.set_major_locator( MaxNLocator(nbins = 3) )   
283
+            ax2.get_xaxis().set_major_formatter(FormatStrFormatter('%0.2f'))
284
+
285
+            pdf.savefig(facecolor=[0,0,0,0])
286
+            plt.close(fig)
287
+
288
+        np.save("MRM", MRM)
289
+        centres = (ifaces[0:-1]+ifaces[1:])/2
290
+        X,Y = np.meshgrid(ifaces,ifaces)
291
+
292
+        fig = plt.figure( figsize=(pc2in(20.0),pc2in(22.)) )
293
+        ax1 = fig.add_axes( [.2,.15,.6,.7] )
294
+        ax1.pcolor(X,Y,MRM, cmap = cmocean.cm.ice)
295
+        ax1.set_ylim(ifaces[-1], ifaces[0])
296
+        maxDepth = np.argmax(MRM, axis=0)
297
+
298
+        plt.plot(centres[maxDepth], centres, color='white')
299
+
300
+        # Determine DOI 
301
+        DOIMetric =  centres[maxDepth]/centres #> 0.9 
302
+        DOI = ifaces[ np.where(DOIMetric < 0.9 ) ][0]
303
+        plt.axhline(y=DOI, color='white', linestyle='-.')
304
+
305
+        ax1.set_ylim( ifaces[-1], ifaces[0] )
306
+        ax1.set_xlim( ifaces[0], ifaces[-1] )
307
+        ax1.set_xlabel(u"depth (m)")
308
+        ax1.set_ylabel(u"depth (m)")
309
+
310
+        pdf.close()
311
+
312
+
242 313
 
243
-    T2Bins = np.append( T2Bins, T2Bins[-1] + (T2Bins[-1]-T2Bins[-2]) )
244 314
     INV = np.reshape(inv, (len(ifaces)-1,cont["T2Bins"]["number"]) )
245 315
 
246 316
     #alphas = np.tile(SNR, (len(T2Bins)-1,1))
@@ -254,7 +324,7 @@ def main():
254 324
 
255 325
     ##############  LINEAR RESULT   ##########################
256 326
 
257
-    Y,X = meshgrid( ifaces, T2Bins )
327
+    Y,X = meshgrid( ifaces, T2Bins2 )
258 328
     fig = plt.figure( figsize=(pc2in(20.0),pc2in(22.)) )
259 329
     ax1 = fig.add_axes( [.2,.15,.6,.7] )
260 330
     im = ax1.pcolor(X, Y, INV.T, cmap=cmocean.cm.tempo) #cmap='viridis')
@@ -264,7 +334,7 @@ def main():
264 334
     #im = ax1.pcolormesh(X, Y, INV.T, alpha=alphas) #, cmap=cmocean.cm.tempo) #cmap='viridis')
265 335
     #ax1.axhline( y=ifaces[SNRidx], xmin=T2Bins[0], xmax=T2Bins[-1], color='black'  )
266 336
     im.set_edgecolor('face')
267
-    ax1.set_xlim( T2Bins[0], T2Bins[-1] )
337
+    ax1.set_xlim( T2Bins[0], T2Bins2[-1] )
268 338
     ax1.set_ylim( ifaces[-1], ifaces[0] )
269 339
     cb = plt.colorbar(im, label = u"PWC (m$^3$/m$^3$)") #, format='%1.1f')
270 340
     cb.locator = MaxNLocator( nbins = 4)
@@ -286,7 +356,9 @@ def main():
286 356
     ax2.set_ylim( ifaces[-1], ifaces[0] )
287 357
     ax2.xaxis.set_major_locator( MaxNLocator(nbins = 3) )   
288 358
     ax2.get_xaxis().set_major_formatter(FormatStrFormatter('%0.2f'))
289
-    ax2.axhline( y=ifaces[SNRidx], xmin=0, xmax=1, color='black', linestyle='dashed'  )
359
+    #ax2.axhline( y=ifaces[SNRidx], xmin=0, xmax=1, color='black', linestyle='dashed'  )
360
+    if CalcDOI:
361
+        ax2.axhline( y=DOI, xmin=0, xmax=1, color='black', linestyle='dashed'  )
290 362
     #ax2.xaxis.set_label_position('bottom') 
291 363
 
292 364
     plt.savefig("akvoInversion.pdf")
@@ -294,44 +366,45 @@ def main():
294 366
 
295 367
     ##############  NONLINEAR RESULT   ##########################
296 368
 
297
-    Y,X = meshgrid( ifaces, T2Bins )
298
-    fig = plt.figure( figsize=(pc2in(20.0),pc2in(22.)) )
299
-    ax1 = fig.add_axes( [.2,.15,.6,.7] )
300
-    im = ax1.pcolor(X, Y, INVc.T, cmap=cmocean.cm.tempo) #cmap='viridis')
301
-    #im = ax1.pcolor(X[0:SNRidx,:], Y[0:SNRidx,:], INV.T[0:SNRidx,:], cmap=cmocean.cm.tempo) #cmap='viridis')
302
-    #im = ax1.pcolor(X[SNRidx::,:], Y[SNRidx::,:], INV.T[SNRidx::,:], cmap=cmocean.cm.tempo, alpha=.5) #cmap='viridis')
303
-    #im = ax1.pcolormesh(X, Y, INV.T, alpha=alphas) #, cmap=cmocean.cm.tempo) #cmap='viridis')
304
-    #im = ax1.pcolormesh(X, Y, INV.T, alpha=alphas) #, cmap=cmocean.cm.tempo) #cmap='viridis')
305
-    #ax1.axhline( y=ifaces[SNRidx], xmin=T2Bins[0], xmax=T2Bins[-1], color='black'  )
306
-    im.set_edgecolor('face')
307
-    ax1.set_xlim( T2Bins[0], T2Bins[-1] )
308
-    ax1.set_ylim( ifaces[-1], ifaces[0] )
309
-    cb = plt.colorbar(im, label = u"PWC (m$^3$/m$^3$)") #, format='%1.1f')
310
-    cb.locator = MaxNLocator( nbins = 4)
311
-    cb.ax.yaxis.set_offset_position('left')                         
312
-    cb.update_ticks()
369
+    if nonLinearRefinement: 
370
+        Y,X = meshgrid( ifaces, T2Bins )
371
+        fig = plt.figure( figsize=(pc2in(20.0),pc2in(22.)) )
372
+        ax1 = fig.add_axes( [.2,.15,.6,.7] )
373
+        im = ax1.pcolor(X, Y, INVc.T, cmap=cmocean.cm.tempo) #cmap='viridis')
374
+        #im = ax1.pcolor(X[0:SNRidx,:], Y[0:SNRidx,:], INV.T[0:SNRidx,:], cmap=cmocean.cm.tempo) #cmap='viridis')
375
+        #im = ax1.pcolor(X[SNRidx::,:], Y[SNRidx::,:], INV.T[SNRidx::,:], cmap=cmocean.cm.tempo, alpha=.5) #cmap='viridis')
376
+        #im = ax1.pcolormesh(X, Y, INV.T, alpha=alphas) #, cmap=cmocean.cm.tempo) #cmap='viridis')
377
+        #im = ax1.pcolormesh(X, Y, INV.T, alpha=alphas) #, cmap=cmocean.cm.tempo) #cmap='viridis')
378
+        #ax1.axhline( y=ifaces[SNRidx], xmin=T2Bins[0], xmax=T2Bins[-1], color='black'  )
379
+        im.set_edgecolor('face')
380
+        ax1.set_xlim( T2Bins[0], T2Bins[-1] )
381
+        ax1.set_ylim( ifaces[-1], ifaces[0] )
382
+        cb = plt.colorbar(im, label = u"PWC (m$^3$/m$^3$)") #, format='%1.1f')
383
+        cb.locator = MaxNLocator( nbins = 4)
384
+        cb.ax.yaxis.set_offset_position('left')                         
385
+        cb.update_ticks()
313 386
  
314
-    ax1.set_xlabel(u"$T_2^*$ (ms)")
315
-    ax1.set_ylabel(u"depth (m)")
387
+        ax1.set_xlabel(u"$T_2^*$ (ms)")
388
+        ax1.set_ylabel(u"depth (m)")
316 389
     
317
-    ax1.get_xaxis().set_major_formatter(FormatStrFormatter('%1.0f'))
318
-    ax1.get_yaxis().set_major_formatter(FormatStrFormatter('%1.0f'))
319
-    ax1.xaxis.set_major_locator( MaxNLocator(nbins = 4) )   
320
-
321
-    #ax1.xaxis.set_label_position('top') 
322
-
323
-    ax2 = ax1.twiny()
324
-    ax2.plot( np.sum(INVc, axis=1), (ifaces[1:]+ifaces[0:-1])/2 ,  color='red' )
325
-    ax2.set_xlabel(u"total water (m$^3$/m$^3$)")
326
-    ax2.set_ylim( ifaces[-1], ifaces[0] )
327
-    ax2.xaxis.set_major_locator( MaxNLocator(nbins = 3) )   
328
-    ax2.get_xaxis().set_major_formatter(FormatStrFormatter('%0.2f'))
329
-    #ax2.axhline( y=ifaces[SNRidx], xmin=0, xmax=1, color='black', linestyle='dashed'  )
330
-    #ax2.xaxis.set_label_position('bottom') 
331
-    fig.suptitle("Non linear inversion")
332
-    plt.savefig("akvoInversionNL.pdf")
333
-
334
-
390
+        ax1.get_xaxis().set_major_formatter(FormatStrFormatter('%1.0f'))
391
+        ax1.get_yaxis().set_major_formatter(FormatStrFormatter('%1.0f'))
392
+        ax1.xaxis.set_major_locator( MaxNLocator(nbins = 4) )   
393
+
394
+        #ax1.xaxis.set_label_position('top') 
395
+
396
+        ax2 = ax1.twiny()
397
+        ax2.plot( np.sum(INVc, axis=1), (ifaces[1:]+ifaces[0:-1])/2 ,  color='red' )
398
+        ax2.set_xlabel(u"total water (m$^3$/m$^3$)")
399
+        ax2.set_ylim( ifaces[-1], ifaces[0] )
400
+        ax2.xaxis.set_major_locator( MaxNLocator(nbins = 3) )   
401
+        ax2.get_xaxis().set_major_formatter(FormatStrFormatter('%0.2f'))
402
+        #ax2.axhline( y=ifaces[SNRidx], xmin=0, xmax=1, color='black', linestyle='dashed'  )
403
+        if CalcDOI:
404
+            ax2.axhline( y=DOI, xmin=0, xmax=1, color='black', linestyle='dashed'  )
405
+        #ax2.xaxis.set_label_position('bottom') 
406
+        fig.suptitle("Non linear inversion")
407
+        plt.savefig("akvoInversionNL.pdf")
335 408
 
336 409
     #############
337 410
     # water plot#
@@ -340,7 +413,7 @@ def main():
340 413
     ax = fig2.add_axes( [.2,.15,.6,.7] )
341 414
     
342 415
     # Bound water cutoff 
343
-    Bidx = T2Bins[0:-1]<33.0
416
+    Bidx = T2Bins<33.0
344 417
     twater = np.sum(INV, axis=1)
345 418
     bwater = np.sum(INV[:,Bidx], axis=1)
346 419
     
@@ -357,18 +430,22 @@ def main():
357 430
     ax.set_xlim( 0, ax.get_xlim()[1] )
358 431
     
359 432
     #ax.axhline( y=ifaces[SNRidx], xmin=0, xmax=1, color='black', linestyle='dashed'  )
433
+    if CalcDOI:
434
+        ax.axhline( y=DOI, xmin=0, xmax=1, color='black', linestyle='dashed'  )
360 435
     
361 436
     plt.savefig("akvoInversionWC.pdf")
362 437
     plt.legend()  
363 438
  
364 439
 
365 440
     # Report results into a text file 
366
-    fr = pd.DataFrame( INV, columns=T2Bins[0:-1] )
441
+    fr = pd.DataFrame( INV, columns=T2Bins ) #[0:-1] )
367 442
     fr.insert(0, "layer top", ifaces[0:-1] )
368 443
     fr.insert(1, "layer bottom", ifaces[1::] )
369 444
     fr.insert(2, "NMR total water", np.sum(INV, axis=1) )
370 445
     fr.insert(3, "NMR bound water", bwater )
371 446
     fr.insert(4, "Layer SNR", SNR )
447
+    if CalcDOI:
448
+        fr.insert(5, "Resolution", DOIMetric )
372 449
 
373 450
     fr.to_csv("akvoInversion.csv")    
374 451
     #fr.to_excel("akvoInversion.xlsx")    

+ 4
- 4
akvo/tressel/logbarrier.py View File

@@ -291,9 +291,9 @@ def logBarrier(A, b, T2Bins, lambdastar, x_0=0, xr=0, alpha=10, mu1=10, mu2=10,
291 291
 
292 292
     if (i == MAXITER-1 ):
293 293
         ibreak = 2
294
-        print("Reached max iterations!!", alpha, np.sqrt(phid/len(b)), ibreak)
295
-        kappa = curvaturefd(np.log(np.array(PHIM)), np.log(np.array(PHID)), ALPHA[0:-1])
296
-        x = MOD[ np.argmax(kappa) ]
294
+        #print("Reached max iterations!!", alpha, np.sqrt(phid/len(b)), ibreak)
295
+        #kappa = curvaturefd(np.log(np.array(PHIM)), np.log(np.array(PHID)), ALPHA[0:-1])
296
+        x = MOD[-1]
297 297
         b_pre = np.dot(A, x)
298 298
         phid = np.linalg.norm( np.dot(Wd, (b-b_pre)))**2
299 299
         phim = np.linalg.norm( np.dot(Phim_base, (x-xr)) )**2
@@ -303,7 +303,7 @@ def logBarrier(A, b, T2Bins, lambdastar, x_0=0, xr=0, alpha=10, mu1=10, mu2=10,
303 303
         #print("Returning L curve result")
304 304
         return x, ibreak, np.sqrt(phid/len(b)), PHIM, PHID/len(b), np.argmax(kappa), Wd, Phim_base, alphastar
305 305
     else:
306
-        print("")
306
+        print("Returning max iteration result")
307 307
         return x, ibreak, np.sqrt(phid/len(b))
308 308
 
309 309
 

+ 2
- 0
akvo/tressel/nonlinearinv.py View File

@@ -38,6 +38,8 @@ def nonlinearinversion( x0, Wd, K, d_obs, Wm, alphastar):
38 38
     bounds = np.zeros((len(x0),2))
39 39
     bounds[:,0] = x0*0.75
40 40
     bounds[:,1] = x0*1.25
41
+    #bounds[:,0] = 0
42
+    #bounds[:,1] = np.max(x0)*1.25
41 43
     return so.minimize(PHI, x0, args, 'L-BFGS-B', bounds=bounds)     # Works well 
42 44
     #return so.minimize(PHI, x0, args, 'Powell', bounds=bounds)       # Slow but works 
43 45
     #return so.minimize(PHI, x0, args, 'trust-constr', bounds=bounds) # very Slow 

Loading…
Cancel
Save