feiyu02
7 天以前 594de76ed51fd49fb79b912212bb0052a63e7671
src/main/kotlin/com/flightfeather/uav/model/epw/EPWDataPrep.kt
@@ -12,6 +12,7 @@
import kotlin.math.min
import kotlin.math.round
import kotlin.math.sqrt
import kotlin.time.times
/**
 * 数据平滑预处理
@@ -29,10 +30,7 @@
    // 均值倍数参数
    private val xratio = 3
    // 连续数据的合理最大增长倍率
    private val multiplier = 20
    // 需要处理的因子类型
    // 需要平滑处理的因子类型
    private var calTypes = when (deviceType) {
        UWDeviceType.VEHICLE,
        UWDeviceType.UAV,
@@ -41,6 +39,25 @@
        UWDeviceType.GRID -> WeightType.prepFixed
        else -> WeightType.prepFixed
    }
    // 只需要检查范围和变化幅度的因子类型
    private var rangeTypes = listOf(
        FactorType.PM25.des,
        FactorType.PM10.des,
        FactorType.VOC.des
    )
    // 无需修正的因子类型
    private var noCalTypes = listOf(
        FactorType.TEMPERATURE.des,
        FactorType.HUMIDITY.des,
        FactorType.LNG.des,
        FactorType.LAT.des,
        FactorType.VELOCITY.des,
        FactorType.TIME.des,
        FactorType.WIND_DIRECTION.des,
        FactorType.HEIGHT.des
    )
    private val lastData = mutableListOf<DataVo>()
@@ -66,7 +83,7 @@
                val it = mDataList[i].values?.get(y) ?: continue
                if (!calTypes.contains(it.factorName)) continue
                val vMax = FactorType.getVMax(it.factorName) ?: continue
                val vMax = FactorType.getVMin(it.factorName) ?: continue
                it.factorData ?: continue
                if (it.factorData!! > vMax) {
@@ -132,9 +149,10 @@
            i = 0
        }
        while (i < mDataList.size) {
            // 针对每个监测因子,分别做数据平滑处理
            for (y in mDataList[i].values?.indices ?: 0..0) {
                val it = mDataList[i].values?.get(y) ?: continue
                val vMax = FactorType.getVMax(it.factorName) ?: continue
                val vMax = FactorType.getVMin(it.factorName) ?: continue
                it.factorData ?: continue
                if (it.factorData!! > vMax) {
@@ -151,26 +169,50 @@
                        // 去除无效值的标准差
                        val std = standardDeviation(avg.first, list, it.factorName)
                        // 合理最大值
                        val max = max(avg.first + std * nstd, avg.first + avg.first * xratio)
                        var maxValue = max(avg.first + std * nstd, avg.first + avg.first * xratio)
                        maxValue = max(maxValue, FactorType.getRange(it.factorName)?.second ?: .0)
                        // 合理最小值
                        val min = min(avg.first - std * nstd, avg.first / (1 + xratio))
                        val minValue = min(avg.first - std * nstd, avg.first / (1 + xratio))
                        // 判断监测因子是否需要进行平滑处理,
                        // 若不需要,则判断量级是否在合理范围内以及变化倍率是否在合理范围内
                        if (!calTypes.contains(it.factorName)) {
                            if (isInRange(it) != true || excessiveChange(it) == true) {
                                // 采用计算所得均值代替原始值
                                it.factorData = avg.first
                            }
                        } else {
                        if (calTypes.contains(it.factorName)) {
                            // 数据不处于合理范围并且有效个数达标时,采用计算所得均值代替原始值
                            if (avg.second > max(ncal / 5, 2)
                                && (it.factorData!! < min || it.factorData!! > max)
                                && (it.factorData!! < minValue || it.factorData!! > maxValue)
                            ) {
                                it.factorData = avg.first
                            }
                        }
                        // 判断量级是否在合理范围内以及变化倍率是否在合理范围内
                        else if (rangeTypes.contains(it.factorName)) {
                            if (isInRange(it) != true || excessiveChange(it) == true) {
                                // 采用计算所得均值代替原始值
                                it.factorData = avg.first
                            }
                        }
                    }
                }
            }
            // 根据物理规律,剔除或修正不合理的数据
            val data = mDataList[i]
            // 1. PM2.5 应该始终小于PM10
            val pm25 = data.getFactorData(FactorType.PM25)
            val pm10 = data.getFactorData(FactorType.PM10)
            if (pm25 != null && pm10 != null) {
                // 若pm2.5大于pm10
                if (pm25 >= pm10){
                    val lastIndex = i - 1
                    // 则将pm2.5修改为前一个数据的值
                    if (lastIndex >= 0) {
                        data.setFactorData(FactorType.PM25, mDataList[lastIndex].getFactorData(FactorType.PM25))
                    } else {
                        if (lastData.isEmpty()) {
                            // 没有历史数据时,修改为pm10的80%(后续待优化比例 2026.3.6)
                            data.setFactorData(FactorType.PM25, data.getFactorData(FactorType.PM10)?.times(.8))
                        } else {
                            data.setFactorData(FactorType.PM25, lastData.last().getFactorData(FactorType.PM25))
                        }
                    }
                }
            }
@@ -289,6 +331,6 @@
                break
            }
        }
        return m > multiplier
        return m > FactorType.getMultiplier(airData.factorName)
    }
}