CE318太阳光度计AOD与水汽反演:质控、定标和交叉验证
简介:面向大气遥感与气溶胶观测的学习者,这份CE318太阳光度计数据处理资料围绕AOD与大气水汽含量wv的反演展开,适合具备一定大气光学基础、希望用C++实现从原始观测到参数计算的读者。压缩包共5个文件,均为cpp源码,整体约9KB,按功能覆盖CE318数据读取、气溶胶光学厚度与水汽含量的对比计算、仪器定标以及角度拟合等环节,可作为课程实验或科研预处理的参考实现。已有1084人学习下载,说明其在同类小众数据处理资料中具有一定参考价值。读者可从中了解观测数据清洗、辐射量比较与反演结果校核的组织方式,并借助源码梳理AOD与wv计算的模块划分、关键参数传递和常见异常处理思路,便于移植到Python或其他分析流程中。包体轻量、主题集中,更适合作为算法原型和代码框架来查阅,而非完整业务系统。
1. 从一台 CE318 的观测文件说起:AOD 和 wv 到底怎么落地
凌晨三点,自动观测站的 CE318 又传回一包 .dat 文件,里面是八个波段、每几分钟一次的太阳直射电压。对做气溶胶和大气水汽的人来说,这些数字真正的价值只有两个:气溶胶光学厚度 AOD,以及整层水汽含量 wv。CE318 的太阳光度计数据看起来门槛不高,无非是电压除以定标常数、取对数、再除以大气质量数,但真要把 AOD 做到能和公开基准产品对上、把 940 nm 通道的水汽反演稳定在可发布水平,中间隔着定标、云筛选、瑞利订正、臭氧订正和查找表系数这几道坎。这篇笔记按我实际处理观测文件的顺序拆:先讲原始数据和 triplet 质量控制,再写 AOD 反演和 Angstrom 指数,然后落到 940 nm 水汽通道,最后把踩过的坑和交叉验证方法摊开。适合手头有 CE318 观测文件、准备自己写处理脚本的同行,也适合刚接手站点数据、需要判断现有流程靠不靠谱的人。
2. 数据预处理:从原始电压到可用的观测量
2.1 先认清 CE318 的测量序列和文件结构
CE318 的一次观测不是单帧,而是一组按时间排列的测量序列。典型文件里包含日期、时间、太阳天顶角、各波段直射电压,以及仪器内部温度、气压等辅助量。不同固件导出的列名和分隔符不一样,常见的是空格或逗号分隔的文本,字段顺序也随版本变化。我一般先做一件事:拿一天的文件,把头十行和尾十行打印出来,确认时间格式、波段顺序、有没有表头、有没有以#开头的注释行。这一步不做,后面列名对不上,AOD 会整列错位,而且错得很隐蔽。
处理之前要把三个辅助量准备好:观测点的气压、臭氧柱总量、日地距离修正因子。气压影响瑞利光学厚度,臭氧影响短波波段,日地距离影响定标常数的换算。CE318 文件里通常有气压字段,但如果没有,就要从站点气象数据补。臭氧可以用当天的卫星或再分析资料,精度不需要极高,但 440 nm 附近不能忽略。日地距离因子按儒略日计算,常见做法是用简化的椭圆轨道公式。这些量不需要手工算,写成函数挂在读取流程后面即可。
另一个容易被忽略的点是时间。CE318 记录的是 UTC 还是本地时间,不同站点配置不同。AOD 反演本身对时间不敏感,但一旦要和公开基准产品逐点对比,时区错一小时就会让匹配失败。我的习惯是读入后先统一转成 UTC,并在数据框里保留原始时间列,方便回溯。时间戳解析用pandas.to_datetime时显式指定utc=True,不要依赖默认本地时区。
2.2 云筛选和 triplet 质量控制
CE318 的 AOD 反演里,云是最大的污染源。薄云会让电压偏高,AOD 偏低;厚云直接让信号饱和或掉零。单帧判断云很难,所以厂家和公开处理流程都用 triplet 方法:连续三次测量作为一个 triplet,三个值之间的变异系数超过阈值就整组丢弃。常见阈值是 1% 到 5%,具体看波段和站点气候。我一般先按 2% 跑一遍,再看剩余数据量;如果剩余太少,再放宽到 5%,但要在日志里注明。
triplet 的实现不复杂:按时间排序,每三条一组,计算每个波段电压的标准差除以均值。注意不是对 AOD 做,而是对原始电压做,因为电压更接近观测值本身。还要处理一种情况:三次测量中间缺了一次,不能硬凑,直接跳过这组。另一个细节是太阳天顶角,太低的太阳高度角对应太大的人气质量数,AOD 误差会被放大,通常把天顶角大于 75° 到 80° 的数据剔掉。这个阈值不要一刀切,低纬度站点可以放到 80°,高纬度冬季可能只能用到 70°。
除了 triplet,还要做电压范围检查。每个波段的定标常数 V0 是已知的,测量电压如果大于 V0 的 1.2 倍,基本可以判定异常;小于 0 或等于 0 的直接丢。这个检查能挡住大部分仪器饱和和遮光问题。做完这两步,剩下的数据才进入 AOD 计算。
2.3 读取与清洗的 Python 实现
下面这段代码假设你已经把原始文件整理成 CSV,列名统一为datetime, airmass, v440, v675, v870, v940, v1020。实际文件列名不同,改rename映射即可。代码里保留了原始时间列,并做了 triplet 标记。
import numpy as np import pandas as pd # 读取已导出的 CSV,原始文件如果是空格分隔,把 sep 改成 r'\s+' df = pd.read_csv("ce318_day.csv", parse_dates=["datetime"]) df["datetime"] = pd.to_datetime(df["datetime"], utc=True) df = df.sort_values("datetime").reset_index(drop=True) # 基本电压检查:负值、零值、超过定标常数 1.2 倍的标记为无效 V0 = {"v440": 12500.0, "v675": 9800.0, "v870": 7600.0, "v940": 6200.0, "v1020": 5400.0} for col, v0 in V0.items(): df[f"{col}_valid"] = (df[col] > 0) & (df[col] < 1.2 * v0) # triplet 质量控制:每三条一组,计算每个波段的变异系数 df["triplet_id"] = np.arange(len(df)) // 3 triplet_stats = df.groupby("triplet_id").agg( n=("datetime", "count"), cv440=("v440", lambda x: x.std() / x.mean() if x.mean() > 0 else np.nan), cv675=("v675", lambda x: x.std() / x.mean() if x.mean() > 0 else np.nan), cv870=("v870", lambda x: x.std() / x.mean() if x.mean() > 0 else np.nan), cv940=("v940", lambda x: x.std() / x.mean() if x.mean() > 0 else np.nan), ) # 只有三条齐全且四个波段变异系数都小于 0.02 的 triplet 保留 good_triplet = triplet_stats[ (triplet_stats["n"] == 3) & (triplet_stats[["cv440", "cv675", "cv870", "cv940"]] < 0.02).all(axis=1) ].index df["triplet_ok"] = df["triplet_id"].isin(good_triplet) # 太阳天顶角筛选:这里用 airmass 反推,airmass > 4 约对应天顶角 75° 以上 df["geometry_ok"] = df["airmass"] < 4.0 df_clean = df[df["triplet_ok"] & df["geometry_ok"]].copy() print(f"原始 {len(df)} 条,清洗后 {len(df_clean)} 条")这段代码的逻辑分三层。第一层是电压合法性,V0是示意值,实际必须换成你仪器定标文件里的数,不能直接抄。第二层是 triplet,按行号每三条一组,要求三条齐全且各波段变异系数小于 0.02;cv计算的是标准差除以均值,均值接近零时返回NaN,避免除零。第三层是几何筛选,airmass < 4.0是经验阈值,对应太阳天顶角大约 75°,低纬度站点可以放到 4.5,高纬度冬季建议收到 3.0。清洗后不要急着算 AOD,先把每个波段剩余数据量打印出来,如果 440 nm 只剩个位数,说明当天云太多或者阈值太严,这份数据不适合做日平均。
3. AOD 反演:Beer-Lambert、定标和 Angstrom 指数
3.1 从电压到光学厚度的公式与定标常数
CE318 测的是太阳直射电压,满足 Beer-Lambert 定律的离散形式:V(λ) = V0(λ) * (d0/d)^2 * exp(-m * τ(λ))。其中V0是定标常数,d0/d是日地距离修正,m是大气质量数,τ是总光学厚度。反解出来就是τ = ln(V0 * (d0/d)^2 / V) / m。总光学厚度里包含气溶胶、瑞利散射、臭氧吸收、二氧化氮吸收,水汽吸收在 940 nm 单独处理,不放进 AOD 波段。要求 AOD,就把非气溶胶项减掉:τ_aer = τ_total - τ_Ray - τ_O3 - τ_NO2。
定标常数V0是整个流程的命门。它通常来自厂家定标文件,也可能来自站点自己做的 Langley 定标。不同仪器、不同波段、不同定标日期,V0都不一样。我见过最常见的翻车是:脚本里硬编码了一组V0,换了一台仪器还在用,AOD 整体偏移 0.05 到 0.1,肉眼看曲线还挺正常,和基准产品一比就露馅。正确做法是把V0放在单独的配置文件里,文件名带仪器序列号和定标日期,脚本启动时校验序列号是否匹配。Langley 定标不是本文重点,但要知道:如果V0是自己拟合的,必须用晴空稳定日、大气质量数跨度足够大的数据,且拟合残差要检查。
日地距离修正因子按观测时刻的儒略日算,常见近似公式是(d0/d)^2 = 1.00011 + 0.034221*cos(g) + 0.00128*sin(g) + 0.000719*cos(2g) + 0.000077*sin(2g),其中g = 2π*(day_of_year-1)/365.25。这个因子在 1 月附近约 1.034,7 月附近约 0.967,量级 3%,对 AOD 的影响在小光学厚度时不能忽略。很多脚本图省事直接取 1,短波波段会带来 0.01 左右的系统偏差。
3.2 气溶胶光学厚度计算与波长插值
AOD 计算按波段逐个做。先算总光学厚度,再减瑞利、臭氧、二氧化氮。瑞利光学厚度用近似公式τ_R = 0.008735 * λ^(-4.08) * P/1013.25,λ单位是微米,P是站点气压。这个公式在 440 到 1020 nm 范围内够用,短波 340 nm 附近误差会大一些,如果做 340 nm 要换更精确的 Bodhaine 参数化。臭氧光学厚度用τ_O3 = k_O3(λ) * ozone_DU / 1000,吸收系数k_O3随波长查表,440 nm 附近约 0.0003 每 DU 量级,675 nm 以上基本可以忽略。二氧化氮在污染站点才需要认真订正,清洁站点可以设零,但要在文档里写明。
下面是一个按波段计算 AOD 的函数,定标常数和系数都从字典传入,不硬编码在公式里。
import numpy as np # 臭氧吸收系数示意,单位:每 DU 的光学厚度,实际用查表值替换 O3_COEF = {440: 0.00032, 675: 0.00004, 870: 0.00001, 1020: 0.00000} def rayleigh_od(wavelength_nm, pressure_hpa): """瑞利光学厚度近似,波长单位 nm,气压单位 hPa""" lam_um = wavelength_nm / 1000.0 return 0.008735 * lam_um ** (-4.08) * pressure_hpa / 1013.25 def no2_od(wavelength_nm, no2_du): """二氧化氮光学厚度,清洁站点可传 0""" # 简化系数,实际按波段查表 coef = {440: 0.00012, 675: 0.00002, 870: 0.00000, 1020: 0.00000} return coef.get(wavelength_nm, 0.0) * no2_du def compute_aod(row, v0, pressure_hpa, ozone_du, no2_du=0.0): """输入一行观测,返回各波段 AOD 字典""" out = {} for wl in [440, 675, 870, 1020]: v = row[f"v{wl}"] if not np.isfinite(v) or v <= 0: out[wl] = np.nan continue # 日地距离修正已在 row 中预先算好,列名 earth_sun_factor tau_total = np.log(v0[f"v{wl}"] * row["earth_sun_factor"] / v) / row["airmass"] tau_aer = (tau_total - rayleigh_od(wl, pressure_hpa) - O3_COEF.get(wl, 0.0) * ozone_du - no2_od(wl, no2_du)) out[wl] = tau_aer return out这段代码里row["earth_sun_factor"]是提前算好的(d0/d)^2,airmass是大气质量数。v0字典必须来自当前仪器的定标文件,pressure_hpa用观测时刻的站点气压,ozone_du用当天臭氧柱总量。O3_COEF和no2_od里的系数只是示意,实际要换成你所用波段宽度和滤光片对应的查表值。函数返回NaN而不是抛异常,是为了让批量处理能继续跑,但事后要统计NaN比例。如果 440 nm 的 AOD 出现负值且绝对值大于 0.05,先别急着当噪声丢,检查定标常数和气压是不是用错了。
3.3 Angstrom 指数与波长依赖的校验
AOD 本身是波长相关的,常用 Angstrom 指数描述这种依赖:τ_aer(λ) = β * λ^(-α),α就是 Angstrom 指数。用 440 nm 和 870 nm 两个波段算:α = -ln(τ440/τ870) / ln(440/870)。α大于 1 通常表示细模态气溶胶占优,小于 0.5 表示粗模态占优,沙尘或海盐场景常见。这个指数不参与水汽反演,但它是检查 AOD 质量的好工具:如果某天α突然从 1.2 掉到 0.1,或者出现负值,大概率是某个波段的定标或云筛选出了问题。
我一般会把α和τ440画成散点图,正常站点会形成一个有物理意义的带状分布,异常点会飘在外面。还有一个检查是波长插值:用 440 和 870 的 AOD 去预测 675 的 AOD,看残差是否在 0.02 以内。如果 675 nm 的残差系统性偏大,可能是 675 波段的定标常数有问题,或者臭氧订正用错了。这些检查不需要额外数据,用已有的三个波段就能做。
Angstrom 指数对水汽反演也有间接影响:940 nm 通道的 AOD 不能直接用来算水汽,但如果你要检查 940 nm 的信号是否合理,可以用α外推一个 940 nm 的 AOD 参考值,和 940 nm 的总光学厚度比,看看水汽吸收项是不是大得离谱。这个技巧在后面水汽章节还会用到。
4. 水汽含量 wv 反演:940 nm 通道的查找表与经验系数
4.1 940 nm 水汽通道的物理基础
940 nm 落在水汽吸收带内,CE318 这个波段的电压同时受气溶胶散射、瑞利散射和水汽吸收影响。水汽反演的核心思路是:先假设 940 nm 的气溶胶光学厚度可以用邻近波段外推,再扣掉瑞利和臭氧,剩下的吸收光学厚度就归给水汽。实际处理里更常用的是经验公式或查找表,因为 940 nm 的滤光片带宽、仪器响应函数和水汽吸收线型都会影响结果,纯解析计算很难做准。
常见做法有两种。第一种是厂家配套软件里的经验公式,形式大致是wv = (1/m) * (ln(V0_940/V_940) / a),有的还带二次项或气压修正。第二种是查找表,用辐射传输模式预先算好不同水汽含量、不同天顶角、不同气溶胶条件下的大气透过率,反演时查表插值。两种方法没有绝对优劣,经验公式快、适合批量,查找表准、但依赖模式输入。我一般先用经验公式跑一版,再用查找表或公开基准产品抽检,偏差超过 10% 就回头查系数。
不管用哪种方法,V0_940都必须来自同一次定标,且不能和 AOD 波段的V0混用。940 nm 的定标常数对水汽反演的影响是系统性的:V0偏 2%,wv 可能偏 5% 以上,因为公式里是取对数后再除以吸收系数,误差会被放大。另一个关键是大气质量数,水汽反演用的大气质量数和水汽吸收的质量数不完全一样,经验公式里通常仍用几何大气质量数,但低太阳高度角时误差明显,所以水汽反演也要做天顶角筛选。
4.2 查找表法和经验公式的实现
下面给一个经验公式的批量实现,包含二次项修正和异常值过滤。公式结构是wv = (1/m) * (ln(V0/V) / a) + b * (ln(V0/V))^2,其中a和b是仪器和波段相关的系数,必须从定标文件或厂家文档里取,代码里的数值只是占位,不能直接用于生产。
import numpy as np def retrieve_wv(row, v0_940, a_coef, b_coef, max_wv=8.0): """ 经验公式反演水汽含量。 row 需要包含:v940, airmass, earth_sun_factor v0_940: 940 nm 定标常数 a_coef, b_coef: 经验系数,来自定标文件 max_wv: 物理上限,超过视为异常 """ v = row["v940"] m = row["airmass"] if not np.isfinite(v) or v <= 0 or m <= 0: return np.nan # 日地距离修正后的等效电压比 ratio = v0_940 * row["earth_sun_factor"] / v if ratio <= 1.0: # 电压高于定标常数,可能是云或仪器异常 return np.nan ln_ratio = np.log(ratio) # 经验公式:一次项加二次项修正 wv = (ln_ratio / a_coef + b_coef * ln_ratio ** 2) / m if not np.isfinite(wv) or wv <= 0 or wv > max_wv: return np.nan return wv代码里ratio <= 1.0的判断很关键:正常情况下V0 * earth_sun_factor应该大于测量电压,因为大气有消光;如果反过来,说明测量电压异常偏高,常见原因是薄云增强了前向散射,或者仪器刚做过定标但常数没更新。max_wv=8.0是经验上限,实际站点水汽很少超过 6 cm,超过 8 基本可以判为异常。a_coef和b_coef的取值因仪器而异,不要抄网上的通用值,去找你仪器最近一次定标报告。如果找不到二次项系数,可以令b_coef=0先用线性项跑,但要在结果里标注方法版本。
批量跑的时候,不要只输出 wv 一列。把ln_ratio、airmass、earth_sun_factor和原始电压一起保留,后面排查异常时能直接看出是哪一项出的问题。我习惯再加一列wv_flag,标记ratio<=1、wv>max_wv、airmass>4等不同原因,统计时按 flag 分组,比只看NaN有用。
4.3 结果对比与异常值处理
水汽反演结果要和至少一种独立来源对比。常见的是公开观测网的 Level 2.0 产品,或者同站点的微波辐射计、探空资料。对比时不能只比日均值,要按时间窗口匹配,比如 ±30 分钟内的均值,否则日变化会被抹平。匹配后算偏差和均方根误差,偏差在 10% 以内、均方根误差在 0.3 cm 以内,一般可以接受;如果偏差是系统性的,优先查V0_940和吸收系数;如果误差是随机的,查云筛选和天顶角阈值。
异常值处理要克制。水汽在时间序列上连续变化,突然出现一个 0.2 cm 或 7 cm 的点,大概率是云或仪器问题,可以直接丢。但如果连续几个小时都偏低,不要逐点丢,先看是不是气压或臭氧订正用了常数、实际当天变化较大。还有一种情况是 940 nm 电压接近饱和,ln_ratio很小,反演出的 wv 接近零,这种点会被wv<=0过滤掉,但过滤比例高的时候要检查是不是仪器增益设置不对。
5. 避坑与排查:AOD 和 wv 反演里最容易翻车的五件事
5.1 定标常数用错,整条曲线偏移
现象:AOD 时间序列形状正常,但和基准产品比整体偏高或偏低 0.05 以上,Angstrom 指数也偏得不多。原因通常是V0用了别的仪器、别的定标日期,或者日地距离因子没乘。解决:把V0从脚本里挪到配置文件,文件名带序列号和定标日期,启动时校验;日地距离因子单独写函数,单元测试用一个已知日期对一遍。我现在的习惯是每次换仪器先跑一天数据,和基准产品比日均值,偏差超过 0.02 就不往下做。
5.2 triplet 阈值一刀切,晴空数据被误杀
现象:清洗后数据量骤减,尤其是冬季或高纬度站点,剩下不到原始量的 10%。原因是变异系数阈值 0.02 对低信号波段太严,或者三条测量里有一条缺测被整组丢掉。解决:按波段设不同阈值,440 nm 可以严一点,1020 nm 放宽到 0.05;缺测的 triplet 不要硬凑,但可以标记后单独评估。另一个办法是先按天统计剩余率,连续多天低于 20% 就回头检查阈值,不要直接认为天气差。
5.3 水汽公式漏了二次项或气压修正
现象:wv 在低水汽时和基准产品对得上,高水汽时系统性偏低,偏差随 wv 增大而增大。原因是经验公式只用了线性项,高水汽时吸收饱和,线性近似不够。解决:找定标报告里的二次项系数,没有就改用查找表;同时检查气压修正,有些公式里的m需要乘P/1013.25。如果二次项系数来源不明,宁可不加,也不要用网上抄来的通用值,否则低水汽段会被带偏。
5.4 时间戳时区错位,匹配全失败
现象:AOD 和 wv 自身看着正常,但和基准产品按时间匹配后一条都对不上,或者匹配上的都是错误时段。原因是原始文件用本地时间,脚本按 UTC 解析,差了几个小时。解决:读入时保留原始时间字符串,显式转换时区,输出文件里同时写 UTC 和本地时间两列;匹配前先打印前五条时间戳,和基准产品对一眼。这个坑不复杂,但一旦发生,排查成本很高,因为数据本身没错,错的是索引。
5.5 把云污染当晴空,AOD 偏低 wv 偏高
现象:AOD 出现不合理的低值,同时 wv 偏高,Angstrom 指数跳变。原因是薄云增强了 940 nm 的前向散射,电压偏高,ln_ratio偏小,wv 反而被算大;AOD 波段电压偏高则让 AOD 偏低。解决:除了 triplet,再加一道“相邻波段一致性”检查,用 440、675、870 的 AOD 拟合 Angstrom 指数,残差超过 0.05 的整组标记;水汽那边检查ratio是否接近 1,接近 1 的直接丢。云筛选没有万能阈值,只能多层过滤加人工抽检。
6. 从单站到批量:用公开基准产品做交叉验证和自动化
单站跑通只是第一步,真正要拿这份数据处理长期观测,得把批量脚本和交叉验证固定下来。我的做法是每天定时跑前一天的文件,输出三张表:清洗后的观测表、AOD 表、wv 表,每张表都带质量标记和版本号。版本号不是形式主义,定标常数、系数、阈值任何一项改了都要升版本,否则半年后回头看,根本分不清哪批结果用的是什么参数。批量脚本里加一个config.yaml,把仪器序列号、定标日期、V0字典、triplet 阈值、天顶角上限、水汽系数全写进去,脚本启动时打印配置摘要,日志里留一份。
交叉验证我一般按周做,不按天。按天做容易被个别云污染点带偏,按周看偏差和趋势更稳。匹配窗口用 ±30 分钟,先把基准产品的时间转成 UTC,再按最近邻匹配,匹配不上就跳过,不要插值。对比指标至少看三个:平均偏差、均方根误差、相关系数。AOD 的相关系数低于 0.95 就要查,水汽的均方根误差大于 0.4 cm 就要查。查的顺序是:先看时间匹配数量,再看异常点分布,最后才动公式。很多时候问题不在公式,在匹配和筛选。
下面是一个批量交叉验证的骨架,重点在匹配和统计,不在绘图。
import pandas as pd import numpy as np def match_nearest(df_a, df_b, time_col="datetime", tolerance="30min"): """按最近时间匹配两个数据框,返回匹配后的合并表""" df_a = df_a.sort_values(time_col).copy() df_b = df_b.sort_values(time_col).copy() df_a[time_col] = pd.to_datetime(df_a[time_col], utc=True) df_b[time_col] = pd.to_datetime(df_b[time_col], utc=True) matched = pd.merge_asof( df_a, df_b, on=time_col, direction="nearest", tolerance=pd.Timedelta(tolerance), suffixes=("_mine", "_ref") ) return matched.dropna(subset=["AOD440_ref"]) def summary_stats(matched, col_mine, col_ref): """计算偏差、均方根误差、相关系数""" x = matched[col_mine].astype(float) y = matched[col_ref].astype(float) mask = np.isfinite(x) & np.isfinite(y) x, y = x[mask], y[mask] bias = (x - y).mean() rmse = np.sqrt(((x - y) ** 2).mean()) corr = np.corrcoef(x, y)[0, 1] if len(x) > 2 else np.nan return {"n": len(x), "bias": bias, "rmse": rmse, "corr": corr}pd.merge_asof要求两个表都按时间排序,direction="nearest"是最近邻,tolerance="30min"控制最大允许间隔。匹配后一定要看n,如果一周只剩几十个点,先别分析偏差,回去查时间格式和筛选阈值。summary_stats里先做有限值过滤,避免NaN污染统计。这个骨架不绘图,但输出可以直接写进日志或周报。我的习惯是每周一早上跑一遍上周的匹配,把n、bias、rmse、corr四列贴在一张表里,连续几周bias漂移就说明定标或系数该更新了。
还有一个小技巧:把 AOD 和 wv 的交叉验证结果按天气类型分组,晴天、薄云、沙尘各看一遍。整体指标好看不代表每种场景都对,沙尘天的 Angstrom 指数低,水汽反演的云筛选阈值可能偏松,分组之后问题更容易暴露。从那以后我每次换定标常数,都强制走一遍“单日对比 → 周统计 → 分组检查”这三步,不再只看一条时间序列顺眼就发布。希望帮到你。
本文还有配套的精品资源,点击获取