ningshuxia
2025-04-16 a67da735b33be01b24845ce03ae7551cf55ddbbc
02-desktop/Desktop/IStation.Test/Station2Helper.cs
@@ -1,9 +1,15 @@
using IStation.Model;
using System.ComponentModel;
using System.ComponentModel.DataAnnotations;
namespace IStation.Test
{
    /// <summary>
    /// 数据导入
    /// 根据3倍标准差粗过滤异常数据
    /// 再用数据用1hz分类,调用修正算法更新出最新的曲线
    /// 缺失的频率向上取最近的hz相似换算下去
    /// 现场调度用更新后的曲线调度
    /// </summary>
    public class Station2Helper
    {
        /// <summary>
@@ -13,18 +19,18 @@
        {
            var projectId = 661070185922629;
            IStation.SettingsD.Project.ID = projectId;
            var monitorDataSourcesId = 606203941007429;
            var monitorDataSourcesId = 663976941449285;//2024-202504
            var stationIndex = 2;
            var stationId = 462958422204485;
            var dtStart = new DateTime(2024, 1, 1);
            var dtEnd = new DateTime(2025, 1, 1);
            var dtEnd = new DateTime(2025, 5, 1);
            var bll = new BLL.StationSignalRecordPacket();
            var bllEquipment = new BLL.Equipment();
            var bllCurve = new BLL.PumpCurve();
            var pumpList = bllEquipment.GetPumpListByBelongTypeAndBelongID(IStation.ObjectType.Station, stationId);
            var pumpList = bllEquipment.GetPumpModelListByBelongTypeAndBelongID(IStation.ObjectType.Station, stationId);
            var flagList = pumpList.Select(x => x.SortCode).OrderBy(x => x).ToList();
            var flagPumpDict = pumpList.ToDictionary(x => x.SortCode, x => x.RatedParas);
            var flagQhCurveDict = new Dictionary<int, Model.CurveExpress>();
@@ -44,10 +50,7 @@
            var pipe_pressure_id_list = GlobalHelperW.GetPipePressureIdList(stationIndex);
            var packet_list = bll.Get(monitorDataSourcesId, stationId);
            //packet_list = packet_list.Where(x => (x.Year >= dtStart.Year && x.Year <= dtEnd.Year) && (x.Month >= dtStart.Month && x.Month <= dtEnd.Month)).ToList();
            //if (packet_list == null || !packet_list.Any())
            //    return;
            var allStationRecordList = packet_list.SelectMany(x => x.StationSignalRecords).ToList();
            Console.WriteLine($"泵站总数:{allStationRecordList.Count}");
            var stationRecordList = DynamicThresholdProcessorHelper.Filter(allStationRecordList);
@@ -72,16 +75,12 @@
                }
                return true;
            }).ToList();
            Console.WriteLine($"泵站总数:{stationRecordList2.Count} 二次过滤:{allStationRecordList.Count - stationRecordList2.Count}");
            Console.WriteLine($"泵站总数:{stationRecordList2.Count} 二次过滤:{allStationRecordList.Count - stationRecordList2.Count}");
            var allPumpRecordList = stationRecordList2.SelectMany(x => x.PumpSignalRecords).ToList();
            Console.WriteLine($"泵总数:{allPumpRecordList.Count}");
            var fullPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "pumpcsv");
            if (Directory.Exists(fullPath))
            {
                Directory.Delete(fullPath, true);
            }
            var fullPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "pumpcsv");
            Directory.CreateDirectory(fullPath);
            var allPumpRecordList2 = allPumpRecordList.Where(x =>
@@ -116,9 +115,10 @@
                    pumpFlagHzRecordGroup.Add((flag, 50), flagHzRecordList);
                    if (flagHzRecordList.Any())
                    {
                        var curvePtList =pumpQh.GetFitPoints(200).Select(x => new CurvePtViewModel(x)).ToList();
                        var curvePtList = pumpQh.GetFitPoints(200).Select(x => new CurvePtViewModel(x)).ToList();
                        CsvHelper.ExportToCsv(curvePtList, Path.Combine(fullPath, $"{flag}_{50}_old_curve.csv"));
                        CsvHelper.ExportToCsv(flagHzRecordList, Path.Combine(fullPath, $"{flag}_{50}.csv"));
                        CsvHelper.ExportToCsv(flagHzRecordList.Select(x=>new CurvePtViewModel(x.FlowRate,x.Head)), Path.Combine(fullPath, $"{flag}_{50}.csv"));
                    }
                }
                else
@@ -127,30 +127,28 @@
                    {
                        return Math.Round(x.Rpm / pump.Nr * 50, 0);
                    });
                    hzGroup= hzGroup.Where(x=>x.Key>10).ToList();
                    hzGroup = hzGroup.Where(x => x.Key > 10).ToList();
                    foreach (var pumpFlagHz in hzGroup)
                    {
                        var hz = pumpFlagHz.Key;
                        var allFlagHzRecordList = pumpFlagHz.ToList();
                        //var allFlagHzRecordList = pumpFlagHz.Where(x=>x.Frequency!=IStation.Error.Default).ToList();
                        //if (allFlagHzRecordList == null || !allFlagHzRecordList.Any())
                        //{
                        //    Console.WriteLine($"{flag}泵-{hz}hz p 跳过");
                        //    continue;
                        //}
                        if (allFlagHzRecordList.Count < 30)
                        {
                            Console.WriteLine($"{flag}泵-{hz}hz 总数:{allFlagHzRecordList.Count},<5 跳过");
                        }
                        var flagHzRecordList = DynamicThresholdProcessorHelper.Filter(allFlagHzRecordList);
                        if (allFlagHzRecordList.Count < 30)
                        {
                            Console.WriteLine($"{flag}泵-{hz}hz 过滤后总数:{allFlagHzRecordList.Count},<5 跳过");
                        }
                        Console.WriteLine($"{flag}泵-{hz}hz 总数:{allFlagHzRecordList.Count},过滤:{allFlagHzRecordList.Count - flagHzRecordList.Count}");
                        pumpFlagHzRecordGroup.Add((flag, (int)hz), flagHzRecordList);
                        if (flagHzRecordList.Any())
                        {
                            var curvePtList = SimilarCalculateHelper.CalculateQH(pumpQh, 50, hz).GetFitPoints(100).Select(x => new CurvePtViewModel(x)).ToList();
                            CsvHelper.ExportToCsv(curvePtList, Path.Combine(fullPath, $"{flag}_{hz}_old_curve.csv"));
                            CsvHelper.ExportToCsv(flagHzRecordList, Path.Combine(fullPath, $"{flag}_{hz}.csv"));
                        {
                            var curvePtList = SimilarCalculateHelper.CalculateQH(pumpQh, 50, hz).GetFitPoints(100);
                            CsvHelper.ExportToCsv(curvePtList.Select(x => new CurvePtViewModel(x)).ToList(), Path.Combine(fullPath, $"{flag}_{hz}_old_curve.csv"));
                            CsvHelper.ExportToCsv(flagHzRecordList.Select(x => new CurvePtViewModel(x.FlowRate, x.Head)), Path.Combine(fullPath, $"{flag}_{hz}.csv"));
                        }
                    }
@@ -159,195 +157,11 @@
            }
            /*
                   var vm_list = new List<PumpViewModel>();
                   foreach (var group in pumpFlagHzRecordGroup)
                   {
                       var flag = group.Key.Flag;
                       var hz = group.Key.Hz;
                       var pump = flagPumpDict[flag];
                       var curve_qh = flagQhCurveDict[flag];
                       foreach (var pump_record in group.Value)
                       {
                           var vm_pump = new PumpViewModel();
                           vm_pump.Flag = flag;
                           vm_pump.Rpm = pump_record.Rpm;
                           vm_pump.Hz = hz;
                           vm_pump.Hz0 = hz;
                           vm_pump.WaterLevel = pump_record.WaterLevel;
                           vm_pump.InletPressure = Math.Round(Model.CurveCalcuHelper.Mpa2M(pump_record.InletPressure), 2);
                           vm_pump.OutletPressure = Math.Round(Model.CurveCalcuHelper.Mpa2M(pump_record.OutletPressure), 2);
                           vm_pump.PressureDiff = Math.Round(vm_pump.OutletPressure - vm_pump.InletPressure, 5);
                           vm_pump.Flow = pump_record.FlowRate;
                           vm_pump.Head = pump_record.Head;
                           vm_pump.Power = pump_record.InstantaneousPower;
                           var curve_head = GetCurveHead(curve_qh, pump.Nr, pump_record.Rpm, pump_record.FlowRate);
                           curve_head = Math.Round(curve_head, 2);
                           var pump_head50hz = Model.CurveCalcuHelper.Calculate50HByHz(vm_pump.Head, hz);
                           var curve_head50hz = Model.CurveCalcuHelper.Calculate50HByHz(curve_head, hz);
                           var head_diff = pump_head50hz - curve_head50hz;
                           head_diff = Math.Round(head_diff, 5);
                           vm_pump.CurveHead = curve_head;
                           vm_pump.HeadDiff = head_diff;
                           vm_list.Add(vm_pump);
                       }
                   }
                   var vm_pump_facotr_list = new List<PumpFactorViewModel>();
                   foreach (var station_record in stationRecordList2)
                   {
                       var pump_signal_records = station_record.PumpSignalRecords;
                       pump_signal_records = pump_signal_records.OrderBy(x => x.Flag).ToList();
                       foreach (var pump_record in pump_signal_records)
                       {
                           if (pump_record.Rpm == IStation.Error.Default || pump_record.Head == IStation.Error.Default)
                           {
                               continue;
                           }
                           var flag = pump_record.Flag;
                           var pump = flagPumpDict[flag];
                           var curve_qh = flagQhCurveDict[flag];
                           if (!pump.IsBp)
                           {
                               pump_record.Rpm = pump.Nr;
                           }
                           var hz = pump_record.Rpm / pump.Nr * 50;
                           hz = Math.Round(hz, 1);
                           var vm_pump = new PumpViewModel();
                           vm_pump.Time = station_record.Time.ToString("G");
                           vm_pump.Flag = flag;
                           vm_pump.Rpm = pump_record.Rpm;
                           vm_pump.Hz = hz;
                           vm_pump.Hz0 = Math.Round(hz, 0);
                           vm_pump.WaterLevel = pump_record.WaterLevel;
                           vm_pump.InletPressure = Math.Round(Model.CurveCalcuHelper.Mpa2M(pump_record.InletPressure), 2);
                           vm_pump.OutletPressure = Math.Round(Model.CurveCalcuHelper.Mpa2M(pump_record.OutletPressure), 2);
                           vm_pump.PressureDiff = Math.Round(vm_pump.OutletPressure - vm_pump.InletPressure, 5);
                           vm_pump.Flow = pump_record.FlowRate;
                           vm_pump.Head = pump_record.Head;
                           vm_pump.Power = pump_record.InstantaneousPower;
                           var curve_head = GetCurveHead(curve_qh, pump.Nr, pump_record.Rpm, pump_record.FlowRate);
                           curve_head = Math.Round(curve_head, 2);
                           var pump_head50hz = Model.CurveCalcuHelper.Calculate50HByHz(vm_pump.Head, hz);
                           var curve_head50hz = Model.CurveCalcuHelper.Calculate50HByHz(curve_head, hz);
                           var head_diff = pump_head50hz - curve_head50hz;
                           head_diff = Math.Round(head_diff, 5);
                           vm_pump.CurveHead = curve_head;
                           vm_pump.HeadDiff = head_diff;
                           vm_list.Add(vm_pump);
                       }
                   }
                   if (!vm_list.Any())
                   {
                       return;
                   }
                   var flag_hz_head_diff_list = vm_list.Select(x => new Tuple<int, double, double>(x.Flag, x.Hz0, x.HeadDiff)).ToList();
                   var list = AnalysisHelper.GetAnalysisFactorDtoList(flagPumpDict, flag_hz_head_diff_list);
                   foreach (var item in list)
                   {
                       var vm_pump_facotr = new PumpFactorViewModel();
                       vm_pump_facotr.Flag = item.Flag;
                       vm_pump_facotr.Hz = item.Hz;
                       vm_pump_facotr.STDP = item.HeadSTDP;
                       vm_pump_facotr.STDPHead = item.HeadDeviation;
                       vm_pump_facotr.Note = $"{item.Accuracy == -1}";
                       vm_pump_facotr.Round();
                       vm_pump_facotr_list.Add(vm_pump_facotr);
                   }
                   var group_by_flag = vm_list.GroupBy(x => new { x.Flag, x.Hz0 });
                   foreach (var flag_item in group_by_flag)
                   {
                       var flag = flag_item.Key.Flag;
                       var factor = vm_pump_facotr_list?.Find(x => x.Flag == flag && x.Hz == flag_item.Key.Hz0);
                       if (factor == null)
                       {
                           continue;
                       }
                       var pump = flagPumpDict[flag];
                       var qh = flagQhCurveDict[flag];
                       var qh_correct_points = qh.DefinePoints.Select(x => new Model.CurvePoint(x.X, x.Y + factor.STDPHead ?? 0)).ToList();
                       var qh_correct = Model.FitCurveHelper.BuildCurveExpress(qh_correct_points, Model.eCurveFitType.CubicCurve);
                       foreach (var vm in flag_item)
                       {
                           vm.CorrectCurveHead = GetCurveHead(qh_correct, pump.Nr, vm.Rpm, vm.Flow);
                           vm.CorrectHeadDiff = vm.Head - vm.CorrectCurveHead;
                           vm.CorrectCurveHead = Math.Round(vm.CorrectCurveHead, 2);
                           vm.CorrectHeadDiff = Math.Round(vm.CorrectHeadDiff, 5);
                           vm.CorrectPressureDiff = vm.CorrectCurveHead - Model.CurveCalcuHelper.CalculateOtherPress(vm.Flow, pump.Ic, pump.Oc, null, null);
                           vm.CorrectPressureDiffDiff = vm.CorrectPressureDiff - vm.PressureDiff;
                           vm.CorrectPressureDiff = Math.Round(vm.CorrectPressureDiff, 2);
                           vm.CorrectPressureDiffDiff = Math.Round(vm.CorrectPressureDiffDiff, 5);
                       }
                   }*/
            //CsvHelper.ExportToCsv(vm_list, "PumpData.csv");
            //CsvHelper.ExportToCsv(vm_pump_facotr_list, "PumpFacotrData.csv");
        }
        private static Tuple<double[], double> FilterBySTDP(double[] array, double min_dev, int count)
        {
            if (array == null || !array.Any())
            {
                return default;
            }
            var array_avg = array.Average();
            var array_count = array.Count();
            FilterOutliersHelper.STDEV(array, out double std_dev, out double std_dev_pop);
            if (Math.Abs(std_dev_pop) < min_dev)
            {
                return new Tuple<double[], double>(array, std_dev_pop);
            }
            if (count > 3)
            {
                return new Tuple<double[], double>(array, std_dev_pop);
            }
            var filter_array = array.Where(x => !(Math.Abs(x - array_avg) > Math.Abs(std_dev_pop * 2))).ToArray();
            if (filter_array == null || !filter_array.Any())
            {
                return default;
            }
            count++;
            return FilterBySTDP(filter_array, min_dev, count);
        }
        private static double GetCurveHead(Model.CurveExpress curve_qh, double nr, double rpm, double flow)
        {
            if (curve_qh == null)
                return default;
            var similar_qh = Model.CurveCalcuHelper.CalculateSimilarQH(curve_qh, nr, rpm);
            if (similar_qh == null)
                return default;
            var head = similar_qh.GetFitPointY(flow);
            return head;
        }
    }
@@ -359,104 +173,21 @@
    {
        public CurvePtViewModel() { }
        public CurvePtViewModel(CurvePoint rhs)
        {
            this.X = rhs.X;
            this.Y = rhs.Y;
        {
            X = Math.Round(rhs.X, 6);
            Y = Math.Round(rhs.Y, 6);
        }
        public CurvePtViewModel(double x, double y)
        {
            X = x;
            Y = y;
        }
        [Display(Name = "X")]
        public double X { get; set; }
        [Display(Name = "Y")]
        public double Y { get; set; }
    }
    public class PumpViewModel
    {
        [Display(Name = "泵")]
        public int Flag { get; set; }
        [Display(Name = "转速")]
        public double Rpm { get; set; }
        [Display(Name = "频率")]
        public double Hz { get; set; }
        [Display(Name = "频率")]
        public double Hz0 { get; set; }
        [Display(Name = "水位")]
        public double WaterLevel { get; set; }
        [Display(Name = "进口压力")]
        public double InletPressure { get; set; }
        [Display(Name = "出口压力")]
        public double OutletPressure { get; set; }
        [Display(Name = "压差")]
        public double PressureDiff { get; set; }
        [Display(Name = "瞬时流量")]
        public double Flow { get; set; }
        [Display(Name = "扬程")]
        public double Head { get; set; }
        [Display(Name = "瞬时功率")]
        public double Power { get; set; }
        [Display(Name = "曲线扬程")]
        public double CurveHead { get; set; }
        [Display(Name = "扬程差值")]
        public double HeadDiff { get; set; }
        [Display(Name = "修正曲线扬程")]
        public double CorrectCurveHead { get; set; }
        [Display(Name = "修正扬程差值")]
        public double CorrectHeadDiff { get; set; }
        [Display(Name = "修正压差")]
        public double CorrectPressureDiff { get; set; }
        [Display(Name = "修正压差差值")]
        public double CorrectPressureDiffDiff { get; set; }
    }
    public class PumpFactorViewModel
    {
        [Display(Name = "泵")]
        public int Flag { get; set; }
        [Display(Name = "频率")]
        public double Hz { get; set; }
        [Display(Name = "总体标准差")]
        public double? STDP { get; set; }
        [Display(Name = "扬程(STDP)")]
        public double? STDPHead { get; set; }
        [Display(Name = "备注")]
        public string Note { get; set; }
        public void Round()
        {
            if (STDP.HasValue)
            {
                STDP = Math.Round(STDP.Value, 5);
            }
            if (STDPHead.HasValue)
            {
                STDPHead = Math.Round(STDPHead.Value, 5);
            }
        }
    }
    #endregion
}