/// <summary> /// возвращает относительные среднемесячные скорости по месяцам для многолетнего ряда /// </summary> /// <param name="range"></param> /// <param name="allMonth">истина, если в ряде представлены не все месяцы года</param> /// <returns></returns> private static Dictionary <Months, double> getRelativeAverageMonthSpeeds(RawRange range, out bool allMonth) { double rAverage = range.Average((item) => { return(item.Speed); }); //средняя скорость во всем ряде на МС Dictionary <Months, double> msRelatives = new Dictionary <Months, double>(); //относительные скорости по месяцам на МС allMonth = true; for (int m = 1; m <= 12; m++) { Months month = (Months)m; double mAverage = double.NaN; var r = from t in range where t.Date.Month == m select t.Speed; if (r.Count() == 0) { allMonth = false; mAverage = 0; } else { mAverage = r.Average(); } msRelatives.Add(month, mAverage / rAverage);//относительная скорость = среднемесячная скорость / средняя скорость ряда } return(msRelatives); }
/// <summary> /// возвращает отклонение повторямости скорости от среднемноголетней /// </summary> /// <param name="range"></param> /// <param name="totalRange"></param> /// <returns></returns> private static double getExpectancyDeviation(RawRange range, RawRange totalRange) { StatisticalRange <GradationItem> exp = GetExpectancy(totalRange, Vars.Options.CurrentSpeedGradation); double averSpeed = totalRange.Average((t) => t.Speed); DeviationsInfo dinfo = ProcessRangeDeviations(range, averSpeed, exp); return(dinfo.ExpDeviation); }
/// <summary> /// расчёт отклонений от заданных многолетних значений /// </summary> /// <param name="r">ряд за небольшой промежуток (год)</param> /// <param name="averSpeed">среднемноголетняя скорость</param> /// <param name="exp">многолетняя повторяемость скорости ветра</param> /// <returns></returns> internal static DeviationsInfo ProcessRangeDeviations(RawRange r, double averSpeed, StatisticalRange <GradationItem> exp) { DeviationsInfo res = new DeviationsInfo(); double aver = r.Average((t) => t.Speed); res.SpeedDeviation = Math.Abs(aver - averSpeed); StatisticalRange <GradationItem> th = GetExpectancy(r, Vars.Options.CurrentSpeedGradation); res.ExpDeviation = Math.Sqrt(exp.Values.Zip(th.Values, (a, b) => Math.Pow(a - b, 2)).Aggregate((x, y) => x + y)); //корень из суммы квадратов разностей повторяемостей многолетней и этого промежутка return(res); }
/// <summary> /// сохранение ВЭК /// </summary> /// <param name="filename"></param> /// <param name="range"></param> public override void SaveEnergyInfo(string filename, RawRange range) { using (ExcelPackage excelPackage = new ExcelPackage()) { //Set some properties of the Excel document excelPackage.Workbook.Properties.Author = "Wind Energy"; excelPackage.Workbook.Properties.Title = range.Name; excelPackage.Workbook.Properties.Created = DateTime.Now; //Create the WorkSheet ExcelWorksheet worksheet = excelPackage.Workbook.Worksheets.Add("Лист 1"); List <object> years = new List <object>(); foreach (RawItem item in range) { if (!years.Contains(item.Date.Year)) { years.Add(item.Date.Year); } } double totalAverageSpeed = range.Average((t) => t.Speed); //формирование заголовка List <string> cap = new List <string>() { "Год", "Месяц", "Кол-во измерений" }; foreach (GradationItem grad in Vars.Options.CurrentSpeedGradation.Items) { cap.Add(grad.Average.ToString("0.00")); } cap.AddRange(new string[] { "Vmin, м/с", "Vmax, м/с", "Vср, м/с", "Vэкстр.50, м/с", "δ(P)", "Cv(V)", "𝜎(V)", "γ", "β", "Nвал уд., Вт/м^2", "Эвал уд., Вт*ч/м^2" }); foreach (WindDirections16 wd in WindDirections16.Calm.GetEnumItems().GetRange(0, 17)) { cap.Add(wd.Description()); } //ЗАПИСЬ ФАЙЛА //запись заголовка for (int j = 1; j <= cap.Count; j++) { worksheet.Cells[1, j].Value = cap[j - 1]; } worksheet.Cells[1, 1, 1, cap.Count].Style.Font.Bold = true; worksheet.Cells[1, 1, 1, cap.Count].Style.Fill.PatternType = ExcelFillStyle.Solid; worksheet.Cells[1, 1, 1, cap.Count].Style.Fill.BackgroundColor.SetColor(Color.Gray); worksheet.View.FreezePanes(2, 3); //запись данных обо всём периоде EnergyInfo ri1 = StatisticEngine.ProcessRange(range); StatisticalRange <WindDirections16> sd1 = StatisticEngine.GetDirectionExpectancy(range, GradationInfo <WindDirections16> .Rhumb16Gradations); StatisticalRange <GradationItem> ss1 = StatisticEngine.GetExpectancy(range, Vars.Options.CurrentSpeedGradation); EnergyInfo ei1 = StatisticEngine.ProcessRange(ss1); int cells = saveEnergyInfoLine(worksheet, 2, ri1, ei1, sd1, ss1, "Все года", "Все месяцы", range.Count); worksheet.Cells[2, 1, 2, cells].Style.Font.Bold = true; worksheet.Cells[2, 1, 2, cells].Style.Fill.PatternType = ExcelFillStyle.Solid; worksheet.Cells[2, 1, 2, cells].Style.Fill.BackgroundColor.SetColor(Color.LightGray); //запись данных для каждого года int line = 3; foreach (int year in years) //цикл по годам { //для каждого месяца в году for (int mt = 0; mt <= 12; mt++) //по месяцам, начиная со всех { Months month = (Months)mt; RawRange rn = range.GetRange(false, true, DateTime.Now, DateTime.Now, year, month.Description()); if (rn == null || rn.Count == 0) { continue; } EnergyInfo ri = StatisticEngine.ProcessRange(rn, range); StatisticalRange <WindDirections16> sd = StatisticEngine.GetDirectionExpectancy(rn, GradationInfo <WindDirections16> .Rhumb16Gradations); StatisticalRange <GradationItem> ss = StatisticEngine.GetExpectancy(rn, Vars.Options.CurrentSpeedGradation); EnergyInfo ei = StatisticEngine.ProcessRange(ss); cells = saveEnergyInfoLine(worksheet, line, ri, ei, sd, ss, year.ToString(), month.Description(), rn.Count); if (Math.IEEERemainder(mt + 1, 2) == 0 || mt == 0) //на нечетных строках добавляем серый фон { worksheet.Cells[line, 1, line, cells].Style.Fill.PatternType = ExcelFillStyle.Solid; worksheet.Cells[line, 1, line, cells].Style.Fill.BackgroundColor.SetColor(Color.LightGray); } if (month == Months.All) //для суммарной информации по году выделение жирным { worksheet.Cells[line, 1, line, cells].Style.Font.Bold = true; } line++; } } //запись данных для каждого месяца отдельно line += 3; //для каждого месяца в году for (int mt = 1; mt <= 12; mt++) //по месяцам { Months month = (Months)mt; RawRange rn = range.GetRange(false, true, DateTime.Now, DateTime.Now, "Все", month.Description()); if (rn == null || rn.Count == 0) { continue; } EnergyInfo ri = StatisticEngine.ProcessRange(rn, range); StatisticalRange <WindDirections16> sd = StatisticEngine.GetDirectionExpectancy(rn, GradationInfo <WindDirections16> .Rhumb16Gradations); StatisticalRange <GradationItem> ss = StatisticEngine.GetExpectancy(rn, Vars.Options.CurrentSpeedGradation); EnergyInfo ei = StatisticEngine.ProcessRange(ss); cells = saveEnergyInfoLine(worksheet, line, ri, ei, sd, ss, "Все года", month.Description(), rn.Count); if (Math.IEEERemainder(mt + 1, 2) == 0 || mt == 0) //на нечетных строках добавляем серый фон { worksheet.Cells[line, 1, line, cells].Style.Fill.PatternType = ExcelFillStyle.Solid; worksheet.Cells[line, 1, line, cells].Style.Fill.BackgroundColor.SetColor(Color.LightGray); } line++; } //Save your file FileInfo fi = new FileInfo(filename); excelPackage.SaveAs(fi); } }
/// <summary> /// восстановить ряд до нужного интревала наблюдений /// </summary> /// <param name="range">Ряд для восстановления</param> /// <param name="param">параметры восстановления</param> /// <param name="actionPercent">изменение процента выполнения</param> /// <param name="actionAfter">действие после обработки</param> /// <returns></returns> public Task <RawRange> ProcessRange(RawRange range, RestorerParameters param, Action <int, string> actionPercent, Action <RawRange, RawRange, double> actionAfter) { RawRange baseRange = null;//ряд, на основе которого будет идти восстановление range.PerformRefreshQuality(); Range = new RawRange(range.OrderBy(x => x.Date).ToList()); this.param = param; this.actionPercent = actionPercent; prepareIterpolators(); //расчет каждого значения Task <RawRange> tsk = new Task <RawRange>(() => { ConcurrentBag <RawItem> resultCollection = new ConcurrentBag <RawItem>(); Parallel.ForEach(newRangeX, (p) => { incrementCounter(); StandartIntervals currentInterval = getIntervalOfDateArgument(p, range); if (currentInterval == StandartIntervals.None) { throw new WindEnergyException("Что-то не так. Не удалось найти интервал наблюдений"); } double speed, direct, temp, wet, press; //если целевой интервал меньше текущего, то интерполируем как обычно if ((int)currentInterval >= (int)param.Interval || param.Method == InterpolateMethods.NearestMeteostation) { speed = methodSpeeds.GetValue(p); direct = methodDirects.GetValue(p); temp = methodTemp.GetValue(p); wet = methodWet.GetValue(p); press = methodPress.GetValue(p); } else //Если целевой интервал больше текущего, то надо осреднять значения за целевой интервал { DateTime from = new DateTime().AddMinutes(p - (int)param.Interval); DateTime to = new DateTime().AddMinutes(p); RawRange part = range.GetRange(true, false, from, to, null, null); if (part.Count == 0) { speed = methodSpeeds.GetValue(p); direct = methodDirects.GetValue(p); temp = methodTemp.GetValue(p); wet = methodWet.GetValue(p); press = methodPress.GetValue(p); } else { speed = part.Average(item => item.Speed); direct = part.Average(item => item.Direction > 0 ? item.Direction : 0); temp = part.Average(item => item.Temperature); wet = part.Average(item => item.Wetness); press = part.Average(item => item.Pressure); } } if (double.IsNaN(speed)) { return; } if (speed < 0) { speed = 0; } resultCollection.Add(new RawItem(p, speed, direct, temp, wet, press)); }); RawRange res = new RawRange(resultCollection.OrderBy(item => item.DateArgument)); res.Position = range.Position; res.Meteostation = range.Meteostation; res.Height = range.Height; if (actionAfter != null) { actionAfter.Invoke(res, baseRange, r); } return(res); }); tsk.Start(); return(tsk); }