First commit after changed file framework
这个提交包含在:
+163
@@ -0,0 +1,163 @@
|
||||
import numpy as np
|
||||
import math
|
||||
from scipy.fftpack import fft
|
||||
from matplotlib import pyplot as plt
|
||||
from scipy.interpolate import interp1d
|
||||
from pyat.DataBase import DataBase
|
||||
|
||||
class BathyM:
|
||||
def __init__(self, ran=None, depth=None):
|
||||
self.r = ran
|
||||
self.d = depth
|
||||
|
||||
class SSP_:
|
||||
def __init__(self, r, z, c):
|
||||
self.r = r
|
||||
self.z = z
|
||||
self.c = c
|
||||
|
||||
class Sed:
|
||||
def __init__(self, z, cp, cs, rho, a_p, a_s):
|
||||
self.z = z
|
||||
self.cp = cp
|
||||
self.cs = cs
|
||||
self.rho = rho
|
||||
self.a_p = a_p
|
||||
self.a_s = a_s
|
||||
|
||||
class Base:
|
||||
def __init__(self, cp, cs, rho, a_p, a_s):
|
||||
self.cp = cp
|
||||
self.cs = cs
|
||||
self.rho = rho
|
||||
self.a_p = a_p
|
||||
self.a_s = a_s
|
||||
|
||||
class Coord:
|
||||
def __init__(self, lon, lat):
|
||||
self.lon = lon
|
||||
self.lat = lat
|
||||
|
||||
def GetSeaDepth(data, N, coordS, R, azi):
|
||||
r = np.linspace(0, R, N)
|
||||
lon = coordS.lon + r * math.sin(azi) / (111 * math.cos(coordS.lat / 180 * math.pi))
|
||||
lat = coordS.lat + r * math.cos(azi) / 111
|
||||
z = np.zeros(N)
|
||||
for it in range(N):
|
||||
data.set_coord(lat[it], lon[it])
|
||||
z[it] = data.get_bottomDepth()
|
||||
return r, z
|
||||
|
||||
|
||||
def GetEnv(data, freq, coordS, coordR=None, R=None, azi=None):
|
||||
if coordR == None:
|
||||
azi = azi/180*math.pi
|
||||
lon = coordS.lon + R * math.sin(azi) / (111 * math.cos(coordS.lat/180*math.pi))
|
||||
lat = coordS.lat + R * math.cos(azi) / 111
|
||||
coordR = Coord(lon, lat)
|
||||
|
||||
if R == None:
|
||||
x = (coordR.lon - coordS.lon) * (111 * math.cos(coordS.lat/180*math.pi))
|
||||
y = (coordR.lat - coordS.lat) * 111
|
||||
R = math.sqrt(x*x + y*y)
|
||||
if y > 0:
|
||||
azi = math.atan(x / y)
|
||||
elif y == 0:
|
||||
azi = np.sign(x) * math.pi / 2
|
||||
else:
|
||||
azi = math.atan(x / y) + math.pi
|
||||
|
||||
# Get Bathymetry
|
||||
N = math.ceil(1000 * R / (1500 / freq))
|
||||
#print("N = {}".format(N))
|
||||
if N == 1:
|
||||
N1 = 2
|
||||
else:
|
||||
r, z = GetSeaDepth(data, N, coordS, R, azi)
|
||||
Z = np.square(abs(fft(z-np.mean(z))))
|
||||
s1 = np.sum(Z[0:math.ceil(N / 2)-1])
|
||||
s2 = 0
|
||||
for it in range(math.ceil(N / 2)):
|
||||
s2 = s2 + Z[it]
|
||||
if s2 / s1 > 0.98:
|
||||
break
|
||||
N1 = max(2 * it, 1)
|
||||
# plt.plot(r, z)
|
||||
|
||||
#print("N1 = {}".format(N1))
|
||||
r, z = GetSeaDepth(data, N1, coordS, R, azi)
|
||||
bathym = BathyM(r, z)
|
||||
#plt.plot(r, z)
|
||||
#plt.gca().invert_yaxis()
|
||||
#plt.show()
|
||||
|
||||
# Get Sound Speed Profile
|
||||
|
||||
# N2 = math.ceil(1000 * R / (30 * 1500 / freq))
|
||||
N2 = N1
|
||||
# N2=math.ceil(N2/2)
|
||||
r = np.linspace(0, R, N2)
|
||||
lon = coordS.lon + r * math.sin(azi) / (111 * math.cos(coordS.lat / 180 * math.pi))
|
||||
lat = coordS.lat + r * math.cos(azi) / 111
|
||||
ssp = []
|
||||
|
||||
z_ssp = np.arange(0, 30, 1)
|
||||
z_ssp = np.append(z_ssp, np.arange(30, 100, 10))
|
||||
z_ssp = np.append(z_ssp, np.arange(100, 2000, 50))
|
||||
z_ssp = np.append(z_ssp, np.arange(2000, 10000, 100))
|
||||
z_ssp = np.append(z_ssp, np.ceil(bathym.d))
|
||||
z_ssp = np.sort(z_ssp)
|
||||
z_ssp = np.unique(z_ssp)
|
||||
|
||||
|
||||
for it in range(N2):
|
||||
data.set_coord(lat[it], lon[it])
|
||||
velFullPf = data.get_velFullProfile()
|
||||
itp1 = interp1d(velFullPf.x, velFullPf.y)
|
||||
z_idx = (z_ssp <= velFullPf.x[-1]) & (z_ssp >= 0)
|
||||
ssp_z = z_ssp[z_idx]
|
||||
ssp_c = itp1(ssp_z)
|
||||
ssp.append(SSP_(r[it], ssp_z, ssp_c))
|
||||
#ssp.append(SSP_(r[it], velFullPf.x, velFullPf.y))
|
||||
#plt.plot(velFullPf.y, velFullPf.x)
|
||||
|
||||
# plt.gca().invert_yaxis()
|
||||
# plt.show()
|
||||
|
||||
# Sediment
|
||||
sed = []
|
||||
z = np.array([0, 50])
|
||||
cp = np.array([1550, 1590])
|
||||
cs = np.array([0, 0])
|
||||
rho = np.array([1.3, 1.5])
|
||||
a_p = np.array([0.1, 0.1])
|
||||
a_s = np.array([0, 0])
|
||||
for it in range(N2):
|
||||
sed.append(Sed(z, cp, cs, rho, a_p, a_s))
|
||||
|
||||
# Base
|
||||
base = []
|
||||
Cb_p = 1550 # Sound speed of P-wave
|
||||
Cb_s = 0 # Sound speed of S-wave
|
||||
Rhob = 1.4 # Density of sea bottom
|
||||
Ab_p = 0.2 # Attenuation of P-wave
|
||||
Ab_s = 0 # Attenuation of S-wave
|
||||
for it in range(N2):
|
||||
base.append(Base(Cb_p, Cb_s, Rhob, Ab_p, Ab_s))
|
||||
|
||||
return bathym, ssp, sed, base
|
||||
|
||||
# if __name__ == "__main__":
|
||||
# freq = 25
|
||||
# # 定义坐标
|
||||
# lat = 18.00
|
||||
# lon = 114.00
|
||||
# # 定义时间段
|
||||
# timeIndex = db.timeDict['Annual']
|
||||
# # 创建类
|
||||
# data = db.DataBase()
|
||||
# # 设置时间段
|
||||
# data.set_timePeriod(timeIndex)
|
||||
|
||||
# #[bathym, ssp, sed, base] = GetEnv(data, freq, Coord(lon, lat), R=111, azi=-90)
|
||||
# [bathym, ssp, sed, base] = GetEnv(data, freq, Coord(lon, lat), Coord(113,19))
|
||||
+348
@@ -0,0 +1,348 @@
|
||||
import numpy as np
|
||||
from scipy.interpolate import Akima1DInterpolator, interp1d
|
||||
from netCDF4 import Dataset
|
||||
from pyat.ProfileDataType import Profile
|
||||
|
||||
'''
|
||||
************************************************************
|
||||
该模块用于从数据库中, 获取剖面信息
|
||||
************************************************************
|
||||
'''
|
||||
|
||||
# 时间段标识
|
||||
|
||||
|
||||
|
||||
# def MunkFormula(z, v1, epsilon, z1):
|
||||
# eta = 2*(z-z1)/z1
|
||||
# return v1*(1+epsilon*(np.exp(-eta)+eta-1))
|
||||
|
||||
def soundSpeed(tem, sal, dep):
|
||||
'''
|
||||
声速计算公式
|
||||
'''
|
||||
# C = 1449.2 + 4.6*T - 0.055*T^2 + 0.00029*T^3 + (1.34 - 0.01*T)(S-35) + 0.017*D
|
||||
# 式中:T为海⽔测点的温度,单位为℃;S为海⽔测点的盐度,单位为‰;D为海⽔测点的深度,单位为m。
|
||||
vel = 1449.2 + 4.6*tem - 0.055*tem*tem + 0.00029 * \
|
||||
tem*tem*tem + (1.34 - 0.01*tem) * \
|
||||
(sal-35.0) + 0.017*dep
|
||||
return vel
|
||||
|
||||
|
||||
class DataBase():
|
||||
"""
|
||||
获取数据库中的剖面信息
|
||||
"""
|
||||
def __init__(self,ETOPO1path,STpath):
|
||||
# 打开ETOPO1数据
|
||||
fileETOPO1 = ETOPO1path+'/ETOPO1_Bed_g_gmt4.nc'
|
||||
dataETOPO1 = Dataset(fileETOPO1)
|
||||
# 获取ETOPO1网格
|
||||
self.latGrid1 = dataETOPO1.variables['y'][:]
|
||||
self.lonGrid1 = dataETOPO1.variables['x'][:]
|
||||
# 获取海深数据
|
||||
self.botGrid = -dataETOPO1.variables['z'][:]
|
||||
self.STpath=STpath
|
||||
return
|
||||
|
||||
def clearVar(self):
|
||||
"""
|
||||
清空变量
|
||||
"""
|
||||
self.botDep = None
|
||||
self.salRawPf = None
|
||||
self.temRawPf = None
|
||||
self.velRawPf = None
|
||||
self.velInterpPf = None
|
||||
self.velExtPf = None
|
||||
self.velFullPf = None
|
||||
self.isValid = True
|
||||
return
|
||||
|
||||
def set_timePeriod(self, timeIndex):
|
||||
"""
|
||||
设置时间段
|
||||
"""
|
||||
self.timeIndex = timeIndex
|
||||
# 打开WOA18数据
|
||||
#fileWOA18sal = '.\WOA18\woa18_A5B7_s' + timeIndex + '_04.nc'
|
||||
#fileWOA18tem = '.\WOA18\woa18_A5B7_t' + timeIndex + '_04.nc'
|
||||
fileST=self.STpath+'/CA'+timeIndex+'.nc'
|
||||
dataST = Dataset(fileST)
|
||||
# 获取WOA18网格
|
||||
self.latGrid2 = dataST.variables['lat'][:]
|
||||
self.lonGrid2 = dataST.variables['lon'][:]
|
||||
# 获取深度数据
|
||||
self.depthGrid = dataST.variables['zlev'][:]*(-1)
|
||||
# 获取盐度数据
|
||||
self.salGrid = np.squeeze(dataST.variables['SALT'][:])
|
||||
# 获取温度数据
|
||||
self.temGrid = np.squeeze(
|
||||
dataST.variables['THETA'][:])
|
||||
self.clearVar()
|
||||
return
|
||||
|
||||
def set_coord(self, lat, lon):
|
||||
"""
|
||||
设置坐标
|
||||
"""
|
||||
self.lat = lat
|
||||
self.lon = lon
|
||||
self.clearVar()
|
||||
return
|
||||
|
||||
def interpBilinear(self, latId, lonId, dataGrid, dataTpye):
|
||||
"""
|
||||
双线性插值
|
||||
"""
|
||||
latId0 = int(np.ceil(latId))
|
||||
lonId0 = int(np.ceil(lonId))
|
||||
a = latId - latId0
|
||||
b = lonId - lonId0
|
||||
if (dataTpye == 1):
|
||||
data0 = dataGrid[latId0, lonId0]
|
||||
data1 = dataGrid[latId0+1, lonId0]
|
||||
data2 = dataGrid[latId0+1, lonId0+1]
|
||||
data3 = dataGrid[latId0, lonId0+1]
|
||||
else:
|
||||
data0 = dataGrid[:, latId0, lonId0]
|
||||
data1 = dataGrid[:, latId0+1, lonId0]
|
||||
data2 = dataGrid[:, latId0+1, lonId0+1]
|
||||
data3 = dataGrid[:, latId0, lonId0+1]
|
||||
data01 = (1-a)*data0+a*data1
|
||||
data32 = (1-a)*data3+a*data2
|
||||
data = (1-b)*data01+b*data32
|
||||
return data
|
||||
|
||||
def normCoord(self, latGrid, lonGrid):
|
||||
"""
|
||||
坐标单位化
|
||||
"""
|
||||
lat0 = latGrid[0]
|
||||
lon0 = lonGrid[0]
|
||||
dlat = latGrid[1]-latGrid[0]
|
||||
dlon = lonGrid[1]-lonGrid[0]
|
||||
latId = (self.lat - lat0)/dlat
|
||||
lonId = (self.lon - lon0)/dlon
|
||||
return (latId, lonId)
|
||||
|
||||
def get_bottomDepth(self):
|
||||
"""
|
||||
获得海底深度
|
||||
"""
|
||||
if (self.botDep == None):
|
||||
# 单位化经纬度
|
||||
(latId, lonId) = self.normCoord(self.latGrid1, self.lonGrid1)
|
||||
# 获取网格点海深
|
||||
self.botDep = self.interpBilinear(latId, lonId, self.botGrid, 1)
|
||||
return self.botDep
|
||||
|
||||
def get_salRawProfile(self):
|
||||
"""
|
||||
获得原始盐度剖面
|
||||
"""
|
||||
if (self.salRawPf == None):
|
||||
botDep = self.get_bottomDepth()
|
||||
# 单位化经纬度
|
||||
(latId, lonId) = self.normCoord(self.latGrid2, self.lonGrid2)
|
||||
# 获取盐度剖面信息
|
||||
sal = self.interpBilinear(latId, lonId, self.salGrid, 2)
|
||||
# 获取有效数据段
|
||||
dep = self.depthGrid[sal.mask == False]
|
||||
sal = sal[sal.mask == False]
|
||||
dep = dep.flatten()
|
||||
sal = sal.flatten()
|
||||
# 若为空,则为无效数据
|
||||
if sal.size == 0:
|
||||
self.isValid = False
|
||||
# 剖面赋值
|
||||
salRawPf = Profile()
|
||||
salRawPf.set_data(dep, sal)
|
||||
salRawPf.set_coord(self.lat, self.lon)
|
||||
salRawPf.set_bottomDepth(botDep)
|
||||
self.salRawPf = salRawPf
|
||||
return self.salRawPf
|
||||
|
||||
def get_temRawProfile(self):
|
||||
"""
|
||||
获得原始温度剖面
|
||||
"""
|
||||
if (self.temRawPf == None):
|
||||
botDep = self.get_bottomDepth()
|
||||
# 单位化经纬度
|
||||
(latId, lonId) = self.normCoord(self.latGrid2, self.lonGrid2)
|
||||
# 获取温度剖面信息
|
||||
tem = self.interpBilinear(latId, lonId, self.temGrid, 2)
|
||||
# 获取有效数据段
|
||||
dep = self.depthGrid[tem.mask == False]
|
||||
tem = tem[tem.mask == False]
|
||||
dep = dep.flatten()
|
||||
tem = tem.flatten()
|
||||
# 若为空,则为无效数据
|
||||
if tem.size == 0:
|
||||
self.isValid = False
|
||||
# 剖面赋值
|
||||
temRawPf = Profile()
|
||||
temRawPf.set_data(dep, tem)
|
||||
temRawPf.set_coord(self.lat, self.lon)
|
||||
temRawPf.set_bottomDepth(botDep)
|
||||
self.temRawPf = temRawPf
|
||||
return self.temRawPf
|
||||
|
||||
def get_velRawProfile(self):
|
||||
"""
|
||||
获得原始声速剖面
|
||||
"""
|
||||
if (self.velRawPf == None):
|
||||
botDep = self.get_bottomDepth()
|
||||
# 获取温盐深数据
|
||||
dep = self.get_salRawProfile().x
|
||||
sal = self.get_salRawProfile().y
|
||||
tem = self.get_temRawProfile().y
|
||||
# 计算声速
|
||||
if self.isValid == True:
|
||||
vel = soundSpeed(tem, sal, dep)
|
||||
else:
|
||||
dep = np.array([0])
|
||||
vel = np.array([0])
|
||||
# 剖面赋值
|
||||
velRawPf = Profile()
|
||||
velRawPf.set_data(dep, vel)
|
||||
velRawPf.set_coord(self.lat, self.lon)
|
||||
velRawPf.set_bottomDepth(botDep)
|
||||
self.velRawPf = velRawPf
|
||||
return self.velRawPf
|
||||
|
||||
def get_velInterpProfile(self):
|
||||
"""
|
||||
获得插值后的声速剖面
|
||||
将非等距离采样填充为深度间隔为1m的序列, 并应用Akima插值算法, 对数据进行插值
|
||||
"""
|
||||
if (self.velInterpPf == None):
|
||||
botDep = self.get_bottomDepth()
|
||||
if self.isValid == True:
|
||||
# 获得原始声速剖面数据
|
||||
dep = self.get_velRawProfile().x
|
||||
vel = self.get_velRawProfile().y
|
||||
# 对剖面进行垂向插值处理,将非等距离采样填充为深度间隔为1m的序列
|
||||
depInterp = np.arange(0, dep[-1]+1, 1)
|
||||
# 应用Akima插值算法,对数据进行插值
|
||||
if dep.size == 1:
|
||||
velInterp = vel
|
||||
else:
|
||||
func = Akima1DInterpolator(dep, vel)
|
||||
velInterp = func(depInterp)
|
||||
else:
|
||||
depInterp = np.array([0])
|
||||
velInterp = np.array([0])
|
||||
# 剖面赋值
|
||||
velInterpPf = Profile()
|
||||
velInterpPf.set_data(depInterp, velInterp)
|
||||
velInterpPf.set_coord(self.lat, self.lon)
|
||||
velInterpPf.set_bottomDepth(botDep)
|
||||
self.velInterpPf = velInterpPf
|
||||
return self.velInterpPf
|
||||
|
||||
def get_velExtProfile(self):
|
||||
"""
|
||||
获得延拓后的声速剖面
|
||||
"""
|
||||
if (self.velExtPf == None):
|
||||
botDep = self.get_bottomDepth()
|
||||
if self.isValid == True:
|
||||
# 获得原始声速剖面数据
|
||||
dep = self.get_velRawProfile().x
|
||||
vel = self.get_velRawProfile().y
|
||||
# 获得剖面最低处温盐值
|
||||
tem = self.get_temRawProfile().y[-1]
|
||||
sal = self.get_salRawProfile().y[-1]
|
||||
# 延拓部分深度序列
|
||||
depExt = np.arange(np.ceil(dep[-1]), botDep+1)
|
||||
# 按照声速公式延拓,假设温盐不变,仅深度变化
|
||||
velExt = soundSpeed(tem, sal, depExt)
|
||||
else:
|
||||
depExt = np.array([0])
|
||||
velExt = np.array([0])
|
||||
# 剖面赋值
|
||||
velExtPf = Profile()
|
||||
velExtPf.set_data(depExt, velExt)
|
||||
velExtPf.set_coord(self.lat, self.lon)
|
||||
velExtPf.set_bottomDepth(botDep)
|
||||
self.velExtPf = velExtPf
|
||||
return self.velExtPf
|
||||
|
||||
def get_velFullProfile(self):
|
||||
'''
|
||||
获得全海深声速剖面
|
||||
'''
|
||||
if (self.velFullPf == None):
|
||||
botDep = self.get_bottomDepth()
|
||||
if self.isValid == True:
|
||||
# 插值后的速度剖面
|
||||
depInterp = self.get_velInterpProfile().x
|
||||
velInterp = self.get_velInterpProfile().y
|
||||
# 延拓后的速度剖面
|
||||
depExt = self.get_velExtProfile().x
|
||||
velExt = self.get_velExtProfile().y
|
||||
# 全海深声速剖面
|
||||
depFull = np.concatenate((depInterp, depExt))
|
||||
velFull = np.concatenate((velInterp, velExt))
|
||||
else:
|
||||
depFull = np.array([0])
|
||||
velFull = np.array([0])
|
||||
# 剖面赋值
|
||||
velFullPf = Profile()
|
||||
velFullPf.set_data(depFull, velFull)
|
||||
velFullPf.set_coord(self.lat, self.lon)
|
||||
velFullPf.set_bottomDepth(botDep)
|
||||
self.velFullPf = velFullPf
|
||||
return self.velFullPf
|
||||
|
||||
def export_velFullProfile_txt(self, filePath):
|
||||
'''
|
||||
速度剖面导出txt文件
|
||||
'''
|
||||
velPf = self.get_velFullProfile()
|
||||
lat = velPf.lat
|
||||
lon = velPf.lon
|
||||
botDep = velPf.botDep
|
||||
dep = velPf.x
|
||||
vel = velPf.y
|
||||
# 导出文本
|
||||
line1 = 'lat[degree north], {0:>7.4f}, lon[degree east], {1:>7.4f}, BottomDepth[m], {2:>5.0f}\n'.format(
|
||||
lat, lon, botDep)
|
||||
line2 = 'depth[m], velocity[m/s]'
|
||||
np.savetxt(filePath, np.stack((dep, vel), -1),
|
||||
fmt='%.5e', delimiter=',', comments='', header=line1+line2)
|
||||
|
||||
def export_velFullProfile_nc(self, filePath):
|
||||
'''
|
||||
速度剖面导出nc文件
|
||||
'''
|
||||
velPf = self.get_velFullProfile()
|
||||
lat = velPf.lat
|
||||
lon = velPf.lon
|
||||
botDep = velPf.botDep
|
||||
dep = velPf.x
|
||||
vel = velPf.y
|
||||
|
||||
data = Dataset(filePath, 'w', format='NETCDF4')
|
||||
data.createDimension('lon', 1)
|
||||
data.createDimension('lat', 1)
|
||||
data.createDimension('botDep', 1)
|
||||
data.createDimension('dep', dep.size)
|
||||
data.createDimension('vel', vel.size)
|
||||
|
||||
data.createVariable('lon', 'f', ('lon'))
|
||||
data.createVariable('lat', 'f', ('lat'))
|
||||
data.createVariable('botDep', 'f', ('botDep'))
|
||||
data.createVariable('dep', 'f', ('dep'))
|
||||
data.createVariable('vel', 'f', ('vel'))
|
||||
|
||||
data.variables['lat'][:] = lat
|
||||
data.variables['lon'][:] = lon
|
||||
data.variables['botDep'][:] = botDep
|
||||
data.variables['dep'][:] = dep
|
||||
data.variables['vel'][:] = vel
|
||||
|
||||
data.close()
|
||||
+89
@@ -0,0 +1,89 @@
|
||||
import numpy as np
|
||||
from scipy.fft import fft
|
||||
import soundfile as sf
|
||||
from numpy import log10
|
||||
import math
|
||||
|
||||
# Average Noise Spectral Level
|
||||
def ANSL(u, fs, M, A=0, N=None, D=None, w=None):
|
||||
"""
|
||||
:param u: Voltage data (Unit: V)
|
||||
:param fs: Sampling rate (Unit: Hz)
|
||||
:param M: Sensitivity (Unit: dBV re 1uPa)
|
||||
:param A: Preamplifier (Unit: dB)
|
||||
:param N: Segment length
|
||||
:param D: Overlap length
|
||||
:param w: Window
|
||||
:return: Spectral level
|
||||
"""
|
||||
L = len(u)
|
||||
if N == None:
|
||||
if L >= fs:
|
||||
N = round(fs)
|
||||
else:
|
||||
N = L
|
||||
elif N > L:
|
||||
raise Exception("Segment length is larger than data length.")
|
||||
|
||||
if D == None:
|
||||
D = 0
|
||||
|
||||
if w is None:
|
||||
w = np.hamming(N)
|
||||
G = np.mean(np.square(abs(w)))
|
||||
|
||||
K = 1 + math.floor((L-N) / (N-D))
|
||||
|
||||
T = N / fs
|
||||
df = 1 / T
|
||||
X2 = np.zeros(N)
|
||||
for k in range(K):
|
||||
X = fft(w * u[round(k*(N-D)):round(k*(N-D)+N)])
|
||||
X2 += np.square(abs(X))
|
||||
|
||||
spl = 10 * log10(X2) - 10 * log10(N*fs*G*K/2) - M - A
|
||||
freq = np.arange(0, fs/2, df)
|
||||
spl = spl[0:len(freq)]
|
||||
|
||||
return freq, spl
|
||||
|
||||
|
||||
# 1/3 Octave Spectral Level
|
||||
def OneThirdOct_SPL(freq, spl, f_start, Npoints):
|
||||
"""
|
||||
:param freq: Frequency
|
||||
:param spl: 1 Hz bandwidth spectral level
|
||||
:param f_start: Starting frequency of the 1/3 octave
|
||||
:param Npoints: The number of frequency points
|
||||
:return: 1/3 Octave Spectral Level
|
||||
"""
|
||||
fC = f_start * np.power(2, np.arange(Npoints)/3)
|
||||
fL = f_start * np.power(2, np.arange(Npoints)/3 - 1.0/6)
|
||||
fH = f_start * np.power(2, np.arange(Npoints)/3 + 1.0/6)
|
||||
|
||||
spl_oct = np.zeros(Npoints)
|
||||
for it in range(Npoints):
|
||||
# idx = (freq >= fL[it]) & (freq <= fH[it])
|
||||
idx = np.where((freq >= fL[it]) & (freq <= fH[it]))
|
||||
# print(idx)
|
||||
# print(spl[idx])
|
||||
spl_oct[it] = 10 * log10(np.mean(np.power(10, spl[idx]/10)))
|
||||
# print(spl_oct[it])
|
||||
|
||||
return fC, spl_oct
|
||||
|
||||
def call_oanp(soundFile, M, A=0):
|
||||
[x, fs] = sf.read(soundFile)
|
||||
u = 3 * x # Voltage data
|
||||
# M = -164.0 # Sensitivity
|
||||
# A = 0 # Preamplifier
|
||||
N = fs # Segment length
|
||||
D = N/2 # Overlap length
|
||||
w = np.hanning(N) # Window
|
||||
|
||||
# Average Noise Spectral Level
|
||||
[freq, spl] = ANSL(u, fs, M, A, N, D, w)
|
||||
# 1/3 Octave Spectral Level
|
||||
[fC, spl_oct] = OneThirdOct_SPL(freq, spl, f_start=20, Npoints=28)
|
||||
|
||||
return [freq, spl, fC, spl_oct]
|
||||
@@ -0,0 +1,53 @@
|
||||
class Profile():
|
||||
"""
|
||||
记录剖面数据
|
||||
"""
|
||||
|
||||
def __init__(self):
|
||||
self.x = None
|
||||
self.y = None
|
||||
self.lat = None
|
||||
self.lon = None
|
||||
self.botDep = None
|
||||
|
||||
def set_data(self, x, y):
|
||||
'''
|
||||
设置曲线
|
||||
'''
|
||||
self.x = x
|
||||
self.y = y
|
||||
|
||||
def set_coord(self, lat, lon):
|
||||
'''
|
||||
设置坐标
|
||||
'''
|
||||
self.lat = lat
|
||||
self.lon = lon
|
||||
|
||||
def set_bottomDepth(self, botDep):
|
||||
'''
|
||||
设置深度
|
||||
'''
|
||||
self.botDep = botDep
|
||||
|
||||
|
||||
class Channel():
|
||||
'''
|
||||
储存声道道信息
|
||||
'''
|
||||
|
||||
def __init__(self):
|
||||
self.exist = False
|
||||
self.depAxis = None
|
||||
self.velAxis = None
|
||||
|
||||
|
||||
class SpringLayer():
|
||||
'''
|
||||
储存跃层信息
|
||||
'''
|
||||
|
||||
def __init__(self):
|
||||
self.exist = False
|
||||
self.limit = None
|
||||
self.intensity = None
|
||||
+168
@@ -0,0 +1,168 @@
|
||||
import unicodedata
|
||||
import numpy as np
|
||||
from pyat.ProfileDataType import Profile
|
||||
from scipy.interpolate import interp1d
|
||||
from scipy.signal import butter, filtfilt
|
||||
from pyat.DataBase import DataBase
|
||||
|
||||
'''
|
||||
************************************************************
|
||||
该模块用读取实测的声速剖面
|
||||
************************************************************
|
||||
'''
|
||||
|
||||
def is_number(s):
|
||||
'''
|
||||
判断是否为数字
|
||||
'''
|
||||
try:
|
||||
float(s)
|
||||
return True
|
||||
except ValueError:
|
||||
pass
|
||||
|
||||
try:
|
||||
unicodedata.numeric(s)
|
||||
return True
|
||||
except (TypeError, ValueError):
|
||||
pass
|
||||
|
||||
return False
|
||||
|
||||
def readRawProfile(fname):
|
||||
# 读取经纬度, 海深等信息
|
||||
f = open(fname)
|
||||
line = f.readline()
|
||||
line = line.split(',')
|
||||
if is_number(line[1]):
|
||||
lat = float(line[1])
|
||||
else:
|
||||
lat = None
|
||||
if is_number(line[3]):
|
||||
lon = float(line[3])
|
||||
else:
|
||||
lon = None
|
||||
if is_number(line[5]):
|
||||
botDep = float(line[5])
|
||||
else:
|
||||
botDep = None
|
||||
f.close()
|
||||
# 读取数据
|
||||
data = np.loadtxt(fname, skiprows=2,delimiter=',')
|
||||
# 剖面赋值
|
||||
velPf = Profile()
|
||||
velPf.set_data(data[:, 0], data[:, 1])
|
||||
velPf.set_coord(lat, lon)
|
||||
velPf.set_bottomDepth(botDep)
|
||||
return velPf
|
||||
|
||||
|
||||
def removeHead(velPf):
|
||||
'''
|
||||
去掉剖面头部异常数据, 刚入水的
|
||||
'''
|
||||
lat = velPf.lat
|
||||
lon = velPf.lon
|
||||
botDep = velPf.botDep
|
||||
dep = velPf.x
|
||||
vel = velPf.y
|
||||
# 梯度阈值
|
||||
gradc = 1.0
|
||||
# 去掉前面一段(刚入水)变化计较剧烈的区域
|
||||
for i in range(dep.size-1):
|
||||
grad = np.abs((vel[i+1]-vel[i])/(dep[i+1]-dep[i]))
|
||||
if grad < gradc:
|
||||
break
|
||||
dep = dep[i+1:]
|
||||
vel = vel[i+1:]
|
||||
# 剖面赋值
|
||||
velPf = Profile()
|
||||
velPf.set_data(dep, vel)
|
||||
velPf.set_coord(lat, lon)
|
||||
velPf.set_bottomDepth(botDep)
|
||||
return velPf
|
||||
|
||||
|
||||
def removeTail(velPf, ETOPO1Path, STPath):
|
||||
'''
|
||||
去掉剖面尾部异常数据, 触底后的
|
||||
'''
|
||||
lat = velPf.lat
|
||||
lon = velPf.lon
|
||||
botDep = velPf.botDep
|
||||
dep = velPf.x
|
||||
vel = velPf.y
|
||||
# 如果没有给定深度,则直接从数据库中提取
|
||||
if botDep == None:
|
||||
data = DataBase(ETOPO1Path, STPath)
|
||||
data.set_coord(lat, lon)
|
||||
botDep = data.get_bottomDepth()
|
||||
# 过滤掉触底后的曲线
|
||||
temp = dep < botDep
|
||||
dep = dep[temp]
|
||||
vel = vel[temp]
|
||||
# 剖面赋值
|
||||
velPf = Profile()
|
||||
velPf.set_data(dep, vel)
|
||||
velPf.set_coord(lat, lon)
|
||||
velPf.set_bottomDepth(botDep)
|
||||
return velPf
|
||||
|
||||
|
||||
def resampleProfile(velPf):
|
||||
'''
|
||||
重采样剖面, 间隔1m采样
|
||||
'''
|
||||
lat = velPf.lat
|
||||
lon = velPf.lon
|
||||
botDep = velPf.botDep
|
||||
dep = velPf.x
|
||||
vel = velPf.y
|
||||
# 得到等间距的采样曲线
|
||||
depInterp = np.arange(0, dep[-1])
|
||||
f = interp1d(dep, vel, fill_value='extrapolate')
|
||||
velInterp = f(depInterp)
|
||||
# 剖面赋值
|
||||
velPf = Profile()
|
||||
velPf.set_data(depInterp, velInterp)
|
||||
velPf.set_coord(lat, lon)
|
||||
velPf.set_bottomDepth(botDep)
|
||||
return velPf
|
||||
|
||||
|
||||
def lowPassFilter(velPf):
|
||||
'''
|
||||
低通滤波器, 使曲线平滑
|
||||
'''
|
||||
lat = velPf.lat
|
||||
lon = velPf.lon
|
||||
botDep = velPf.botDep
|
||||
dep = velPf.x
|
||||
vel = velPf.y
|
||||
# 设计数字滤波器
|
||||
freqc = 0.05
|
||||
order = 2
|
||||
b, a = butter(order, freqc)
|
||||
# 对曲线进行滤波
|
||||
vel = filtfilt(b, a, vel)
|
||||
# 剖面赋值
|
||||
velPf = Profile()
|
||||
velPf.set_data(dep, vel)
|
||||
velPf.set_coord(lat, lon)
|
||||
velPf.set_bottomDepth(botDep)
|
||||
return velPf
|
||||
|
||||
|
||||
def processProfile(velRawPf, ETOPO1Path, STPath):
|
||||
'''
|
||||
对原始剖面数据进行处理, 得到处理后的剖面
|
||||
'''
|
||||
# 去掉刚入水,剧烈变化部分
|
||||
velPf = removeHead(velRawPf)
|
||||
# 去掉触底后,无效部分
|
||||
velPf = removeTail(velPf, ETOPO1Path, STPath)
|
||||
# 等间距重采样
|
||||
velPf = resampleProfile(velPf)
|
||||
# 低通滤波
|
||||
velPf = lowPassFilter(velPf)
|
||||
return velPf
|
||||
可执行文件
+237
@@ -0,0 +1,237 @@
|
||||
import numpy as np
|
||||
from scipy.signal import find_peaks
|
||||
from pyat.ProfileDataType import Channel, SpringLayer
|
||||
|
||||
'''
|
||||
************************************************************
|
||||
该模块用于分析剖面, 根据标准化剖面,得到声道, 跃层分析结果
|
||||
************************************************************
|
||||
'''
|
||||
|
||||
|
||||
class ProfileTool():
|
||||
'''
|
||||
剖面分析工具, 根据标准化剖面,得到声道, 跃层分析结果
|
||||
'''
|
||||
|
||||
def __init__(self):
|
||||
self.clearVar()
|
||||
|
||||
def clearVar(self):
|
||||
"""
|
||||
清空函数调用记录
|
||||
"""
|
||||
self.maxTurn = None
|
||||
self.minTurn = None
|
||||
self.surfCh = None
|
||||
self.deepCh = None
|
||||
self.surfSL = None
|
||||
self.mainSL = None
|
||||
return
|
||||
|
||||
def set_profile(self, velPf):
|
||||
'''
|
||||
设置剖面
|
||||
'''
|
||||
self.velPf = velPf
|
||||
self.clearVar()
|
||||
|
||||
def findMaxTurn(self):
|
||||
'''
|
||||
寻找最大值的拐点
|
||||
'''
|
||||
if (self.maxTurn == None):
|
||||
dep = self.velPf.x
|
||||
vel = self.velPf.y
|
||||
# 寻找极大值,设定窗口宽度为20m
|
||||
peaks, properties = find_peaks(vel, width=20)
|
||||
if (peaks.size != 0):
|
||||
peaks = peaks[vel[peaks] > vel[0]]
|
||||
if (peaks.size != 0):
|
||||
# 定位极大值中最大的那个
|
||||
peak = peaks[np.argmax(vel[peaks])]
|
||||
self.maxTurn = peak
|
||||
else:
|
||||
self.maxTurn = -1
|
||||
return self.maxTurn
|
||||
|
||||
def findMinTrun(self):
|
||||
'''
|
||||
寻找最小值的拐点
|
||||
'''
|
||||
if (self.minTurn == None):
|
||||
dep = self.velPf.x
|
||||
vel = self.velPf.y
|
||||
# 寻找最小值拐点,设定窗口宽度为20m
|
||||
peaks, properties = find_peaks(-vel, width=20)
|
||||
if (peaks.size != 0):
|
||||
peaks = peaks[vel[peaks] < vel[0]]
|
||||
if (peaks.size != 0):
|
||||
# 定位极小值中最小的那个
|
||||
peak = peaks[np.argmin(vel[peaks])]
|
||||
self.minTurn = peak
|
||||
else:
|
||||
self.minTurn = -1
|
||||
return self.minTurn
|
||||
|
||||
def get_surfaceChannel(self):
|
||||
'''
|
||||
计算表面声道
|
||||
'''
|
||||
if (self.surfCh == None):
|
||||
dep = self.velPf.x
|
||||
vel = self.velPf.y
|
||||
maxTurn = self.findMaxTurn()
|
||||
minTurn = self.findMinTrun()
|
||||
if maxTurn != -1:
|
||||
self.surfCh = Channel()
|
||||
self.surfCh.exist = True
|
||||
self.surfCh.depAxis = dep[0]
|
||||
self.surfCh.velAxis = vel[0]
|
||||
else:
|
||||
self.surfCh = Channel()
|
||||
self.surfCh.exist = False
|
||||
return self.surfCh
|
||||
|
||||
def get_deepChannel(self):
|
||||
'''
|
||||
计算深海声道
|
||||
'''
|
||||
if (self.deepCh == None):
|
||||
dep = self.velPf.x
|
||||
vel = self.velPf.y
|
||||
maxTurn = self.findMaxTurn()
|
||||
minTurn = self.findMinTrun()
|
||||
if minTurn != -1:
|
||||
self.deepCh = Channel()
|
||||
self.deepCh.exist = True
|
||||
self.deepCh.depAxis = dep[minTurn]
|
||||
self.deepCh.velAxis = vel[minTurn]
|
||||
else:
|
||||
self.deepCh = Channel()
|
||||
self.deepCh.exist = False
|
||||
return self.deepCh
|
||||
|
||||
def get_springLayer(self):
|
||||
'''
|
||||
计算跃层
|
||||
'''
|
||||
if (self.surfSL == None):
|
||||
dep = self.velPf.x
|
||||
vel = self.velPf.y
|
||||
# 寻找拐点
|
||||
maxTurn = self.findMaxTurn()
|
||||
minTurn = self.findMinTrun()
|
||||
# 初始化跃层
|
||||
surfSL = SpringLayer()
|
||||
surfSL.exist = False
|
||||
mainSL = SpringLayer()
|
||||
mainSL.exist = False
|
||||
if (maxTurn != -1 and minTurn != -1):
|
||||
# 对应这种形状
|
||||
# \
|
||||
# \
|
||||
# /
|
||||
# /
|
||||
# \
|
||||
# \
|
||||
surfSL.exist = True
|
||||
surfSL.limit = np.array([dep[0], dep[maxTurn]])
|
||||
surfSL.intensity = (vel[maxTurn]-vel[0])/(dep[maxTurn]-dep[0])
|
||||
mainSL.exist = True
|
||||
mainSL.limit = np.array([dep[maxTurn], dep[minTurn]])
|
||||
mainSL.intensity = (
|
||||
vel[minTurn]-vel[maxTurn])/(dep[minTurn]-dep[maxTurn])
|
||||
elif (maxTurn != -1 and minTurn == -1):
|
||||
# 对应这种形状
|
||||
# \
|
||||
# \
|
||||
# /
|
||||
# /
|
||||
# /
|
||||
surfSL.exist = True
|
||||
surfSL.limit = np.array([dep[0], dep[maxTurn]])
|
||||
surfSL.intensity = (vel[maxTurn]-vel[0])/(dep[maxTurn]-dep[0])
|
||||
mainSL.exist = True
|
||||
mainSL.limit = np.array([dep[maxTurn], dep[-1]])
|
||||
mainSL.intensity = (vel[-1]-vel[maxTurn]) / \
|
||||
(dep[-1]-dep[maxTurn])
|
||||
elif (maxTurn == -1 and minTurn != -1):
|
||||
# 对应这种形状
|
||||
# /
|
||||
# /
|
||||
# /
|
||||
# \
|
||||
# \
|
||||
# \
|
||||
mainSL.exist = True
|
||||
mainSL.limit = np.array([dep[0], dep[minTurn]])
|
||||
mainSL.intensity = (vel[minTurn]-vel[0])/(dep[minTurn]-dep[0])
|
||||
elif (maxTurn == -1 and minTurn == -1):
|
||||
if vel[-1] < vel[0]:
|
||||
# 对应这种形状
|
||||
# /
|
||||
# /
|
||||
# /
|
||||
mainSL.exist = True
|
||||
mainSL.limit = np.array([dep[0], dep[-1]])
|
||||
mainSL.intensity = (vel[-1]-vel[0])/(dep[-1]-dep[0])
|
||||
else:
|
||||
# 对应这种形状
|
||||
# \
|
||||
# \
|
||||
# \
|
||||
surfSL.exist = True
|
||||
surfSL.limit = np.array([dep[0], dep[-1]])
|
||||
surfSL.intensity = (vel[-1]-vel[0])/(dep[-1]-dep[0])
|
||||
self.surfSL = surfSL
|
||||
self.mainSL = mainSL
|
||||
return (self.surfSL, self.mainSL)
|
||||
|
||||
def export_profileParm(self, fileName):
|
||||
'''
|
||||
计算结果输出文件
|
||||
'''
|
||||
lat = self.velPf.lat
|
||||
lon = self.velPf.lon
|
||||
botDep = self.velPf.botDep
|
||||
# 计算表面声道
|
||||
surfCh = self.get_surfaceChannel()
|
||||
# 计算深海声道
|
||||
deepCh = self.get_deepChannel()
|
||||
# 计算跃层信息
|
||||
surfSL, mainSL = self.get_springLayer()
|
||||
f = open(fileName, mode='w')
|
||||
# 输出坐标深度
|
||||
line = 'lat[degree north], {0:>7.4f}, lon[degree east], {1:>7.4f}, BottomDepth[m], {2:>5.0f}\n'.format(
|
||||
lat, lon, botDep)
|
||||
f.write(line)
|
||||
f.write('----------------------------\n')
|
||||
if surfCh.exist:
|
||||
f.write('表面声道轴深度: {0:>.2f}\n'.format(surfCh.depAxis))
|
||||
f.write('表面声道声速: {0:>.4f}\n'.format(surfCh.velAxis))
|
||||
else:
|
||||
f.write('表面声道轴深度: NONE\n')
|
||||
f.write('表面声道声速: NONE\n')
|
||||
f.write('----------------------------\n')
|
||||
if deepCh.exist:
|
||||
f.write('深海声道轴深度: {0:>.2f}\n'.format(deepCh.depAxis))
|
||||
f.write('深海声道声速: {0:>.4f}\n'.format(deepCh.velAxis))
|
||||
else:
|
||||
f.write('深海声道轴深度: NONE\n')
|
||||
f.write('深海声道声速: NONE\n')
|
||||
f.write('----------------------------\n')
|
||||
if surfSL.exist:
|
||||
f.write('表面跃层区间: {0:>.2f}, {1:>.2f}\n'.format(surfSL.limit[0], surfSL.limit[1]))
|
||||
f.write('表面跃层强度: {0:>.4f}\n'.format(surfSL.intensity))
|
||||
else:
|
||||
f.write('表面跃层区间: NONE\n')
|
||||
f.write('表面跃层强度: NONE\n')
|
||||
f.write('----------------------------\n')
|
||||
if mainSL.exist:
|
||||
f.write('主跃层区间: {0:>.2f}, {1:>.2f}\n'.format(mainSL.limit[0], mainSL.limit[1]))
|
||||
f.write('主跃层强度: {0:>.4f}\n'.format(mainSL.intensity))
|
||||
else:
|
||||
f.write('主跃层区间: NONE\n')
|
||||
f.write('主跃层强度: NONE\n')
|
||||
f.close()
|
||||
+319
@@ -0,0 +1,319 @@
|
||||
import os
|
||||
from multiprocessing import Pool
|
||||
from functools import partial
|
||||
from time import time
|
||||
from shutil import rmtree
|
||||
import numpy as np
|
||||
from scipy.interpolate import interp1d
|
||||
from copy import deepcopy
|
||||
from pyat import ramRW_new as ramRW
|
||||
from pyat.DataBase import DataBase,soundSpeed
|
||||
|
||||
|
||||
class BathyM:
|
||||
def __init__(self, ran=None, depth=None):
|
||||
self.r = ran
|
||||
self.d = depth
|
||||
|
||||
|
||||
class SSP_:
|
||||
def __init__(self, r, z, c):
|
||||
self.r = r
|
||||
self.z = z
|
||||
self.c = c
|
||||
|
||||
|
||||
class Sed:
|
||||
def __init__(self, z, cp, cs, rho, a_p, a_s):
|
||||
self.z = z
|
||||
self.cp = cp
|
||||
self.cs = cs
|
||||
self.rho = rho
|
||||
self.a_p = a_p
|
||||
self.a_s = a_s
|
||||
|
||||
|
||||
class Coord:
|
||||
def __init__(self, lon, lat):
|
||||
self.lon = lon
|
||||
self.lat = lat
|
||||
|
||||
|
||||
class RANDI_Para:
|
||||
def __init__(self, baseDir, freq, lon, lat, Range, dRange, dTheta, v_ship, l_ship, theta=0):
|
||||
self.baseDir = baseDir
|
||||
self.freq = freq
|
||||
self.lon = lon
|
||||
self.lat = lat
|
||||
self.Range = Range
|
||||
self.dRange = dRange
|
||||
self.dTheta = dTheta
|
||||
self.v_ship = v_ship
|
||||
self.l_ship = l_ship
|
||||
self.theta = theta
|
||||
|
||||
def refreshTheta(self, theta):
|
||||
self.theta = theta
|
||||
return self
|
||||
|
||||
|
||||
def RANDI_GetSeaDepth(data, N, coordS, R, azi):
|
||||
r = np.linspace(0, R, N)
|
||||
lon = coordS.lon + r * np.sin(azi) / (111 * np.cos(coordS.lat / 180 * np.pi))
|
||||
lat = coordS.lat + r * np.cos(azi) / 111
|
||||
|
||||
z = np.zeros(N)
|
||||
for it in range(N):
|
||||
data.set_coord(lat[it], lon[it])
|
||||
z[it] = data.get_bottomDepth()
|
||||
return r, z
|
||||
|
||||
|
||||
def RANDI_GetMeanProfile(data, N, coordS, R, azi):
|
||||
r = np.linspace(0, R, N)
|
||||
lon = coordS.lon + r * np.sin(azi) / (111 * np.cos(coordS.lat / 180 * np.pi))
|
||||
lat = coordS.lat + r * np.cos(azi) / 111
|
||||
sal = np.full([len(data.depthGrid), N], np.nan)
|
||||
tem = np.full([len(data.depthGrid), N], np.nan)
|
||||
for i in range(N):
|
||||
data.set_coord(lat[i], lon[i])
|
||||
salPf = data.get_salRawProfile()
|
||||
temPf = data.get_temRawProfile()
|
||||
if len(salPf.x) > 1:
|
||||
sal[0:len(salPf.x), i] = salPf.y
|
||||
tem[0:len(temPf.x), i] = temPf.y
|
||||
sal = np.ma.masked_array(sal, np.isnan(sal))
|
||||
tem = np.ma.masked_array(tem, np.isnan(tem))
|
||||
sal_m = np.mean(sal, 1)
|
||||
tem_m = np.mean(tem, 1)
|
||||
z = data.depthGrid[~sal_m.mask]
|
||||
sal_m = sal_m[~sal_m.mask]
|
||||
tem_m = tem_m[~tem_m.mask]
|
||||
return z, sal_m, tem_m
|
||||
|
||||
|
||||
def RANDI_GetEnv(data, coordS, coordR=None, R=None, azi=None):
|
||||
if coordR == None:
|
||||
azi = azi / 180 * np.pi
|
||||
lon = coordS.lon + R * np.sin(azi) / (111 * np.cos(coordS.lat / 180 * np.pi))
|
||||
lat = coordS.lat + R * np.cos(azi) / 111
|
||||
coordR = Coord(lon, lat)
|
||||
|
||||
if R == None:
|
||||
x = (coordR.lon - coordS.lon) * (111 * np.cos(coordS.lat / 180 * np.pi))
|
||||
y = (coordR.lat - coordS.lat) * 111
|
||||
R = np.sqrt(x * x + y * y)
|
||||
if y > 0:
|
||||
azi = np.arctan(x / y)
|
||||
elif y == 0:
|
||||
azi = np.sign(x) * np.pi / 2
|
||||
else:
|
||||
azi = np.arctan(x / y) + np.pi
|
||||
|
||||
# Get Bathymetry
|
||||
N = int(np.ceil(R / 10) + 1)
|
||||
r, z = RANDI_GetSeaDepth(data, N, coordS, R, azi)
|
||||
bathym = BathyM(r, z)
|
||||
# plt.plot(r, z)
|
||||
# plt.gca().invert_yaxis()
|
||||
# plt.show()
|
||||
|
||||
# Get Sound Speed Profile
|
||||
z_ssp, sal_m, tem_m = RANDI_GetMeanProfile(data, N, coordS, R, azi)
|
||||
if max(bathym.d) > z_ssp[-1]:
|
||||
z_ssp = np.append(z_ssp, max(bathym.d))
|
||||
sal_m = np.append(sal_m, sal_m[-1])
|
||||
tem_m = np.append(tem_m, tem_m[-1])
|
||||
c_ssp = soundSpeed(tem_m, sal_m, z_ssp)
|
||||
ssp = SSP_(0, z_ssp, c_ssp)
|
||||
# plt.plot(c_ssp, z_ssp)
|
||||
# plt.gca().invert_yaxis()
|
||||
# plt.show()
|
||||
|
||||
# Sediment
|
||||
z = np.array([0, 50])
|
||||
cp = np.array([1550, 1590])
|
||||
cs = np.array([0, 0])
|
||||
rho = np.array([1.3, 1.5])
|
||||
a_p = np.array([0.1, 0.1])
|
||||
a_s = np.array([0, 0])
|
||||
sed = Sed(z, cp, cs, rho, a_p, a_s)
|
||||
|
||||
return bathym, ssp, sed
|
||||
|
||||
|
||||
def RANDI_writeRAMin(baseDir, data, freq, dTheta, lat, lon, Range, rd, ship_sd, SeaDepthLim):
|
||||
t1 = time()
|
||||
btyFile = open("bty", 'w')
|
||||
for theta in np.arange(0, 360, dTheta):
|
||||
[bathm, ssp, sed] = RANDI_GetEnv(data, Coord(lon, lat), R=Range, azi=theta)
|
||||
for dd in bathm.d:
|
||||
btyFile.write(str(dd) + ' ')
|
||||
btyFile.write('\n')
|
||||
idx = np.where(bathm.d < SeaDepthLim)
|
||||
if len(idx[0]) > 0:
|
||||
bathm.r = bathm.r[0:idx[0][0]]
|
||||
bathm.d = bathm.d[0:idx[0][0]]
|
||||
|
||||
title = "Waveguide"
|
||||
# Source and receiving position
|
||||
bathm.r = bathm.r * 1000 # km -> m
|
||||
rmax = max(bathm.r) # Maximum receiving range (unit: m)
|
||||
zmax = round(max(bathm.d) + 5 * 1500 / freq) # Maximum receiving depth (uint: m)
|
||||
zmplt = 0 # round(max(bathm.d)*1.05) # Maximum depth of plot (uint: m)
|
||||
dz = 1500 / freq / 4 # Step in depth direction: wavelength / 15
|
||||
dr = 5 * dz # Step in range direction
|
||||
pos = ramRW.PosRAM(rd, ship_sd, rmax, zmax, dr, dz, zmplt)
|
||||
|
||||
# Sound speed profile for RAM
|
||||
Z = sed.z
|
||||
cw_p = ramRW.PROF(ssp.z, ssp.c) # Water sound speed profile
|
||||
cb_p = ramRW.PROF(Z, sed.cp) # Bottom sound speed profile
|
||||
rhob_p = ramRW.PROF(Z, sed.rho) # Sea bottom density profile
|
||||
|
||||
Ap = sed.a_p
|
||||
if Z[-1] < 5 * 1500 / freq:
|
||||
Z = np.append(Z, 3 * 1500 / freq)
|
||||
Ap = np.append(Ap, Ap[-1])
|
||||
Z = np.append(Z, Z[-1] + 2 * 1500 / freq)
|
||||
Ap = np.append(Ap, 10)
|
||||
# Ap = sed[it].a_p
|
||||
attn_p = ramRW.PROF(Z, Ap) # Sea bottom attenuation profile
|
||||
|
||||
ssp_ram = [ramRW.SSPRAM(0, cw_p, cb_p, rhob_p, attn_p)]
|
||||
|
||||
# Write ram.in file
|
||||
if not os.path.exists(baseDir + "/TL/temp/theta_{:1d}".format(theta)):
|
||||
os.makedirs(baseDir + "/TL/temp/theta_{:1d}".format(theta))
|
||||
envfil = baseDir + "/TL/temp/theta_{:1d}/ram.in".format(theta)
|
||||
ramRW.write_env_RAM(title, envfil, freq, pos, bathm, ssp_ram)
|
||||
t2 = time()
|
||||
#print(t2 - t1)
|
||||
btyFile.close()
|
||||
|
||||
|
||||
def RANDI_callRAM(baseDir, NThreads, freq, dTheta):
|
||||
'''
|
||||
t1 = time()
|
||||
for theta in np.arange(0,360,5):
|
||||
os.chdir(baseDir + "/TL/theta_{:1d}".format(theta))
|
||||
os.system(baseDir + "/ram.exe")
|
||||
|
||||
os.chdir(baseDir)
|
||||
t2 = time()
|
||||
print(t2-t1)
|
||||
'''
|
||||
t1 = time()
|
||||
func = partial(callRAM, baseDir)
|
||||
pool = Pool(NThreads)
|
||||
pool.map(func, np.arange(0, 360, dTheta))
|
||||
t2 = time()
|
||||
#print(t2 - t1)
|
||||
|
||||
if os.path.exists(baseDir + f"/TL/freq_{round(freq)}"):
|
||||
rmtree(baseDir + f"/TL/freq_{round(freq)}")
|
||||
os.rename(baseDir + "/TL/temp", baseDir + f"/TL/freq_{round(freq)}")
|
||||
|
||||
|
||||
def callRAM(baseDir, theta):
|
||||
AtBinPath = os.path.dirname(os.path.abspath(__file__))+'/at/bin'
|
||||
print(AtBinPath)
|
||||
os.chdir(baseDir + "/TL/temp/theta_{:1d}".format(theta))
|
||||
os.system(AtBinPath + "/ram")
|
||||
os.chdir(baseDir)
|
||||
|
||||
def RANDI_getShipNum(lat, lon, Range, dRange, theta):
|
||||
NRange = int(Range / dRange)
|
||||
#shipNum = np.random.rand(NRange)
|
||||
shipNum = 0.5*np.ones(NRange)
|
||||
return shipNum
|
||||
|
||||
def calNoise(randiP):
|
||||
rr = np.arange(randiP.dRange / 2, randiP.Range, randiP.dRange)
|
||||
SL = RossShipSL(randiP.freq, randiP.v_ship, randiP.l_ship)
|
||||
S = np.power(10, SL / 10)
|
||||
shipNum = RANDI_getShipNum(randiP.lat, randiP.lon, randiP.Range, randiP.dRange, randiP.theta)
|
||||
filePath = randiP.baseDir + f"/TL/freq_{round(randiP.freq)}/theta_{round(randiP.theta)}"
|
||||
[r, tl] = ramRW.readTLline_RAM(filePath)
|
||||
r = r / 1000
|
||||
I2 = np.power(10, tl / 10)
|
||||
I_ = interp1d(r, I2)
|
||||
I = I_(rr[rr < r[-1]])
|
||||
noise = sum(shipNum[rr < r[-1]] * S / I)
|
||||
return noise
|
||||
|
||||
def RANDI_calNL(randiP, NThreads):
|
||||
'''
|
||||
t1 = time()
|
||||
theta = np.arange(0, 360, dTheta)
|
||||
noise1 = np.zeros(len(theta))
|
||||
for i in range(len(theta)):
|
||||
randiP.theta = theta[i]
|
||||
noise1[i] = calNoise(randiP)
|
||||
NL1 = 10 * np.log10(sum(noise1))
|
||||
t2 = time()
|
||||
print(t2-t1)
|
||||
'''
|
||||
|
||||
t1 = time()
|
||||
RANDI_P = []
|
||||
for theta in np.arange(0, 360, randiP.dTheta):
|
||||
randiP.theta = theta
|
||||
RANDI_P.append(deepcopy(randiP))
|
||||
pool = Pool(NThreads)
|
||||
noise = pool.map(calNoise, RANDI_P)
|
||||
NL = 10 * np.log10(sum(noise))
|
||||
t2 = time()
|
||||
#print(t2-t1)
|
||||
return NL
|
||||
|
||||
|
||||
def RossShipSL(freq, v, l):
|
||||
if freq < 500:
|
||||
Lso = -10 * np.log10(np.power(10, -1.06 * np.log10(freq) - 14.34) +
|
||||
np.power(10, 3.32 * np.log10(freq) - 21.425))
|
||||
else:
|
||||
Lso = 173.2 - 18 * np.log10(freq)
|
||||
|
||||
if freq <= 28.4:
|
||||
df = 8.1
|
||||
elif freq < 191.6:
|
||||
df = 22.3-9.77*np.log10(freq)
|
||||
else:
|
||||
df = 0
|
||||
|
||||
dl = np.power(l, 1.15) / 3643
|
||||
Ls = Lso + 60*np.log10(v/12) + 20*np.log10(l/300) + df*dl + 3
|
||||
return Ls
|
||||
|
||||
|
||||
def call_RANDI(ETOPO1Path, STPath, baseDir, freq, rd, lon, lat, timeType, NThreads):
|
||||
# 定义时间段
|
||||
timeIndex = timeType
|
||||
# 创建类
|
||||
data = DataBase(ETOPO1Path, STPath)
|
||||
# 设置时间段
|
||||
data.set_timePeriod(timeIndex)
|
||||
|
||||
Range = 500 # Range of sound field calculation (Unit: km)
|
||||
ship_sd = 6.0 # Ship source depth (Unit: m)
|
||||
dTheta = 5 # The angle of sector (Unit: °)
|
||||
dRange = 10 # The
|
||||
SeaDepthLim = 20 # (Unut: m)
|
||||
v_ship = 12 # Ship speed (Unit: kt)
|
||||
l_ship = 300 # Ship length (Unit: ft)
|
||||
|
||||
randiP = RANDI_Para(baseDir, freq, lon, lat, Range, dRange, dTheta, v_ship, l_ship)
|
||||
|
||||
RANDI_writeRAMin(baseDir, data, freq, dTheta, lat, lon, Range, rd, ship_sd, SeaDepthLim)
|
||||
|
||||
RANDI_callRAM(baseDir, NThreads, freq, dTheta)
|
||||
|
||||
NL = RANDI_calNL(randiP, NThreads)
|
||||
|
||||
return NL
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
可执行文件
+143
@@ -0,0 +1,143 @@
|
||||
""" Wind Generated Noise Prediction """
|
||||
import numpy as np
|
||||
from scipy.interpolate import interp1d
|
||||
from pyat import DataBase as db
|
||||
import matplotlib.pyplot as plt
|
||||
|
||||
class MdlPara():
|
||||
def __init__(self, title, lat, lon, seaDepth, month, freq, vc, a, b, vs):
|
||||
self.title = title
|
||||
self.lat = lat
|
||||
self.lon = lon
|
||||
self.seaDepth = seaDepth
|
||||
self.month = month
|
||||
self.freq = freq
|
||||
self.vc = vc
|
||||
self.a = a
|
||||
self.b = b
|
||||
self.vs = vs
|
||||
|
||||
def loadMdlPara(filename):
|
||||
f = open(filename, mode='r')
|
||||
|
||||
mdlPara = []
|
||||
eof = False
|
||||
while (1):
|
||||
# Title
|
||||
while (1):
|
||||
line = f.readline()
|
||||
if line == '':
|
||||
eof = True
|
||||
break
|
||||
title = line.strip()
|
||||
if title != '':
|
||||
break
|
||||
if eof:
|
||||
break
|
||||
|
||||
# Latitude and Longitude
|
||||
line = f.readline()
|
||||
line = line.strip().split()
|
||||
lat = np.double(line[0])
|
||||
lon = np.double(line[1])
|
||||
|
||||
# Sea Depth
|
||||
line = f.readline()
|
||||
line = line.strip().split()
|
||||
seaDepth = np.double(line[0])
|
||||
|
||||
# Month
|
||||
line = f.readline()
|
||||
line = line.strip().split()
|
||||
month = np.int8(line[0])
|
||||
|
||||
# Model Parameters
|
||||
freq = []
|
||||
vc = []
|
||||
a = []
|
||||
b = []
|
||||
vs = []
|
||||
while (1):
|
||||
line = f.readline()
|
||||
line = line.strip().split()
|
||||
if line[0] == '0':
|
||||
break
|
||||
freq.append(np.double(line[0]))
|
||||
vc.append(np.double(line[1]))
|
||||
a.append(np.double(line[2]))
|
||||
b.append(np.double(line[3]))
|
||||
vs.append(np.double(line[4]))
|
||||
|
||||
mdlPara.append(MdlPara(title, lat, lon, seaDepth, month, freq, vc, a, b, vs))
|
||||
|
||||
return mdlPara
|
||||
|
||||
|
||||
def WGNMdl(mdlPara, windspeed):
|
||||
f = np.array(mdlPara.freq)
|
||||
spl = np.zeros(len(f))
|
||||
for it in range(len(f)):
|
||||
if windspeed < mdlPara.vc[it]:
|
||||
spl[it] = mdlPara.a[it] + mdlPara.b[it] * 10 * np.log10(mdlPara.vc[it])
|
||||
elif (mdlPara.vs[it] is not np.NaN) & (windspeed > mdlPara.vs[it]):
|
||||
spl[it] = mdlPara.a[it] + mdlPara.b[it] * 10 * np.log10(mdlPara.vs[it])
|
||||
else:
|
||||
spl[it] = mdlPara.a[it] + mdlPara.b[it] * 10 * np.log10(windspeed)
|
||||
|
||||
return f, spl
|
||||
|
||||
|
||||
def WGNPd(dataFile, seaDepth, windspeed, month, freq):
|
||||
if min(freq) < 50:
|
||||
raise UserWarning("The minimum frequency must be larger than 50 Hz")
|
||||
|
||||
mdlPara = loadMdlPara(dataFile)
|
||||
|
||||
z = seaDepth
|
||||
|
||||
Q = []
|
||||
for it in range(len(mdlPara)):
|
||||
q1 = abs(mdlPara[it].seaDepth - z) / (mdlPara[it].seaDepth + z)
|
||||
q2 = min(abs(month-mdlPara[it].month), 12-abs(month-mdlPara[it].month)) / 6
|
||||
alpha = 0.7
|
||||
Q.append(alpha * q1 + (1-alpha) * q2)
|
||||
idx = np.argmin(Q)
|
||||
# print([z, month, idx])
|
||||
|
||||
f0, spl0 = WGNMdl(mdlPara[idx], windspeed)
|
||||
if max(freq) > max(f0):
|
||||
spl0 = np.append(spl0, spl0[-1] - 5 * np.log2(max(freq)/max(f0)))
|
||||
f0 = np.append(f0, max(freq))
|
||||
if min(f0) > 200:
|
||||
spl0 = np.insert(spl0, 0, spl0[0] + 5 * np.log2(min(f0)/200))
|
||||
f0 = np.insert(f0, 0, 200)
|
||||
if min(f0) > 50:
|
||||
spl0 = np.insert(spl0, 0, spl0[0] + 9 * np.log2(min(f0)/50))
|
||||
f0 = np.insert(f0, 0, 50)
|
||||
|
||||
itp1 = interp1d(np.log10(f0), spl0)
|
||||
spl = itp1(np.log10(freq))
|
||||
|
||||
return freq, spl
|
||||
|
||||
|
||||
# if __name__=="__main__":
|
||||
# lat = 19
|
||||
# lon = 116
|
||||
# windspeed = 5 # unit: m/s
|
||||
# month = 3
|
||||
# freq = 50 * np.power(2, np.arange(25)/3)
|
||||
|
||||
# # 定义时间段
|
||||
# timeIndex = db.timeDict['Annual']
|
||||
# # 创建类
|
||||
# data = db.DataBase()
|
||||
# # 设置时间段
|
||||
# data.set_timePeriod(timeIndex)
|
||||
|
||||
# f, spl = WGNPd(data, lat, lon, windspeed, month, freq)
|
||||
|
||||
# plt.semilogx(f, spl)
|
||||
# plt.xlabel('Frequency / Hz')
|
||||
# plt.ylabel('Noise Level / dB')
|
||||
# plt.show()
|
||||
可执行文件
+8
@@ -0,0 +1,8 @@
|
||||
'''
|
||||
Description:
|
||||
|
||||
Author: Hunter Akins
|
||||
|
||||
'''
|
||||
import os, sys
|
||||
sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
|
||||
+228
@@ -0,0 +1,228 @@
|
||||
from pyat.readwrite import write_env, read_shd, get_rays
|
||||
from pyat.env import Pos, Source, Dom, cInt, SSPraw, SSP, HS, BotBndry, TopBndry, Bndry, Box, Beam
|
||||
from os import system
|
||||
import numpy as np
|
||||
from pyat.config import AtBinPath
|
||||
|
||||
|
||||
def write_ssp(sspfile, ssp, bathm, NZmax):
|
||||
if sspfile[-3:] != 'ssp':
|
||||
sspfile += '.ssp'
|
||||
with open(sspfile, 'w') as f:
|
||||
f.write(str(len(ssp)) + '\r\n')
|
||||
for val in bathm.r:
|
||||
f.write(str(val) + '\t')
|
||||
f.write('\r\n')
|
||||
for row in range(NZmax):
|
||||
for col in range(len(ssp)):
|
||||
if len(ssp[col].z) <= row:
|
||||
f.write('{:4.6f}'.format(1800) + '\t')
|
||||
else:
|
||||
f.write('{:6f}'.format(ssp[col].c[row]) + '\t')
|
||||
f.write('\r\n')
|
||||
return
|
||||
|
||||
|
||||
def write_bathy(btyfile, bathm):
|
||||
if btyfile[-3:] != 'bty':
|
||||
btyfile += '.bty'
|
||||
with open(btyfile, 'w') as f:
|
||||
f.write('CS\r\n')
|
||||
f.write(str(len(bathm.d)) + '\r\n')
|
||||
for row in range(len(bathm.r)):
|
||||
f.write(' ' + str(bathm.r[row]) + ' ' + str(bathm.d[row]) + '\r\n')
|
||||
return
|
||||
|
||||
|
||||
def calZmax(ssp):
|
||||
d = np.array([], dtype=int)
|
||||
for it in range(len(ssp)):
|
||||
d = np.append(d, len(ssp[it].z))
|
||||
NZmax =max(d)
|
||||
ssp_idx = np.argmax(d)
|
||||
Zmax = ssp[ssp_idx].z[-1]
|
||||
return NZmax, Zmax, ssp_idx
|
||||
|
||||
def call_Bellhop(freq, sd, rd, bathm, ssp, sed, base):
|
||||
# Source and receiving position
|
||||
filename = 'envB'
|
||||
Rmax = bathm.r[-1] # unit: km
|
||||
dr = (1500 / freq) / 1000 # wavelength / 10, unit: km
|
||||
ran = np.linspace(0, Rmax, round(Rmax / dr)) # Receiving range (unit: km)
|
||||
NZmax, Zmax, ssp_idx = calZmax(ssp)
|
||||
RD = np.linspace(0, Zmax, round(Zmax / 10) + 1)
|
||||
pos = Pos(Source(sd), Dom(ran, rd))
|
||||
# Range of phase velocity
|
||||
cInt.Low = 1400
|
||||
cInt.High = 15000
|
||||
|
||||
# The number of media
|
||||
NMedia = 1
|
||||
ssp_raw = []
|
||||
depth = [0]
|
||||
# Sound speed profile
|
||||
Z = ssp[ssp_idx].z # Depth
|
||||
Cp = ssp[ssp_idx].c # Speed of P-wave
|
||||
Cs = np.zeros(np.shape(Z)) # Speed of S-wave
|
||||
Rho = np.ones(np.shape(Z)) # Density of the media
|
||||
Ap = np.zeros(np.shape(Z)) # Attenuation of P-wave
|
||||
As = np.zeros(np.shape(Z)) # Attenuation of S-wave
|
||||
ssp_raw.append(SSPraw(Z, Cp, Cs, Rho, Ap, As))
|
||||
depth.append(Z[-1])
|
||||
|
||||
# Sediment is ignored
|
||||
'''
|
||||
if sed != None:
|
||||
Z = sed[0].z + ssp[0].z[-1] # Depth
|
||||
Cp = sed[0].cp # Speed of P-wave
|
||||
Cs = sed[0].cs # Speed of S-wave
|
||||
Rho = sed[0].rho # Density of the media
|
||||
Ap = sed[0].a_p # Attenuation of P-wave
|
||||
As = sed[0].a_s # Attenuation of S-wave
|
||||
ssp_raw.append(SSPraw(Z, Cp, Cs, Rho, Ap, As))
|
||||
depth.append(Z[-1])
|
||||
'''
|
||||
|
||||
Opt_top = 'SVW'
|
||||
N = np.zeros(NMedia, np.int8)
|
||||
Sigma = np.zeros(NMedia + 1)
|
||||
sspB = SSP(ssp_raw, depth, NMedia, Opt_top, N, Sigma)
|
||||
|
||||
# Bottom option
|
||||
hs = HS(base[0].cp, base[0].cs, base[0].rho, base[0].a_p, base[0].a_s)
|
||||
Opt_bot = 'A~'
|
||||
bottom = BotBndry(Opt_bot, hs)
|
||||
top = TopBndry(Opt_top)
|
||||
bdy = Bndry(top, bottom)
|
||||
# Beam params
|
||||
run_type = 'C' # incoherently sum beams, see AT docs for more info
|
||||
nbeams = 0
|
||||
alpha = np.linspace(-45, 45, 2) # min and max launch angle -20 degrees to 20 degrees
|
||||
box = Box(Zmax, max(bathm.r)) # bound the region you let the beams go, depth in meters and range in km
|
||||
deltas = 0 # length step of ray trace, 0 means automatically choose
|
||||
beam = Beam(RunType=run_type, Nbeams=nbeams, alpha=alpha, box=box, deltas=deltas) # package
|
||||
|
||||
# Write *.env file
|
||||
write_env(filename + '.env', 'BELLHOP', 'Pekeris profile', freq, sspB, bdy, pos, beam, cInt, Rmax)
|
||||
write_ssp(filename, ssp, bathm, NZmax)
|
||||
write_bathy(filename, bathm)
|
||||
|
||||
system(AtBinPath + "/bellhop " + filename)
|
||||
# Read sound field
|
||||
[x, x, x, x, Pos1, pressure] = read_shd(filename + '.shd')
|
||||
TL = -10 * np.log10(np.square(np.abs(pressure))) # Transmission Loss
|
||||
|
||||
return Pos1, TL
|
||||
|
||||
def call_Bellhop_Rays(freq, sd, rd, bathm, ssp, sed, base):
|
||||
# Source and receiving position
|
||||
filename = 'cz'
|
||||
Rmax = bathm.r[-1] # unit: km
|
||||
dr = (1500 / freq) / 1000 # wavelength / 10, unit: km
|
||||
ran = np.linspace(dr, Rmax, round(Rmax / dr)) # Receiving range (unit: km)
|
||||
NZmax, Zmax, ssp_idx = calZmax(ssp)
|
||||
RD = np.linspace(0, Zmax, round(Zmax / 10) + 1)
|
||||
pos = Pos(Source(sd), Dom(ran, rd))
|
||||
# Range of phase velocity
|
||||
cInt.Low = 1400
|
||||
cInt.High = 15000
|
||||
|
||||
# The number of media
|
||||
NMedia = 1
|
||||
ssp_raw = []
|
||||
depth = [0]
|
||||
# Sound speed profile
|
||||
Z = ssp[ssp_idx].z # Depth
|
||||
Cp = ssp[ssp_idx].c # Speed of P-wave
|
||||
Cs = np.zeros(np.shape(Z)) # Speed of S-wave
|
||||
Rho = np.ones(np.shape(Z)) # Density of the media
|
||||
Ap = np.zeros(np.shape(Z)) # Attenuation of P-wave
|
||||
As = np.zeros(np.shape(Z)) # Attenuation of S-wave
|
||||
ssp_raw.append(SSPraw(Z, Cp, Cs, Rho, Ap, As))
|
||||
depth.append(Z[-1])
|
||||
|
||||
# Sediment is ignored
|
||||
'''
|
||||
if sed != None:
|
||||
Z = sed[0].z + ssp[0].z[-1] # Depth
|
||||
Cp = sed[0].cp # Speed of P-wave
|
||||
Cs = sed[0].cs # Speed of S-wave
|
||||
Rho = sed[0].rho # Density of the media
|
||||
Ap = sed[0].a_p # Attenuation of P-wave
|
||||
As = sed[0].a_s # Attenuation of S-wave
|
||||
ssp_raw.append(SSPraw(Z, Cp, Cs, Rho, Ap, As))
|
||||
depth.append(Z[-1])
|
||||
'''
|
||||
|
||||
Opt_top = 'SVW'
|
||||
N = np.zeros(NMedia, np.int8)
|
||||
Sigma = np.zeros(NMedia + 1)
|
||||
sspB = SSP(ssp_raw, depth, NMedia, Opt_top, N, Sigma)
|
||||
|
||||
# Bottom option
|
||||
hs = HS(base[0].cp, base[0].cs, base[0].rho, base[0].a_p, base[0].a_s)
|
||||
Opt_bot = 'A~'
|
||||
bottom = BotBndry(Opt_bot, hs)
|
||||
top = TopBndry(Opt_top)
|
||||
bdy = Bndry(top, bottom)
|
||||
# Beam params
|
||||
nbeams = 301
|
||||
alpha = np.linspace(-10, 10, 2) # min and max launch angle -20 degrees to 20 degrees
|
||||
box = Box(Zmax, max(bathm.r)) # bound the region you let the beams go, depth in meters and range in km
|
||||
deltas = 0 # length step of ray trace, 0 means automatically choose
|
||||
run_type = 'R'
|
||||
beam = Beam(RunType=run_type, Nbeams=nbeams, alpha=alpha, box=box, deltas=deltas) # package
|
||||
|
||||
# Write *.env file
|
||||
write_env(filename + '.env', 'BELLHOP', 'Pekeris profile', freq, sspB, bdy, pos, beam, cInt, Rmax)
|
||||
write_bathy(filename, bathm)
|
||||
|
||||
system(AtBinPath + "/bellhop " + filename)
|
||||
# Read sound field
|
||||
return get_rays(filename + ".ray")
|
||||
|
||||
def find_cvgcRays(rays_total):
|
||||
Rays = []
|
||||
num_bnc_min = np.Inf
|
||||
for ray in rays_total[0]:
|
||||
if ray.num_top_bnc + ray.num_bot_bnc < num_bnc_min and max(ray.xy[1,:]) > 100:
|
||||
num_bnc_min = ray.num_top_bnc + ray.num_bot_bnc
|
||||
|
||||
for ray in rays_total[0]:
|
||||
if ray.num_top_bnc + ray.num_bot_bnc > num_bnc_min + 1:
|
||||
continue
|
||||
elif max(ray.xy[1,:]) < 100:
|
||||
continue
|
||||
else:
|
||||
Rays.append(ray)
|
||||
return Rays
|
||||
|
||||
# if __name__=="__main__":
|
||||
''' ********************************************** '''
|
||||
''' ******************** Test ******************** '''
|
||||
# freq = 25 # Frequency
|
||||
# sd = np.array([10.0]) # Source depth
|
||||
# rd = np.linspace(0, 4000, 401) # Receiving depth
|
||||
# # 定义坐标
|
||||
# lat = 19.00
|
||||
# lon = 116.00
|
||||
# # 定义时间段
|
||||
# timeIndex = db.timeDict['Annual']
|
||||
# # 创建类
|
||||
# data = db.DataBase()
|
||||
# # 设置时间段
|
||||
# data.set_timePeriod(timeIndex)
|
||||
|
||||
# [bathm, ssp, sed, base] = GetEnv(data, freq, Coord(lon, lat), R=100, azi=90)
|
||||
# [Pos, TL] = call_Bellhop(freq, sd, rd, bathm, ssp, sed, base)
|
||||
|
||||
# #[x, x, x, x, Pos, pressure] = read_shd('envB.shd')
|
||||
# #TL = -10 * np.log10(np.square(np.abs(pressure))) # Transmission Loss
|
||||
# # Plot
|
||||
# plt.pcolor(Pos.r.range, Pos.r.depth, TL[0,0,:,:], vmin=40, vmax=130,cmap='jet_r', shading='auto')
|
||||
# plt.xlabel("Range/m")
|
||||
# plt.ylabel("Depth/m")
|
||||
# plt.gca().invert_yaxis()
|
||||
# plt.colorbar()
|
||||
# plt.plot(bathm.r*1000, bathm.d, color='k')
|
||||
# plt.show()
|
||||
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"AtBinPath": "/home/shunli/pro/pyat/at/bin"
|
||||
}
|
||||
+10
@@ -0,0 +1,10 @@
|
||||
import json
|
||||
from os import path
|
||||
|
||||
jsonPath = path.dirname(path.abspath(__file__)) + '/config.json'
|
||||
with open(jsonPath,'r') as jsonFile:
|
||||
paramData = json.load(jsonFile)
|
||||
if "AtBinPath" in paramData:
|
||||
AtBinPath = paramData["AtBinPath"]
|
||||
else:
|
||||
AtBinPath = path.dirname(path.abspath(__file__))+'/at/bin'
|
||||
+32
@@ -0,0 +1,32 @@
|
||||
import numpy as np
|
||||
|
||||
|
||||
# 函数
|
||||
def dis_mats(m, d): # 以线阵为例
|
||||
dis = np.zeros((m, m))
|
||||
for i in range(m):
|
||||
D = np.arange(0, m * d, d) - d * int(i) * np.ones(m)
|
||||
dis[i] = D
|
||||
dis = np.triu(dis)
|
||||
dis += dis.T - np.diag(dis.diagonal())
|
||||
|
||||
return dis # 所有阵元的间距的集合
|
||||
|
||||
|
||||
def pn_funcs(f, c, dis): # 所有阵元的噪声相关性
|
||||
k = 2 * np.pi * f / c
|
||||
# pn = np.sinc(k * dis)
|
||||
a = np.sin(k * dis)
|
||||
b = k * dis
|
||||
|
||||
pn = np.divide(a, b, np.ones_like(a), where=b != 0) # sin0/0=1
|
||||
|
||||
return pn
|
||||
|
||||
|
||||
def ag_funcs(m, pn):
|
||||
ps = np.power(m, 2)
|
||||
ag_s = ps / np.sum(pn) #
|
||||
ag = 10 * np.log10(ag_s)
|
||||
|
||||
return ag
|
||||
+321
@@ -0,0 +1,321 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
from os import system
|
||||
import numpy as np
|
||||
from pyat.AcousticPara import GetEnv, Coord
|
||||
from scipy.signal import savgol_filter, medfilt
|
||||
from pyat.DataBase import DataBase
|
||||
from pyat.readwrite import write_env, write_bathy, read_shd, get_rays
|
||||
from pyat.env import Pos, Source, Dom, cInt, SSPraw, SSP, HS, BotBndry, TopBndry, Bndry, Box, Beam
|
||||
import matplotlib.pyplot as plt
|
||||
from pyat.config import AtBinPath
|
||||
|
||||
file_cz_data = open('cz_data.txt', 'w')
|
||||
|
||||
class CzRangeWidth:
|
||||
def __init__(self, minRange, maxRange, width):
|
||||
self.minRange = minRange
|
||||
self.maxRange = maxRange
|
||||
self.width = width
|
||||
|
||||
class CzDetail:
|
||||
def __init__(self, descript, directCz, reflectCz):
|
||||
self.descript = descript
|
||||
self.directCz = directCz
|
||||
self.reflectCz = reflectCz
|
||||
|
||||
class CzData:
|
||||
def __init__(self, azi, ranges, depths, TL, bathym, Rays, CzDetail):
|
||||
self.azi = azi
|
||||
self.ranges = ranges
|
||||
self.depths = depths
|
||||
self.TL = TL
|
||||
self.bathym = bathym
|
||||
self.Rays = Rays
|
||||
self.CzDetail = CzDetail
|
||||
|
||||
def calZmax(ssp, sed):
|
||||
d = np.array([],dtype=int)
|
||||
for it in range(len(ssp)):
|
||||
d=np.append(d,ssp[it].z[-1])
|
||||
Zmax =max(d)
|
||||
ssp_idx = np.argmax(d)
|
||||
return Zmax, ssp_idx
|
||||
|
||||
def call_Bellhop(freq, sd, rd, bathm, ssp, sed, base):
|
||||
# Source and receiving position
|
||||
filename='cz'
|
||||
Rmax = bathm.r[-1] # unit: km
|
||||
dr = (1500 / freq) / 1000 # wavelength / 10, unit: km
|
||||
ran = np.linspace(0, Rmax, round(Rmax / dr)) # Receiving range (unit: km)
|
||||
Zmax, ssp_idx = calZmax(ssp, sed)
|
||||
"""RD 已修改 8.26"""
|
||||
RD = np.linspace(0, Zmax, round(Zmax/10) + 1)
|
||||
pos = Pos(Source(sd), Dom(ran, RD))
|
||||
# Range of phase velocity
|
||||
cInt.Low = 1400
|
||||
cInt.High = 15000
|
||||
|
||||
# The number of media
|
||||
NMedia = 1
|
||||
ssp_raw = []
|
||||
depth = [0]
|
||||
# Sound speed profile
|
||||
Z = ssp[ssp_idx].z # Depth
|
||||
Cp = ssp[ssp_idx].c # Speed of P-wave
|
||||
Cs = np.zeros(np.shape(Z)) # Speed of S-wave
|
||||
Rho = np.ones(np.shape(Z)) # Density of the media
|
||||
Ap = np.zeros(np.shape(Z)) # Attenuation of P-wave
|
||||
As = np.zeros(np.shape(Z)) # Attenuation of S-wave
|
||||
ssp_raw.append(SSPraw(Z, Cp, Cs, Rho, Ap, As))
|
||||
depth.append(Z[-1])
|
||||
|
||||
# Sediment
|
||||
if sed != None:
|
||||
|
||||
Z = sed[0].z + ssp[0].z[-1] # Depth
|
||||
Cp = sed[0].cp # Speed of P-wave
|
||||
Cs = sed[0].cs # Speed of S-wave
|
||||
Rho = sed[0].rho # Density of the media
|
||||
Ap = sed[0].a_p # Attenuation of P-wave
|
||||
As = sed[0].a_s # Attenuation of S-wave
|
||||
ssp_raw.append(SSPraw(Z, Cp, Cs, Rho, Ap, As))
|
||||
depth.append(Z[-1])
|
||||
"""Opt_top 已修改 8.26"""
|
||||
Opt_top = 'SVW'
|
||||
N = np.zeros(NMedia, np.int8)
|
||||
Sigma = np.zeros(NMedia+1)
|
||||
sspK = SSP(ssp_raw, depth, NMedia, Opt_top, N, Sigma)
|
||||
|
||||
# Bottom option
|
||||
hs = HS(base[0].cp, base[0].cs, base[0].rho, base[0].a_p, base[0].a_s)
|
||||
Opt_bot = 'A~'
|
||||
bottom = BotBndry(Opt_bot, hs)
|
||||
top = TopBndry(Opt_top)
|
||||
bdy = Bndry(top, bottom)
|
||||
# Beam params
|
||||
run_type = 'C' # incoherently sum beams, see AT docs for more info
|
||||
nbeams = 0
|
||||
alpha = np.linspace(-90, 90, 2) # min and max launch angle -20 degrees to 20 degrees
|
||||
box = Box(Zmax, 100) # bound the region you let the beams go, depth in meters and range in km
|
||||
deltas = 0 # length step of ray trace, 0 means automatically choose
|
||||
beam = Beam(RunType=run_type, Nbeams=nbeams, alpha=alpha, box=box, deltas=deltas) # package
|
||||
"""删除ssp 已修改 8.26"""
|
||||
# Write *.env file
|
||||
write_env(filename + '.env', 'BELLHOP', 'Pekeris profile', freq, sspK, bdy, pos, beam, cInt, Rmax)
|
||||
write_bathy(filename,bathm)
|
||||
|
||||
|
||||
system(AtBinPath + "/bellhop " + filename)
|
||||
# Read sound field
|
||||
[x, x, x, x, Pos1, pressure] = read_shd(filename + '.shd')
|
||||
TL = -10 * np.log10(np.square(np.abs(pressure))) # Transmission Loss
|
||||
|
||||
return Pos1, TL
|
||||
|
||||
def call_Bellhop_Rays(freq, sd, rd, bathm, ssp, sed, base):
|
||||
# Source and receiving position
|
||||
filename = 'cz_ray'
|
||||
Rmax = bathm.r[-1] # unit: km
|
||||
dr = (1500 / freq) / 1000 # wavelength / 10, unit: km
|
||||
ran = np.linspace(0, Rmax, round(Rmax / dr)) # Receiving range (unit: km)
|
||||
Zmax, ssp_idx = calZmax(ssp, sed)
|
||||
"""RD 已修改 8.26"""
|
||||
RD = np.linspace(0, Zmax, round(Zmax / 10) + 1)
|
||||
pos = Pos(Source(sd), Dom(ran, RD))
|
||||
# Range of phase velocity
|
||||
cInt.Low = 1400
|
||||
cInt.High = 15000
|
||||
|
||||
# The number of media
|
||||
NMedia = 1
|
||||
ssp_raw = []
|
||||
depth = [0]
|
||||
# Sound speed profile
|
||||
Z = ssp[ssp_idx].z # Depth
|
||||
Cp = ssp[ssp_idx].c # Speed of P-wave
|
||||
Cs = np.zeros(np.shape(Z)) # Speed of S-wave
|
||||
Rho = np.ones(np.shape(Z)) # Density of the media
|
||||
Ap = np.zeros(np.shape(Z)) # Attenuation of P-wave
|
||||
As = np.zeros(np.shape(Z)) # Attenuation of S-wave
|
||||
ssp_raw.append(SSPraw(Z, Cp, Cs, Rho, Ap, As))
|
||||
depth.append(Z[-1])
|
||||
|
||||
# Sediment
|
||||
if sed != None:
|
||||
Z = sed[0].z + ssp[0].z[-1] # Depth
|
||||
Cp = sed[0].cp # Speed of P-wave
|
||||
Cs = sed[0].cs # Speed of S-wave
|
||||
Rho = sed[0].rho # Density of the media
|
||||
Ap = sed[0].a_p # Attenuation of P-wave
|
||||
As = sed[0].a_s # Attenuation of S-wave
|
||||
ssp_raw.append(SSPraw(Z, Cp, Cs, Rho, Ap, As))
|
||||
depth.append(Z[-1])
|
||||
"""Opt_top 已修改 8.26"""
|
||||
Opt_top = 'SVW'
|
||||
N = np.zeros(NMedia, np.int8)
|
||||
Sigma = np.zeros(NMedia + 1)
|
||||
sspK = SSP(ssp_raw, depth, NMedia, Opt_top, N, Sigma)
|
||||
|
||||
# Bottom option
|
||||
hs = HS(base[0].cp, base[0].cs, base[0].rho, base[0].a_p, base[0].a_s)
|
||||
Opt_bot = 'A~'
|
||||
bottom = BotBndry(Opt_bot, hs)
|
||||
top = TopBndry(Opt_top)
|
||||
bdy = Bndry(top, bottom)
|
||||
# Beam params
|
||||
run_type = 'R' # incoherently sum beams, see AT docs for more info
|
||||
nbeams = 301
|
||||
alpha = np.linspace(-15, 15, 2) # min and max launch angle -20 degrees to 20 degrees
|
||||
box = Box(Zmax, 100) # bound the region you let the beams go, depth in meters and range in km
|
||||
deltas = 0 # length step of ray trace, 0 means automatically choose
|
||||
beam = Beam(RunType=run_type, Nbeams=nbeams, alpha=alpha, box=box, deltas=deltas) # package
|
||||
"""删除ssp 已修改 8.26"""
|
||||
# Write *.env file
|
||||
write_env(filename + '.env', 'BELLHOP', 'Pekeris profile', freq, sspK, bdy, pos, beam, cInt, Rmax)
|
||||
write_bathy(filename, bathm)
|
||||
|
||||
system(AtBinPath + "/bellhop " + filename)
|
||||
# Read sound field
|
||||
return get_rays(filename + ".ray")
|
||||
|
||||
def find_cvgcRays(rays_total):
|
||||
Rays = []
|
||||
num_bnc_min = np.Inf
|
||||
for ray in rays_total[0]:
|
||||
if ray.num_top_bnc + ray.num_bot_bnc < num_bnc_min and max(ray.xy[1,:]) > 100:
|
||||
num_bnc_min = ray.num_top_bnc + ray.num_bot_bnc
|
||||
|
||||
for ray in rays_total[0]:
|
||||
if ray.num_top_bnc + ray.num_bot_bnc > num_bnc_min + 1:
|
||||
continue
|
||||
elif max(ray.xy[1,:]) < 100:
|
||||
continue
|
||||
else:
|
||||
Rays.append(ray)
|
||||
return Rays
|
||||
|
||||
def call_hjq(r, TL):
|
||||
TL_R = 20 * np.log10(r)
|
||||
out=[]
|
||||
|
||||
dTL = (TL_R - TL) * (TL <= TL_R)
|
||||
dTL[np.isnan(dTL)] = 0
|
||||
test_fliter_s = savgol_filter(dTL, 103, 3)
|
||||
test_fliter = medfilt(test_fliter_s,13)
|
||||
|
||||
signal=1
|
||||
for r_3 in range(len(r)):
|
||||
if r[r_3]>30000:
|
||||
break
|
||||
|
||||
czrangewidth_list = []
|
||||
for i in range(r_3,len(test_fliter)):
|
||||
czrangewidth = CzRangeWidth(0,0,0)
|
||||
if(test_fliter[i]>=5):
|
||||
out.append(i)
|
||||
if i+1<len(test_fliter):
|
||||
if test_fliter[i+1]<5:
|
||||
m = r[out[0]]
|
||||
n = r[out[len(out) - 1]]
|
||||
l=n-m
|
||||
# file_cz_data.write('\n'"会聚区距离:%.1fm"%m +"-%.1fm" %n)
|
||||
# file_cz_data.write('\n'"会聚区宽度:%.1fm\n"%l )
|
||||
czrangewidth_list.append(CzRangeWidth(m,n,l))
|
||||
out.clear()
|
||||
signal=0
|
||||
else:
|
||||
m = r[out[0]]
|
||||
n = r[out[len(out) - 1]]
|
||||
l = n - m
|
||||
# file_cz_data.write('\n'"会聚区距离:%.1fm" % m + "-%.1fm" % n)
|
||||
# file_cz_data.write('\n'"会聚区宽度:%.1fm\n" % l )
|
||||
czrangewidth_list.append(CzRangeWidth(m,n,l))
|
||||
out.clear()
|
||||
signal = 0
|
||||
# if signal==1:
|
||||
# file_cz_data.write('\n'" 没有出现会聚区\n")
|
||||
#滤波器效果图:
|
||||
#plt.plot(r, TL)
|
||||
#plt.plot(r, TL_R)
|
||||
# plt.plot(r,dTL)
|
||||
# plt.plot(r, test_fliter)
|
||||
# plt.gca().invert_yaxis()
|
||||
|
||||
# plt.show()
|
||||
return czrangewidth_list
|
||||
|
||||
|
||||
def call_fangwei(freq, sd, rd, bathm, ssp, sed, base, isPlot=False):
|
||||
czdetail = CzDetail("", [], [])
|
||||
last=len(ssp[0].c)-1
|
||||
# if ssp[0].c[0] > ssp[0].c[last]:
|
||||
# file_cz_data.write('\n'"直达会聚区:无")
|
||||
# file_cz_data.write('\n'"反射会聚区:")
|
||||
# else:
|
||||
# file_cz_data.write('\n'"直达会聚区:")
|
||||
sed = None
|
||||
rays_total = call_Bellhop_Rays(freq, sd, rd, bathm, ssp, sed, base)
|
||||
Rays = find_cvgcRays(rays_total)
|
||||
[Pos, TL] = call_Bellhop(freq, sd, rd, bathm, ssp, sed, base)
|
||||
[x, x, x, x, Pos, pressure] = read_shd('cz.shd')
|
||||
TL = -10 * np.log10(np.square(np.abs(pressure))) # Transmission Loss
|
||||
# Plot
|
||||
if isPlot:
|
||||
plt.pcolor(Pos.r.range, Pos.r.depth, TL[0, 0, :, :], vmin=40, vmax=130, cmap='jet_r', shading='auto')
|
||||
plt.xlabel("Range/m")
|
||||
plt.ylabel("Depth/m")
|
||||
plt.gca().invert_yaxis()
|
||||
plt.colorbar()
|
||||
plt.show()
|
||||
czrangewidth_list = call_hjq(Pos.r.range,TL[0, 0, 1,:])
|
||||
if ssp[0].c[0] > ssp[0].c[last]:
|
||||
czdetail.directCz = []
|
||||
czdetail.reflectCz = czrangewidth_list
|
||||
else:
|
||||
czdetail.directCz = czrangewidth_list
|
||||
czdetail.reflectCz = []
|
||||
return Pos.r.range, Pos.r.depth, TL[0, 0, :, :], bathm, Rays, czdetail
|
||||
|
||||
def call_cz(ETOPO1Path, STPath, freq, lat, lon, azi, sourceDepth=10, receiveDepth=10, timeType='Annual', isPlot=False):
|
||||
sd = np.array([sourceDepth]) # Source depth
|
||||
rd = np.linspace(0, receiveDepth, 351) # Receiving depth
|
||||
# 定义时间段
|
||||
timeIndex = timeType
|
||||
# 创建类
|
||||
data = DataBase(ETOPO1Path, STPath)
|
||||
# 设置时间段
|
||||
data.set_timePeriod(timeIndex)
|
||||
|
||||
results = []
|
||||
ranges, depths, TL, bathym, Rays = [], [], [], [], []
|
||||
|
||||
''' 计算单个方向的会聚区 '''
|
||||
if azi != None:
|
||||
[bathm, ssp, sed, base] = GetEnv(data, 25, Coord(lon, lat), R=100, azi=azi)
|
||||
if np.mean(bathm.d) < 2000:
|
||||
return results
|
||||
else:
|
||||
ranges, depths, TL, bathym, Rays, czdetail = call_fangwei(freq, sd, rd, bathm, ssp, sed, base, isPlot=isPlot)
|
||||
czdetail.descript = "{:.1f}°方向".format(azi)
|
||||
results.append(CzData(0, ranges, depths, TL, bathym, Rays, czdetail))
|
||||
return results
|
||||
|
||||
''' 计算8个方向的会聚区 '''
|
||||
[bathm, ssp, sed, base] = GetEnv(data, 25, Coord(lon, lat), R=100, azi=0)
|
||||
if bathm.d[0] < 2000:
|
||||
# file_cz_data.write("各个方位都不会出现会聚区")
|
||||
return results
|
||||
else:
|
||||
descripts = ["正北方向", "东北方向", "正东方向", "东南方向", "正南方向", "西南方向", "正西方向", "西北方向"]
|
||||
theta = np.arange(0, 359, 45)
|
||||
for i in range(8):
|
||||
[bathm, ssp, sed, base] = GetEnv(data, 25, Coord(lon, lat), R=100, azi=theta[i])
|
||||
if np.mean(bathm.d) < 2000:
|
||||
# 不会出现会聚区
|
||||
continue
|
||||
ranges, depths, TL, bathym, Rays, czdetail = call_fangwei(freq, sd, rd, bathm, ssp, sed, base, isPlot=isPlot)
|
||||
czdetail.descript = descripts[i]
|
||||
results.append(CzData(theta[i], ranges, depths, TL, bathym, Rays, czdetail))
|
||||
|
||||
return results
|
||||
可执行文件
+411
@@ -0,0 +1,411 @@
|
||||
import numpy as np
|
||||
# from copy import deepcopy
|
||||
from matplotlib import cm
|
||||
# from matplotlib.colors import ListedColormap as LCM
|
||||
from scipy.interpolate import interp1d
|
||||
import matplotlib.pyplot as plt
|
||||
|
||||
|
||||
'''
|
||||
Objects for interfacing with Michael Porter's models.
|
||||
Designed in analog with the types of objects called by read_shd, write_fieldflp, write_env, etc.
|
||||
'''
|
||||
|
||||
|
||||
class Source:
|
||||
def __init__(self, depth):
|
||||
self.depth = depth
|
||||
self.x = None
|
||||
self.y = None
|
||||
|
||||
class Dom:
|
||||
def __init__(self, ran, depth, offsets=None):
|
||||
self.range = ran # in km
|
||||
self.depth = depth
|
||||
if offsets is not None:
|
||||
self.offsets = offsets
|
||||
|
||||
class Pos:
|
||||
def __init__(self, Source, Dom):
|
||||
self.s = Source
|
||||
self.r = Dom
|
||||
|
||||
class Ice:
|
||||
def __init__(self, BumDen, eta, xi):
|
||||
self.BumDen= BumDen
|
||||
self.eta = eta
|
||||
self.xi = xi
|
||||
|
||||
class SSPraw:
|
||||
def __init__(self,z, alphaR, betaR, rho, alphaI, betaI):
|
||||
"""
|
||||
Input:
|
||||
z - numpy 1d array
|
||||
Depths the ssp is taken at
|
||||
alphaR - numpy 1d array
|
||||
ssp vals
|
||||
betaR - numpy 1d array
|
||||
shear speeds
|
||||
rho - numpy 1d array
|
||||
density vals at the points
|
||||
alphaI - numpy 1d array
|
||||
attenuation (p-wave)
|
||||
betaI - numpy 1d array
|
||||
shear attenuation
|
||||
"""
|
||||
self.z = z
|
||||
self.alphaR = alphaR # sound speed in array
|
||||
self.betaR = betaR # shear wave speed
|
||||
self.rho = rho
|
||||
self.alphaI = alphaI # atten. in array (alpha (z))
|
||||
self.betaI = betaI # shear attenuation
|
||||
|
||||
def make_sspf(self):
|
||||
self.sspf = interp1d(self.z, self.alphaR)
|
||||
|
||||
def interp_all(self):
|
||||
self.betaI_f = interp1d(self.z, self.betaI)
|
||||
self.betaR_f = interp1d(self.z, self.betaR)
|
||||
self.rho_f = interp1d(self.z, self.rho)
|
||||
self.alphaR_f = interp1d(self.z, self.alphaR)
|
||||
self.alphaI_f = interp1d(self.z, self.alphaI)
|
||||
return self.alphaR_f, self.betaR_f, self.rho_f, self.alphaI_f, self.betaI_f
|
||||
|
||||
class SSP:
|
||||
def __init__(self, raw, depth, NMedia, Opt=None, N=None, sigma=0, ranges=0):
|
||||
self.NMedia = NMedia # number of media layers
|
||||
self.Opt = Opt # option: not sure what this is for
|
||||
self.N = N # array with num points in each layer, don't include one for halfpace
|
||||
self.sigma = sigma # ''interfacial roughness'', one for each layer? see Kuperman and ingenito 1977 for definition, include a point for the halfspace
|
||||
self.depth = depth # depth array for layers
|
||||
self.ranges = ranges
|
||||
self.raw = raw # list of raw ssp profile
|
||||
self.sspf = None
|
||||
|
||||
def make_sspf(self):
|
||||
for raw in self.raw:
|
||||
raw.make_sspf()
|
||||
if self.NMedia > 1:
|
||||
self.ssp_vals = np.zeros((len(self.depth), 1))
|
||||
if self.NMedia == 2:
|
||||
layer_depth = self.raw[0].z[-1]
|
||||
self.sspf = lambda z: np.piecewise(z, [z<layer_depth, z>=layer_depth], [lambda z: self.raw[0].sspf(z), lambda z: self.raw[1].sspf(z)])
|
||||
elif self.NMedia == 3:
|
||||
layer_depth_one = self.raw[0].z[-1]
|
||||
layer_depth_two = self.raw[1].z[-1]
|
||||
func1 = lambda z: np.piecewise(z, [z<layer_depth_one, z>= layer_depth_one], [lambda z: self.raw[0].sspf(z), lambda z: self.raw[1].sspf(z)])
|
||||
self.sspf = lambda z: np.piecewise(z, [z<layer_depth_two, z>= layer_depth_two], [lambda z: func1(z), lambda z: self.raw[2].sspf(z)])
|
||||
else:
|
||||
raise ValueError("too many layers")
|
||||
else:
|
||||
self.ssp_vals = self.raw[0].alphaR
|
||||
self.sspf = self.raw[0].sspf
|
||||
|
||||
class HS:
|
||||
def __init__(self, alphaR=np.array([]), betaR=np.array([]), rho=np.array([]), alphaI=np.array([]), betaI=np.array([])):
|
||||
self.alphaR = np.array(alphaR)
|
||||
self.betaR = np.array(betaR)
|
||||
self.rho = np.array(rho)
|
||||
self.alphaI = np.array(alphaI)
|
||||
self.betaI = np.array(betaI)
|
||||
|
||||
class BotBndry:
|
||||
def __init__(self, Opt, Hs, depth=[], betaI=[0], ):
|
||||
self.Opt = Opt # 'A' for analytic or 'CVW' for interpolated ssp
|
||||
self.hs = Hs
|
||||
|
||||
class TopBndry:
|
||||
def __init__(self, Opt, depth=[]):
|
||||
self.Opt = Opt
|
||||
self.cp = None
|
||||
self.cs = None
|
||||
self.rho = None
|
||||
|
||||
class Bndry:
|
||||
def __init__(self, top, bot):
|
||||
self.Top = top
|
||||
self.Bot = bot
|
||||
|
||||
class Box:
|
||||
def __init__(self, z, r):
|
||||
self.r = r
|
||||
self.z = z
|
||||
|
||||
class Beam:
|
||||
def __init__(self, RunType=None, Type=None,Nbeams=None, Ibeam=None, Nrays=None, alpha=None, deltas=None, box=None, epmult=None, rloop=None, Ibwin=None, Nimage = None):
|
||||
self.RunType = RunType
|
||||
self.Type = Type
|
||||
self.Nbeams = Nbeams
|
||||
self.Ibeam = Ibeam
|
||||
self.Nrays = Nrays
|
||||
self.alpha = alpha
|
||||
self.deltas = deltas
|
||||
self.box = box
|
||||
self.epmult = epmult
|
||||
self.rloop = rloop
|
||||
self.Ibwin = Ibwin
|
||||
self.Nimage = None
|
||||
|
||||
class cInt:
|
||||
def __init__(self, low, high):
|
||||
self.Low = low
|
||||
self.High = high
|
||||
|
||||
class Field:
|
||||
def __init__(self, **kwargs):
|
||||
self.pos = kwargs['pos']
|
||||
self.greens = kwargs['pressure']
|
||||
self.freq = kwargs['freq'] # a list of frequencies
|
||||
|
||||
def contour(self):
|
||||
shape = np.shape(self.greens)
|
||||
if len(shape) > 2:
|
||||
raise ValueError("Field object is too high dimensional, try multi_contour")
|
||||
pos = self.pos
|
||||
ax = plt.contourf(pos.r.range, -pos.r.depth, np.log10(abs(self.greens.real)))
|
||||
return ax
|
||||
|
||||
def multi_contour(self):
|
||||
print('not implemented, maybe one day...')
|
||||
|
||||
class Modes:
|
||||
def __init__(self, **kwargs):
|
||||
self.M = kwargs['M']
|
||||
self.k = kwargs['modes_k']
|
||||
self.z = np.array(kwargs['z'])
|
||||
self.phi = kwargs['modes_phi']
|
||||
self.top = kwargs['top']
|
||||
self.bot = kwargs['bot']
|
||||
self.N = kwargs['N']
|
||||
self.Nfreq = kwargs['Nfreq']
|
||||
self.Nmedia = kwargs['Nmedia']
|
||||
self.depth = kwargs['depth']
|
||||
self.rho = kwargs['rho']
|
||||
self.freqvec = kwargs['freqVec']
|
||||
self.init_dict = kwargs
|
||||
self.num_modes = self.M # easier to remember
|
||||
|
||||
def get_excited_modes(self, sd, threshold):
|
||||
'''
|
||||
return an array of modes that are excited by a source at sd meters depth
|
||||
threshold
|
||||
|
||||
also populate some structures in moded caled excited_phi and excited_k
|
||||
|
||||
'''
|
||||
if sd not in self.z:
|
||||
raise ValueError("sd not in the depth array, are you sure it's the right depth you're passing?")
|
||||
depth_ind = [i for i in range(len(self.z)) if self.z[i] == sd][0]
|
||||
vals = self.phi[depth_ind,:]
|
||||
const = np.max(abs(vals))
|
||||
filtered_inds = [i for i in range(len(self.k)) if abs(self.phi[depth_ind, i]) / const > threshold]
|
||||
self.excited_phi = self.phi[:, filtered_inds]
|
||||
self.excited_k = self.k[filtered_inds]
|
||||
return self.excited_phi, self.excited_k
|
||||
|
||||
def get_source_depth_ind(self, sd):
|
||||
"""
|
||||
sd is an int
|
||||
"""
|
||||
tol = 1e-2
|
||||
sind = [i for i in range(len(self.z)) if abs(self.z[i]-sd) < tol]
|
||||
if len(sind) == 0 :
|
||||
raise ValueError("sd not in the depth array, are you sure it's the right depth you're passing?")
|
||||
else:
|
||||
self.sind = sind[0]
|
||||
return self.sind
|
||||
|
||||
def remove_source_pos(self, sd):
|
||||
"""
|
||||
Take the source at sd from the mode matrix
|
||||
Initiate a new attribute to hold the source
|
||||
modal value
|
||||
"""
|
||||
sind = self.get_source_depth_ind(sd)
|
||||
new_pos_len = len(self.z) - 1
|
||||
new_phi = np.zeros((new_pos_len, self.num_modes), dtype=self.phi.dtype)
|
||||
new_phi[:sind, :] = self.phi[:sind, :]
|
||||
new_phi[sind:,:] = self.phi[sind+1:,:]
|
||||
self.phi = new_phi
|
||||
new_z = np.zeros((new_pos_len), dtype=self.z.dtype)
|
||||
new_z[:sind] = self.z[:sind]
|
||||
new_z[sind:] = self.z[sind+1:]
|
||||
self.z = new_z
|
||||
self.source_strength = self.phi[sind,:]
|
||||
return
|
||||
|
||||
def get_source_strength(self, sd):
|
||||
"""
|
||||
Get the value of each mode at the source depth sd (meters)
|
||||
Initialize new attribute for the source strength
|
||||
"""
|
||||
sind = self.get_source_depth_ind(sd)
|
||||
vals = self.phi[sind,:]
|
||||
self.source_strength = vals
|
||||
return vals
|
||||
|
||||
def get_receiver_modes(self, zr):
|
||||
"""
|
||||
zr is array like
|
||||
"""
|
||||
tol = 1e-3
|
||||
r_inds = [i for i in range(len(self.z)) if np.min(abs(self.z[i]-zr)) < tol]
|
||||
receiver_modes = self.phi[r_inds, :]
|
||||
self.receiver_modes = receiver_modes
|
||||
return receiver_modes
|
||||
|
||||
def get_source_excitation(self, zs):
|
||||
"""
|
||||
For case where there is a track, there may be multiple repeats in zs
|
||||
"""
|
||||
tol = 1e-3
|
||||
r_inds = [np.argmin(abs(zs[i] - self.z)) for i in range(len(zs))]
|
||||
strength_modes = self.phi[r_inds, :]
|
||||
self.strength_modes = strength_modes
|
||||
return strength_modes
|
||||
|
||||
|
||||
def plot(self):
|
||||
figs = []
|
||||
if self.M > 5:
|
||||
for i in range(self.M):
|
||||
fig = plt.figure(i)
|
||||
plt.plot(self.phi[:,i], -self.z)
|
||||
figs.append(fig)
|
||||
return figs
|
||||
|
||||
def __repr__(self):
|
||||
return 'Modes object with ' + str(self.M) + ' distinct modes'
|
||||
|
||||
class Arrival:
|
||||
def __init__(self, info_list):
|
||||
self.amp = info_list[0]
|
||||
self.delay = info_list[1]
|
||||
self.src_ang = info_list[2]
|
||||
self.rec_ang = info_list[3]
|
||||
self.num_top_bnc = info_list[4]
|
||||
self.num_bot_bnc = info_list[5]
|
||||
|
||||
class Arrivals:
|
||||
def __init__(self, arrival_list):
|
||||
self.arrivals = arrival_list
|
||||
|
||||
def plot_cir(self, vals=None,ax=None):
|
||||
"""
|
||||
Plot the channel impulse response
|
||||
Vals provides the option to pass in a set of arrivals to use fo calibrating the y axis
|
||||
If vals=None, I use the arrivals in the object to calibrate the y-axis
|
||||
I don't create a figure
|
||||
I return ymin, ymax, vals so that the values from this arrival set can be used in a more global
|
||||
scope to set the y-axis limits (useful for creating videos comprised of snapshots of a bunch
|
||||
of CIR's). For example, I want to plot a bunch of Arrivals on the same plot, or combine a bunch of
|
||||
CIRs into a video. Then I need to have the same axis limits for all the plots.
|
||||
I can use default vals (None) for the first plot, then use the ymin, ymax, vals return values
|
||||
in a larger scope to standardize the axes. Then for the second, third, ... plots, I pass in vals
|
||||
to make sure they all have the same time axis.
|
||||
Output -
|
||||
ymin - float
|
||||
ymax -float
|
||||
plus/minus 1.5 times max amplitude value
|
||||
vals - list
|
||||
vals[0] is the times
|
||||
vals[1] is the amplitude vals
|
||||
"""
|
||||
arrival_list = self.arrivals
|
||||
amps = np.array([abs(x.amp) for x in arrival_list])
|
||||
phase = np.array([np.angle(x.amp) for x in arrival_list])
|
||||
times = np.array([x.delay for x in arrival_list])
|
||||
"""
|
||||
Create the time axis
|
||||
"""
|
||||
if type(vals) != type(None):
|
||||
t = np.linspacea(.9*np.min(vals[0]), 1.1*np.max(vals[0]), 100)
|
||||
else:
|
||||
t = np.linspace(.9*np.min(times), 1.1*np.max(times), 100)
|
||||
zeros = np.zeros(t.size)
|
||||
if type(ax) == type(None):
|
||||
fig, ax = plt.subplots(2,1)
|
||||
ax.scatter(t.real, zeros, s=6)
|
||||
ax.stem(times.real, amps.real, markerfmt=' ', basefmt=' ',use_line_collection=True)
|
||||
ax.scatter(times.real, amps,s=16,c='k')
|
||||
scale = 1.5*np.max(abs(amps)) # set yaxis scale
|
||||
ymin = - scale
|
||||
ymax = scale
|
||||
vals = [times.real, amps]
|
||||
return ymin, ymax, vals
|
||||
|
||||
def plot_ellipse(self, vals=None, ref_amp =None, src_ang=False, ax=None):
|
||||
"""
|
||||
Produce the travel time ellipse with colorbar for amplitude
|
||||
Input -
|
||||
self - contains all the arrival info
|
||||
vals - optional
|
||||
allows me to use a reference arrival set to calibrate the plot axes
|
||||
vals[0] = times
|
||||
vals[0] = amps
|
||||
"""
|
||||
arrival_list = self.arrivals
|
||||
amps = np.array([abs(x.amp) for x in arrival_list])
|
||||
times = np.array([x.delay.real for x in arrival_list])
|
||||
rec_angles = np.array([x.rec_ang for x in arrival_list])
|
||||
src_angles = np.array([x.rec_ang for x in arrival_list])
|
||||
"""
|
||||
Create the time axis
|
||||
"""
|
||||
if type(vals) != type(None):
|
||||
tmin, tmax = np.min(vals[0]), np.max(vals[0])
|
||||
else:
|
||||
tmin, tmax = np.min(times), np.max(times)
|
||||
if type(ref_amp) == type(None):
|
||||
amps = amps / np.max(abs(amps))
|
||||
else:
|
||||
amps /= abs(ref_amp)
|
||||
cvals = 10*np.log10(abs(amps))
|
||||
#cvals = np.linspace(-5, 0, len(amps))
|
||||
""" Make a nice cmap """
|
||||
cmap = cm.get_cmap('Spectral')
|
||||
""" Configure the x axis """
|
||||
|
||||
if type(ax) == type(None):
|
||||
fig, ax = plt.subplots(2,1)
|
||||
ax.scatter([tmin, tmax], [0,0], s=0)
|
||||
if src_ang == False:
|
||||
angles = rec_angles
|
||||
else:
|
||||
angles = src_angles
|
||||
max_db_down = 10
|
||||
cvals_normed = abs(cvals) / max_db_down
|
||||
strong_inds = cvals > -max_db_down
|
||||
ax.scatter(times[strong_inds], angles[strong_inds], s=25, c=cmap(cvals_normed[strong_inds]))
|
||||
vals = [times, amps]
|
||||
ymin, ymax = -1.5*np.max(abs(angles)), 1.5*np.max(abs(angles))
|
||||
return ymin, ymax, vals
|
||||
|
||||
class KernInput:
|
||||
def __init__(self, Field_r, Field_s, env):
|
||||
self.gr = Field_r.greens_mat
|
||||
self.num_rcvrs = len(self.gr)
|
||||
self.gs = np.flip(Field_s.greens_mat, axis=1) # move source off axis
|
||||
self.env = env
|
||||
self.Pos = self.Field_r.Pos
|
||||
|
||||
|
||||
class Eigenray:
|
||||
def __init__(self, launch_ang, num_top_bnc, num_bot_bnc, xy_arr):
|
||||
"""
|
||||
launch_ang
|
||||
launch angl in degrees
|
||||
num_top_bnc
|
||||
integer
|
||||
num_bot_bnc
|
||||
integer
|
||||
xy_arr - np array
|
||||
2 by num steps, first is x position, second is y
|
||||
(so plt.plot(xy_arr[0,:], xy_arr[1,:]) will plot the ray)
|
||||
"""
|
||||
self.src_ang = launch_ang
|
||||
self.num_top_bnc = num_top_bnc
|
||||
self.num_bot_bnc = num_bot_bnc
|
||||
self.xy = xy_arr
|
||||
|
||||
|
||||
可执行文件
+139
@@ -0,0 +1,139 @@
|
||||
from os import system
|
||||
import numpy as np
|
||||
from pyat.readwrite import write_env, write_fieldflp, read_shd
|
||||
from pyat.env import Pos, Source, Dom, cInt, SSPraw, SSP, HS, BotBndry, TopBndry, Bndry
|
||||
from pyat.config import AtBinPath
|
||||
|
||||
def calZmax(ssp, sed):
|
||||
d = np.array([])
|
||||
for it in range(len(ssp)):
|
||||
if sed == None:
|
||||
d = np.append(d, ssp[it].z[-1])
|
||||
else:
|
||||
d = np.append(d, ssp[it].z[-1] + sed[it].z[-1])
|
||||
Zmax = max(d)
|
||||
return Zmax
|
||||
|
||||
|
||||
def call_krakenc(freq, sd, rd, bathm, ssp, sed, base):
|
||||
filename = "envK"
|
||||
envFilename = "envK.env"
|
||||
model = "KRAKEN"
|
||||
title = "Krakenc Waveguide"
|
||||
|
||||
# Source and receiving position
|
||||
Rmax = bathm.r[-1] # unit: km
|
||||
dr = (1500 / freq / 3) / 1000 # wavelength / 10, unit: km
|
||||
ran = np.linspace(0, Rmax, round(Rmax / dr)) # Receiving range (unit: km)
|
||||
Zmax = calZmax(ssp, sed)
|
||||
RD = np.linspace(0, Zmax, round(Zmax) + 1)
|
||||
pos = Pos(Source(sd), Dom(ran, RD))
|
||||
|
||||
# Range of phase velocity
|
||||
cInt.Low = 1400
|
||||
cInt.High = 15000
|
||||
|
||||
# Write environmental file
|
||||
for it in range(len(ssp)):
|
||||
# The number of media
|
||||
if sed != None:
|
||||
NMedia = 2
|
||||
else:
|
||||
NMedia = 1
|
||||
|
||||
ssp_raw = []
|
||||
depth = [0]
|
||||
# Sound speed profile
|
||||
Z = ssp[it].z # Depth
|
||||
Cp = ssp[it].c # Speed of P-wave
|
||||
Cs = np.zeros(np.shape(Z)) # Speed of S-wave
|
||||
Rho = np.ones(np.shape(Z)) # Density of the media
|
||||
Ap = np.zeros(np.shape(Z)) # Attenuation of P-wave
|
||||
As = np.zeros(np.shape(Z)) # Attenuation of S-wave
|
||||
ssp_raw.append(SSPraw(Z, Cp, Cs, Rho, Ap, As))
|
||||
depth.append(Z[-1])
|
||||
|
||||
# Sediment
|
||||
if sed != None:
|
||||
Z = sed[it].z + ssp[it].z[-1] # Depth
|
||||
Cp = sed[it].cp # Speed of P-wave
|
||||
Cs = sed[it].cs # Speed of S-wave
|
||||
Rho = sed[it].rho # Density of the media
|
||||
Ap = sed[it].a_p # Attenuation of P-wave
|
||||
As = sed[it].a_s # Attenuation of S-wave
|
||||
ssp_raw.append(SSPraw(Z, Cp, Cs, Rho, Ap, As))
|
||||
depth.append(Z[-1])
|
||||
|
||||
# Make sure that the base depth is consistent in all profiles
|
||||
if depth[-1] != Zmax:
|
||||
Z = [depth[-1], Zmax] # Depth
|
||||
Cp = [Cp[-1], base[it].cp] # Speed of P-wave
|
||||
Cs = [Cs[-1], base[it].cs] # Speed of S-wave
|
||||
Rho = [Rho[-1], base[it].rho] # Density of the media
|
||||
Ap = [Ap[-1], base[it].a_p] # Attenuation of P-wave
|
||||
As = [As[-1], base[it].a_s] # Attenuation of S-wave
|
||||
ssp_raw.append(SSPraw(Z, Cp, Cs, Rho, Ap, As))
|
||||
depth.append(Z[-1])
|
||||
NMedia += 1
|
||||
|
||||
Opt_top = 'SVW .'
|
||||
N = np.zeros(NMedia, np.int8)
|
||||
Sigma = np.zeros(NMedia+1)
|
||||
sspK = SSP(ssp_raw, depth, NMedia, Opt_top, N, Sigma)
|
||||
|
||||
# Bottom option
|
||||
hs = HS(base[it].cp, base[it].cs, base[it].rho, base[it].a_p, base[it].a_s)
|
||||
Opt_bot = 'A'
|
||||
bottom = BotBndry(Opt_bot, hs)
|
||||
top = TopBndry(Opt_top)
|
||||
bdy = Bndry(top, bottom)
|
||||
|
||||
# Write *.env file
|
||||
if it == 0:
|
||||
write_env(envFilename, model, title, freq, sspK, bdy, pos, [], cInt, Rmax)
|
||||
else:
|
||||
write_env(envFilename, model, title, freq, sspK, bdy, pos, [], cInt, Rmax, None, 'a')
|
||||
|
||||
# Call krakenc.exe
|
||||
system(AtBinPath + "/krakenc " + filename)
|
||||
# Write *.flp file
|
||||
Opt_flp = 'RC'
|
||||
pos.r.depth = rd
|
||||
write_fieldflp(filename, Opt_flp, pos, NProf=len(ssp), rProf=bathm.r)
|
||||
# Call field.exe
|
||||
system(AtBinPath + "/field " + filename)
|
||||
# Read sound field
|
||||
[x, x, x, x, Pos1, pressure] = read_shd(filename+'.shd')
|
||||
TL = -10 * np.log10(np.square(np.abs(pressure))) # Transmission Loss
|
||||
|
||||
return Pos1, TL
|
||||
|
||||
# if __name__=="__main__":
|
||||
''' ********************************************************************************* '''
|
||||
''' ***************************** Input Parameters ********************************** '''
|
||||
''' ********************************************************************************* '''
|
||||
# freq = 25 # Frequency
|
||||
# sd = np.array([40.0]) # Source depth
|
||||
# rd = np.linspace(0, 500, 501) # Receiving depth
|
||||
|
||||
# # 定义坐标
|
||||
# lat = 18.00
|
||||
# lon = 114.00
|
||||
# # 定义时间段
|
||||
# timeIndex = db.timeDict['Annual']
|
||||
# # 创建类
|
||||
# data = db.DataBase()
|
||||
# # 设置时间段
|
||||
# data.set_timePeriod(timeIndex)
|
||||
|
||||
# [bathm, ssp, sed, base] = GetEnv(data, 25, Coord(lon, lat), R=50, azi=0)
|
||||
|
||||
# [Pos, TL] = call_krakenc(freq, sd, rd, bathm, ssp, sed, base)
|
||||
|
||||
# # Plot
|
||||
# plt.pcolor(Pos.r.range, Pos.r.depth, TL[0,0,:,:], vmin=40, vmax=130, cmap='jet_r', shading='auto')
|
||||
# plt.xlabel("Range/m")
|
||||
# plt.ylabel("Depth/m")
|
||||
# plt.gca().invert_yaxis()
|
||||
# plt.colorbar()
|
||||
# plt.show()
|
||||
可执行文件
+72
@@ -0,0 +1,72 @@
|
||||
from pyat.ramRW import PosRAM, PROF, SSPRAM, write_env_RAM, readTL_RAM
|
||||
from os import system
|
||||
import numpy as np
|
||||
from pyat.config import AtBinPath
|
||||
|
||||
def call_ram(freq, sd, rd, bathm, ssp, sed):
|
||||
''' ********************************************************************************* '''
|
||||
''' ************************** Sound Field Calculation ****************************** '''
|
||||
''' ********************************************************************************* '''
|
||||
title = "Waveguide"
|
||||
# Source and receiving position
|
||||
bathm.r = bathm.r * 1000 # km -> m
|
||||
rmax = max(bathm.r) # Maximum receiving range (unit: m)
|
||||
zmax = round(max(bathm.d) * 2) # Maximum receiving depth (uint: m)
|
||||
zmplt = round(max(bathm.d)*1.1) # Maximum depth of plot (uint: m)
|
||||
dz = 1500 / freq / 15 # Step in depth direction: wavelength / 15
|
||||
dr = 10 * dz # Step in range direction
|
||||
pos = PosRAM(sd, rd, rmax, zmax, dr, dz, zmplt)
|
||||
|
||||
# Sound speed profile for RAM
|
||||
ssp_ram = []
|
||||
for it in range(len(ssp)):
|
||||
rp = bathm.r[it] # Range of this profile
|
||||
Z = sed[it].z
|
||||
cw_p = PROF(ssp[it].z, ssp[it].c) # Water sound speed profile
|
||||
cb_p = PROF(Z, sed[it].cp) # Bottom sound speed profile
|
||||
rhob_p = PROF(Z, sed[it].rho) # Sea bottom density profile
|
||||
Z = np.append(Z, Z[-1] + 100)
|
||||
Ap = np.append(sed[it].a_p, 10)
|
||||
# Ap = sed[it].a_p
|
||||
attn_p = PROF(Z, Ap) # Sea bottom attenuation profile
|
||||
|
||||
ssp_ram.append(SSPRAM(rp, cw_p, cb_p, rhob_p, attn_p))
|
||||
|
||||
|
||||
# Write ram.in file
|
||||
write_env_RAM(title, freq, pos, bathm, ssp_ram)
|
||||
# Call ram.exe
|
||||
system(AtBinPath + "/ram")
|
||||
# Read tl.grid
|
||||
return readTL_RAM()
|
||||
|
||||
# if __name__=="__main__":
|
||||
# ''' ********************************************************************************* '''
|
||||
# ''' ***************************** Input Parameters ********************************** '''
|
||||
# ''' ********************************************************************************* '''
|
||||
# freq = 25 # Frequency
|
||||
# sd = 40.0 # Source depth
|
||||
# rd = 30.0 # Receiving depth
|
||||
|
||||
# # 定义坐标
|
||||
# lat = 18.00
|
||||
# lon = 114.00
|
||||
# # 定义时间段
|
||||
# timeIndex = db.timeDict['Annual']
|
||||
# # 创建类
|
||||
# data = db.DataBase()
|
||||
# # 设置时间段
|
||||
# data.set_timePeriod(timeIndex)
|
||||
|
||||
# [bathm, ssp, sed, base] = GetEnv(data, 25, Coord(lon, lat), R=100, azi=5)
|
||||
|
||||
# # 调用ram模块
|
||||
# [rd, rr, TL] = call_ram(freq, sd, rd, bathm, ssp, sed)
|
||||
|
||||
# # Plot
|
||||
# plt.pcolormesh(rr, rd, TL, vmin=40, vmax=90, cmap='jet_r', shading='auto')
|
||||
# plt.xlabel("Range/m")
|
||||
# plt.ylabel("Depth/m")
|
||||
# plt.gca().invert_yaxis()
|
||||
# plt.colorbar()
|
||||
# plt.show()
|
||||
可执行文件
+151
@@ -0,0 +1,151 @@
|
||||
from pyat.env import *
|
||||
import numpy as np
|
||||
|
||||
def write_env_RAM(TitleEnv, freq, pos, bathym, ssp, envfil = "ram.in"):
|
||||
# envfil = "ram.in"
|
||||
Rmax = pos.rmax
|
||||
|
||||
f = open(envfil, "wt")
|
||||
|
||||
ndr = 1
|
||||
ndz = 1
|
||||
|
||||
zmplt = pos.zmplt
|
||||
|
||||
c0 = np.mean(ssp[0].cw.v)
|
||||
|
||||
nPade = 8 # The number of Pade terms
|
||||
nStarter = 4 # The number of starter terms
|
||||
rs = 0.0 # The stability constraints range
|
||||
|
||||
f.write("{:s}".format(TitleEnv) + " ! Title\r\n")
|
||||
f.write("{:8.2f} ".format(freq) + \
|
||||
"{:8.2f} ".format(pos.zs) + \
|
||||
"{:8.2f} ".format(pos.zr) + \
|
||||
"\t \t \t ! Frequency (Hz) zs zr\r\n")
|
||||
f.write("{:8.2f} ".format(Rmax) + \
|
||||
"{:8.2f} ".format(pos.dr) + \
|
||||
"{:3d} ".format(ndr) + \
|
||||
"\t \t \t ! rmax dr ndr \r\n")
|
||||
f.write("{:8.2f} ".format(pos.zmax) + \
|
||||
"{:8.2f} ".format(pos.dz) + \
|
||||
"{:3d} ".format(ndz) + \
|
||||
"{:8.2f} ".format(zmplt) + \
|
||||
"\t \t \t ! zmax dz ndz zmplt\r\n")
|
||||
f.write("{:8.2f} ".format(c0) + \
|
||||
"{:1d} ".format(nPade) + \
|
||||
"{:1d} ".format(nStarter) + \
|
||||
"{:8.2f} ".format(rs) + \
|
||||
"\t \t \t ! c0 np ns rs\r\n")
|
||||
|
||||
# Bathymetry
|
||||
for it in range(len(bathym.r)):
|
||||
f.write("{:8.2f} ".format(bathym.r[it]) + "{:8.2f} ".format(bathym.d[it]) + \
|
||||
" \t \t \t ! rb zb\r\n")
|
||||
|
||||
# Sound speed profile
|
||||
f.write("-1 -1\r\n")
|
||||
for it in range(len(ssp)):
|
||||
# rp
|
||||
if it != 0:
|
||||
f.write("{:8.2f} \t \t \t ! rp\r\n".format(ssp[it].rp))
|
||||
# cw
|
||||
for ii in range(len(ssp[it].cw.z)):
|
||||
f.write("{:8.2f} ".format(ssp[it].cw.z[ii]) + "{:8.2f} ".format(ssp[it].cw.v[ii]) + \
|
||||
" \t \t \t ! z cw\r\n")
|
||||
f.write("-1 -1\r\n")
|
||||
|
||||
# cb
|
||||
for ii in range(len(ssp[it].cb.z)):
|
||||
f.write("{:8.2f} ".format(ssp[it].cb.z[ii]) + "{:8.2f} ".format(ssp[it].cb.v[ii]) + \
|
||||
" \t \t \t ! z cb\r\n")
|
||||
f.write("-1 -1\r\n")
|
||||
|
||||
# rhob
|
||||
for ii in range(len(ssp[it].rhob.z)):
|
||||
f.write("{:8.2f} ".format(ssp[it].rhob.z[ii]) + "{:8.2f} ".format(ssp[it].rhob.v[ii]) + \
|
||||
" \t \t \t ! z rhob\r\n")
|
||||
f.write("-1 -1\r\n")
|
||||
|
||||
# attn
|
||||
for ii in range(len(ssp[it].attn.z)):
|
||||
f.write("{:8.2f} ".format(ssp[it].attn.z[ii]) + "{:8.2f} ".format(ssp[it].attn.v[ii]) + \
|
||||
" \t \t \t ! z attn\r\n")
|
||||
f.write("-1 -1\r\n")
|
||||
|
||||
|
||||
def readTL_RAM(filePath=None):
|
||||
if filePath != None:
|
||||
f = open(filePath + "\\tl.grid")
|
||||
else:
|
||||
f = open("tl.grid")
|
||||
|
||||
rec_marker1 = np.fromfile(f, dtype=np.int32, count=1)
|
||||
if rec_marker1 == 60:
|
||||
datatype = np.int32
|
||||
else:
|
||||
rec_maker1 = np.fromfile(f, dtype=np.int32, count=1)
|
||||
datatype = np.int64
|
||||
|
||||
|
||||
freq = np.fromfile(f, dtype=np.float32, count=1)
|
||||
zs = np.fromfile(f, dtype=np.float32, count=1)
|
||||
zr = np.fromfile(f, dtype=np.float32, count=1)
|
||||
rmax = np.fromfile(f, dtype=np.float32, count=1)
|
||||
dr = np.fromfile(f, dtype=np.float32, count=1)
|
||||
ndr = np.fromfile(f, dtype=np.int32, count=1)
|
||||
zmax = np.fromfile(f, dtype=np.float32, count=1)
|
||||
dz = np.fromfile(f, dtype=np.float32, count=1)
|
||||
ndz = np.fromfile(f, dtype=np.int32, count=1)
|
||||
zmplt = np.fromfile(f, dtype=np.float32, count=1)
|
||||
c0 = np.fromfile(f, dtype=np.float32, count=1)
|
||||
nPade = np.fromfile(f, dtype=np.int32, count=1)
|
||||
nStarter = np.fromfile(f, dtype=np.int32, count=1)
|
||||
rs = np.fromfile(f, dtype=np.float32, count=1)
|
||||
lz = np.fromfile(f, dtype=np.int32, count=1)
|
||||
|
||||
rec_marker2 = np.fromfile(f, dtype=datatype, count=1)
|
||||
|
||||
rr = np.arange(ndr*dr, rmax+ndr*dr, ndr*dr)
|
||||
rd = ndz * dz * (np.arange(lz) + 1)
|
||||
Nrr = len(rr)
|
||||
Nrd = len(rd)
|
||||
|
||||
tl = np.zeros([Nrr, Nrd],dtype=np.float32)
|
||||
for it in range(Nrr):
|
||||
marker1 = np.fromfile(f, dtype=datatype, count=1)
|
||||
tl[it][:] = np.fromfile(f, dtype=np.float32, count=Nrd)
|
||||
marker2 = np.fromfile(f, dtype=datatype, count=1)
|
||||
|
||||
tl = np.transpose(tl)
|
||||
|
||||
return [rd, rr, tl]
|
||||
|
||||
|
||||
class PosRAM:
|
||||
def __init__(self, zs, zr, rmax, zmax, dr, dz, zmplt):
|
||||
self.zs = zs
|
||||
self.zr = zr
|
||||
self.rmax = rmax
|
||||
self.zmax = zmax
|
||||
self.dr = dr
|
||||
self.dz = dz
|
||||
self.zmplt = zmplt
|
||||
|
||||
|
||||
class SSPRAM:
|
||||
def __init__(self, rp, cw_p, cb_p, rhob_p, attn_p):
|
||||
self.rp = rp
|
||||
self.cw = cw_p
|
||||
self.cb = cb_p
|
||||
self.rhob = rhob_p
|
||||
self.attn = attn_p
|
||||
|
||||
|
||||
class PROF:
|
||||
def __init__(self, depth, value):
|
||||
self.z = depth
|
||||
self.v = value
|
||||
|
||||
|
||||
|
||||
+168
@@ -0,0 +1,168 @@
|
||||
from pyat.env import *
|
||||
import numpy as np
|
||||
|
||||
|
||||
def write_env_RAM(TitleEnv, envfil, freq, pos, bathym, ssp):
|
||||
Rmax = pos.rmax
|
||||
|
||||
f = open(envfil, "wt")
|
||||
|
||||
ndr = 1
|
||||
ndz = 1
|
||||
|
||||
zmplt = pos.zmplt
|
||||
|
||||
c0 = np.mean(ssp[0].cw.v)
|
||||
|
||||
nPade = 3 # The number of Pade terms
|
||||
nStarter = 4 # The number of starter terms
|
||||
rs = 0.0 # The stability constraints range
|
||||
|
||||
f.write("{:s}".format(TitleEnv) + " ! Title\r\n")
|
||||
f.write("{:8.2f} ".format(freq) + \
|
||||
"{:8.2f} ".format(pos.zs) + \
|
||||
"{:8.2f} ".format(pos.zr) + \
|
||||
"\t \t \t ! Frequency (Hz) zs zr\r\n")
|
||||
f.write("{:8.2f} ".format(Rmax) + \
|
||||
"{:8.2f} ".format(pos.dr) + \
|
||||
"{:3d} ".format(ndr) + \
|
||||
"\t \t \t ! rmax dr ndr \r\n")
|
||||
f.write("{:8.2f} ".format(pos.zmax) + \
|
||||
"{:8.2f} ".format(pos.dz) + \
|
||||
"{:3d} ".format(ndz) + \
|
||||
"{:8.2f} ".format(zmplt) + \
|
||||
"\t \t \t ! zmax dz ndz zmplt\r\n")
|
||||
f.write("{:8.2f} ".format(c0) + \
|
||||
"{:1d} ".format(nPade) + \
|
||||
"{:1d} ".format(nStarter) + \
|
||||
"{:8.2f} ".format(rs) + \
|
||||
"\t \t \t ! c0 np ns rs\r\n")
|
||||
|
||||
# Bathymetry
|
||||
for it in range(len(bathym.r)):
|
||||
f.write("{:8.2f} ".format(bathym.r[it]) + "{:8.2f} ".format(bathym.d[it]) + \
|
||||
" \t \t \t ! rb zb\r\n")
|
||||
|
||||
# Sound speed profile
|
||||
f.write("-1 -1\r\n")
|
||||
for it in range(len(ssp)):
|
||||
# rp
|
||||
if it != 0:
|
||||
f.write("{:8.2f} \t \t \t ! rp\r\n".format(ssp[it].rp))
|
||||
# cw
|
||||
for ii in range(len(ssp[it].cw.z)):
|
||||
f.write("{:8.2f} ".format(ssp[it].cw.z[ii]) + "{:8.2f} ".format(ssp[it].cw.v[ii]) + \
|
||||
" \t \t \t ! z cw\r\n")
|
||||
f.write("-1 -1\r\n")
|
||||
|
||||
# cb
|
||||
for ii in range(len(ssp[it].cb.z)):
|
||||
f.write("{:8.2f} ".format(ssp[it].cb.z[ii]) + "{:8.2f} ".format(ssp[it].cb.v[ii]) + \
|
||||
" \t \t \t ! z cb\r\n")
|
||||
f.write("-1 -1\r\n")
|
||||
|
||||
# rhob
|
||||
for ii in range(len(ssp[it].rhob.z)):
|
||||
f.write("{:8.2f} ".format(ssp[it].rhob.z[ii]) + "{:8.2f} ".format(ssp[it].rhob.v[ii]) + \
|
||||
" \t \t \t ! z rhob\r\n")
|
||||
f.write("-1 -1\r\n")
|
||||
|
||||
# attn
|
||||
for ii in range(len(ssp[it].attn.z)):
|
||||
f.write("{:8.2f} ".format(ssp[it].attn.z[ii]) + "{:8.2f} ".format(ssp[it].attn.v[ii]) + \
|
||||
" \t \t \t ! z attn\r\n")
|
||||
f.write("-1 -1\r\n")
|
||||
|
||||
|
||||
def readTL_RAM(filePath=None):
|
||||
if filePath != None:
|
||||
f = open(filePath + "\\tl.grid")
|
||||
else:
|
||||
f = open("tl.grid")
|
||||
|
||||
rec_marker1 = np.fromfile(f, dtype=np.int32, count=1)
|
||||
if rec_marker1 == 60:
|
||||
datatype = np.int32
|
||||
else:
|
||||
rec_maker1 = np.fromfile(f, dtype=np.int32, count=1)
|
||||
datatype = np.int64
|
||||
|
||||
|
||||
freq = np.fromfile(f, dtype=np.float32, count=1)
|
||||
zs = np.fromfile(f, dtype=np.float32, count=1)
|
||||
zr = np.fromfile(f, dtype=np.float32, count=1)
|
||||
rmax = np.fromfile(f, dtype=np.float32, count=1)
|
||||
dr = np.fromfile(f, dtype=np.float32, count=1)
|
||||
ndr = np.fromfile(f, dtype=np.int32, count=1)
|
||||
zmax = np.fromfile(f, dtype=np.float32, count=1)
|
||||
dz = np.fromfile(f, dtype=np.float32, count=1)
|
||||
ndz = np.fromfile(f, dtype=np.int32, count=1)
|
||||
zmplt = np.fromfile(f, dtype=np.float32, count=1)
|
||||
c0 = np.fromfile(f, dtype=np.float32, count=1)
|
||||
nPade = np.fromfile(f, dtype=np.int32, count=1)
|
||||
nStarter = np.fromfile(f, dtype=np.int32, count=1)
|
||||
rs = np.fromfile(f, dtype=np.float32, count=1)
|
||||
lz = np.fromfile(f, dtype=np.int32, count=1)
|
||||
|
||||
rec_marker2 = np.fromfile(f, dtype=datatype, count=1)
|
||||
|
||||
rr = np.arange(ndr*dr, rmax+ndr*dr, ndr*dr)
|
||||
rd = ndz * dz * (np.arange(lz) + 1)
|
||||
Nrr = len(rr)
|
||||
Nrd = len(rd)
|
||||
|
||||
tl = np.zeros([Nrr, Nrd],dtype=np.float32)
|
||||
for it in range(Nrr):
|
||||
marker1 = np.fromfile(f, dtype=datatype, count=1)
|
||||
tl[it][:] = np.fromfile(f, dtype=np.float32, count=Nrd)
|
||||
marker2 = np.fromfile(f, dtype=datatype, count=1)
|
||||
|
||||
tl = np.transpose(tl)
|
||||
|
||||
return [rd, rr, tl]
|
||||
|
||||
def readTLline_RAM(filePath=None):
|
||||
if filePath != None:
|
||||
f = open(filePath + "/tl.line")
|
||||
else:
|
||||
f = open("tl.line")
|
||||
|
||||
lines = f.readlines()
|
||||
f.close()
|
||||
rr = np.zeros(len(lines))
|
||||
tl = np.zeros(len(lines))
|
||||
for i in range(len(lines)):
|
||||
data = lines[i].strip().split(' ')
|
||||
rr[i] = float(data[0])
|
||||
tl[i] = float(data[-1])
|
||||
|
||||
return rr, tl
|
||||
|
||||
|
||||
class PosRAM:
|
||||
def __init__(self, zs, zr, rmax, zmax, dr, dz, zmplt):
|
||||
self.zs = zs
|
||||
self.zr = zr
|
||||
self.rmax = rmax
|
||||
self.zmax = zmax
|
||||
self.dr = dr
|
||||
self.dz = dz
|
||||
self.zmplt = zmplt
|
||||
|
||||
|
||||
class SSPRAM:
|
||||
def __init__(self, rp, cw_p, cb_p, rhob_p, attn_p):
|
||||
self.rp = rp
|
||||
self.cw = cw_p
|
||||
self.cb = cb_p
|
||||
self.rhob = rhob_p
|
||||
self.attn = attn_p
|
||||
|
||||
|
||||
class PROF:
|
||||
def __init__(self, depth, value):
|
||||
self.z = depth
|
||||
self.v = value
|
||||
|
||||
|
||||
|
||||
可执行文件
+1507
文件差异内容过多而无法显示
加载差异
可执行文件
+74
@@ -0,0 +1,74 @@
|
||||
import numpy as np
|
||||
|
||||
"""混响级计算"""
|
||||
def call_RLs_Ss(v,SL,freq,tau,theta,l,r): #海面混响
|
||||
"""
|
||||
v:风速,m/s
|
||||
SL:声源级,dB
|
||||
freq:声纳频率,KHz
|
||||
tau: 发射脉冲宽度,ms
|
||||
theta:海底掠射角,du
|
||||
l: 阵列长度,m
|
||||
r: 斜向距离,m"""
|
||||
freq = freq*1000
|
||||
beta=158*np.power((v*np.power(freq,1.0/3)),-0.58)
|
||||
Ss=3.3*beta*np.log10(theta/30)-42.4*np.log10(beta)+2.6#海面散射强度经验公式,Chapman,Harris.水声学原理,p237
|
||||
C=1500 #声速
|
||||
tau=tau/1000 #单位换算
|
||||
lam=C/freq#波长
|
||||
phi= np.power(10,np.log10(lam/2/l/np.pi)+0.92)#l>lambda水平线阵/边长>>lambda等效波束宽度,水声学原理p225
|
||||
TL=20*np.log10(r) #传播损失经验公式
|
||||
A = C*tau*phi*r/2 #海面散射面积
|
||||
rls = SL-2*TL+Ss+10*np.log10(A)
|
||||
return rls
|
||||
def call_RLs_Sb(SL,freq,tau,theta,l,r): #海底混响
|
||||
"""
|
||||
SL:声源级,dB
|
||||
freq:声纳频率,KHz
|
||||
tau: 发射脉冲宽度,ms
|
||||
theta:海底掠射角,du
|
||||
l: 阵列长度,m
|
||||
r: 斜向距离,m"""
|
||||
Sb=-28+10*np.log10(np.sin(theta)*np.sin(theta))#海底散射强度经验公式,Mackenzie.水声学原理,p243
|
||||
C=1500 #声速
|
||||
tau=tau/1000 #单位换算
|
||||
lam=C/(freq*1000)#波长
|
||||
phi= np.power(10,np.log10(lam/2/l/np.pi)+0.92)#l>lambda水平线阵/边长>>lambda等效波束宽度,水声学原理p225
|
||||
TL=20*np.log10(r) #传播损失经验公式
|
||||
A = C*tau*phi*r/2 #海底散射面积
|
||||
rls = SL-2*TL+Sb+10*np.log10(A)
|
||||
return rls
|
||||
|
||||
def call_RLs_Sv(SL,Sv,freq,tau,l,r): #海面混响
|
||||
"""
|
||||
SL:声源级,dB
|
||||
SV:散射强度,用户输入
|
||||
freq:声纳频率,KHz
|
||||
tau: 发射脉冲宽度,ms
|
||||
theta:海底掠射角,du
|
||||
l: 阵列长度,m
|
||||
r: 斜向距离,m"""
|
||||
freq = freq*1000
|
||||
C=1500 #声速
|
||||
tau=tau/1000 #单位换算
|
||||
lam=C/freq#波长
|
||||
phi= np.power(10,np.log10(lam/2/l/np.pi)+0.92)#l>lambda水平线阵/边长>>lambda等效波束宽度,水声学原理p225
|
||||
TL=20*np.log10(r) #传播损失经验公式
|
||||
A = C*tau*phi*r*r/2 #海面散射面积
|
||||
rls = SL-2*TL+Sv+10*np.log10(A)
|
||||
return rls
|
||||
|
||||
def call_rl(v,SL,Sv,freq,tau,theta,l,r):
|
||||
"""
|
||||
v:风速,m/s
|
||||
SL:声源级,dB
|
||||
SV:散射强度,用户输入
|
||||
freq:声纳频率,KHz
|
||||
tau: 发射脉冲宽度,ms
|
||||
theta:海底掠射角,du
|
||||
l: 阵列长度,m
|
||||
r: 斜向距离,m"""
|
||||
rlss = call_RLs_Ss(v,SL,freq,tau,theta,l,r)
|
||||
rlsb = call_RLs_Sb(SL,freq,tau,theta,l,r)
|
||||
rlsv = call_RLs_Sv(SL,Sv,freq,tau,l,r)
|
||||
return [rlss, rlsb, rlsv]
|
||||
@@ -0,0 +1,7 @@
|
||||
from distutils.core import setup
|
||||
from Cython.Build import cythonize
|
||||
setup(ext_modules = cythonize(["bellhop.py", "config.py", "cscore.py", "czcore.py", "env.py", "krakenc.py",
|
||||
"OANPd.py", "ProfileDataType.py", "ProfileRead.py", "ProfileTool.py", "ram.py", "ramRW_new.py",
|
||||
"ramRW.py", "RANDIcore.py", "readwrite.py", "rlcore.py", "tlcore.py", "WGNPd.py"
|
||||
]))
|
||||
# setup(ext_modules = cythonize(["cscore.py"]))
|
||||
+87
@@ -0,0 +1,87 @@
|
||||
import numpy as np
|
||||
from pyat.AcousticPara import GetEnv, Coord
|
||||
from pyat.DataBase import DataBase
|
||||
from pyat.bellhop import call_Bellhop
|
||||
from pyat.krakenc import call_krakenc
|
||||
from pyat.ram import call_ram
|
||||
import matplotlib.pyplot as plt
|
||||
|
||||
def call_tl(ETOPO1Path, STPath, freq, sourceDepth, sourceLat, sourceLon, receiveDepth,
|
||||
receiveLat=None, receiveLon=None, range=None, azi=None, timeType='Annual', modelType='kraken', isPlot=False):
|
||||
""" Input:
|
||||
freq - float, Frequency
|
||||
sourceDepth - float, Source depth
|
||||
sourceLat - float, Source lat
|
||||
sourceLon - float, Source lon
|
||||
receiveDepth - float, Receive depth
|
||||
receiveLat - float, Receive lat
|
||||
receiveLon - float, Receive lon
|
||||
range - float, Range from source to receive
|
||||
azi - float, azimuth angle from receive to source
|
||||
timeType - char, #全年平均 'Annual', #1-12月'January''February''March''April''May''June''July''August''September'
|
||||
October': '10''November''December', #北半球四季'Winter''Spring''Summer''Autumn'
|
||||
modelType - char, 'bellhop'、'kraken'、'ram'
|
||||
isPlot - plot or not
|
||||
"""
|
||||
""" Output:
|
||||
ranges 距离
|
||||
depths 深度
|
||||
TL 传播损失
|
||||
bathym类 地形数据 bathym.r距离 bathym.d深度
|
||||
"""
|
||||
# 定义时间段
|
||||
timeIndex = timeType
|
||||
# 创建类
|
||||
data = DataBase(ETOPO1Path, STPath)
|
||||
# 设置时间段
|
||||
data.set_timePeriod(timeIndex)
|
||||
|
||||
bathym, ssp, sed, base = [], [], [], []
|
||||
if (receiveLat != None) and (receiveLon != None):
|
||||
[bathym, ssp, sed, base] = GetEnv(data, 25, Coord(sourceLon, sourceLat), coordR=Coord(receiveLon, receiveLat))
|
||||
elif (range != None) and (azi != None):
|
||||
[bathym, ssp, sed, base] = GetEnv(data, 25, Coord(sourceLon, sourceLat), R=range, azi=azi)
|
||||
else:
|
||||
print('no receive info!')
|
||||
return [], [], [], bathym
|
||||
if modelType == 'bellhop':
|
||||
sd = np.array([sourceDepth]) # Source depth
|
||||
rd = np.linspace(0, receiveDepth, int(receiveDepth/10)) # Receiving depth
|
||||
[Pos, TL] = call_Bellhop(freq, sd, rd, bathym, ssp, sed, base)
|
||||
# Plot
|
||||
if isPlot:
|
||||
plt.pcolor(Pos.r.range, Pos.r.depth, TL[0,0,:,:], vmin=40, vmax=130, cmap='jet_r', shading='auto')
|
||||
plt.xlabel("Range/m")
|
||||
plt.ylabel("Depth/m")
|
||||
plt.gca().invert_yaxis()
|
||||
plt.colorbar()
|
||||
plt.show()
|
||||
return Pos.r.range, Pos.r.depth, TL[0,0,:,:], bathym
|
||||
elif modelType == 'kraken':
|
||||
sd = np.array([sourceDepth]) # Source depth
|
||||
rd = np.linspace(0, receiveDepth, int(receiveDepth/10)) # Receiving depth
|
||||
[Pos, TL] = call_krakenc(freq, sd, rd, bathym, ssp, sed, base)
|
||||
# Plot
|
||||
if isPlot:
|
||||
plt.pcolor(Pos.r.range, Pos.r.depth, TL[0,0,:,:], vmin=40, vmax=130, cmap='jet_r', shading='auto')
|
||||
plt.xlabel("Range/m")
|
||||
plt.ylabel("Depth/m")
|
||||
plt.gca().invert_yaxis()
|
||||
plt.colorbar()
|
||||
plt.show()
|
||||
return Pos.r.range, Pos.r.depth, TL[0,0,:,:], bathym
|
||||
elif modelType == 'ram':
|
||||
# 调用ram模块
|
||||
[rd, rr, TL] = call_ram(freq, sourceDepth, receiveDepth, bathym, ssp, sed)
|
||||
# Plot
|
||||
if isPlot:
|
||||
plt.pcolormesh(rr, rd, TL, vmin=60, vmax=130, cmap='jet_r', shading='auto')
|
||||
plt.xlabel("Range/m")
|
||||
plt.ylabel("Depth/m")
|
||||
plt.gca().invert_yaxis()
|
||||
plt.colorbar()
|
||||
plt.show()
|
||||
return rr, rd, TL, bathym
|
||||
else:
|
||||
return [], [], [], bathym
|
||||
|
||||
在新工单中引用
屏蔽一个用户