169 行
4.1 KiB
Python
169 行
4.1 KiB
Python
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
|