ningshuxia
2025-04-01 ea7b317c22ecb371910373b4d20f6bac3ad47738
WinFrmUI/PBS.WinFrmUI.Hydro/05-system-curve/02-chart/SystemCurveChartCtrl.cs
@@ -1,5 +1,7 @@
using DevExpress.Utils;
using DevExpress.CodeParser;
using DevExpress.Utils;
using DevExpress.XtraCharts;
using System.Linq;
using Yw.WinFrmUI.Phart;
namespace PBS.WinFrmUI.Hydro
@@ -156,20 +158,39 @@
            foreach (var item in waterPointGroup)
            {
                var x = item.Key;
                var yList = item.Select(x => x.EndPressure).OrderBy(x => x).ToList();
                var list = item.Select(t => new Yw.Geometry.Point2d(x, t.EndPressure)).ToList();
                var yUpper = CalculatePercentile(yList, 0.95);
                var yLower = CalculatePercentile(yList, 0.05);
                var yNumList = yList.Where(x => x >= yLower && x <= yUpper);
                if (yNumList == null || !yNumList.Any())
                //var yList = item.Select(x => x.EndPressure).OrderBy(x => x).ToList();
                //var yUpper = CalculatePercentile(yList, 0.95);
                //var yLower = CalculatePercentile(yList, 0.05);
                //var yNumList = yList.Where(x => x >= yLower && x <= yUpper);
                //if (yNumList == null || !yNumList.Any())
                //{
                //    continue;
                //}
                //var yAverage = yNumList.Where(x => x >= yLower && x <= yUpper).Average();
                //upperPressurePtList.Add(new Yw.Geometry.Point2d(x, yUpper));
                //lowerPressurePtList.Add(new Yw.Geometry.Point2d(x, yLower));
                //averagePressurePtList.Add(new Yw.Geometry.Point2d(x, yAverage));
                var fList = DynamicThresholdProcessor.FilterWithDynamicSigma(list);
               // var fList = FilterByStdDev(list);
                if (fList == null || !fList.Any())
                {
                    continue;
                }
                var yAverage = yNumList.Where(x => x >= yLower && x <= yUpper).Average();
                var yUpper = fList.Max(x => x.Y);
                var yLower = fList.Min(x => x.Y);
                var yAverage = fList.Average(x => x.Y);
                upperPressurePtList.Add(new Yw.Geometry.Point2d(x, yUpper));
                lowerPressurePtList.Add(new Yw.Geometry.Point2d(x, yLower));
                averagePressurePtList.Add(new Yw.Geometry.Point2d(x, yAverage));
            }
            if (averagePressurePtList.Count > 4)
@@ -226,6 +247,48 @@
            return sortedData[lower] * (1 - fraction) + sortedData[upper] * fraction;
        }
        public List<Yw.Geometry.Point2d> FilterByStdDev(List<Yw.Geometry.Point2d> group)
        {
            var filteredData = new List<Yw.Geometry.Point2d>();
            // 小样本数据不处理(阈值设为10)
            if (group.Count() < 3)
            {
                filteredData.AddRange(group);
                return default;
            }
            // 计算统计量
            var pressures = group.Select(p => p.Y).ToList();
            double mean = pressures.Average();
            double stdDev = CalculateSampleStdDev(pressures); // 样本标准差
            // 设置3σ边界[1,3,4](@ref)
            double lowerBound = mean - 3 * stdDev;
            double upperBound = mean + 3 * stdDev;
            // 过滤异常值
            filteredData.AddRange(
                group.Where(p => p.Y >= lowerBound && p.Y <= upperBound)
            );
            return filteredData;
        }
        // 样本标准差计算(n-1)[7,8](@ref)
        private double CalculateSampleStdDev(List<double> values)
        {
            if (values.Count < 2) return 0;
            double mean = values.Average();
            double sumSquares = values.Sum(v => Math.Pow(v - mean, 2));
            return Math.Sqrt(sumSquares / (values.Count - 1));
        }
        #region Set Axis