高空探测数据处理主要是针对探空观测数据,按照业务要求对数据进行质控、产品生成等。主要包括原始观测数据的初级质控、中心级质控、相关产品生成等。本文涉及到的主要算法实现基于C++11及其STL模版库。
一、数据初级质控
数据初级质控主要是对温度、湿度、气压、海拔高度、经度、纬度、东向风速、北向风速、升速等要素进行极值检查,在极值范围内的保留,超出极值的剔除。
1.1气压极值检查
气压正常范围0~1100hpa,超过此范围的气压数据直接剔除
int QCMethod::pressure_extreme_check(float p)
{
if ((p<0)&&(p>1100))
{
qcode = 2;
}
else
qcode = 0;
return qcode;
}
范围一个标志位,2表示气压极值检查错误,0表示通过,1表示可疑。
1.2温度极值检查
温度受地理位置以及气压高度影响,所以做温度极值检查时同时需要站点纬度以及温度数据的气压高度。
int QCMethod::Tem_extreme_check(float tem,float station_lat,float p)
{
if (station_lat < 45)
{
if ((p>925) && (p<=1000))
{
if ((tem < -55) || (tem>50))
qcode = 2;
else if ((tem < -40) || (tem > 45))
qcode = 1;
else
qcode = 0;
}
if ((p<=925) && (p>850))
{
if ((tem < -65) || (tem>40))
qcode = 2;
else if ((tem < -50) || (tem > 35))
qcode = 1;
else
qcode = 0;
}
if ((p<=850) && (p>700))
{
if ((tem < -85) || (tem>30))
qcode = 2;
else if ((tem < -70) || (tem > 25))
qcode = 1;
else
qcode = 0;
}
if ((p<=700) && (p>500))
{
if ((tem < -95) || (tem>15))
qcode = 2;
else if ((tem < -80) || (tem > 5))
qcode = 1;
else
qcode = 0;
}
if ((p<=500) && (p>400))
{
if ((tem < -100) || (tem>0))
qcode = 2;
else if ((tem < -85) || (tem > -5))
qcode = 1;
else
qcode = 0;
}
if ((p<=400) && (p>300))
{
if ((tem < -100) || (tem>-5))
qcode = 2;
else if ((tem < -85) || (tem > -10))
qcode = 1;
else
qcode = 0;
}
if ((p<=300) && (p>250))
{
if ((tem < -100) || (tem>-5))
qcode = 2;
else if ((tem < -85) || (tem > -10))
qcode = 1;
else
qcode = 0;
}
if ((p<=250) && (p>200))
{
if ((tem < -100) || (tem>-5))
qcode = 2;
else if ((tem < -85) || (tem > -10))
qcode = 1;
else
qcode = 0;
}
if ((p<=200) && (p>150))
{
if ((tem < -100) || (tem>-5))
qcode = 2;
else if ((tem < -90) || (tem > -10))
qcode = 1;
else
qcode = 0;
}
if ((p<=150) && (p>100))
{
if ((tem < -100) || (tem>-5))
qcode = 2;
else if ((tem < -90) || (tem > -10))
qcode = 1;
else
qcode = 0;
}
if ((p<=100) && (p>70))
{
if ((tem < -100) || (tem>5))
qcode = 2;
else if ((tem < -90) || (tem > -5))
qcode = 1;
else
qcode = 0;
}
if ((p<=70) && (p>50))
{
if ((tem < -100) || (tem>5))
qcode = 2;
else if ((tem < -85) || (tem > -5))
qcode = 1;
else
qcode = 0;
}
if ((p<=50) && (p>30))
{
if ((tem < -100) || (tem>5))
qcode = 2;
else if ((tem < -85) || (tem > -5))
qcode = 1;
else
qcode = 0;
}
if ((p<=30) && (p>20))
{
if ((tem < -100) || (tem>5))
qcode = 2;
else if ((tem < -85) || (tem > -5))
qcode = 1;
else
qcode = 0;
}
if ((p<=20) && (p>10))
{
if ((tem < -100) || (tem>5))
qcode = 2;
else if ((tem < -85) || (tem > -5))
qcode = 1;
else
qcode = 0;
}
if ((p<=10) && (p>7))
{
if ((tem < -90) || (tem>20))
qcode = 2;
else if ((tem < -80) || (tem > 10))
qcode = 1;
else
qcode = 0;
}
if ((p<=7) && (p>5))
{
if ((tem < -80) || (tem>30))
qcode = 2;
else if ((tem < -70) || (tem > 15))
qcode = 1;
else
qcode = 0;
}
if ((p<=5) && (p>3))
{
if ((tem < -70) || (tem>35))
qcode = 2;
else if ((tem < -60) || (tem > 25))
qcode = 1;
else
qcode = 0;
}
if ((p<=3) && (p>2))
{
if ((tem < -70) || (tem>40))
qcode = 2;
else if ((tem < -60) || (tem > 30))
qcode = 1;
else
qcode = 0;
}
if ((p<=2) && (p>1))
{
if ((tem < -70) || (tem>40))
qcode = 2;
else if ((tem < -60) || (tem > 30))
qcode = 1;
else
qcode = 0;
}
}
else
{
if ((p>925) && (p<=1000))
{
if ((tem < -90) || (tem>45))
qcode = 2;
else if ((tem < -70) || (tem > 35))
qcode = 1;
else
qcode = 0;
}
if ((p<=925) && (p>850))
{
if ((tem < -90) || (tem>35))
qcode = 2;
else if ((tem < -70) || (tem > 30))
qcode = 1;
else
qcode = 0;
}
if ((p<=850) && (p>700))
{
if ((tem < -90) || (tem>25))
qcode = 2;
else if ((tem < -70) || (tem > 20))
qcode = 1;
else
qcode = 0;
}
if ((p<=700) && (p>500))
{
if ((tem < -100) || (tem>10))
qcode = 2;
else if ((tem < -80) || (tem > 5))
qcode = 1;
else
qcode = 0;
}
if ((p<=500) && (p>400))
{
if ((tem < -100) || (tem>0))
qcode = 2;
else if ((tem < -85) || (tem > -5))
qcode = 1;
else
qcode = 0;
}
if ((p<=400) && (p>300))
{
if ((tem < -100) || (tem>-5))
qcode = 2;
else if ((tem < -85) || (tem > -10))
qcode = 1;
else
qcode = 0;
}
if ((p<=300) && (p>250))
{
if ((tem < -100) || (tem>-5))
qcode = 2;
else if ((tem < -85) || (tem > -10))
qcode = 1;
else
qcode = 0;
}
if ((p<=250) && (p>200))
{
if ((tem < -100) || (tem>-5))
qcode = 2;
else if ((tem < -85) || (tem > -10))
qcode = 1;
else
qcode = 0;
}
if ((p<=200) && (p>150))
{
if ((tem < -100) || (tem>-5))
qcode = 2;
else if ((tem < -90) || (tem > -10))
qcode = 1;
else
qcode = 0;
}
if ((p<=150) && (p>100))
{
if ((tem < -100) || (tem>-5))
qcode = 2;
else if ((tem < -90) || (tem > -10))
qcode = 1;
else
qcode = 0;
}
if ((p<=100) && (p>70))
{
if ((tem < -100) || (tem>5))
qcode = 2;
else if ((tem < -90) || (tem > -5))
qcode = 1;
else
qcode = 0;
}
if ((p<=70) && (p>50))
{
if ((tem < -100) || (tem>5))
qcode = 2;
else if ((tem < -85) || (tem > -5))
qcode = 1;
else
qcode = 0;
}
if ((p<=50) && (p>30))
{
if ((tem < -100) || (tem>5))
qcode = 2;
else if ((tem < -85) || (tem > -5))
qcode = 1;
else
qcode = 0;
}
if ((p<=30) && (p>20))
{
if ((tem < -100) || (tem>5))
qcode = 2;
else if ((tem < -85) || (tem > -5))
qcode = 1;
else
qcode = 0;
}
if ((p<=20) && (p>10))
{
if ((tem < -100) || (tem>5))
qcode = 2;
else if ((tem < -85) || (tem > -5))
qcode = 1;
else
qcode = 0;
}
if ((p<=10) && (p>7))
{
if ((tem < -90) || (tem>20))
qcode = 2;
else if ((tem < -80) || (tem > 10))
qcode = 1;
else
qcode = 0;
}
if ((p<=7) && (p>5))
{
if ((tem < -80) || (tem>30))
qcode = 2;
else if ((tem < -70) || (tem > 15))
qcode = 1;
else
qcode = 0;
}
if ((p<=5) && (p>3))
{
if ((tem < -70) || (tem>35))
qcode = 2;
else if ((tem < -60) || (tem > 25))
qcode = 1;
else
qcode = 0;
}
if ((p<=3) && (p>2))
{
if ((tem < -70) || (tem>40))
qcode = 2;
else if ((tem < -60) || (tem > 30))
qcode = 1;
else
qcode = 0;
}
if ((p<=2) && (p>1))
{
if ((tem < -70) || (tem>40))
qcode = 2;
else if ((tem < -60) || (tem > 30))
qcode = 1;
else
qcode = 0;
}
}
return qcode;
}
温度数据跟观测站点纬度以及数据的气压高度关系较为密切,无法脱离这两个要素单独判断。返回的标志位含义同上。
1.3湿度极值检查
由于实际业务中发现湿度传感器异常情况较多,所以对湿度数据不进行初级质控。
1.4海拔高度极值检查
海拔高度极值检查与观测站点的海拔有密切关系,不能低于观测站海拔,不高于大气层高度。
int QCMethod::Height_extreme_check(float hg,float station_altitude)
{
if ((hg > station_altitude) && (hg < 40000.0))
qcode = 0;
else
qcode = 2;
return qcode;
}
1.5经纬度极值检查
观测数据的经度和纬度应在站点经度的10度范围内,超过这个距离则认为是异常数据。
int QCMethod::Lon_extreme_check(float lon,float station_lon)
{
if (abs(lon-station_lon) < 10)
qcode = 0;
else
qcode = 2;
return qcode;
}
int QCMethod::Lat_extreme_check(float lat,float station_lat)
{
if (abs(lat-station_lat) < 10)
qcode = 0;
else
qcode = 2;
return qcode;
}
1.6东向风速北向风速极值检查
东向风速和北向风速不应超过100m/s。
int QCMethod::esp_extreme_check(float esp){
if (fabsf(esp)>=100)
return 2;
else
return 0;
}
int QCMethod::nsp_extreme_check(float nsp){
if (fabsf(nsp)>=100)
return 2;
else
return 0;
}
1.7升速极值检查
升速不应超过1000m/s
int QCMethod::vsp_extreme_check(float vsp){
if (fabsf(vsp)>1000)
return 2;
else
return 0;
}
解释一下,由于都是使用的float类型的数据,所以在对数据取绝对值时使用的是fabsf()方法,abs()方法是对整形数据取绝对值,这两个方法都在C++标准库中。
下一篇文章介绍比较重要,同时也是比较复杂的中心级质控。