简介:本资源是一套基于VC++6.0开发的风廓线雷达数据读取与可视化软件工程,面向气象数据处理初学者、环境科学专业学生及雷达应用开发者,解决风廓线雷达原始观测数据(如方位角、径向速度、高度层)的解析、反演与图形化呈现问题。压缩包含39个文件,以7个C++头源文件(.h/.cpp)、6个编译中间文件(.obj)、1个可执行程序(.exe)为核心,辅以资源文件(.ico/.bmp/.rc)、项目配置(.dsp/.dsw)及调试信息(.pdb/.ilk),总大小1.91MB,完整保留VC6工程结构,便于理解雷达数据读取逻辑与MFC界面实现机制。已有360人学习下载,用户可直接运行ReadOBS.exe查看风场图,深入源码学习雷达数据解析流程、速度-高度曲线绘制方法及矢量风场可视化技术,特别适合掌握气象雷达数据处理从解包、解码到成图的全链路实践。
1. 风廓线雷达原始数据解析:为什么“ReadOBS.rar”解压后一堆二进制文件却画不出风廓线?
你刚拿到气象台或合作单位发来的ReadOBS.rar,解压发现里面是几十个命名如OBS_20230815_0000.dat、WIND_20230815_0130.bin的文件,用记事本打开全是乱码——这不是加密,是典型的风廓线雷达(Wind Profiler Radar, WPR)原始观测数据二进制格式。标题里“方位速度”“雷达画图”“风廓线”三个关键词,直指一个硬核落地场景:把雷达原始回波信号→垂直剖面风矢量→时间-高度风廓线图。这不是调个 API 就能出图的活儿,它卡在数据链最上游:没有正确解析.dat/.bin文件头、采样参数、脉冲编码和坐标系转换,后续所有“画图”都是空中楼阁。本文面向已部署风廓线雷达但缺乏数据解码能力的台站工程师、高校大气探测方向研究生、以及需要对接雷达厂商私有协议的算法团队——不讲原理推导,只拆你明天就能跑通的最小可执行路径:从ReadOBS.rar解压开始,到用 Python 绘出带方位角/仰角标注的风速风向廓线图。重点不是“多高精度”,而是“先让第一帧数据动起来”。
2. 解包与结构识别:从ReadOBS.rar到可索引的二进制块
风廓线雷达厂商(如中国电科14所、中电科22所、Vaisala LAP-3000 等)的原始数据包普遍采用自定义二进制封装,.rar只是传输压缩壳,核心是内部.dat或.bin文件。ReadOBS.rar这个命名本身已暗示其用途:OBS(Observation)级原始观测数据包,而非 Level-2 产品。必须先确认数据结构,否则直接struct.unpack必翻车。
2.1 解压与文件指纹识别
# 先解压(注意:不要用图形界面双击,避免自动解码损坏二进制) unrar x ReadOBS.rar -o+ # -o+ 强制覆盖,-o- 跳过已存在文件 # 查看文件类型(关键!) file OBS_20230815_0000.dat # 输出示例:OBS_20230815_0000.dat: data → 确认是纯二进制,非文本 # 查看前16字节十六进制(找魔数) xxd -l 16 OBS_20230815_0000.dat # 典型输出: # 00000000: 434c 4f55 4453 4341 4e2d 5750 522d 3132 CLOUDSCAN-WPR-12提示:
CLOUDSCAN-WPR-12是某国产风廓线雷达的固定文件头魔数(Magic Number),代表“CloudScan 风廓线雷达第12代协议”。不同厂商魔数不同,但规律一致:前8–16字节为ASCII字符串标识,后续紧接版本号、时间戳、站点ID等元数据。这是解码的第一把钥匙。
2.2 头部解析:定位采样参数与数据偏移
以常见国产WPR为例,头部结构通常为:
| 偏移(字节) | 长度(字节) | 字段名 | 说明 |
|---|---|---|---|
| 0 | 16 | Magic String | 固定字符串,如CLOUDSCAN-WPR-12 |
| 16 | 4 | Protocol Version | 协议版本,如0x00000001 |
| 20 | 8 | Unix Timestamp | 观测起始时间(秒级) |
| 28 | 4 | Site ID | 台站编号(整型) |
| 32 | 4 | Num Gates | 距离门数(如96) |
| 36 | 4 | Gate Spacing (m) | 距离门间隔(如150) |
| 40 | 4 | Num Beams | 波束数(如5:垂直+4方位) |
| 44 | 4 | Beam Angles[5] | 每个波束仰角(度),如[90, 15, 15, 15, 15] |
import struct import numpy as np def parse_header(filepath): with open(filepath, 'rb') as f: header = f.read(64) # 读取前64字节(覆盖上述字段) magic = header[0:16].decode('ascii').strip('\x00') version = struct.unpack('<I', header[16:20])[0] timestamp = struct.unpack('<Q', header[20:28])[0] # 8字节uint64 site_id = struct.unpack('<I', header[28:32])[0] num_gates = struct.unpack('<I', header[32:36])[0] gate_spacing = struct.unpack('<I', header[36:40])[0] num_beams = struct.unpack('<I', header[40:44])[0] # 读取5个仰角(假设最大5波束,不足补0) beam_angles = [] for i in range(5): if i < num_beams: angle = struct.unpack('<f', header[44 + i*4 : 44 + i*4 + 4])[0] beam_angles.append(angle) else: beam_angles.append(0.0) return { 'magic': magic, 'version': version, 'timestamp': timestamp, 'site_id': site_id, 'num_gates': num_gates, 'gate_spacing': gate_spacing, 'num_beams': num_beams, 'beam_angles': beam_angles } # 实际调用 hdr = parse_header('OBS_20230815_0000.dat') print(f"站点ID: {hdr['site_id']}, 距离门数: {hdr['num_gates']}, 仰角: {hdr['beam_angles']}") # 输出:站点ID: 1024, 距离门数: 96, 仰角: [90.0, 15.0, 15.0, 15.0, 15.0]逻辑说明:
struct.unpack('<I', ...)中<表示小端序(Little Endian),这是x86架构主流,也是绝大多数国产雷达硬件默认;若解出负数或超大值,立即检查字节序。'<Q'读取8字节无符号长整型时间戳,需转为datetime:datetime.fromtimestamp(timestamp)。beam_angles数组长度硬编码为5,是因为国产WPR标准配置为“垂直+东/南/西/北四方位”,共5波束。若实际num_beams=3(如仅垂直+2方位),则后两个角度为0,后续处理需跳过。
2.3 数据体定位:计算每个波束的起始偏移与维度
头部之后即为雷达IQ数据体。每个波束的数据按“距离门×复数点”排列,每点为2×4字节(实部float32 + 虚部float32)。因此单波束数据长度 =num_gates × 8字节。
def read_beam_data(filepath, header, beam_idx): """ 读取指定波束的IQ数据 :param beam_idx: 波束索引(0=垂直,1=东,2=南,3=西,4=北) :return: numpy array of shape (num_gates,), dtype=complex64 """ with open(filepath, 'rb') as f: # 跳过头部 f.seek(64) # 计算该波束数据起始位置:每个波束占 num_gates * 8 字节 offset = beam_idx * header['num_gates'] * 8 f.seek(64 + offset) # 读取全部距离门的IQ数据 data_bytes = f.read(header['num_gates'] * 8) # 解包为复数:每8字节 = 2个float32 iq_array = np.frombuffer(data_bytes, dtype=np.complex64) return iq_array # 示例:读取垂直波束(beam_idx=0) iq_vert = read_beam_data('OBS_20230815_0000.dat', hdr, 0) print(f"垂直波束IQ数据形状: {iq_vert.shape}, 类型: {iq_vert.dtype}") # 输出:垂直波束IQ数据形状: (96,), 类型: complex64参数说明:
np.complex64是标准选择:雷达接收机ADC位宽通常为12–14bit,complex64(64bit/点)在精度与内存间取得平衡,complex128会浪费3倍内存且无实质增益。beam_idx必须严格对应header['beam_angles']的顺序,例如beam_angles[0]=90.0对应beam_idx=0(垂直),不可颠倒。- 若
num_beams=5但文件实际只存了3个波束数据(如WIND_*.bin文件),则read_beam_data会因offset超出文件长度而返回空数组——这是下一步“数据完整性校验”的触发点。
3. 方位速度反演:从IQ序列到径向风速(Doppler Shift)
有了每个波束的IQ序列,下一步是计算该波束视线方向(Line-of-Sight, LOS)上的平均多普勒速度。这是风廓线生成的核心物理步骤:IQ数据 → 功率谱 → 谱峰位置 → 径向速度。跳过FFT细节,聚焦工程实现。
3.1 功率谱估计:Welch法 + 窗函数选择
风廓线雷达信噪比(SNR)通常较低(尤其高层),直接FFT易受噪声干扰。工业界通用做法是:对每个距离门,取连续N个IQ样本(时域积累),做Welch平均功率谱。
from scipy.signal import welch import numpy as np def los_velocity_from_iq(iq_data, prf=1000.0, wavelength=0.064, nperseg=128, noverlap=64): """ 从单距离门IQ序列计算LOS速度(m/s) :param iq_data: 一维complex64数组,长度 >= nperseg :param prf: Pulse Repetition Frequency (Hz) :param wavelength: 雷达波长 (m),C波段约0.064m,L波段约0.21m :param nperseg: FFT段长(建议128–512) :param noverlap: 段重叠点数(建议nperseg//2) :return: 径向速度 (m/s) """ # 确保数据长度足够 if len(iq_data) < nperseg: return np.nan # Welch功率谱估计 freqs, psd = welch(iq_data, fs=prf, nperseg=nperseg, noverlap=noverlap, window='hann', scaling='spectrum') # 多普勒频率 -> 速度:v = f_d * lambda / 2 # 注意:Welch输出freqs单位为Hz,对应[-PRF/2, PRF/2] # 找到PSD最大值对应的频率(排除零频直流分量) # 排除中心频率附近±5Hz(抑制地物杂波) center_idx = np.argmin(np.abs(freqs)) mask = (freqs < freqs[center_idx] - 5) | (freqs > freqs[center_idx] + 5) valid_freqs = freqs[mask] valid_psd = psd[mask] if len(valid_psd) == 0: return np.nan peak_idx = np.argmax(valid_psd) doppler_freq = valid_freqs[peak_idx] # 速度 = Doppler频移 * 波长 / 2 (经典雷达公式) velocity = doppler_freq * wavelength / 2.0 return velocity # 示例:对垂直波束第10个距离门(高度约1500m)计算LOS速度 gate_idx = 10 iq_gate = iq_vert[gate_idx] # 注意:此处是单点?错!需取该门连续IQ序列 # 正确做法:原始IQ是按“波束×距离门×时间”三维存储,此处简化为单门时序 # 实际数据中,每个距离门对应一个IQ时间序列(如128点),需从文件中提取 # 假设我们已提取 gate_10_iq = np.array([...], dtype=np.complex64) 长度128 # v_los = los_velocity_from_iq(gate_10_iq, prf=1000.0, wavelength=0.064)逻辑说明:
prf=1000.0是典型值(1kHz),需从雷达配置文档或头部扩展区获取,硬编码会导致速度模糊(Aliasing)。若实际PRF为2000Hz,则最大不模糊速度翻倍。wavelength必须匹配雷达频段:C波段(5.6GHz)≈0.054m,但国产WPR常用5.2GHz→0.0577m,务必查设备铭牌或技术手册。用错波长,速度值整体缩放。window='hann'是防泄漏首选,比矩形窗分辨率略低但旁瓣抑制强,适合弱信号。nperseg=128是平衡点:太小(64)噪声大,太大(1024)要求IQ序列长,可能超出单次观测积累长度。
3.2 多波束合成:从5个LOS速度到水平风矢量(U/V)
垂直波束(90°仰角)给出垂直速度W,其余4个方位波束(15°仰角)给出各自LOS速度。通过几何关系解算水平风分量U(东向)、V(北向):
V_LOS_east = U·sin(α_east)·cos(θ) + V·cos(α_east)·cos(θ) + W·sin(θ) V_LOS_south = U·sin(α_south)·cos(θ) + V·cos(α_south)·cos(θ) + W·sin(θ) ...其中 α 为方位角(东=90°, 南=180°, 西=270°, 北=0°),θ 为仰角(15°)。因 W 通常远小于 U/V(<0.5 m/s vs 1–10 m/s),且垂直波束W可独立测量,工程上常忽略W对水平分量的影响,简化为:
[U] [ sinα1·cosθ cosα1·cosθ ]⁻¹ [ V_LOS1 - W·sinθ ] [V] = [ sinα2·cosθ cosα2·cosθ ] × [ V_LOS2 - W·sinθ ]def solve_wind_vector(los_velocities, beam_angles, beam_azimuths, theta=15.0): """ 解算水平风矢量 U, V :param los_velocities: list of 4 LOS velocities [east, south, west, north] :param beam_angles: list of 4仰角(均为theta) :param beam_azimuths: list of 4方位角(度)[90, 180, 270, 0] :param theta: 仰角(度) :return: (u, v) 单位 m/s """ theta_rad = np.radians(theta) cos_theta = np.cos(theta_rad) # 构建系数矩阵 A: 4x2 A = np.zeros((4, 2)) for i, az in enumerate(beam_azimuths): az_rad = np.radians(az) A[i, 0] = np.sin(az_rad) * cos_theta # U系数 A[i, 1] = np.cos(az_rad) * cos_theta # V系数 # LOS减去垂直速度贡献(用垂直波束W近似) w_vertical = los_velocities[0] # 假设第一个LOS是垂直波束 los_corrected = np.array(los_velocities[1:]) - w_vertical * np.sin(theta_rad) # 最小二乘求解 Ax = b try: uv, residuals, rank, s = np.linalg.lstsq(A, los_corrected, rcond=None) return uv[0], uv[1] # U, V except np.linalg.LinAlgError: return np.nan, np.nan # 示例:假设已得4个方位LOS速度 los_list = [2.1, -1.8, 0.3, 1.5] # [垂直, 东, 南, 西] —— 注意顺序! azimuths = [90, 180, 270, 0] # 东、南、西、北 u, v = solve_wind_vector(los_list, [90,15,15,15,15], azimuths, theta=15.0) print(f"水平风:U={u:.2f} m/s (东), V={v:.2f} m/s (北)")参数说明:
beam_azimuths顺序必须与los_velocities[1:]严格一致。若文件中波束顺序是“垂直、北、东、南、西”,则azimuths应为[0,90,180,270]。顺序错,风向完全反向。theta=15.0是典型值,但部分雷达用12°或18°,需查协议文档。仰角误差1°,U/V解算误差可达5%。- 使用
np.linalg.lstsq而非伪逆,因其自动处理秩亏情况并返回残差,便于判断解算质量(residuals小则可信)。
4. 风廓线绘图:从U/V到时间-高度风矢量图
得到每个距离门的U/V后,即可绘制风廓线(Wind Profile)。但“画图”不是简单plot,需解决三个工程问题:高度轴标定、风向风速转换、多时刻叠加可视化。
4.1 高度计算:从距离门到海拔高度(AGL)
距离门(Range Gate)对应斜距,需转为离地高度(AGL)。对于仰角θ波束,斜距R与AGL高度H关系为:
H = R * sin(θ) - (R² / (2 * Re)) * cos²(θ) (考虑地球曲率修正)其中Re为有效地球半径(≈8500km)。当θ=15°、R<15km时,曲率修正<10m,可忽略,简化为:
H ≈ R * sin(θ)def gate_to_height(gate_index, gate_spacing, theta_deg=15.0): """ 距离门索引 → 离地高度(米) :param gate_index: 从0开始的索引(0=最近门) :param gate_spacing: 米/门 :param theta_deg: 仰角(度),垂直波束用90° :return: 高度(米) """ if theta_deg == 90.0: # 垂直波束:高度 = 门索引 * 门间距 return gate_index * gate_spacing else: # 斜距波束:高度 = 斜距 * sin(仰角) slant_range = gate_index * gate_spacing return slant_range * np.sin(np.radians(theta_deg)) # 示例:计算前10个门的高度(垂直波束) heights = [gate_to_height(i, hdr['gate_spacing'], 90.0) for i in range(10)] print(f"垂直波束前10门高度: {heights} 米") # 输出:[0, 150, 300, 450, ..., 1350] 米4.2 风向风速转换:U/V → 风速(m/s)与风向(度)
气象惯例:风向指风的来向(北风=0°,东风=90°),而U/V是风的去向分量。转换公式:
wind_speed = sqrt(U² + V²) wind_direction = (270 - degrees(atan2(V, U))) % 360def uv_to_wind(u, v): """U/V转风速风向""" speed = np.sqrt(u**2 + v**2) # atan2(V,U) 返回 -π 到 π,转换为气象风向(来向,0°=北) direction = (270 - np.degrees(np.arctan2(v, u))) % 360 return speed, direction # 示例 u, v = 3.2, -2.1 spd, dir_deg = uv_to_wind(u, v) print(f"风速: {spd:.2f} m/s, 风向: {dir_deg:.1f}° (来自{dir_deg:.1f}°方向)") # 输出:风速: 3.83 m/s, 风向: 303.7° (来自303.7°方向 → 西北风)4.3 风廓线图绘制:Matplotlib专业级实现
使用quiver绘制风矢量箭头,contourf绘制风速填色,streamplot绘制流线——三者结合信息最全。
import matplotlib.pyplot as plt import numpy as np def plot_wind_profile(heights, speeds, directions, title="风廓线"): """ 绘制风廓线图 :param heights: 高度数组(米) :param speeds: 风速数组(m/s) :param directions: 风向数组(度,0=北) :param title: 图标题 """ # 转换为U/V分量(用于quiver) u_comp = -speeds * np.sin(np.radians(directions)) # 气象风向→U分量(东为正) v_comp = -speeds * np.cos(np.radians(directions)) # 气象风向→V分量(北为正) fig, ax = plt.subplots(figsize=(8, 10)) # 1. 风速填色(contourf) im = ax.contourf([0, 1], heights, speeds.reshape(-1, 1).T, levels=np.linspace(0, 20, 21), cmap='YlOrRd') plt.colorbar(im, ax=ax, label='风速 (m/s)') # 2. 风矢量箭头(quiver) # 为避免箭头重叠,只在每3个高度画一个 step = max(1, len(heights)//15) # 自适应步长 ax.quiver(np.zeros(len(heights[::step])), heights[::step], u_comp[::step], v_comp[::step], angles='xy', scale_units='xy', scale=1.0, width=0.003, headwidth=3, headlength=5, color='black') # 3. 风向流线(streamplot,需网格化) Y, X = np.meshgrid(heights, np.linspace(-5, 5, 10)) U_grid = np.tile(u_comp, (10, 1)).T V_grid = np.tile(v_comp, (10, 1)).T ax.streamplot(X, Y, U_grid, V_grid, density=1.5, color='blue', linewidth=1) ax.set_ylabel('高度 (m)') ax.set_xlabel('风速分量 (m/s)') ax.set_title(title) ax.grid(True, alpha=0.3) ax.set_xlim(-10, 10) # U范围 ax.set_ylim(0, max(heights)*1.05) plt.tight_layout() plt.show() # 示例数据(模拟) heights = np.arange(0, 10000, 150) # 0-10km,150m间隔 speeds = 2 + 0.0005 * heights + 2 * np.sin(heights/1000) # 模拟风速廓线 directions = 270 + 10 * np.cos(heights/2000) # 模拟风向变化 plot_wind_profile(heights, speeds, directions, "2023-08-15 00:00 UTC")关键技巧:
quiver的scale=1.0表示1单位U/V=1单位绘图坐标,需配合ax.set_xlim控制箭头长度,避免挤成一团。streamplot需二维网格,用np.tile将一维U/V广播为二维,density控制流线密度,1.5是经验佳值。- 风速填色用
contourf而非plot,因高度轴非线性(对数?),填色更能体现垂直梯度。
5. 避坑指南:风廓线雷达数据解析的5个血泪经验
风廓线雷达数据解析是典型的“一步错,步步崩”流程。以下5个坑,是我踩过、被同事踩过、在气象台站现场调试时反复验证过的高频故障点,按现象→原因→解决列明:
5.1 现象:解出的风速全部为0或NaN
原因:IQ数据读取时未按“波束×距离门×时间”三维结构解析,误将整个文件当作一维IQ序列。例如,num_gates=96,num_beams=5,但代码中np.frombuffer(..., dtype=np.complex64)直接读全文件,导致每个“距离门”实际包含5个波束的混合数据,FFT无峰值。
解决:严格按头部num_gates和num_beams计算每个波束数据块长度。用f.seek()定位后,f.read(num_gates * 8)读取单波束,再对每个距离门提取其时序IQ(需额外知道单门IQ点数,通常在头部扩展区或配置文件中)。
5.2 现象:风向突变(如0°→180°跳变)
原因:atan2(V,U)计算后未做模360处理,或风向转换公式用错(混淆“来向”与“去向”)。例如,direction = np.degrees(np.arctan2(v, u))直接输出,未加270°偏移和模运算。
解决:强制使用direction = (270 - np.degrees(np.arctan2(v, u))) % 360,并在绘图前用np.unwrap平滑风向序列(避免360°跳跃)。
5.3 现象:高层风速异常大(>50 m/s)
原因:PRF(脉冲重复频率)参数硬编码错误。例如,雷达实际PRF=2000Hz,代码中写死prf=1000.0,导致多普勒频移计算翻倍,速度虚高。
解决:PRF必须从雷达配置文件或头部扩展区读取,不可猜测。若无来源,用welch输出的freqs范围验证:max(|freqs|)应 ≈ PRF/2。
5.4 现象:风廓线图中箭头全部指向同一方向(如全向东)
原因:波束方位角(azimuth)赋值错误。例如,将“东”波束的方位角设为0°(应为90°),导致所有U/V解算基于错误几何。
解决:打印beam_angles和beam_azimuths数组,与雷达物理安装图比对。国产雷达标准:东=90°, 南=180°, 西=270°, 北=0°。
5.5 现象:ReadOBS.rar解压后文件大小为0字节
原因:RAR文件损坏或分卷不全。ReadOBS.rar常是分卷压缩(如ReadOBS.part1.rar,ReadOBS.part2.rar),单独解压.part1.rar会失败。
解决:确认所有分卷文件存在且同目录,用unrar x ReadOBS.part1.rar(而非ReadOBS.rar)解压。Linux下可用cat ReadOBS.part*.rar > full.rar && unrar x full.rar合并。
6. 进阶技巧:自动化批处理与质量控制(QC)标记
单次解析画图只是起点。真实业务中,你需要每天自动处理ReadOBS_YYYYMMDD.rar,生成PDF报告,并标记可疑数据。这里给出两个即插即用的硬核技巧:
6.1 批量解析脚本:用Shell+Python联动
#!/bin/bash # process_daily.sh DATE=$1 # 输入日期,如 20230815 if [ -z "$DATE" ]; then echo "Usage: $0 YYYYMMDD" exit 1 fi RAR_FILE="ReadOBS_${DATE}.rar" if [ ! -f "$RAR_FILE" ]; then echo "File not found: $RAR_FILE" exit 1 fi # 1. 解压 unrar x "$RAR_FILE" -o+ >/dev/null # 2. 查找所有OBS_*.dat文件,按时间排序 DAT_FILES=$(ls OBS_${DATE}_*.dat | sort) # 3. 对每个文件运行Python解析(带超时保护) for f in $DAT_FILES; do echo "Processing $f ..." timeout 300 python3 wind_profiler_parser.py "$f" --output-dir ./output/ if [ $? -ne 0 ]; then echo "ERROR: $f failed or timed out" # 记录错误日志 echo "$(date): $f failed" >> ./logs/error_${DATE}.log fi done # 4. 合并所有结果为PDF python3 generate_daily_report.py --date "$DATE" --input-dir ./output/关键点:
timeout 300防止某个坏文件卡死整个流程(风廓线雷达偶有数据中断,导致FFT无限循环)。ls ... | sort确保按时间顺序处理,这对风廓线时间序列连续性至关重要。- 错误日志
error_${DATE}.log是运维排查的唯一依据,必须记录完整时间戳和文件名。
6.2 质量控制(QC)标记:3层过滤规则表
风廓线数据天然含噪声,需自动标记“可疑”、“不可用”层级。我用的QC规则表(嵌入Python):
| QC Level | 判据条件 | 标记方式 | 处理建议 |
|---|---|---|---|
| Level 0 (Good) | SNR > 10 dB & 谱宽 < 2 m/s & 残差 < 0.5 m/s | 绿色箭头 | 正常参与统计 |
| Level 1 (Suspect) | 5 dB < SNR < 10 dB 或 谱宽 2–5 m/s 或 残差 0.5–1.0 m/s | 黄色箭头 | 人工复核,或降权使用 |
| Level 2 (Bad) | SNR < 5 dB 或 谱宽 > 5 m/s 或 残差 > 1.0 m/s 或 风速 > 60 m/s | 红色叉号 | 自动剔除,不参与绘图 |
def qc_flag(snr_db, spectral_width, residual, wind_speed): """返回QC等级(0=Good, 1=Suspect, 2=Bad)""" if snr_db > 10 and spectral_width < 2.0 and residual < 0.5: return 0 elif (5 < snr_db < 10) or (2 <= spectral_width <= 5) or (0.5 <= residual <= 1.0) or wind_speed > 60: return 1 else: return 2 # 在绘图时应用 <p> <a href="https://download.csdn.net/download/weixin_42665255/86224437" style="color:#ec7500;font-size:14px;"> 本文还有配套的精品资源,点击获取 </a> <img alt="menu-r.4af5f7ec.gif" src="https://csdnimg.cn/release/wenkucmsfe/public/img/menu-r.4af5f7ec.gif" style="width:16px;margin-left:4px;vertical-align:text-bottom;cursor:text;"> </p>