mirror of
https://github.com/wassname/simpeg.git
synced 2026-09-09 11:34:26 +08:00
SimPEG.MT Mergify.
Merge branch 'move2Simpeg' of https://github.com/simpeg/simpegmt into mt/dev Conflicts: .gitignore .travis.yml LICENSE docs/conf.py docs/index.rst requirements.txt setup.py
This commit is contained in:
@@ -0,0 +1,111 @@
|
||||
# Analytic solution of EM fields due to a plane wave
|
||||
|
||||
import numpy as np, SimPEG as simpeg
|
||||
|
||||
def getEHfields(m1d,sigma,freq,zd,scaleUD=True):
|
||||
'''Analytic solution for MT 1D layered earth. Returns E and H fields.
|
||||
|
||||
:param SimPEG.mesh, object m1d: Mesh object with the 1D spatial information.
|
||||
:param numpy.array, vector sigma: Physical property of conductivity corresponding with the mesh.
|
||||
:param float, freq: Frequency to calculate data at.
|
||||
:param numpy array, vector zd: location to calculate EH fields at
|
||||
:param bollean, scaleUD: scales the output to be 1 at the top, increases numeracal stability.
|
||||
|
||||
Assumes a halfspace with the same conductive as the last cell below.
|
||||
|
||||
'''
|
||||
# Note add an error check for the mesh and sigma are the same size.
|
||||
|
||||
# Constants: Assume constant
|
||||
mu = 4*np.pi*1e-7*np.ones((m1d.nC+1))
|
||||
eps = 8.85*1e-12*np.ones((m1d.nC+1))
|
||||
# Angular freq
|
||||
w = 2*np.pi*freq
|
||||
# Add the halfspace value to the property
|
||||
sig = np.concatenate((np.array([sigma[0]]),sigma))
|
||||
# Calculate the wave number
|
||||
k = np.sqrt(eps*mu*w**2-1j*mu*sig*w)
|
||||
|
||||
# Initiate the propagation matrix, in the order down up.
|
||||
UDp = np.zeros((2,m1d.nC+1),dtype=complex)
|
||||
UDp[1,0] = 1. # Set the wave amplitude as 1 into the half-space at the bottom of the mesh
|
||||
# Loop over all the layers, starting at the bottom layer
|
||||
for lnr, h in enumerate(m1d.hx): # lnr-number of layer, h-thickness of the layer
|
||||
# Calculate
|
||||
yp1 = k[lnr]/(w*mu[lnr]) # Admittance of the layer below the current layer
|
||||
zp = (w*mu[lnr+1])/k[lnr+1] # Impedance in the current layer
|
||||
# Build the propagation matrix
|
||||
|
||||
# Convert fields to down/up going components in layer below current layer
|
||||
Pj1 = np.array([[1,1],[yp1,-yp1]])
|
||||
# Convert fields to down/up going components in current layer
|
||||
Pjinv = 1./2*np.array([[1,zp],[1,-zp]])
|
||||
# Propagate down and up components through the current layer
|
||||
elamh = np.array([[np.exp(-1j*k[lnr+1]*h),0],[0,np.exp(1j*k[lnr+1]*h)]])
|
||||
|
||||
# The down and up component in current layer.
|
||||
UDp[:,lnr+1] = elamh.dot(Pjinv.dot(Pj1)).dot(UDp[:,lnr])
|
||||
|
||||
if scaleUD:
|
||||
UDp[:,lnr+1::-1] = UDp[:,lnr+1::-1]/UDp[1,lnr+1]
|
||||
|
||||
# Calculate the fields
|
||||
Ed = np.empty((zd.size,),dtype=complex)
|
||||
Eu = np.empty((zd.size,),dtype=complex)
|
||||
Hd = np.empty((zd.size,),dtype=complex)
|
||||
Hu = np.empty((zd.size,),dtype=complex)
|
||||
|
||||
# Loop over the layers and calculate the fields
|
||||
# In the halfspace below the mesh
|
||||
dup = m1d.vectorNx[0]
|
||||
dind = dup >= zd
|
||||
Ed[dind] = UDp[1,0]*np.exp(-1j*k[0]*(dup-zd[dind]))
|
||||
Eu[dind] = UDp[0,0]*np.exp(1j*k[0]*(dup-zd[dind]))
|
||||
Hd[dind] = (k[0]/(w*mu[0]))*UDp[1,0]*np.exp(-1j*k[0]*(dup-zd[dind]))
|
||||
Hu[dind] = -(k[0]/(w*mu[0]))*UDp[0,0]*np.exp(1j*k[0]*(dup-zd[dind]))
|
||||
for ki,mui,epsi,dlow,dup,Up,Dp in zip(k[1::],mu[1::],eps[1::],m1d.vectorNx[:-1],m1d.vectorNx[1::],UDp[0,1::],UDp[1,1::]):
|
||||
dind = np.logical_and(dup >= zd, zd > dlow)
|
||||
Ed[dind] = Dp*np.exp(-1j*ki*(dup-zd[dind]))
|
||||
Eu[dind] = Up*np.exp(1j*ki*(dup-zd[dind]))
|
||||
Hd[dind] = (ki/(w*mui))*Dp*np.exp(-1j*ki*(dup-zd[dind]))
|
||||
Hu[dind] = -(ki/(w*mui))*Up*np.exp(1j*ki*(dup-zd[dind]))
|
||||
|
||||
# Return return the fields
|
||||
return Ed, Eu, Hd, Hu
|
||||
|
||||
def getImpedance(m1d,sigma,freq):
|
||||
"""Analytic solution for MT 1D layered earth. Returns the impedance at the surface.
|
||||
|
||||
:param SimPEG.mesh, object m1d: Mesh object with the 1D spatial information.
|
||||
:param numpy.array, vector sigma: Physical property corresponding with the mesh.
|
||||
:param numpy.array, vector freq: Frequencies to calculate data at.
|
||||
|
||||
|
||||
"""
|
||||
|
||||
# Define constants
|
||||
mu0 = 4*np.pi*1e-7
|
||||
eps0 = 8.85e-12
|
||||
|
||||
# Initiate the impedances
|
||||
Z1d = np.empty(len(freq) , dtype='complex')
|
||||
h = m1d.hx #vectorNx[:-1]
|
||||
# Start the process
|
||||
for nrFr, fr in enumerate(freq):
|
||||
om = 2*np.pi*fr
|
||||
Zall = np.empty(len(h)+1,dtype='complex')
|
||||
# Calculate the impedance for the bottom layer
|
||||
Zall[0] = (mu0*om)/np.sqrt(mu0*eps0*(om)**2 - 1j*mu0*sigma[0]*om)
|
||||
|
||||
for nr,hi in enumerate(h):
|
||||
# Calculate the wave number
|
||||
# print nr,sigma[nr]
|
||||
k = np.sqrt(mu0*eps0*om**2 - 1j*mu0*sigma[nr]*om)
|
||||
Z = (mu0*om)/k
|
||||
|
||||
Zall[nr+1] = Z *((Zall[nr] + Z*np.tanh(1j*k*hi))/(Z + Zall[nr]*np.tanh(1j*k*hi)))
|
||||
|
||||
#pdb.set_trace()
|
||||
Z1d[nrFr] = Zall[-1]
|
||||
|
||||
return Z1d
|
||||
@@ -0,0 +1,45 @@
|
||||
import numpy as np, SimPEG as simpeg
|
||||
from MT1Danalytic import getEHfields
|
||||
from scipy.constants import mu_0
|
||||
|
||||
def get1DEfields(m1d,sigma,freq,sourceAmp=1.0):
|
||||
"""Function to get 1D electrical fields"""
|
||||
|
||||
# Get the gradient
|
||||
G = m1d.nodalGrad
|
||||
# Mass matrices
|
||||
# Magnetic permeability
|
||||
Mmu = simpeg.Utils.sdiag(m1d.vol*(1.0/mu_0))
|
||||
# Conductivity
|
||||
Msig = m1d.getFaceInnerProduct(sigma)
|
||||
# Set up the solution matrix
|
||||
A = G.T*Mmu*G + 1j*2.*np.pi*freq*Msig
|
||||
# Define the inner part of the solution matrix
|
||||
Aii = A[1:-1,1:-1]
|
||||
# Define the outer part of the solution matrix
|
||||
Aio = A[1:-1,[0,-1]]
|
||||
|
||||
# Set the boundary conditions
|
||||
Ed, Eu, Hd, Hu = getEHfields(m1d,sigma,freq,m1d.vectorNx)
|
||||
Etot = (Ed + Eu)
|
||||
if sourceAmp is not None:
|
||||
Etot = ((Etot/Etot[-1])*sourceAmp) # Scale the fields to be equal to sourceAmp at the top
|
||||
## Note: The analytic solution is derived with e^iwt
|
||||
bc = np.r_[Etot[0],Etot[-1]]
|
||||
# The right hand side
|
||||
rhs = Aio*bc
|
||||
# Solve the system
|
||||
Aii_inv = simpeg.Solver(Aii)
|
||||
eii = Aii_inv*rhs
|
||||
# Assign the boundary conditions
|
||||
e = np.r_[bc[0],eii,bc[1]]
|
||||
# Return the electrical fields
|
||||
return e
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
||||
hz = [(100.,18)]
|
||||
M = simpeg.Mesh.TensorMesh([hz],'C')
|
||||
sig = np.zeros(M.nC) + 1e-8
|
||||
sig[M.vectorCCx<=0] = sigHalf
|
||||
@@ -0,0 +1,4 @@
|
||||
from MT1Dsolutions import * # Add the names of the functions
|
||||
from MT1Danalytic import *
|
||||
from dataUtils import *
|
||||
from ediFilesUtils import *
|
||||
@@ -0,0 +1,245 @@
|
||||
# Utils used for the data,
|
||||
import numpy as np, matplotlib.pyplot as plt, sys
|
||||
import SimPEG as simpeg
|
||||
import numpy.lib.recfunctions as recFunc
|
||||
from scipy.constants import mu_0
|
||||
from scipy import interpolate as sciint
|
||||
|
||||
def getAppRes(MTdata):
|
||||
# Make impedance
|
||||
zList = []
|
||||
for src in MTdata.survey.srcList:
|
||||
zc = [src.freq]
|
||||
for rx in src.rxList:
|
||||
if 'i' in rx.rxType:
|
||||
m=1j
|
||||
else:
|
||||
m = 1
|
||||
zc.append(m*MTdata[src,rx])
|
||||
zList.append(zc)
|
||||
return [appResPhs(zList[i][0],np.sum(zList[i][1:3])) for i in np.arange(len(zList))]
|
||||
|
||||
def rotateData(MTdata,rotAngle):
|
||||
'''
|
||||
Function that rotates clockwist by rotAngle (- negative for a counter-clockwise rotation)
|
||||
'''
|
||||
recData = MTdata.toRecArray('Complex')
|
||||
impData = rec2ndarr(recData[['zxx','zxy','zyx','zyy']],complex)
|
||||
# Make the rotation matrix
|
||||
# c,s,zxx,zxy,zyx,zyy = sympy.symbols('c,s,zxx,zxy,zyx,zyy')
|
||||
# rotM = sympy.Matrix([[c,-s],[s, c]])
|
||||
# zM = sympy.Matrix([[zxx,zxy],[zyx,zyy]])
|
||||
# rotM*zM*rotM.T
|
||||
# [c*(c*zxx - s*zyx) - s*(c*zxy - s*zyy), c*(c*zxy - s*zyy) + s*(c*zxx - s*zyx)],
|
||||
# [c*(c*zyx + s*zxx) - s*(c*zyy + s*zxy), c*(c*zyy + s*zxy) + s*(c*zyx + s*zxx)]])
|
||||
s = np.sin(-np.deg2rad(rotAngle))
|
||||
c = np.cos(-np.deg2rad(rotAngle))
|
||||
rotMat = np.array([[c,-s],[s,c]])
|
||||
rotData = (rotMat.dot(impData.reshape(-1,2,2).dot(rotMat.T))).transpose(1,0,2).reshape(-1,4)
|
||||
outRec = recData.copy()
|
||||
for nr,comp in enumerate(['zxx','zxy','zyx','zyy']):
|
||||
outRec[comp] = rotData[:,nr]
|
||||
|
||||
from SimPEG import MT
|
||||
return MT.Data.fromRecArray(outRec)
|
||||
|
||||
|
||||
def appResPhs(freq,z):
|
||||
app_res = ((1./(8e-7*np.pi**2))/freq)*np.abs(z)**2
|
||||
app_phs = np.arctan2(z.imag,z.real)*(180/np.pi)
|
||||
return app_res, app_phs
|
||||
|
||||
def skindepth(rho,freq):
|
||||
''' Function to calculate the skindepth of EM waves'''
|
||||
return np.sqrt( (rho*((1/(freq * mu_0 * np.pi )))))
|
||||
|
||||
def rec2ndarr(x,dt=float):
|
||||
return x.view((dt, len(x.dtype.names)))
|
||||
|
||||
def makeAnalyticSolution(mesh,model,elev,freqs):
|
||||
from SimPEG import MT
|
||||
data1D = []
|
||||
for freq in freqs:
|
||||
anaEd, anaEu, anaHd, anaHu = MT.Utils.MT1Danalytic.getEHfields(mesh,model,freq,elev)
|
||||
anaE = anaEd+anaEu
|
||||
anaH = anaHd+anaHu
|
||||
|
||||
anaZ = anaE/anaH
|
||||
# Add to the list
|
||||
data1D.append((freq,0,0,elev,anaZ[0]))
|
||||
dataRec = np.array(data1D,dtype=[('freq',float),('x',float),('y',float),('z',float),('zyx',complex)])
|
||||
return dataRec
|
||||
|
||||
def plotMT1DModelData(problem,models,symList=None):
|
||||
from SimPEG import MT
|
||||
# Setup the figure
|
||||
fontSize = 15
|
||||
|
||||
fig = plt.figure(figsize=[9,7])
|
||||
axM = fig.add_axes([0.075,.1,.25,.875])
|
||||
axM.set_xlabel('Resistivity [Ohm*m]',fontsize=fontSize)
|
||||
axM.set_xlim(1e-1,1e5)
|
||||
axM.set_ylim(-10000,5000)
|
||||
axM.set_ylabel('Depth [km]',fontsize=fontSize)
|
||||
axR = fig.add_axes([0.42,.575,.5,.4])
|
||||
axR.set_xscale('log')
|
||||
axR.set_yscale('log')
|
||||
axR.invert_xaxis()
|
||||
# axR.set_xlabel('Frequency [Hz]')
|
||||
axR.set_ylabel('Apparent resistivity [Ohm m]',fontsize=fontSize)
|
||||
|
||||
axP = fig.add_axes([0.42,.1,.5,.4])
|
||||
axP.set_xscale('log')
|
||||
axP.invert_xaxis()
|
||||
axP.set_ylim(0,90)
|
||||
axP.set_xlabel('Frequency [Hz]',fontsize=fontSize)
|
||||
axP.set_ylabel('Apparent phase [deg]',fontsize=fontSize)
|
||||
|
||||
# if not symList:
|
||||
# symList = ['x']*len(models)
|
||||
import plotDataTypes as pDt
|
||||
# Loop through the models.
|
||||
modelList = [problem.survey.mtrue]
|
||||
modelList.extend(models)
|
||||
if False:
|
||||
modelList = [problem.mapping.sigmaMap*mod for mod in modelList]
|
||||
for nr, model in enumerate(modelList):
|
||||
# Calculate the data
|
||||
if nr==0:
|
||||
data1D = problem.dataPair(problem.survey,problem.survey.dobs).toRecArray('Complex')
|
||||
else:
|
||||
data1D = problem.dataPair(problem.survey,problem.survey.dpred(model)).toRecArray('Complex')
|
||||
# Plot the data and the model
|
||||
colRat = nr/((len(modelList)-1.999)*1.)
|
||||
if colRat > 1.:
|
||||
col = 'k'
|
||||
else:
|
||||
col = plt.cm.seismic(1-colRat)
|
||||
# The model - make the pts to plot
|
||||
meshPts = np.concatenate((problem.mesh.gridN[0:1],np.kron(problem.mesh.gridN[1::],np.ones(2))[:-1]))
|
||||
modelPts = np.kron(1./(problem.mapping.sigmaMap*model),np.ones(2,))
|
||||
axM.semilogx(modelPts,meshPts,color=col)
|
||||
|
||||
## Data
|
||||
# Appres
|
||||
pDt.plotIsoStaImpedance(axR,np.array([0,0]),data1D,'zyx','res',pColor=col)
|
||||
# Appphs
|
||||
pDt.plotIsoStaImpedance(axP,np.array([0,0]),data1D,'zyx','phs',pColor=col)
|
||||
try:
|
||||
allData = np.concatenate((allData,simpeg.mkvc(data1D['zyx'],2)),1)
|
||||
except:
|
||||
allData = simpeg.mkvc(data1D['zyx'],2)
|
||||
freq = simpeg.mkvc(data1D['freq'],2)
|
||||
res, phs = appResPhs(freq,allData)
|
||||
|
||||
stdCol = 'gray'
|
||||
axRtw = axR.twinx()
|
||||
axRtw.set_ylabel('Std of log10',color=stdCol)
|
||||
[(t.set_color(stdCol), t.set_rotation(-45)) for t in axRtw.get_yticklabels()]
|
||||
axPtw = axP.twinx()
|
||||
axPtw.set_ylabel('Std ',color=stdCol)
|
||||
[t.set_color(stdCol) for t in axPtw.get_yticklabels()]
|
||||
axRtw.plot(freq, np.std(np.log10(res),1),'--',color=stdCol)
|
||||
axPtw.plot(freq, np.std(phs,1),'--',color=stdCol)
|
||||
|
||||
# Fix labels and ticks
|
||||
|
||||
yMtick = [l/1000 for l in axM.get_yticks().tolist()]
|
||||
axM.set_yticklabels(yMtick)
|
||||
[ l.set_rotation(90) for l in axM.get_yticklabels()]
|
||||
[ l.set_rotation(90) for l in axR.get_yticklabels()]
|
||||
[(t.set_color(stdCol), t.set_rotation(-45)) for t in axRtw.get_yticklabels()]
|
||||
[t.set_color(stdCol) for t in axPtw.get_yticklabels()]
|
||||
for ax in [axM,axR,axP]:
|
||||
ax.xaxis.set_tick_params(labelsize=fontSize)
|
||||
ax.yaxis.set_tick_params(labelsize=fontSize)
|
||||
return fig
|
||||
|
||||
def printTime():
|
||||
import time
|
||||
print time.strftime("%a, %d %b %Y %H:%M:%S +0000", time.localtime())
|
||||
|
||||
def convert3Dto1Dobject(MTdata,rxType3D='zyx'):
|
||||
from SimPEG import MT
|
||||
# Find the unique locations
|
||||
# Need to find the locations
|
||||
recDataTemp = MTdata.toRecArray()
|
||||
# Check if survey.std has been assigned.
|
||||
## NEED TO: write this...
|
||||
# Calculte and add the DET of the tensor to the recArray
|
||||
if 'det' in rxType3D:
|
||||
Zon = (recDataTemp['zxxr']+1j*recDataTemp['zxxi'])*(recDataTemp['zyyr']+1j*recDataTemp['zyyi'])
|
||||
Zoff = (recDataTemp['zxyr']+1j*recDataTemp['zxyi'])*(recDataTemp['zyxr']+1j*recDataTemp['zyxi'])
|
||||
det = np.sqrt(Zon.data - Zoff.data)
|
||||
recData = recFunc.append_fields(recDataTemp,['zdetr','zdeti'],[det.real,det.imag] )
|
||||
else:
|
||||
recData = recDataTemp
|
||||
|
||||
uniLocs = rec2ndarr(np.unique(recData[['x','y','z']])).data
|
||||
mtData1DList = []
|
||||
if 'zxy' in rxType3D:
|
||||
corr = -1 # Shift the data to comply with the quadtrature of the 1d problem
|
||||
else:
|
||||
corr = 1
|
||||
for loc in uniLocs:
|
||||
# Make the receiver list
|
||||
rx1DList = []
|
||||
for rxType in ['z1dr','z1di']:
|
||||
rx1DList.append(MT.Rx(simpeg.mkvc(loc,2).T,rxType))
|
||||
# Source list
|
||||
locrecData = recData[np.sqrt(np.sum( (rec2ndarr(recData[['x','y','z']]).data - loc )**2,axis=1)) < 1e-5]
|
||||
dat1DList = []
|
||||
src1DList = []
|
||||
for freq in locrecData['freq']:
|
||||
src1DList.append(MT.SrcMT.src_polxy_1Dprimary(rx1DList,freq))
|
||||
for comp in ['r','i']:
|
||||
dat1DList.append( corr * locrecData[rxType3D+comp][locrecData['freq']== freq].data )
|
||||
|
||||
# Make the survey
|
||||
sur1D = MT.Survey(src1DList)
|
||||
|
||||
# Make the data
|
||||
dataVec = np.hstack(dat1DList)
|
||||
dat1D = MT.Data(sur1D,dataVec)
|
||||
sur1D.dobs = dataVec
|
||||
# Need to take MTdata.survey.std and split it as well.
|
||||
std=0.05
|
||||
sur1D.std = np.abs(sur1D.dobs*std) #+ 0.01*np.linalg.norm(sur1D.dobs)
|
||||
mtData1DList.append(dat1D)
|
||||
|
||||
# Return the the list of data.
|
||||
return mtData1DList
|
||||
|
||||
def resampleMTdataAtFreq(MTdata,freqs):
|
||||
"""
|
||||
Function to resample MTdata at set of frequencies
|
||||
|
||||
"""
|
||||
from SimPEG import MT
|
||||
# Make a rec array
|
||||
MTrec = MTdata.toRecArray().data
|
||||
|
||||
# Find unique locations
|
||||
uniLoc = np.unique(MTrec[['x','y','z']])
|
||||
uniFreq = MTdata.survey.freqs
|
||||
# Get the comps
|
||||
dNames = MTrec.dtype
|
||||
|
||||
# Loop over all the locations and interpolate
|
||||
for loc in uniLoc:
|
||||
# Find the index of the station
|
||||
ind = np.sqrt(np.sum((rec2ndarr(MTrec[['x','y','z']]) - rec2ndarr(loc))**2,axis=1)) < 1. # Find dist of 1 m accuracy
|
||||
# Make a temporary recArray and interpolate all the components
|
||||
tArrRec = np.concatenate((simpeg.mkvc(freqs,2),np.ones((len(freqs),1))*rec2ndarr(loc),np.nan*np.ones((len(freqs),12))),axis=1).view(dNames)
|
||||
for comp in ['zxxr','zxxi','zxyr','zxyi','zyxr','zyxi','zyyr','zyyi','tzxr','tzxi','tzyr','tzyi']:
|
||||
int1d = sciint.interp1d(MTrec[ind]['freq'],MTrec[ind][comp],bounds_error=False)
|
||||
tArrRec[comp] = simpeg.mkvc(int1d(freqs),2)
|
||||
|
||||
# Join together
|
||||
try:
|
||||
outRecArr = recFunc.stack_arrays((outRecArr,tArrRec))
|
||||
except NameError as e:
|
||||
outRecArr = tArrRec
|
||||
|
||||
# Make the MTdata and return
|
||||
return MT.Data.fromRecArray(outRecArr)
|
||||
@@ -0,0 +1,175 @@
|
||||
# Functions to import and export MT EDI files.
|
||||
from SimPEG import mkvc
|
||||
from scipy.constants import mu_0
|
||||
from numpy.lib import recfunctions as recFunc
|
||||
from SimPEG.MT.Utils.dataUtils import rec2ndarr
|
||||
|
||||
# Import modules
|
||||
import numpy as np
|
||||
import os, sys, re
|
||||
try:
|
||||
import osr
|
||||
except ImportError as e:
|
||||
print 'Could not import osr, missing the gdal package'
|
||||
pass
|
||||
|
||||
class EDIimporter:
|
||||
"""
|
||||
A class to import EDIfiles.
|
||||
|
||||
"""
|
||||
_impUnitEDI2SI = 4*np.pi*1e-4 # Convert Z[mV/km/nT] (as in EDI)to Z[V/A] SI unit
|
||||
_impUnitSI2EDI = 1./_impUnitEDI2SI # ConvertZ[V/A] SI unit to Z[mV/km/nT] (as in EDI)
|
||||
|
||||
# Properties
|
||||
filesList = None
|
||||
comps = None
|
||||
|
||||
# Hidden properties
|
||||
_outEPSG = None
|
||||
_2out = None
|
||||
|
||||
|
||||
def __init__(self, EDIfilesList, compList=None, outEPSG=None):
|
||||
|
||||
# Set the fileList
|
||||
self.filesList = EDIfilesList
|
||||
# Set the components to import
|
||||
if compList is None:
|
||||
self.comps = ['ZXXR','ZXYR','ZYXR','ZYYR','ZXXI','ZXYI','ZYXI','ZYYI','ZXX.VAR','ZXY.VAR','ZYX.VAR','ZYY.VAR']
|
||||
else:
|
||||
self.comps = compList
|
||||
if outEPSG is not None:
|
||||
self._outEPSG = outEPSG
|
||||
|
||||
def __call__(self,comps=None):
|
||||
|
||||
if comps is None:
|
||||
return self._data
|
||||
|
||||
return self._data[comps]
|
||||
|
||||
def importFiles(self):
|
||||
"""
|
||||
Function to import EDI files into a object.
|
||||
|
||||
|
||||
"""
|
||||
|
||||
# Constants that are needed for convertion of units
|
||||
|
||||
# Temp lists
|
||||
tmpStaList = []
|
||||
|
||||
tmpCompList = ['freq','x','y','z']
|
||||
tmpCompList.extend(self.comps)
|
||||
# Make the outarray
|
||||
dtRI = [(compS.lower().replace('.',''),float) for compS in tmpCompList]
|
||||
# Loop through all the files
|
||||
for nrEDI, EDIfile in enumerate(self.filesList):
|
||||
# Read the file into a list of the lines
|
||||
with open(EDIfile,'r') as fid:
|
||||
EDIlines = fid.readlines()
|
||||
# Find the location
|
||||
latD, longD, elevM = _findLatLong(EDIlines)
|
||||
# Transfrom coordinates
|
||||
transCoord = self._transfromPoints(longD,latD)
|
||||
# Extract the name of the file (station)
|
||||
EDIname = EDIfile.split(os.sep)[-1].split('.')[0]
|
||||
# Arrange the data
|
||||
staList = [EDIname, EDIfile, transCoord[0], transCoord[1], elevM[0]]
|
||||
# Add to the station list
|
||||
tmpStaList.extend(staList)
|
||||
|
||||
# Read the frequency data
|
||||
freq = _findEDIcomp('>FREQ',EDIlines)
|
||||
# Make the temporary rec array.
|
||||
tArrRec = ( np.nan*np.ones( (len(freq),len(dtRI)) ) ).view(dtRI) #np.concatenate((freq*np.ones((locs.shape[0],1)),locs,np.nan*np.ones((locs.shape[0],8))),axis=1).view(dtRI)
|
||||
# Add data to the array
|
||||
tArrRec['freq'] = mkvc(freq,2)
|
||||
tArrRec['x'] = mkvc(np.ones((len(freq),1))*transCoord[0],2)
|
||||
tArrRec['y'] = mkvc(np.ones((len(freq),1))*transCoord[1],2)
|
||||
tArrRec['z'] = mkvc(np.ones((len(freq),1))*elevM[0],2)
|
||||
for comp in self.comps:
|
||||
# Deal with converting units of the impedance tensor
|
||||
if 'Z' in comp:
|
||||
unitConvert = self._impUnitEDI2SI
|
||||
else:
|
||||
unitConvert = 1
|
||||
# Rotate the data since EDI x is *north, y *east but Simpeg uses x *east, y *north (* means internal reference frame)
|
||||
key = [comp.lower().replace('.','').replace(s,t) for s,t in [['xx','yy'],['xy','yx'],['yx','xy'],['yy','xx']] if s in comp.lower()][0]
|
||||
tArrRec[key] = mkvc(unitConvert*_findEDIcomp('>'+comp,EDIlines),2)
|
||||
# Make a masked array
|
||||
mArrRec = np.ma.MaskedArray(rec2ndarr(tArrRec),mask=np.isnan(rec2ndarr(tArrRec))).view(dtype=tArrRec.dtype)
|
||||
try:
|
||||
outTemp = recFunc.stack_arrays((outTemp,mArrRec))
|
||||
except NameError as e:
|
||||
outTemp = mArrRec
|
||||
|
||||
# Assign the data
|
||||
self._data = outTemp
|
||||
|
||||
# % Assign the data to the obj
|
||||
# nOutData=length(obj.data);
|
||||
# obj.data(nOutData+1:nOutData+length(TEMP.data),:) = TEMP.data;
|
||||
def _transfromPoints(self,longD,latD):
|
||||
# Coordinates convertor
|
||||
if self._2out is None:
|
||||
src = osr.SpatialReference()
|
||||
src.ImportFromEPSG(4326)
|
||||
out = osr.SpatialReference()
|
||||
if self._outEPSG is None:
|
||||
# Find the UTM EPSG number
|
||||
Nnr = 700 if latD < 0.0 else 600
|
||||
utmZ = int(1+(longD+180.0)/6.0)
|
||||
self._outEPSG = 32000 + Nnr + utmZ
|
||||
out.ImportFromEPSG(self._outEPSG)
|
||||
self._2out = osr.CoordinateTransformation(src,out)
|
||||
# Return the transfrom
|
||||
return self._2out.TransformPoint(longD,latD)
|
||||
|
||||
# Hidden functions
|
||||
def _findLatLong(fileLines):
|
||||
latDMS = np.array(fileLines[_findLine('LAT=',fileLines)[0]].split('=')[1].split()[0].split(':'),float)
|
||||
longDMS = np.array(fileLines[_findLine('LONG=',fileLines)[0]].split('=')[1].split()[0].split(':'),float)
|
||||
elevM = np.array([fileLines[_findLine('ELEV=',fileLines)[0]].split('=')[1].split()[0]],float)
|
||||
# Convert to D.ddddd values
|
||||
latS = np.sign(latDMS[0])
|
||||
longS = np.sign(longDMS[0])
|
||||
latD = latDMS[0] + latS*latDMS[1]/60 + latS*latDMS[2]/3600
|
||||
longD = longDMS[0] + longS*longDMS[1]/60 + longS*longDMS[2]/3600
|
||||
return latD, longD, elevM
|
||||
|
||||
def _findLine(comp,fileLines):
|
||||
""" Find a line number in the file"""
|
||||
# Line counter
|
||||
c = 0
|
||||
# List of indices for found lines
|
||||
found = []
|
||||
# Loop through all the lines
|
||||
for line in fileLines:
|
||||
if comp in line:
|
||||
# Append if found
|
||||
found.append(c)
|
||||
# Increse the counter
|
||||
c += 1
|
||||
# Return the found indices
|
||||
return found
|
||||
|
||||
def _findEDIcomp(comp,fileLines,dt=float):
|
||||
"""
|
||||
Extract the data vector.
|
||||
|
||||
Returns a list of the data.
|
||||
"""
|
||||
# Find the data
|
||||
headLine, indHead = [(st,nr) for nr,st in enumerate(fileLines) if re.search(comp,st)][0]
|
||||
# Extract the data
|
||||
nrVec = int(headLine.split()[-1])
|
||||
c = 0
|
||||
dataList = []
|
||||
while c < nrVec:
|
||||
indHead += 1
|
||||
dataList.extend(fileLines[indHead].split())
|
||||
c = len(dataList)
|
||||
return np.array(dataList,dt)
|
||||
@@ -0,0 +1,416 @@
|
||||
from matplotlib import pyplot as plt, colors, numpy as np
|
||||
|
||||
|
||||
def rec2nd(structArray):
|
||||
""" Converts a structured/record array to ndarray to do operations on."""
|
||||
return structArray.view((np.float,len(structArray.dtype.names)))
|
||||
|
||||
def plotIsoFreqNSimpedance(ax,freq,array,flag,par='abs',colorbar=True,colorNorm='SymLog',cLevel=True,contour=True):
|
||||
|
||||
indUniFreq = np.where(freq==array['freq'])
|
||||
|
||||
|
||||
x, y = array['x'][indUniFreq],array['y'][indUniFreq]
|
||||
if par == 'abs':
|
||||
zPlot = np.abs(array[flag][indUniFreq])
|
||||
cmap = plt.get_cmap('OrRd_r')#seismic')
|
||||
level = np.logspace(0,-5,31)
|
||||
clevel = np.logspace(0,-4,5)
|
||||
plotNorm = colors.LogNorm()
|
||||
elif par == 'real':
|
||||
zPlot = np.real(array[flag][indUniFreq])
|
||||
cmap = plt.get_cmap('RdYlBu')
|
||||
if cLevel:
|
||||
level = np.concatenate((-np.logspace(0,-10,31),np.logspace(-10,0,31)))
|
||||
clevel = np.concatenate((-np.logspace(0,-8,5),np.logspace(-8,0,5)))
|
||||
else:
|
||||
level = np.linspace(zPlot.min(),zPlot.max(),100)
|
||||
clevel = np.linspace(zPlot.min(),zPlot.max(),10)
|
||||
if colorNorm=='SymLog':
|
||||
plotNorm = colors.SymLogNorm(1e-10,linscale=2)
|
||||
else:
|
||||
plotNorm = colors.Normalize()
|
||||
elif par == 'imag':
|
||||
zPlot = np.imag(array[flag][indUniFreq])
|
||||
cmap = plt.get_cmap('RdYlBu')
|
||||
level = np.concatenate((-np.logspace(0,-10,31),np.logspace(-10,0,31)))
|
||||
clevel = np.concatenate((-np.logspace(0,-8,5),np.logspace(-8,0,5)))
|
||||
plotNorm = colors.SymLogNorm(1e-10,linscale=2)
|
||||
if cLevel:
|
||||
level = np.concatenate((-np.logspace(0,-10,31),np.logspace(-10,0,31)))
|
||||
clevel = np.concatenate((-np.logspace(0,-8,5),np.logspace(-8,0,5)))
|
||||
else:
|
||||
level = np.linspace(zPlot.min(),zPlot.max(),100)
|
||||
clevel = np.linspace(zPlot.min(),zPlot.max(),10)
|
||||
if colorNorm=='SymLog':
|
||||
plotNorm = colors.SymLogNorm(1e-10,linscale=2)
|
||||
elif colorNorm=='Lin':
|
||||
plotNorm = colors.Normalize()
|
||||
if contour:
|
||||
cs = ax.tricontourf(x,y,zPlot,levels=level,cmap=cmap,norm=plotNorm)#,extend='both')
|
||||
else:
|
||||
uniX,uniY = np.unique(x),np.unique(y)
|
||||
X,Y = np.meshgrid(np.append(uniX-25,uniX[-1]+25),np.append(uniY-25,uniY[-1]+25))
|
||||
cs = ax.pcolor(X,Y,np.reshape(zPlot,(len(uniY),len(uniX))),cmap=cmap,norm=plotNorm)
|
||||
if colorbar:
|
||||
plt.colorbar(cs,cax=ax.cax,ticks=clevel,format='%1.2e')
|
||||
ax.set_title(flag+' '+par,fontsize=8)
|
||||
return cs
|
||||
|
||||
def plotIsoFreqNSDiff(ax,freq,arrayList,flag,par='abs',colorbar=True,cLevel=True,mask=None,contourLine=True,useLog=False):
|
||||
|
||||
indUniFreq0 = np.where(freq==arrayList[0]['freq'])
|
||||
indUniFreq1 = np.where(freq==arrayList[1]['freq'])
|
||||
seicmap = plt.get_cmap('RdYlBu')#seismic')
|
||||
x, y = arrayList[0]['x'][indUniFreq0],arrayList[0]['y'][indUniFreq0]
|
||||
if par == 'abs':
|
||||
if useLog:
|
||||
zPlot = (np.log10(np.abs(arrayList[0][flag][indUniFreq0])) - np.log10(np.abs(arrayList[1][flag][indUniFreq1])))/np.log10(np.abs(arrayList[1][flag][indUniFreq1]))
|
||||
else:
|
||||
zPlot = (np.abs(arrayList[0][flag][indUniFreq0]) - np.abs(arrayList[1][flag][indUniFreq1]))/np.abs(arrayList[1][flag][indUniFreq1])
|
||||
if mask:
|
||||
maskInd = np.logical_or(np.abs(arrayList[0][flag][indUniFreq0])< 1e-3,np.abs(arrayList[1][flag][indUniFreq1]) < 1e-3)
|
||||
zPlot = np.ma.array(zPlot)
|
||||
zPlot[maskInd] = mask
|
||||
if cLevel:
|
||||
level = np.arange(-200,201,10)
|
||||
clevel = np.arange(-200,201,25)
|
||||
else:
|
||||
level = np.linspace(zPlot.min(),zPlot.max(),100)
|
||||
clevel = np.linspace(zPlot.min(),zPlot.max(),10)
|
||||
elif par == 'real':
|
||||
if useLog:
|
||||
zPlot = (np.log10(np.real(arrayList[0][flag][indUniFreq0])) -np.log10(np.real(arrayList[1][flag][indUniFreq1])))/np.log10(np.abs((np.real(arrayList[1][flag][indUniFreq1]))))
|
||||
else:
|
||||
zPlot = (np.real(arrayList[0][flag][indUniFreq0]) -np.real(arrayList[1][flag][indUniFreq1]))/np.abs((np.real(arrayList[1][flag][indUniFreq1])))
|
||||
if mask:
|
||||
maskInd = np.logical_or(np.abs(np.real(arrayList[0][flag][indUniFreq0])) < 1e-3,np.abs(np.real(arrayList[1][flag][indUniFreq1])) < 1e-3)
|
||||
zPlot = np.ma.array(zPlot)
|
||||
zPlot[maskInd] = mask
|
||||
if cLevel:
|
||||
level = np.arange(-200,201,10)
|
||||
clevel = np.arange(-200,201,25)
|
||||
else:
|
||||
level = np.linspace(zPlot.min(),zPlot.max(),100)
|
||||
clevel = np.linspace(zPlot.min(),zPlot.max(),10)
|
||||
elif par == 'imag':
|
||||
if useLog:
|
||||
zPlot = (np.log10(np.imag(arrayList[0][flag][indUniFreq0])) -np.log10(np.imag(arrayList[1][flag][indUniFreq1])))/np.log10(np.abs((np.imag(arrayList[1][flag][indUniFreq1]))))
|
||||
else:
|
||||
zPlot = (np.imag(arrayList[0][flag][indUniFreq0]) -np.imag(arrayList[1][flag][indUniFreq1]))/np.abs((np.imag(arrayList[1][flag][indUniFreq1])))
|
||||
if mask:
|
||||
maskInd = np.logical_or(np.abs(np.imag(arrayList[0][flag][indUniFreq0])) < 1e-3,np.abs(np.imag(arrayList[1][flag][indUniFreq1])) < 1e-3)
|
||||
zPlot = np.ma.array(zPlot)
|
||||
zPlot[maskInd] = mask
|
||||
if cLevel:
|
||||
level = np.arange(-200,201,10)
|
||||
clevel = np.arange(-200,201,25)
|
||||
else:
|
||||
level = np.linspace(zPlot.min(),zPlot.max(),100)
|
||||
clevel = np.linspace(zPlot.min(),zPlot.max(),10)
|
||||
cs = ax.tricontourf(x,y,zPlot*100,levels=level*100,cmap=seicmap,extend='both') #,norm=colors.SymLogNorm(1e-2,linscale=2))
|
||||
if contourLine:
|
||||
csl = ax.tricontour(x,y,zPlot*100,levels=clevel*100,colors='k')
|
||||
plt.clabel(csl, fontsize=7, inline=1,fmt='%1.1e',inline_spacing=10)
|
||||
if colorbar:
|
||||
cb = plt.colorbar(cs,cax=ax.cax,ticks=clevel*100,format='%1.1e')
|
||||
for t in cb.ax.get_yticklabels():
|
||||
t.set_rotation(60)
|
||||
t.set_fontsize(8)
|
||||
|
||||
ax.set_title(flag+' '+par,fontsize=8)
|
||||
|
||||
def plotIsoFreqNStipper(ax,freq,array,flag,par='abs',colorbar=True,colorNorm='SymLog',cLevel=True,contour=True):
|
||||
|
||||
indUniFreq = np.where(freq==array['freq'])
|
||||
|
||||
x, y = array['x'][indUniFreq],array['y'][indUniFreq]
|
||||
if par == 'abs':
|
||||
cmap = plt.get_cmap('OrRd_r')#seismic')
|
||||
zPlot = np.abs(array[flag][indUniFreq])
|
||||
if cLevel:
|
||||
level = np.logspace(-4,0,33)
|
||||
clevel = np.logspace(-4,0,5)
|
||||
else:
|
||||
level = np.linspace(zPlot.min(),zPlot.max(),100)
|
||||
clevel = np.linspace(zPlot.min(),zPlot.max(),10)
|
||||
if colorNorm=='SymLog':
|
||||
plotNorm = colors.LogNorm()
|
||||
else:
|
||||
plotNorm = colors.Normalize()
|
||||
elif par == 'real':
|
||||
cmap = plt.get_cmap('RdYlBu')
|
||||
zPlot = np.real(array[flag][indUniFreq])
|
||||
if cLevel:
|
||||
level = np.concatenate((-np.logspace(0,-4,33),np.logspace(-4,0,33)))
|
||||
clevel = np.concatenate((-np.logspace(0,-4,5),np.logspace(-4,0,5)))
|
||||
else:
|
||||
level = np.linspace(zPlot.min(),zPlot.max(),100)
|
||||
clevel = np.linspace(zPlot.min(),zPlot.max(),10)
|
||||
if colorNorm=='SymLog':
|
||||
plotNorm = colors.SymLogNorm(1e-4,linscale=2)
|
||||
else:
|
||||
plotNorm = colors.Normalize()
|
||||
elif par == 'imag':
|
||||
cmap = plt.get_cmap('RdYlBu')
|
||||
zPlot = np.imag(array[flag][indUniFreq])
|
||||
if cLevel:
|
||||
level = np.concatenate((-np.logspace(0,-4,33),np.logspace(-4,0,33)))
|
||||
clevel = np.concatenate((-np.logspace(0,-4,5),np.logspace(-4,0,5)))
|
||||
else:
|
||||
level = np.linspace(zPlot.min(),zPlot.max(),100)
|
||||
clevel = np.linspace(zPlot.min(),zPlot.max(),10)
|
||||
if colorNorm=='SymLog':
|
||||
plotNorm = colors.SymLogNorm(1e-4,linscale=2)
|
||||
else:
|
||||
plotNorm = colors.Normalize()
|
||||
if contour:
|
||||
cs = ax.tricontourf(x,y,zPlot,levels=level,cmap=cmap,norm=plotNorm)#,extend='both')
|
||||
else:
|
||||
uniX,uniY = np.unique(x),np.unique(y)
|
||||
X,Y = np.meshgrid(np.append(uniX-25,uniX[-1]+25),np.append(uniY-25,uniY[-1]+25))
|
||||
cs = ax.pcolor(X,Y,np.reshape(zPlot,(len(uniY),len(uniX))),levels=level,cmap=cmap,norm=plotNorm,edgecolors='k', linewidths=0.5)
|
||||
if colorbar:
|
||||
plt.colorbar(cs,cax=ax.cax,ticks=clevel,format='%1.2e')
|
||||
ax.set_title(flag+' '+par,fontsize=8)
|
||||
|
||||
def plotIsoStaImpedance(ax,loc,array,flag,par='abs',pSym='s',pColor=None):
|
||||
|
||||
appResFact = 1/(8*np.pi**2*10**(-7))
|
||||
treshold = 1.0 # 1 meter
|
||||
indUniSta = np.sqrt(np.sum((rec2nd(array[['x','y']])-loc)**2,axis=1)) < treshold
|
||||
freq = array['freq'][indUniSta]
|
||||
|
||||
if par == 'abs':
|
||||
zPlot = np.abs(array[flag][indUniSta])
|
||||
elif par == 'real':
|
||||
zPlot = np.real(array[flag][indUniSta])
|
||||
elif par == 'imag':
|
||||
zPlot = np.imag(array[flag][indUniSta])
|
||||
elif par == 'res':
|
||||
zPlot = (appResFact/freq)*np.abs(array[flag][indUniSta])**2
|
||||
elif par == 'phs':
|
||||
zPlot = np.arctan2(array[flag][indUniSta].imag,array[flag][indUniSta].real)*(180/np.pi)
|
||||
|
||||
if not pColor:
|
||||
if 'xx' in flag:
|
||||
lab = 'XX'
|
||||
pColor = 'g'
|
||||
elif 'xy' in flag:
|
||||
lab = 'XY'
|
||||
pColor = 'r'
|
||||
elif 'yx' in flag:
|
||||
lab = 'YX'
|
||||
pColor = 'b'
|
||||
elif 'yy' in flag:
|
||||
lab = 'YY'
|
||||
pColor = 'y'
|
||||
|
||||
ax.plot(freq,zPlot,color=pColor,marker=pSym,label=flag)
|
||||
|
||||
|
||||
def plotPsudoSectNSimpedance(ax,sectDict,array,flag,par='abs',colorbar=True,colorNorm='None',cLevel=None,contour=True):
|
||||
|
||||
indSect = np.where(sectDict.values()[0]==array[sectDict.keys()[0]])
|
||||
|
||||
# Define the plot axes
|
||||
if 'x' in sectDict.keys()[0]:
|
||||
x = array['y'][indSect]
|
||||
else:
|
||||
x = array['x'][indSect]
|
||||
y = array['freq'][indSect]
|
||||
|
||||
if par == 'abs':
|
||||
zPlot = np.abs(array[flag][indSect])
|
||||
cmap = plt.get_cmap('OrRd_r')#seismic')
|
||||
if cLevel:
|
||||
level = np.logspace(0,-5,31,endpoint=True)
|
||||
clevel = np.logspace(0,-4,5,endpoint=True)
|
||||
else:
|
||||
level = np.linspace(zPlot.min(),zPlot.max(),100,endpoint=True)
|
||||
clevel = np.linspace(zPlot.min(),zPlot.max(),10,endpoint=True)
|
||||
|
||||
elif par == 'ares':
|
||||
zPlot = np.abs(array[flag][indSect])**2/(8*np.pi**2*10**(-7)*array['freq'][indSect])
|
||||
cmap = plt.get_cmap('RdYlBu')#seismic)
|
||||
if cLevel:
|
||||
zMax = np.log10(cLevel[1])
|
||||
zMin = np.log10(cLevel[0])
|
||||
else:
|
||||
zMax = (np.ceil(np.log10(np.abs(zPlot).max())))
|
||||
zMin = (np.floor(np.log10(np.abs(zPlot).min())))
|
||||
level = np.logspace(zMin,zMax,(zMax-zMin)*8+1,endpoint=True)
|
||||
clevel = np.logspace(zMin,zMax,(zMax-zMin)*2+1,endpoint=True)
|
||||
plotNorm = colors.LogNorm()
|
||||
|
||||
elif par == 'aphs':
|
||||
zPlot = np.arctan2(array[flag][indSect].imag,array[flag][indSect].real)*(180/np.pi)
|
||||
cmap = plt.get_cmap('RdYlBu')#seismic)
|
||||
if cLevel:
|
||||
zMax = cLevel[1]
|
||||
zMin = cLevel[0]
|
||||
else:
|
||||
zMax = (np.ceil(zPlot).max())
|
||||
zMin = (np.floor(zPlot).min())
|
||||
level = np.arange(zMin,zMax+.1,1)
|
||||
clevel = np.arange(zMin,zMax+.1,10)
|
||||
plotNorm = colors.Normalize()
|
||||
|
||||
elif par == 'real':
|
||||
zPlot = np.real(array[flag][indSect])
|
||||
cmap = plt.get_cmap('Spectral') #('RdYlBu')
|
||||
if cLevel:
|
||||
zMax = np.log10(cLevel[1])
|
||||
zMin = np.log10(cLevel[0])
|
||||
else:
|
||||
zMax = (np.ceil(np.log10(np.abs(zPlot).max())))
|
||||
zMin = (np.floor(np.log10(np.abs(zPlot).min())))
|
||||
level = np.concatenate((-np.logspace(zMax,zMin-.125,(zMax-zMin)*8+1,endpoint=True),np.logspace(zMin-.125,zMax,(zMax-zMin)*8+1,endpoint=True)))
|
||||
clevel = np.concatenate((-np.logspace(zMax,zMin,(zMax-zMin)*1+1,endpoint=True),np.logspace(zMin,zMax,(zMax-zMin)*1+1,endpoint=True)))
|
||||
plotNorm = colors.SymLogNorm(np.abs(level).min(),linscale=0.1)
|
||||
elif par == 'imag':
|
||||
zPlot = np.imag(array[flag][indSect])
|
||||
cmap = plt.get_cmap('Spectral') #('RdYlBu')
|
||||
|
||||
if cLevel:
|
||||
zMax = np.log10(cLevel[1])
|
||||
zMin = np.log10(cLevel[0])
|
||||
else:
|
||||
zMax = (np.ceil(np.log10(np.abs(zPlot).max())))
|
||||
zMin = (np.floor(np.log10(np.abs(zPlot).min())))
|
||||
level = np.concatenate((-np.logspace(zMax,zMin-.125,(zMax-zMin)*8+1,endpoint=True),np.logspace(zMin-.125,zMax,(zMax-zMin)*8+1,endpoint=True)))
|
||||
clevel = np.concatenate((-np.logspace(zMax,zMin,(zMax-zMin)*1+1,endpoint=True),np.logspace(zMin,zMax,(zMax-zMin)*1+1,endpoint=True)))
|
||||
plotNorm = colors.SymLogNorm(np.abs(level).min(),linscale=0.1)
|
||||
|
||||
if colorNorm=='SymLog':
|
||||
plotNorm = colors.SymLogNorm(np.abs(level).min(),linscale=0.1)
|
||||
elif colorNorm=='Lin':
|
||||
plotNorm = colors.Normalize()
|
||||
elif colorNorm=='Log':
|
||||
plotNorm = colors.LogNorm()
|
||||
if contour:
|
||||
cs = ax.tricontourf(x,y,zPlot,levels=level,cmap=cmap,norm=plotNorm)#,extend='both')
|
||||
else:
|
||||
uniX,uniY = np.unique(x),np.unique(y)
|
||||
X,Y = np.meshgrid(np.append(uniX-25,uniX[-1]+25),np.append(uniY-25,uniY[-1]+25))
|
||||
cs = ax.pcolor(X,Y,np.reshape(zPlot,(len(uniY),len(uniX))),cmap=cmap,norm=plotNorm)
|
||||
if colorbar:
|
||||
csB = plt.colorbar(cs,cax=ax.cax,ticks=clevel,format='%1.2e')
|
||||
# csB.on_mappable_changed(cs)
|
||||
ax.set_title(flag+' '+par,fontsize=8)
|
||||
return cs, csB
|
||||
return cs,None
|
||||
|
||||
|
||||
def plotPsudoSectNSDiff(ax,sectDict,arrayList,flag,par='abs',colorbar=True,colorNorm='SymLog',cLevel=None,contour=True,mask=None,useLog=False):
|
||||
|
||||
def sortInArr(arr):
|
||||
return np.sort(arr,order=['freq','x','y','z'])
|
||||
# Find the index for the slice
|
||||
indSect0 = np.where(sectDict.values()[0]==arrayList[0][sectDict.keys()[0]])
|
||||
indSect1 = np.where(sectDict.values()[0]==arrayList[1][sectDict.keys()[0]])
|
||||
# Extract and sort the mats
|
||||
arr0 = sortInArr(arrayList[0][indSect0])
|
||||
arr1 = sortInArr(arrayList[1][indSect1])
|
||||
|
||||
# Define the plot axes
|
||||
if 'x' in sectDict.keys()[0]:
|
||||
x0 = arr0['y']
|
||||
x1 = arr1['y']
|
||||
else:
|
||||
x0 = arr0['x']
|
||||
x1 = arr1['x']
|
||||
y0 = arr0['freq']
|
||||
y1 = arr1['freq']
|
||||
|
||||
|
||||
if par == 'abs':
|
||||
if useLog:
|
||||
zPlot = (np.log10(np.abs(arr0[flag])) - np.log10(np.abs(arr1[flag])))/np.log10(np.abs(arr1[flag]))
|
||||
else:
|
||||
zPlot = (np.abs(arr0[flag]) - np.abs(arr1[flag]))/np.abs(arr1[flag])
|
||||
if mask:
|
||||
maskInd = np.logical_or(np.abs(arr0[flag])< 1e-3,np.abs(arr1[flag]) < 1e-3)
|
||||
zPlot = np.ma.array(zPlot)
|
||||
zPlot[maskInd] = mask
|
||||
cmap = plt.get_cmap('RdYlBu')#seismic)
|
||||
elif par == 'ares':
|
||||
arF = 1/(8*np.pi**2*10**(-7))
|
||||
if useLog:
|
||||
zPlot = (np.log10((arF/arr0['freq'])*np.abs(arr0[flag])**2) - np.log10((arF/arr1['freq'])*np.abs(arr1[flag])**2))/np.log10((arF/arr1['freq'])*np.abs(arr1[flag])**2)
|
||||
else:
|
||||
zPlot = ((arF/arr0['freq'])*np.abs(arr0[flag])**2 - (arF/arr1['freq'])*np.abs(arr1[flag])**2)/((arF/arr1['freq'])*np.abs(arr1[flag])**2)
|
||||
if mask:
|
||||
maskInd = np.logical_or(np.abs(arr0[flag])< 1e-3,np.abs(arr1[flag]) < 1e-3)
|
||||
zPlot = np.ma.array(zPlot)
|
||||
zPlot[maskInd] = mask
|
||||
cmap = plt.get_cmap('Spectral')#seismic)
|
||||
|
||||
elif par == 'aphs':
|
||||
if useLog:
|
||||
zPlot = (np.log10(np.arctan2(arr0[flag].imag,arr0[flag].real)*(180/np.pi)) - np.log10(np.arctan2(arr1[flag].imag,arr1[flag].real)*(180/np.pi)) )/np.log10(np.arctan2(arr1[flag].imag,arr1[flag].real)*(180/np.pi))
|
||||
else:
|
||||
zPlot = ( np.arctan2(arr0[flag].imag,arr0[flag].real)*(180/np.pi) - np.arctan2(arr1[flag].imag,arr1[flag].real)*(180/np.pi) )/(np.arctan2(arr1[flag].imag,arr1[flag].real)*(180/np.pi))
|
||||
if mask:
|
||||
maskInd = np.logical_or(np.abs(arr0[flag])< 1e-3,np.abs(arr1[flag]) < 1e-3)
|
||||
zPlot = np.ma.array(zPlot)
|
||||
zPlot[maskInd] = mask
|
||||
cmap = plt.get_cmap('Spectral')#seismic)
|
||||
elif par == 'real':
|
||||
if useLog:
|
||||
zPlot = (np.log10(arr0[flag].real) - np.log10(arr1[flag].real))/np.log10(arr1[flag].real)
|
||||
else:
|
||||
zPlot = (arr0[flag].real - arr1[flag].real)/arr1[flag].real
|
||||
if mask:
|
||||
maskInd = np.logical_or(arr0[flag].real< 1e-3,arr1[flag].real < 1e-3)
|
||||
zPlot = np.ma.array(zPlot)
|
||||
zPlot[maskInd] = mask
|
||||
cmap = plt.get_cmap('Spectral') #('Spectral')
|
||||
|
||||
elif par == 'imag':
|
||||
if useLog:
|
||||
zPlot = (np.log10(arr0[flag].imag) - np.log10(arr1[flag].imag))/np.log10(arr1[flag].imag)
|
||||
else:
|
||||
zPlot = (arr0[flag].imag - arr1[flag].imag)/arr1[flag].imag
|
||||
if mask:
|
||||
maskInd = np.logical_or(arr0[flag].imag< 1e-3,arr1[flag].imag < 1e-3)
|
||||
zPlot = np.ma.array(zPlot)
|
||||
zPlot[maskInd] = mask
|
||||
cmap = plt.get_cmap('Spectral') #('RdYlBu')
|
||||
|
||||
if cLevel:
|
||||
zMax = np.log10(cLevel[1])
|
||||
zMin = np.log10(cLevel[0])
|
||||
else:
|
||||
zMax = (np.ceil(np.log10(np.abs(zPlot).max())))
|
||||
zMin = (np.floor(np.log10(np.abs(zPlot).min())))
|
||||
|
||||
|
||||
if colorNorm=='SymLog':
|
||||
level = np.concatenate((-np.logspace(zMax,zMin-.125,(zMax-zMin)*8+1,endpoint=True),np.logspace(zMin-.125,zMax,(zMax-zMin)*8+1,endpoint=True)))
|
||||
clevel = np.concatenate((-np.logspace(zMax,zMin,(zMax-zMin)*1+1,endpoint=True),np.logspace(zMin,zMax,(zMax-zMin)*1+1,endpoint=True)))
|
||||
plotNorm = colors.SymLogNorm(np.abs(level).min(),linscale=0.1)
|
||||
elif colorNorm=='Lin':
|
||||
if cLevel:
|
||||
level = np.arange(cLevel[0],cLevel[1]+.1,(cLevel[1] - cLevel[0])/50.)
|
||||
clevel = np.arange(cLevel[0],cLevel[1]+.1,(cLevel[1] - cLevel[0])/10.)
|
||||
else:
|
||||
level = np.arange(zPlot.min(),zPlot.max(),(zPlot.max() - zPlot.min())/50.)
|
||||
clevel = np.arange(zPlot.min(),zPlot.max(),(zPlot.max() - zPlot.min())/10.)
|
||||
plotNorm = colors.Normalize()
|
||||
elif colorNorm=='Log':
|
||||
level = np.logspace(zMin-.125,zMax,(zMax-zMin)*8+1,endpoint=True)
|
||||
clevel = np.logspace(zMin,zMax,(zMax-zMin)*2+1,endpoint=True)
|
||||
plotNorm = colors.LogNorm()
|
||||
if contour:
|
||||
cs = ax.tricontourf(x0,y0,zPlot*100,levels=level*100,cmap=cmap,norm=plotNorm,extend='both')#,extend='both')
|
||||
else:
|
||||
uniX,uniY = np.unique(x0),np.unique(y0)
|
||||
X,Y = np.meshgrid(np.append(uniX-25,uniX[-1]+25),np.append(uniY-25,uniY[-1]+25))
|
||||
cs = ax.pcolor(X,Y,np.reshape(zPlot,(len(uniY),len(uniX))),cmap=cmap,norm=plotNorm)
|
||||
if colorbar:
|
||||
csB = plt.colorbar(cs,cax=ax.cax,ticks=clevel*100,format='%1.2e')
|
||||
# csB.on_mappable_changed(cs)
|
||||
ax.set_title(flag+' '+par + ' diff',fontsize=8)
|
||||
return cs, csB
|
||||
return cs,None
|
||||
@@ -0,0 +1,46 @@
|
||||
import SimPEG as simpeg, numpy as np
|
||||
|
||||
def homo1DModelSource(mesh,freq,m_back):
|
||||
'''
|
||||
Function that calculates and return background fields for a 3D mesh and model.
|
||||
The calculuations use 1D field solution for a vertical slice throught model (south-western most column),
|
||||
which is assigned at the fields everywhere for the respective polarizations.2
|
||||
|
||||
:param Simpeg mesh object mesh: Holds information on the discretization
|
||||
:param float freq: The frequency to solve at
|
||||
:param np.array m_back: Background model of conductivity to base the calculations on.
|
||||
:rtype: numpy.ndarray (mesh.nE,2)
|
||||
:return: eBG_bp, E fields for the background model at both polarizations.
|
||||
|
||||
'''
|
||||
|
||||
# import
|
||||
from SimPEG.MT.Utils import get1DEfields
|
||||
# Get a 1d solution for a halfspace background
|
||||
mesh1d = simpeg.Mesh.TensorMesh([mesh.hz],np.array([mesh.x0[2]]))
|
||||
# Note: Everything is using e^iwt
|
||||
e0_1d = get1DEfields(mesh1d,mesh.r(m_back,'CC','CC','M')[0,0,:],freq)
|
||||
# Setup x (east) polarization (_x)
|
||||
ex_px = np.zeros(mesh.vnEx,dtype=complex)
|
||||
ey_px = np.zeros((mesh.nEy,1),dtype=complex)
|
||||
ez_px = np.zeros((mesh.nEz,1),dtype=complex)
|
||||
# Assign the source to ex_x
|
||||
for i in np.arange(mesh.vnEx[0]):
|
||||
for j in np.arange(mesh.vnEx[1]):
|
||||
ex_px[i,j,:] = -e0_1d
|
||||
eBG_px = np.vstack((simpeg.Utils.mkvc(ex_px,2),ey_px,ez_px))
|
||||
# Setup y (north) polarization (_py)
|
||||
ex_py = np.zeros((mesh.nEx,1), dtype='complex128')
|
||||
ey_py = np.zeros(mesh.vnEy, dtype='complex128')
|
||||
ez_py = np.zeros((mesh.nEz,1), dtype='complex128')
|
||||
# Assign the source to ey_py
|
||||
|
||||
for i in np.arange(mesh.vnEy[0]):
|
||||
for j in np.arange(mesh.vnEy[1]):
|
||||
ey_py[i,j,:] = e0_1d
|
||||
# ey_py[1:-1,1:-1,1:-1] = 0
|
||||
eBG_py = np.vstack((ex_py,simpeg.Utils.mkvc(ey_py,2),ez_py))
|
||||
|
||||
# Return the electric fields
|
||||
eBG_bp = np.hstack((eBG_px,eBG_py))
|
||||
return eBG_bp
|
||||
Reference in New Issue
Block a user