from akvo.tressel.SlidesPlot import * import numpy as np import sys import matplotlib.pyplot as plt import cmocean from pylab import meshgrid from akvo.tressel.logbarrier import * import yaml,os import multiprocessing import itertools from scipy.linalg import svd from matplotlib.backends.backend_pdf import PdfPages from matplotlib.colors import LogNorm from matplotlib.colors import LightSource from matplotlib.ticker import ScalarFormatter from matplotlib.ticker import MaxNLocator from matplotlib.ticker import AutoMinorLocator from matplotlib.ticker import LogLocator from matplotlib.ticker import FormatStrFormatter from matplotlib.colors import Normalize import cmocean from akvo.tressel.lemma_yaml import * from akvo.tressel import nonlinearinv as nl import pandas as pd # For Mihai, but consider letting fonts be user selected. #import matplotlib.pyplot as plt #plt.rcParams["font.family"] = "arial" import matplotlib.colors as colors # From https://stackoverflow.com/questions/18926031/how-to-extract-a-subset-of-a-colormap-as-a-new-colormap-in-matplotlib def truncate_colormap(cmap, minval=0.0, maxval=1.0, n=100): new_cmap = colors.LinearSegmentedColormap.from_list( 'trunc({n},{a:.2f},{b:.2f})'.format(n=cmap.name, a=minval, b=maxval), cmap(np.linspace(minval, maxval, n))) return new_cmap def buildKQT(K0,tg,T2Bins): """ Constructs a QT inversion kernel from an initial amplitude one. """ nlay, nq = np.shape(K0) nt2 = len(T2Bins) nt = len(tg) KQT = np.zeros( ( nq*nt,nt2*nlay), dtype=np.complex128 ) for iq in range(nq): for it in range(nt): for ilay in range(nlay): for it2 in range(nt2): #KQT[iq*nt + it,ilay*nt2+it2] = K0[ilay,iq]*np.exp(-((10+tg[it])*1e-3)/(1e-3*T2Bins[it2])) KQT[iq*nt + it,ilay*nt2+it2] = K0[ilay,iq]*np.exp(-((10+tg[it])*1e-3)/(1e-3*T2Bins[it2])) return KQT def loadAkvoData(fnamein, chan): """ Loads data from an Akvo YAML file. The 0.02 is hard coded as the pulse length. This needs to be corrected in future kernel calculations. The current was reported but not the pulse length. """ fname = (os.path.splitext(fnamein)[0]) with open(fnamein, 'r') as stream: try: AKVO = (yaml.load(stream, Loader=yaml.Loader)) except yaml.YAMLError as exc: print(exc) exit() Z = np.zeros( (AKVO.nPulseMoments, AKVO.Gated["Pulse 1"]["abscissa"].size ) ) ZS = np.zeros( (AKVO.nPulseMoments, AKVO.Gated["Pulse 1"]["abscissa"].size ) ) for q in range(AKVO.nPulseMoments): Z[q] = AKVO.Gated["Pulse 1"][chan]["Q-"+str(q) + " CA"].data if chan == "Chan. 1": ZS[q] = AKVO.Gated["Pulse 1"][chan]["STD"].data elif chan == "Chan. 2": ZS[q] = AKVO.Gated["Pulse 1"][chan]["STD"].data elif chan == "Chan. 3": ZS[q] = AKVO.Gated["Pulse 1"][chan]["STD"].data elif chan == "Chan. 4": ZS[q] = AKVO.Gated["Pulse 1"][chan]["STD"].data else: print("DOOM!!!") exit() #Z *= 1e-9 #ZS *= 1e-9 J = np.array(AKVO.Pulses["Pulse 1"]["current"].data) #J = np.append(J,J[-1]+(J[-1]-J[-2])) # This was a pcolor hack, get rid of this #print("J", J) Q = AKVO.pulseLength[0]*J return Z, ZS, AKVO.Gated["Pulse 1"]["abscissa"].data, Q def catLayers(K0): K = np.zeros( (len(K0.keys()), len(K0["layer-0"].data)) , dtype=complex ) for lay in range(len(K0.keys())): #print(K0["layer-"+str(lay)].data) # print (lay) K[lay] =K0["layer-"+str(lay)].data # print (lay) return 1e9*K # invert in nV def loadK0(fname): """ Loads in initial amplitude kernel """ print("loading K0", fname) with open(fname) as f: K0 = yaml.load(f, Loader=yaml.Loader) K = catLayers(K0.K0) ifaces = np.array(K0.Interfaces.data) return ifaces, K #return ifaces, np.abs(K) def invertDelta(G, V_n, T2Bins, sig, alphastar): """ helper function that simply calls logBarrier, simplfies parallel execution """ model = logBarrier(G, V_n, T2Bins, "Single", MAXITER=1, sigma=sig, alpha=alphastar, smooth="Smallest") return model def main(): if (len (sys.argv) < 2): print ("akvoQT invertParameters.yaml") exit() with open(sys.argv[1], 'r') as stream: try: cont = (yaml.load(stream, Loader=yaml.Loader)) except yaml.YAMLError as exc: print(exc) exit(1) ############################################### # Load in data ############################################### V = [] VS = [] QQ = [] tg = 0 for dat in cont['data']: for ch in cont['data'][dat]['channels']: print("dat", dat, "ch", ch) v,vs,tg,Q = loadAkvoData(dat, ch) V.append(v) VS.append(vs) QQ.append(Q) for iv in range(1, len(V)): V[0] = np.concatenate( (V[0], V[iv]) ) VS[0] = np.concatenate( (VS[0], VS[iv]) ) V = V[0] VS = VS[0] ############################################### # Load in kernels ############################################### K0 = [] for kern in cont["K0"]: ifaces,k0 = loadK0( kern ) K0.append(k0) for ik in range(1, len(K0)): K0[0] = np.concatenate( (K0[0].T, K0[ik].T) ).T K0 = K0[0] #np.save("ifaces", ifaces) #exit() #plt.matshow(np.real(K0)) #plt.show() #exit() ############################################################## # VERY Simple Sensitivity based calc. of noise per layer # # minimally useful, but retained for backwards compatibility # maxq = np.argmax(np.abs(K0), axis=1) maxK = .1 * np.abs(K0)[ np.arange(0,len(ifaces)-1), maxq ] # 10% water is arbitrary SNR = maxK / (VS[0][0]) ############################################### # Build full kernel ############################################### T2Bins = np.logspace( np.log10(cont["T2Bins"]["low"]), np.log10(cont["T2Bins"]["high"]), cont["T2Bins"]["number"], endpoint=True, base=10) T2Bins2 = np.append( T2Bins, T2Bins[-1] + (T2Bins[-1]-T2Bins[-2]) ) NT2 = len(T2Bins) KQT = np.real(buildKQT(np.abs(K0),tg,T2Bins)) ############################################### # Linear Inversion ############################################### print("Calling inversion", flush=True) inv, ibreak, errn, phim, phid, mkappa, Wd, Wm, alphastar = logBarrier(KQT, np.ravel(V), T2Bins, "lcurve", MAXITER=150, sigma=np.ravel(VS), alpha=1e7, smooth="Smallest" ) ################################ # Summary plots, Data Space # ################################ # TODO, need to clean this up for the case of multiple channels! Each channel should be a new row. It will be ugly, but important # TODO, loop over channels ich = 0 for ch in cont['data'][dat]['channels']: figx = plt.figure( figsize=(pc2in(42.0),pc2in(22.)) ) ax1 = figx.add_axes([.100, .15, .200, .70]) ax2 = figx.add_axes([.325, .15, .200, .70]) # shifted to make room for shared colourbar axc1= figx.add_axes([.550, .15, .025, .70]) # shifted to make room for shared colourbar ax3 = figx.add_axes([.670, .15, .200, .70]) axc2= figx.add_axes([.895, .15, .025, .70]) # shifted to make room for shared colourbar ax3.set_yscale('log') ax2.set_yscale('log') ax1.set_yscale('log') ax2.yaxis.set_ticklabels([]) ax3.yaxis.set_ticklabels([]) ax3.set_xscale('log') ax2.set_xscale('log') ax1.set_xscale('log') ax1.set_ylabel("Q (A $\cdot$ s)") ax1.set_xlabel("time (s)") ax2.set_xlabel("time (s)") ax3.set_xlabel("time (s)") #TT, QQQ = np.meshgrid(tg, np.ravel(QQ)) TT, QQQ = np.meshgrid(tg, np.ravel(QQ[ich])) nq = np.shape(QQ[ich])[0] #- 1 # -1 to account for padding in pcolor, but this was changed nt = np.shape(tg)[0] ntq = nt*nq VV = V[ich*nq:ich*nq+nq,:] # slice this channel VVS = VS[ich*nq:ich*nq+nq,:] # slice this channel mmax = np.max(np.abs(VV)) mmin = np.min(VV) obs = ax1.pcolor(TT, QQQ, VV, cmap=cmocean.cm.curl_r, vmin=-mmax, vmax=mmax, shading='auto') # pcolor edge not defined ax1.set_title("observed") pre = np.dot(KQT[ich*ntq:(ich+1)*ntq,:], inv) PRE = np.reshape( pre, np.shape(VV) ) prem = ax2.pcolor(TT, QQQ, PRE, cmap=cmocean.cm.curl_r, vmin=-mmax, vmax=mmax,shading='auto' ) ax2.set_title("predicted") cbar = plt.colorbar(prem, axc1) axc1.set_ylim( [np.min(VV), np.max(VV)] ) cbar.outline.set_edgecolor(None) cbar.set_label('$V_N$ (nV)') DIFF = (PRE-VV) / VVS md = np.max(np.abs(DIFF)) dim = ax3.pcolor(TT, QQQ, DIFF, cmap=cmocean.cm.balance, vmin=-md, vmax=md, shading='auto') ax3.set_title("misfit / $\widehat{\sigma}$") cbar2 = plt.colorbar(dim, axc2) #axc1.set_ylim( [np.min(V), np.max(V)] ) cbar2.outline.set_edgecolor(None) cbar2.set_label('$V_N$ (nV)') #plt.colorbar(dim, ax3) figx.suptitle(ch + " linear Inversion") plt.savefig(ch + "dataspace.pdf") ich += 1 ############################################### # Non-linear refinement! ############################################### nonLinearRefinement = cont['NonLinearRefinement'] if nonLinearRefinement: KQTc = buildKQT(K0, tg, T2Bins) prec = np.abs(np.dot(KQTc, inv)) phidc = np.linalg.norm(np.dot(Wd,prec-np.ravel(V)))**2 print("PHID forward linear=", errn, "PHID forward nonlinear=", phidc/len(np.ravel(V))) res = nl.nonlinearinversion(inv, Wd, KQTc, np.ravel(V), Wm, alphastar ) if res.success == True: INVc = np.reshape(res.x, (len(ifaces)-1,cont["T2Bins"]["number"]) ) prec = np.abs(np.dot(KQTc, res.x)) phidc = np.linalg.norm(np.dot(Wd,prec-np.ravel(V)))**2 PREc = np.reshape( prec, np.shape(V) ) print("PHID linear=", errn, "PHID nonlinear=", phidc/len(np.ravel(V))) while phidc/len(np.ravel(V)) > errn: phidc_old = phidc/len(np.ravel(V)) #alphastar *= .9 res = nl.nonlinearinversion(res.x, Wd, KQTc, np.ravel(V), Wm, alphastar ) if res.success == True: INVc = np.reshape(res.x, (len(ifaces)-1,cont["T2Bins"]["number"]) ) prec = np.abs(np.dot(KQTc, res.x)) phidc = np.linalg.norm(np.dot(Wd,prec-np.ravel(V)))**2 PREc = np.reshape( prec, np.shape(V) ) print("PHID linear=", errn, "PHID nonlinear=", phidc/len(np.ravel(V))) else: nonLinearRefinement = False print("Non-linear inversion failed, results will not be shown") break if phidc_old - phidc/len(np.ravel(V)) < 0.005: print("Not making progress reducing misfit in nonlinear refinement") break # Turn this into a nice figure w/ shared axes etc. # plt.matshow(PREc, cmap='Blues') # plt.gca().set_title("nonlinear predicted") # plt.colorbar() # # DIFFc = (PREc-V) / VS # md = np.max(np.abs(DIFF)) # plt.matshow(DIFFc, cmap=cmocean.cm.balance, vmin=-md, vmax=md) # plt.gca().set_title("nonlinear misfit / $\widehat{\sigma}$") # plt.colorbar() ################################ # Summary plots, Data Space # ################################ ich = 0 for ch in cont['data'][dat]['channels']: figx = plt.figure( figsize=(pc2in(42.0),pc2in(22.)) ) ax1 = figx.add_axes([.100, .15, .200, .70]) ax2 = figx.add_axes([.325, .15, .200, .70]) # shifted to make room for shared colourbar axc1= figx.add_axes([.550, .15, .025, .70]) # shifted to make room for shared colourbar ax3 = figx.add_axes([.670, .15, .200, .70]) axc2= figx.add_axes([.895, .15, .025, .70]) # shifted to make room for shared colourbar ax3.set_yscale('log') ax2.set_yscale('log') ax1.set_yscale('log') ax2.yaxis.set_ticklabels([]) ax3.yaxis.set_ticklabels([]) ax3.set_xscale('log') ax2.set_xscale('log') ax1.set_xscale('log') ax1.set_ylabel("Q (A $\cdot$ s)") ax1.set_xlabel("time (s)") ax2.set_xlabel("time (s)") ax3.set_xlabel("time (s)") #TT, QQQ = np.meshgrid(tg, np.ravel(QQ)) TT, QQQ = np.meshgrid(tg, np.ravel(QQ[ich])) nq = np.shape(QQ[ich])[0] # to account for padding in pcolor, this changed nt = np.shape(tg)[0] ntq = nt*nq VV = V[ich*nq:ich*nq+nq,:] # slice this channel VVS = VS[ich*nq:ich*nq+nq,:] # slice this channel mmax = np.max(np.abs(VV)) mmin = np.min(VV) obs = ax1.pcolor(TT, QQQ, VV, cmap=cmocean.cm.curl_r, vmin=-mmax, vmax=mmax, shading='auto') ax1.set_title("observed") ## Here neds to change pre = np.abs(np.dot(KQTc[ich*ntq:(ich+1)*ntq,:], inv)) PRE = np.reshape( pre, np.shape(VV) ) prem = ax2.pcolor(TT, QQQ, PRE, cmap=cmocean.cm.curl_r, vmin=-mmax, vmax=mmax, shading='auto' ) ax2.set_title("predicted") cbar = plt.colorbar(prem, axc1) axc1.set_ylim( [np.min(VV), np.max(VV)] ) cbar.outline.set_edgecolor(None) cbar.set_label('$V_N$ (nV)') DIFF = (PRE-VV) / VVS md = np.max(np.abs(DIFF)) dim = ax3.pcolor(TT, QQQ, DIFF, cmap=cmocean.cm.balance, vmin=-md, vmax=md, shading='auto') ax3.set_title("misfit / $\widehat{\sigma}$") cbar2 = plt.colorbar(dim, axc2) #axc1.set_ylim( [np.min(V), np.max(V)] ) cbar2.outline.set_edgecolor(None) cbar2.set_label('$V_N$ (nV)') #plt.colorbar(dim, ax3) figx.suptitle(ch + " non-linear Inversion") plt.savefig(ch + "_NLdataspace.pdf") ich += 1 ############################################### # Appraise DOI using simplified MRM ############################################### CalcDOI = cont['CalcDOI'] if CalcDOI: pdf = PdfPages('resolution_analysis' + '.pdf' ) MRM = np.zeros((len(ifaces)-1, len(ifaces)-1)) # Build delta models DELTA = [] for ilay in range(len(ifaces)-1): #for ilay in range(4): iDeltaT2 = len(T2Bins)//2 deltaMod = np.zeros( (len(ifaces)-1, len(T2Bins)) ) deltaMod[ilay][iDeltaT2] = 0.3 dV = np.dot(KQT, np.ravel(deltaMod)) #dinv, dibreak, derrn = logBarrier( KQT, dV, T2Bins, "single", MAXITER=1, sigma=np.ravel(VS), alpha=alphastar, smooth="Smallest" ) #output = invertDelta(KQT, dV, T2Bins, np.ravel(VS), alphastar) DELTA.append(dV) print("Performing resolution analysis in parallel, printed output may not be inorder.", flush=True) with multiprocessing.Pool() as pool: invresults = pool.starmap(invertDelta, zip(itertools.repeat(KQT), DELTA, itertools.repeat(T2Bins), itertools.repeat(np.ravel(VS)), itertools.repeat(alphastar) )) # invresults = pool.starmap(logBarrier, zip(itertools.repeat(KQT), DELTA, itertools.repeat(T2Bins), itertools.repeat('single'), \ # itertools.repeat('MAXITER=1'), itertools.repeat(np.ravel(VS)), itertools.repeat(alphastar))) #, itertools.repeat(u'smooth=\'Smallest\'')) ) # This could be parallelized for ilay in range(len(ifaces)-1): # invert #dinv, dibreak, derrn = logBarrier(KQT, dV, T2Bins, "single", MAXITER=1, sigma=np.ravel(VS), alpha=alphastar, smooth="Smallest" ) #print("Sum dinv from", str(ifaces[ilay]), "to", str(ifaces[ilay+1]), "=", np.sum(dinv)) dinv, dibreak, derrn = invresults[ilay] DINV = np.reshape(dinv, (len(ifaces)-1,cont["T2Bins"]["number"]) ) MRM[ilay,:] = np.sum(DINV, axis=1) Y,X = meshgrid( ifaces, T2Bins2 ) fig = plt.figure( figsize=(pc2in(20.0),pc2in(22.)) ) ax1 = fig.add_axes( [.2,.15,.6,.7] ) im = ax1.pcolor(X, Y, DINV.T, cmap=cmocean.cm.tempo, shading='auto') ax1.plot( T2Bins[iDeltaT2], (ifaces[ilay]+ifaces[ilay+1])/2, 's', markersize=6, markeredgecolor='black') #, markerfacecolor=None ) im.set_edgecolor('face') ax1.set_xlabel(u"$T_2^*$ (ms)") ax1.set_ylabel(u"depth (m)") ax1.set_xlim( T2Bins2[0], T2Bins2[-1] ) ax1.set_ylim( ifaces[-1], ifaces[0] ) ax2 = ax1.twiny() ax2.plot( np.sum(DINV, axis=1), (ifaces[1:]+ifaces[0:-1])/2 , color='mediumblue' ) ax2.set_xlabel(u"total water (m$^3$/m$^3$)", color='mediumblue') ax2.set_ylim( ifaces[-1], ifaces[0] ) ax2.xaxis.set_major_locator( MaxNLocator(nbins = 3) ) ax2.get_xaxis().set_major_formatter(FormatStrFormatter('%0.2f')) pdf.savefig(facecolor=[0,0,0,0]) plt.close(fig) np.save("MRM", MRM) centres = (ifaces[0:-1]+ifaces[1:])/2 X,Y = np.meshgrid(ifaces,ifaces) fig = plt.figure( figsize=(pc2in(20.0),pc2in(22.)) ) ax1 = fig.add_axes( [.2,.15,.6,.7] ) ax1.pcolor(X,Y,MRM, cmap = cmocean.cm.ice) ax1.set_ylim(ifaces[-1], ifaces[0]) maxDepth = np.argmax(MRM, axis=0) plt.plot(centres[maxDepth], centres, color='white') # Determine DOI DOIMetric = centres[maxDepth]/centres #> 0.9 DOI = ifaces[ np.where(DOIMetric < 0.9 ) ][0] plt.axhline(y=DOI, color='white', linestyle='-.') ax1.set_ylim( ifaces[-1], ifaces[0] ) ax1.set_xlim( ifaces[0], ifaces[-1] ) ax1.set_xlabel(u"depth (m)") ax1.set_ylabel(u"depth (m)") plt.savefig("resolutionmatrix.pdf") pdf.close() INV = np.reshape(inv, (len(ifaces)-1,cont["T2Bins"]["number"]) ) ############## LINEAR RESULT ########################## Y,X = meshgrid( ifaces, T2Bins2 ) fig = plt.figure( figsize=(pc2in(20.0),pc2in(22.)) ) ax1 = fig.add_axes( [.2,.15,.6,.7] ) im = ax1.pcolor(X, Y, INV.T, cmap=cmocean.cm.tempo) #cmap='viridis') im.set_edgecolor('face') ax1.set_xlim( T2Bins[0], T2Bins[-1] ) ax1.set_ylim( ifaces[-1], ifaces[0] ) cb = plt.colorbar(im, label = u"PWC (m$^3$/m$^3$)") #, format='%1.1f') cb.locator = MaxNLocator( nbins = 4) cb.ax.yaxis.set_offset_position('left') cb.update_ticks() ax1.set_xlabel(u"$T_2^*$ (ms)") ax1.set_ylabel(u"depth (m)") ax1.get_xaxis().set_major_formatter(FormatStrFormatter('%1.0f')) ax1.get_yaxis().set_major_formatter(FormatStrFormatter('%1.0f')) ax1.xaxis.set_major_locator( MaxNLocator(nbins = 4) ) ax2 = ax1.twiny() ax2.plot( np.sum(INV, axis=1), (ifaces[1:]+ifaces[0:-1])/2 , color='mediumblue' ) ax2.set_xlabel(u"NMR total water (m$^3$/m$^3$)", color='mediumblue') ax2.set_ylim( ifaces[-1], ifaces[0] ) ax2.xaxis.set_major_locator( MaxNLocator(nbins = 3) ) ax2.get_xaxis().set_major_formatter(FormatStrFormatter('%0.2f')) #ax2.axhline( y=ifaces[SNRidx], xmin=0, xmax=1, color='black', linestyle='dashed' ) if CalcDOI: ax2.axhline( y=DOI, xmin=0, xmax=1, color='black', linestyle='dashed' ) ax2.tick_params(axis='x', colors='mediumblue') plt.setp(ax2.get_xticklabels(), color="mediumblue") plt.savefig("akvoInversion.pdf") ############# # water plot# fig2 = plt.figure( figsize=(pc2in(20.0),pc2in(22.)) ) ax = fig2.add_axes( [.2,.15,.6,.7] ) # Bound water cutoff Bidx = T2Bins<33.0 twater = np.sum(INV, axis=1) bwater = np.sum(INV[:,Bidx], axis=1) ax.plot( twater, (ifaces[0:-1]+ifaces[1::])/2, label="NMR total water", color='blue' ) ax.plot( bwater, (ifaces[0:-1]+ifaces[1::])/2, label="NMR bound water", color='green' ) ax.fill_betweenx((ifaces[0:-1]+ifaces[1::])/2 , twater, bwater, where=twater >= bwater, facecolor='blue', alpha=.5) ax.fill_betweenx((ifaces[0:-1]+ifaces[1::])/2 , bwater, 0, where=bwater >= 0, facecolor='green', alpha=.5) ax.set_xlabel(r"$\theta_N$ (m$^3$/m$^3$)") ax.set_ylabel(r"depth (m)") ax.set_ylim( ifaces[-1], ifaces[0] ) ax.set_xlim( 0, ax.get_xlim()[1] ) #ax.axhline( y=ifaces[SNRidx], xmin=0, xmax=1, color='black', linestyle='dashed' ) if CalcDOI: ax.axhline( y=DOI, xmin=0, xmax=1, color='black', linestyle='dashed' ) # Hide the right and top spines ax.spines['right'].set_visible(False) ax.spines['top'].set_visible(False) # Only show ticks on the left and bottom spines ax.yaxis.set_ticks_position('left') ax.xaxis.set_ticks_position('bottom') plt.legend() plt.savefig("akvoInversionWC.pdf") fr = pd.DataFrame( INV, columns=T2Bins ) #[0:-1] ) fr.insert(0, "layer top", ifaces[0:-1] ) fr.insert(1, "layer bottom", ifaces[1::] ) fr.insert(2, "NMR total water", np.sum(INV, axis=1) ) fr.insert(3, "NMR bound water", bwater ) fr.insert(4, "Layer SNR", SNR ) if CalcDOI: fr.insert(5, "Resolution", DOIMetric ) fr.to_csv("akvoInversion.csv", mode='w+') ############## NONLINEAR RESULT ########################## if nonLinearRefinement: Y,X = meshgrid( ifaces, T2Bins2 ) fig = plt.figure( figsize=(pc2in(20.0),pc2in(22.)) ) ax1 = fig.add_axes( [.2,.15,.6,.7] ) im = ax1.pcolor(X, Y, INVc.T, cmap=cmocean.cm.tempo) #cmap='viridis') #im = ax1.pcolor(X[0:SNRidx,:], Y[0:SNRidx,:], INV.T[0:SNRidx,:], cmap=cmocean.cm.tempo) #cmap='viridis') #im = ax1.pcolor(X[SNRidx::,:], Y[SNRidx::,:], INV.T[SNRidx::,:], cmap=cmocean.cm.tempo, alpha=.5) #cmap='viridis') #im = ax1.pcolormesh(X, Y, INV.T, alpha=alphas) #, cmap=cmocean.cm.tempo) #cmap='viridis') #im = ax1.pcolormesh(X, Y, INV.T, alpha=alphas) #, cmap=cmocean.cm.tempo) #cmap='viridis') #ax1.axhline( y=ifaces[SNRidx], xmin=T2Bins[0], xmax=T2Bins[-1], color='black' ) im.set_edgecolor('face') ax1.set_xlim( T2Bins[0], T2Bins[-1] ) ax1.set_ylim( ifaces[-1], ifaces[0] ) cb = plt.colorbar(im, label = u"PWC (m$^3$/m$^3$)") #, format='%1.1f') cb.locator = MaxNLocator( nbins = 4) cb.ax.yaxis.set_offset_position('left') cb.update_ticks() ax1.set_xlabel(u"$T_2^*$ (ms)") ax1.set_ylabel(u"depth (m)") ax1.get_xaxis().set_major_formatter(FormatStrFormatter('%1.0f')) ax1.get_yaxis().set_major_formatter(FormatStrFormatter('%1.0f')) ax1.xaxis.set_major_locator( MaxNLocator(nbins = 4) ) #ax1.xaxis.set_label_position('top') ax2 = ax1.twiny() ax2.plot( np.sum(INVc, axis=1), (ifaces[1:]+ifaces[0:-1])/2 , color='mediumblue' ) ax2.set_xlabel(u"NMR total water (m$^3$/m$^3$)", color='mediumblue') ax2.set_ylim( ifaces[-1], ifaces[0] ) ax2.xaxis.set_major_locator( MaxNLocator(nbins = 3) ) ax2.get_xaxis().set_major_formatter(FormatStrFormatter('%0.2f')) #ax2.axhline( y=ifaces[SNRidx], xmin=0, xmax=1, color='black', linestyle='dashed' ) if CalcDOI: ax2.axhline( y=DOI, xmin=0, xmax=1, color='black', linestyle='dashed' ) #ax2.xaxis.set_label_position('bottom') #fig.suptitle("Non linear inversion") ax2.tick_params(axis='x', colors='mediumblue') plt.setp(ax2.get_xticklabels(), color="mediumblue") plt.savefig("akvoInversionNL.pdf") ############# # water plot# fig2 = plt.figure( figsize=(pc2in(20.0),pc2in(22.)) ) ax = fig2.add_axes( [.2,.15,.6,.7] ) # Bound water cutoff Bidx = T2Bins<33.0 twater = np.sum(INVc, axis=1) bwater = np.sum(INVc[:,Bidx], axis=1) ax.plot( twater, (ifaces[0:-1]+ifaces[1::])/2, label="NMR total water", color='blue' ) ax.plot( bwater, (ifaces[0:-1]+ifaces[1::])/2, label="NMR bound water", color='green' ) ax.fill_betweenx((ifaces[0:-1]+ifaces[1::])/2 , twater, bwater, where=twater >= bwater, facecolor='blue', alpha=.5) ax.fill_betweenx((ifaces[0:-1]+ifaces[1::])/2 , bwater, 0, where=bwater >= 0, facecolor='green', alpha=.5) ax.set_xlabel(r"$\theta_N$ (m$^3$/m$^3$)") ax.set_ylabel(r"depth (m)") ax.set_ylim( ifaces[-1], ifaces[0] ) ax.set_xlim( 0, ax.get_xlim()[1] ) #ax.axhline( y=ifaces[SNRidx], xmin=0, xmax=1, color='black', linestyle='dashed' ) if CalcDOI: ax.axhline( y=DOI, xmin=0, xmax=1, color='black', linestyle='dashed' ) # Hide the right and top spines ax.spines['right'].set_visible(False) ax.spines['top'].set_visible(False) # Only show ticks on the left and bottom spines ax.yaxis.set_ticks_position('left') ax.xaxis.set_ticks_position('bottom') plt.savefig("akvoNLInversionWC.pdf") plt.legend() # Report results into a text file fr = pd.DataFrame( INVc, columns=T2Bins ) #[0:-1] ) fr.insert(0, "layer top", ifaces[0:-1] ) fr.insert(1, "layer bottom", ifaces[1::] ) fr.insert(2, "NMR total water", np.sum(INVc, axis=1) ) fr.insert(3, "NMR bound water", bwater ) fr.insert(4, "Layer SNR", SNR ) if CalcDOI: fr.insert(5, "Resolution", DOIMetric ) fr.to_csv("akvoNLInversion.csv", mode='w+') #fr.to_excel("akvoInversion.xlsx") plt.show() if __name__ == "__main__": main()