/// <summary> /// загружает ряд наблюдений с ближайшей МС /// </summary> /// <param name="from">начало ряда</param> /// <param name="to">конец ряда</param> /// <param name="coordinates">координаты исходного ряда</param> /// <returns></returns> private static RawRange getNearestRange(DateTime from, DateTime to, PointLatLng coordinates) { if (from > to) { throw new WindEnergyException("Дата from больше, чем to"); } RawRange res = null; RP5MeteostationInfo nearestMS = Vars.RP5Meteostations.GetNearestMS(coordinates); if (nearestMS == null) { throw new Exception("Не удалось найти ближайшую метеостанцию в заданном радиусе"); } RP5ru provider = new RP5ru(Vars.Options.CacheFolder + "\\rp5.ru"); provider.GetMeteostationExtInfo(ref nearestMS); if (from < nearestMS.MonitoringFrom) //если исходный ряд начинается { from = nearestMS.MonitoringFrom; } if (from > to) { throw new Exception("Ряды не пересекаются: один из рядов заканчивается раньше, чем начинается другой"); } res = provider.GetRange(from, to, nearestMS); return(res); }
/// <summary> /// загрузка файла CSV поддерживаемых форматов /// </summary> /// <param name="fileName"></param> /// <returns></returns> public override RawRange LoadRange(string fileName) { StreamReader sr = new StreamReader(fileName, Encoding.UTF8, true); //определение формата файла csv string title = null, title2 = null, title3 = null; title = sr.ReadLine(); if (!sr.EndOfStream) { title2 = sr.ReadLine(); } if (!sr.EndOfStream) { title3 = sr.ReadLine(); } sr.Close(); if (title == null) { throw new WindEnergyException("Файл пуст!"); } string regex = @"^\d+[\.\,].\d*\s+\d+[\.\,].\d*$"; //этот файл - один из типов файлов rp5.ru (в заголовке есть тип источника, во второй строке указана кодировка, в третьей есть ссылка на источник) if ((title.Contains("WMO_ID") || title.Contains("METAR")) && title2 != null && title2.Contains("UTF-8") && title3 != null && title3.Contains("rp5.ru")) { return(RP5ru.LoadCSV(fileName)); } //этот файл - просто файл CSV (в заголовке есть тип источника, во второй строке есть координаты точки) else if ((title.Contains("ID")) && title2 != null && new Regex(regex).IsMatch(title2)) { return(loadCSVFile(fileName)); } //этот файл другого формата else { throw new Exception("Файл повреждён или имеет неподдерживаемый формат"); } }
/// <summary> /// Пытается импортировать файл на основе заданных настроек. При ошибке выбрасывает исключение WindEnergyException с информацией или ArgumentException при недопустимых настройках /// </summary> /// <returns></returns> /// <param name="count">количество считываемых строк, начиная со StartLine</param> public RawRange Import(long count = long.MaxValue) { CheckParameters(); //проверка параметров //Импорт данных string data = GetText(count); RawRange res = new RawRange(); res.BeginChange(); string[] lines = data.Split('\r'); int line_i = 0; foreach (string line in lines) { line_i++; string[] arr = new Regex("w*" + Delimeter + "w*").Split(line.Replace("\n", "")); if (arr.Length <= 1) { continue; } List <ImportFields> fields = this.Columns.Keys.ToList(); RawItem item = new RawItem(); foreach (ImportFields field in fields) { int index = Columns[field] - 1; string value = arr[index]; if (Trimmers != null && Trimmers.Length > 0) { value = value.Trim(Trimmers); } try { switch (field) { case ImportFields.Date: item.Date = DateTime.Parse(value); break; case ImportFields.Direction: switch (DirectionUnit) { case DirectionUnits.Degrees: item.Direction = double.Parse(value.Replace('.', Constants.DecimalSeparator)); break; case DirectionUnits.TextRP5: item.DirectionRhumb = RP5ru.GetWindDirectionFromString(value); break; case DirectionUnits.None: throw new ArgumentException("Не заданы единицы измерения для направления"); default: throw new WindEnergyException("Эта единица измерений не реализована"); } break; case ImportFields.Pressure: switch (PressureUnit) { case PressureUnits.KPa: item.Pressure = double.Parse(value.Replace('.', Constants.DecimalSeparator)) * Constants.MMHGART_IN_1KPA; //перевод в мм рт. ст. break; case PressureUnits.mmHgArt: item.Pressure = double.Parse(value.Replace('.', Constants.DecimalSeparator)); break; case PressureUnits.None: throw new ArgumentException("Не заданы единицы измерения для давления"); default: throw new WindEnergyException("Эта единица измерений не реализована"); } break; case ImportFields.Wetness: switch (WetnessUnit) { case WetnessUnits.Percents: item.Wetness = double.Parse(value.Replace('.', Constants.DecimalSeparator)); break; case WetnessUnits.Parts: item.Wetness = double.Parse(value.Replace('.', Constants.DecimalSeparator)) * 100d; //перевод в % break; case WetnessUnits.None: throw new ArgumentException("Не заданы единицы измерения для влажности"); default: throw new WindEnergyException("Эта единица измерений не реализована"); } break; case ImportFields.Temperature: item.Temperature = double.Parse(value.Replace('.', Constants.DecimalSeparator)); break; case ImportFields.Speed: item.Speed = double.Parse(value.Replace('.', Constants.DecimalSeparator)); break; default: throw new WindEnergyException("Этот параметр не реализован"); } } catch (Exception ex) { throw new WindEnergyException($"Не удалось распознать строку \"{value}\" как значение поля {field.Description()} в строке {line_i}", ex.Message); } } res.Add(item); } if ((bool)BindNearestMS) { res.Meteostation = Vars.RP5Meteostations.GetNearestMS(this.Coordinates); } res.Position = this.Coordinates; res.Name = Path.GetFileNameWithoutExtension(this.FilePath); res.EndChange(); res.PerformRefreshQuality(); return(res); }
public FormLoadFromRP5() { InitializeComponent(); engine = new RP5ru(Vars.Options.CacheFolder + "\\rp5.ru"); DialogResult = DialogResult.None; }
/// <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); }