高空探测数据处理主要是针对探空观测数据,按照业务要求对数据进行质控、产品生成等。主要包括原始观测数据的初级质控、中心级质控、相关产品生成等。本文涉及到的主要算法实现基于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++标准库中。

下一篇文章介绍比较重要,同时也是比较复杂的中心级质控。