First commit after changed file framework
这个提交包含在:
+5
@@ -160,3 +160,8 @@ cython_debug/
|
|||||||
# option (not recommended) you can uncomment the following to ignore the entire idea folder.
|
# option (not recommended) you can uncomment the following to ignore the entire idea folder.
|
||||||
#.idea/
|
#.idea/
|
||||||
|
|
||||||
|
.vscode/
|
||||||
|
packages/
|
||||||
|
pyat/at/
|
||||||
|
pyqt/
|
||||||
|
test/
|
||||||
@@ -0,0 +1,51 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
import warnings
|
||||||
|
warnings.filterwarnings('ignore')
|
||||||
|
import argparse, json
|
||||||
|
from common import NoIndent, MyEncoder
|
||||||
|
|
||||||
|
def _argparse():
|
||||||
|
parser = argparse.ArgumentParser(description='tl client')
|
||||||
|
parser.add_argument('-a', '--argfile', action='store', dest='argfile', required=True, help='name of arguments file')
|
||||||
|
return parser.parse_args()
|
||||||
|
|
||||||
|
def main():
|
||||||
|
parser = _argparse()
|
||||||
|
argfile = parser.argfile
|
||||||
|
if argfile[-5:] != '.json':
|
||||||
|
print('输入的参数文件名有误')
|
||||||
|
return
|
||||||
|
with open(argfile,'r') as jsonFile:
|
||||||
|
paramData = json.load(jsonFile)
|
||||||
|
if ("ETOPO1Path" not in paramData) or ("STPath" not in paramData) or\
|
||||||
|
("freq" not in paramData) or ("receiveDepth" not in paramData) or\
|
||||||
|
("lat" not in paramData) or ("lon" not in paramData) or\
|
||||||
|
("timeType" not in paramData) or\
|
||||||
|
("NThreads" not in paramData) or ("outParam" not in paramData):
|
||||||
|
print(f'{argfile}中的参数有误,请核实!')
|
||||||
|
return
|
||||||
|
ETOPO1Path = paramData["ETOPO1Path"]
|
||||||
|
STPath = paramData["STPath"]
|
||||||
|
freq = float(paramData["freq"])
|
||||||
|
receiveDepth = float(paramData["receiveDepth"])
|
||||||
|
lat = float(paramData["lat"])
|
||||||
|
lon = float(paramData["lon"])
|
||||||
|
timeType = paramData["timeType"]
|
||||||
|
NThreads = int(paramData["NThreads"])
|
||||||
|
outParam = paramData["outParam"]
|
||||||
|
|
||||||
|
from pyat.RANDIcore import call_RANDI
|
||||||
|
NL = call_RANDI(ETOPO1Path, STPath, outParam["outPath"], freq, receiveDepth,
|
||||||
|
lon, lat, timeType, NThreads)
|
||||||
|
print(round(NL,2))
|
||||||
|
outData = {
|
||||||
|
"param": paramData,
|
||||||
|
"noiseLevel": round(NL,2)
|
||||||
|
}
|
||||||
|
with open(("" if outParam["outPath"]=="" else outParam["outPath"] + "/")+"RANDIOut.json", 'w') as jsonFile:
|
||||||
|
json_data = json.dumps(outData, cls=MyEncoder, indent=2, ensure_ascii=False)
|
||||||
|
jsonFile.write(json_data)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
main()
|
||||||
@@ -0,0 +1,32 @@
|
|||||||
|
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
from _ctypes import PyObj_FromPtr
|
||||||
|
import json, re
|
||||||
|
|
||||||
|
class NoIndent(object):
|
||||||
|
""" Value wrapper. """
|
||||||
|
def __init__(self, value):
|
||||||
|
self.value = value
|
||||||
|
|
||||||
|
class MyEncoder(json.JSONEncoder):
|
||||||
|
FORMAT_SPEC = '@@{}@@'
|
||||||
|
regex = re.compile(FORMAT_SPEC.format(r'(\d+)'))
|
||||||
|
|
||||||
|
def __init__(self, **kwargs):
|
||||||
|
super(MyEncoder, self).__init__(**kwargs)
|
||||||
|
|
||||||
|
def default(self, obj):
|
||||||
|
return (self.FORMAT_SPEC.format(id(obj)) if isinstance(obj, NoIndent)
|
||||||
|
else super(MyEncoder, self).default(obj))
|
||||||
|
|
||||||
|
def encode(self, obj):
|
||||||
|
format_spec = self.FORMAT_SPEC # Local var to expedite access.
|
||||||
|
json_repr = super(MyEncoder, self).encode(obj) # Default JSON.
|
||||||
|
for match in self.regex.finditer(json_repr):
|
||||||
|
id = int(match.group(1))
|
||||||
|
no_indent = PyObj_FromPtr(id)
|
||||||
|
json_obj_repr = json.dumps(no_indent.value)
|
||||||
|
json_repr = json_repr.replace(
|
||||||
|
'"{}"'.format(format_spec.format(id)), json_obj_repr)
|
||||||
|
|
||||||
|
return json_repr
|
||||||
@@ -0,0 +1,88 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
import warnings
|
||||||
|
warnings.filterwarnings('ignore')
|
||||||
|
import argparse, json
|
||||||
|
from common import NoIndent, MyEncoder
|
||||||
|
|
||||||
|
def _argparse():
|
||||||
|
parser = argparse.ArgumentParser(description='cs client')
|
||||||
|
parser.add_argument('-a', '--argfile', action='store', dest='argfile', required=True, help='name of arguments file')
|
||||||
|
return parser.parse_args()
|
||||||
|
|
||||||
|
def main():
|
||||||
|
parser = _argparse()
|
||||||
|
argfile = parser.argfile
|
||||||
|
if argfile[-5:] != '.json':
|
||||||
|
print('输入的参数文件名有误')
|
||||||
|
return
|
||||||
|
with open(argfile,'r') as jsonFile:
|
||||||
|
paramData = json.load(jsonFile)
|
||||||
|
if ("m" not in paramData) or ("d" not in paramData) or\
|
||||||
|
("f" not in paramData) or ("c" not in paramData) or\
|
||||||
|
("outParam" not in paramData):
|
||||||
|
print(f'{argfile}中的参数有误,请核实!')
|
||||||
|
return
|
||||||
|
m = int(paramData["m"])
|
||||||
|
d = float(paramData["d"])
|
||||||
|
f = float(paramData["f"])
|
||||||
|
c = float(paramData["c"])
|
||||||
|
outParam = paramData["outParam"]
|
||||||
|
|
||||||
|
from pyat.cscore import np, dis_mats, pn_funcs, ag_funcs
|
||||||
|
import sys
|
||||||
|
print(sys.path)
|
||||||
|
|
||||||
|
|
||||||
|
# 输出:
|
||||||
|
# 所有阵元的间距的集合
|
||||||
|
dis_m = dis_mats(m, d)
|
||||||
|
print('所有阵元的间距的集合:', dis_m)
|
||||||
|
|
||||||
|
# 相邻阵元的噪声相关性
|
||||||
|
pn_res = pn_funcs(f, c, dis_m)
|
||||||
|
print('相邻阵元的噪声相关性:pn=', pn_res[0, 1])
|
||||||
|
|
||||||
|
# 阵增益
|
||||||
|
ag_res = ag_funcs(m, pn_res)
|
||||||
|
print('阵增益:ag=', ag_res)
|
||||||
|
outData = {
|
||||||
|
"param": paramData,
|
||||||
|
"dis": np.round(dis_m,2).tolist(),
|
||||||
|
"pn": np.round(pn_res,2).tolist(),
|
||||||
|
"ag": np.round(ag_res,2).tolist()
|
||||||
|
}
|
||||||
|
with open(("" if outParam["outPath"]=="" else outParam["outPath"] + "/")+"csOut.json", 'w') as jsonFile:
|
||||||
|
json_data = json.dumps(outData, cls=MyEncoder, indent=2, ensure_ascii=False)
|
||||||
|
jsonFile.write(json_data)
|
||||||
|
# # write data to file
|
||||||
|
# # 保存地形数据
|
||||||
|
# bathym.r = np.around(bathym.r, decimals=0)
|
||||||
|
# bathym.d = np.around(bathym.d, decimals=0)
|
||||||
|
# bathymData = {
|
||||||
|
# "param": paramData,
|
||||||
|
# "count": len(bathym.d),
|
||||||
|
# "descript": "距离、深度",
|
||||||
|
# "data": NoIndent(list(zip(bathym.r, bathym.d)))
|
||||||
|
# }
|
||||||
|
# with open(("" if outParam["outPath"]=="" else outParam["outPath"] + "/")+"tlOut_bathym.json", 'w') as jsonFile:
|
||||||
|
# json_data = json.dumps(bathymData, cls=MyEncoder, indent=2, ensure_ascii=False)
|
||||||
|
# jsonFile.write(json_data)
|
||||||
|
|
||||||
|
# # 保存传播损失数据
|
||||||
|
# tlpoint = []
|
||||||
|
# depths = np.around(depths, decimals=0)
|
||||||
|
# ranges = np.around(ranges, decimals=0)
|
||||||
|
# TL = np.around(TL, decimals=2)
|
||||||
|
# tlpoint = list(zip(np.tile(depths.reshape(len(depths),1),len(ranges)).flatten(), np.tile(ranges,(len(depths),1)).flatten(), TL.flatten()))
|
||||||
|
# tlData = {
|
||||||
|
# "param": paramData,
|
||||||
|
# "count": len(ranges)*len(depths),
|
||||||
|
# "descript": "距离、深度、损失",
|
||||||
|
# "data": NoIndent(tlpoint)
|
||||||
|
# }
|
||||||
|
# with open(("" if outParam["outPath"]=="" else outParam["outPath"] + "/")+"tlOut_tl.json", 'w') as jsonFile:
|
||||||
|
# json_data = json.dumps(tlData, cls=MyEncoder, indent=2, ensure_ascii=False)
|
||||||
|
# jsonFile.write(json_data)
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
main()
|
||||||
@@ -0,0 +1,154 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
import warnings
|
||||||
|
warnings.filterwarnings('ignore')
|
||||||
|
import argparse, json
|
||||||
|
from common import NoIndent, MyEncoder
|
||||||
|
|
||||||
|
def _argparse():
|
||||||
|
parser = argparse.ArgumentParser(description='Average Noise Spectral Level')
|
||||||
|
parser.add_argument('-a', '--argfile', action='store', dest='argfile', required=True, help='name of arguments file')
|
||||||
|
return parser.parse_args()
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
parser = _argparse()
|
||||||
|
argfile = parser.argfile
|
||||||
|
if argfile[-5:] != '.json':
|
||||||
|
print('输入的参数文件名有误')
|
||||||
|
return
|
||||||
|
with open(argfile,'r') as jsonFile:
|
||||||
|
paramData = json.load(jsonFile)
|
||||||
|
if ("ETOPO1Path" not in paramData) or ("STPath" not in paramData) or \
|
||||||
|
("freq" not in paramData) or ("sourceDepth" not in paramData) or ("receiveDepth" not in paramData) or\
|
||||||
|
("lat" not in paramData) or ("lon" not in paramData) or\
|
||||||
|
("timeType" not in paramData) or\
|
||||||
|
("outParam" not in paramData):
|
||||||
|
print(f'{argfile}中的参数有误,请核实!')
|
||||||
|
return
|
||||||
|
ETOPO1Path = paramData["ETOPO1Path"]
|
||||||
|
STPath = paramData["STPath"]
|
||||||
|
freq = float(paramData["freq"])
|
||||||
|
sourceDepth = float(paramData["sourceDepth"])
|
||||||
|
receiveDepth = float(paramData["receiveDepth"])
|
||||||
|
lat = float(paramData["lat"])
|
||||||
|
lon = float(paramData["lon"])
|
||||||
|
try:
|
||||||
|
azi = float(paramData["azi"])
|
||||||
|
except:
|
||||||
|
azi = None
|
||||||
|
timeType = paramData["timeType"]
|
||||||
|
outParam = paramData["outParam"]
|
||||||
|
if "outPath" not in outParam:
|
||||||
|
outParam["outPath"] = ""
|
||||||
|
|
||||||
|
from pyat.czcore import call_cz
|
||||||
|
import numpy as np
|
||||||
|
|
||||||
|
# call_cz函数返回汇聚区计算的中间值CzData的列表
|
||||||
|
# CzData保存了方位角、距离、深度、损失、地形、会聚区等数据
|
||||||
|
# 其中czdata.azi是方位角、czdata.ranges是距离列表、czdata.depths是深度列表、
|
||||||
|
# czdata.TL是损失、czdata.bathym是地形数据
|
||||||
|
# czdata.Rays是声线数据
|
||||||
|
# czdata.CzDetail是会聚区数据,包括会聚区宽度和距离
|
||||||
|
res = call_cz(ETOPO1Path, STPath, freq, lat, lon, azi, sourceDepth, receiveDepth, timeType=timeType)
|
||||||
|
# call_cz(25, 18.0, 114.0, 10, 3500)
|
||||||
|
|
||||||
|
# write data to file
|
||||||
|
#输出json文件
|
||||||
|
outData = {}
|
||||||
|
outData["param"] = paramData
|
||||||
|
if len(res) == 0:
|
||||||
|
outData["result"] = "无会聚区"
|
||||||
|
outData["data"] = []
|
||||||
|
else:
|
||||||
|
outData["result"] = "有会聚区"
|
||||||
|
outDataData, outBathymData,outTlData,outRayData = [],[],[],[]
|
||||||
|
json.encoder.FLOAT_REPR = lambda x: format(x, '.3f')
|
||||||
|
for index in range(len(res)):
|
||||||
|
bathymData,tlData,rayData = {},{},{}
|
||||||
|
# 保存地形数据
|
||||||
|
res[index].bathym.r = np.around(res[index].bathym.r, decimals=0)
|
||||||
|
res[index].bathym.d = np.around(res[index].bathym.d, decimals=0)
|
||||||
|
bathymData = {
|
||||||
|
"param": paramData,
|
||||||
|
"azi": f'{round(res[index].azi)}',
|
||||||
|
"count": len(res[index].bathym.d),
|
||||||
|
"descript": "距离、深度",
|
||||||
|
"data": NoIndent(list(zip(res[index].bathym.r,res[index].bathym.d)))
|
||||||
|
}
|
||||||
|
# 保存传播损失数据
|
||||||
|
tlpoint = []
|
||||||
|
res[index].depths = np.around(res[index].depths, decimals=0)
|
||||||
|
res[index].ranges = np.around(res[index].ranges, decimals=0)
|
||||||
|
res[index].TL = np.around(res[index].TL, decimals=2)
|
||||||
|
tlpoint = list(zip(np.tile(res[index].depths.reshape(len(res[index].depths),1),len(res[index].ranges)).flatten(), np.tile(res[index].ranges,(len(res[index].depths),1)).flatten(), res[index].TL.flatten()))
|
||||||
|
tlData = {
|
||||||
|
"param": paramData,
|
||||||
|
"azi": f'{round(res[index].azi)}',
|
||||||
|
"count": len(res[index].ranges)*len(res[index].depths),
|
||||||
|
"descript": "距离、深度、损失",
|
||||||
|
"data": NoIndent(tlpoint)
|
||||||
|
}
|
||||||
|
# 保存声线数据
|
||||||
|
raypoint = []
|
||||||
|
for ray in res[index].Rays:
|
||||||
|
ray.xy[0] = np.around(ray.xy[0], decimals=2)
|
||||||
|
ray.xy[1] = np.around(ray.xy[1], decimals=2)
|
||||||
|
tempdata = {
|
||||||
|
"pointCount": len(ray.xy[0]),
|
||||||
|
"data": NoIndent(list(zip(ray.xy[0],ray.xy[1])))
|
||||||
|
}
|
||||||
|
raypoint.append(tempdata)
|
||||||
|
rayData = {
|
||||||
|
"param": paramData,
|
||||||
|
"azi": f'{round(res[index].azi)}',
|
||||||
|
"count": len(res[index].Rays),
|
||||||
|
"rayData": raypoint
|
||||||
|
}
|
||||||
|
# print(len(res[index].Rays))
|
||||||
|
czDeatilData = {}
|
||||||
|
czDeatilData["descript"] = res[index].CzDetail.descript
|
||||||
|
if len(res[index].CzDetail.directCz) == 0:
|
||||||
|
czDeatilData["directCz"] = []
|
||||||
|
else:
|
||||||
|
directczdetaillist = []
|
||||||
|
for directcz in res[index].CzDetail.directCz:
|
||||||
|
directczdetail = {
|
||||||
|
"minRange": f'{round(directcz.minRange,1)}',
|
||||||
|
"maxRange": f'{round(directcz.maxRange,1)}',
|
||||||
|
"width": f'{round(directcz.width,1)}',
|
||||||
|
}
|
||||||
|
directczdetaillist.append(directczdetail)
|
||||||
|
czDeatilData["directCz"] = directczdetaillist
|
||||||
|
if len(res[index].CzDetail.reflectCz) == 0:
|
||||||
|
czDeatilData["reflectCz"] = []
|
||||||
|
else:
|
||||||
|
reflectczdetaillist = []
|
||||||
|
for reflectcz in res[index].CzDetail.reflectCz:
|
||||||
|
reflectczdetail = {
|
||||||
|
"minRange": f'{round(reflectcz.minRange,1)}',
|
||||||
|
"maxRange": f'{round(reflectcz.maxRange,1)}',
|
||||||
|
"width": f'{round(reflectcz.width,1)}',
|
||||||
|
}
|
||||||
|
reflectczdetaillist.append(reflectczdetail)
|
||||||
|
czDeatilData["reflectCz"] = reflectczdetaillist
|
||||||
|
outDataData.append(czDeatilData)
|
||||||
|
outBathymData.append(bathymData)
|
||||||
|
outTlData.append(tlData)
|
||||||
|
outRayData.append(rayData)
|
||||||
|
with open(("" if outParam["outPath"]=="" else outParam["outPath"] + "/")+"czOut_bathym.json", 'w') as jsonFile:
|
||||||
|
json_data = json.dumps(outBathymData, cls=MyEncoder, indent=2, ensure_ascii=False)
|
||||||
|
jsonFile.write(json_data)
|
||||||
|
with open(("" if outParam["outPath"]=="" else outParam["outPath"] + "/")+"czOut_tl.json", 'w') as jsonFile:
|
||||||
|
json_data = json.dumps(outTlData, cls=MyEncoder, indent=2, ensure_ascii=False)
|
||||||
|
jsonFile.write(json_data)
|
||||||
|
with open(("" if outParam["outPath"]=="" else outParam["outPath"] + "/")+"czOut_ray.json", 'w') as jsonFile:
|
||||||
|
json_data = json.dumps(outRayData, cls=MyEncoder, indent=2, ensure_ascii=False)
|
||||||
|
jsonFile.write(json_data)
|
||||||
|
outData["data"] = outDataData
|
||||||
|
|
||||||
|
with open(("" if outParam["outPath"]=="" else outParam["outPath"] + "/")+"czOut.json", 'w') as jsonFile:
|
||||||
|
json.dump(outData, jsonFile, indent=4, ensure_ascii=False)
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
main()
|
||||||
@@ -0,0 +1,59 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
import warnings
|
||||||
|
warnings.filterwarnings('ignore')
|
||||||
|
import argparse, json
|
||||||
|
from common import NoIndent, MyEncoder
|
||||||
|
|
||||||
|
def _argparse():
|
||||||
|
parser = argparse.ArgumentParser(description='Average Noise Spectral Level')
|
||||||
|
parser.add_argument('-a', '--argfile', action='store', dest='argfile', required=True, help='name of arguments file')
|
||||||
|
return parser.parse_args()
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
parser = _argparse()
|
||||||
|
argfile = parser.argfile
|
||||||
|
if argfile[-5:] != '.json':
|
||||||
|
print('输入的参数文件名有误')
|
||||||
|
return
|
||||||
|
with open(argfile,'r') as jsonFile:
|
||||||
|
paramData = json.load(jsonFile)
|
||||||
|
if ("soundFile" not in paramData) or ("sense" not in paramData) or\
|
||||||
|
("filter" not in paramData) or ("png" not in paramData) or\
|
||||||
|
("outParam" not in paramData):
|
||||||
|
print(f'{argfile}中的参数有误,请核实!')
|
||||||
|
return
|
||||||
|
soundFile = paramData["soundFile"]
|
||||||
|
M = float(paramData["sense"])
|
||||||
|
A = float(paramData["filter"])
|
||||||
|
png = paramData["png"]
|
||||||
|
outParam = paramData["outParam"]
|
||||||
|
|
||||||
|
from pyat.OANPd import call_oanp
|
||||||
|
from matplotlib import pyplot as plt
|
||||||
|
import numpy as np
|
||||||
|
|
||||||
|
[freq, spl, fC, spl_oct] = call_oanp(soundFile=soundFile, M=M , A=A)
|
||||||
|
# call_oanp(soundFile="./SAW2577_20200923_150000.wav", W=-164.0 , A=0, isPlot=isPlot)
|
||||||
|
|
||||||
|
#输出json文件
|
||||||
|
outData = {}
|
||||||
|
outData["param"] = paramData
|
||||||
|
outData["descript"] = "frequency and noise level"
|
||||||
|
outData["count"] = len(fC)
|
||||||
|
fC = np.around(fC, decimals=0)
|
||||||
|
spl_oct = np.around(spl_oct, decimals=2)
|
||||||
|
outData["data"] = NoIndent(list(zip(fC,spl_oct)))
|
||||||
|
with open(("" if outParam["outPath"]=="" else outParam["outPath"] + "/")+"oanpOut.json", 'w') as jsonFile:
|
||||||
|
json_data = json.dumps(outData, cls=MyEncoder, indent=2, ensure_ascii=False)
|
||||||
|
jsonFile.write(json_data)
|
||||||
|
|
||||||
|
if png:
|
||||||
|
plt.semilogx(freq[20:10000], spl[20:10000])
|
||||||
|
plt.semilogx(fC, spl_oct)
|
||||||
|
plt.xlabel("Frequency / Hz")
|
||||||
|
plt.ylabel("Noise Level / dB")
|
||||||
|
plt.show()
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
main()
|
||||||
可执行文件
+220
@@ -0,0 +1,220 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
import warnings
|
||||||
|
warnings.filterwarnings('ignore')
|
||||||
|
|
||||||
|
import argparse, json
|
||||||
|
|
||||||
|
def _argparse():
|
||||||
|
parser = argparse.ArgumentParser(description='剖面分析工具, 根据标准化剖面,得到声道, 跃层分析结果')
|
||||||
|
parser.add_argument('-a', '--argfile', action='store', dest='argfile', required=True, help='name of arguments file')
|
||||||
|
return parser.parse_args()
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
parser = _argparse()
|
||||||
|
argfile = parser.argfile
|
||||||
|
if argfile[-5:] != '.json':
|
||||||
|
print('输入的参数文件名有误')
|
||||||
|
return
|
||||||
|
with open(argfile,'r') as jsonFile:
|
||||||
|
paramData = json.load(jsonFile)
|
||||||
|
if ("realtime" not in paramData):
|
||||||
|
print(f'{argfile}中的参数有误,请核实!')
|
||||||
|
return
|
||||||
|
realtime = paramData["realtime"]
|
||||||
|
if not realtime:
|
||||||
|
if ("ETOPO1Path" not in paramData) or ("STPath" not in paramData) or\
|
||||||
|
("lat" not in paramData) or ("lon" not in paramData) or\
|
||||||
|
("timeType" not in paramData) or ("png" not in paramData) or\
|
||||||
|
("outParam" not in paramData):
|
||||||
|
print(f'{argfile}中的参数有误,请核实!')
|
||||||
|
return
|
||||||
|
ETOPO1Path = paramData["ETOPO1Path"]
|
||||||
|
STPath = paramData["STPath"]
|
||||||
|
lat = float(paramData["lat"])
|
||||||
|
lon = float(paramData["lon"])
|
||||||
|
timeType = paramData["timeType"]
|
||||||
|
png = paramData["png"]
|
||||||
|
outParam = paramData["outParam"]
|
||||||
|
if "outPath" not in outParam:
|
||||||
|
outParam["outPath"] = ""
|
||||||
|
|
||||||
|
from pyat.DataBase import DataBase
|
||||||
|
import matplotlib.pyplot as plt
|
||||||
|
from pyat.ProfileTool import ProfileTool
|
||||||
|
import numpy as np
|
||||||
|
# 定义时间段
|
||||||
|
timeIndex = timeType
|
||||||
|
# 创建类
|
||||||
|
data = DataBase(ETOPO1Path, STPath)
|
||||||
|
# 设置时间段
|
||||||
|
data.set_timePeriod(timeIndex)
|
||||||
|
# 设置坐标
|
||||||
|
data.set_coord(lat, lon)
|
||||||
|
# 全海深速度剖面
|
||||||
|
velPf = data.get_velFullProfile()
|
||||||
|
# 设置剖面分析工具
|
||||||
|
velPfTool = ProfileTool()
|
||||||
|
velPfTool.set_profile(velPf)
|
||||||
|
# 计算表面声道
|
||||||
|
surfCh = velPfTool.get_surfaceChannel()
|
||||||
|
# 计算深海声道
|
||||||
|
deepCh = velPfTool.get_deepChannel()
|
||||||
|
# 计算跃层信息
|
||||||
|
surfSL, mainSL = velPfTool.get_springLayer()
|
||||||
|
# 导出结果文件
|
||||||
|
velPfTool.export_profileParm('velPfParam.txt')
|
||||||
|
# 导出剖面文件
|
||||||
|
# data.export_velFullProfile_txt('velFullProfile.txt')
|
||||||
|
data.export_velFullProfile_nc('velFullProfile.nc')
|
||||||
|
# 打印结果
|
||||||
|
f = open('velPfParam.txt')
|
||||||
|
lines=f.readlines()
|
||||||
|
for line in lines:
|
||||||
|
print(line)
|
||||||
|
f.close()
|
||||||
|
|
||||||
|
#输出json文件
|
||||||
|
outData = {}
|
||||||
|
outData["param"] = paramData
|
||||||
|
outData["lat"] = f'{round(velPf.lat,4)}'
|
||||||
|
outData["lon"] = f'{round(velPf.lon,4)}'
|
||||||
|
outData["botDep"] = f'{round(velPf.botDep)}'
|
||||||
|
properties = {
|
||||||
|
"表面声道轴深度": f'{round(surfCh.depAxis,2)}' if surfCh.exist else "NONE",
|
||||||
|
"表面声道声速": f'{round(surfCh.velAxis,4)}' if surfCh.exist else "NONE",
|
||||||
|
"深海声道轴深度": f'{round(deepCh.depAxis,2)}' if deepCh.exist else "NONE",
|
||||||
|
"深海声道声速": f'{round(deepCh.velAxis,4)}' if deepCh.exist else "NONE",
|
||||||
|
"表面跃层区间": f'{round(surfSL.limit[0],2)}, {round(surfSL.limit[1],2)}' if surfSL.exist else "NONE",
|
||||||
|
"表面跃层强度": f'{round(surfSL.intensity,4)}' if surfSL.exist else "NONE",
|
||||||
|
"主跃层区间": f'{round(mainSL.limit[0],2)}, {round(mainSL.limit[1],2)}' if mainSL.exist else "NONE",
|
||||||
|
"主跃层强度": f'{round(mainSL.intensity,4)}' if mainSL.exist else "NONE",
|
||||||
|
}
|
||||||
|
velPf.x = np.around(velPf.x, decimals=0)
|
||||||
|
velPf.y = np.around(velPf.y, decimals=4)
|
||||||
|
outData["out"] = {
|
||||||
|
"properties": properties,
|
||||||
|
"声剖面列表": list(zip(velPf.x,velPf.y))
|
||||||
|
}
|
||||||
|
with open(("" if outParam["outPath"]=="" else outParam["outPath"] + "/")+"profileOut.json", 'w') as jsonFile:
|
||||||
|
json.dump(outData, jsonFile, indent=4, ensure_ascii=False)
|
||||||
|
|
||||||
|
if png:
|
||||||
|
# 绘图
|
||||||
|
fig, ax = plt.subplots()
|
||||||
|
# 声速剖面
|
||||||
|
ax.plot(velPf.y, velPf.x)
|
||||||
|
if surfCh.exist:
|
||||||
|
ax.axhline(surfCh.depAxis, linestyle='--',
|
||||||
|
color='r', label='surface channel axis')
|
||||||
|
if deepCh.exist:
|
||||||
|
ax.axhline(deepCh.depAxis, linestyle='--',
|
||||||
|
color='g', label='deep channel axis')
|
||||||
|
if surfSL.exist:
|
||||||
|
ax.fill_between([1480, 1550], surfSL.limit[0],
|
||||||
|
surfSL.limit[1], alpha=0.2, color='r')
|
||||||
|
if mainSL.exist:
|
||||||
|
ax.fill_between([1480, 1550], mainSL.limit[0],
|
||||||
|
mainSL.limit[1], alpha=0.2, color='g')
|
||||||
|
ax.set_xlim(1480, 1550)
|
||||||
|
ax.invert_yaxis()
|
||||||
|
ax.set_xlabel('velocity')
|
||||||
|
ax.set_ylabel('depth')
|
||||||
|
ax.legend(loc=4)
|
||||||
|
# 显示绘图
|
||||||
|
plt.show()
|
||||||
|
else:
|
||||||
|
if ("ETOPO1Path" not in paramData) or ("STPath" not in paramData) or\
|
||||||
|
("profileFile" not in paramData) or ("png" not in paramData) or\
|
||||||
|
("outParam" not in paramData):
|
||||||
|
print(f'{argfile}中的参数有误,请核实!')
|
||||||
|
return
|
||||||
|
ETOPO1Path = paramData["ETOPO1Path"]
|
||||||
|
STPath = paramData["STPath"]
|
||||||
|
profileFile = paramData["profileFile"]
|
||||||
|
png = paramData["png"]
|
||||||
|
outParam = paramData["outParam"]
|
||||||
|
if "outPath" not in outParam:
|
||||||
|
outParam["outPath"] = ""
|
||||||
|
|
||||||
|
import matplotlib.pyplot as plt
|
||||||
|
from pyat.ProfileTool import ProfileTool
|
||||||
|
from pyat.ProfileRead import readRawProfile, processProfile
|
||||||
|
import numpy as np
|
||||||
|
# 读取实测声速剖面
|
||||||
|
velRawPf = readRawProfile(profileFile)
|
||||||
|
# 对剖面进行后处理
|
||||||
|
velPf = processProfile(velRawPf, ETOPO1Path, STPath)
|
||||||
|
|
||||||
|
# 设置剖面分析工具
|
||||||
|
velPfTool = ProfileTool()
|
||||||
|
velPfTool.set_profile(velPf)
|
||||||
|
# 计算表面声道
|
||||||
|
surfCh = velPfTool.get_surfaceChannel()
|
||||||
|
# 计算深海声道
|
||||||
|
deepCh = velPfTool.get_deepChannel()
|
||||||
|
# 计算跃层信息
|
||||||
|
surfSL, mainSL = velPfTool.get_springLayer()
|
||||||
|
# 导出结果文件
|
||||||
|
velPfTool.export_profileParm('velPfParam.txt')
|
||||||
|
# 打印结果
|
||||||
|
f = open('velPfParam.txt')
|
||||||
|
lines=f.readlines()
|
||||||
|
for line in lines:
|
||||||
|
print(line)
|
||||||
|
f.close()
|
||||||
|
|
||||||
|
#输出json文件
|
||||||
|
outData = {}
|
||||||
|
outData["param"] = paramData
|
||||||
|
outData["lat"] = f'{round(velPf.lat,4)}'
|
||||||
|
outData["lon"] = f'{round(velPf.lon,4)}'
|
||||||
|
outData["botDep"] = f'{round(velPf.botDep)}'
|
||||||
|
properties = {
|
||||||
|
"表面声道轴深度": f'{round(surfCh.depAxis,2)}' if surfCh.exist else "NONE",
|
||||||
|
"表面声道声速": f'{round(surfCh.velAxis,4)}' if surfCh.exist else "NONE",
|
||||||
|
"深海声道轴深度": f'{round(deepCh.depAxis,2)}' if deepCh.exist else "NONE",
|
||||||
|
"深海声道声速": f'{round(deepCh.velAxis,4)}' if deepCh.exist else "NONE",
|
||||||
|
"表面跃层区间": f'{round(surfSL.limit[0],2)}, {round(surfSL.limit[1],2)}' if surfSL.exist else "NONE",
|
||||||
|
"表面跃层强度": f'{round(surfSL.intensity,4)}' if surfSL.exist else "NONE",
|
||||||
|
"主跃层区间": f'{round(mainSL.limit[0],2)}, {round(mainSL.limit[1],2)}' if mainSL.exist else "NONE",
|
||||||
|
"主跃层强度": f'{round(mainSL.intensity,4)}' if mainSL.exist else "NONE",
|
||||||
|
}
|
||||||
|
velPf.x = np.around(velPf.x, decimals=0)
|
||||||
|
velPf.y = np.around(velPf.y, decimals=4)
|
||||||
|
profileList = list(zip(velPf.x,velPf.y))
|
||||||
|
outData["out"] = {
|
||||||
|
"properties": properties,
|
||||||
|
"声剖面列表": profileList
|
||||||
|
}
|
||||||
|
with open(("" if outParam["outPath"]=="" else outParam["outPath"] + "/")+"profileOut.json", 'w') as jsonFile:
|
||||||
|
json.dump(outData, jsonFile, indent=4, ensure_ascii=False)
|
||||||
|
|
||||||
|
if png:
|
||||||
|
# 绘图
|
||||||
|
fig, ax = plt.subplots()
|
||||||
|
# 声速剖面
|
||||||
|
ax.plot(velPf.y, velPf.x)
|
||||||
|
if surfCh.exist:
|
||||||
|
ax.axhline(surfCh.depAxis, linestyle='--',
|
||||||
|
color='r', label='surface channel axis')
|
||||||
|
if deepCh.exist:
|
||||||
|
ax.axhline(deepCh.depAxis, linestyle='--',
|
||||||
|
color='g', label='deep channel axis')
|
||||||
|
if surfSL.exist:
|
||||||
|
ax.fill_between([1480, 1550], surfSL.limit[0],
|
||||||
|
surfSL.limit[1], alpha=0.2, color='r')
|
||||||
|
if mainSL.exist:
|
||||||
|
ax.fill_between([1480, 1550], mainSL.limit[0],
|
||||||
|
mainSL.limit[1], alpha=0.2, color='g')
|
||||||
|
ax.set_xlim(1480, 1550)
|
||||||
|
ax.invert_yaxis()
|
||||||
|
ax.set_xlabel('velocity')
|
||||||
|
ax.set_ylabel('depth')
|
||||||
|
ax.legend(loc=4)
|
||||||
|
# 显示绘图
|
||||||
|
plt.show()
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
main()
|
||||||
|
|
||||||
+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
|
||||||
|
|
||||||
@@ -0,0 +1,58 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
import warnings
|
||||||
|
warnings.filterwarnings('ignore')
|
||||||
|
import argparse, json
|
||||||
|
|
||||||
|
def _argparse():
|
||||||
|
parser = argparse.ArgumentParser(description='混响级计算')
|
||||||
|
parser.add_argument('-a', '--argfile', action='store', dest='argfile', required=True, help='name of arguments file')
|
||||||
|
return parser.parse_args()
|
||||||
|
|
||||||
|
def main():
|
||||||
|
parser = _argparse()
|
||||||
|
argfile = parser.argfile
|
||||||
|
if argfile[-5:] != '.json':
|
||||||
|
print('输入的参数文件名有误')
|
||||||
|
return
|
||||||
|
with open(argfile,'r') as jsonFile:
|
||||||
|
paramData = json.load(jsonFile)
|
||||||
|
if ("windSpeed" not in paramData) or ("soundLevel" not in paramData) or\
|
||||||
|
("SV" not in paramData) or ("freq" not in paramData) or\
|
||||||
|
("tau" not in paramData) or ("theta" not in paramData) or\
|
||||||
|
("length" not in paramData) or ("range" not in paramData) or\
|
||||||
|
("outParam" not in paramData):
|
||||||
|
print(f'{argfile}中的参数有误,请核实!')
|
||||||
|
return
|
||||||
|
v = float(paramData["windSpeed"])
|
||||||
|
SL = float(paramData["soundLevel"])
|
||||||
|
Sv = float(paramData["SV"])
|
||||||
|
freq = float(paramData["freq"])
|
||||||
|
tau = float(paramData["tau"])
|
||||||
|
theta = float(paramData["theta"])
|
||||||
|
l = float(paramData["length"])
|
||||||
|
r = float(paramData["range"])
|
||||||
|
outParam = paramData["outParam"]
|
||||||
|
|
||||||
|
from pyat.rlcore import call_rl
|
||||||
|
[rlss, rlsb, rlsv] = call_rl(v,SL,Sv,freq,tau,theta,l,r)
|
||||||
|
# [rlss,rlsb] = call_rl(5,170,55,10,9.5,0.3,182.5)
|
||||||
|
|
||||||
|
#输出json文件
|
||||||
|
outData = {}
|
||||||
|
outData["param"] = paramData
|
||||||
|
outData["海面混响"] = f'{round(rlss,2)}'
|
||||||
|
outData["海底混响"] = f'{round(rlsb,2)}'
|
||||||
|
outData["体积混响"] = f'{round(rlsv,2)}'
|
||||||
|
with open(("" if outParam["outPath"]=="" else outParam["outPath"] + "/")+"rlOut.json", 'w') as jsonFile:
|
||||||
|
json.dump(outData, jsonFile, indent=2, ensure_ascii=False)
|
||||||
|
|
||||||
|
#海面混响
|
||||||
|
print("海面混响计算结果:", round(rlss,2))
|
||||||
|
#海底混响
|
||||||
|
print("海底混响计算结果:", round(rlsb,2))
|
||||||
|
#立体混响
|
||||||
|
print("体积混响计算结果:", round(rlsv,2))
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
main()
|
||||||
@@ -0,0 +1,79 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
import warnings
|
||||||
|
warnings.filterwarnings('ignore')
|
||||||
|
import argparse, json
|
||||||
|
from common import NoIndent, MyEncoder
|
||||||
|
|
||||||
|
def _argparse():
|
||||||
|
parser = argparse.ArgumentParser(description='tl client')
|
||||||
|
parser.add_argument('-a', '--argfile', action='store', dest='argfile', required=True, help='name of arguments file')
|
||||||
|
return parser.parse_args()
|
||||||
|
|
||||||
|
def main():
|
||||||
|
parser = _argparse()
|
||||||
|
argfile = parser.argfile
|
||||||
|
if argfile[-5:] != '.json':
|
||||||
|
print('输入的参数文件名有误')
|
||||||
|
return
|
||||||
|
with open(argfile,'r') as jsonFile:
|
||||||
|
paramData = json.load(jsonFile)
|
||||||
|
if (("ETOPO1Path" not in paramData) or ("STPath" not in paramData) or\
|
||||||
|
"freq" not in paramData) or ("sourceDepth" not in paramData) or\
|
||||||
|
("receiveDepth" not in paramData) or ("sLat" not in paramData) or\
|
||||||
|
("sLon" not in paramData) or ("rLat" not in paramData) or\
|
||||||
|
("rLon" not in paramData) or ("timeType" not in paramData) or\
|
||||||
|
("modelType" not in paramData) or ("png" not in paramData) or\
|
||||||
|
("outParam" not in paramData):
|
||||||
|
print(f'{argfile}中的参数有误,请核实!')
|
||||||
|
return
|
||||||
|
ETOPO1Path = paramData["ETOPO1Path"]
|
||||||
|
STPath = paramData["STPath"]
|
||||||
|
freq = float(paramData["freq"])
|
||||||
|
sourceDepth = float(paramData["sourceDepth"])
|
||||||
|
receiveDepth = float(paramData["receiveDepth"])
|
||||||
|
sLat = float(paramData["sLat"])
|
||||||
|
sLon = float(paramData["sLon"])
|
||||||
|
rLat = float(paramData["rLat"])
|
||||||
|
rLon = float(paramData["rLon"])
|
||||||
|
timeType = paramData["timeType"]
|
||||||
|
modelType = paramData["modelType"]
|
||||||
|
png = paramData["png"]
|
||||||
|
outParam = paramData["outParam"]
|
||||||
|
|
||||||
|
from pyat.tlcore import call_tl
|
||||||
|
import numpy as np
|
||||||
|
[ranges, depths, TL, bathym] = call_tl(ETOPO1Path, STPath, freq=freq, sourceDepth=sourceDepth, sourceLat=sLat, sourceLon=sLon, receiveDepth=receiveDepth,
|
||||||
|
receiveLat=rLat, receiveLon=rLon, timeType=timeType, modelType=modelType, isPlot=png)
|
||||||
|
|
||||||
|
# write data to file
|
||||||
|
# 保存地形数据
|
||||||
|
bathym.r = np.around(bathym.r, decimals=0)
|
||||||
|
bathym.d = np.around(bathym.d, decimals=0)
|
||||||
|
bathymData = {
|
||||||
|
"param": paramData,
|
||||||
|
"count": len(bathym.d),
|
||||||
|
"descript": "距离、深度",
|
||||||
|
"data": NoIndent(list(zip(bathym.r, bathym.d)))
|
||||||
|
}
|
||||||
|
with open(("" if outParam["outPath"]=="" else outParam["outPath"] + "/")+"tlOut_bathym.json", 'w') as jsonFile:
|
||||||
|
json_data = json.dumps(bathymData, cls=MyEncoder, indent=2, ensure_ascii=False)
|
||||||
|
jsonFile.write(json_data)
|
||||||
|
|
||||||
|
# 保存传播损失数据
|
||||||
|
tlpoint = []
|
||||||
|
depths = np.around(depths, decimals=0)
|
||||||
|
ranges = np.around(ranges, decimals=0)
|
||||||
|
TL = np.around(TL, decimals=2)
|
||||||
|
tlpoint = list(zip(np.tile(depths.reshape(len(depths),1),len(ranges)).flatten(), np.tile(ranges,(len(depths),1)).flatten(), TL.flatten()))
|
||||||
|
tlData = {
|
||||||
|
"param": paramData,
|
||||||
|
"count": len(ranges)*len(depths),
|
||||||
|
"descript": "距离、深度、损失",
|
||||||
|
"data": NoIndent(tlpoint)
|
||||||
|
}
|
||||||
|
with open(("" if outParam["outPath"]=="" else outParam["outPath"] + "/")+"tlOut_tl.json", 'w') as jsonFile:
|
||||||
|
json_data = json.dumps(tlData, cls=MyEncoder, indent=2, ensure_ascii=False)
|
||||||
|
jsonFile.write(json_data)
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
main()
|
||||||
+207
@@ -0,0 +1,207 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
import warnings
|
||||||
|
warnings.filterwarnings('ignore')
|
||||||
|
import argparse, json
|
||||||
|
from common import NoIndent, MyEncoder
|
||||||
|
|
||||||
|
def _argparse():
|
||||||
|
parser = argparse.ArgumentParser(description='tl realtime client')
|
||||||
|
parser.add_argument('-a', '--argfile', action='store', dest='argfile', required=True, help='name of arguments file')
|
||||||
|
return parser.parse_args()
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
parser = _argparse()
|
||||||
|
argfile = parser.argfile
|
||||||
|
if argfile[-5:] != '.json':
|
||||||
|
print('输入的参数文件名有误')
|
||||||
|
return
|
||||||
|
with open(argfile,'r') as jsonFile:
|
||||||
|
paramData = json.load(jsonFile)
|
||||||
|
if ("freq" not in paramData) or ("sourceDepth" not in paramData) or\
|
||||||
|
("receiveDepth" not in paramData) or ("modelType" not in paramData) or\
|
||||||
|
("bathyfile" not in paramData) or ("sspfile" not in paramData) or\
|
||||||
|
("z_min" not in paramData) or ("z_max" not in paramData) or\
|
||||||
|
("cp_min" not in paramData) or ("cp_max" not in paramData) or\
|
||||||
|
("cs_min" not in paramData) or ("cs_max" not in paramData) or\
|
||||||
|
("rho_min" not in paramData) or ("rho_max" not in paramData) or\
|
||||||
|
("ap_min" not in paramData) or ("ap_max" not in paramData) or\
|
||||||
|
("as_min" not in paramData) or ("as_max" not in paramData) or\
|
||||||
|
("Cb_p" not in paramData) or ("Cb_s" not in paramData) or\
|
||||||
|
("Rhob" not in paramData) or ("Ab_p" not in paramData) or\
|
||||||
|
("Ab_s" not in paramData) or ("png" not in paramData) or\
|
||||||
|
("outParam" not in paramData):
|
||||||
|
print(f'{argfile}中的参数有误,请核实!')
|
||||||
|
return
|
||||||
|
freq = float(paramData["freq"])
|
||||||
|
sourceDepth = float(paramData["sourceDepth"])
|
||||||
|
receiveDepth = float(paramData["receiveDepth"])
|
||||||
|
modelType = paramData["modelType"]
|
||||||
|
btyfile = paramData["bathyfile"]
|
||||||
|
sspfile = paramData["sspfile"]
|
||||||
|
z_min = float(paramData["z_min"])
|
||||||
|
z_max = float(paramData["z_max"])
|
||||||
|
cp_min = float(paramData["cp_min"])
|
||||||
|
cp_max = float(paramData["cp_max"])
|
||||||
|
cs_min = float(paramData["cs_min"])
|
||||||
|
cs_max = float(paramData["cs_max"])
|
||||||
|
rho_min = float(paramData["rho_min"])
|
||||||
|
rho_max = float(paramData["rho_max"])
|
||||||
|
ap_min = float(paramData["ap_min"])
|
||||||
|
ap_max = float(paramData["ap_max"])
|
||||||
|
as_min = float(paramData["as_min"])
|
||||||
|
as_max = float(paramData["as_max"])
|
||||||
|
Cb_p = float(paramData["Cb_p"])
|
||||||
|
Cb_s = float(paramData["Cb_s"])
|
||||||
|
Rhob = float(paramData["Rhob"])
|
||||||
|
Ab_p = float(paramData["Ab_p"])
|
||||||
|
Ab_s = float(paramData["Ab_s"])
|
||||||
|
png = paramData["png"]
|
||||||
|
outParam = paramData["outParam"]
|
||||||
|
|
||||||
|
from scipy.interpolate import Akima1DInterpolator
|
||||||
|
import numpy as np
|
||||||
|
from pyat.AcousticPara import BathyM, Base, Sed, SSP_
|
||||||
|
from pyat.tlcore import call_Bellhop, call_krakenc, call_ram
|
||||||
|
import matplotlib.pyplot as plt
|
||||||
|
|
||||||
|
bathym, ssp, sed, base = [], [], [], []
|
||||||
|
with open(btyfile, 'r') as f:
|
||||||
|
lines = f.readlines()
|
||||||
|
if len(lines) < 1:
|
||||||
|
print(f'{btyfile}中的参数有误,请核实!')
|
||||||
|
return
|
||||||
|
# 读取数据
|
||||||
|
data = np.loadtxt(btyfile, skiprows=1, usecols=(0, 1))
|
||||||
|
bathym = BathyM(data[:, 0], data[:, 1])
|
||||||
|
|
||||||
|
profile_num = 0
|
||||||
|
with open(sspfile, 'r') as f:
|
||||||
|
try:
|
||||||
|
line = f.readline()
|
||||||
|
profile_num = int((line.split())[0])
|
||||||
|
while line:
|
||||||
|
line = f.readline()
|
||||||
|
if '距离' in line:
|
||||||
|
ranges, depths, vels = [], [], []
|
||||||
|
line = f.readline()
|
||||||
|
while line and ('分隔符' not in line):
|
||||||
|
ranges.append(1)
|
||||||
|
depths.append(float((line.split())[0]))
|
||||||
|
vels.append(float((line.split())[1]))
|
||||||
|
line = f.readline()
|
||||||
|
ssp.append(SSP_(ranges, depths, vels))
|
||||||
|
except Exception as err:
|
||||||
|
print(f'{sspfile}中的参数有误,请核实!')
|
||||||
|
print(err)
|
||||||
|
return
|
||||||
|
|
||||||
|
"""akima 0829"""
|
||||||
|
z_ssp = np.array([])
|
||||||
|
for i in range(len(ssp)):
|
||||||
|
z_ssp = np.append(z_ssp, ssp[i].z)
|
||||||
|
z_ssp = np.unique(z_ssp)
|
||||||
|
z_ssp = np.sort(z_ssp)
|
||||||
|
|
||||||
|
for i in range(len(ssp)):
|
||||||
|
dep = ssp[i].z
|
||||||
|
vel = ssp[i].c
|
||||||
|
# 对剖面进行垂向插值处理
|
||||||
|
depInterp = z_ssp[z_ssp<=ssp[i].z[-1]]
|
||||||
|
# 应用Akima插值算法,对ssp进行插值
|
||||||
|
func = Akima1DInterpolator(dep, vel)
|
||||||
|
velInterp = func(depInterp)
|
||||||
|
# 剖面赋值
|
||||||
|
ssp[i].z = depInterp
|
||||||
|
ssp[i].c = velInterp
|
||||||
|
len_real = len(depInterp)-1
|
||||||
|
#for it in range(len_real,int(deep_max)):
|
||||||
|
# ssp[i].c = np.append(ssp[i].c,0)
|
||||||
|
|
||||||
|
# Sediment
|
||||||
|
z = np.array([z_min, z_max])
|
||||||
|
cp = np.array([cp_min, cp_max])
|
||||||
|
cs = np.array([cs_min, cs_max])
|
||||||
|
rho = np.array([rho_min, rho_max])
|
||||||
|
a_p = np.array([ap_min, ap_max])
|
||||||
|
a_s = np.array([as_min, as_max])
|
||||||
|
for it in range(profile_num):
|
||||||
|
sed.append(Sed(z, cp, cs, rho, a_p, a_s))
|
||||||
|
|
||||||
|
# Base
|
||||||
|
base = []
|
||||||
|
for it in range(profile_num):
|
||||||
|
base.append(Base(Cb_p, Cb_s, Rhob, Ab_p, Ab_s))
|
||||||
|
|
||||||
|
ranges, depths, TL = [], [], []
|
||||||
|
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)
|
||||||
|
ranges, depths, TL = Pos.r.range, Pos.r.depth, TL[0,0,:,:]
|
||||||
|
# Plot
|
||||||
|
if png:
|
||||||
|
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()
|
||||||
|
print(TL[0, 0, :, :])
|
||||||
|
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)
|
||||||
|
ranges, depths, TL = Pos.r.range, Pos.r.depth, TL[0,0,:,:]
|
||||||
|
# Plot
|
||||||
|
if png:
|
||||||
|
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()
|
||||||
|
elif modelType == 'ram':
|
||||||
|
# 调用ram模块
|
||||||
|
[rd, rr, TL] = call_ram(freq, sourceDepth, receiveDepth, bathym, ssp, sed)
|
||||||
|
ranges, depths, TL = rr, rd, TL
|
||||||
|
# Plot
|
||||||
|
if png:
|
||||||
|
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()
|
||||||
|
|
||||||
|
# 保存地形数据
|
||||||
|
bathym.r = np.around(bathym.r, decimals=0)
|
||||||
|
bathym.d = np.around(bathym.d, decimals=0)
|
||||||
|
bathymData = {
|
||||||
|
"param": paramData,
|
||||||
|
"count": len(bathym.d),
|
||||||
|
"descript": "距离、深度",
|
||||||
|
"data": NoIndent(list(zip(bathym.r, bathym.d)))
|
||||||
|
}
|
||||||
|
with open(("" if outParam["outPath"]=="" else outParam["outPath"] + "/")+"tlRealtimeOut_bathym.json", 'w') as jsonFile:
|
||||||
|
json_data = json.dumps(bathymData, cls=MyEncoder, indent=2, ensure_ascii=False)
|
||||||
|
jsonFile.write(json_data)
|
||||||
|
|
||||||
|
# 保存传播损失数据
|
||||||
|
tlpoint = []
|
||||||
|
depths = np.around(depths, decimals=0)
|
||||||
|
ranges = np.around(ranges, decimals=0)
|
||||||
|
TL = np.around(TL, decimals=2)
|
||||||
|
tlpoint = list(zip(np.tile(depths.reshape(len(depths),1),len(ranges)).flatten(), np.tile(ranges,(len(depths),1)).flatten(), TL.flatten()))
|
||||||
|
tlData = {
|
||||||
|
"param": paramData,
|
||||||
|
"count": len(ranges)*len(depths),
|
||||||
|
"descript": "距离、深度、损失",
|
||||||
|
"data": NoIndent(tlpoint)
|
||||||
|
}
|
||||||
|
with open(("" if outParam["outPath"]=="" else outParam["outPath"] + "/")+"tlRealtimeOut_tl.json", 'w') as jsonFile:
|
||||||
|
json_data = json.dumps(tlData, cls=MyEncoder, indent=2, ensure_ascii=False)
|
||||||
|
jsonFile.write(json_data)
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
main()
|
||||||
@@ -0,0 +1,60 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
import warnings
|
||||||
|
warnings.filterwarnings('ignore')
|
||||||
|
import argparse, json
|
||||||
|
|
||||||
|
def _argparse():
|
||||||
|
parser = argparse.ArgumentParser(description='Wind Generated Noise Prediction')
|
||||||
|
parser.add_argument('-a', '--argfile', action='store', dest='argfile', required=True, help='name of arguments file')
|
||||||
|
return parser.parse_args()
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
parser = _argparse()
|
||||||
|
argfile = parser.argfile
|
||||||
|
if argfile[-5:] != '.json':
|
||||||
|
print('输入的参数文件名有误')
|
||||||
|
return
|
||||||
|
with open(argfile,'r') as jsonFile:
|
||||||
|
paramData = json.load(jsonFile)
|
||||||
|
if ("dataFile" not in paramData) or ("freq" not in paramData) or\
|
||||||
|
("depth" not in paramData) or ("windSpeed" not in paramData) or\
|
||||||
|
("month" not in paramData) or\
|
||||||
|
("png" not in paramData) or \
|
||||||
|
("outParam" not in paramData):
|
||||||
|
print(f'{argfile}中的参数有误,请核实!')
|
||||||
|
return
|
||||||
|
dataFile = paramData["dataFile"]
|
||||||
|
freq = float(paramData["freq"])
|
||||||
|
depth = float(paramData["depth"])
|
||||||
|
windSpeed = float(paramData["windSpeed"])
|
||||||
|
month = int(paramData["month"])
|
||||||
|
png = paramData["png"]
|
||||||
|
outParam = paramData["outParam"]
|
||||||
|
|
||||||
|
from pyat.WGNPd import WGNPd
|
||||||
|
from pyat.DataBase import DataBase
|
||||||
|
import matplotlib.pyplot as plt
|
||||||
|
import numpy as np
|
||||||
|
|
||||||
|
freq = 50 * np.power(2, np.arange(freq)/3)
|
||||||
|
frequency, spl = WGNPd(dataFile, depth, windSpeed, month, freq)
|
||||||
|
|
||||||
|
#输出json文件
|
||||||
|
outData = {}
|
||||||
|
outData["param"] = paramData
|
||||||
|
outData["descript"] = "frequency and noise level"
|
||||||
|
frequency = np.around(frequency, decimals=0)
|
||||||
|
spl = np.around(spl, decimals=2)
|
||||||
|
outData["data"] = list(zip(frequency, spl))
|
||||||
|
with open(("" if outParam["outPath"]=="" else outParam["outPath"] + "/")+"wgnpOut.json", 'w') as jsonFile:
|
||||||
|
json.dump(outData, jsonFile, indent=2, ensure_ascii=False)
|
||||||
|
|
||||||
|
if png:
|
||||||
|
plt.semilogx(freq, spl)
|
||||||
|
plt.xlabel('Frequency / Hz')
|
||||||
|
plt.ylabel('Noise Level / dB')
|
||||||
|
plt.show()
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
main()
|
||||||
在新工单中引用
屏蔽一个用户