/// <summary> /// проверка на соответствие нормальному закону распределния ряда. озвращая критерий согласия Пирсона для этого ряда /// http://www.ekonomstat.ru/kurs-lektsij-po-teorii-statistiki/403-proverka-sootvetstvija-rjada-raspredelenija.html /// https://life-prog.ru/2_84515_proverka-po-kriteriyu-hi-kvadrat.html критерий пирсона /// https://math.semestr.ru/group/example-normal-distribution.php для нормального распределения /// </summary> /// <param name="range">ряд</param> /// <param name="parameter">проверяемый параметр</param> /// <returns></returns> private static double checkNormalLaw(RawRange range, MeteorologyParameters parameter) { GradationInfo <GradationItem> grads; switch (parameter) { case MeteorologyParameters.Speed: grads = new GradationInfo <GradationItem>(0, SPEED_GRADATION_STEP, range.Max((item) => { return(item.Speed); })); //градации скорости break; case MeteorologyParameters.Direction: StatisticalRange <WindDirections16> srwd = StatisticEngine.GetDirectionExpectancy(range, GradationInfo <WindDirections16> .Rhumb16Gradations); return(0); case MeteorologyParameters.Temperature: grads = new GradationInfo <GradationItem>(0, TEMPERATURE_GRADATION_STEP, range.Max((item) => { return(item.Temperature); })); //градации температуры break; case MeteorologyParameters.Wetness: grads = new GradationInfo <GradationItem>(0, WETNESS_GRADATION_STEP, range.Max((item) => { return(item.Wetness); })); //градации влажности break; default: throw new WindEnergyException("Этот параметр не реализован"); } //РАСЧЕТ ДЛЯ ВСЕХ, КРОМЕ НАПРАВЛЕНИЙ StatisticalRange <GradationItem> stat_range = StatisticEngine.GetExpectancy(range, grads, parameter); //статистический ряд // TODO: расчет критерия пирсона для ряда return(0); }
/// <summary> /// расчет характеристик ряда /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void formEnergyInfo_Shown(object sender, EventArgs e) { radioButtonSelectPeriod.Checked = true; DateTime min = range.Min((i) => i.Date); DateTime max = range.Max((i) => i.Date); dateTimePickerFrom.MinDate = min; dateTimePickerTo.MinDate = min; dateTimePickerFrom.MaxDate = max; dateTimePickerTo.MaxDate = max; dateTimePickerFrom.Value = min; dateTimePickerTo.Value = max; years = new List <object>(); foreach (RawItem item in range) { if (!years.Contains(item.Date.Year)) { years.Add(item.Date.Year); } } _ = comboBoxYear.Items.Add("Все"); comboBoxYear.Items.AddRange(years.ToArray()); comboBoxYear.SelectedItem = "Все"; comboBoxMonth.Items.AddRange(Months.January.GetItems().ToArray()); comboBoxMonth.SelectedItem = Months.All.Description(); refreshInfo(); drawGraphs(); ready = true; }
/// <summary> /// ищет наиболее подходящую к заданной точке МС и получает её ряд. Если ряд не найден, то возвращает null /// </summary> /// <param name="coordinates"></param> /// <param name="r"></param> /// <param name="actionPercent"></param> /// <param name="Range">ряд, для которого подбирается функция</param> /// <exception cref="GetBaseRangeException">Возвращает иснформацию о параметрах, мешающих получить ближайшую МС</exception> /// <returns></returns> internal static RawRange TryGetBaseRange(RawRange Range, PointLatLng coordinates, out double r, Action <int, string> actionPercent) { bool nlaw = CheckNormalLaw(Range, Vars.Options.NormalLawPirsonCoefficientDiapason); if (!nlaw) { throw new WindEnergyException("Исходный ряд не подчиняется нормальному закону распределения"); } DateTime from = Range.Min((ri) => ri.Date).Date, to = Range.Max((ri) => ri.Date).Date; List <RP5MeteostationInfo> mts = Vars.RP5Meteostations.GetNearestMS(coordinates, Vars.Options.NearestMSRadius, false); Dictionary <double, double> funcSpeed = Range.GetFunction(MeteorologyParameters.Speed); //функция скорости на заданном ряде RawRange res = null; double rmax = double.MinValue, total_rmax = double.MinValue; RP5ru provider = new RP5ru(Vars.Options.CacheFolder + "\\rp5.ru"); for (int i = 0; i < mts.Count; i++) { if (actionPercent != null) { actionPercent.Invoke((int)((i * 1d / mts.Count) * 100d), "Поиск подходящей МС..."); } RP5MeteostationInfo m = mts[i]; //если нет диапазона измерений в БД, то загружаем с сайта if (m.MonitoringFrom == DateTime.MinValue) { provider.GetMeteostationExtInfo(ref m); } //если для этой МС нет наблюдений в этом периоде, то переходим на другую if (m.MonitoringFrom > from) { continue; } //загрузка ряда с очередной МС RawRange curRange = null; try { curRange = provider.GetRange(from, to, m); } catch (WindEnergyException wex) // если не удалось получить ряд этой МС, то переходим к следующей { continue; } curRange = new Checker().ProcessRange(curRange, new CheckerParameters(LimitsProviders.StaticLimits, curRange.Position), out CheckerInfo info, null); //исправляем ошибки //СКОРОСТЬ MeteorologyParameters parameter = MeteorologyParameters.Speed; Dictionary <double, double> funcSpeedCurrentNearest = curRange.GetFunction(parameter); //функция скорости на текущей МС //проверка на нормальный закон распределения bool normal = CheckNormalLaw(curRange, Vars.Options.NormalLawPirsonCoefficientDiapason); if (!normal) { continue; } //расчёт и проверка коэфф корреляции List <double>[] table = calcTableCoeff(funcSpeed, funcSpeedCurrentNearest); //таблица для расчет коэффициентов double current_r = getParameterR(table); //коэффициент корреляции //общий максимальный коэфф корреляции if (current_r > total_rmax) { total_rmax = current_r; } //проверяем, можно ли взять эту МС if (current_r > rmax) { //истина, если надо проверять этот параметр на допустимый диапазон корреляции bool needCheck = Vars.Options.MinimalCorrelationControlParametres.Contains(parameter); if ((needCheck && current_r >= Vars.Options.MinimalCorrelationCoeff) || !needCheck) { rmax = current_r; res = curRange; } } } r = rmax; if (res == null) { RP5MeteostationInfo mi = Vars.RP5Meteostations.GetNearestMS(coordinates); double l = EarthModel.CalculateDistance(mi.Position, coordinates); throw new GetBaseRangeException(total_rmax, Vars.Options.MinimalCorrelationCoeff, l, mts.Count, Vars.Options.NearestMSRadius, coordinates); } return(res); }