public void TestToString() { DateTime date = DateTime.UtcNow; var dateString = date.ToString("yyyyMMdd HH:00"); NamTableRow row = new NamTableRow(date, date, new Tuple <double, double>(1.0, 2.0)); row.APCPStepSize = 1; row.APCPSurface = 1.0; row.CRAINSurface = 1; row.CSNOWSurface = 1; row.RH2mAboveGround = 1.0; row.TMP2mAboveGround = 1.0; row.TMP80mAboveGround = 1.0; row.TMPSurface = 1.0; row.TMPTrop = 1.0; row.UGRD10m = 1.0; row.UGRD80m = 1.0; row.UGRDTrop = 1.0; row.VGRD10m = 1.0; row.VGRD80m = 1.0; row.VGRDTrop = 1.0; var s = row.ToString(); var substring = s.Split(','); Assert.AreEqual(substring.Length, 18); Assert.AreEqual(substring[0], dateString, "Date string incorrect format"); }
/// <summary> /// From a grib file decode it in to an object representing a row in our output file /// </summary> /// <param name="file">GribFile</param> /// <returns>List of rows</returns> public static List <NamTableRow> ParseNamGribFile(GribFile file) { var Rows = new List <GribRow>(); DateTime?refTime = null; foreach (GribMessage msg in file) { var tmpTime = msg.Time; //Total precip is a time step value so make sure the time we get is at the end of the period //hour 0 is always 0 because of this; but some forecasts have more than one hours between steps //so make sure we enable this var stepSize = 0; if (msg.ParameterName == "Total precipitation") { int endStep = 0; int startStep = 0; var success = Int32.TryParse(msg.StartStep, out startStep); if (!success) { throw new Exception($"Unable to parse start step variable: {msg.StartStep} from grib file"); } /* * if(startStep != 0) * { * //some forecasts have sub intervals, ignore these * //if we start using forecasts other than the one produced at time 00 then we might need to modify this to account for different start steps * continue; * } */ success = Int32.TryParse(msg.EndStep, out endStep); if (!success) { throw new Exception($"Unable to parse end step variable: {msg.EndStep} from grib file"); } stepSize = endStep - startStep; tmpTime = tmpTime.AddHours(stepSize); } foreach (var val in msg.GridCoordinateValues) { if (val.IsMissing) { continue; } //Console.WriteLine("Lat: {0} Lon: {1} Name: {2} Time: {3} Level: {4} Val: {5}", val.Latitude, val.Longitude, msg.ParameterName, msg.Time, msg.Level, val.Value); double lat = Math.Round(val.Latitude, 6, MidpointRounding.AwayFromZero); double lon = Math.Round(-(360.0 - val.Longitude), 6, MidpointRounding.AwayFromZero); refTime = msg.ReferenceTime; Rows.Add(new GribRow { Lat = lat, Lon = lon, ParameterName = msg.ParameterName, //ParameterShortName = msg.ParameterShortName, //accessing this is very slow; only add it if we need it Time = tmpTime, ReferenceTime = msg.ReferenceTime, Level = msg.Level, TypeOfLevel = msg.TypeOfLevel, StepSize = stepSize, Value = val.Value }); } } var rowLookup = Rows.ToLookup(r => new Tuple <double, double, DateTime>(r.Lat, r.Lon, r.Time)); var namTable = new List <NamTableRow>(); foreach (var key in rowLookup) { if (refTime == null) { throw new InvalidDataException("refTime is null and should be a valid datetime"); } var newRow = new NamTableRow(key.Key.Item3, refTime.Value, new Tuple <double, double>(key.Key.Item1, key.Key.Item2)); foreach (var column in key) { if (column.TypeOfLevel == "surface" || column.TypeOfLevel == "heightAboveGround") { if (column.Level == 0) { if (column.ParameterName == "Total precipitation") { newRow.APCPSurface = column.Value; newRow.APCPStepSize = column.StepSize; continue; } else if (column.ParameterName == "195") { newRow.CSNOWSurface = (int)column.Value; continue; } else if (column.ParameterName == "192") { newRow.CRAINSurface = (int)column.Value; continue; } else if (column.ParameterName == "Temperature") { newRow.TMPSurface = column.Value; continue; } } else if (column.Level == 2) { if (column.ParameterName == "Temperature") { newRow.TMP2mAboveGround = column.Value; continue; } if (column.ParameterName == "Relative humidity") { newRow.RH2mAboveGround = column.Value; continue; } } else if (column.Level == 10) { if (column.ParameterName == "u-component of wind") { newRow.UGRD10m = column.Value; continue; } else if (column.ParameterName == "v-component of wind") { newRow.VGRD10m = column.Value; continue; } } else if (column.Level == 80) { if (column.ParameterName == "Temperature") { newRow.TMP80mAboveGround = column.Value; continue; } else if (column.ParameterName == "u-component of wind") { newRow.UGRD80m = column.Value; continue; } else if (column.ParameterName == "v-component of wind") { newRow.VGRD80m = column.Value; continue; } } } else if (column.TypeOfLevel == "tropopause") { if (column.ParameterName == "Temperature") { newRow.TMPTrop = column.Value; continue; } else if (column.ParameterName == "u-component of wind") { newRow.UGRDTrop = column.Value; continue; } else if (column.ParameterName == "v-component of wind") { newRow.VGRDTrop = column.Value; continue; } } throw new NotSupportedException($"unknown parameter level: {column.Level} name: {column.ParameterName}"); } namTable.Add(newRow); } return(namTable); }