| | |
| | | import kotlin.math.min |
| | | import kotlin.math.round |
| | | import kotlin.math.sqrt |
| | | import kotlin.time.times |
| | | |
| | | /** |
| | | * 数据平滑预处理 |
| | |
| | | // 均值倍数参数 |
| | | private val xratio = 3 |
| | | |
| | | // 连续数据的合理最大增长倍率 |
| | | private val multiplier = 20 |
| | | |
| | | // 需要处理的因子类型 |
| | | // 需要平滑处理的因子类型 |
| | | private var calTypes = when (deviceType) { |
| | | UWDeviceType.VEHICLE, |
| | | UWDeviceType.UAV, |
| | |
| | | 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>() |
| | | |
| | |
| | | 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) { |
| | |
| | | */ |
| | | fun mDataPrep2(dataPackage: AirDataPackage): List<DataVo> { |
| | | val vo = dataPackage.toDataVo() |
| | | return mDataPrep2(listOf(vo)) |
| | | return mDataPrep2(vo) |
| | | } |
| | | |
| | | /** |
| | | * 实时数据平滑处理 |
| | | */ |
| | | fun mDataPrep2(dataVo: DataVo): List<DataVo> { |
| | | return mDataPrep2(listOf(dataVo)) |
| | | } |
| | | |
| | | /** |
| | |
| | | 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) { |
| | |
| | | // 去除无效值的标准差 |
| | | 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)) |
| | | } |
| | | } |
| | | } |
| | | } |
| | |
| | | break |
| | | } |
| | | } |
| | | return m > multiplier |
| | | return m > FactorType.getMultiplier(airData.factorName) |
| | | } |
| | | } |