First commit after changed file framework

这个提交包含在:
2023-03-14 18:52:04 +08:00
父节点 e23318c8f1
当前提交 79a6a31dc7
共修改 34 个文件,包含 5751 行新增和 0 行删除
+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]
+53
查看文件
@@ -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()
+3
查看文件
@@ -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]
+7
查看文件
@@ -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