import unicodedata import numpy as np from ProfileDataType import Profile from scipy.interpolate import interp1d from scipy.signal import butter, filtfilt from 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