| | |
| | | using IStation.Model; |
| | | using System.ComponentModel; |
| | | using System.ComponentModel.DataAnnotations; |
| | | |
| | | namespace IStation.Test |
| | | { |
| | | /// <summary> |
| | | /// 数据导入 |
| | | /// 根据3倍标准差粗过滤异常数据 |
| | | /// 再用数据用1hz分类,调用修正算法更新出最新的曲线 |
| | | /// 缺失的频率向上取最近的hz相似换算下去 |
| | | /// 现场调度用更新后的曲线调度 |
| | | /// </summary> |
| | | public class Station2Helper |
| | | { |
| | | /// <summary> |
| | |
| | | { |
| | | 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>(); |
| | |
| | | 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); |
| | |
| | | } |
| | | 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 => |
| | |
| | | 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 |
| | |
| | | { |
| | | 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")); |
| | | |
| | | } |
| | | } |
| | | |
| | |
| | | } |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | /* |
| | | |
| | | 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; |
| | | } |
| | | |
| | | |
| | | |
| | | } |
| | | |
| | |
| | | { |
| | | 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 |
| | | } |