气象雷达基数据格式解析:从二进制文件结构到数据还原实践

📅 发布时间:2026/10/15 12:18:54
气象雷达基数据格式解析:从二进制文件结构到数据还原实践
简介SA/SB和CA/CB雷达基数据格式说明文档面向气象雷达数据解析、科研人员及软件开发者主要解决雷达基数据二进制结构不明确、径向数据读取困难等问题。文档按字节偏移详细说明了28字节雷达信息头、15字节径向数据收集时间、17字节儒略日、17字节方位角、21字节径向数据状态、21字节仰角、22字节体扫内仰角数等字段的长度与编码方式并给出了反射率、速度、谱宽数据的距离库长、库数及最大径向长度等参数。针对SA/SB与CA/CB两种雷达还分别说明了数据排列顺序、距离库数上限如SA/SB反射率最大460库速度/谱宽920库CA/CB反射率最大800库速度/谱宽1600库及编码公式如反射率数据数值-2/2-32dBZ同时涵盖体扫模式、多普勒速度分辨率、Nyquist速度、系统订正常数等头部信息可辅助理解径向数据整体结构。资源为1个doc文件大小92KB以文字说明和字节表格为主便于对照查阅。目前已有2797人学习/下载适合需要编写雷达数据解析程序或进行格式转换的研究人员与工程师。1. 雷达基数据格式说明搞懂它之前你手里的雷达文件只是一团乱码做气象雷达算法的人大概率都经历过这个时刻拿到一个基数据文件后缀是.bin或者干脆没有后缀用十六进制编辑器打开前面是一串看不懂的字节后面是密密麻麻的数字文件多大、径向多少、角度怎么存的全靠猜。雷达基数据不是普通的图像或表格它是一卷按扫描顺序排列的二进制数组里面装着回波强度、径向速度和谱宽等物理量但每种雷达、每个厂商甚至不同软件版本存储规则都可能不一样。这篇笔记用通用雷达基数据的格式逻辑带你从文件头读到数据体把字节、缩放、缺测这些坑一次性踩平。2. 先把雷达基数据的底子摸清三种流派、两层结构、一个关键区别2.1 厂商私有格式与行业通用格式的分界雷达基数据格式看起来杂乱但本质上只分两类。第一类是厂商私有格式由雷达硬件厂商定义例如某些型号的业务雷达会把基数据存成自定义二进制的样子文件头里有魔数标识、版本号、站点信息和扫描参数数据体按径向逐条存放。这类格式的好处是写入效率高厂商的软件直接读坏处是换一套软件或换一个数据源就必须先逆向文件结构。第二类是行业通用格式由学术机构或行业组织提出用于交换和归档。常见的做法是定义统一的文件头、维度顺序和变量命名再结合通用数据容器来存。比如欧洲雷达社区推动的ODIM_H5规范要求用HDF5承载数据组每个数据组包含“how”、“what”、“where”三类属性集合又比如美国气象界常用的CFRadial约定基于NetCDF来组织径向扫描数据。读这类格式时重点已经不是“文件字节怎么排”而是“属性名怎么映射”。这两类的选择对后续处理链路影响很大。如果你只是临时读一批数据做研究私有格式直接解析就够了如果你要搭一套长期运行的业务系统建议在入口处统一转成通用格式再入库。我一般会在对接阶段同时保留原始文件和转换后的通用文件原始文件用于校对通用文件用于算法迭代。2.2 从文件头读出格式身份最小识别流程不管是什么格式拿到文件的第一步不是直接写解析代码而是先确认它是谁。常见做法是同时做三件事第一用十六进制工具看前256个字节寻找魔数、版本号或者可读文本第二看文件扩展名和来源系统的命名规则有些业务系统会在文件名里直接写“径向数-库数-仰角数”第三把文件交给厂商自带软件或开源库试读一次能读通就基本确定格式家族。举例来说某型号雷达的基数据文件头通常会有固定文本标记、数据生成时间、站点编号、体扫起始角度、径向数、每径向库数、仰角数和径向数据长度。这里的“每径向库数”和“径向数据长度”是后续解析的两个核心参数前者决定一根径向上有多少个采样点后者决定一根径向在文件中占多少字节。很多解析翻车都是因为这两个数字在文件头里以不同单位出现有的是库数有的是字节数中间还夹着径向头的长度没有计入。识别完文件头之后要做一次“冒烟测试”用文件总字节数除以径向头长度加径向数据长度看结果是否等于文件头里写的径向总数。能整除、结果吻合说明结构判断基本正确对不上说明中间某处有填充字节或者长度看错这个除法校验是整个解析流程里最便宜的纠错手段。2.3 基数据与产品数据的本质差异别拿产品算法要求基数据雷达基数据是“最接近原始观测”的数据层它保存的是信号处理器输出的物理量估计值一般包括反射率因子常用单位dBZ、平均径向速度单位m/s和谱宽单位m/s。而雷达产品是基数据经过算法加工之后的图像化或网格化结果比如组合反射率、垂直液态水含量、回波顶高等它们已经做过了插值、合成和坐标变换。这个区别直接决定了画图方式完全不同。基数据需要在极坐标系下显示x轴是方位角y轴是距离库雷达位于原点产品数据通常已经转到经纬度网格或笛卡尔坐标可以直接叠加地图。很多刚从图像处理转来做雷达的开发者会把基数据当成“图像”去训练深度学习模型一上来就用普通图像增强手段处理结果在极坐标畸变上吃了大亏。因此拿到基数据之后第一件事不是画图而是确认你后续要做的是极坐标下的算法比如单径向去噪、速度退模糊还是先做坐标转换到笛卡尔网格比如做拼图、做定量降水估计。这决定了你是先解格式还是先做坐标变换直接影响整个处理链路的架构。3. 手工解析一个二进制基数据文件逐字节拆解和最小可用代码3.1 径向头与数据体结构怎么排当我们把基数据文件看作一串字节流它的逻辑结构可以抽象为文件头区、仰角数据块区、可选尾部区。文件头区保存全局信息和各仰角的索引表仰角数据块区里是若干根径向每一根径向都由径向头和数据体组成。径向头里存放的东西通常包括径向序号、方位角、仰角、径向状态码、数据长度、数据压缩标记、时间戳等。数据体则是一组按距离库顺序排列的数值每个库对应一个采样距离。可以把一根径向理解成雷达朝某个方位射出一条射线射线从雷达中心往外按距离均匀取点每个点就是一个库bin。这里有一个关键点数据体里的物理量通常是“原始量化值”不是最终的物理量。比如反射率的原始值可能是0到255之间的整数需要通过公式 Z 原始值 × 缩放因子 偏移量才能得到dBZ速度也是这样原始量化值要乘速度缩放因子再加上偏移量。也就是说解析基数据不只是把二进制读成数字还要做量纲还原。3.2 一个能跑通的最小解析脚本字节按位抠量纲逐步还原下面给一段基于通用假设的Python解析骨架。它不针对某个具体厂商格式而是按“文件头索引表径向头数据体”的常见套路写你拿到自己的文件后把偏移量和长度替换成实际值即可。代码核心思路先读文件头拿到元信息再循环读径向逐段还原。import struct import numpy as np # 假设文件头结构请按实际格式调整偏移量与类型 # 魔数: 8字节, 版本号: 4字节, 径向总数: 4字节, 每径向库数: 4字节 # 径向头长度: 4字节, 数据体长度: 4字节, 全部为小端序 def parse_radar_header(f): f.seek(0) magic f.read(8) # 魔数字节 version, radial_total, bins, radial_header_len, data_len struct.unpack( 5I, f.read(20) ) return { magic: magic, version: version, radial_total: radial_total, bins: bins, radial_header_len: radial_header_len, data_len: data_len, } def parse_radial(f, header): raw f.read(header[radial_header_len]) # 假定径向头里序号2字节, 方位角浮点4字节, 仰角浮点4字节, 状态2字节 seq, az, el, status struct.unpack(HffH, raw[:12]) # 读取数据体 raw_data f.read(header[data_len]) count header[data_len] // 2 # 假设每个库占2字节 quant np.frombuffer(raw_data, dtypeu2, countcount) # 量纲还原反射率因子示例 reflectivity quant.astype(np.float32) * 0.5 - 32.0 return { seq: seq, azimuth: az, elevation: el, status: status, reflectivity: reflectivity, } with open(example_radar.bin, rb) as f: hdr parse_radar_header(f) radial_records [] for i in range(hdr[radial_total]): radial_records.append(parse_radial(f, hdr)) print(f共解析 {len(radial_records)} 根径向)这段代码里struct.unpack的格式串是按小端序逐字段拆字节所有字段的起始位置完全依赖你对文件结构的判断。参数说明如下radial_total决定循环次数radial_header_len决定每根径向跳过多少字节data_len决定每根径向的数据体大小dtypeu2表示无符号16位小端整数如果你遇到的是浮点型数据体需要换成f4。常见做法是先解析第一根径向并打印方位角、仰角和前10个库的数值与厂商软件显示的对应剖面做目视对比。能对上说明结构判断正确对不上优先检查径向头长度是否正确、数据体是否被压缩、字节序是否反了。记住这段代码只是通用骨架真实文件里字段顺序、偏移量几乎必然不同你要做的是把它的每个常数替换成你自己文件头的真实描述替换一次跑一次冒烟测试。3.3 从文件大小反推结构合理性不写代码也能做结构校验解析之前可以先用文件系统层面做一个数学题。假设文件总大小是125829120字节文件头占1024字节径向头占128字节数据体的长度是每个库2字节乘以600个库等于1200字节那么每根径向总长是1328字节。用文件总大小 - 文件头大小除以1328如果结果是个整数或接近整数说明结构猜测对了如果余数很大说明数据体长度算错或者有额外的仰角索引区和填充字节。我一般会把这个除法校验写在解析脚本的最前面作为断言语句文件结构一旦对不上就立即报警而不是等到读完几万根径向后才发现数据全乱。这个方法看起来土实际上能拦截掉绝大多数因版本切换或数据拼接错误导致的问题。另一个可以提前做的校验是检查径向序号是否连续。正常一个体扫文件里径向序号从0递增到总数减一如果中间出现跳号、重复号说明文件被截断或合并过。这个检查也能作为解析脚本的第一道质检门。4. 六个基数据参数确认错一个整卷数据就白处理4.1 字节序、缩放因子和偏移量是三个独立参数别只改一个字节序大小端、缩放因子、偏移量这三个参数是基数据解析中出错率最高的地方。字节序错了解析出来的数值会变成毫无规律的巨大或极小数字表现是整卷数据直接废掉缩放因子错了回波强度的数值范围对不上可能出现负的反射率或者全大于80dBZ的异常偏移量错了物理量整体平移速度场会整体偏正或偏负。我见过最典型的翻车现场某开发者改对了字节序反射率看起来正常但速度场整体大了0.5m/s排查了半天发现是偏移量填错了四分之一。这三个参数必须在同一份文档或同一个配置里维护每次接入新数据源时三者一起来校验。检验方法很简单找一根地物杂波较强的径向看反射率原始值中出现饱和值比如255或4095的比例找零速的静止地物点看速度还原值是否接近0。4.2 仰角层、径向数和库数的读取顺序先定维度还是先定顺序文件头里一般会写明“这个体扫包含多少个仰角层、每层多少根径向、每根径向多少个库”。但要注意这三者的存储顺序在不同格式里差别很大。有的格式按仰角层外部循环即先存第1层的所有径向再存第2层有的格式按径向外部循环径向按方位角连续排列仰角信息写在径向头里。如果存储顺序判断错了解析出来的“仰角层”实际上是把方向角相近但仰角不同的径向混在一起。表现为绘制PPI平面位置显示时同一仰角层的数据出现角度跳变绘制RHIs距离高度显示时剖面出现不连续的“缝”。处理办法是在完整解析之前先看文件索引表或仰角表。多数文件会在文件头或索引区给出“仰角层起始径向号”你提取这些起始号看它们是递增的还是交错的就能判断出存储顺序。有些格式还在文件名里直接标注了“体扫21层”字样这类信息要利用起来。4.3 缺测值和数据质量标记和正常物理量用同一个变量别混在一起当数字算基数据数据体里除了有效观测值还必然存在缺测值、地物杂波标记、超出量程的值。使用者最容易犯的错误是把缺测值当成普通数值参与后续算法运算。比如缺测值常被编码为0而正确的反射率缺测可能是0×8000即32768如果你直接减去偏移量再乘缩放因子就会得到-32到-16之间的“假回波”有的算法甚至会把它当成弱回波参与拼图造成小面积虚假回波。所以解析数据体时一定要先做“原始值→质量标记判定→物理量还原”三步。先判断原始量化值是否等于缺测值、是否等于无效值再决定是否做物理量还原。这一步应该在解析函数里完成而不是在后续的滤波里隐式处理。4.4 径向长度不是一成不变的体扫末尾可能出现短径向或断径向一些雷达在体扫切换到下一仰角层时会写入一根“结束径向”或“状态径向”它的数据体长度可能为0或只有正常径向的一半。如果你在循环里假设所有径向长度一致就会出现文件指针偏移错误导致后续解析全乱。常见的做法是在循环里每次读取径向头后先判断状态码或数据体长度是否为0如果是就直接跳过不重复累加库数。同时文件结构里如果有“本层径向数”“本文件径向数”两套数字要多看一个字段很多业务文件里的“径向总数”是实际径向加结束径向的总和容易让人多循环一次。5. 基数据解析避坑四个典型故障的现象、原因、解决5.1 回波强度整体偏高20dB量纲缩放因子用成了对数尺度现象某一天把一批新接入的雷达基数据解析完之后绘图发现回波强度全场偏高20dB以上连晴天里的地物杂波都显示成40dBZ的强回波雨区更是直接顶到70dBZ。原因排查发现数据体里的原始值本身是“反射率因子Z的线性值”的量化结果不是“分贝值dBZ”的量化结果。解析时直接用了dBZ的缩放因子做还原相当于在线性值和分贝值之间少做了一次对数转换。解决确认公式应该分两步。第一步把原始量化值还原成Z的线性值第二步用10倍的log10转成dBZ。建议解析函数里增加一个数据源配置字段明确标注“原始值类型是dbz还是z”避免下一次再犯。5.2 第一根径向正常后面所有径向逐渐错位径向头长度少算了四个字节现象脚本解析第一根径向时方位角正确但从第二根径向开始方位角数值逐步漂移到第50根径向已经完全对不上径向之间的回波强度分布也变得零碎。原因径向头里除了常规的序号、方位角、仰角、状态码之外还藏着4个字节的保留字段或CRC校验解析代码里没算进去。每读一根径向就少跳过4字节累积到第50根时已经偏了200字节彻底乱套。解决用十六进制编辑器对比第二根径向的实际起点和脚本计算的起点找到差异字节数。然后回看径向头的结构定义把保留字段加进去。这个坑很隐蔽因为第一根径向总是能对上的容易让人误以为结构完全正确。5.3 速度场出现放射状条纹越靠近雷达越密集速度去混叠阈值用错了现象解析反射率正常但速度场图上出现从雷达中心向外放射的条纹像一道道“光芒”近距离条纹密集远距离稀疏且条纹方向与径向一致。原因基数据里的速度值本身可能处于混叠状态。真实的多普勒速度范围由脉冲重复频率决定如果解析时设置的去混叠速度阈值Nyquist速度与实际雷达参数不符将无法正确展开折叠的速度值看起来就是放射状跳变。更常见的是解析环节没错但后续做速度产品时把阈值设成了通用值没有读取文件头中实际的最大速度参数。解决查看基数据文件头里的最大径向速度或模糊速度字段用真实参数做去混叠。若是开发算法先把文件头里的速度范围直接用于所有后续速度处理不要靠人工配置人工配置在不同季节、不同体扫模式下很容易出错。5.4 剖面图出现“拉链”状空隙仰角层顺序被当成连续排列现象做RHI剖面时垂直方向上回波出现一条条水平空隙像拉链没拉上。把某个高度层的回波单独抽出来看发现部分仰角的回波位置整体跳了一层。原因多仰角文件里仰角层顺序并非按仰角从小到大排列而是按扫描时间顺序排列实际仰角值写在每个径向头里。解析时如果直接按文件顺序把每一“层”当作一个固定仰角就会出现仰角值跳变。解决先解析所有径向的仰角值然后按仰角值聚类分组再做层内数据组织。不要依赖文件里“层号”字段除非你能确认它是严格递增的仰角序号而非扫描序号。6. 解析完成之后用开源库交叉验证你的结果是否可信6.1 找一个参考实现把同一文件的解析结果做数值对比手工解析完成后最有效的验证不是自己再读一遍而是找一个靠谱的参考实现做交叉对比。雷达气象领域有一些被广泛使用的开源库能够读取多种通用格式的基数据文件。你不需要把整个库接入业务系统只需要用它读同一个文件然后用差值分析对比两种解析的结果。具体做法是你的解析脚本输出每根径向的方位角数组和反射率数组参考库也输出同样的结构二者做点对点相减统计差值分布。正常情况下差值应为0或者接近浮点精度误差。如果差值有系统性偏移优先检查你的量纲还原公式如果差值呈随机散点状优先检查径向头字段位置是否错位。6.2 不只对比“能对上”还要看“极端值能不能对上”数值对比不能只看常规回波区的匹配情况还要专门看三个地方第一缺测值的位置是否一致双方标记的无效数据是否落在相同库第二最大反射率的位置和数值是否一致尤其那些回波顶附近的边缘点第三速度场的正负分界线是否一致如果两者的速度符号边界差出好几个库说明你的径向序号或方位角排序仍有偏差。我习惯把差值对比做成一个脚本化测试每次接入新数据源时自动跑一遍输出差值分布、最大差值、缺测一致性三项指标超过阈值就报警。这套东西不复杂但能帮你在算法开发阶段省掉一半的排查时间。6.3 交叉验证通过之后再进业务处理管线基数据解析是雷达数据处理链路的最底层这一层出问题上面所有算法都是沙上建塔。所以交叉验证通过不是终点而是进入后续处理的条件。建议在解析模块外面单独做一层“接收入口”统一做文件头校验、径向数校验、缺测比例统计和交叉验证标记记录每份文件的处理状态。这样即使某天接入一批新格式文件也可以通过状态标记快速定位是哪一步出了问题。最后说一个血泪教训别相信“这个文件厂商看一眼就知道格式”这句话。有一次我们接了一台旧雷达的存档数据厂商软件已经无法安装只能对着残留的配置文档手工猜结构连续两天都在改字节序和偏移量最后靠开源库的相似格式文档对照才跑通。那次之后我给自己定了一个规矩任何新格式接入第一天只做结构猜测与文件大小校验第二天才写正式解析代码而且必须在第三天把交叉验证的差值报告发给整个数据处理团队看。这样看起来慢实际是走得最快的一条路希望帮到你。本文还有配套的精品资源点击获取