diff --git a/src/NGrib/BadGribFormatException.cs b/src/NGrib/BadGribFormatException.cs index 1550033..8200e7f 100644 --- a/src/NGrib/BadGribFormatException.cs +++ b/src/NGrib/BadGribFormatException.cs @@ -24,23 +24,20 @@ * along with NGrib. If not, see . */ -using System; +namespace NGrib; -namespace NGrib +/// +/// The exception that is thrown when the read stream does not +/// respect the GRIB 2 data format. +/// +public class BadGribFormatException : Exception { - /// - /// The exception that is thrown when the read stream does not - /// respect the GRIB 2 data format. - /// - public class BadGribFormatException : Exception - { /// /// Initializes a new instance of the class /// with a specified error message. /// /// The message that describes the error. public BadGribFormatException(string message) : base(message) - { - } - } + { + } } \ No newline at end of file diff --git a/src/NGrib/BigEndianBitConverter.cs b/src/NGrib/BigEndianBitConverter.cs index 481a455..b7d3a12 100644 --- a/src/NGrib/BigEndianBitConverter.cs +++ b/src/NGrib/BigEndianBitConverter.cs @@ -24,77 +24,75 @@ * along with NGrib. If not, see . */ -using System; using System.Numerics; -namespace NGrib +namespace NGrib; + +internal static class BigEndianBitConverter { - internal static class BigEndianBitConverter - { - public const int Int8MinValue = -127; - public const int Int32MinValue = -2147483647; + public const int Int8MinValue = -127; + public const int Int32MinValue = -2147483647; - public static int ToInt8(byte[] data, int startIndex) => ToInt8(data[startIndex]); + public static int ToInt8(byte[] data, int startIndex) => ToInt8(data[startIndex]); - public static int ToInt8(byte data) => (1 - ((data & 128) >> 6)) * (data & 127); + public static int ToInt8(byte data) => (1 - ((data & 128) >> 6)) * (data & 127); - public static int ToUInt16(byte[] data, int startIndex) - { - var index = startIndex; - return (data[index++] << 8) | data[index]; - } + public static int ToUInt16(byte[] data, int startIndex) + { + var index = startIndex; + return (data[index++] << 8) | data[index]; + } - public static int ToInt16(byte[] data, int startIndex) - { - var index = startIndex; - return (1 - ((data[index] & 128) >> 6)) * ((data[index++] & 127) << 8 | data[index]); - } + public static int ToInt16(byte[] data, int startIndex) + { + var index = startIndex; + return (1 - ((data[index] & 128) >> 6)) * ((data[index++] & 127) << 8 | data[index]); + } - public static long ToUInt32(byte[] data, int startIndex) - { - var index = startIndex; - return ((uint) data[index++] << 24) | - ((uint) data[index++] << 16) | - ((uint) data[index++] << 8) | - data[index]; - } + public static long ToUInt32(byte[] data, int startIndex) + { + var index = startIndex; + return ((uint) data[index++] << 24) | + ((uint) data[index++] << 16) | + ((uint) data[index++] << 8) | + data[index]; + } - public static BigInteger ToUInt64(byte[] data, int startIndex) - { - var index = startIndex; - return ((ulong) data[index++] << 56) | - ((ulong) data[index++] << 48) | - ((ulong) data[index++] << 40) | - ((ulong) data[index++] << 32) | - ((ulong) data[index++] << 24) | - ((ulong) data[index++] << 16) | - ((ulong) data[index++] << 8) | - data[index]; - } + public static BigInteger ToUInt64(byte[] data, int startIndex) + { + var index = startIndex; + return ((ulong) data[index++] << 56) | + ((ulong) data[index++] << 48) | + ((ulong) data[index++] << 40) | + ((ulong) data[index++] << 32) | + ((ulong) data[index++] << 24) | + ((ulong) data[index++] << 16) | + ((ulong) data[index++] << 8) | + data[index]; + } - public static int ToInt32(byte[] data, int startIndex) - { - var index = startIndex; - return (1 - ((data[index] & 128) >> 6)) * ((data[index++] & 127) << 24 | - data[index++] << 16 | - data[index++] << 8 | - data[index]); - } + public static int ToInt32(byte[] data, int startIndex) + { + var index = startIndex; + return (1 - ((data[index] & 128) >> 6)) * ((data[index++] & 127) << 24 | + data[index++] << 16 | + data[index++] << 8 | + data[index]); + } - public static float ToSingle(byte[] data, int startIndex) - { - if (BitConverter.IsLittleEndian) - { - var reversedBytes = new[] - { - data[startIndex+3], - data[startIndex+2], - data[startIndex+1], - data[startIndex] - }; - return BitConverter.ToSingle(reversedBytes, 0); - } - return BitConverter.ToSingle(data, startIndex); - } - } -} + public static float ToSingle(byte[] data, int startIndex) + { + if (BitConverter.IsLittleEndian) + { + var reversedBytes = new[] + { + data[startIndex+3], + data[startIndex+2], + data[startIndex+1], + data[startIndex] + }; + return BitConverter.ToSingle(reversedBytes, 0); + } + return BitConverter.ToSingle(data, startIndex); + } +} \ No newline at end of file diff --git a/src/NGrib/BufferedBinaryReader.cs b/src/NGrib/BufferedBinaryReader.cs index c16067c..5e9fc1a 100644 --- a/src/NGrib/BufferedBinaryReader.cs +++ b/src/NGrib/BufferedBinaryReader.cs @@ -17,310 +17,307 @@ * along with NGrib. If not, see . */ -using System; -using System.IO; using System.Numerics; using NGrib.Grib2.Sections; -namespace NGrib +namespace NGrib; + +/// +/// Based on Jackson Dunstan implementation . +/// +public class BufferedBinaryReader : IDisposable { - /// - /// Based on Jackson Dunstan implementation . - /// - internal class BufferedBinaryReader : IDisposable - { - private readonly Stream stream; - private readonly bool leaveOpen; - private readonly byte[] buffer; - private readonly int bufferSize; - private int bufferOffset; - private int numBufferedBytes; - private long savedPosition; - private int NumBytesAvailable => Math.Max(0, numBufferedBytes - bufferOffset); - - public bool HasReachedStreamEnd => stream.Position >= stream.Length && NumBytesAvailable <= 0; - - public BufferedBinaryReader(Stream stream, bool leaveOpen = false, int bufferSize = 4096) - { - this.stream = stream; - this.leaveOpen = leaveOpen; - this.bufferSize = bufferSize; - buffer = new byte[bufferSize]; - MarkBufferAsUsed(); - SaveCurrentPosition(); - } - - private bool FillBuffer() - { - var numBytesUnread = bufferSize - bufferOffset; - var numBytesToRead = bufferSize - numBytesUnread; - bufferOffset = 0; - numBufferedBytes = numBytesUnread; - if (numBytesUnread > 0) - { - Buffer.BlockCopy(buffer, numBytesToRead, buffer, 0, numBytesUnread); - } - while (numBytesToRead > 0) - { - var numBytesRead = stream.Read(buffer, numBytesUnread, numBytesToRead); - if (numBytesRead == 0) - { - return false; - } - numBufferedBytes += numBytesRead; - numBytesToRead -= numBytesRead; - numBytesUnread += numBytesRead; - } - return true; - } - - private void EnsureAvailable(int numBytes) - { - if (NumBytesAvailable >= numBytes) return; + private readonly Stream stream; + private readonly bool leaveOpen; + private readonly byte[] buffer; + private readonly int bufferSize; + private int bufferOffset; + private int numBufferedBytes; + private long savedPosition; + private int NumBytesAvailable => Math.Max(0, numBufferedBytes - bufferOffset); + + public bool HasReachedStreamEnd => stream.Position >= stream.Length && NumBytesAvailable <= 0; + + public BufferedBinaryReader(Stream stream, bool leaveOpen = false, int bufferSize = 4096) + { + this.stream = stream; + this.leaveOpen = leaveOpen; + this.bufferSize = bufferSize; + buffer = new byte[bufferSize]; + MarkBufferAsUsed(); + SaveCurrentPosition(); + } + + private bool FillBuffer() + { + var numBytesUnread = bufferSize - bufferOffset; + var numBytesToRead = bufferSize - numBytesUnread; + bufferOffset = 0; + numBufferedBytes = numBytesUnread; + if (numBytesUnread > 0) + { + Buffer.BlockCopy(buffer, numBytesToRead, buffer, 0, numBytesUnread); + } + while (numBytesToRead > 0) + { + var numBytesRead = stream.Read(buffer, numBytesUnread, numBytesToRead); + if (numBytesRead == 0) + { + return false; + } + numBufferedBytes += numBytesRead; + numBytesToRead -= numBytesRead; + numBytesUnread += numBytesRead; + } + return true; + } + + private void EnsureAvailable(int numBytes) + { + if (NumBytesAvailable >= numBytes) return; - // Try to read from the stream - // and check that we were able to read the bytes we wanted - if (!FillBuffer() && NumBytesAvailable < numBytes) - { - throw new IndexOutOfRangeException(); - } - } + // Try to read from the stream + // and check that we were able to read the bytes we wanted + if (!FillBuffer() && NumBytesAvailable < numBytes) + { + throw new IndexOutOfRangeException(); + } + } public byte ReadByte() { - EnsureAvailable(sizeof(byte)); - var val = buffer[bufferOffset]; - bufferOffset += sizeof(byte); - return val; - } + EnsureAvailable(sizeof(byte)); + var val = buffer[bufferOffset]; + bufferOffset += sizeof(byte); + return val; + } - public int ReadUInt8() => ReadByte(); + public int ReadUInt8() => ReadByte(); - public int ReadInt8() => BigEndianBitConverter.ToInt8(ReadByte()); + public int ReadInt8() => BigEndianBitConverter.ToInt8(ReadByte()); - public int ReadUInt16() - { - EnsureAvailable(sizeof(short)); - var val = BigEndianBitConverter.ToUInt16(buffer, bufferOffset); - bufferOffset += sizeof(short); - return val; - } + public int ReadUInt16() + { + EnsureAvailable(sizeof(short)); + var val = BigEndianBitConverter.ToUInt16(buffer, bufferOffset); + bufferOffset += sizeof(short); + return val; + } public int ReadInt16() { - EnsureAvailable(sizeof(short)); - var val = BigEndianBitConverter.ToInt16(buffer, bufferOffset); - bufferOffset += sizeof(short); - return val; + EnsureAvailable(sizeof(short)); + var val = BigEndianBitConverter.ToInt16(buffer, bufferOffset); + bufferOffset += sizeof(short); + return val; + } + + public long ReadUInt32() + { + EnsureAvailable(sizeof(uint)); + var val = BigEndianBitConverter.ToUInt32(buffer, bufferOffset); + bufferOffset += sizeof(uint); + return val; + } + + public int ReadInt32() + { + EnsureAvailable(sizeof(int)); + var val = BigEndianBitConverter.ToInt32(buffer, bufferOffset); + bufferOffset += sizeof(int); + return val; } - public long ReadUInt32() - { - EnsureAvailable(sizeof(uint)); - var val = BigEndianBitConverter.ToUInt32(buffer, bufferOffset); - bufferOffset += sizeof(uint); - return val; - } - - public int ReadInt32() - { - EnsureAvailable(sizeof(int)); - var val = BigEndianBitConverter.ToInt32(buffer, bufferOffset); - bufferOffset += sizeof(int); - return val; - } - - /// - /// Read a double value (L) represented by : - /// - a scale factor F (UInt8); - /// - a scaled value V (UInt32); - /// where L * 10^F = V. - /// - /// Original value - public double? ReadScaledValue() - { - var scaleFactor = ReadInt8(); - var scaledValue = ReadInt32(); - - if (scaleFactor == BigEndianBitConverter.Int8MinValue && scaledValue == BigEndianBitConverter.Int32MinValue) - { - // All bits set to 1 means that no value is provided. - return null; - } - - return scaledValue * Math.Pow(10, -scaleFactor); - } - - public void NextUIntN() - { - positionInBbbReadBuffer = 0; - bitByBitReadBuffer = 0; - } - - private int bitByBitReadBuffer; - private int positionInBbbReadBuffer; - public int ReadUIntN(int nbBit) - { - int bitsLeft = nbBit; - int result = 0; - - if (positionInBbbReadBuffer == 0) - { - bitByBitReadBuffer = ReadByte(); - positionInBbbReadBuffer = 8; - } - - while (true) - { - int shift = bitsLeft - positionInBbbReadBuffer; - if (shift > 0) - { - // Consume the entire buffer - result |= bitByBitReadBuffer << shift; - bitsLeft -= positionInBbbReadBuffer; - - // Get the next byte from the RandomAccessFile - bitByBitReadBuffer = ReadByte(); - positionInBbbReadBuffer = 8; - } - else - { - // Consume a portion of the buffer - result |= bitByBitReadBuffer >> -shift; - positionInBbbReadBuffer -= bitsLeft; - bitByBitReadBuffer &= 0xff >> (8 - positionInBbbReadBuffer); // mask off consumed bits - - return result; - } - } - } - - public int ReadIntN(int nbBit) - { - var result = ReadUIntN(nbBit); - return result.AsSignedInt(nbBit); - } + /// + /// Read a double value (L) represented by : + /// - a scale factor F (UInt8); + /// - a scaled value V (UInt32); + /// where L * 10^F = V. + /// + /// Original value + public double? ReadScaledValue() + { + var scaleFactor = ReadInt8(); + var scaledValue = ReadInt32(); + + if (scaleFactor == BigEndianBitConverter.Int8MinValue && scaledValue == BigEndianBitConverter.Int32MinValue) + { + // All bits set to 1 means that no value is provided. + return null; + } + + return scaledValue * Math.Pow(10, -scaleFactor); + } + + public void NextUIntN() + { + positionInBbbReadBuffer = 0; + bitByBitReadBuffer = 0; + } + + private int bitByBitReadBuffer; + private int positionInBbbReadBuffer; + public int ReadUIntN(int nbBit) + { + int bitsLeft = nbBit; + int result = 0; + + if (positionInBbbReadBuffer == 0) + { + bitByBitReadBuffer = ReadByte(); + positionInBbbReadBuffer = 8; + } + + while (true) + { + int shift = bitsLeft - positionInBbbReadBuffer; + if (shift > 0) + { + // Consume the entire buffer + result |= bitByBitReadBuffer << shift; + bitsLeft -= positionInBbbReadBuffer; + + // Get the next byte from the RandomAccessFile + bitByBitReadBuffer = ReadByte(); + positionInBbbReadBuffer = 8; + } + else + { + // Consume a portion of the buffer + result |= bitByBitReadBuffer >> -shift; + positionInBbbReadBuffer -= bitsLeft; + bitByBitReadBuffer &= 0xff >> (8 - positionInBbbReadBuffer); // mask off consumed bits + + return result; + } + } + } + + public int ReadIntN(int nbBit) + { + var result = ReadUIntN(nbBit); + return result.AsSignedInt(nbBit); + } - public BigInteger ReadUInt64() - { - EnsureAvailable(sizeof(ulong)); - var val = BigEndianBitConverter.ToUInt64(buffer, bufferOffset); - bufferOffset += sizeof(ulong); - return val; - } - - public float ReadSingle() - { - EnsureAvailable(sizeof(float)); - var val = BigEndianBitConverter.ToSingle(buffer, bufferOffset); - bufferOffset += sizeof(float); - return val; - } - - public byte[] Read(int numBytes) - { - var result = new byte[numBytes]; - - var numBytesLeftToRead = numBytes; - var resultOffset = 0; - while (numBytesLeftToRead > 0) - { - var numBytesRead = Math.Min(bufferSize, numBytesLeftToRead); - - EnsureAvailable(numBytesRead); - Buffer.BlockCopy(buffer, bufferOffset, result, resultOffset, numBytesRead); - bufferOffset += numBytesRead; - - resultOffset += numBytesRead; - numBytesLeftToRead -= numBytesRead; - } - - return result; - } - - public DateTime ReadDateTime() - { - var year = ReadUInt16(); - var month = ReadUInt8(); - var day = ReadUInt8(); - var hour = ReadUInt8(); - var minute = ReadUInt8(); - var second = ReadUInt8(); - - return new DateTime(year, month, day, hour, minute, second, DateTimeKind.Utc); - } - - public SectionInfo PeekSection() - { - SaveCurrentPosition(); - var info = ReadSectionInfo(); - SeekToSavedPosition(); - return info; - } - - public SectionInfo ReadSectionInfo() - { - var sectionLength = ReadUInt32(); - - if (sectionLength == Constants.GribFileStartCode) - { - return new SectionInfo(Constants.IndicatorSectionLength, SectionCode.IndicatorSection); - } + public BigInteger ReadUInt64() + { + EnsureAvailable(sizeof(ulong)); + var val = BigEndianBitConverter.ToUInt64(buffer, bufferOffset); + bufferOffset += sizeof(ulong); + return val; + } + + public float ReadSingle() + { + EnsureAvailable(sizeof(float)); + var val = BigEndianBitConverter.ToSingle(buffer, bufferOffset); + bufferOffset += sizeof(float); + return val; + } + + public byte[] Read(int numBytes) + { + var result = new byte[numBytes]; + + var numBytesLeftToRead = numBytes; + var resultOffset = 0; + while (numBytesLeftToRead > 0) + { + var numBytesRead = Math.Min(bufferSize, numBytesLeftToRead); + + EnsureAvailable(numBytesRead); + Buffer.BlockCopy(buffer, bufferOffset, result, resultOffset, numBytesRead); + bufferOffset += numBytesRead; + + resultOffset += numBytesRead; + numBytesLeftToRead -= numBytesRead; + } + + return result; + } + + public DateTime ReadDateTime() + { + var year = ReadUInt16(); + var month = ReadUInt8(); + var day = ReadUInt8(); + var hour = ReadUInt8(); + var minute = ReadUInt8(); + var second = ReadUInt8(); + + return new DateTime(year, month, day, hour, minute, second, DateTimeKind.Utc); + } + + public SectionInfo PeekSection() + { + SaveCurrentPosition(); + var info = ReadSectionInfo(); + SeekToSavedPosition(); + return info; + } + + public SectionInfo ReadSectionInfo() + { + var sectionLength = ReadUInt32(); + + if (sectionLength == Constants.GribFileStartCode) + { + return new SectionInfo(Constants.IndicatorSectionLength, SectionCode.IndicatorSection); + } - if (sectionLength == Constants.GribFileEndCode) - { - return new SectionInfo(Constants.EndSectionLength, SectionCode.EndSection); - } - - var sectionCode = ReadUInt8(); - return new SectionInfo(sectionLength, sectionCode); - } - - public void Skip(int numBytes) - { - if (numBytes <= NumBytesAvailable) - { - bufferOffset += numBytes; - } - else - { - var offset = numBytes - NumBytesAvailable; - stream.Seek(offset, SeekOrigin.Current); - MarkBufferAsUsed(); - } - } - - public void Seek(long offset, SeekOrigin origin) - { - stream.Seek(offset, origin); - MarkBufferAsUsed(); - } - - private void MarkBufferAsUsed() - { - // Mark the buffer as completely used - // to trigger a refill - bufferOffset = bufferSize; - } - - public void Dispose() - { - if (!leaveOpen) - { - stream.Close(); - } - } - - public void SaveCurrentPosition() - { - savedPosition = Position; - } + if (sectionLength == Constants.GribFileEndCode) + { + return new SectionInfo(Constants.EndSectionLength, SectionCode.EndSection); + } + + var sectionCode = ReadUInt8(); + return new SectionInfo(sectionLength, sectionCode); + } + + public void Skip(int numBytes) + { + if (numBytes <= NumBytesAvailable) + { + bufferOffset += numBytes; + } + else + { + var offset = numBytes - NumBytesAvailable; + stream.Seek(offset, SeekOrigin.Current); + MarkBufferAsUsed(); + } + } + + public void Seek(long offset, SeekOrigin origin) + { + stream.Seek(offset, origin); + MarkBufferAsUsed(); + } + + private void MarkBufferAsUsed() + { + // Mark the buffer as completely used + // to trigger a refill + bufferOffset = bufferSize; + } + + public void Dispose() + { + if (!leaveOpen) + { + stream.Close(); + } + } + + public void SaveCurrentPosition() + { + savedPosition = Position; + } public long Position => stream.Position - NumBytesAvailable; - public void SeekToSavedPosition() - { - Seek(savedPosition, SeekOrigin.Begin); - } - } -} + public void SeekToSavedPosition() + { + Seek(savedPosition, SeekOrigin.Begin); + } +} \ No newline at end of file diff --git a/src/NGrib/Common/Adapters/Grib1FileAdapter.cs b/src/NGrib/Common/Adapters/Grib1FileAdapter.cs new file mode 100644 index 0000000..ea4012f --- /dev/null +++ b/src/NGrib/Common/Adapters/Grib1FileAdapter.cs @@ -0,0 +1,23 @@ +using System.Collections; +using NGrib.Grib1; + +namespace NGrib.Common.Adapters; + +public class Grib1FileAdapter:IGribFile +{ + private readonly Grib1File _grib1File; + private readonly Hashtable _hashtable = new(); + Grib1GridDefinitionSection gds = null; + public Grib1FileAdapter(Grib1File grib1File) + { + _grib1File = grib1File; + } + + public IGribMessage GetMessage(Stream stream) + { + var message = + _grib1File.ReadGrib1Record(stream, stream.Position, _hashtable, ref gds); + return new Grib1MessageAdapter(message, _grib1File, stream); + } + +} \ No newline at end of file diff --git a/src/NGrib/Common/Adapters/Grib1MessageAdapter.cs b/src/NGrib/Common/Adapters/Grib1MessageAdapter.cs new file mode 100644 index 0000000..822e020 --- /dev/null +++ b/src/NGrib/Common/Adapters/Grib1MessageAdapter.cs @@ -0,0 +1,84 @@ +using System.Data; +using System.Diagnostics; +using NGrib.Grib1; +using NGrib.Grib1.PdsParameterTables; + +namespace NGrib.Common.Adapters; + +public class Grib1MessageAdapter : IGribMessage +{ + private Grib1Record _record; + private Grib1File _grib1File; + private readonly Stream _stream; + + public Grib1MessageAdapter(Grib1Record @record, Grib1File grib1File, Stream stream) + { + _record = record; + _grib1File = grib1File; + _stream = stream; + } + + public string Name => _record.ProductDefinitionSection.Parameter.Name; + + public DateTime Time => GetForecastTime(); + + + public IEnumerable> GetData() + { + var rawData = + _grib1File.getData(_stream, _record.DataOffset, + _record.ProductDefinitionSection.DecimalScale, false); + return _record.GridDefinitionSection.EnumerateGridPoints() + .Zip(rawData, (c, v) => new KeyValuePair(c, v)); + } + + public int Version => 1; + + public int ParameterHash + { + get + { + var parametr = _record.ProductDefinitionSection; + if (parametr.WaveSpectra2DDirFreq != null) + throw new DataException("Нестандартная секция"); + return (parametr.Center, parametr.Description, parametr.P1, parametr.P2, parametr.Parameter.Description, + parametr.Parameter.Name, parametr.Parameter.Number, parametr.Parameter.Unit, + parametr.Type, parametr.Unit, parametr.CustomData, parametr.DecimalScale, parametr.Grid_Id, + parametr.LengthErr, parametr.LevelName, parametr.LevelValue1, parametr.LevelValue2, + parametr.ParameterNumber, parametr.Process_Id, parametr.ProductDefinition, + parametr.SubCenter, parametr.TableVersion, parametr.TimeUnit, parametr.TimeRangeUnit) + .GetHashCode(); + } + } + + private DateTime GetForecastTime() + { + var productSection = _record.ProductDefinitionSection; + var baseTime = productSection.BaseTime; + var unit = productSection.TimeRangeUnit; + var unitNumber = productSection.ForecastTime; + + return unit switch + { + TimeRangeUnitGrib1.Day => baseTime.AddDays(unitNumber), + TimeRangeUnitGrib1.Minute => baseTime.AddMinutes(unitNumber), + TimeRangeUnitGrib1.Hour => baseTime.AddHours(unitNumber), + TimeRangeUnitGrib1.Month => baseTime.AddMonths(unitNumber), + TimeRangeUnitGrib1.Year => baseTime.AddYears(unitNumber), + TimeRangeUnitGrib1.Decade => baseTime.AddYears(10 * unitNumber), + TimeRangeUnitGrib1.Normal => baseTime.AddYears(30 * unitNumber), + TimeRangeUnitGrib1.Century => baseTime.AddYears(100 * unitNumber), + TimeRangeUnitGrib1.Hours3 => baseTime.AddHours(3 * unitNumber), + TimeRangeUnitGrib1.Hours6 => baseTime.AddHours(6 * unitNumber), + TimeRangeUnitGrib1.Hours12 => baseTime.AddHours(12 * unitNumber), + TimeRangeUnitGrib1.Minutes15 => baseTime.AddMinutes(15 * unitNumber), + TimeRangeUnitGrib1.Minutes30 => baseTime.AddMinutes(30 * unitNumber), + TimeRangeUnitGrib1.Second => baseTime.AddSeconds(unitNumber), + TimeRangeUnitGrib1.Reserved => + throw new NotSupportedException("Ключ формата был зарезервирован в стандарте и не реализован"), + TimeRangeUnitGrib1.Missing => + throw new NotSupportedException("Ключ формата отсутствовал в стандарте и не реализован"), + _ => throw new NotSupportedException("Поведение для этого заначения ключа не было реализовано") + }; + } +} \ No newline at end of file diff --git a/src/NGrib/Common/Adapters/Grib2FileAdapter.cs b/src/NGrib/Common/Adapters/Grib2FileAdapter.cs new file mode 100644 index 0000000..5caad8d --- /dev/null +++ b/src/NGrib/Common/Adapters/Grib2FileAdapter.cs @@ -0,0 +1,21 @@ +using NGrib.Grib2; + +namespace NGrib.Common.Adapters; + +public class Grib2FileAdapter:IGribFile +{ + private readonly Grib2File _grib2File; + + public Grib2FileAdapter(Grib2File grib2File) + { + _grib2File = grib2File; + } + + public IGribMessage GetMessage(Stream stream) + { + using var reader = new BufferedBinaryReader(stream, true); + var message = _grib2File.ReadGrib2Message(reader, out var currentPosition); + stream.Seek(currentPosition, SeekOrigin.Begin); + return new Grib2MessageAdapter(message, stream); + } +} \ No newline at end of file diff --git a/src/NGrib/Common/Adapters/Grib2MessageAdapter.cs b/src/NGrib/Common/Adapters/Grib2MessageAdapter.cs new file mode 100644 index 0000000..13561ce --- /dev/null +++ b/src/NGrib/Common/Adapters/Grib2MessageAdapter.cs @@ -0,0 +1,85 @@ +using NGrib.Grib2; +using NGrib.Grib2.CodeTables; +using NGrib.Grib2.Templates.ProductDefinitions; + +namespace NGrib.Common.Adapters; + +public class Grib2MessageAdapter : IGribMessage +{ + private readonly Message _message; + private readonly Stream _stream; + + public Grib2MessageAdapter(Message message, Stream stream) + { + _message = message; + _stream = stream; + } + + public int GribVersion => 2; + + public string Name => _message.DataSets.Single() + .ProductDefinitionSection.ProductDefinition?.Parameter?.Name ?? + (ChemicalOrPhysicalConsistent.HasValue + ? Enum.GetName(typeof(ChemicalOrPhysicalConsistent), ChemicalOrPhysicalConsistent.Value) + : (string) null); + + public DateTime Time + { + get + { + var reference = _message.IdentificationSection.ReferenceTime; + var productDefinition = + (ProductDefinition0000) _message.DataSets.Single().ProductDefinitionSection.ProductDefinition; + var time = productDefinition + .ForecastTime; + var unit = productDefinition.TimeRangeUnitGrib2; + var result = unit switch + { + TimeRangeUnitGrib2.Minute => reference.AddMinutes(time), + TimeRangeUnitGrib2.Hour => reference.AddHours(time), + TimeRangeUnitGrib2.Day => reference.AddDays(time), + TimeRangeUnitGrib2.Month => reference.AddMonths(time), + TimeRangeUnitGrib2.Year => reference.AddYears(time), + TimeRangeUnitGrib2.Decade => reference.AddYears(10 * time), + TimeRangeUnitGrib2.Normal => reference.AddYears(30 * time), + TimeRangeUnitGrib2.Century => reference.AddYears(100 * time), + TimeRangeUnitGrib2.Hours3 => reference.AddHours(3 * time), + TimeRangeUnitGrib2.Hours6 => reference.AddHours(6 * time), + TimeRangeUnitGrib2.Hours12 => reference.AddHours(12 * time), + TimeRangeUnitGrib2.Second => reference.AddSeconds(time), + TimeRangeUnitGrib2.Missing => + throw new NotSupportedException("Код единицы измерения на момент реализации отсустствовал"), + _ => throw new NotSupportedException("Логика для этого кода единицы измерения не была примененена в этой функции") + }; + return result; + } + } + + public ChemicalOrPhysicalConsistent? ChemicalOrPhysicalConsistent => + (_message.DataSets.Single().ProductDefinitionSection.ProductDefinition as ProductDefinition0040) + ?.ChemicalOrPhysicalConsistent; + + public int? StartStep => + (_message.DataSets.Single().ProductDefinitionSection.ProductDefinition as ProductDefinition0000) + ?.HoursAfter; + + + public IEnumerable> GetData() + { + using var reader = new BufferedBinaryReader(_stream, true); + return _message.DataSets.Single().GetData(reader); + } + + public int Version => 2; + + public int ParameterHash + { + get + { + var param = _message.IdentificationSection; + return (param.Section,param.Length,param.Center,param.CenterCode,param.ProductStatus, + param.ProductType,param.LocalTableVersion,param.MasterTableVersion, + param.ReferenceTimeSignificance,param.SubCenterCode,param).GetHashCode(); + } + } +} \ No newline at end of file diff --git a/src/NGrib/Common/CommonGribFile.cs b/src/NGrib/Common/CommonGribFile.cs new file mode 100644 index 0000000..f9f3da2 --- /dev/null +++ b/src/NGrib/Common/CommonGribFile.cs @@ -0,0 +1,95 @@ +using System.Text; +using NGrib.Common.Adapters; +using NGrib.Grib1; +using NGrib.Grib2; + +namespace NGrib.Common; + +public class CommonGribFile : IGribFile +{ + private readonly Grib1FileAdapter _grib1File = new(new Grib1File()); + private readonly Grib2FileAdapter _grib2File = new(new Grib2File()); + + + public static bool SeekHeader(Stream raf, long stop, out long startOffset) + { + // seek header + StringBuilder hdr = new StringBuilder(); + int match = 0; + startOffset = -1; + + while (raf.Position < stop && raf.Position Grib edition number 1, 2 or 0 not a Grib file. + /// + /// + /// NotSupportedException + /// int 0 not a Grib file, 1 Grib1, 2 Grib2 + /// + private static int GetEdition(Stream InputStream, out long offset) + { + long length = (InputStream.Length < 4000L) ? InputStream.Length :InputStream.Position + 4000L; + if (!SeekHeader(InputStream, length, out offset)) + { + return 0; // not valid Grib file + } + + // Read Section 0 Indicator Section to get Edition number + Grib1IndicatorSection isRenamed = new Grib1IndicatorSection(InputStream); // section 0 + return isRenamed.GribEdition; + } + + public IGribMessage GetMessage(Stream stream) + { + var edition = GetEdition(stream, out var offset); + if (edition == 0 && offset == -1) + return null; + switch (edition) + { + case 1: + stream.Seek(offset+4, SeekOrigin.Begin); + return _grib1File.GetMessage(stream); + case 2: + stream.Seek(offset, SeekOrigin.Begin); + return _grib2File.GetMessage(stream); + default: + throw new NotSupportedException(); + } + } +} \ No newline at end of file diff --git a/src/NGrib/Common/IGribFile.cs b/src/NGrib/Common/IGribFile.cs new file mode 100644 index 0000000..5768a43 --- /dev/null +++ b/src/NGrib/Common/IGribFile.cs @@ -0,0 +1,6 @@ +namespace NGrib.Common; + +public interface IGribFile +{ + IGribMessage GetMessage(Stream stream); +} \ No newline at end of file diff --git a/src/NGrib/Common/IGribMessage.cs b/src/NGrib/Common/IGribMessage.cs new file mode 100644 index 0000000..2271c5c --- /dev/null +++ b/src/NGrib/Common/IGribMessage.cs @@ -0,0 +1,15 @@ +namespace NGrib.Common; + +public interface IGribMessage +{ + DateTime Time { get; } + + string Name { get; } + + IEnumerable> GetData(); + + int Version { get; } + //int ParameterNumber { get; set; } + + int ParameterHash { get; } +} \ No newline at end of file diff --git a/src/NGrib/Constants.cs b/src/NGrib/Constants.cs index 4757d95..60c57a7 100644 --- a/src/NGrib/Constants.cs +++ b/src/NGrib/Constants.cs @@ -1,43 +1,42 @@ -/* - * This file is part of NGrib. - * - * Copyright 2020 Nicolas Mangu - * - * NGrib is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * NGrib is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with NGrib. If not, see . - */ - -namespace NGrib -{ - internal class Constants - { - public static byte[] GribFileStart = { 0x47, 0x52, 0x49, 0x42 }; - - /// - /// "GRIB" (coded according to the International Alphabet No. 5.) - /// converted to long. - /// - public static long GribFileStartCode = 1196575042; - - public static byte[] GribFileEnd = { 0x37, 0x37, 0x37, 0x37 }; - - /// - /// "7777" (coded according to the International Alphabet No. 5.) - /// converted to long. - /// - public static long GribFileEndCode = 926365495; - - public static long IndicatorSectionLength = 16; - public static long EndSectionLength = 16; - } +/* + * This file is part of NGrib. + * + * Copyright © 2020 Nicolas Manguй + * + * NGrib is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * NGrib is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with NGrib. If not, see . + */ + +namespace NGrib; + +internal class Constants +{ + public static byte[] GribFileStart = { 0x47, 0x52, 0x49, 0x42 }; + + /// + /// "GRIB" (coded according to the International Alphabet No. 5.) + /// converted to long. + /// + public static long GribFileStartCode = 1196575042; + + public static byte[] GribFileEnd = { 0x37, 0x37, 0x37, 0x37 }; + + /// + /// "7777" (coded according to the International Alphabet No. 5.) + /// converted to long. + /// + public static long GribFileEndCode = 926365495; + + public static long IndicatorSectionLength = 16; + public static long EndSectionLength = 16; } \ No newline at end of file diff --git a/src/NGrib/Coordinate.cs b/src/NGrib/Coordinate.cs index 5fbb0d2..8c43548 100644 --- a/src/NGrib/Coordinate.cs +++ b/src/NGrib/Coordinate.cs @@ -17,74 +17,75 @@ * along with NGrib. If not, see . */ -using System; +namespace NGrib; -namespace NGrib +/// +/// Represents a location on the Earth surface. +/// +public readonly struct Coordinate { - /// - /// Represents a location on the Earth surface. - /// - public readonly struct Coordinate - { - private const int CoordinateNbDecimals = 9; // 9 decimals means a 110 microns precision. - private const double CoordinatePrecision = 1e-9; + private const int CoordinateNbDecimals = 9; // 9 decimals means a 110 microns precision. + private const double CoordinatePrecision = 1e-9; + + private static double ConvertLongitude(double longitude) => longitude >= 180d ? longitude - 360d : longitude; - /// - /// Specifies the north–south position. - /// - public double Latitude { get; } + /// + /// Specifies the north–south position. + /// + public double Latitude { get; } - /// - /// Specifies the east–west position. - /// - public double Longitude { get; } + /// + /// Specifies the east–west position. + /// + public double Longitude { get; } - /// - /// Initializes a new instance of the Coordinate class - /// based on the specified file. - /// - /// Latitude of the point. - /// Longitude of the point. - public Coordinate(double latitude, double longitude) - { - Latitude = Math.Round(Math.Max(Math.Min(latitude, 90d), -90d), CoordinateNbDecimals); - Longitude = Math.Round(-180d <= longitude && longitude <= 180d ? longitude : SimplifyLongitude(longitude), CoordinateNbDecimals); - } + /// + /// Initializes a new instance of the Coordinate class + /// based on the specified file. + /// + /// Latitude of the point. + /// Longitude of the point. + public Coordinate(double latitude, double longitude) + { + Latitude = Math.Round(Math.Max(Math.Min(latitude, 90d), -90d), CoordinateNbDecimals); + var simplyConverted = ConvertLongitude(longitude); + Longitude = Math.Round(simplyConverted is >= -180d and <= 180d ? simplyConverted : SimplifyLongitude(longitude), CoordinateNbDecimals); + + } - private bool IsOnSameLongitude(Coordinate other) => EqualsWithTolerance(Longitude, other.Longitude) || IsAntimeridian(Longitude) && IsAntimeridian(other.Longitude); + private bool IsOnSameLongitude(Coordinate other) => EqualsWithTolerance(Longitude, other.Longitude) || IsAntimeridian(Longitude) && IsAntimeridian(other.Longitude); - private static bool IsAntimeridian(double longitude) => EqualsWithTolerance(Math.Abs(longitude), 180); + private static bool IsAntimeridian(double longitude) => EqualsWithTolerance(Math.Abs(longitude), 180); - public bool Equals(Coordinate other) => EqualsWithTolerance(Latitude, other.Latitude) && IsOnSameLongitude(other); + public bool Equals(Coordinate other) => EqualsWithTolerance(Latitude, other.Latitude) && IsOnSameLongitude(other); - public override bool Equals(object obj) => obj is Coordinate other && Equals(other); + public override bool Equals(object obj) => obj is Coordinate other && Equals(other); - private static bool EqualsWithTolerance(double a, double b) => Math.Abs(a - b) <= CoordinatePrecision; + private static bool EqualsWithTolerance(double a, double b) => Math.Abs(a - b) <= CoordinatePrecision; - public override int GetHashCode() - { - unchecked - { - return (Latitude.GetHashCode() * 397) ^ Longitude.GetHashCode(); - } - } + public override int GetHashCode() + { + unchecked + { + return (Latitude.GetHashCode() * 397) ^ Longitude.GetHashCode(); + } + } - public Coordinate Add(double latitudeIncrement, double longitudeIncrement) - { - return new Coordinate(Latitude + latitudeIncrement, Longitude + longitudeIncrement); - } + public Coordinate Add(double latitudeIncrement, double longitudeIncrement) + { + return new Coordinate(Latitude + latitudeIncrement, Longitude + longitudeIncrement); + } - private static double SimplifyLongitude(double longitude) - { - var radians = longitude.ToRadians(); - return Math.Atan2(Math.Sin(radians), Math.Cos(radians)).ToDegrees(); - } + private static double SimplifyLongitude(double longitude) + { + var radians = longitude.ToRadians(); + return Math.Atan2(Math.Sin(radians), Math.Cos(radians)).ToDegrees(); + } - public static implicit operator Coordinate(ValueTuple latLon) => new Coordinate(latLon.Item1, latLon.Item2); + public static implicit operator Coordinate(ValueTuple latLon) => new Coordinate(latLon.Item1, latLon.Item2); - public override string ToString() - { - return $"{nameof(Latitude)}: {Latitude}, {nameof(Longitude)}: {Longitude}"; - } - } -} + public override string ToString() + { + return $"{nameof(Latitude)}: {Latitude}, {nameof(Longitude)}: {Longitude}"; + } +} \ No newline at end of file diff --git a/src/NGrib/Extensions.cs b/src/NGrib/Extensions.cs index b1bf0bf..2d7d6f0 100644 --- a/src/NGrib/Extensions.cs +++ b/src/NGrib/Extensions.cs @@ -17,61 +17,58 @@ * along with NGrib. If not, see . */ -using System; +namespace NGrib; -namespace NGrib +internal static class Extensions { - internal static class Extensions - { - /// - /// Convert to radians. - /// - /// The value to convert to radians - /// The value in radians - public static double ToRadians(this double val) => Math.PI / 180d * val; + /// + /// Convert to radians. + /// + /// The value to convert to radians + /// The value in radians + public static double ToRadians(this double val) => Math.PI / 180d * val; - /// - /// Convert to degrees. - /// - /// The value to convert to degrees - /// The value in degrees - public static double ToDegrees(this double val) => 180d / Math.PI * val; + /// + /// Convert to degrees. + /// + /// The value to convert to degrees + /// The value in degrees + public static double ToDegrees(this double val) => 180d / Math.PI * val; - public static T? As(this int val) where T : struct, Enum, IConvertible - { - if (IsFlagEnum(typeof(T))) - { + public static T? As(this int val) where T : struct, Enum, IConvertible + { + if (IsFlagEnum(typeof(T))) + { - } - return (T?) (Enum.IsDefined(typeof(T), val) ? Enum.ToObject(typeof(T), val) : null); - } + } + return (T?) (Enum.IsDefined(typeof(T), val) ? Enum.ToObject(typeof(T), val) : null); + } - public static bool IsFlagEnum(Type t) => t.IsEnum && !Attribute.IsDefined(t, typeof(FlagsAttribute)); + public static bool IsFlagEnum(Type t) => t.IsEnum && !Attribute.IsDefined(t, typeof(FlagsAttribute)); - public static int AsSignedInt(this int value, int nbBit) - { - if (value.GetBit(nbBit)) - { - // The sign bit is on => it's negative! - // Reset leading bit - value = value.SetBit(nbBit, false); - // build 2's-complement - value = ~value; - value += 1; - } + public static int AsSignedInt(this int value, int nbBit) + { + if (value.GetBit(nbBit)) + { + // The sign bit is on => it's negative! + // Reset leading bit + value = value.SetBit(nbBit, false); + // build 2's-complement + value = ~value; + value += 1; + } - return value; - } + return value; + } - public static bool GetBit(this int value, int index) - { - var mask = 1 << (index -1); - return (value & mask) > 0; - } + public static bool GetBit(this int value, int index) + { + var mask = 1 << (index -1); + return (value & mask) > 0; + } - public static int SetBit(this int value, int index, bool bitValue) - { - return bitValue ? value | (1 << (index - 1)) : value & ~(1 << (index - 1)); - } - } -} + public static int SetBit(this int value, int index, bool bitValue) + { + return bitValue ? value | (1 << (index - 1)) : value & ~(1 << (index - 1)); + } +} \ No newline at end of file diff --git a/src/NGrib/Grib1/GdsKeys.cs b/src/NGrib/Grib1/GdsKeys.cs new file mode 100644 index 0000000..2ebae55 --- /dev/null +++ b/src/NGrib/Grib1/GdsKeys.cs @@ -0,0 +1,81 @@ +namespace NGrib.Grib1; + +public sealed class GdsKeys +{ + /* + * stores GDS of Grib1 file, there is possibility of more than 1 + */ + //UPGRADE_NOTE: Final was removed from the declaration of 'gdsHM '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'" + //UPGRADE_TODO: Class 'java.util.HashMap' was converted to 'System.Collections.Hashtable' which has a different behavior. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1073_javautilHashMap'" + /// Get GDS's of the GRIB file. + /// + /// + /// gdsHM + /// + //UPGRADE_TODO: Class 'java.util.HashMap' was converted to 'System.Collections.Hashtable' which has a different behavior. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1073_javautilHashMap'" + public System.Collections.Hashtable GdSs { get; } = new(); + + /* + * stores products of Grib file, products have enough info to get the + * metadata about a parameter and the data. products are lightweight + * records. + */ + //UPGRADE_NOTE: Final was removed from the declaration of 'products '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'" + //private Grib1Input _grib1Input; + /// Get products of the GRIB file. + /// + /// + /// products + /// + public System.Collections.ArrayList Products { get; } = new(); + + public void CheckGdSkeys(Grib1GridDefinitionSection gds, System.Collections.Hashtable gdsCounter) + { + // lat/lon grids can have > 1 GDSs + if (gds.GridType == 0 || gds.GridType == 4) + { + return; + } + + String bestKey = ""; + int count = 0; + // find bestKey with the most counts + //UPGRADE_TODO: Method 'java.util.HashMap.keySet' was converted to 'SupportClass.HashSetSupport' which has a different behavior. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1073_javautilHashMapkeySet'" + //UPGRADE_TODO: Method 'java.util.Iterator.hasNext' was converted to 'System.Collections.IEnumerator.MoveNext' which has a different behavior. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1073_javautilIteratorhasNext'" + for (System.Collections.IEnumerator it = new SupportClass.HashSetSupport(gdsCounter.Keys).GetEnumerator(); + it.MoveNext();) + { + //UPGRADE_TODO: Method 'java.util.Iterator.next' was converted to 'System.Collections.IEnumerator.Current' which has a different behavior. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1073_javautilIteratornext'" + String key = (String) it.Current; + //UPGRADE_TODO: Method 'java.util.HashMap.get' was converted to 'System.Collections.Hashtable.Item' which has a different behavior. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1073_javautilHashMapget_javalangObject'" + int gdsCount = Int32.Parse((String) gdsCounter[key]); + if (gdsCount > count) + { + count = gdsCount; + bestKey = key; + } + } + + // remove best key from gdsCounter, others will be removed from gdsHM + gdsCounter.Remove(bestKey); + // remove all GDSs using the gdsCounter + //UPGRADE_TODO: Method 'java.util.HashMap.keySet' was converted to 'SupportClass.HashSetSupport' which has a different behavior. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1073_javautilHashMapkeySet'" + //UPGRADE_TODO: Method 'java.util.Iterator.hasNext' was converted to 'System.Collections.IEnumerator.MoveNext' which has a different behavior. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1073_javautilIteratorhasNext'" + for (System.Collections.IEnumerator it = new SupportClass.HashSetSupport(gdsCounter.Keys).GetEnumerator(); + it.MoveNext();) + { + //UPGRADE_TODO: Method 'java.util.Iterator.next' was converted to 'System.Collections.IEnumerator.Current' which has a different behavior. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1073_javautilIteratornext'" + String key = (String) it.Current; + GdSs.Remove(key); + } + + // reset GDS keys in products too + for (int i = 0; i < Products.Count; i++) + { + Grib1Product g1P = (Grib1Product) Products[i]; + g1P.GDSkey = bestKey; + } + + return; + } +} \ No newline at end of file diff --git a/src/NGrib/Grib1/Grib1BinaryDataSection.cs b/src/NGrib/Grib1/Grib1BinaryDataSection.cs index 3434a48..7fcf245 100644 --- a/src/NGrib/Grib1/Grib1BinaryDataSection.cs +++ b/src/NGrib/Grib1/Grib1BinaryDataSection.cs @@ -1,7 +1,7 @@ /* * This file is part of NGrib. * - * Copyright 2020 Nicolas Mangu + * Copyright � 2020 Nicolas Mangu� * * Copyright 2006-2010 Seaware AB, PO Box 1244, SE-131 28 * Nacka Strand, Sweden, info@seaware.se. @@ -24,228 +24,225 @@ * along with NGrib. If not, see . */ -using System; +namespace NGrib.Grib1; -namespace NGrib.Grib1 +/// +/// A class representing the binary data section (BDS) of a GRIB record. +/// +public sealed class Grib1BinaryDataSection { - /// - /// A class representing the binary data section (BDS) of a GRIB record. - /// - public sealed class Grib1BinaryDataSection - { - /// - /// Grid values as an array of float. - /// - public float[] Values { get; } - - /// - /// Constant value for an undefined grid value. - /// - public static float MissingValue { get; } = -9999f; - - /// - /// Length in bytes of this BDS. - /// - private int length; - - /// - /// Buffer for one byte which will be processed bit by bit. - /// - private int bitBuf; - - /// - /// Current bit position in bitBuf. - /// - private int bitPos; - - /// Indicates whether the BMS is represented by a single value - /// Octet 12 is empty, and the data is represented by the reference value. - /// - private bool isConstant; - - /// Constructs a Grib1BinaryDataSection object from a raf. - /// A bit map is defined. - /// - /// - /// raf with BDS content - /// - /// the exponent of the decimal scale - /// - /// bit map section of GRIB record - /// - /// - /// NotSupportedException if stream contains no valid GRIB file - //UPGRADE_TODO: Class 'java.io.RandomAccessFile' was converted to 'System.IO.FileStream' which has a different behavior. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1073_javaioRandomAccessFile'" - internal Grib1BinaryDataSection(System.IO.Stream raf, int decimalscale, Grib1BitMapSection bms) - { - // octets 1-3 (section length) - length = (int) GribNumbers.uint3(raf); - - - // octet 4, 1st half (packing flag) - int unusedbits = raf.ReadByte(); - - // TODO Check this!!! - if ((unusedbits & 192) != 0) - throw new NotSupportedException("BDS: (octet 4, 1st half) not grid point data and simple packing "); - - // octet 4, 2nd half (number of unused bits at end of this section) - unusedbits = unusedbits & 15; - - - // octets 5-6 (binary scale factor) - int binscale = GribNumbers.int2(raf); - - // octets 7-10 (reference point = minimum value) - float refvalue = GribNumbers.float4(raf); - - // octet 11 (number of bits per value) - int numbits = raf.ReadByte(); - - if (numbits == 0) - isConstant = true; - - - // *** read values ******************************************************* - - //UPGRADE_WARNING: Data types in Visual C# might be different. Verify the accuracy of narrowing conversions. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1042'" - float ref_Renamed = (float) (Math.Pow(10.0, -decimalscale) * refvalue); - //UPGRADE_WARNING: Data types in Visual C# might be different. Verify the accuracy of narrowing conversions. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1042'" - float scale = (float) (Math.Pow(10.0, -decimalscale) * Math.Pow(2.0, binscale)); - - if (bms != null) - { - bool[] bitmap = bms.Bitmap; - - Values = new float[bitmap.Length]; - for (int i = 0; i < bitmap.Length; i++) - { - if (bitmap[i]) - { - if (!isConstant) - { - Values[i] = ref_Renamed + scale * bits2UInt(numbits, raf); - } - else - { - // rdg - added this to handle a constant valued parameter - Values[i] = ref_Renamed; - } - } - else - Values[i] = MissingValue; - } - } - else - { - // bms is null - if (!isConstant) - { - - //(((length - 11) * 8 - unusedbits) / numbits)); - Values = new float[((length - 11) * 8 - unusedbits) / numbits]; - - for (int i = 0; i < Values.Length; i++) - { - Values[i] = ref_Renamed + scale * bits2UInt(numbits, raf); - } - } - else - { - // constant valued - same min and max - int x = 0, y = 0; - raf.Seek(raf.Position - 53, System.IO.SeekOrigin.Begin); // return to start of GDS - length = (int) GribNumbers.uint3(raf); - if (length == 42) - { - // Lambert/Mercator offset - SupportClass.Skip(raf, 3); - x = GribNumbers.int2(raf); - y = GribNumbers.int2(raf); - } - else - { - SupportClass.Skip(raf, 7); - length = (int) GribNumbers.uint3(raf); - if (length == 32) - { - // Polar sterographic - SupportClass.Skip(raf, 3); - x = GribNumbers.int2(raf); - y = GribNumbers.int2(raf); - } - else - { - x = y = 1; - Console.Out.WriteLine("BDS constant value, can't determine array size"); - } - } - - Values = new float[x * y]; - for (int i = 0; i < Values.Length; i++) - Values[i] = ref_Renamed; - } - } - } // end Grib1BinaryDataSection - - /// Convert bits (nb) to Unsigned Int . - /// - /// - /// - /// - /// - /// - /// int of BinaryDataSection section - /// - //UPGRADE_TODO: Class 'java.io.RandomAccessFile' was converted to 'System.IO.FileStream' which has a different behavior. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1073_javaioRandomAccessFile'" - private int bits2UInt(int nb, System.IO.Stream raf) - { - int bitsLeft = nb; - int result = 0; - - if (bitPos == 0) - { - bitBuf = raf.ReadByte(); - bitPos = 8; - } - - while (true) - { - int shift = bitsLeft - bitPos; - if (shift > 0) - { - // Consume the entire buffer - result |= bitBuf << shift; - bitsLeft -= bitPos; - - // Get the next byte from the RandomAccessFile - bitBuf = raf.ReadByte(); - bitPos = 8; - } - else - { - // Consume a portion of the buffer - result |= bitBuf >> -shift; - bitPos -= bitsLeft; - bitBuf &= 0xff >> (8 - bitPos); // mask off consumed bits - - return result; - } - } // end while - } // end bits2Int - - // *** public methods **************************************************** - - // --Commented out by Inspection START (11/17/05 1:25 PM): - // /** - // * Get the length in bytes of this section. - // * - // * @return length in bytes of this section - // */ - // public int getLength() - // { - // return length; - // } - // --Commented out by Inspection STOP (11/17/05 1:25 PM) - } // end class Grib1BinaryDataSection -} \ No newline at end of file + /// + /// Grid values as an array of float. + /// + public double[] Values { get; } + + /// + /// Constant value for an undefined grid value. + /// + public static double MissingValue { get; } = -9999d; + + /// + /// Length in bytes of this BDS. + /// + private int length; + + /// + /// Buffer for one byte which will be processed bit by bit. + /// + private int bitBuf; + + /// + /// Current bit position in bitBuf. + /// + private int bitPos; + + /// Indicates whether the BMS is represented by a single value + /// Octet 12 is empty, and the data is represented by the reference value. + /// + private bool isConstant; + + /// Constructs a Grib1BinaryDataSection object from a raf. + /// A bit map is defined. + /// + /// + /// raf with BDS content + /// + /// the exponent of the decimal scale + /// + /// bit map section of GRIB record + /// + /// + /// NotSupportedException if stream contains no valid GRIB file + //UPGRADE_TODO: Class 'java.io.RandomAccessFile' was converted to 'System.IO.FileStream' which has a different behavior. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1073_javaioRandomAccessFile'" + internal Grib1BinaryDataSection(System.IO.Stream raf, int decimalscale, Grib1BitMapSection bms) + { + // octets 1-3 (section length) + length = (int) GribNumbers.uint3(raf); + + + // octet 4, 1st half (packing flag) + int unusedbits = raf.ReadByte(); + + // TODO Check this!!! + if ((unusedbits & 192) != 0) + throw new NotSupportedException("BDS: (octet 4, 1st half) not grid point data and simple packing "); + + // octet 4, 2nd half (number of unused bits at end of this section) + unusedbits = unusedbits & 15; + + + // octets 5-6 (binary scale factor) + int binscale = GribNumbers.int2(raf); + + // octets 7-10 (reference point = minimum value) + double refvalue = GribNumbers.double4(raf); + + // octet 11 (number of bits per value) + int numbits = raf.ReadByte(); + + if (numbits == 0) + isConstant = true; + + + // *** read values ******************************************************* + + //UPGRADE_WARNING: Data types in Visual C# might be different. Verify the accuracy of narrowing conversions. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1042'" + double ref_Renamed = (Math.Pow(10.0d, -decimalscale) * refvalue); + //UPGRADE_WARNING: Data types in Visual C# might be different. Verify the accuracy of narrowing conversions. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1042'" + double scale = (Math.Pow(10.0d, -decimalscale) * Math.Pow(2.0d, binscale)); + + if (bms != null) + { + bool[] bitmap = bms.Bitmap; + + Values = new double[bitmap.Length]; + for (int i = 0; i < bitmap.Length; i++) + { + if (bitmap[i]) + { + if (!isConstant) + { + Values[i] = ref_Renamed + scale * bits2UInt(numbits, raf); + } + else + { + // rdg - added this to handle a constant valued parameter + Values[i] = ref_Renamed; + } + } + else + Values[i] = MissingValue; + } + } + else + { + // bms is null + if (!isConstant) + { + + //(((length - 11) * 8 - unusedbits) / numbits)); + Values = new double[((length - 11) * 8 - unusedbits) / numbits]; + + for (int i = 0; i < Values.Length; i++) + { + Values[i] = ref_Renamed + scale * bits2UInt(numbits, raf); + } + } + else + { + // constant valued - same min and max + int x = 0, y = 0; + raf.Seek(raf.Position - 53, System.IO.SeekOrigin.Begin); // return to start of GDS + length = (int) GribNumbers.uint3(raf); + if (length == 42) + { + // Lambert/Mercator offset + SupportClass.Skip(raf, 3); + x = GribNumbers.int2(raf); + y = GribNumbers.int2(raf); + } + else + { + SupportClass.Skip(raf, 7); + length = (int) GribNumbers.uint3(raf); + if (length == 32) + { + // Polar sterographic + SupportClass.Skip(raf, 3); + x = GribNumbers.int2(raf); + y = GribNumbers.int2(raf); + } + else + { + x = y = 1; + Console.Out.WriteLine("BDS constant value, can't determine array size"); + } + } + + Values = new double[x * y]; + for (int i = 0; i < Values.Length; i++) + Values[i] = ref_Renamed; + } + } + } // end Grib1BinaryDataSection + + /// Convert bits (nb) to Unsigned Int . + /// + /// + /// + /// + /// + /// + /// int of BinaryDataSection section + /// + //UPGRADE_TODO: Class 'java.io.RandomAccessFile' was converted to 'System.IO.FileStream' which has a different behavior. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1073_javaioRandomAccessFile'" + private int bits2UInt(int nb, System.IO.Stream raf) + { + int bitsLeft = nb; + int result = 0; + + if (bitPos == 0) + { + bitBuf = raf.ReadByte(); + bitPos = 8; + } + + while (true) + { + int shift = bitsLeft - bitPos; + if (shift > 0) + { + // Consume the entire buffer + result |= bitBuf << shift; + bitsLeft -= bitPos; + + // Get the next byte from the RandomAccessFile + bitBuf = raf.ReadByte(); + bitPos = 8; + } + else + { + // Consume a portion of the buffer + result |= bitBuf >> -shift; + bitPos -= bitsLeft; + bitBuf &= 0xff >> (8 - bitPos); // mask off consumed bits + + return result; + } + } // end while + } // end bits2Int + + // *** public methods **************************************************** + + // --Commented out by Inspection START (11/17/05 1:25 PM): + // /** + // * Get the length in bytes of this section. + // * + // * @return length in bytes of this section + // */ + // public int getLength() + // { + // return length; + // } + // --Commented out by Inspection STOP (11/17/05 1:25 PM) +} // end class Grib1BinaryDataSection \ No newline at end of file diff --git a/src/NGrib/Grib1/Grib1BitMapSection.cs b/src/NGrib/Grib1/Grib1BitMapSection.cs index d9f4dc5..2a146b6 100644 --- a/src/NGrib/Grib1/Grib1BitMapSection.cs +++ b/src/NGrib/Grib1/Grib1BitMapSection.cs @@ -24,68 +24,67 @@ * along with NGrib. If not, see . */ -namespace NGrib.Grib1 +namespace NGrib.Grib1; + +/// A class that represents the bitmap section (BMS) of a GRIB record. It +/// indicates grid points where no grid value is defined by a 0. +/// +/// +/// 1.0 +/// +public sealed class Grib1BitMapSection { - /// A class that represents the bitmap section (BMS) of a GRIB record. It - /// indicates grid points where no grid value is defined by a 0. - /// - /// - /// 1.0 - /// - public sealed class Grib1BitMapSection - { - /// Get bit map. - /// - /// - /// bit map as array of boolean values - /// - public bool[] Bitmap { get; } + /// Get bit map. + /// + /// + /// bit map as array of boolean values + /// + public bool[] Bitmap { get; } - /// Length in bytes of this section. - //UPGRADE_NOTE: Final was removed from the declaration of 'length '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'" - private int length; + /// Length in bytes of this section. + //UPGRADE_NOTE: Final was removed from the declaration of 'length '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'" + private int length; - /// Constructs a Grib1BitMapSection object from a raf input stream. - /// - /// - /// input stream with BMS content - /// - /// - //UPGRADE_TODO: Class 'java.io.RandomAccessFile' was converted to 'System.IO.FileStream' which has a different behavior. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1073_javaioRandomAccessFile'" - internal Grib1BitMapSection(System.IO.Stream raf) - { - int[] bitmask = new int[] {128, 64, 32, 16, 8, 4, 2, 1}; + /// Constructs a Grib1BitMapSection object from a raf input stream. + /// + /// + /// input stream with BMS content + /// + /// + //UPGRADE_TODO: Class 'java.io.RandomAccessFile' was converted to 'System.IO.FileStream' which has a different behavior. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1073_javaioRandomAccessFile'" + internal Grib1BitMapSection(System.IO.Stream raf) + { + int[] bitmask = new int[] {128, 64, 32, 16, 8, 4, 2, 1}; - // octet 1-3 (length of section) - length = (int) GribNumbers.uint3(raf); + // octet 1-3 (length of section) + length = (int) GribNumbers.uint3(raf); - // octet 4 unused bits - int unused = raf.ReadByte(); + // octet 4 unused bits + int unused = raf.ReadByte(); - // octets 5-6 - int bm = GribNumbers.int2(raf); - if (bm != 0) - { - System.Console.Out.WriteLine("BMS pre-defined BM provided by center"); - if ((length - 6) == 0) - return; - sbyte[] data = new sbyte[length - 6]; - SupportClass.ReadInput(raf, data, 0, data.Length); - return; - } + // octets 5-6 + int bm = GribNumbers.int2(raf); + if (bm != 0) + { + System.Console.Out.WriteLine("BMS pre-defined BM provided by center"); + if ((length - 6) == 0) + return; + sbyte[] data = new sbyte[length - 6]; + SupportClass.ReadInput(raf, data, 0, data.Length); + return; + } - sbyte[] data2 = new sbyte[length - 6]; - SupportClass.ReadInput(raf, data2, 0, data2.Length); + sbyte[] data2 = new sbyte[length - 6]; + SupportClass.ReadInput(raf, data2, 0, data2.Length); - // create new bit map, octet 4 contains number of unused bits at the end - Bitmap = new bool[(length - 6) * 8 - unused]; + // create new bit map, octet 4 contains number of unused bits at the end + Bitmap = new bool[(length - 6) * 8 - unused]; - // fill bit map - for (int i = 0; i < Bitmap.Length; i++) - Bitmap[i] = (data2[i / 8] & bitmask[i % 8]) != 0; - } // end Grib1BitMapSection - } // end Grib1BitMapSection -} \ No newline at end of file + // fill bit map + for (int i = 0; i < Bitmap.Length; i++) + Bitmap[i] = (data2[i / 8] & bitmask[i % 8]) != 0; + } // end Grib1BitMapSection +} // end Grib1BitMapSection \ No newline at end of file diff --git a/src/NGrib/Grib1/Grib1Data.cs b/src/NGrib/Grib1/Grib1Data.cs index e1b920a..314cda1 100644 --- a/src/NGrib/Grib1/Grib1Data.cs +++ b/src/NGrib/Grib1/Grib1Data.cs @@ -1,7 +1,7 @@ /* * This file is part of NGrib. * - * Copyright 2020 Nicolas Mangu + * Copyright � 2020 Nicolas Mangu� * * Copyright 2006-2010 Seaware AB, PO Box 1244, SE-131 28 * Nacka Strand, Sweden, info@seaware.se. @@ -24,74 +24,48 @@ * along with NGrib. If not, see . */ -namespace NGrib.Grib1 -{ - /// A class used to extract data from a GRIB1 file. - /// see IndexFormat.txt - /// - public sealed class Grib1Data - { - /* - * used to hold open file descriptor - */ - //UPGRADE_TODO: Class 'java.io.RandomAccessFile' was converted to 'System.IO.FileStream' which has a different behavior. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1073_javaioRandomAccessFile'" - private System.IO.Stream raf; - - // *** constructors ******************************************************* - - /// Constructs a Grib2Data object from a stream. - /// - /// - /// ucar.unidata.io.RandomAccessFile with GRIB content. - /// - /// - //UPGRADE_TODO: Class 'java.io.RandomAccessFile' was converted to 'System.IO.FileStream' which has a different behavior. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1073_javaioRandomAccessFile'" - public Grib1Data(System.IO.Stream raf) - { - this.raf = raf; - } +namespace NGrib.Grib1; - public void setFilename(string filename) - { - raf = new System.IO.FileStream(filename, System.IO.FileMode.Open, System.IO.FileAccess.Read); - } - - public void closeFile() - { - raf.Close(); - } +/// A class used to extract data from a GRIB1 file. +/// see IndexFormat.txt +/// +public sealed class Grib1Data +{ + /* + * used to hold open file descriptor + */ + //UPGRADE_TODO: Class 'java.io.RandomAccessFile' was converted to 'System.IO.FileStream' which has a different behavior. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1073_javaioRandomAccessFile'" + private System.IO.Stream raf; - /// Reads the Grib data - /// - /// - /// offset into file. - /// - /// - /// - /// - /// - /// NotSupportedException - /// float[] - /// - public float[] getData(long offset, int DecimalScale, bool bmsExists) - { - long start = (System.DateTime.Now.Ticks - 621355968000000000) / 10000; + private readonly Grib1File _grib1File; - raf.Seek(offset, System.IO.SeekOrigin.Begin); + // *** constructors ******************************************************* + /// Constructs a Grib2Data object from a stream. + /// + /// + /// ucar.unidata.io.RandomAccessFile with GRIB content. + /// + /// + //UPGRADE_TODO: Class 'java.io.RandomAccessFile' was converted to 'System.IO.FileStream' which has a different behavior. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1073_javaioRandomAccessFile'" + public Grib1Data(System.IO.Stream raf, Grib1File grib1File) + { + this.raf = raf; + _grib1File = grib1File; + } - // Need section 3 and 4 to read/interpet the data, section 5 - // as a check that all data read and sections are correct + public void setFilename(string filename) + { + raf = new System.IO.FileStream(filename, System.IO.FileMode.Open, System.IO.FileAccess.Read); + } - Grib1BitMapSection bms = null; - if (bmsExists) - // read Bit Mapped Section 3 - bms = new Grib1BitMapSection(raf); + public void closeFile() + { + raf.Close(); + } - // read Binary Data Section 4 - Grib1BinaryDataSection bds = new Grib1BinaryDataSection(raf, DecimalScale, bms); + public double[] getData(long offset, int DecimalScale, bool bmsExists) => + _grib1File.getData(raf, offset, DecimalScale, bmsExists); - return bds.Values; - } // end getData - } // end Grib1Data -} \ No newline at end of file + // end getData +} // end Grib1Data \ No newline at end of file diff --git a/src/NGrib/Grib1/Grib1EndSection.cs b/src/NGrib/Grib1/Grib1EndSection.cs index b9aa778..f979f9f 100644 --- a/src/NGrib/Grib1/Grib1EndSection.cs +++ b/src/NGrib/Grib1/Grib1EndSection.cs @@ -24,80 +24,79 @@ * along with NGrib. If not, see . */ -namespace NGrib.Grib1 +namespace NGrib.Grib1; + +/// A class that represents the EndSection of a GRIB1 product. +/// +/// +sealed class Grib1EndSection { - /// A class that represents the EndSection of a GRIB1 product. - /// - /// - sealed class Grib1EndSection - { - /// Get ending flag for Grib record. - /// - /// - /// true if "7777" found - /// - public bool EndFound - { - get { return endFound; } + /// Get ending flag for Grib record. + /// + /// + /// true if "7777" found + /// + public bool EndFound + { + get { return endFound; } - // --Commented out by Inspection START (11/17/05 1:32 PM): - // /** - // * how long was the ending, should be 4 bytes. - // * @return int - // */ - // public static final int getLength() - // { - // return length; - // } - // --Commented out by Inspection STOP (11/17/05 1:32 PM) - } + // --Commented out by Inspection START (11/17/05 1:32 PM): + // /** + // * how long was the ending, should be 4 bytes. + // * @return int + // */ + // public static final int getLength() + // { + // return length; + // } + // --Commented out by Inspection STOP (11/17/05 1:32 PM) + } - /* - * was the grib endding 7777 found. - */ - private bool endFound; + /* + * was the grib endding 7777 found. + */ + private bool endFound; - /* - * how long was the ending, should be 4 bytes. - */ - private int length; + /* + * how long was the ending, should be 4 bytes. + */ + private int length; - // *** constructors ******************************************************* + // *** constructors ******************************************************* - /// Constructs a Grib1EndSection object from a byteBuffer. - /// - /// - /// RandomAccessFile with EndSection content - /// - /// - //UPGRADE_TODO: Class 'java.io.RandomAccessFile' was converted to 'System.IO.FileStream' which has a different behavior. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1073_javaioRandomAccessFile'" - internal Grib1EndSection(System.IO.Stream raf) - { - int match = 0; - while (raf.Position < raf.Length) - { - // code must be "7" "7" "7" "7" - sbyte c = (sbyte) raf.ReadByte(); + /// Constructs a Grib1EndSection object from a byteBuffer. + /// + /// + /// RandomAccessFile with EndSection content + /// + /// + //UPGRADE_TODO: Class 'java.io.RandomAccessFile' was converted to 'System.IO.FileStream' which has a different behavior. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1073_javaioRandomAccessFile'" + internal Grib1EndSection(System.IO.Stream raf) + { + int match = 0; + while (raf.Position < raf.Length) + { + // code must be "7" "7" "7" "7" + sbyte c = (sbyte) raf.ReadByte(); - length++; - if (c == '7') - { - match += 1; + length++; + if (c == '7') + { + match += 1; - } - else - { + } + else + { - match = 0; /* Needed to protect against bad ending case. */ - } + match = 0; /* Needed to protect against bad ending case. */ + } - if (match == 4) - { - endFound = true; + if (match == 4) + { + endFound = true; - break; - } - } - } // end Grib1EndSection - } // end Grib1EndSection -} \ No newline at end of file + break; + } + } + } // end Grib1EndSection +} // end Grib1EndSection \ No newline at end of file diff --git a/src/NGrib/Grib1/Grib1Ensemble.cs b/src/NGrib/Grib1/Grib1Ensemble.cs index 6396aaf..2870112 100644 --- a/src/NGrib/Grib1/Grib1Ensemble.cs +++ b/src/NGrib/Grib1/Grib1Ensemble.cs @@ -29,124 +29,123 @@ /// code is not complete. /// -namespace NGrib.Grib1 +namespace NGrib.Grib1; + +/// Represents an Ensemble product. +/// +/// +public sealed class Grib1Ensemble { - /// Represents an Ensemble product. - /// - /// - public sealed class Grib1Ensemble - { - /// The Type. - private int eType; - - /// The Identification number. - private int eId; - - /// The Product Identifier. - private int eProd; - - /// The Spatial Identifier. - private int eSpatial; - - /// Probability product definition. - private int epd; - - private int ept; - private int epll; - private int epul; - private int eSize; - private int eCSize; - private int eCNumber; - private int eCMethod; - private int nLat; - private int sLat; - private int eLat; - private int wLat; - private sbyte[] cm; - - /// Creates an ensemble object for the product PDS. - /// RandomAccessFile. - /// - /// - /// - /// IOException - //UPGRADE_TODO: Class 'java.io.RandomAccessFile' was converted to 'System.IO.FileStream' which has a different behavior. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1073_javaioRandomAccessFile'" - internal Grib1Ensemble(System.IO.Stream raf, int parameterNumber) - { - // skip 12 bytes to start of ensemble - SupportClass.Skip(raf, 12); - - // octet 41 id's ensemble - int app = raf.ReadByte(); - if (app != 1) - { - System.Console.Out.WriteLine("not ensemble product"); - return; - } - - // octet 42 Type - eType = raf.ReadByte(); - - // octet 43 Identification number - eId = raf.ReadByte(); - - // octet 44 Product Identifier - eProd = raf.ReadByte(); - - // octet 45 Spatial Identifier - eSpatial = raf.ReadByte(); - - if (parameterNumber == 191 || parameterNumber == 192) - { - // octet 46 Probability product definition - epd = raf.ReadByte(); - - // octet 47 Probability type - ept = raf.ReadByte(); - - // octet 48-51 Probability lower limit - epll = GribNumbers.int4(raf); - - // octet 52-55 Probability upper limit - epul = GribNumbers.int4(raf); - - // octet 56-60 reserved - int reserved = GribNumbers.int4(raf); - - if (eType == 4 || eType == 5) - { - // octet 61 Ensemble size - eSize = raf.ReadByte(); - - // octet 62 Cluster size - eCSize = raf.ReadByte(); - - // octet 63 Number of clusters - eCNumber = raf.ReadByte(); - - // octet 64 Clustering Method - eCMethod = raf.ReadByte(); - - // octet 65-67 Northern latitude of clustering domain - nLat = GribNumbers.int3(raf); - - // octet 68-70 Southern latitude of clustering domain - sLat = GribNumbers.int3(raf); - - // octet 71-73 Eastern latitude of clustering domain - eLat = GribNumbers.int3(raf); - - // octet 74-76 Western latitude of clustering domain - wLat = GribNumbers.int3(raf); - - if (eType == 4) - { - // octets 77-86 Cluster Membership - cm = new sbyte[10]; - SupportClass.ReadInput(raf, cm, 0, cm.Length); - } - } - } - } - } // end Grib1Ensemble -} \ No newline at end of file + /// The Type. + private int eType; + + /// The Identification number. + private int eId; + + /// The Product Identifier. + private int eProd; + + /// The Spatial Identifier. + private int eSpatial; + + /// Probability product definition. + private int epd; + + private int ept; + private int epll; + private int epul; + private int eSize; + private int eCSize; + private int eCNumber; + private int eCMethod; + private int nLat; + private int sLat; + private int eLat; + private int wLat; + private sbyte[] cm; + + /// Creates an ensemble object for the product PDS. + /// RandomAccessFile. + /// + /// + /// + /// IOException + //UPGRADE_TODO: Class 'java.io.RandomAccessFile' was converted to 'System.IO.FileStream' which has a different behavior. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1073_javaioRandomAccessFile'" + internal Grib1Ensemble(System.IO.Stream raf, int parameterNumber) + { + // skip 12 bytes to start of ensemble + SupportClass.Skip(raf, 12); + + // octet 41 id's ensemble + int app = raf.ReadByte(); + if (app != 1) + { + System.Console.Out.WriteLine("not ensemble product"); + return; + } + + // octet 42 Type + eType = raf.ReadByte(); + + // octet 43 Identification number + eId = raf.ReadByte(); + + // octet 44 Product Identifier + eProd = raf.ReadByte(); + + // octet 45 Spatial Identifier + eSpatial = raf.ReadByte(); + + if (parameterNumber == 191 || parameterNumber == 192) + { + // octet 46 Probability product definition + epd = raf.ReadByte(); + + // octet 47 Probability type + ept = raf.ReadByte(); + + // octet 48-51 Probability lower limit + epll = GribNumbers.int4(raf); + + // octet 52-55 Probability upper limit + epul = GribNumbers.int4(raf); + + // octet 56-60 reserved + int reserved = GribNumbers.int4(raf); + + if (eType == 4 || eType == 5) + { + // octet 61 Ensemble size + eSize = raf.ReadByte(); + + // octet 62 Cluster size + eCSize = raf.ReadByte(); + + // octet 63 Number of clusters + eCNumber = raf.ReadByte(); + + // octet 64 Clustering Method + eCMethod = raf.ReadByte(); + + // octet 65-67 Northern latitude of clustering domain + nLat = GribNumbers.int3(raf); + + // octet 68-70 Southern latitude of clustering domain + sLat = GribNumbers.int3(raf); + + // octet 71-73 Eastern latitude of clustering domain + eLat = GribNumbers.int3(raf); + + // octet 74-76 Western latitude of clustering domain + wLat = GribNumbers.int3(raf); + + if (eType == 4) + { + // octets 77-86 Cluster Membership + cm = new sbyte[10]; + SupportClass.ReadInput(raf, cm, 0, cm.Length); + } + } + } + } +} // end Grib1Ensemble \ No newline at end of file diff --git a/src/NGrib/Grib1/Grib1File.cs b/src/NGrib/Grib1/Grib1File.cs new file mode 100644 index 0000000..0366c94 --- /dev/null +++ b/src/NGrib/Grib1/Grib1File.cs @@ -0,0 +1,125 @@ +using System.Collections; + +namespace NGrib.Grib1; + +public sealed class Grib1File +{ + /* + * the header of Grib record + */ + private const string _header = "GRIB"; + + private readonly GdsKeys _keys = new(); + + private readonly GdsKeys _gdsKeys = new(); + + + + public Grib1Record ReadGrib1Record(Stream InputStream, long startOffset, Hashtable gdsCounter, ref Grib1GridDefinitionSection gds) + { + Grib1ProductDefinitionSection pds; + // Read Section 0 Indicator Section + Grib1IndicatorSection isRenamed = new Grib1IndicatorSection(InputStream); + + // EOR (EndOfRecord) calculated so skipping data sections is faster + long eor = InputStream.Position + isRenamed.GribLength - isRenamed.Length; + + // Read Section 1 Product Definition Section PDS + pds = new Grib1ProductDefinitionSection(InputStream); + if (pds.LengthErr) + return null; + + if (pds.gdsExists()) + { + // Read Section 2 Grid Definition Section GDS + gds = new Grib1GridDefinitionSection(InputStream); + } + else + { + // GDS doesn't exist so make one + + + gds = (Grib1GridDefinitionSection) new Grib1Grid(pds); + } + + // obtain BMS or BDS offset in the file for this product + long dataOffset; + if (pds.Center == 98) + { + // check for ecmwf offset by 1 bug + int length = (int) GribNumbers.uint3(InputStream); // should be length of BMS + if ((length + InputStream.Position) < eor) + { + dataOffset = InputStream.Position - 3; // ok + } + else + { + dataOffset = InputStream.Position - 2; + } + } + else + { + dataOffset = InputStream.Position; + } + + // position filePointer to EndOfRecord + InputStream.Seek(eor, SeekOrigin.Begin); + + + // assume scan ok + Grib1Record gr = new Grib1Record(_header, isRenamed, pds, gds, dataOffset, InputStream.Position, + startOffset); + + var currentPosition = InputStream.Position; + + InputStream.Position = currentPosition; + + // early return because ending "7777" missing + if (InputStream.Position > InputStream.Length) + { + InputStream.Seek(0, SeekOrigin.Begin); + _gdsKeys.CheckGdSkeys(gds, gdsCounter); + throw new BadGribFormatException("Grib1Input: GRIB ending missing. Possible file corruption"); + } + + return gr; + } + + /// Reads the Grib data + /// + /// + /// offset into file. + /// + /// + /// + /// + /// + /// NotSupportedException + /// float[] + /// + public double[] getData(Stream raf, long offset, int DecimalScale, bool bmsExists) + { + long start = (System.DateTime.Now.Ticks - 621355968000000000) / 10000; + + raf.Seek(offset, System.IO.SeekOrigin.Begin); + + + // Need section 3 and 4 to read/interpet the data, section 5 + // as a check that all data read and sections are correct + + Grib1BitMapSection bms = null; + if (bmsExists) + // read Bit Mapped Section 3 + bms = new Grib1BitMapSection(raf); + + // read Binary Data Section 4 + Grib1BinaryDataSection bds = new Grib1BinaryDataSection(raf, DecimalScale, bms); + + return bds.Values; + } + + public void CheckGdSkeys(Grib1GridDefinitionSection gds, Hashtable gdsCounter) + { + _keys.CheckGdSkeys(gds, gdsCounter); + } +} \ No newline at end of file diff --git a/src/NGrib/Grib1/Grib1Grid.cs b/src/NGrib/Grib1/Grib1Grid.cs index 818e7df..1dbefe4 100644 --- a/src/NGrib/Grib1/Grib1Grid.cs +++ b/src/NGrib/Grib1/Grib1Grid.cs @@ -24,259 +24,258 @@ * along with NGrib. If not, see . */ -namespace NGrib.Grib1 +namespace NGrib.Grib1; + +/// A class that represents a canned grid definition section (GDS) . +public sealed class Grib1Grid : Grib1GridDefinitionSection { - /// A class that represents a canned grid definition section (GDS) . - public sealed class Grib1Grid : Grib1GridDefinitionSection - { - /// Constructs a Grib1Grid object from a pds. - /// - /// - /// Grib1ProductDefinitionSection to formulate grib - /// - /// - internal Grib1Grid(Grib1ProductDefinitionSection pds) : base() - { - int generatingProcess = pds.Process_Id; - int gridNumber = pds.Grid_Id; - - // checksum = 1000 + grid number - checksum = "1000" + System.Convert.ToString(gridNumber); - - switch (gridNumber) - { - case 21: - case 22: - case 23: - case 24: - { - type = 0; // Latitude/Longitude - name = getName(type); - - // (Nx - number of points along x-axis) - nx = 37; - - // (Ny - number of points along y-axis) - ny = 37; - - // (resolution and component flags). See Table 7 - resolution = 0x88; - - // (Dx - Longitudinal Direction Increment ) - dx = 5.0; - - // (Dy - Latitudinal Direction Increment ) - dy = 2.5; - - // (Scanning mode) See Table 8 - scan = 64; - - if (gridNumber == 21) - { - // (La1 - latitude of first grid point) - lat1 = 0.0; - - // (Lo1 - longitude of first grid point) - lon1 = 0.0; - - // (La2 - latitude of last grid point) - lat2 = 90.0; - - // (Lo2 - longitude of last grid point) - lon2 = 180.0; - } - else if (gridNumber == 22) - { - // (La1 - latitude of first grid point) - lat1 = 0.0; - - // (Lo1 - longitude of first grid point) - lon1 = -180.0; - - // (La2 - latitude of last grid point) - lat2 = 90.0; - - // (Lo2 - longitude of last grid point) - lon2 = 0.0; - } - else if (gridNumber == 23) - { - // (La1 - latitude of first grid point) - lat1 = -90.0; - - // (Lo1 - longitude of first grid point) - lon1 = 0.0; - - // (La2 - latitude of last grid point) - lat2 = 0.0; - - // (Lo2 - longitude of last grid point) - lon2 = 180.0; - } - else if (gridNumber == 24) - { - // (La1 - latitude of first grid point) - lat1 = -90.0; - - // (Lo1 - longitude of first grid point) - lon1 = -180.0; - - // (La2 - latitude of last grid point) - lat2 = 0.0; - - // (Lo2 - longitude of last grid point) - lon2 = 0.0; - } - } - break; - - - case 25: - case 26: - { - type = 0; // Latitude/Longitude - name = getName(type); + /// Constructs a Grib1Grid object from a pds. + /// + /// + /// Grib1ProductDefinitionSection to formulate grib + /// + /// + internal Grib1Grid(Grib1ProductDefinitionSection pds) : base() + { + int generatingProcess = pds.Process_Id; + int gridNumber = pds.Grid_Id; + + // checksum = 1000 + grid number + checksum = "1000" + System.Convert.ToString(gridNumber); + + switch (gridNumber) + { + case 21: + case 22: + case 23: + case 24: + { + type = 0; // Latitude/Longitude + name = getName(type); + + // (Nx - number of points along x-axis) + nx = 37; + + // (Ny - number of points along y-axis) + ny = 37; + + // (resolution and component flags). See Table 7 + resolution = 0x88; + + // (Dx - Longitudinal Direction Increment ) + dx = 5.0; + + // (Dy - Latitudinal Direction Increment ) + dy = 2.5; + + // (Scanning mode) See Table 8 + scan = 64; + + if (gridNumber == 21) + { + // (La1 - latitude of first grid point) + lat1 = 0.0; + + // (Lo1 - longitude of first grid point) + lon1 = 0.0; + + // (La2 - latitude of last grid point) + lat2 = 90.0; + + // (Lo2 - longitude of last grid point) + lon2 = 180.0; + } + else if (gridNumber == 22) + { + // (La1 - latitude of first grid point) + lat1 = 0.0; + + // (Lo1 - longitude of first grid point) + lon1 = -180.0; + + // (La2 - latitude of last grid point) + lat2 = 90.0; + + // (Lo2 - longitude of last grid point) + lon2 = 0.0; + } + else if (gridNumber == 23) + { + // (La1 - latitude of first grid point) + lat1 = -90.0; + + // (Lo1 - longitude of first grid point) + lon1 = 0.0; + + // (La2 - latitude of last grid point) + lat2 = 0.0; + + // (Lo2 - longitude of last grid point) + lon2 = 180.0; + } + else if (gridNumber == 24) + { + // (La1 - latitude of first grid point) + lat1 = -90.0; + + // (Lo1 - longitude of first grid point) + lon1 = -180.0; + + // (La2 - latitude of last grid point) + lat2 = 0.0; + + // (Lo2 - longitude of last grid point) + lon2 = 0.0; + } + } + break; + + + case 25: + case 26: + { + type = 0; // Latitude/Longitude + name = getName(type); + + // (Nx - number of points along x-axis) + nx = 72; + + // (Ny - number of points along y-axis) + ny = 19; + + // (resolution and component flags). See Table 7 + resolution = 0x88; + + // (Dx - Longitudinal Direction Increment ) + dx = 5.0; - // (Nx - number of points along x-axis) - nx = 72; + // (Dy - Latitudinal Direction Increment ) + dy = 5.0; - // (Ny - number of points along y-axis) - ny = 19; + // (Scanning mode) See Table 8 + scan = 64; - // (resolution and component flags). See Table 7 - resolution = 0x88; + if (gridNumber == 25) + { + // (La1 - latitude of first grid point) + lat1 = 0.0; - // (Dx - Longitudinal Direction Increment ) - dx = 5.0; + // (Lo1 - longitude of first grid point) + lon1 = 0.0; - // (Dy - Latitudinal Direction Increment ) - dy = 5.0; + // (La2 - latitude of last grid point) + lat2 = 90.0; - // (Scanning mode) See Table 8 - scan = 64; + // (Lo2 - longitude of last grid point) + lon2 = 355.0; + } + else if (gridNumber == 26) + { + // (La1 - latitude of first grid point) + lat1 = -90.0; - if (gridNumber == 25) - { - // (La1 - latitude of first grid point) - lat1 = 0.0; + // (Lo1 - longitude of first grid point) + lon1 = 0.0; + + // (La2 - latitude of last grid point) + lat2 = 0.0; + + // (Lo2 - longitude of last grid point) + lon2 = 355.0; + } + } + break; + + + case 61: + case 62: + case 63: + case 64: + { + type = 0; // Latitude/Longitude + name = getName(type); + + // (Nx - number of points along x-axis) + nx = 91; + + // (Ny - number of points along y-axis) + ny = 46; - // (Lo1 - longitude of first grid point) - lon1 = 0.0; + // (resolution and component flags). See Table 7 + resolution = 0x88; - // (La2 - latitude of last grid point) - lat2 = 90.0; + // (Dx - Longitudinal Direction Increment ) + dx = 2.0; - // (Lo2 - longitude of last grid point) - lon2 = 355.0; - } - else if (gridNumber == 26) - { - // (La1 - latitude of first grid point) - lat1 = -90.0; + // (Dy - Latitudinal Direction Increment ) + dy = 2.0; - // (Lo1 - longitude of first grid point) - lon1 = 0.0; - - // (La2 - latitude of last grid point) - lat2 = 0.0; - - // (Lo2 - longitude of last grid point) - lon2 = 355.0; - } - } - break; - - - case 61: - case 62: - case 63: - case 64: - { - type = 0; // Latitude/Longitude - name = getName(type); - - // (Nx - number of points along x-axis) - nx = 91; - - // (Ny - number of points along y-axis) - ny = 46; - - // (resolution and component flags). See Table 7 - resolution = 0x88; + // (Scanning mode) See Table 8 + scan = 64; - // (Dx - Longitudinal Direction Increment ) - dx = 2.0; + if (gridNumber == 61) + { + // (La1 - latitude of first grid point) + lat1 = 0.0; - // (Dy - Latitudinal Direction Increment ) - dy = 2.0; + // (Lo1 - longitude of first grid point) + lon1 = 0.0; - // (Scanning mode) See Table 8 - scan = 64; - - if (gridNumber == 61) - { - // (La1 - latitude of first grid point) - lat1 = 0.0; + // (La2 - latitude of last grid point) + lat2 = 90.0; - // (Lo1 - longitude of first grid point) - lon1 = 0.0; + // (Lo2 - longitude of last grid point) + lon2 = 180.0; + } + else if (gridNumber == 62) + { + // (La1 - latitude of first grid point) + lat1 = 0.0; + + // (Lo1 - longitude of first grid point) + lon1 = -180.0; - // (La2 - latitude of last grid point) - lat2 = 90.0; + // (La2 - latitude of last grid point) + lat2 = 90.0; - // (Lo2 - longitude of last grid point) - lon2 = 180.0; - } - else if (gridNumber == 62) - { - // (La1 - latitude of first grid point) - lat1 = 0.0; - - // (Lo1 - longitude of first grid point) - lon1 = -180.0; + // (Lo2 - longitude of last grid point) + lon2 = 0.0; + } + else if (gridNumber == 63) + { + // (La1 - latitude of first grid point) + lat1 = -90.0; - // (La2 - latitude of last grid point) - lat2 = 90.0; + // (Lo1 - longitude of first grid point) + lon1 = 0.0; - // (Lo2 - longitude of last grid point) - lon2 = 0.0; - } - else if (gridNumber == 63) - { - // (La1 - latitude of first grid point) - lat1 = -90.0; + // (La2 - latitude of last grid point) + lat2 = 0.0; + + // (Lo2 - longitude of last grid point) + lon2 = 180.0; + } + else if (gridNumber == 64) + { + // (La1 - latitude of first grid point) + lat1 = -90.0; + + // (Lo1 - longitude of first grid point) + lon1 = -180.0; + + // (La2 - latitude of last grid point) + lat2 = 0.0; + + // (Lo2 - longitude of last grid point) + lon2 = 0.0; + } + + break; + } - // (Lo1 - longitude of first grid point) - lon1 = 0.0; - - // (La2 - latitude of last grid point) - lat2 = 0.0; - - // (Lo2 - longitude of last grid point) - lon2 = 180.0; - } - else if (gridNumber == 64) - { - // (La1 - latitude of first grid point) - lat1 = -90.0; - - // (Lo1 - longitude of first grid point) - lon1 = -180.0; - - // (La2 - latitude of last grid point) - lat2 = 0.0; - - // (Lo2 - longitude of last grid point) - lon2 = 0.0; - } - - break; - } - - default: - System.Console.Out.WriteLine("Grid " + gridNumber + " not configured yet"); - break; - } - } // end Grib1Grid - } // end Grib1Grid -} \ No newline at end of file + default: + System.Console.Out.WriteLine("Grid " + gridNumber + " not configured yet"); + break; + } + } // end Grib1Grid +} // end Grib1Grid \ No newline at end of file diff --git a/src/NGrib/Grib1/Grib1GridDefinitionSection.cs b/src/NGrib/Grib1/Grib1GridDefinitionSection.cs index ac39ae2..1a99ec2 100644 --- a/src/NGrib/Grib1/Grib1GridDefinitionSection.cs +++ b/src/NGrib/Grib1/Grib1GridDefinitionSection.cs @@ -1,7 +1,7 @@ /* * This file is part of NGrib. * - * Copyright 2020 Nicolas Mangu + * Copyright © 2020 Nicolas Manguй * * Copyright 2006-2010 Seaware AB, PO Box 1244, SE-131 28 * Nacka Strand, Sweden, info@seaware.se. @@ -24,793 +24,789 @@ * along with NGrib. If not, see . */ -using System; -using System.Collections.Generic; using System.Diagnostics; -using NGrib; -namespace NGrib.Grib1 +namespace NGrib.Grib1; + +/// A class that represents the grid definition section (GDS) of a GRIB record. +public class Grib1GridDefinitionSection { - /// A class that represents the grid definition section (GDS) of a GRIB record. - public class Grib1GridDefinitionSection - { - /// is this a thin grid. - /// - /// - /// isThin grid boolean - /// - virtual public bool IsThin - { - get { return isThin; } - // --Commented out by Inspection START (11/17/05 1:42 PM): - // public final int[] getNumPlPts() - // { - // return numPlPts; - // } - // --Commented out by Inspection STOP (11/17/05 1:42 PM) - } - - /// Get type of grid. - /// - /// - /// type of grid - /// - virtual public int GridType - { - get { return type; } - } - - /// Get type of grid. - /// - /// - /// type of grid - /// - virtual public int Gdtn - { - get { return type; } - } - - /// Get number of grid columns. - /// - /// - /// number of grid columns - /// - virtual public int Nx - { - get { return nx; } - } - - /// Get number of grid rows. - /// - /// - /// number of grid rows. - /// - virtual public int Ny - { - get { return ny; } - } - - /// Get y-coordinate/latitude of grid start point. - /// - /// - /// y-coordinate/latitude of grid start point - /// - virtual public double La1 - { - get { return lat1; } - } - - /// Get x-coordinate/longitude of grid start point. - /// - /// - /// x-coordinate/longitude of grid start point - /// - virtual public double Lo1 - { - get { return lon1; } - } - - /// Get grid resolution. - /// - /// - /// resolution - /// - virtual public int Resolution - { - get { return resolution; } - } - - /// grid shape spherical or oblate. - /// int grid shape code 1 or 3 - /// - virtual public int Shape - { - get - { - int res = resolution >> 6; - if (res == 1 || res == 3) - { - return 1; - } - else - { - return 0; - } - } - } - - /// Grib 1 has static radius. - /// ShapeRadius of 6367.47 - /// - public static double ShapeRadius - { - get { return 6367.47; } - } - - /// Grib 1 has static MajorAxis. - /// ShapeMajorAxis of 6378.160 - /// - public static double ShapeMajorAxis - { - get { return 6378.160; } - } - - /// Grib 1 has static MinorAxis. - /// - /// - /// ShapeMinorAxis of 6356.775 - /// - public static double ShapeMinorAxis - { - get { return 6356.775; } - } - - /// Get y-coordinate/latitude of grid end point. - /// - /// - /// y-coordinate/latitude of grid end point - /// - virtual public double La2 - { - get { return lat2; } - } - - /// Get x-coordinate/longitude of grid end point. - /// - /// - /// x-coordinate/longitude of grid end point - /// - virtual public double Lo2 - { - get { return lon2; } - } - - /// orientation of the grid. - /// lov - /// - virtual public double Lov - { - get { return lov; } - } - - /// not defined in Grib1. - /// lad - /// - virtual public double Lad - { - get { return 0; } - } - - /// Get x-increment/distance between two grid points. - /// - /// - /// x-increment - /// - virtual public double Dx - { - get { return dx; } - } - - /// Get y-increment/distance between two grid points. - /// - /// - /// y-increment - /// - virtual public double Dy - { - get { return dy; } - } - - /// Get parallels between a pole and the equator. - /// - /// - /// np - /// - virtual public double Np - { - get { return np; } - } - - /// Get scan mode. - /// - /// - /// scan mode - /// - virtual public int ScanMode - { - get { return scan; } - } - - /// Get Projection Center flag - see note 5 of Table D. - /// - /// - /// Projection Center flag - /// - virtual public int ProjectionCenter - { - get { return proj_center; } - } - - /// Get first latitude from the pole at which cylinder cuts spherical earth - - /// see note 8 of Table D. - /// - /// - /// latitude - /// - virtual public double Latin - { - get { return latin1; } - } - - /// Get first latitude from the pole at which cone cuts spherical earth - - /// see note 8 of Table D. - /// - /// - /// latitude of south pole - /// - virtual public double Latin1 - { - get { return latin1; } - } - - /// Get second latitude from the pole at which cone cuts spherical earth - - /// see note 8 of Table D. - /// - /// - /// latitude of south pole - /// - virtual public double Latin2 - { - get { return latin2; } - } - - /// Get latitude of south pole. - /// - /// - /// latitude - /// - virtual public double SpLat - { - get { return latsp; } - } - - /// Get longitude of south pole of a rotated latitude/longitude grid. - /// - /// - /// longitude - /// - virtual public double SpLon - { - get { return lonsp; } - } - - /// MD5 checksum of this gds, used for comparisons. - /// - /// - /// string representation of this GDS checksum - /// - virtual public String CheckSum - { - get { return checksum; } - } - - /// Length in bytes of this section. - private int length; - - /// P(V|L). - /// PV - list of vertical coordinate parameters. - /// PL - list of numbers of points in each row. - /// or 255 missing. - /// - private int P_VorL; - //UPGRADE_NOTE: Final was removed from the declaration of 'numPlPts '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'" - // private int[] numPlPts = null; - - /// Is this a thin grid code not implemented. - private bool isThin; - - /// Type of grid (See table 6)ie 1 == Mercator Projection Grid. - protected internal int type; - - /// Grid name. - protected internal String name = ""; - - /// Number of grid columns. (Also Ni). - protected internal int nx; - - /// Number of grid rows. (Also Nj). - protected internal int ny; - - /// Latitude of grid start point. - protected internal double lat1; - - /// Longitude of grid start point. - protected internal double lon1; - - /// Latitude of grid last point. - protected internal double lat2; - - /// Longitude of grid last point. - protected internal double lon2; - - /// orientation of the grid. - private double lov; - - /// Resolution of grid (See table 7). - protected internal int resolution; - - /// x-distance between two grid points - /// can be delta-Lon or delta x. - /// - protected internal double dx; - - /// y-distance of two grid points - /// can be delta-Lat or delta y. - /// - protected internal double dy; - - /// Number of parallels between a pole and the equator. - private int np; - - /// Scanning mode (See table 8). - protected internal int scan; - - /// Projection Center Flag. - private int proj_center; - - /// Latin 1 - The first latitude from pole at which secant cone cuts the - /// sperical earth. See Note 8 of ON388. - /// - private double latin1; - - /// Latin 2 - The second latitude from pole at which secant cone cuts the - /// sperical earth. See Note 8 of ON388. - /// - private double latin2; - - /// latitude of south pole. - private double latsp; - - /// longitude of south pole. - private double lonsp; - - /// checksum value for this gds. - protected internal String checksum = ""; - - // *** constructors ******************************************************* - /// constructor - internal Grib1GridDefinitionSection() - { - } - - /// Constructs a Grib1GridDefinitionSection object from a raf. - /// - /// - /// RandomAccessFile with GDS content - /// - /// - /// NoValidGribException if raf contains no valid GRIB info - //UPGRADE_TODO: Class 'java.io.RandomAccessFile' was converted to 'System.IO.FileStream' which has a different behavior. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1073_javaioRandomAccessFile'" - internal Grib1GridDefinitionSection(System.IO.Stream raf) - { - int reserved; // used to read empty space - - // octets 1-3 (Length of GDS) - length = (int) GribNumbers.uint3(raf); - if (length == 0) - { - // there's a extra byte between PDS and GDS - SupportClass.Skip(raf, -2); - length = (int) GribNumbers.uint3(raf); - } + /// is this a thin grid. + /// + /// + /// isThin grid boolean + /// + virtual public bool IsThin + { + get { return isThin; } + // --Commented out by Inspection START (11/17/05 1:42 PM): + // public final int[] getNumPlPts() + // { + // return numPlPts; + // } + // --Commented out by Inspection STOP (11/17/05 1:42 PM) + } + + /// Get type of grid. + /// + /// + /// type of grid + /// + virtual public int GridType + { + get { return type; } + } + + /// Get type of grid. + /// + /// + /// type of grid + /// + virtual public int Gdtn + { + get { return type; } + } + + /// Get number of grid columns. + /// + /// + /// number of grid columns + /// + virtual public int Nx + { + get { return nx; } + } + + /// Get number of grid rows. + /// + /// + /// number of grid rows. + /// + virtual public int Ny + { + get { return ny; } + } + + /// Get y-coordinate/latitude of grid start point. + /// + /// + /// y-coordinate/latitude of grid start point + /// + virtual public double La1 + { + get { return lat1; } + } + + /// Get x-coordinate/longitude of grid start point. + /// + /// + /// x-coordinate/longitude of grid start point + /// + virtual public double Lo1 + { + get { return lon1; } + } + + /// Get grid resolution. + /// + /// + /// resolution + /// + virtual public int Resolution + { + get { return resolution; } + } + + /// grid shape spherical or oblate. + /// int grid shape code 1 or 3 + /// + virtual public int Shape + { + get + { + int res = resolution >> 6; + if (res == 1 || res == 3) + { + return 1; + } + else + { + return 0; + } + } + } + + /// Grib 1 has static radius. + /// ShapeRadius of 6367.47 + /// + public static double ShapeRadius + { + get { return 6367.47; } + } + + /// Grib 1 has static MajorAxis. + /// ShapeMajorAxis of 6378.160 + /// + public static double ShapeMajorAxis + { + get { return 6378.160; } + } + + /// Grib 1 has static MinorAxis. + /// + /// + /// ShapeMinorAxis of 6356.775 + /// + public static double ShapeMinorAxis + { + get { return 6356.775; } + } + + /// Get y-coordinate/latitude of grid end point. + /// + /// + /// y-coordinate/latitude of grid end point + /// + virtual public double La2 + { + get { return lat2; } + } + + /// Get x-coordinate/longitude of grid end point. + /// + /// + /// x-coordinate/longitude of grid end point + /// + virtual public double Lo2 + { + get { return lon2; } + } + + /// orientation of the grid. + /// lov + /// + virtual public double Lov + { + get { return lov; } + } + + /// not defined in Grib1. + /// lad + /// + virtual public double Lad + { + get { return 0; } + } + + /// Get x-increment/distance between two grid points. + /// + /// + /// x-increment + /// + virtual public double Dx + { + get { return dx; } + } + + /// Get y-increment/distance between two grid points. + /// + /// + /// y-increment + /// + virtual public double Dy + { + get { return dy; } + } + + /// Get parallels between a pole and the equator. + /// + /// + /// np + /// + virtual public double Np + { + get { return np; } + } + + /// Get scan mode. + /// + /// + /// scan mode + /// + virtual public int ScanMode + { + get { return scan; } + } + + /// Get Projection Center flag - see note 5 of Table D. + /// + /// + /// Projection Center flag + /// + virtual public int ProjectionCenter + { + get { return proj_center; } + } + + /// Get first latitude from the pole at which cylinder cuts spherical earth - + /// see note 8 of Table D. + /// + /// + /// latitude + /// + virtual public double Latin + { + get { return latin1; } + } + + /// Get first latitude from the pole at which cone cuts spherical earth - + /// see note 8 of Table D. + /// + /// + /// latitude of south pole + /// + virtual public double Latin1 + { + get { return latin1; } + } + + /// Get second latitude from the pole at which cone cuts spherical earth - + /// see note 8 of Table D. + /// + /// + /// latitude of south pole + /// + virtual public double Latin2 + { + get { return latin2; } + } + + /// Get latitude of south pole. + /// + /// + /// latitude + /// + virtual public double SpLat + { + get { return latsp; } + } + + /// Get longitude of south pole of a rotated latitude/longitude grid. + /// + /// + /// longitude + /// + virtual public double SpLon + { + get { return lonsp; } + } + + /// MD5 checksum of this gds, used for comparisons. + /// + /// + /// string representation of this GDS checksum + /// + virtual public String CheckSum + { + get { return checksum; } + } + + /// Length in bytes of this section. + private int length; + + /// P(V|L). + /// PV - list of vertical coordinate parameters. + /// PL - list of numbers of points in each row. + /// or 255 missing. + /// + private int P_VorL; + //UPGRADE_NOTE: Final was removed from the declaration of 'numPlPts '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'" + // private int[] numPlPts = null; + + /// Is this a thin grid code not implemented. + private bool isThin; + + /// Type of grid (See table 6)ie 1 == Mercator Projection Grid. + protected internal int type; + + /// Grid name. + protected internal String name = ""; + + /// Number of grid columns. (Also Ni). + protected internal int nx; + + /// Number of grid rows. (Also Nj). + protected internal int ny; + + /// Latitude of grid start point. + protected internal double lat1; + + /// Longitude of grid start point. + protected internal double lon1; + + /// Latitude of grid last point. + protected internal double lat2; + + /// Longitude of grid last point. + protected internal double lon2; + + /// orientation of the grid. + private double lov; + + /// Resolution of grid (See table 7). + protected internal int resolution; + + /// x-distance between two grid points + /// can be delta-Lon or delta x. + /// + protected internal double dx; + + /// y-distance of two grid points + /// can be delta-Lat or delta y. + /// + protected internal double dy; + + /// Number of parallels between a pole and the equator. + private int np; + + /// Scanning mode (See table 8). + protected internal int scan; + + /// Projection Center Flag. + private int proj_center; + + /// Latin 1 - The first latitude from pole at which secant cone cuts the + /// sperical earth. See Note 8 of ON388. + /// + private double latin1; + + /// Latin 2 - The second latitude from pole at which secant cone cuts the + /// sperical earth. See Note 8 of ON388. + /// + private double latin2; + + /// latitude of south pole. + private double latsp; + + /// longitude of south pole. + private double lonsp; + + /// checksum value for this gds. + protected internal String checksum = ""; + + // *** constructors ******************************************************* + /// constructor + internal Grib1GridDefinitionSection() + { + } + + /// Constructs a Grib1GridDefinitionSection object from a raf. + /// + /// + /// RandomAccessFile with GDS content + /// + /// + /// NoValidGribException if raf contains no valid GRIB info + //UPGRADE_TODO: Class 'java.io.RandomAccessFile' was converted to 'System.IO.FileStream' which has a different behavior. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1073_javaioRandomAccessFile'" + internal Grib1GridDefinitionSection(System.IO.Stream raf) + { + int reserved; // used to read empty space + + // octets 1-3 (Length of GDS) + length = (int) GribNumbers.uint3(raf); + if (length == 0) + { + // there's a extra byte between PDS and GDS + SupportClass.Skip(raf, -2); + length = (int) GribNumbers.uint3(raf); + } + + + // TODO Fix Checksum stuff + // get byte array for this gds, then reset raf to same position + // calculate checksum for this gds via the byte array + /* + long mark = raf.Position; + sbyte[] dst = new sbyte[length - 3]; + SupportClass.ReadInput(raf, dst, 0, dst.Length); + raf.Seek(mark, System.IO.SeekOrigin.Begin); + //UPGRADE_ISSUE: Class 'java.util.zip.CRC32' was not converted. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1000_javautilzipCRC32'" + //UPGRADE_ISSUE: Constructor 'java.util.zip.CRC32.CRC32' was not converted. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1000_javautilzipCRC32'" + CRC32 cs = new CRC32(); + //UPGRADE_ISSUE: Method 'java.util.zip.CRC32.update' was not converted. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1000_javautilzipCRC32'" + cs.update(dst); + //UPGRADE_ISSUE: Method 'java.util.zip.CRC32.getValue' was not converted. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1000_javautilzipCRC32'" + checksum = System.Convert.ToString(cs.getValue()); + */ - // TODO Fix Checksum stuff - // get byte array for this gds, then reset raf to same position - // calculate checksum for this gds via the byte array - /* - long mark = raf.Position; - sbyte[] dst = new sbyte[length - 3]; - SupportClass.ReadInput(raf, dst, 0, dst.Length); - raf.Seek(mark, System.IO.SeekOrigin.Begin); - //UPGRADE_ISSUE: Class 'java.util.zip.CRC32' was not converted. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1000_javautilzipCRC32'" - //UPGRADE_ISSUE: Constructor 'java.util.zip.CRC32.CRC32' was not converted. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1000_javautilzipCRC32'" - CRC32 cs = new CRC32(); - //UPGRADE_ISSUE: Method 'java.util.zip.CRC32.update' was not converted. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1000_javautilzipCRC32'" - cs.update(dst); - //UPGRADE_ISSUE: Method 'java.util.zip.CRC32.getValue' was not converted. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1000_javautilzipCRC32'" - checksum = System.Convert.ToString(cs.getValue()); + // octets 4 NV + int NV = raf.ReadByte(); - */ - // octets 4 NV - int NV = raf.ReadByte(); + // octet 5 PL the location (octet number) of the list of numbers of points in each row + P_VorL = raf.ReadByte(); - // octet 5 PL the location (octet number) of the list of numbers of points in each row - P_VorL = raf.ReadByte(); + // octet 6 (grid type) + type = raf.ReadByte(); + + name = getName(type); + + if (type != 50) + { + // values same up to resolution + + // octets 7-8 (Nx - number of points along x-axis) + nx = GribNumbers.int2(raf); + nx = (nx == -1) ? 1 : nx; + // octets 9-10 (Ny - number of points along y-axis) + ny = GribNumbers.int2(raf); + ny = (ny == -1) ? 1 : ny; - // octet 6 (grid type) - type = raf.ReadByte(); - - name = getName(type); - - if (type != 50) - { - // values same up to resolution - - // octets 7-8 (Nx - number of points along x-axis) - nx = GribNumbers.int2(raf); - nx = (nx == -1) ? 1 : nx; + // octets 11-13 (La1 - latitude of first grid point) + lat1 = GribNumbers.int3(raf) / 1000.0; - // octets 9-10 (Ny - number of points along y-axis) - ny = GribNumbers.int2(raf); - ny = (ny == -1) ? 1 : ny; + // octets 14-16 (Lo1 - longitude of first grid point) + lon1 = GribNumbers.int3(raf) / 1000.0; - // octets 11-13 (La1 - latitude of first grid point) - lat1 = GribNumbers.int3(raf) / 1000.0; + // octet 17 (resolution and component flags). See Table 7 + resolution = raf.ReadByte(); + } - // octets 14-16 (Lo1 - longitude of first grid point) - lon1 = GribNumbers.int3(raf) / 1000.0; + switch (type) + { + // Latitude/Longitude grids , Arakawa semi-staggered e-grid rotated + // Arakawa filled e-grid rotated + case 0: + case 4: + case 40: + case 201: + case 202: - // octet 17 (resolution and component flags). See Table 7 - resolution = raf.ReadByte(); - } + // octets 18-20 (La2 - latitude of last grid point) + lat2 = GribNumbers.int3(raf) / 1000.0; - switch (type) - { - // Latitude/Longitude grids , Arakawa semi-staggered e-grid rotated - // Arakawa filled e-grid rotated - case 0: - case 4: - case 40: - case 201: - case 202: + // octets 21-23 (Lo2 - longitude of last grid point) + lon2 = GribNumbers.int3(raf) / 1000.0; - // octets 18-20 (La2 - latitude of last grid point) - lat2 = GribNumbers.int3(raf) / 1000.0; + // octets 24-25 (Dx - Longitudinal Direction Increment ) + dx = GribNumbers.int2(raf) / 1000.0; - // octets 21-23 (Lo2 - longitude of last grid point) - lon2 = GribNumbers.int3(raf) / 1000.0; + // octets 26-27 (Dy - Latitudinal Direction Increment ) + // Np - parallels between a pole and the equator + if (type == 4) + { + np = GribNumbers.int2(raf); + } + else + { + dy = GribNumbers.int2(raf) / 1000.0; + } - // octets 24-25 (Dx - Longitudinal Direction Increment ) - dx = GribNumbers.int2(raf) / 1000.0; + // octet 28 (Scanning mode) See Table 8 + scan = raf.ReadByte(); - // octets 26-27 (Dy - Latitudinal Direction Increment ) - // Np - parallels between a pole and the equator - if (type == 4) - { - np = GribNumbers.int2(raf); - } - else - { - dy = GribNumbers.int2(raf) / 1000.0; - } + // octet 29-32 reserved + reserved = GribNumbers.int4(raf); - // octet 28 (Scanning mode) See Table 8 - scan = raf.ReadByte(); + if (length > 32) + { + // getP_VorL(raf); + // Vertical coordinates (NV) and thinned grids (PL) not supported - skip this + SupportClass.Skip(raf, length - 32); + } - // octet 29-32 reserved - reserved = GribNumbers.int4(raf); + break; // end Latitude/Longitude grids - if (length > 32) - { - // getP_VorL(raf); - // Vertical coordinates (NV) and thinned grids (PL) not supported - skip this - SupportClass.Skip(raf, length - 32); - } - break; // end Latitude/Longitude grids + case 1: // Mercator grids + // octets 18-20 (La2 - latitude of last grid point) + lat2 = GribNumbers.int3(raf) / 1000.0; - case 1: // Mercator grids + // octets 21-23 (Lo2 - longitude of last grid point) + lon2 = GribNumbers.int3(raf) / 1000.0; - // octets 18-20 (La2 - latitude of last grid point) - lat2 = GribNumbers.int3(raf) / 1000.0; + // octets 24-26 (Latin - latitude where cylinder intersects the earth + latin1 = GribNumbers.int3(raf) / 1000.0; - // octets 21-23 (Lo2 - longitude of last grid point) - lon2 = GribNumbers.int3(raf) / 1000.0; + // octet 27 reserved + reserved = raf.ReadByte(); - // octets 24-26 (Latin - latitude where cylinder intersects the earth - latin1 = GribNumbers.int3(raf) / 1000.0; + // octet 28 (Scanning mode) See Table 8 + scan = raf.ReadByte(); - // octet 27 reserved - reserved = raf.ReadByte(); + // octets 29-31 (Dx - Longitudinal Direction Increment ) + dx = GribNumbers.int3(raf); - // octet 28 (Scanning mode) See Table 8 - scan = raf.ReadByte(); + // octets 32-34 (Dx - Longitudinal Direction Increment ) + dy = GribNumbers.int3(raf); - // octets 29-31 (Dx - Longitudinal Direction Increment ) - dx = GribNumbers.int3(raf); + // octet 35-42 reserved + reserved = GribNumbers.int4(raf); + reserved = GribNumbers.int4(raf); - // octets 32-34 (Dx - Longitudinal Direction Increment ) - dy = GribNumbers.int3(raf); + if (length > 42) + { + // getP_VorL(raf); + // Vertical coordinates (NV) and thinned grids (PL) not supported - skip this + SupportClass.Skip(raf, length - 42); + } - // octet 35-42 reserved - reserved = GribNumbers.int4(raf); - reserved = GribNumbers.int4(raf); + break; // end Mercator grids - if (length > 42) - { - // getP_VorL(raf); - // Vertical coordinates (NV) and thinned grids (PL) not supported - skip this - SupportClass.Skip(raf, length - 42); - } - break; // end Mercator grids + case 3: // Lambert Conformal + // octets 18-20 (Lov - Orientation of the grid - east lon parallel to y axis) + lov = GribNumbers.int3(raf) / 1000.0; - case 3: // Lambert Conformal + // octets 21-23 (Dx - the X-direction grid length) See Note 2 of Table D + dx = GribNumbers.int3(raf); - // octets 18-20 (Lov - Orientation of the grid - east lon parallel to y axis) - lov = GribNumbers.int3(raf) / 1000.0; + // octets 24-26 (Dy - the Y-direction grid length) See Note 2 of Table D + dy = GribNumbers.int3(raf); - // octets 21-23 (Dx - the X-direction grid length) See Note 2 of Table D - dx = GribNumbers.int3(raf); + // octets 27 (Projection Center flag) See Note 5 of Table D + proj_center = raf.ReadByte(); - // octets 24-26 (Dy - the Y-direction grid length) See Note 2 of Table D - dy = GribNumbers.int3(raf); + // octet 28 (Scanning mode) See Table 8 + scan = raf.ReadByte(); - // octets 27 (Projection Center flag) See Note 5 of Table D - proj_center = raf.ReadByte(); + // octets 29-31 (Latin1 - first lat where secant cone cuts spherical earth + latin1 = GribNumbers.int3(raf) / 1000.0; - // octet 28 (Scanning mode) See Table 8 - scan = raf.ReadByte(); + // octets 32-34 (Latin2 - second lat where secant cone cuts spherical earth) + latin2 = GribNumbers.int3(raf) / 1000.0; - // octets 29-31 (Latin1 - first lat where secant cone cuts spherical earth - latin1 = GribNumbers.int3(raf) / 1000.0; + // octets 35-37 (lat of southern pole) + latsp = GribNumbers.int3(raf) / 1000.0; - // octets 32-34 (Latin2 - second lat where secant cone cuts spherical earth) - latin2 = GribNumbers.int3(raf) / 1000.0; + // octets 38-40 (lon of southern pole) + lonsp = GribNumbers.int3(raf) / 1000.0; - // octets 35-37 (lat of southern pole) - latsp = GribNumbers.int3(raf) / 1000.0; + // octets 41-42 + reserved = GribNumbers.int2(raf); - // octets 38-40 (lon of southern pole) - lonsp = GribNumbers.int3(raf) / 1000.0; + if (length > 42) + { + // getP_VorL(raf); + // Vertical coordinates (NV) and thinned grids (PL) not supported - skip this + SupportClass.Skip(raf, length - 42); + } - // octets 41-42 - reserved = GribNumbers.int2(raf); + break; // end Lambert Conformal - if (length > 42) - { - // getP_VorL(raf); - // Vertical coordinates (NV) and thinned grids (PL) not supported - skip this - SupportClass.Skip(raf, length - 42); - } - break; // end Lambert Conformal + case 5: // Polar Stereographic grids + // octets 18-20 (Lov - Orientation of the grid - east lon parallel to y axis) + lov = GribNumbers.int3(raf) / 1000.0; - case 5: // Polar Stereographic grids + // octets 21-23 (Dx - Longitudinal Direction Increment ) + dx = GribNumbers.int3(raf); - // octets 18-20 (Lov - Orientation of the grid - east lon parallel to y axis) - lov = GribNumbers.int3(raf) / 1000.0; + // octets 24-26(Dy - Latitudinal Direction Increment ) + dy = GribNumbers.int3(raf); - // octets 21-23 (Dx - Longitudinal Direction Increment ) - dx = GribNumbers.int3(raf); + // octets 27 (Projection Center flag) See Note 5 of Table D + proj_center = raf.ReadByte(); - // octets 24-26(Dy - Latitudinal Direction Increment ) - dy = GribNumbers.int3(raf); + // octet 28 (Scanning mode) See Table 8 + scan = raf.ReadByte(); - // octets 27 (Projection Center flag) See Note 5 of Table D - proj_center = raf.ReadByte(); + // octet 29-32 reserved + reserved = GribNumbers.int4(raf); - // octet 28 (Scanning mode) See Table 8 - scan = raf.ReadByte(); + if (length > 32) + { + // getP_VorL(raf); + // Vertical coordinates (NV) and thinned grids (PL) not supported - skip this + SupportClass.Skip(raf, length - 32); + } - // octet 29-32 reserved - reserved = GribNumbers.int4(raf); + break; // end Polar Stereographic grids - if (length > 32) - { - // getP_VorL(raf); - // Vertical coordinates (NV) and thinned grids (PL) not supported - skip this - SupportClass.Skip(raf, length - 32); - } - break; // end Polar Stereographic grids + default: + Console.Out.WriteLine("Unknown Grid Type : " + type); + break; + } // end switch grid_type - default: - Console.Out.WriteLine("Unknown Grid Type : " + type); - break; - } // end switch grid_type + if ((scan & 63) != 0) + throw new BadGribFormatException("GDS: This scanning mode (" + scan + ") is not supported."); + } // end Grib1GridDefinitionSection( raf ) + //UPGRADE_TODO: Class 'java.io.RandomAccessFile' was converted to 'System.IO.FileStream' which has a different behavior. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1073_javaioRandomAccessFile'" + private void getP_VorL(System.IO.Stream raf) + { + isThin = true; + int numPts; + if (ny != 1) + { + dx = (float) GribNumbers.UNDEFINED; + numPts = ny; + } + else + { + dx = (float) GribNumbers.UNDEFINED; + numPts = nx; + } - if ((scan & 63) != 0) - throw new BadGribFormatException("GDS: This scanning mode (" + scan + ") is not supported."); - } // end Grib1GridDefinitionSection( raf ) - //UPGRADE_TODO: Class 'java.io.RandomAccessFile' was converted to 'System.IO.FileStream' which has a different behavior. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1073_javaioRandomAccessFile'" - private void getP_VorL(System.IO.Stream raf) - { - isThin = true; - int numPts; - if (ny != 1) - { - dx = (float) GribNumbers.UNDEFINED; - numPts = ny; - } - else - { - dx = (float) GribNumbers.UNDEFINED; - numPts = nx; - } + int[] numPlPts = new int[numPts]; + for (int i = 0; i < numPts; i++) + { + numPlPts[i] = GribNumbers.int2(raf); + } + } - int[] numPlPts = new int[numPts]; - for (int i = 0; i < numPts; i++) - { - numPlPts[i] = GribNumbers.int2(raf); + // *** public methods *************************************************** - } - } + // --Commented out by Inspection START (11/17/05 1:43 PM): + // /** + // * Get length in bytes of this section. + // * + // * @return length in bytes of this section + // */ + // public final int getLength() + // { + // return length; + // } + // --Commented out by Inspection STOP (11/17/05 1:43 PM) - // *** public methods *************************************************** + /// Get Grid name. + /// + /// + /// name + /// + public String getName() + { + return name; + } - // --Commented out by Inspection START (11/17/05 1:43 PM): - // /** - // * Get length in bytes of this section. - // * - // * @return length in bytes of this section - // */ - // public final int getLength() - // { - // return length; - // } - // --Commented out by Inspection STOP (11/17/05 1:43 PM) + /// Get Grid name. + /// + /// + /// + /// + /// name + /// + static public String getName(int type) + { + switch (type) + { + case 0: return "Latitude/Longitude Grid"; - /// Get Grid name. - /// - /// - /// name - /// - public String getName() - { - return name; - } + case 1: return "Mercator Projection Grid"; - /// Get Grid name. - /// - /// - /// - /// - /// name - /// - static public String getName(int type) - { - switch (type) - { - case 0: return "Latitude/Longitude Grid"; + case 2: return "Gnomonic Projection Grid"; + + case 3: return "Lambert Conformal"; - case 1: return "Mercator Projection Grid"; + case 4: return "Gaussian Latitude/Longitude"; + + case 5: return "Polar Stereographic projection Grid"; + + case 6: return "Universal Transverse Mercator"; + + case 7: return "Simple polyconic projection"; + + case 8: return "Albers equal-area, secant or tangent, conic or bi-polar, projection"; + + case 9: return "Miller's cylindrical projection"; + + case 10: return "Rotated latitude/longitude grid"; + + case 13: return "Oblique Lambert conformal, secant or tangent, conical or bipolar, projection"; + + case 14: return "Rotated Gaussian latitude/longitude grid"; + + case 20: return "Stretched latitude/longitude grid"; + + case 24: return "Stretched Gaussian latitude/longitude grid"; + + case 30: return "Stretched and rotated latitude/longitude grids"; + + case 34: return "Stretched and rotated Gaussian latitude/longitude grids"; + + case 50: return "Spherical Harmonic Coefficients"; + + case 60: return "Rotated spherical harmonic coefficients"; + + case 70: return "Stretched spherical harmonics"; + + case 80: return "Stretched and rotated spherical harmonic coefficients"; + + case 90: return "Space view perspective or orthographic"; + + case 201: return "Arakawa semi-staggered E-grid on rotated latitude/longitude grid-point array"; + + case 202: return "Arakawa filled E-grid on rotated latitude/longitude grid-point array"; + } + + return "Unknown"; + } // end getName - case 2: return "Gnomonic Projection Grid"; - - case 3: return "Lambert Conformal"; + /// shape of grid. + /// grid shape name + /// + public String getShapeName() + { + return getShapeName(Shape); + } - case 4: return "Gaussian Latitude/Longitude"; - - case 5: return "Polar Stereographic projection Grid"; - - case 6: return "Universal Transverse Mercator"; - - case 7: return "Simple polyconic projection"; - - case 8: return "Albers equal-area, secant or tangent, conic or bi-polar, projection"; - - case 9: return "Miller's cylindrical projection"; - - case 10: return "Rotated latitude/longitude grid"; - - case 13: return "Oblique Lambert conformal, secant or tangent, conical or bipolar, projection"; - - case 14: return "Rotated Gaussian latitude/longitude grid"; - - case 20: return "Stretched latitude/longitude grid"; - - case 24: return "Stretched Gaussian latitude/longitude grid"; - - case 30: return "Stretched and rotated latitude/longitude grids"; - - case 34: return "Stretched and rotated Gaussian latitude/longitude grids"; - - case 50: return "Spherical Harmonic Coefficients"; - - case 60: return "Rotated spherical harmonic coefficients"; - - case 70: return "Stretched spherical harmonics"; - - case 80: return "Stretched and rotated spherical harmonic coefficients"; - - case 90: return "Space view perspective or orthographic"; - - case 201: return "Arakawa semi-staggered E-grid on rotated latitude/longitude grid-point array"; - - case 202: return "Arakawa filled E-grid on rotated latitude/longitude grid-point array"; - } - - return "Unknown"; - } // end getName - - /// shape of grid. - /// grid shape name - /// - public String getShapeName() - { - return getShapeName(Shape); - } - - /// shape of grid. - /// grid shape code - /// - /// String grid shape name - /// - static public String getShapeName(int code) - { - if (code == 1) - { - return "oblate spheroid"; - } - else - { - return "spherical"; - } - } + /// shape of grid. + /// grid shape code + /// + /// String grid shape name + /// + static public String getShapeName(int code) + { + if (code == 1) + { + return "oblate spheroid"; + } + else + { + return "spherical"; + } + } - public IEnumerable EnumerateGridPoints() - { - if ((Resolution & 128) == 0 || // The direction increments have to be given - ScanMode != 0) // Expect to scan the grid from North to South and West to East, and consecutive in i direction - { - throw new NotSupportedException(); - } + public IEnumerable EnumerateGridPoints() + { + if ((Resolution & 128) == 0 || // The direction increments have to be given + ScanMode != 0) // Expect to scan the grid from North to South and West to East, and consecutive in i direction + { + throw new NotSupportedException(); + } - var firstGridPoint = new Coordinate(La1, Lo1); - var lastGridPoint = new Coordinate(La2, Lo2); + var firstGridPoint = new Coordinate(La1, Lo1); + var lastGridPoint = new Coordinate(La2, Lo2); - var xStep = Dx; - var yStep = -Dy; - var currentGridPoint = firstGridPoint; + var xStep = Dx; + var yStep = -Dy; + var currentGridPoint = firstGridPoint; - // Adjacent points in x direction are consecutive - var latitudeOffset = 0d; - for (var y = 0; y < Ny; y++) - { - var longitudeOffset = 0d; - for (var x = 0; x < Nx; x++) - { - currentGridPoint = firstGridPoint.Add(latitudeOffset, longitudeOffset); - yield return currentGridPoint; + // Adjacent points in x direction are consecutive + var latitudeOffset = 0d; + for (var y = 0; y < Ny; y++) + { + var longitudeOffset = 0d; + for (var x = 0; x < Nx; x++) + { + currentGridPoint = firstGridPoint.Add(latitudeOffset, longitudeOffset); + yield return currentGridPoint; - longitudeOffset += xStep; - } - latitudeOffset += yStep; - } + longitudeOffset += xStep; + } + latitudeOffset += yStep; + } - Debug.Assert(lastGridPoint.Equals(currentGridPoint)); - } - } // end Grib1GridDefinitionSection -} \ No newline at end of file + Debug.Assert(lastGridPoint.Equals(currentGridPoint)); + } +} // end Grib1GridDefinitionSection \ No newline at end of file diff --git a/src/NGrib/Grib1/Grib1IndicatorSection.cs b/src/NGrib/Grib1/Grib1IndicatorSection.cs index c794a50..f4df8b2 100644 --- a/src/NGrib/Grib1/Grib1IndicatorSection.cs +++ b/src/NGrib/Grib1/Grib1IndicatorSection.cs @@ -1,7 +1,7 @@ /* * This file is part of NGrib. * - * Copyright 2020 Nicolas Mangu + * Copyright © 2020 Nicolas Manguй * * Copyright 2006-2010 Seaware AB, PO Box 1244, SE-131 28 * Nacka Strand, Sweden, info@seaware.se. @@ -24,146 +24,143 @@ * along with NGrib. If not, see . */ -using System; - -namespace NGrib.Grib1 +namespace NGrib.Grib1; + +/// A class that represents the IndicatorSection of a GRIB record. +/// +/// +/// Robb Kambic +/// +/// 1.0 +/// +/// +public sealed class Grib1IndicatorSection { - /// A class that represents the IndicatorSection of a GRIB record. - /// - /// - /// Robb Kambic - /// - /// 1.0 - /// - /// - public sealed class Grib1IndicatorSection - { - /// Get the byte length of this GRIB record. - /// - /// - /// length in bytes of GRIB record - /// - public long GribLength - { - get { return gribLength; } - } - - /// Get the byte length of the IndicatorSection0 section. - /// - /// - /// length in bytes of IndicatorSection0 section - /// - public int Length - { - get { return length; } - } - - /// Get the edition of the GRIB specification used. - /// - /// - /// edition number of GRIB specification - /// - public int GribEdition - { - get { return edition; } - } - - /// Length in bytes of GRIB record. - private long gribLength; - - /// Length in bytes of IndicatorSection. - /// Section length differs between GRIB editions 1 and 2 - /// Currently only GRIB edition 1 supported - length is 16 octets/bytes. - /// - private int length; - - /// Discipline - GRIB Master Table Number. - private int discipline; - - /// Edition of GRIB specification used. - //UPGRADE_NOTE: Final was removed from the declaration of 'edition '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'" - private int edition; - - // *** constructors ******************************************************* - - /// Constructs a Grib1IndicatorSection object from a byteBuffer. - /// - /// - /// RandomAccessFile with IndicatorSection content - /// - /// - /// NotSupportedException if raf contains no valid GRIB file - /// IOException - //UPGRADE_TODO: Class 'java.io.RandomAccessFile' was converted to 'System.IO.FileStream' which has a different behavior. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1073_javaioRandomAccessFile'" - internal Grib1IndicatorSection(System.IO.Stream raf) - { - long mark = raf.Position; - //if Grib edition 1, get bytes for the gribLength - int[] data = new int[3]; - for (int i = 0; i < 3; i++) - { - data[i] = raf.ReadByte(); - } - - - // edition of GRIB specification - edition = raf.ReadByte(); - - if (edition == 1) - { - // length of GRIB record - // Reset to beginning, then read 3 bytes - raf.Position = mark; - gribLength = (long) GribNumbers.uint3(raf); - // Skip next byte, edition already read - raf.ReadByte(); - - length = 8; - } - else if (edition == 2) - { - // length of GRIB record - discipline = data[2]; - - gribLength = GribNumbers.int8(raf); - - length = 16; - } - else - { - throw new NotSupportedException("GRIB edition " + edition + " is not yet supported"); - } - } // end Grib1IndicatorSection - - // --Commented out by Inspection START (12/5/05 3:52 PM): - // /** - // * Discipline - GRIB Master Table Number. - // * @return discipline as a number - // */ - // public final int getDiscipline() - // { - // return discipline; - // } - // --Commented out by Inspection STOP (12/5/05 3:52 PM) - - // --Commented out by Inspection START (12/5/05 3:52 PM): - // /** - // * Discipline - GRIB Master Table Name. - // * @return return Discipline Name as String - // */ - // public final String getDisciplineName() - // { - // switch( discipline ) { - // - // case 0: return "Meteorological products" ; - // case 1: return "Hydrological products"; - // case 2: return "Land surface products"; - // case 3: return "Space products"; - // case 10: return "Oceanographic products"; - // default: return "Unknown"; - // } - // - // } - // --Commented out by Inspection STOP (12/5/05 3:52 PM) - } + /// Get the byte length of this GRIB record. + /// + /// + /// length in bytes of GRIB record + /// + public long GribLength + { + get { return gribLength; } + } + + /// Get the byte length of the IndicatorSection0 section. + /// + /// + /// length in bytes of IndicatorSection0 section + /// + public int Length + { + get { return length; } + } + + /// Get the edition of the GRIB specification used. + /// + /// + /// edition number of GRIB specification + /// + public int GribEdition + { + get { return edition; } + } + + /// Length in bytes of GRIB record. + private long gribLength; + + /// Length in bytes of IndicatorSection. + /// Section length differs between GRIB editions 1 and 2 + /// Currently only GRIB edition 1 supported - length is 16 octets/bytes. + /// + private int length; + + /// Discipline - GRIB Master Table Number. + private int discipline; + + /// Edition of GRIB specification used. + //UPGRADE_NOTE: Final was removed from the declaration of 'edition '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'" + private int edition; + + // *** constructors ******************************************************* + + /// Constructs a Grib1IndicatorSection object from a byteBuffer. + /// + /// + /// RandomAccessFile with IndicatorSection content + /// + /// + /// NotSupportedException if raf contains no valid GRIB file + /// IOException + //UPGRADE_TODO: Class 'java.io.RandomAccessFile' was converted to 'System.IO.FileStream' which has a different behavior. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1073_javaioRandomAccessFile'" + internal Grib1IndicatorSection(System.IO.Stream raf) + { + long mark = raf.Position; + //if Grib edition 1, get bytes for the gribLength + int[] data = new int[3]; + for (int i = 0; i < 3; i++) + { + data[i] = raf.ReadByte(); + } + + + // edition of GRIB specification + edition = raf.ReadByte(); + + if (edition == 1) + { + // length of GRIB record + // Reset to beginning, then read 3 bytes + raf.Position = mark; + gribLength = (long) GribNumbers.uint3(raf); + // Skip next byte, edition already read + raf.ReadByte(); + + length = 8; + } + else if (edition == 2) + { + // length of GRIB record + discipline = data[2]; + + gribLength = GribNumbers.int8(raf); + + length = 16; + } + else + { + throw new NotSupportedException("GRIB edition " + edition + " is not yet supported"); + } + } // end Grib1IndicatorSection + + // --Commented out by Inspection START (12/5/05 3:52 PM): + // /** + // * Discipline - GRIB Master Table Number. + // * @return discipline as a number + // */ + // public final int getDiscipline() + // { + // return discipline; + // } + // --Commented out by Inspection STOP (12/5/05 3:52 PM) + + // --Commented out by Inspection START (12/5/05 3:52 PM): + // /** + // * Discipline - GRIB Master Table Name. + // * @return return Discipline Name as String + // */ + // public final String getDisciplineName() + // { + // switch( discipline ) { + // + // case 0: return "Meteorological products" ; + // case 1: return "Hydrological products"; + // case 2: return "Land surface products"; + // case 3: return "Space products"; + // case 10: return "Oceanographic products"; + // default: return "Unknown"; + // } + // + // } + // --Commented out by Inspection STOP (12/5/05 3:52 PM) } \ No newline at end of file diff --git a/src/NGrib/Grib1/Grib1Input.cs b/src/NGrib/Grib1/Grib1Input.cs index 7512731..ceeb719 100644 --- a/src/NGrib/Grib1/Grib1Input.cs +++ b/src/NGrib/Grib1/Grib1Input.cs @@ -1,7 +1,7 @@ /* * This file is part of NGrib. * - * Copyright 2020 Nicolas Mangu + * Copyright � 2020 Nicolas Mangu� * * Copyright 2006-2010 Seaware AB, PO Box 1244, SE-131 28 * Nacka Strand, Sweden, info@seaware.se. @@ -24,484 +24,137 @@ * along with NGrib. If not, see . */ -using System; -using System.Collections.Generic; -using System.IO; +using NGrib.Common; -namespace NGrib.Grib1 +namespace NGrib.Grib1; + +/// A class that scans a GRIB file to extract product information. +public sealed class Grib1Input { - /// A class that scans a GRIB file to extract product information. - public sealed class Grib1Input - { - /// Grib edition number 1, 2 or 0 not a Grib file. - /// NotSupportedException - /// int 0 not a Grib file, 1 Grib1, 2 Grib2 - /// - public int Edition - { - get - { - long length = (InputStream.Length < 4000L) ? InputStream.Length : 4000L; - if (!seekHeader(InputStream, length)) - { - return 0; // not valid Grib file - } - - // Read Section 0 Indicator Section to get Edition number - Grib1IndicatorSection is_Renamed = new Grib1IndicatorSection(InputStream); // section 0 - return is_Renamed.GribEdition; - } - // end getEdition - } - - /// Get products of the GRIB file. - /// - /// - /// products - /// - public System.Collections.ArrayList Products - { - get { return products; } - } - - /// Get records of the GRIB file. - /// - /// - /// records - /// - public IReadOnlyList Records => records; - - /// Get GDS's of the GRIB file. - /// - /// - /// gdsHM - /// - //UPGRADE_TODO: Class 'java.util.HashMap' was converted to 'System.Collections.Hashtable' which has a different behavior. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1073_javautilHashMap'" - public System.Collections.Hashtable GDSs - { - get { return gdsHM; } - } - - public int ProductsCount - { - get { return products.Count; } - } - - public int RecordsCount - { - get { return records.Count; } - } - - /* - * raf for grib file - */ - internal Stream InputStream { get; private set; } - - /* - * the header of Grib record - */ - private String header = "GRIB"; - - /* - * stores records of Grib file, records consist of objects for each section. - * there are 5 sections to a Grib1 record. - */ - //UPGRADE_NOTE: Final was removed from the declaration of 'records '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'" - private List records = new List(); - - /* - * stores products of Grib file, products have enough info to get the - * metadata about a parameter and the data. products are lightweight - * records. - */ - //UPGRADE_NOTE: Final was removed from the declaration of 'products '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'" - private System.Collections.ArrayList products = new System.Collections.ArrayList(); - - /* - * stores GDS of Grib1 file, there is possibility of more than 1 - */ - //UPGRADE_NOTE: Final was removed from the declaration of 'gdsHM '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'" - //UPGRADE_TODO: Class 'java.util.HashMap' was converted to 'System.Collections.Hashtable' which has a different behavior. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1073_javautilHashMap'" - private System.Collections.Hashtable gdsHM = new System.Collections.Hashtable(); - - // *** constructors ******************************************************* - - /// Constructs a Grib1Input object from a raf. - /// - /// - /// with GRIB content - /// - /// - //UPGRADE_TODO: Class 'java.io.RandomAccessFile' was converted to 'System.IO.FileStream' which has a different behavior. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1073_javaioRandomAccessFile'" - public Grib1Input(System.IO.Stream raf) - { - this.InputStream = raf; - } - - public Grib1Input() - { - } - - /// scans a Grib file to gather information that could be used to - /// create an index or dump the metadata contents. - /// - /// - /// products have enough information for data extractions - /// - /// returns after processing one record in the Grib file - /// - /// NotSupportedException - public void scan(bool getProducts, bool oneRecord) - { - long start = (DateTime.Now.Ticks - 621355968000000000) / 10000; - // stores the number of times a particular GDS is used - //UPGRADE_TODO: Class 'java.util.HashMap' was converted to 'System.Collections.Hashtable' which has a different behavior. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1073_javautilHashMap'" - System.Collections.Hashtable gdsCounter = new System.Collections.Hashtable(); - Grib1ProductDefinitionSection pds = null; - Grib1GridDefinitionSection gds = null; - long startOffset = -1; - - - while (InputStream.Position < InputStream.Length) - { - if (seekHeader(InputStream, InputStream.Length, out startOffset)) - { - // Read Section 0 Indicator Section - Grib1IndicatorSection is_Renamed = new Grib1IndicatorSection(InputStream); - - // EOR (EndOfRecord) calculated so skipping data sections is faster - long EOR = InputStream.Position + is_Renamed.GribLength - is_Renamed.Length; - - // Read Section 1 Product Definition Section PDS - pds = new Grib1ProductDefinitionSection(InputStream); - if (pds.LengthErr) - continue; - - if (pds.gdsExists()) - { - // Read Section 2 Grid Definition Section GDS - gds = new Grib1GridDefinitionSection(InputStream); - } - else - { - // GDS doesn't exist so make one - - - - gds = (Grib1GridDefinitionSection) new Grib1Grid(pds); - } - - // obtain BMS or BDS offset in the file for this product - long dataOffset = 0; - if (pds.Center == 98) - { - // check for ecmwf offset by 1 bug - int length = (int) GribNumbers.uint3(InputStream); // should be length of BMS - if ((length + InputStream.Position) < EOR) - { - dataOffset = InputStream.Position - 3; // ok - } - else - { - dataOffset = InputStream.Position - 2; - } - } - else - { - dataOffset = InputStream.Position; - } - - // position filePointer to EndOfRecord - InputStream.Seek(EOR, System.IO.SeekOrigin.Begin); - - - // assume scan ok - if (getProducts) - { - Grib1Product gp = new Grib1Product(header, pds, getGDSkey(gds, gdsCounter), dataOffset, InputStream.Position); - products.Add(gp); - } - else - { - Grib1Record gr = new Grib1Record(header, is_Renamed, pds, gds, dataOffset, InputStream.Position, startOffset); - records.Add(gr); - } - - if (oneRecord) - return; - - // early return because ending "7777" missing - if (InputStream.Position > InputStream.Length) - { - InputStream.Seek(0, System.IO.SeekOrigin.Begin); - Console.Error.WriteLine("Grib1Input: possible file corruption"); - checkGDSkeys(gds, gdsCounter); - return; - } - } // end if seekHeader - - - - } // end while raf.Position < raf.Length - - - // (System.currentTimeMillis()- start) + " milliseconds"); - checkGDSkeys(gds, gdsCounter); - return; - } // end scan - - /// scans a Grib file to gather information that could be used to - /// create an index or dump the metadata contents. - /// - /// - /// products have enough information for data extractions - /// - /// returns after processing one record in the Grib file - /// - /// NotSupportedException - public IEnumerable scanRecords() - { - InputStream.Seek(0, SeekOrigin.Begin); - - // stores the number of times a particular GDS is used - //UPGRADE_TODO: Class 'java.util.HashMap' was converted to 'System.Collections.Hashtable' which has a different behavior. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1073_javautilHashMap'" - System.Collections.Hashtable gdsCounter = new System.Collections.Hashtable(); - Grib1ProductDefinitionSection pds = null; - Grib1GridDefinitionSection gds = null; - long startOffset = -1; - - - while (InputStream.Position < InputStream.Length) - { - if (seekHeader(InputStream, InputStream.Length, out startOffset)) - { - // Read Section 0 Indicator Section - Grib1IndicatorSection is_Renamed = new Grib1IndicatorSection(InputStream); - - // EOR (EndOfRecord) calculated so skipping data sections is faster - long EOR = InputStream.Position + is_Renamed.GribLength - is_Renamed.Length; - - // Read Section 1 Product Definition Section PDS - pds = new Grib1ProductDefinitionSection(InputStream); - if (pds.LengthErr) - continue; - - if (pds.gdsExists()) - { - // Read Section 2 Grid Definition Section GDS - gds = new Grib1GridDefinitionSection(InputStream); - } - else - { - // GDS doesn't exist so make one - - - - gds = (Grib1GridDefinitionSection)new Grib1Grid(pds); - } - - // obtain BMS or BDS offset in the file for this product - long dataOffset; - if (pds.Center == 98) - { - // check for ecmwf offset by 1 bug - int length = (int)GribNumbers.uint3(InputStream); // should be length of BMS - if ((length + InputStream.Position) < EOR) - { - dataOffset = InputStream.Position - 3; // ok - } - else - { - dataOffset = InputStream.Position - 2; - } - } - else - { - dataOffset = InputStream.Position; - } - - // position filePointer to EndOfRecord - InputStream.Seek(EOR, System.IO.SeekOrigin.Begin); - - - // assume scan ok - Grib1Record gr = new Grib1Record(header, is_Renamed, pds, gds, dataOffset, InputStream.Position, startOffset); - - var currentPosition = InputStream.Position; - yield return gr; - InputStream.Position = currentPosition; - - // early return because ending "7777" missing - if (InputStream.Position > InputStream.Length) - { - InputStream.Seek(0, System.IO.SeekOrigin.Begin); - checkGDSkeys(gds, gdsCounter); - throw new BadGribFormatException("Grib1Input: GRIB ending missing. Possible file corruption"); - } - } // end if seekHeader - } // end while raf.Position < raf.Length - - checkGDSkeys(gds, gdsCounter); - } // end scan - - //UPGRADE_TODO: Class 'java.io.RandomAccessFile' was converted to 'System.IO.FileStream' which has a different behavior. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1073_javaioRandomAccessFile'" - private bool seekHeader(System.IO.Stream raf, long stop, out long startOffset) - { - // seek header - System.Text.StringBuilder hdr = new System.Text.StringBuilder(); - int match = 0; - startOffset = -1; - - while (raf.Position < stop) - { - // code must be "G" "R" "I" "B" - char c = (char) raf.ReadByte(); - - hdr.Append((char) c); - if (c == 'G') - { - match = 1; - startOffset = raf.Position - 1; - } - else if ((c == 'R') && (match == 1)) - { - match = 2; - } - else if ((c == 'I') && (match == 2)) - { - match = 3; - } - else if ((c == 'B') && (match == 3)) - { - return true; - } - else - { - match = 0; /* Needed to protect against "GaRaIaB" case. */ - } - } - - return false; - } // end seekHeader - - private bool seekHeader(System.IO.Stream raf, long stop) - { - long startOffsetDummy = -1; - return seekHeader(raf, stop, out startOffsetDummy); - } - - //UPGRADE_TODO: Class 'java.util.HashMap' was converted to 'System.Collections.Hashtable' which has a different behavior. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1073_javautilHashMap'" - private String getGDSkey(Grib1GridDefinitionSection gds, System.Collections.Hashtable gdsCounter) - { - String key = gds.CheckSum; - // only Lat/Lon grids can have > 1 GDSs - if (gds.GridType == 0 || gds.GridType == 4) - { - if (!gdsHM.ContainsKey(key)) - { - // check if gds is already saved - gdsHM[key] = gds; - } - } - else if (!gdsHM.ContainsKey(key)) - { - // check if gds is already saved - gdsHM[key] = gds; - gdsCounter[key] = "1"; - } - else - { - // increment the counter for this GDS - //UPGRADE_TODO: Method 'java.util.HashMap.get' was converted to 'System.Collections.Hashtable.Item' which has a different behavior. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1073_javautilHashMapget_javalangObject'" - int count = Int32.Parse((String) gdsCounter[key]); - gdsCounter[key] = Convert.ToString(++count); - } - - return key; - } // end getGDSkey - - //UPGRADE_TODO: Class 'java.util.HashMap' was converted to 'System.Collections.Hashtable' which has a different behavior. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1073_javautilHashMap'" - private void checkGDSkeys(Grib1GridDefinitionSection gds, System.Collections.Hashtable gdsCounter) - { - // lat/lon grids can have > 1 GDSs - if (gds.GridType == 0 || gds.GridType == 4) - { - return; - } - - String bestKey = ""; - int count = 0; - // find bestKey with the most counts - //UPGRADE_TODO: Method 'java.util.HashMap.keySet' was converted to 'SupportClass.HashSetSupport' which has a different behavior. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1073_javautilHashMapkeySet'" - //UPGRADE_TODO: Method 'java.util.Iterator.hasNext' was converted to 'System.Collections.IEnumerator.MoveNext' which has a different behavior. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1073_javautilIteratorhasNext'" - for (System.Collections.IEnumerator it = new SupportClass.HashSetSupport(gdsCounter.Keys).GetEnumerator(); it.MoveNext();) - { - //UPGRADE_TODO: Method 'java.util.Iterator.next' was converted to 'System.Collections.IEnumerator.Current' which has a different behavior. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1073_javautilIteratornext'" - String key = (String) it.Current; - //UPGRADE_TODO: Method 'java.util.HashMap.get' was converted to 'System.Collections.Hashtable.Item' which has a different behavior. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1073_javautilHashMapget_javalangObject'" - int gdsCount = Int32.Parse((String) gdsCounter[key]); - if (gdsCount > count) - { - count = gdsCount; - bestKey = key; - } - } - - // remove best key from gdsCounter, others will be removed from gdsHM - gdsCounter.Remove(bestKey); - // remove all GDSs using the gdsCounter - //UPGRADE_TODO: Method 'java.util.HashMap.keySet' was converted to 'SupportClass.HashSetSupport' which has a different behavior. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1073_javautilHashMapkeySet'" - //UPGRADE_TODO: Method 'java.util.Iterator.hasNext' was converted to 'System.Collections.IEnumerator.MoveNext' which has a different behavior. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1073_javautilIteratorhasNext'" - for (System.Collections.IEnumerator it = new SupportClass.HashSetSupport(gdsCounter.Keys).GetEnumerator(); it.MoveNext();) - { - //UPGRADE_TODO: Method 'java.util.Iterator.next' was converted to 'System.Collections.IEnumerator.Current' which has a different behavior. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1073_javautilIteratornext'" - String key = (String) it.Current; - gdsHM.Remove(key); - } - - // reset GDS keys in products too - for (int i = 0; i < products.Count; i++) - { - Grib1Product g1p = (Grib1Product) products[i]; - g1p.GDSkey = bestKey; - } - - return; - } // end checkGDSkeys - - public Grib1Record GetRecord(int idx) - { - if (idx < 0 || idx >= records.Count) - { - throw new IndexOutOfRangeException(); - } - - return records[idx] as Grib1Record; - } - - public Grib1Product GetProduct(int idx) - { - if (idx < 0 || idx >= products.Count) - { - throw new IndexOutOfRangeException(); - } - - return products[idx] as Grib1Product; - } - - public void setFilename(string filename) - { - InputStream = new System.IO.FileStream(filename, System.IO.FileMode.Open, System.IO.FileAccess.Read); - } - - public void closeFile() - { - InputStream.Close(); - } - - public float MissingValue - { - get { return Grib1BinaryDataSection.MissingValue; } - } - } // end Grib1Input -} \ No newline at end of file + #region Fields + /* + * stores records of Grib file, records consist of objects for each section. + * there are 5 sections to a Grib1 record. + */ + //UPGRADE_NOTE: Final was removed from the declaration of 'records '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'" + private List _records = new(); + + private readonly Grib1File _grib1File; + + + #endregion + + + #region Properties + + #region Internal + + /* + * raf for grib file + */ + internal Stream InputStream { get; private set; } + + #endregion + + + #region Public + + /// Get records of the GRIB file. + /// + /// + /// records + /// + public IReadOnlyList Records => _records; + + #endregion + + #endregion + + + #region Constructors + + // *** constructors ******************************************************* + + + /// Constructs a Grib1Input object from a raf. + /// + /// + /// with GRIB content + /// + /// + //UPGRADE_TODO: Class 'java.io.RandomAccessFile' was converted to 'System.IO.FileStream' which has a different behavior. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1073_javaioRandomAccessFile'" + public Grib1Input(System.IO.Stream raf, Grib1File grib1File) + { + this.InputStream = raf; + _grib1File = grib1File; + } + + #endregion + + + #region Methods + + + /// scans a Grib file to gather information that could be used to + /// create an index or dump the metadata contents. + /// + /// + /// products have enough information for data extractions + /// + /// returns after processing one record in the Grib file + /// + /// NotSupportedException + public IEnumerable ScanRecords() + { + + InputStream.Seek(0, SeekOrigin.Begin); + + // stores the number of times a particular GDS is used + //UPGRADE_TODO: Class 'java.util.HashMap' was converted to 'System.Collections.Hashtable' which has a different behavior. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1073_javautilHashMap'" + System.Collections.Hashtable gdsCounter = new System.Collections.Hashtable(); + //Grib1ProductDefinitionSection pds; + Grib1GridDefinitionSection gds = null; + long startOffset; + + + while (InputStream.Position < InputStream.Length) + { + if (!CommonGribFile.SeekHeader(InputStream, InputStream.Length, out startOffset)) continue; + var gr = _grib1File.ReadGrib1Record(InputStream, startOffset, gdsCounter, ref gds); + if (gr == null) + continue; + yield return gr; + } // end while raf.Position < raf.Length + + _grib1File.CheckGdSkeys(gds, gdsCounter); + } + + // end scan + + public Grib1Record GetRecord(int idx) + { + if (idx < 0 || idx >= _records.Count) + { + throw new IndexOutOfRangeException(); + } + + return _records[idx] as Grib1Record; + } + + public void SetFilename(string filename) + { + InputStream = new System.IO.FileStream(filename, System.IO.FileMode.Open, System.IO.FileAccess.Read); + } + + public void CloseFile() + { + InputStream.Close(); + } + + public double MissingValue + { + get { return Grib1BinaryDataSection.MissingValue; } + } + + #endregion +} // end Grib1Input \ No newline at end of file diff --git a/src/NGrib/Grib1/Grib1Product.cs b/src/NGrib/Grib1/Grib1Product.cs index ad510ae..83787ab 100644 --- a/src/NGrib/Grib1/Grib1Product.cs +++ b/src/NGrib/Grib1/Grib1Product.cs @@ -24,111 +24,110 @@ * along with NGrib. If not, see . */ -namespace NGrib.Grib1 +namespace NGrib.Grib1; + +/// Title: Grib1 +/// Description: Class which has the necessary information about +/// a product in a Grib1 File to extract the data for the product. +/// +/// Robb Kambic +/// +/// 1.0 +/// +public sealed class Grib1Product { - /// Title: Grib1 - /// Description: Class which has the necessary information about - /// a product in a Grib1 File to extract the data for the product. - /// - /// Robb Kambic - /// - /// 1.0 - /// - public sealed class Grib1Product - { - /// get the discipline of product as int. - /// discipline - /// - public int Discipline - { - get { return discipline; } - } + /// get the discipline of product as int. + /// discipline + /// + public int Discipline + { + get { return discipline; } + } - /// get category of this product as int. - /// category as a int - /// - public int Category - { - get { return category; } - } + /// get category of this product as int. + /// category as a int + /// + public int Category + { + get { return category; } + } - //UPGRADE_NOTE: Respective javadoc comments were merged. It should be changed in order to comply with .NET documentation conventions. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1199'" - /// gets GDS key for this product. - /// gdsKey - /// - /// sets the GDS key for this product. - /// MD5 checksum as text - /// - public System.String GDSkey - { - get { return gdsKey; } + //UPGRADE_NOTE: Respective javadoc comments were merged. It should be changed in order to comply with .NET documentation conventions. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1199'" + /// gets GDS key for this product. + /// gdsKey + /// + /// sets the GDS key for this product. + /// MD5 checksum as text + /// + public System.String GDSkey + { + get { return gdsKey; } - set { gdsKey = value; } - } + set { gdsKey = value; } + } - /// get the PDS for this product. - /// pds - /// - public Grib1ProductDefinitionSection PDS - { - get { return pds; } - } + /// get the PDS for this product. + /// pds + /// + public Grib1ProductDefinitionSection PDS + { + get { return pds; } + } - /// offset to where to start reading data for this product. - /// dataOffset - /// - public long DataOffset - { - get { return dataOffset; } - } + /// offset to where to start reading data for this product. + /// dataOffset + /// + public long DataOffset + { + get { return dataOffset; } + } - /// where this record ends in the Grib File. - /// endRecordOffset - /// - public long EndRecordOffset - { - get { return endRecordOffset; } - } + /// where this record ends in the Grib File. + /// endRecordOffset + /// + public long EndRecordOffset + { + get { return endRecordOffset; } + } - //UPGRADE_NOTE: Final was removed from the declaration of 'header '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'" - private System.String header; + //UPGRADE_NOTE: Final was removed from the declaration of 'header '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'" + private System.String header; - //UPGRADE_NOTE: Final was removed from the declaration of 'discipline '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'" - private int discipline = 0; + //UPGRADE_NOTE: Final was removed from the declaration of 'discipline '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'" + private int discipline = 0; - //UPGRADE_NOTE: Final was removed from the declaration of 'category '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'" - private int category = -1; + //UPGRADE_NOTE: Final was removed from the declaration of 'category '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'" + private int category = -1; - // --Commented out by Inspection (11/17/05 2:14 PM): protected Grib1IndicatorSection is = null; - private Grib1ProductDefinitionSection pds; - private System.String gdsKey; - private long dataOffset = -1; - private long endRecordOffset = -1; + // --Commented out by Inspection (11/17/05 2:14 PM): protected Grib1IndicatorSection is = null; + private Grib1ProductDefinitionSection pds; + private System.String gdsKey; + private long dataOffset = -1; + private long endRecordOffset = -1; - /// Constructor. - /// - /// - /// - /// - /// - /// - /// - /// - /// endRecordOffset in file - /// - internal Grib1Product(System.String header, Grib1ProductDefinitionSection pds, System.String gdsKey, long offset, long size) - { - this.header = header; - this.gdsKey = gdsKey; - this.pds = pds; - dataOffset = offset; - endRecordOffset = size; - } + /// Constructor. + /// + /// + /// + /// + /// + /// + /// + /// + /// endRecordOffset in file + /// + internal Grib1Product(System.String header, Grib1ProductDefinitionSection pds, System.String gdsKey, long offset, long size) + { + this.header = header; + this.gdsKey = gdsKey; + this.pds = pds; + dataOffset = offset; + endRecordOffset = size; + } - // --Commented out by Inspection START (11/17/05 2:15 PM): - // public final String getHeader(){ - // return header; - // } - // --Commented out by Inspection STOP (11/17/05 2:15 PM) - } // end Grib1Product -} \ No newline at end of file + // --Commented out by Inspection START (11/17/05 2:15 PM): + // public final String getHeader(){ + // return header; + // } + // --Commented out by Inspection STOP (11/17/05 2:15 PM) +} // end Grib1Product \ No newline at end of file diff --git a/src/NGrib/Grib1/Grib1ProductDefinitionSection.cs b/src/NGrib/Grib1/Grib1ProductDefinitionSection.cs index 2d3a111..d87759b 100644 --- a/src/NGrib/Grib1/Grib1ProductDefinitionSection.cs +++ b/src/NGrib/Grib1/Grib1ProductDefinitionSection.cs @@ -1,7 +1,7 @@ /* * This file is part of NGrib. * - * Copyright 2020 Nicolas Mangu + * Copyright © 2020 Nicolas Manguй * * Copyright 2006-2010 Seaware AB, PO Box 1244, SE-131 28 * Nacka Strand, Sweden, info@seaware.se. @@ -32,937 +32,968 @@ /// /// -using System; +using System.Diagnostics.CodeAnalysis; +using NGrib.Grib1.PdsParameterTables; +using NGrib.Grib2.CodeTables; -namespace NGrib.Grib1 +namespace NGrib.Grib1; + +/// A class representing the product definition section (PDS) of a GRIB record. +/// +/// +public sealed record Grib1ProductDefinitionSection { - /// A class representing the product definition section (PDS) of a GRIB record. - /// - /// - public sealed class Grib1ProductDefinitionSection - { - /// Center as int. - /// center_id - /// - public int Center - { - get { return center_id; } - } - - /// Process Id as int. - /// process_id - /// - public int Process_Id - { - get { return process_id; } - } - - /// Grid ID as int. - /// grid_id - /// - public int Grid_Id - { - get { return grid_id; } - } - - /// SubCenter as int. - /// subCenter - /// - public int SubCenter - { - get { return subcenter_id; } - } - - /// gets the Table version as a int. - /// table_version - /// - public int TableVersion - { - get { return table_version; } - } - - /// Get the exponent of the decimal scale used for all data values. - /// - /// - /// exponent of decimal scale - /// - public int DecimalScale - { - get { return decscale; } - } - - /// Get the number of the parameter. - /// - /// - /// index number of parameter in table - /// - public int ParameterNumber - { - get { return parameterNumber; } - } - - /// Get the type of the parameter. - /// - /// - /// type of parameter - /// - public String Type - { - get { return parameter.Name; } - } - - /// Get a descritpion of the parameter. - /// - /// - /// descritpion of parameter - /// - public String Description - { - get { return parameter.Description; } - } - - /// Get the name of the unit of the parameter. - /// - /// - /// name of the unit of the parameter - /// - public String Unit - { - get { return parameter.Unit; } - } - - /// Get the name for the type of level for forecast/analysis. - /// - /// - /// name of level (height or pressure) - /// - public String LevelName - { - get { return level.Name; } - } - - /// Get the numeric value for this level. - /// - /// - /// name of level (height or pressure) - /// - public int LevelType - { - get { return level.Index; } - } - - /// Get the numeric value for this level. - /// - /// - /// name of level (height or pressure) - /// - public int LevelValue1 - { - get - { - //UPGRADE_WARNING: Data types in Visual C# might be different. Verify the accuracy of narrowing conversions. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1042'" - return (int) level.Value1; - } - } - - /// Get value 2 (if it exists) for this level. - /// - /// - /// name of level (height or pressure) - /// - public int LevelValue2 - { - get - { - //UPGRADE_WARNING: Data types in Visual C# might be different. Verify the accuracy of narrowing conversions. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1042'" - return (int) level.Value2; - } - } - - /// Get the base (analysis) time of the forecast. - /// - /// - /// date and time - /// - public DateTime BaseTime - { - get { return baseTime; } - } - - /// gets reference time as a String. - /// referenceTime - /// - public String ReferenceTime - { - get { return referenceTime; } - } - - /// Get the time of the forecast. - /// - /// - /// date and time - /// - public int ForecastTime - { - get { return forecastTime; } - } - - /// Get the time unit. - /// - /// - /// time unit - /// - public int TimeUnitValue - { - get { return timeUnit; } - } - - - /// P1. - /// p1 - /// - public int P1 - { - get { return p1; } - } - - /// P2. - /// p2 - /// - public int P2 - { - get { return p2; } - } - - /// Get the parameter for this pds. - /// parameter - /// - public Parameter Parameter - { - get { return parameter; } - } - - /// gets the time unit ie hour. - /// tUnit - /// - public String TimeUnit - { - get { return tUnit; } - } - - /// ProductDefinition as a int. - /// timeRangeValue - /// - public int ProductDefinition - { - get { return timeRangeValue; } - } - - /// TimeRange as int. - /// timeRangeValue - /// - public int TimeRange - { - get { return timeRangeValue; } - } - - /// TimeRange as String. - /// timeRange - /// - public String TimeRangeString - { - get { return timeRange; } - } - - /// PDS length did not correspond with read . - /// lengthErr - /// - public bool LengthErr - { - get { return lengthErr; } - } - - public int RefTimeT - { - get - { - DateTime startTime = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc); - TimeSpan rt = refTime - startTime; - int t = Convert.ToInt32(rt.TotalSeconds); - return t; - } - } - - public Grib1WaveSpectra2DDirFreq WaveSpectra2DDirFreq - { - get { return waveSpectra2DDirFreq; } - } - - //UPGRADE_ISSUE: Class 'java.text.SimpleDateFormat' was not converted. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1000_javatextSimpleDateFormat'" - private static System.Globalization.DateTimeFormatInfo dateFormat; - - /// Length in bytes of this PDS. - //UPGRADE_NOTE: Final was removed from the declaration of 'length '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'" - private int length; - - /// Exponent of decimal scale. - //UPGRADE_NOTE: Final was removed from the declaration of 'decscale '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'" - private int decscale; - - /// ID of grid type. - //UPGRADE_NOTE: Final was removed from the declaration of 'grid_id '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'" - private int grid_id; - - /// True, if GDS exists. - //UPGRADE_NOTE: Final was removed from the declaration of 'gds_exists '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'" - private bool gds_exists; - - /// True, if BMS exists. - //UPGRADE_NOTE: Final was removed from the declaration of 'bms_exists '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'" - private bool bms_exists; - - /// The parameter as defined in the Parameter Table. - //UPGRADE_NOTE: Final was removed from the declaration of 'parameter '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'" - private Parameter parameter; - - /// parameterNumber. - //UPGRADE_NOTE: Final was removed from the declaration of 'parameterNumber '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'" - private int parameterNumber; - - /// Class containing the information about the level. This helps to actually - /// use the data, otherwise the string for level will have to be parsed. - /// - //UPGRADE_NOTE: Final was removed from the declaration of 'level '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'" - private GribPDSLevel level; - - /// Model Run/Analysis/Reference time. - /// - /// - // TODO Why baseTime??? - private DateTime baseTime; - - private String referenceTime = ""; - - /// Forecast time (valid time). - private int forecastTime; - - /// Forecast time. (valid time 1) - /// Also used as starting time when times represent a period. - /// - private int p1; - - /// Ending time when times represent a period (valid time 2). - private int p2; - - /// Strings used in building a string to represent the time(s) for this PDS - /// See the decoder for octet 21 to get an understanding. - /// - private String timeRange; - - //UPGRADE_NOTE: Final was removed from the declaration of 'timeRangeValue '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'" - private int timeRangeValue; - private String tUnit; - - /// Parameter Table Version number. - //UPGRADE_NOTE: Final was removed from the declaration of 'table_version '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'" - private int table_version; - - /// Identification of center e.g. 88 for Oslo. - //UPGRADE_NOTE: Final was removed from the declaration of 'center_id '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'" - private int center_id; - - /// Identification of subcenter. - //UPGRADE_NOTE: Final was removed from the declaration of 'subcenter_id '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'" - private int subcenter_id; - - /// Identification of Generating Process. - //UPGRADE_NOTE: Final was removed from the declaration of 'process_id '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'" - private int process_id; - - /// ensemble products have more information. - private Grib1Ensemble epds; - - /// PDS length not equal to number bytes read. - //UPGRADE_NOTE: Final was removed from the declaration of 'lengthErr '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'" - private bool lengthErr = false; - - private DateTime refTime; - - private int timeUnit; + /// Center as int. + /// center_id + /// + public int Center + { + get { return center_id; } + } + + /// Process Id as int. + /// process_id + /// + public int Process_Id + { + get { return process_id; } + } + + /// Grid ID as int. + /// grid_id + /// + public int Grid_Id + { + get { return grid_id; } + } + + /// SubCenter as int. + /// subCenter + /// + public int SubCenter + { + get { return subcenter_id; } + } + + /// gets the Table version as a int. + /// table_version + /// + public int TableVersion + { + get { return table_version; } + } + + /// Get the exponent of the decimal scale used for all data values. + /// + /// + /// exponent of decimal scale + /// + public int DecimalScale + { + get { return decscale; } + } + + /// Get the number of the parameter. + /// + /// + /// index number of parameter in table + /// + public int ParameterNumber + { + get { return parameterNumber; } + } + + /// Get the type of the parameter. + /// + /// + /// type of parameter + /// + public String Type + { + get { return parameter.Name; } + } + + /// Get a descritpion of the parameter. + /// + /// + /// descritpion of parameter + /// + public String Description + { + get { return parameter.Description; } + } + + /// Get the name of the unit of the parameter. + /// + /// + /// name of the unit of the parameter + /// + public String Unit + { + get { return parameter.Unit; } + } + + /// Get the name for the type of level for forecast/analysis. + /// + /// + /// name of level (height or pressure) + /// + public String LevelName + { + get { return level.Name; } + } + + /// Get the numeric value for this level. + /// + /// + /// name of level (height or pressure) + /// + public int LevelType + { + get { return level.Index; } + } + + /// Get the numeric value for this level. + /// + /// + /// name of level (height or pressure) + /// + public int LevelValue1 + { + get + { + //UPGRADE_WARNING: Data types in Visual C# might be different. Verify the accuracy of narrowing conversions. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1042'" + return (int) level.Value1; + } + } + + /// Get value 2 (if it exists) for this level. + /// + /// + /// name of level (height or pressure) + /// + public int LevelValue2 + { + get + { + //UPGRADE_WARNING: Data types in Visual C# might be different. Verify the accuracy of narrowing conversions. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1042'" + return (int) level.Value2; + } + } + + /// Get the base (analysis) time of the forecast. + /// + /// + /// date and time + /// + public DateTime BaseTime + { + get { return baseTime; } + } + + /// gets reference time as a String. + /// referenceTime + /// + public String ReferenceTime + { + get { return referenceTime; } + } + + /// Get the time of the forecast. + /// + /// + /// date and time + /// + public int ForecastTime + { + get { return forecastTime; } + } + + /// Get the time unit. + /// + /// + /// time unit + /// + public int TimeUnitValue + { + get { return timeUnit; } + } + + + /// P1. + /// p1 + /// + public int P1 + { + get { return p1; } + } + + /// P2. + /// p2 + /// + public int P2 + { + get { return p2; } + } + + /// Get the parameter for this pds. + /// parameter + /// + public Parameter Parameter + { + get { return parameter; } + } + + /// gets the time unit ie hour. + /// tUnit + /// + public String TimeUnit + { + get { return tUnit; } + } + + public TimeRangeUnitGrib1 TimeRangeUnit => _tRangeUnitGrib1; + + /// ProductDefinition as a int. + /// timeRangeValue + /// + public int ProductDefinition + { + get { return timeRangeValue; } + } + + /// TimeRange as int. + /// timeRangeValue + /// + public int TimeRange + { + get { return timeRangeValue; } + } + + /// TimeRange as String. + /// timeRange + /// + public String TimeRangeString + { + get { return timeRange; } + } + + /// PDS length did not correspond with read . + /// lengthErr + /// + public bool LengthErr + { + get { return lengthErr; } + } + + public int RefTimeT + { + get + { + DateTime startTime = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc); + TimeSpan rt = refTime - startTime; + int t = Convert.ToInt32(rt.TotalSeconds); + return t; + } + } + + public Grib1WaveSpectra2DDirFreq WaveSpectra2DDirFreq + { + get { return waveSpectra2DDirFreq; } + } + + //UPGRADE_ISSUE: Class 'java.text.SimpleDateFormat' was not converted. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1000_javatextSimpleDateFormat'" + private static System.Globalization.DateTimeFormatInfo dateFormat; + + /// Length in bytes of this PDS. + //UPGRADE_NOTE: Final was removed from the declaration of 'length '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'" + private int length; + + /// Exponent of decimal scale. + //UPGRADE_NOTE: Final was removed from the declaration of 'decscale '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'" + private int decscale; + + /// ID of grid type. + //UPGRADE_NOTE: Final was removed from the declaration of 'grid_id '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'" + private int grid_id; + + /// True, if GDS exists. + //UPGRADE_NOTE: Final was removed from the declaration of 'gds_exists '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'" + private bool gds_exists; + + /// True, if BMS exists. + //UPGRADE_NOTE: Final was removed from the declaration of 'bms_exists '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'" + private bool bms_exists; + + /// The parameter as defined in the Parameter Table. + //UPGRADE_NOTE: Final was removed from the declaration of 'parameter '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'" + private Parameter parameter; + + /// parameterNumber. + //UPGRADE_NOTE: Final was removed from the declaration of 'parameterNumber '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'" + private int parameterNumber; + + /// Class containing the information about the level. This helps to actually + /// use the data, otherwise the string for level will have to be parsed. + /// + //UPGRADE_NOTE: Final was removed from the declaration of 'level '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'" + private GribPDSLevel level; + + /// Model Run/Analysis/Reference time. + /// + /// + // TODO Why baseTime??? + private DateTime baseTime; + + private String referenceTime = ""; + + /// Forecast time (valid time). + private int forecastTime; + + /// Forecast time. (valid time 1) + /// Also used as starting time when times represent a period. + /// + private int p1; + + /// Ending time when times represent a period (valid time 2). + private int p2; + + /// Strings used in building a string to represent the time(s) for this PDS + /// See the decoder for octet 21 to get an understanding. + /// + private String timeRange; + + //UPGRADE_NOTE: Final was removed from the declaration of 'timeRangeValue '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'" + private int timeRangeValue; + private String tUnit; + + private TimeRangeUnitGrib1 _tRangeUnitGrib1 = TimeRangeUnitGrib1.Missing; + + /// Parameter Table Version number. + //UPGRADE_NOTE: Final was removed from the declaration of 'table_version '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'" + private int table_version; + + /// Identification of center e.g. 88 for Oslo. + //UPGRADE_NOTE: Final was removed from the declaration of 'center_id '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'" + private int center_id; + + /// Identification of subcenter. + //UPGRADE_NOTE: Final was removed from the declaration of 'subcenter_id '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'" + private int subcenter_id; + + /// Identification of Generating Process. + //UPGRADE_NOTE: Final was removed from the declaration of 'process_id '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'" + private int process_id; + + /// ensemble products have more information. + private Grib1Ensemble epds; + + /// PDS length not equal to number bytes read. + //UPGRADE_NOTE: Final was removed from the declaration of 'lengthErr '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'" + private bool lengthErr = false; - private Grib1WaveSpectra2DDirFreq waveSpectra2DDirFreq; + private DateTime refTime; - /// - /// Data reserved for originating centre use - /// at the end of the section. - /// - /// - /// Each byte is stored as an item in the array. - /// - public int[] CustomData { get; } + private int timeUnit; - // *** constructors ******************************************************* + private Grib1WaveSpectra2DDirFreq waveSpectra2DDirFreq; - /// Constructs a Grib1ProductDefinitionSection object from a raf. - /// - /// - /// with PDS content - /// - /// - /// NotSupportedException if raf contains no valid GRIB file - //UPGRADE_TODO: Class 'java.io.RandomAccessFile' was converted to 'System.IO.FileStream' which has a different behavior. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1073_javaioRandomAccessFile'" - internal Grib1ProductDefinitionSection(System.IO.Stream raf) - { - // octets 1-3 PDS length - length = (int) GribNumbers.uint3(raf); + /// + /// Data reserved for originating centre use + /// at the end of the section. + /// + /// + /// Each byte is stored as an item in the array. + /// + public int[] CustomData { get; } + // *** constructors ******************************************************* - // Paramter table octet 4 - table_version = raf.ReadByte(); + /// Constructs a Grib1ProductDefinitionSection object from a raf. + /// + /// + /// with PDS content + /// + /// + /// NotSupportedException if raf contains no valid GRIB file + //UPGRADE_TODO: Class 'java.io.RandomAccessFile' was converted to 'System.IO.FileStream' which has a different behavior. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1073_javaioRandomAccessFile'" + internal Grib1ProductDefinitionSection(System.IO.Stream raf) + { + // octets 1-3 PDS length + length = (int) GribNumbers.uint3(raf); - // Center octet 5 - center_id = raf.ReadByte(); - // octet 6 Generating Process - See Table A - process_id = raf.ReadByte(); + // Paramter table octet 4 + table_version = raf.ReadByte(); - // octet 7 (id of grid type) - not supported yet - grid_id = raf.ReadByte(); + // Center octet 5 + center_id = raf.ReadByte(); - //octet 8 (flag for presence of GDS and BMS) - int exists = raf.ReadByte(); - //BKSystem.IO.BitStream s = new BKSystem.IO.BitStream(8); + // octet 6 Generating Process - See Table A + process_id = raf.ReadByte(); + + // octet 7 (id of grid type) - not supported yet + grid_id = raf.ReadByte(); + + //octet 8 (flag for presence of GDS and BMS) + int exists = raf.ReadByte(); + //BKSystem.IO.BitStream s = new BKSystem.IO.BitStream(8); // s.WriteByte((byte)raf.ReadByte()); // s.Position = 0; // sbyte exists; // s.Read(out exists); // bms_exists = (exists & 64) == 64; - gds_exists = (exists & 128) == 128; - bms_exists = (exists & 64) == 64; - - // octet 9 (parameter and unit) - parameterNumber = raf.ReadByte(); - - // octets 10-12 (level) - int levelType = raf.ReadByte(); - int levelValue1 = raf.ReadByte(); - int levelValue2 = raf.ReadByte(); - level = new GribPDSLevel(levelType, levelValue1, levelValue2); - - // octets 13-17 (base time for reference time) - int year = raf.ReadByte(); - int month = raf.ReadByte(); - int day = raf.ReadByte(); - int hour = raf.ReadByte(); - int minute = raf.ReadByte(); - - // get info for forecast time - // octet 18 Forecast time unit - timeUnit = raf.ReadByte(); - - switch (timeUnit) - { - case 0: // minute - tUnit = "minute"; - break; - - case 1: // hours - tUnit = "hour"; - break; - - case 2: // day - tUnit = "day"; - break; - - case 3: // month - tUnit = "month"; - break; - - case 4: //1 year - tUnit = "1year"; - break; - - case 5: // decade - tUnit = "decade"; - break; - - case 6: // normal - tUnit = "day"; - break; - - case 7: // century - tUnit = "century"; - break; - - case 10: //3 hours - tUnit = "3hours"; - break; - - case 11: // 6 hours - tUnit = "6hours"; - break; - - case 12: // 12 hours - tUnit = "12hours"; - break; - - case 254: // second - tUnit = "second"; - break; - - - default: - Console.Error.WriteLine("PDS: Time Unit " + timeUnit + " is not yet supported"); - break; - } - - // octet 19 & 20 used to create Forecast time - p1 = raf.ReadByte(); - p2 = raf.ReadByte(); - - // octet 21 (time range indicator) - timeRangeValue = raf.ReadByte(); - // forecast time is always at the end of the range - - switch (timeRangeValue) - { - case 0: - timeRange = "product valid at RT + P1"; - forecastTime = p1; - break; - - case 1: - timeRange = "product valid for RT, P1=0"; - forecastTime = 0; - break; - - case 2: - timeRange = "product valid from (RT + P1) to (RT + P2)"; - forecastTime = p2; - break; - - case 3: - timeRange = "product is an average between (RT + P1) to (RT + P2)"; - forecastTime = p2; - break; - - case 4: - timeRange = "product is an accumulation between (RT + P1) to (RT + P2)"; - forecastTime = p2; - break; - - case 5: - timeRange = "product is the difference (RT + P2) - (RT + P1)"; - forecastTime = p2; - break; - - case 6: - timeRange = "product is an average from (RT - P1) to (RT - P2)"; - forecastTime = -p2; - break; - - case 7: - timeRange = "product is an average from (RT - P1) to (RT + P2)"; - forecastTime = p2; - break; - - case 10: - timeRange = "product valid at RT + P1"; - // p1 really consists of 2 bytes p1 and p2 - forecastTime = p1 = GribNumbers.int2(p1, p2); - p2 = 0; - break; - - case 51: - timeRange = "mean value from RT to (RT + P2)"; - forecastTime = p2; - break; - - default: - Console.Error.WriteLine("PDS: Time Range Indicator " + timeRangeValue + " is not yet supported"); - break; - } - - // octet 22 & 23 - int avgInclude = GribNumbers.int2(raf); - - // octet 24 - int avgMissing = raf.ReadByte(); - - // octet 25 - int century = raf.ReadByte() - 1; - - // octet 26, sub center - subcenter_id = raf.ReadByte(); - - // octets 27-28 (decimal scale factor) - decscale = GribNumbers.int2(raf); - - refTime = new DateTime(century * 100 + year, month, day, hour, minute, 0, DateTimeKind.Utc); - baseTime = refTime; - referenceTime = refTime.ToString(dateFormat); - - - //(century * 100 + year) +"-" + - //month + "-" + day + "T" + hour +":" + minute +":00Z" ); - - - // TODO - /* -parameter_table = GribPDSParamTable.getParameterTable(center_id, subcenter_id, table_version); -parameter = parameter_table.getParameter(parameterNumber); -*/ - parameter = new Parameter(); - - - if (center_id == 7 && subcenter_id == 2) - { - CustomData = new int[0]; - - // ensemble product - epds = new Grib1Ensemble(raf, parameterNumber); - } - // Special handling of 2D Wave Spectra (single) - else if (table_version == 140 && parameterNumber == 251) - { - CustomData = new int[0]; - - SupportClass.Skip(raf, 12); - int extDef = raf.ReadByte(); // Extension definition - - // Read ECMWF extension for 2D wave spectra single - if (extDef == 13) - { - waveSpectra2DDirFreq = new Grib1WaveSpectra2DDirFreq(raf); - } - } - else - { - // Ignore reserved bytes 29-40 - for (int i = 29; i <= Math.Min(length, 40); i++) - { - raf.ReadByte(); - } + gds_exists = (exists & 128) == 128; + bms_exists = (exists & 64) == 64; + + // octet 9 (parameter and unit) + parameterNumber = raf.ReadByte(); + + // octets 10-12 (level) + int levelType = raf.ReadByte(); + int levelValue1 = raf.ReadByte(); + int levelValue2 = raf.ReadByte(); + level = new GribPDSLevel(levelType, levelValue1, levelValue2); + + // octets 13-17 (base time for reference time) + int year = raf.ReadByte(); + int month = raf.ReadByte(); + int day = raf.ReadByte(); + int hour = raf.ReadByte(); + int minute = raf.ReadByte(); + + // get info for forecast time + // octet 18 Forecast time unit + timeUnit = raf.ReadByte(); + + switch (timeUnit) + { + case 0: // minute + tUnit = "minute"; + _tRangeUnitGrib1 = TimeRangeUnitGrib1.Minute; + break; + + case 1: // hours + tUnit = "hour"; + _tRangeUnitGrib1 = TimeRangeUnitGrib1.Hour; + break; + + case 2: // day + tUnit = "day"; + _tRangeUnitGrib1 = TimeRangeUnitGrib1.Day; + break; + + case 3: // month + tUnit = "month"; + _tRangeUnitGrib1 = TimeRangeUnitGrib1.Month; + break; + + case 4: //1 year + tUnit = "1year"; + _tRangeUnitGrib1 = TimeRangeUnitGrib1.Year; + break; + + case 5: // decade + tUnit = "decade"; + _tRangeUnitGrib1 = TimeRangeUnitGrib1.Decade; + break; + + case 6: // normal + tUnit = "normal"; + _tRangeUnitGrib1 = TimeRangeUnitGrib1.Normal; + break; + + case 7: // century + tUnit = "century"; + _tRangeUnitGrib1 = TimeRangeUnitGrib1.Century; + break; + + case 10: //3 hours + tUnit = "3hours"; + _tRangeUnitGrib1 = TimeRangeUnitGrib1.Hours3; + break; + + case 11: // 6 hours + tUnit = "6hours"; + _tRangeUnitGrib1 = TimeRangeUnitGrib1.Hours6; + break; + + case 12: // 12 hours + tUnit = "12hours"; + _tRangeUnitGrib1 = TimeRangeUnitGrib1.Hours12; + break; + + case 13: + tUnit = "15 minutes"; + _tRangeUnitGrib1 = TimeRangeUnitGrib1.Minutes15; + break; + + case 14: + tUnit = "30 minutes"; + _tRangeUnitGrib1 = TimeRangeUnitGrib1.Minutes30; + break; + + case >=15 and <=253: + tUnit = "reserved"; + _tRangeUnitGrib1 = TimeRangeUnitGrib1.Reserved; + break; + + case 254: // second + tUnit = "second"; + _tRangeUnitGrib1 = TimeRangeUnitGrib1.Second; + break; + + default: + Console.Error.WriteLine("PDS: Time Unit " + timeUnit + " is not yet supported"); + _tRangeUnitGrib1 = TimeRangeUnitGrib1.Missing; + break; + } + + // octet 19 & 20 used to create Forecast time + p1 = raf.ReadByte(); + p2 = raf.ReadByte(); + + // octet 21 (time range indicator) + timeRangeValue = raf.ReadByte(); + // forecast time is always at the end of the range + + switch (timeRangeValue) + { + case 0: + timeRange = "product valid at RT + P1"; + forecastTime = p1; + break; + + case 1: + timeRange = "product valid for RT, P1=0"; + forecastTime = 0; + break; + + case 2: + timeRange = "product valid from (RT + P1) to (RT + P2)"; + forecastTime = p2; + break; + + case 3: + timeRange = "product is an average between (RT + P1) to (RT + P2)"; + forecastTime = p2; + break; + + case 4: + timeRange = "product is an accumulation between (RT + P1) to (RT + P2)"; + forecastTime = p2; + break; + + case 5: + timeRange = "product is the difference (RT + P2) - (RT + P1)"; + forecastTime = p2; + break; + + case 6: + timeRange = "product is an average from (RT - P1) to (RT - P2)"; + forecastTime = -p2; + break; + + case 7: + timeRange = "product is an average from (RT - P1) to (RT + P2)"; + forecastTime = p2; + break; + + case 10: + timeRange = "product valid at RT + P1"; + // p1 really consists of 2 bytes p1 and p2 + forecastTime = p1 = GribNumbers.int2(p1, p2); + p2 = 0; + break; + + case 51: + timeRange = "mean value from RT to (RT + P2)"; + forecastTime = p2; + break; + + default: + Console.Error.WriteLine("PDS: Time Range Indicator " + timeRangeValue + " is not yet supported"); + break; + } + + // octet 22 & 23 + int avgInclude = GribNumbers.int2(raf); + + // octet 24 + int avgMissing = raf.ReadByte(); + + // octet 25 + int century = raf.ReadByte() - 1; + + // octet 26, sub center + subcenter_id = raf.ReadByte(); + + // octets 27-28 (decimal scale factor) + decscale = GribNumbers.int2(raf); + + refTime = new DateTime(century * 100 + year, month, day, hour, minute, 0, DateTimeKind.Utc); + baseTime = refTime; + referenceTime = refTime.ToString(dateFormat); + + + //(century * 100 + year) +"-" + + //month + "-" + day + "T" + hour +":" + minute +":00Z" ); + + + var parameterTable = GribPdsParamTable.GetParameterTable(center_id, subcenter_id, table_version); + parameter = parameterTable.GetParameter(parameterNumber); + //parameter = new Parameter(); + + + if (center_id == 7 && subcenter_id == 2) + { + CustomData = new int[0]; + + // ensemble product + epds = new Grib1Ensemble(raf, parameterNumber); + } + // Special handling of 2D Wave Spectra (single) + else if (table_version == 140 && parameterNumber == 251) + { + CustomData = new int[0]; + + SupportClass.Skip(raf, 12); + int extDef = raf.ReadByte(); // Extension definition + + // Read ECMWF extension for 2D wave spectra single + if (extDef == 13) + { + waveSpectra2DDirFreq = new Grib1WaveSpectra2DDirFreq(raf); + } + } + else + { + // Ignore reserved bytes 29-40 + for (int i = 29; i <= Math.Min(length, 40); i++) + { + raf.ReadByte(); + } + + // Try to read extra bytes + CustomData = new int[Math.Max(length - 40, 0)]; + for (int i = 0; i < CustomData.Length; i++) + { + CustomData[i] = raf.ReadByte(); + } + } + } // end Grib1ProductDefinitionSection - // Try to read extra bytes - CustomData = new int[Math.Max(length - 40, 0)]; - for (int i = 0; i < CustomData.Length; i++) - { - CustomData[i] = raf.ReadByte(); - } - } - } // end Grib1ProductDefinitionSection + // --Commented out by Inspection START (11/9/05 10:19 AM): + // /** + // * Get the byte length of this section. + // * + // * @return length in bytes of this section + // */ + // public int getLength() + // { + // return length; + // } + // --Commented out by Inspection STOP (11/9/05 10:19 AM) - // --Commented out by Inspection START (11/9/05 10:19 AM): - // /** - // * Get the byte length of this section. - // * - // * @return length in bytes of this section - // */ - // public int getLength() - // { - // return length; - // } - // --Commented out by Inspection STOP (11/9/05 10:19 AM) + /// Check if GDS exists. + /// + /// + /// true, if GDS exists + /// + public bool gdsExists() + { + return gds_exists; + } - /// Check if GDS exists. - /// - /// - /// true, if GDS exists - /// - public bool gdsExists() - { - return gds_exists; - } + /// Check if BMS exists. + /// + /// + /// true, if BMS exists + /// + public bool bmsExists() + { + return bms_exists; + } - /// Check if BMS exists. - /// - /// - /// true, if BMS exists - /// - public bool bmsExists() - { - return bms_exists; - } + /// Name of Identification of center . + /// Center Name as String + /// + public String getCenter_idName() + { + return getCenter_idName(center_id); + } - /// Name of Identification of center . - /// Center Name as String - /// - public String getCenter_idName() - { - return getCenter_idName(center_id); - } + private static String getCenter_idName(int center) + { + switch (center) + { + case 0: return "WMO Secretariat"; - private static String getCenter_idName(int center) - { - switch (center) - { - case 0: return "WMO Secretariat"; + case 1: + case 2: return "Melbourne"; - case 1: - case 2: return "Melbourne"; + case 4: + case 5: return "Moscow"; - case 4: - case 5: return "Moscow"; + case 7: return "US National Weather Service (NCEP)"; - case 7: return "US National Weather Service (NCEP)"; + case 8: return "US National Weather Service (NWSTG)"; - case 8: return "US National Weather Service (NWSTG)"; + case 9: return "US National Weather Service (other)"; - case 9: return "US National Weather Service (other)"; + case 10: return "Cairo (RSMC/RAFC)"; - case 10: return "Cairo (RSMC/RAFC)"; + case 12: return "Dakar (RSMC/RAFC)"; - case 12: return "Dakar (RSMC/RAFC)"; + case 14: return "Nairobi (RSMC/RAFC)"; - case 14: return "Nairobi (RSMC/RAFC)"; + case 16: return "Atananarivo (RSMC)"; - case 16: return "Atananarivo (RSMC)"; + case 18: return "Tunis Casablanca (RSMC)"; - case 18: return "Tunis Casablanca (RSMC)"; + case 20: return "Las Palmas (RAFC)"; - case 20: return "Las Palmas (RAFC)"; + case 21: return "Algiers (RSMC)"; - case 21: return "Algiers (RSMC)"; + case 22: return "Lagos (RSMC)"; - case 22: return "Lagos (RSMC)"; + case 24: return "Pretoria (RSMC)"; - case 24: return "Pretoria (RSMC)"; + case 25: return "La R?union (RSMC)"; - case 25: return "La R?union (RSMC)"; + case 26: return "Khabarovsk (RSMC)"; - case 26: return "Khabarovsk (RSMC)"; + case 28: return "New Delhi (RSMC/RAFC)"; - case 28: return "New Delhi (RSMC/RAFC)"; + case 30: return "Novosibirsk (RSMC)"; - case 30: return "Novosibirsk (RSMC)"; + case 32: return "Tashkent (RSMC)"; - case 32: return "Tashkent (RSMC)"; + case 33: return "Jeddah (RSMC)"; - case 33: return "Jeddah (RSMC)"; + case 34: return "Tokyo (RSMC), Japan Meteorological Agency"; - case 34: return "Tokyo (RSMC), Japan Meteorological Agency"; + case 36: return "Bangkok"; - case 36: return "Bangkok"; + case 37: return "Ulan Bator"; - case 37: return "Ulan Bator"; + case 38: return "Beijing (RSMC)"; - case 38: return "Beijing (RSMC)"; + case 40: return "Seoul"; - case 40: return "Seoul"; + case 41: return "Buenos Aires (RSMC/RAFC)"; - case 41: return "Buenos Aires (RSMC/RAFC)"; + case 43: return "Brasilia (RSMC/RAFC)"; - case 43: return "Brasilia (RSMC/RAFC)"; + case 45: return "Santiago"; - case 45: return "Santiago"; + case 46: return "Brazilian Space Agency ? INPE"; - case 46: return "Brazilian Space Agency ? INPE"; + case 51: return "Miami (RSMC/RAFC)"; - case 51: return "Miami (RSMC/RAFC)"; + case 52: return "Miami RSMC, National Hurricane Center"; - case 52: return "Miami RSMC, National Hurricane Center"; + case 53: + case 54: return "Montreal (RSMC)"; - case 53: - case 54: return "Montreal (RSMC)"; + case 55: return "San Francisco"; - case 55: return "San Francisco"; + case 57: return "Air Force Weather Agency"; - case 57: return "Air Force Weather Agency"; + case 58: return "Fleet Numerical Meteorology and Oceanography Center"; - case 58: return "Fleet Numerical Meteorology and Oceanography Center"; + case 59: return "The NOAA Forecast Systems Laboratory"; - case 59: return "The NOAA Forecast Systems Laboratory"; + case 60: return "United States National Centre for Atmospheric Research (NCAR)"; - case 60: return "United States National Centre for Atmospheric Research (NCAR)"; + case 64: return "Honolulu"; - case 64: return "Honolulu"; + case 65: return "Darwin (RSMC)"; - case 65: return "Darwin (RSMC)"; + case 67: return "Melbourne (RSMC)"; - case 67: return "Melbourne (RSMC)"; + case 69: return "Wellington (RSMC/RAFC)"; - case 69: return "Wellington (RSMC/RAFC)"; + case 71: return "Nadi (RSMC)"; - case 71: return "Nadi (RSMC)"; + case 74: return "UK Meteorological Office Bracknell (RSMC)"; - case 74: return "UK Meteorological Office Bracknell (RSMC)"; + case 76: return "Moscow (RSMC/RAFC)"; - case 76: return "Moscow (RSMC/RAFC)"; + case 78: return "Offenbach (RSMC)"; - case 78: return "Offenbach (RSMC)"; + case 80: return "Rome (RSMC)"; - case 80: return "Rome (RSMC)"; + case 82: return "Norrkoping"; - case 82: return "Norrkoping"; + case 85: return "Toulouse (RSMC)"; - case 85: return "Toulouse (RSMC)"; + case 86: return "Helsinki"; - case 86: return "Helsinki"; + case 87: return "Belgrade"; - case 87: return "Belgrade"; + case 88: return "Oslo"; - case 88: return "Oslo"; + case 89: return "Prague"; - case 89: return "Prague"; + case 90: return "Episkopi"; - case 90: return "Episkopi"; + case 91: return "Ankara"; - case 91: return "Ankara"; + case 92: return "Frankfurt/Main (RAFC)"; - case 92: return "Frankfurt/Main (RAFC)"; + case 93: return "London (WAFC)"; - case 93: return "London (WAFC)"; + case 94: return "Copenhagen"; - case 94: return "Copenhagen"; + case 95: return "Rota"; - case 95: return "Rota"; + case 96: return "Athens"; - case 96: return "Athens"; + case 97: return "European Space Agency (ESA)"; - case 97: return "European Space Agency (ESA)"; + case 98: return "ECMWF, RSMC"; - case 98: return "ECMWF, RSMC"; + case 99: return "De Bilt"; - case 99: return "De Bilt"; + case 110: return "Hong-Kong"; - case 110: return "Hong-Kong"; + case 210: return "Frascati (ESA/ESRIN)"; - case 210: return "Frascati (ESA/ESRIN)"; + case 211: return "Lanion"; - case 211: return "Lanion"; + case 212: return "Lisboa"; - case 212: return "Lisboa"; + case 213: return "Reykjavik"; - case 213: return "Reykjavik"; + case 254: return "EUMETSAT Operation Centre"; - case 254: return "EUMETSAT Operation Centre"; + default: return "Unknown"; + } + } // end getCenter_idName - default: return "Unknown"; - } - } // end getCenter_idName + /// SubCenter as String. + /// + /// + /// subCenter + /// + public String getSubCenter_idName(int center) + { + if (center_id == 7) + { + //NWS + switch (center) + { + case 0: return "WMO Secretariat"; - /// SubCenter as String. - /// - /// - /// subCenter - /// - public String getSubCenter_idName(int center) - { - if (center_id == 7) - { - //NWS - switch (center) - { - case 0: return "WMO Secretariat"; + case 1: return "NCEP Re-Analysis Project"; - case 1: return "NCEP Re-Analysis Project"; + case 2: return "NCEP Ensemble Products"; - case 2: return "NCEP Ensemble Products"; + case 3: return "NCEP Central Operations"; - case 3: return "NCEP Central Operations"; + case 4: return "Environmental Modeling Center"; - case 4: return "Environmental Modeling Center"; + case 5: return "Hydrometeorological Prediction Center"; - case 5: return "Hydrometeorological Prediction Center"; + case 6: return "Marine Prediction Center"; - case 6: return "Marine Prediction Center"; + case 7: return "Climate Prediction Center"; - case 7: return "Climate Prediction Center"; + case 8: return "Aviation Weather Center"; - case 8: return "Aviation Weather Center"; + case 9: return "Storm Prediction Center"; - case 9: return "Storm Prediction Center"; + case 10: return "Tropical Prediction Center"; - case 10: return "Tropical Prediction Center"; + case 11: return "NWS Techniques Development Laboratory"; - case 11: return "NWS Techniques Development Laboratory"; + case 12: return "NESDIS Office of Research and Applications"; - case 12: return "NESDIS Office of Research and Applications"; + case 13: return "FAA"; - case 13: return "FAA"; + case 14: return "NWS Meteorological Development Laboratory"; - case 14: return "NWS Meteorological Development Laboratory"; + case 15: return " The North American Regional Reanalysis (NARR) Project"; + } + } - case 15: return " The North American Regional Reanalysis (NARR) Project"; - } - } + return getCenter_idName(center); + } - return getCenter_idName(center); - } + /// ProductDefinition name. + /// + /// + /// name of ProductDefinition + /// + public static String getProductDefinitionName(int type) + { + switch (type) + { + case 0: return "Forecast/Uninitialized Analysis/Image Product"; - /// ProductDefinition name. - /// - /// - /// name of ProductDefinition - /// - public static String getProductDefinitionName(int type) - { - switch (type) - { - case 0: return "Forecast/Uninitialized Analysis/Image Product"; + case 1: return "Initialized analysis product"; - case 1: return "Initialized analysis product"; + case 2: return "Product with a valid time between P1 and P2"; - case 2: return "Product with a valid time between P1 and P2"; + case 3: + case 6: + case 7: return "Average"; - case 3: - case 6: - case 7: return "Average"; + case 4: return "Accumulation"; - case 4: return "Accumulation"; + case 5: return "Difference"; - case 5: return "Difference"; + case 10: return "product valid at reference time P1"; - case 10: return "product valid at reference time P1"; + case 51: return "Climatological Mean Value"; - case 51: return "Climatological Mean Value"; + case 113: + case 115: + case 117: return "Average of N forecasts"; - case 113: - case 115: - case 117: return "Average of N forecasts"; + case 114: + case 116: return "Accumulation of N forecasts"; - case 114: - case 116: return "Accumulation of N forecasts"; + case 118: return "Temporal variance"; - case 118: return "Temporal variance"; + case 119: + case 125: return "Standard deviation of N forecasts"; - case 119: - case 125: return "Standard deviation of N forecasts"; + case 123: return "Average of N uninitialized analyses"; - case 123: return "Average of N uninitialized analyses"; + case 124: return "Accumulation of N uninitialized analyses"; - case 124: return "Accumulation of N uninitialized analyses"; + case 128: return "Average of daily forecast accumulations"; - case 128: return "Average of daily forecast accumulations"; + case 129: return "Average of successive forecast accumulations"; - case 129: return "Average of successive forecast accumulations"; + case 130: return "Average of daily forecast averages"; - case 130: return "Average of daily forecast averages"; + case 131: return "Average of successive forecast averages"; - case 131: return "Average of successive forecast averages"; + case 132: return "Climatological Average of N analyses"; - case 132: return "Climatological Average of N analyses"; + case 133: return "Climatological Average of N forecasts"; - case 133: return "Climatological Average of N forecasts"; + case 134: return "Climatological Root Mean Square difference between N forecasts and their verifying analyses"; - case 134: return "Climatological Root Mean Square difference between N forecasts and their verifying analyses"; + case 135: return "Climatological Standard Deviation of N forecasts from the mean of the same N forecasts"; - case 135: return "Climatological Standard Deviation of N forecasts from the mean of the same N forecasts"; + case 136: return "Climatological Standard Deviation of N analyses from the mean of the same N analyses"; + } - case 136: return "Climatological Standard Deviation of N analyses from the mean of the same N analyses"; - } + return "Unknown"; + } - return "Unknown"; - } + static Grib1ProductDefinitionSection() + { + { + dateFormat = new System.Globalization.DateTimeFormatInfo(); + } + } +} - static Grib1ProductDefinitionSection() - { - { - dateFormat = new System.Globalization.DateTimeFormatInfo(); - } - } - } // end class Grib1ProductDefinitionSection -} \ No newline at end of file +// end class Grib1ProductDefinitionSection \ No newline at end of file diff --git a/src/NGrib/Grib1/Grib1Record.cs b/src/NGrib/Grib1/Grib1Record.cs index 66ed547..d7a0cba 100644 --- a/src/NGrib/Grib1/Grib1Record.cs +++ b/src/NGrib/Grib1/Grib1Record.cs @@ -1,7 +1,7 @@ /* * This file is part of NGrib. * - * Copyright 2020 Nicolas Mangu + * Copyright © 2020 Nicolas Manguй * * Copyright 2006-2010 Seaware AB, PO Box 1244, SE-131 28 * Nacka Strand, Sweden, info@seaware.se. @@ -24,51 +24,50 @@ * along with NGrib. If not, see . */ -namespace NGrib.Grib1 +namespace NGrib.Grib1; + +/// Grib1Record contains all the sections of a Grib record. +/// Robb Kambic 11/13/03 +/// +public sealed class Grib1Record { - /// Grib1Record contains all the sections of a Grib record. - /// Robb Kambic 11/13/03 - /// - public sealed class Grib1Record - { - /// Get header. - /// header - /// - public System.String Header { get; } + /// Get header. + /// header + /// + public System.String Header { get; } - /// Get Information record. - /// an IS record - /// - public Grib1IndicatorSection IndicatorSection { get; } + /// Get Information record. + /// an IS record + /// + public Grib1IndicatorSection IndicatorSection { get; } - /// Get Product Definition record. - /// a PDS record - /// - public Grib1ProductDefinitionSection ProductDefinitionSection { get; } + /// Get Product Definition record. + /// a PDS record + /// + public Grib1ProductDefinitionSection ProductDefinitionSection { get; } - /// Get Grid Definition record. - /// a - /// - public Grib1GridDefinitionSection GridDefinitionSection { get; } + /// Get Grid Definition record. + /// a + /// + public Grib1GridDefinitionSection GridDefinitionSection { get; } - /// Get offset to bms. - /// long - /// - public long DataOffset { get; } = -1; + /// Get offset to bms. + /// long + /// + public long DataOffset { get; } = -1; - public long RecordOffset { get; } = -1; + public long RecordOffset { get; } = -1; - private long endRecordOffset = -1; + private long endRecordOffset = -1; - internal Grib1Record(System.String hdr, Grib1IndicatorSection aIndicatorSection, Grib1ProductDefinitionSection aProductDefinitionSection, Grib1GridDefinitionSection aGridDefinitionSection, long offset, long recOffset, long startOfRecordOffset) - { - Header = hdr; - IndicatorSection = aIndicatorSection; - ProductDefinitionSection = aProductDefinitionSection; - GridDefinitionSection = aGridDefinitionSection; - DataOffset = offset; - endRecordOffset = recOffset; - RecordOffset = startOfRecordOffset; - } - } // end Grib1Record -} \ No newline at end of file + internal Grib1Record(System.String hdr, Grib1IndicatorSection aIndicatorSection, Grib1ProductDefinitionSection aProductDefinitionSection, Grib1GridDefinitionSection aGridDefinitionSection, long offset, long recOffset, long startOfRecordOffset) + { + Header = hdr; + IndicatorSection = aIndicatorSection; + ProductDefinitionSection = aProductDefinitionSection; + GridDefinitionSection = aGridDefinitionSection; + DataOffset = offset; + endRecordOffset = recOffset; + RecordOffset = startOfRecordOffset; + } +} // end Grib1Record \ No newline at end of file diff --git a/src/NGrib/Grib1/Grib1WaveSpectra2DDirFreq.cs b/src/NGrib/Grib1/Grib1WaveSpectra2DDirFreq.cs index 7956a66..5aab43c 100644 --- a/src/NGrib/Grib1/Grib1WaveSpectra2DDirFreq.cs +++ b/src/NGrib/Grib1/Grib1WaveSpectra2DDirFreq.cs @@ -24,125 +24,124 @@ * along with NGrib. If not, see . */ -namespace NGrib.Grib1 +namespace NGrib.Grib1; + +public sealed class Grib1WaveSpectra2DDirFreq { - public sealed class Grib1WaveSpectra2DDirFreq - { - private string version; + private string version; + + public string Version + { + get { return version; } + } + + // one-offset + private int directionNumber; - public string Version - { - get { return version; } - } + public int DirectionNumber + { + get { return directionNumber; } + } - // one-offset - private int directionNumber; + // one-offset + private int frequencyNumber; + + public int FrequencyNumber + { + get { return frequencyNumber; } + } + + private int numberOfDirections; + + public int NumberOfDirections + { + get { return numberOfDirections; } + } + + private int numberOfFrequencies; + + public int NumberOfFrequencies + { + get { return numberOfFrequencies; } + } + + private int dirScaleFactor; + + public int DirScaleFactor + { + get { return dirScaleFactor; } + } + + private int freqScaleFactor; + + public int FreqScaleFactor + { + get { return freqScaleFactor; } + } + + private double[] directions; + + public double[] Directions + { + get { return directions; } + } + + private double[] frequencies; + + public double[] Frequencies + { + get { return frequencies; } + } + + /// + /// The direction [deg]. + /// + public double Direction + { + get { return directions[directionNumber - 1]; } + } + + /// + /// The frequency [Hz]; + /// + public double Frequency + { + get { return frequencies[frequencyNumber - 1]; } + } + + + internal Grib1WaveSpectra2DDirFreq(System.IO.Stream raf) + { + SupportClass.Skip(raf, 4); + + byte[] ver = GribNumbers.ReadBytes(raf, 4); + System.Text.Encoding enc = System.Text.Encoding.ASCII; + version = enc.GetString(ver); + + SupportClass.Skip(raf, 2); + + directionNumber = raf.ReadByte(); + frequencyNumber = raf.ReadByte(); + numberOfDirections = raf.ReadByte(); + numberOfFrequencies = raf.ReadByte(); + dirScaleFactor = GribNumbers.int4(raf); + freqScaleFactor = GribNumbers.int4(raf); + + SupportClass.Skip(raf, 37); + + directions = new double[numberOfDirections]; + frequencies = new double[numberOfFrequencies]; + + for (int i = 0; i < numberOfDirections; i++) + { + int val = GribNumbers.int4(raf); + directions[i] = (double) val / (double) dirScaleFactor; + } - public int DirectionNumber - { - get { return directionNumber; } - } - - // one-offset - private int frequencyNumber; - - public int FrequencyNumber - { - get { return frequencyNumber; } - } - - private int numberOfDirections; - - public int NumberOfDirections - { - get { return numberOfDirections; } - } - - private int numberOfFrequencies; - - public int NumberOfFrequencies - { - get { return numberOfFrequencies; } - } - - private int dirScaleFactor; - - public int DirScaleFactor - { - get { return dirScaleFactor; } - } - - private int freqScaleFactor; - - public int FreqScaleFactor - { - get { return freqScaleFactor; } - } - - private double[] directions; - - public double[] Directions - { - get { return directions; } - } - - private double[] frequencies; - - public double[] Frequencies - { - get { return frequencies; } - } - - /// - /// The direction [deg]. - /// - public double Direction - { - get { return directions[directionNumber - 1]; } - } - - /// - /// The frequency [Hz]; - /// - public double Frequency - { - get { return frequencies[frequencyNumber - 1]; } - } - - - internal Grib1WaveSpectra2DDirFreq(System.IO.Stream raf) - { - SupportClass.Skip(raf, 4); - - byte[] ver = GribNumbers.ReadBytes(raf, 4); - System.Text.Encoding enc = System.Text.Encoding.ASCII; - version = enc.GetString(ver); - - SupportClass.Skip(raf, 2); - - directionNumber = raf.ReadByte(); - frequencyNumber = raf.ReadByte(); - numberOfDirections = raf.ReadByte(); - numberOfFrequencies = raf.ReadByte(); - dirScaleFactor = GribNumbers.int4(raf); - freqScaleFactor = GribNumbers.int4(raf); - - SupportClass.Skip(raf, 37); - - directions = new double[numberOfDirections]; - frequencies = new double[numberOfFrequencies]; - - for (int i = 0; i < numberOfDirections; i++) - { - int val = GribNumbers.int4(raf); - directions[i] = (double) val / (double) dirScaleFactor; - } - - for (int i = 0; i < numberOfFrequencies; i++) - { - int val = GribNumbers.int4(raf); - frequencies[i] = (double) val / (double) freqScaleFactor; - } - } - } + for (int i = 0; i < numberOfFrequencies; i++) + { + int val = GribNumbers.int4(raf); + frequencies[i] = (double) val / (double) freqScaleFactor; + } + } } \ No newline at end of file diff --git a/src/NGrib/Grib1/GribNumbers.cs b/src/NGrib/Grib1/GribNumbers.cs index 0261baf..e163d83 100644 --- a/src/NGrib/Grib1/GribNumbers.cs +++ b/src/NGrib/Grib1/GribNumbers.cs @@ -1,7 +1,7 @@ /* * This file is part of NGrib. * - * Copyright 2020 Nicolas Mangu + * Copyright © 2020 Nicolas Manguй * * Copyright 2006-2010 Seaware AB, PO Box 1244, SE-131 28 * Nacka Strand, Sweden, info@seaware.se. @@ -24,218 +24,215 @@ * along with NGrib. If not, see . */ -using System; - -namespace NGrib.Grib1 +namespace NGrib.Grib1; + +/// A class that contains several static methods for converting multiple +/// bytes into one float or integer. +/// +/// +/// Robb Kambic 10/20/04 +/// +/// 2.0 +/// +internal sealed class GribNumbers { - /// A class that contains several static methods for converting multiple - /// bytes into one float or integer. - /// - /// - /// Robb Kambic 10/20/04 - /// - /// 2.0 - /// - internal sealed class GribNumbers - { - /// if missing value is not defined use this value. - public const int UNDEFINED = -9999; - - /// Convert 2 bytes into a signed integer. - /// - /// - /// * - /// - /// integer value - /// - /// IOException - //UPGRADE_TODO: Class 'java.io.RandomAccessFile' was converted to 'System.IO.Stream' which has a different behavior. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1073_javaioRandomAccessFile'" - public static int int2(System.IO.Stream raf) - { - //byte[] bytes = ReadBytes(raf, 2); - //return (int)BitConverter.ToInt16(bytes, 0); - - int a = raf.ReadByte(); - int b = raf.ReadByte(); - return int2(a, b); - } - - public static int int2(int a, int b) - { - return (1 - ((a & 128) >> 6)) * ((a & 127) << 8 | b); - } - - /// Convert 3 bytes into a signed integer. - /// - /// - /// * - /// - /// integer value - /// - /// IOException - public static int int3(System.IO.Stream raf) - { + /// if missing value is not defined use this value. + public const int UNDEFINED = -9999; + + /// Convert 2 bytes into a signed integer. + /// + /// + /// * + /// + /// integer value + /// + /// IOException + //UPGRADE_TODO: Class 'java.io.RandomAccessFile' was converted to 'System.IO.Stream' which has a different behavior. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1073_javaioRandomAccessFile'" + public static int int2(System.IO.Stream raf) + { + //byte[] bytes = ReadBytes(raf, 2); + //return (int)BitConverter.ToInt16(bytes, 0); + + int a = raf.ReadByte(); + int b = raf.ReadByte(); + return int2(a, b); + } + + public static int int2(int a, int b) + { + return (1 - ((a & 128) >> 6)) * ((a & 127) << 8 | b); + } + + /// Convert 3 bytes into a signed integer. + /// + /// + /// * + /// + /// integer value + /// + /// IOException + public static int int3(System.IO.Stream raf) + { // byte[] bytes = ReadBytes(raf, 3); // byte[] fourBytes = new byte[4]; // bytes.CopyTo(fourBytes, 0); // fourBytes[3] = 0; // return BitConverter.ToInt32(fourBytes, 0); - int a = raf.ReadByte(); - int b = raf.ReadByte(); - int c = raf.ReadByte(); - return (1 - ((a & 128) >> 6)) * ((a & 127) << 16 | b << 8 | c); - } - - - /// Convert 4 bytes into a signed integer. - /// - /// - /// * - /// - /// integer value - /// - /// IOException - public static int int4(System.IO.Stream raf) - { - //byte[] bytes = ReadBytes(raf, 4); - //int i1 = BitConverter.ToInt32(bytes, 0); - - int a = raf.ReadByte(); - int b = raf.ReadByte(); - int c = raf.ReadByte(); - int d = raf.ReadByte(); - - // all bits set to ones - if (a == 0xff && b == 0xff && c == 0xff && d == 0xff) - return UNDEFINED; - - int i2 = (1 - ((a & 128) >> 6)) * ((a & 127) << 24 | b << 16 | c << 8 | d); - return i2; - } - - - /// Convert 2 bytes into an unsigned integer. - /// - /// - /// * - /// - /// integer value - /// - /// IOException - public static int uint2(System.IO.Stream raf) - { - //byte[] bytes = ReadBytes(raf, 2); - //return (uint)BitConverter.ToUInt16(bytes, 0); - - int a = raf.ReadByte(); - int b = raf.ReadByte(); - return a << 8 | b; - } - - /// Convert 3 bytes into an unsigned integer. - /// - /// - /// * - /// - /// integer - /// - /// IOException - public static int uint3(System.IO.Stream raf) - { + int a = raf.ReadByte(); + int b = raf.ReadByte(); + int c = raf.ReadByte(); + return (1 - ((a & 128) >> 6)) * ((a & 127) << 16 | b << 8 | c); + } + + + /// Convert 4 bytes into a signed integer. + /// + /// + /// * + /// + /// integer value + /// + /// IOException + public static int int4(System.IO.Stream raf) + { + //byte[] bytes = ReadBytes(raf, 4); + //int i1 = BitConverter.ToInt32(bytes, 0); + + int a = raf.ReadByte(); + int b = raf.ReadByte(); + int c = raf.ReadByte(); + int d = raf.ReadByte(); + + // all bits set to ones + if (a == 0xff && b == 0xff && c == 0xff && d == 0xff) + return UNDEFINED; + + int i2 = (1 - ((a & 128) >> 6)) * ((a & 127) << 24 | b << 16 | c << 8 | d); + return i2; + } + + + /// Convert 2 bytes into an unsigned integer. + /// + /// + /// * + /// + /// integer value + /// + /// IOException + public static int uint2(System.IO.Stream raf) + { + //byte[] bytes = ReadBytes(raf, 2); + //return (uint)BitConverter.ToUInt16(bytes, 0); + + int a = raf.ReadByte(); + int b = raf.ReadByte(); + return a << 8 | b; + } + + /// Convert 3 bytes into an unsigned integer. + /// + /// + /// * + /// + /// integer + /// + /// IOException + public static int uint3(System.IO.Stream raf) + { // byte[] bytes = ReadBytes(raf, 3); // byte[] fourBytes = new byte[4]; // bytes.CopyTo(fourBytes, 0); // fourBytes[3] = 0; // return BitConverter.ToUInt32(fourBytes, 0); - int a = raf.ReadByte(); - int b = raf.ReadByte(); - int c = raf.ReadByte(); - return a << 16 | b << 8 | c; - } - - - /// Convert 4 bytes into a float. - /// - /// - /// FileStream to read from - /// - /// float - /// - /// IOException - public static float float4(System.IO.Stream raf) - { - int a = raf.ReadByte(); - int b = raf.ReadByte(); - int c = raf.ReadByte(); - int d = raf.ReadByte(); - - int sgn, mant, exp; - - mant = b << 16 | c << 8 | d; - if (mant == 0) return 0.0f; - - sgn = -(((a & 128) >> 6) - 1); - exp = (a & 127) - 64; - - return (float) (sgn * Math.Pow(16.0, exp - 6) * mant); - } - - public static float IEEEfloat4(System.IO.Stream raf) - { - byte[] bytes = ReadBytes(raf, 4); - return BitConverter.ToSingle(bytes, 0); - } - - - /// Convert 8 bytes into a signed long. - /// - /// - /// RandomAccessFile - /// - /// - /// long value - /// - /// IOException - //UPGRADE_TODO: Class 'java.io.RandomAccessFile' was converted to 'System.IO.Stream' which has a different behavior. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1073_javaioRandomAccessFile'" - public static long int8(System.IO.Stream raf) - { - int a = raf.ReadByte(); - int b = raf.ReadByte(); - int c = raf.ReadByte(); - int d = raf.ReadByte(); - int e = raf.ReadByte(); - int f = raf.ReadByte(); - int g = raf.ReadByte(); - int h = raf.ReadByte(); - - return (1 - ((a & 128) >> 6)) * ((a & 127) << 56 | b << 48 | c << 40 | d << 32 | e << 24 | f << 16 | g << 8 | h); - } // end int8 - - - public static byte[] ReadBytes(System.IO.Stream raf, int count) - { - byte[] bytes = new byte[count]; - raf.Read(bytes, 0, count); - if (BitConverter.IsLittleEndian) - { - bytes = Swap(bytes); - } - - return bytes; - } - - public static byte[] Swap(byte[] bytes) - { - int nb = bytes.Length; - byte[] swappedBytes = new byte[nb]; - for (int i = 0; i < nb; i++) - { - swappedBytes[i] = bytes[nb - 1 - i]; - } - - return swappedBytes; - } - } // end GribNumbers -} \ No newline at end of file + int a = raf.ReadByte(); + int b = raf.ReadByte(); + int c = raf.ReadByte(); + return a << 16 | b << 8 | c; + } + + + /// Convert 4 bytes into a float. + /// + /// + /// FileStream to read from + /// + /// float + /// + /// IOException + public static double double4(System.IO.Stream raf) + { + int a = raf.ReadByte(); + int b = raf.ReadByte(); + int c = raf.ReadByte(); + int d = raf.ReadByte(); + + int sgn, mant, exp; + + mant = b << 16 | c << 8 | d; + if (mant == 0) return 0.0f; + + sgn = -(((a & 128) >> 6) - 1); + exp = (a & 127) - 64; + + return (double) (sgn * Math.Pow(16.0, exp - 6) * mant); + } + + public static float IEEEfloat4(System.IO.Stream raf) + { + byte[] bytes = ReadBytes(raf, 4); + return BitConverter.ToSingle(bytes, 0); + } + + + /// Convert 8 bytes into a signed long. + /// + /// + /// RandomAccessFile + /// + /// + /// long value + /// + /// IOException + //UPGRADE_TODO: Class 'java.io.RandomAccessFile' was converted to 'System.IO.Stream' which has a different behavior. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1073_javaioRandomAccessFile'" + public static long int8(System.IO.Stream raf) + { + int a = raf.ReadByte(); + int b = raf.ReadByte(); + int c = raf.ReadByte(); + int d = raf.ReadByte(); + int e = raf.ReadByte(); + int f = raf.ReadByte(); + int g = raf.ReadByte(); + int h = raf.ReadByte(); + + return (1 - ((a & 128) >> 6)) * ((a & 127) << 56 | b << 48 | c << 40 | d << 32 | e << 24 | f << 16 | g << 8 | h); + } // end int8 + + + public static byte[] ReadBytes(System.IO.Stream raf, int count) + { + byte[] bytes = new byte[count]; + raf.Read(bytes, 0, count); + if (BitConverter.IsLittleEndian) + { + bytes = Swap(bytes); + } + + return bytes; + } + + public static byte[] Swap(byte[] bytes) + { + int nb = bytes.Length; + byte[] swappedBytes = new byte[nb]; + for (int i = 0; i < nb; i++) + { + swappedBytes[i] = bytes[nb - 1 - i]; + } + + return swappedBytes; + } +} // end GribNumbers \ No newline at end of file diff --git a/src/NGrib/Grib1/GribPDSLevel.cs b/src/NGrib/Grib1/GribPDSLevel.cs index adc3d67..d1dd4be 100644 --- a/src/NGrib/Grib1/GribPDSLevel.cs +++ b/src/NGrib/Grib1/GribPDSLevel.cs @@ -31,737 +31,736 @@ /// Capt Richard D. Gonzalez /// -namespace NGrib.Grib1 +namespace NGrib.Grib1; + +/// A class containing static methods which deliver names of +/// levels and units for byte codes from GRIB records. +/// +public sealed class GribPDSLevel { - /// A class containing static methods which deliver names of - /// levels and units for byte codes from GRIB records. - /// - public sealed class GribPDSLevel - { - /// Index number from table 3 - can be used for comparison even if the - /// description of the level changes. - /// - /// index - /// - public int Index - { - get { return index; } - } - - /// Name of this level. - /// name as String - /// - public System.String Name - { - get { return name; } - } - - /// gets the 1st value for the level. - /// level value 1 - /// - public float Value1 - { - get { return value1; } - } - - /// gets the 2nd value for the level. - /// level value 2 - /// - public float Value2 - { - get { return value2; } - } - - /// Index number from table 3 - can be used for comparison even if the - /// description of the level changes. - /// - //UPGRADE_NOTE: Final was removed from the declaration of 'index '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'" - private int index; - - /// Name of the vertical coordinate/level. - /// - /// - private System.String name; - - /// Value of PDS octet10 if separate from 11, otherwise value from octet10&11. - private float value1; - - /// Value of PDS octet11. - private float value2; - - /// Constructor. Creates a GribPDSLevel based on octets 10-12 of the PDS. - /// Implements tables 3 and 3a. - /// - /// - /// part 1 of level code index - /// - /// part 2 of level code - /// - /// part 3 of level code - /// - /// - internal GribPDSLevel(int pds10, int pds11, int pds12) - { - int pds1112 = pds11 << 8 | pds12; - index = pds10; - switch (index) - { - case 0: - name = "reserved"; - break; - - case 1: - name = "surface"; - break; - - case 2: - name = "cloud base level"; - break; - - case 3: - name = "cloud top level"; - break; - - case 4: - name = "0 degree isotherm level"; - break; - - case 5: - name = "condensation level"; - break; - - case 6: - name = "maximum wind level"; - break; - - case 7: - name = "tropopause level"; - break; - - case 8: - name = "nominal atmosphere top"; - break; - - case 9: - name = "sea bottom"; - break; - - case 20: - name = "Isothermal level"; - value1 = pds1112; - break; - - case 100: - name = "isobaric"; - value1 = pds1112; - break; - - case 101: - name = "layer between two isobaric levels"; - value1 = pds11 * 10; // convert from kPa to hPa - who uses kPa??? - value2 = pds12 * 10; - break; - - case 102: - name = "mean sea level"; - break; - - case 103: - name = "Altitude above MSL"; - value1 = pds1112; - break; - - case 104: - name = "Layer between two altitudes above MSL"; - value1 = (pds11 * 100); // convert hm to m - value2 = (pds12 * 100); - break; - - case 105: - name = "fixed height above ground"; - value1 = pds1112; - break; - - case 106: - name = "layer between two height levels"; - value1 = (pds11 * 100); // convert hm to m - value2 = (pds12 * 100); - break; - - case 107: - name = "Sigma level"; - value1 = pds1112; - break; - - case 108: - name = "Layer between two sigma layers"; - value1 = pds11; - value2 = pds12; - break; - - case 109: - name = "hybrid level"; - value1 = pds1112; - break; - - case 110: - name = "Layer between two hybrid levels"; - value1 = pds11; - value2 = pds12; - break; - - case 111: - name = "Depth below land surface"; - value1 = pds1112; - break; - - case 112: - name = "Layer between two levels below land surface"; - value1 = pds11; - value2 = pds12; - break; - - case 113: - name = "Isentropic theta level"; - value1 = pds1112; - break; - - case 114: - name = "Layer between two isentropic layers"; - value1 = pds11; - value2 = pds12; - break; - - case 115: - name = "level at specified pressure difference from ground to level"; - value1 = pds1112; - break; - - case 116: - name = "Layer between pressure differences from ground to levels"; - value1 = pds11; - value2 = pds12; - break; - - case 117: - name = "potential vorticity(pv) surface"; - value1 = pds1112; - break; - - case 119: - name = "Eta level"; - value1 = pds1112; - break; - - case 120: - name = "layer between two Eta levels"; - value1 = pds11; - value2 = pds12; - break; - - case 121: - name = "layer between two isobaric surfaces"; - value1 = pds11; - value2 = pds12; - break; - - case 125: - name = "Height above ground (high precision)"; - value1 = pds1112; - break; - - case 126: - name = "isobaric level"; - value1 = pds1112; - break; - - case 128: - name = "layer between two sigma levels"; - value1 = pds11; - value2 = pds12; - break; - - case 141: - name = "layer between two isobaric surfaces"; - value1 = pds11 * 10; // convert from kPa to hPa - who uses kPa??? - value2 = pds12; - break; - - case 160: - name = "Depth below sea level"; - value1 = pds1112; - break; - - case 200: - name = "entire atmosphere layer"; - break; - - case 201: - name = "entire ocean layer"; - break; - - case 204: - name = "Highest tropospheric freezing level"; - break; - - case 206: - name = "Grid scale cloud bottom level"; - break; - - case 207: - name = "Grid scale cloud top level"; - break; - - case 209: - name = "Boundary layer cloud bottom level"; - break; - - case 210: - name = "Boundary layer cloud top level"; - break; - - case 211: - name = "Boundary layer cloud layer"; - break; - - case 212: - name = "Low cloud bottom level"; - break; - - case 213: - name = "Low cloud top level"; - break; - - case 214: - name = "Low Cloud Layer"; - break; - - case 222: - name = "Middle cloud bottom level"; - break; - - case 223: - name = "Middle cloud top level"; - break; - - case 224: - name = "Middle Cloud Layer"; - break; - - case 232: - name = "High cloud bottom level"; - break; - - case 233: - name = "High cloud top level"; - break; - - case 234: - name = "High Cloud Layer"; - break; + /// Index number from table 3 - can be used for comparison even if the + /// description of the level changes. + /// + /// index + /// + public int Index + { + get { return index; } + } + + /// Name of this level. + /// name as String + /// + public System.String Name + { + get { return name; } + } + + /// gets the 1st value for the level. + /// level value 1 + /// + public float Value1 + { + get { return value1; } + } + + /// gets the 2nd value for the level. + /// level value 2 + /// + public float Value2 + { + get { return value2; } + } + + /// Index number from table 3 - can be used for comparison even if the + /// description of the level changes. + /// + //UPGRADE_NOTE: Final was removed from the declaration of 'index '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'" + private int index; + + /// Name of the vertical coordinate/level. + /// + /// + private System.String name; + + /// Value of PDS octet10 if separate from 11, otherwise value from octet10&11. + private float value1; + + /// Value of PDS octet11. + private float value2; + + /// Constructor. Creates a GribPDSLevel based on octets 10-12 of the PDS. + /// Implements tables 3 and 3a. + /// + /// + /// part 1 of level code index + /// + /// part 2 of level code + /// + /// part 3 of level code + /// + /// + internal GribPDSLevel(int pds10, int pds11, int pds12) + { + int pds1112 = pds11 << 8 | pds12; + index = pds10; + switch (index) + { + case 0: + name = "reserved"; + break; + + case 1: + name = "surface"; + break; + + case 2: + name = "cloud base level"; + break; + + case 3: + name = "cloud top level"; + break; + + case 4: + name = "0 degree isotherm level"; + break; + + case 5: + name = "condensation level"; + break; + + case 6: + name = "maximum wind level"; + break; + + case 7: + name = "tropopause level"; + break; + + case 8: + name = "nominal atmosphere top"; + break; + + case 9: + name = "sea bottom"; + break; + + case 20: + name = "Isothermal level"; + value1 = pds1112; + break; + + case 100: + name = "isobaric"; + value1 = pds1112; + break; + + case 101: + name = "layer between two isobaric levels"; + value1 = pds11 * 10; // convert from kPa to hPa - who uses kPa??? + value2 = pds12 * 10; + break; + + case 102: + name = "mean sea level"; + break; + + case 103: + name = "Altitude above MSL"; + value1 = pds1112; + break; + + case 104: + name = "Layer between two altitudes above MSL"; + value1 = (pds11 * 100); // convert hm to m + value2 = (pds12 * 100); + break; + + case 105: + name = "fixed height above ground"; + value1 = pds1112; + break; + + case 106: + name = "layer between two height levels"; + value1 = (pds11 * 100); // convert hm to m + value2 = (pds12 * 100); + break; + + case 107: + name = "Sigma level"; + value1 = pds1112; + break; + + case 108: + name = "Layer between two sigma layers"; + value1 = pds11; + value2 = pds12; + break; + + case 109: + name = "hybrid level"; + value1 = pds1112; + break; + + case 110: + name = "Layer between two hybrid levels"; + value1 = pds11; + value2 = pds12; + break; + + case 111: + name = "Depth below land surface"; + value1 = pds1112; + break; + + case 112: + name = "Layer between two levels below land surface"; + value1 = pds11; + value2 = pds12; + break; + + case 113: + name = "Isentropic theta level"; + value1 = pds1112; + break; + + case 114: + name = "Layer between two isentropic layers"; + value1 = pds11; + value2 = pds12; + break; + + case 115: + name = "level at specified pressure difference from ground to level"; + value1 = pds1112; + break; + + case 116: + name = "Layer between pressure differences from ground to levels"; + value1 = pds11; + value2 = pds12; + break; + + case 117: + name = "potential vorticity(pv) surface"; + value1 = pds1112; + break; + + case 119: + name = "Eta level"; + value1 = pds1112; + break; + + case 120: + name = "layer between two Eta levels"; + value1 = pds11; + value2 = pds12; + break; + + case 121: + name = "layer between two isobaric surfaces"; + value1 = pds11; + value2 = pds12; + break; + + case 125: + name = "Height above ground (high precision)"; + value1 = pds1112; + break; + + case 126: + name = "isobaric level"; + value1 = pds1112; + break; + + case 128: + name = "layer between two sigma levels"; + value1 = pds11; + value2 = pds12; + break; + + case 141: + name = "layer between two isobaric surfaces"; + value1 = pds11 * 10; // convert from kPa to hPa - who uses kPa??? + value2 = pds12; + break; + + case 160: + name = "Depth below sea level"; + value1 = pds1112; + break; + + case 200: + name = "entire atmosphere layer"; + break; + + case 201: + name = "entire ocean layer"; + break; + + case 204: + name = "Highest tropospheric freezing level"; + break; + + case 206: + name = "Grid scale cloud bottom level"; + break; + + case 207: + name = "Grid scale cloud top level"; + break; + + case 209: + name = "Boundary layer cloud bottom level"; + break; + + case 210: + name = "Boundary layer cloud top level"; + break; + + case 211: + name = "Boundary layer cloud layer"; + break; + + case 212: + name = "Low cloud bottom level"; + break; + + case 213: + name = "Low cloud top level"; + break; + + case 214: + name = "Low Cloud Layer"; + break; + + case 222: + name = "Middle cloud bottom level"; + break; + + case 223: + name = "Middle cloud top level"; + break; + + case 224: + name = "Middle Cloud Layer"; + break; + + case 232: + name = "High cloud bottom level"; + break; + + case 233: + name = "High cloud top level"; + break; + + case 234: + name = "High Cloud Layer"; + break; - case 235: - name = "Ocean Isotherm Level"; - break; + case 235: + name = "Ocean Isotherm Level"; + break; - case 236: - name = "Layer between two depths below ocean surface"; - value1 = pds11; - value2 = pds12; - break; + case 236: + name = "Layer between two depths below ocean surface"; + value1 = pds11; + value2 = pds12; + break; - case 237: - name = "Bottom of Ocean Mixed Layer"; - break; + case 237: + name = "Bottom of Ocean Mixed Layer"; + break; - case 238: - name = "Bottom of Ocean Isothermal Layer"; - break; + case 238: + name = "Bottom of Ocean Isothermal Layer"; + break; - case 242: - name = "Convective cloud bottom level"; - break; + case 242: + name = "Convective cloud bottom level"; + break; - case 243: - name = "Convective cloud top level"; - break; + case 243: + name = "Convective cloud top level"; + break; - case 244: - name = "Convective cloud layer"; - break; + case 244: + name = "Convective cloud layer"; + break; - case 245: - name = "Lowest level of the wet bulb zero"; - break; + case 245: + name = "Lowest level of the wet bulb zero"; + break; - case 246: - name = "Maximum equivalent potential temperature level"; - break; + case 246: + name = "Maximum equivalent potential temperature level"; + break; - case 247: - name = "Equilibrium level"; - break; + case 247: + name = "Equilibrium level"; + break; - case 248: - name = "Shallow convective cloud bottom level"; - break; + case 248: + name = "Shallow convective cloud bottom level"; + break; - case 249: - name = "Shallow convective cloud top level"; - break; + case 249: + name = "Shallow convective cloud top level"; + break; - case 251: - name = "Deep convective cloud bottom level"; - break; + case 251: + name = "Deep convective cloud bottom level"; + break; - case 252: - name = "Deep convective cloud top level"; - break; + case 252: + name = "Deep convective cloud top level"; + break; - default: - name = "undefined level"; - System.Console.Out.WriteLine("GribPDSLevel: Table 3 level " + index + " is not implemented yet"); - break; - } - } // end GribPDSLevel + default: + name = "undefined level"; + System.Console.Out.WriteLine("GribPDSLevel: Table 3 level " + index + " is not implemented yet"); + break; + } + } // end GribPDSLevel - /// type of vertical coordinate: Description or short Name - /// derived from ON388 - TABLE 3. - /// - /// - /// - /// level description as String - /// - static public System.String getLevelDescription(int id) - { - switch (id) - { - case 0: return "Reserved"; + /// type of vertical coordinate: Description or short Name + /// derived from ON388 - TABLE 3. + /// + /// + /// + /// level description as String + /// + static public System.String getLevelDescription(int id) + { + switch (id) + { + case 0: return "Reserved"; - case 1: return "Ground or water surface"; + case 1: return "Ground or water surface"; - case 2: return "Cloud base level"; + case 2: return "Cloud base level"; - case 3: return "Level of cloud tops"; + case 3: return "Level of cloud tops"; - case 4: return "Level of 0o C isotherm"; + case 4: return "Level of 0o C isotherm"; - case 5: return "Level of adiabatic condensation lifted from the surface"; + case 5: return "Level of adiabatic condensation lifted from the surface"; - case 6: return "Maximum wind level"; + case 6: return "Maximum wind level"; - case 7: return "Tropopause"; + case 7: return "Tropopause"; - case 8: return "Nominal top of the atmosphere"; + case 8: return "Nominal top of the atmosphere"; - case 9: return "Sea bottom"; + case 9: return "Sea bottom"; - case 20: return "Isothermal level"; + case 20: return "Isothermal level"; - case 100: return "Isobaric surface"; + case 100: return "Isobaric surface"; - case 101: return "Layer between 2 isobaric levels"; + case 101: return "Layer between 2 isobaric levels"; - case 102: return "Mean sea level"; + case 102: return "Mean sea level"; - case 103: return "Altitude above mean sea level"; + case 103: return "Altitude above mean sea level"; - case 104: return "Layer between 2 altitudes above msl"; + case 104: return "Layer between 2 altitudes above msl"; - case 105: return "Specified height level above ground"; + case 105: return "Specified height level above ground"; - case 106: return "Layer between 2 specified height level above ground"; + case 106: return "Layer between 2 specified height level above ground"; - case 107: return "Sigma level"; + case 107: return "Sigma level"; - case 108: return "Layer between 2 sigma levels"; + case 108: return "Layer between 2 sigma levels"; - case 109: return "Hybrid level"; + case 109: return "Hybrid level"; - case 110: return "Layer between 2 hybrid levels"; + case 110: return "Layer between 2 hybrid levels"; - case 111: return "Depth below land surface"; + case 111: return "Depth below land surface"; - case 112: return "Layer between 2 depths below land surface"; + case 112: return "Layer between 2 depths below land surface"; - case 113: return "Isentropic theta level"; + case 113: return "Isentropic theta level"; - case 114: return "Layer between 2 isentropic levels"; + case 114: return "Layer between 2 isentropic levels"; - case 115: return "Level at specified pressure difference from ground to level"; + case 115: return "Level at specified pressure difference from ground to level"; - case 116: return "Layer between 2 level at pressure difference from ground to level"; + case 116: return "Layer between 2 level at pressure difference from ground to level"; - case 117: return "Potential vorticity surface"; + case 117: return "Potential vorticity surface"; - case 119: return "Eta level"; + case 119: return "Eta level"; - case 120: return "Layer between 2 Eta levels"; + case 120: return "Layer between 2 Eta levels"; - case 121: return "Layer between 2 isobaric levels"; + case 121: return "Layer between 2 isobaric levels"; - case 125: return "Specified height level above ground"; + case 125: return "Specified height level above ground"; - case 126: return "Isobaric level"; + case 126: return "Isobaric level"; - case 128: return "Layer between 2 sigma levels (hi precision)"; + case 128: return "Layer between 2 sigma levels (hi precision)"; - case 141: return "Layer between 2 isobaric surfaces"; + case 141: return "Layer between 2 isobaric surfaces"; - case 160: return "Depth below sea level"; + case 160: return "Depth below sea level"; - case 200: return "Entire atmosphere"; + case 200: return "Entire atmosphere"; - case 201: return "Entire ocean"; + case 201: return "Entire ocean"; - case 204: return "Highest tropospheric freezing level"; + case 204: return "Highest tropospheric freezing level"; - case 206: return "Grid scale cloud bottom level"; + case 206: return "Grid scale cloud bottom level"; - case 207: return "Grid scale cloud top level"; + case 207: return "Grid scale cloud top level"; - case 209: return "Boundary layer cloud bottom level"; + case 209: return "Boundary layer cloud bottom level"; - case 210: return "Boundary layer cloud top level"; + case 210: return "Boundary layer cloud top level"; - case 211: return "Boundary layer cloud layer"; + case 211: return "Boundary layer cloud layer"; - case 212: return "Low cloud bottom level"; + case 212: return "Low cloud bottom level"; - case 213: return "Low cloud top level"; + case 213: return "Low cloud top level"; - case 214: return "Low Cloud Layer"; + case 214: return "Low Cloud Layer"; - case 222: return "Middle cloud bottom level"; + case 222: return "Middle cloud bottom level"; - case 223: return "Middle cloud top level"; + case 223: return "Middle cloud top level"; - case 224: return "Middle Cloud Layer"; + case 224: return "Middle Cloud Layer"; - case 232: return "High cloud bottom level"; + case 232: return "High cloud bottom level"; - case 233: return "High cloud top level"; + case 233: return "High cloud top level"; - case 234: return "High Cloud Layer"; + case 234: return "High Cloud Layer"; - case 242: return "Convective cloud bottom level"; + case 242: return "Convective cloud bottom level"; - case 243: return "Convective cloud top level"; + case 243: return "Convective cloud top level"; - case 244: return "Convective cloud layer"; + case 244: return "Convective cloud layer"; - case 245: return "Lowest level of the wet bulb zero"; + case 245: return "Lowest level of the wet bulb zero"; - case 246: return "Maximum equivalent potential temperature level"; + case 246: return "Maximum equivalent potential temperature level"; - case 247: return "Equilibrium level"; + case 247: return "Equilibrium level"; - case 248: return "Shallow convective cloud bottom level"; + case 248: return "Shallow convective cloud bottom level"; - case 249: return "Shallow convective cloud top level"; + case 249: return "Shallow convective cloud top level"; - case 251: return "Deep convective cloud bottom level"; + case 251: return "Deep convective cloud bottom level"; - case 252: return "Deep convective cloud top level"; + case 252: return "Deep convective cloud top level"; - case 255: return "Missing"; + case 255: return "Missing"; - default: return "Unknown=" + id; - } - } + default: return "Unknown=" + id; + } + } - /// short name of level. - /// - /// - /// name of level - /// - static public System.String getNameShort(int id) - { - switch (id) - { - case 1: return "surface"; + /// short name of level. + /// + /// + /// name of level + /// + static public System.String getNameShort(int id) + { + switch (id) + { + case 1: return "surface"; - case 2: return "cloud_base"; + case 2: return "cloud_base"; - case 3: return "cloud_tops"; + case 3: return "cloud_tops"; - case 4: return "zeroDegC_isotherm"; + case 4: return "zeroDegC_isotherm"; - case 5: return "adiabatic_condensation_lifted"; + case 5: return "adiabatic_condensation_lifted"; - case 6: return "maximum_wind"; + case 6: return "maximum_wind"; - case 7: return "tropopause"; + case 7: return "tropopause"; - case 8: return "atmosphere_top"; + case 8: return "atmosphere_top"; - case 9: return "sea_bottom"; + case 9: return "sea_bottom"; - case 20: return "isotherm"; + case 20: return "isotherm"; - case 100: return "isobaric"; + case 100: return "isobaric"; - case 101: return "layer_between_two_isobaric"; + case 101: return "layer_between_two_isobaric"; - case 102: return "msl"; + case 102: return "msl"; - case 103: return "altitude_above_msl"; + case 103: return "altitude_above_msl"; - case 104: return "layer_between_two_altitudes_above_msl"; + case 104: return "layer_between_two_altitudes_above_msl"; - case 105: return "height_above_ground"; + case 105: return "height_above_ground"; - case 106: return "layer_between_two_heights_above_ground"; + case 106: return "layer_between_two_heights_above_ground"; - case 107: return "sigma"; + case 107: return "sigma"; - case 108: return "layer_between_two_sigmas"; + case 108: return "layer_between_two_sigmas"; - case 109: return "hybrid"; + case 109: return "hybrid"; - case 110: return "layer_between_two_hybrids"; + case 110: return "layer_between_two_hybrids"; - case 111: return "depth_below_surface"; + case 111: return "depth_below_surface"; - case 112: return "layer_between_two_depths_below_surface"; + case 112: return "layer_between_two_depths_below_surface"; - case 113: return "isentrope"; + case 113: return "isentrope"; - case 114: return "layer_between_two_isentrope"; + case 114: return "layer_between_two_isentrope"; - case 115: return "pressure_difference"; + case 115: return "pressure_difference"; - case 116: return "layer_between_two_pressure_difference_from_ground"; + case 116: return "layer_between_two_pressure_difference_from_ground"; - case 117: return "potential_vorticity_surface"; + case 117: return "potential_vorticity_surface"; - case 119: return "eta"; + case 119: return "eta"; - case 120: return "layer_between_two_eta"; + case 120: return "layer_between_two_eta"; - case 121: return "layer_between_two_isobaric_surfaces"; + case 121: return "layer_between_two_isobaric_surfaces"; - case 125: return "height_above_ground"; + case 125: return "height_above_ground"; - case 126: return "isobaric"; + case 126: return "isobaric"; - case 128: return "layer_between_two_sigmas_hi"; + case 128: return "layer_between_two_sigmas_hi"; - case 141: return "layer_between_two_isobaric_surfaces"; + case 141: return "layer_between_two_isobaric_surfaces"; - case 160: return "depth_below_sea"; + case 160: return "depth_below_sea"; - case 200: return "entire_atmosphere"; + case 200: return "entire_atmosphere"; - case 201: return "entire_ocean"; + case 201: return "entire_ocean"; - case 204: return "highest_tropospheric_freezing"; + case 204: return "highest_tropospheric_freezing"; - case 206: return "grid_scale_cloud bottom"; + case 206: return "grid_scale_cloud bottom"; - case 207: return "grid_scale_cloud_top"; + case 207: return "grid_scale_cloud_top"; - case 209: return "boundary_layer_cloud_bottom"; + case 209: return "boundary_layer_cloud_bottom"; - case 210: return "boundary_layer_cloud_top"; + case 210: return "boundary_layer_cloud_top"; - case 211: return "boundary_layer_cloud_layer"; + case 211: return "boundary_layer_cloud_layer"; - case 212: return "low_cloud_bottom"; + case 212: return "low_cloud_bottom"; - case 213: return "low_cloud_top"; + case 213: return "low_cloud_top"; - case 214: return "low_cloud_layer"; + case 214: return "low_cloud_layer"; - case 222: return "middle_cloud_bottom"; + case 222: return "middle_cloud_bottom"; - case 223: return "middle_cloud_top"; + case 223: return "middle_cloud_top"; - case 224: return "middle_cloud_layer"; + case 224: return "middle_cloud_layer"; - case 232: return "high_cloud_bottom"; + case 232: return "high_cloud_bottom"; - case 233: return "high_cloud_top"; + case 233: return "high_cloud_top"; - case 234: return "high_cloud_layer"; + case 234: return "high_cloud_layer"; - case 242: return "convective_cloud_bottom"; + case 242: return "convective_cloud_bottom"; - case 243: return "convective_cloud_top"; + case 243: return "convective_cloud_top"; - case 244: return "convective_cloud_layer"; + case 244: return "convective_cloud_layer"; - case 245: return "lowest_level_of_wet_bulb_zero"; + case 245: return "lowest_level_of_wet_bulb_zero"; - case 246: return "maximum_equivalent_potential_temperature"; + case 246: return "maximum_equivalent_potential_temperature"; - case 247: return "equilibrium"; + case 247: return "equilibrium"; - case 248: return "shallow_convective_cloud_bottom"; + case 248: return "shallow_convective_cloud_bottom"; - case 249: return "shallow_convective_cloud_top"; + case 249: return "shallow_convective_cloud_top"; - case 251: return "deep_convective_cloud_bottom"; + case 251: return "deep_convective_cloud_bottom"; - case 252: return "deep_convective_cloud_top"; + case 252: return "deep_convective_cloud_top"; - case 255: return ""; + case 255: return ""; - default: return "Unknown" + id; - } - } // end getNameShort + default: return "Unknown" + id; + } + } // end getNameShort - /// type of vertical coordinate: units - /// derived from ON388 - TABLE 3. - /// - /// units number - /// - /// unit as String - /// - static public System.String getUnits(int id) - { - switch (id) - { - case 20: - case 113: - case 114: - return "K"; + /// type of vertical coordinate: units + /// derived from ON388 - TABLE 3. + /// + /// units number + /// + /// unit as String + /// + static public System.String getUnits(int id) + { + switch (id) + { + case 20: + case 113: + case 114: + return "K"; - case 100: - case 101: - case 115: - case 116: - case 121: - case 141: - return "hPa"; + case 100: + case 101: + case 115: + case 116: + case 121: + case 141: + return "hPa"; - case 103: - case 104: - case 105: - case 106: - case 160: - return "m"; + case 103: + case 104: + case 105: + case 106: + case 160: + return "m"; - case 107: - case 108: - case 128: - return "sigma"; + case 107: + case 108: + case 128: + return "sigma"; - case 111: - case 112: - case 125: - return "cm"; + case 111: + case 112: + case 125: + return "cm"; - case 117: - return "10-6Km2/kgs"; + case 117: + return "10-6Km2/kgs"; - case 126: - return "Pa"; - } + case 126: + return "Pa"; + } - return ""; - } // end getUnits - } + return ""; + } // end getUnits } \ No newline at end of file diff --git a/src/NGrib/Grib1/GribPdsParamTable.cs b/src/NGrib/Grib1/GribPdsParamTable.cs new file mode 100644 index 0000000..3b4a7e1 --- /dev/null +++ b/src/NGrib/Grib1/GribPdsParamTable.cs @@ -0,0 +1,37 @@ +using NGrib.Grib1.PdsParameterTables; + +namespace NGrib.Grib1; + +public abstract class GribPdsParamTable +{ + private const string Undefined = "undefined"; + + private static readonly IReadOnlyDictionary<(int, int, int), GribPdsParamTable> _table = + new Dictionary<(int, int, int), GribPdsParamTable>() + { + {(98,0,1),new ParameterTable001()}, + {(98,0,2),new ParameterTable002()}, + {(98,0,3),new ParameterTable003()}, + {(98,0,128), new ParameterTable128()}, + {(98,0,210), new ParameterTable210()} + }; + + private static readonly DefaultParameterTable _default = new(0); + + protected abstract int TableNumber { get; } + + public static GribPdsParamTable GetParameterTable(int centerId, int subcenterId, int tableVersion) + { + if (_table.TryGetValue((centerId, subcenterId, tableVersion), out var parameterTable)) + return parameterTable; + return _default; + } + + public abstract Parameter GetParameter(int parameterNumber); + + protected Parameter GetDefaultParameter(int parameterNumber) + { + return new Parameter(TableNumber * 1000 + parameterNumber, parameterNumber.ToString(), + Undefined, Undefined); + } +} \ No newline at end of file diff --git a/src/NGrib/Grib1/Parameter.cs b/src/NGrib/Grib1/Parameter.cs index 25e0e6b..b9f60c0 100644 --- a/src/NGrib/Grib1/Parameter.cs +++ b/src/NGrib/Grib1/Parameter.cs @@ -1,7 +1,7 @@ /* * This file is part of NGrib. * - * Copyright 2020 Nicolas Mangu + * Copyright � 2020 Nicolas Mangu� * * Copyright 2006-2010 Seaware AB, PO Box 1244, SE-131 28 * Nacka Strand, Sweden, info@seaware.se. @@ -28,112 +28,109 @@ /// Robert Kambic 10/10/03 /// -using System.Runtime.InteropServices; +namespace NGrib.Grib1; -namespace NGrib.Grib1 +/// Class which represents a parameter from a PDS parameter table. +/// A parameter consists of a discipline( ie Meteorological_products), +/// a Category( ie Temperature ) and a number that refers to a name( ie Temperature), +/// Description( ie Temperature at 2 meters), and Units( ie K ). +/// see Parameters.txt +/// +public sealed class Parameter { - /// Class which represents a parameter from a PDS parameter table. - /// A parameter consists of a discipline( ie Meteorological_products), - /// a Category( ie Temperature ) and a number that refers to a name( ie Temperature), - /// Description( ie Temperature at 2 meters), and Units( ie K ). - /// see Parameters.txt - /// - public sealed class Parameter - { - //UPGRADE_NOTE: Respective javadoc comments were merged. It should be changed in order to comply with .NET documentation conventions. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1199'" - /// number of parameter. - /// number - /// - /// sets number of parameter. - /// of parameter - /// - public int Number - { - get { return number; } - - set { number = value; } - } - - //UPGRADE_NOTE: Respective javadoc comments were merged. It should be changed in order to comply with .NET documentation conventions. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1199'" - /// name of parameter. - /// name - /// - /// sets name of parameter. - /// of parameter - /// - public System.String Name - { - get { return name; } - - set { name = value; } - } - - //UPGRADE_NOTE: Respective javadoc comments were merged. It should be changed in order to comply with .NET documentation conventions. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1199'" - /// description of parameter. - /// - /// - /// description - /// - /// sets description of parameter. - /// of parameter - /// - public System.String Description - { - get { return description; } - - set { description = value; } - } - - //UPGRADE_NOTE: Respective javadoc comments were merged. It should be changed in order to comply with .NET documentation conventions. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1199'" - /// unit of parameter. - /// unit - /// - /// sets unit of parameter. - /// of parameter - /// - public System.String Unit - { - get { return unit; } - - set { unit = value; } - } - - /// parameter number. - private int number; - - /// name of parameter. - private System.String name; - - /// description of parameter. - private System.String description; - - /// unit of Parameter. - private System.String unit; - - /// constructor. - internal Parameter() - { - number = -1; - name = "undefined"; - description = "undefined"; - unit = "undefined"; - } - - /// constructor. - /// - /// - /// - /// - /// - /// - /// of parameter - /// - internal Parameter(int number, System.String name, System.String description, System.String unit) - { - this.number = number; - this.name = name; - this.description = description; - this.unit = unit; - } - } + //UPGRADE_NOTE: Respective javadoc comments were merged. It should be changed in order to comply with .NET documentation conventions. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1199'" + /// number of parameter. + /// number + /// + /// sets number of parameter. + /// of parameter + /// + public int Number + { + get { return number; } + + set { number = value; } + } + + //UPGRADE_NOTE: Respective javadoc comments were merged. It should be changed in order to comply with .NET documentation conventions. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1199'" + /// name of parameter. + /// name + /// + /// sets name of parameter. + /// of parameter + /// + public System.String Name + { + get { return name; } + + set { name = value; } + } + + //UPGRADE_NOTE: Respective javadoc comments were merged. It should be changed in order to comply with .NET documentation conventions. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1199'" + /// description of parameter. + /// + /// + /// description + /// + /// sets description of parameter. + /// of parameter + /// + public System.String Description + { + get { return description; } + + set { description = value; } + } + + //UPGRADE_NOTE: Respective javadoc comments were merged. It should be changed in order to comply with .NET documentation conventions. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1199'" + /// unit of parameter. + /// unit + /// + /// sets unit of parameter. + /// of parameter + /// + public System.String Unit + { + get { return unit; } + + set { unit = value; } + } + + /// parameter number. + private int number; + + /// name of parameter. + private System.String name; + + /// description of parameter. + private System.String description; + + /// unit of Parameter. + private System.String unit; + + /// constructor. + internal Parameter() + { + number = -1; + name = "undefined"; + description = "undefined"; + unit = "undefined"; + } + + /// constructor. + /// + /// + /// + /// + /// + /// + /// of parameter + /// + internal Parameter(int number, System.String name, System.String description, System.String unit) + { + this.number = number; + this.name = name; + this.description = description; + this.unit = unit; + } } \ No newline at end of file diff --git a/src/NGrib/Grib1/PdsParameterTables/DefaultParameterTable.cs b/src/NGrib/Grib1/PdsParameterTables/DefaultParameterTable.cs new file mode 100644 index 0000000..b3e64d3 --- /dev/null +++ b/src/NGrib/Grib1/PdsParameterTables/DefaultParameterTable.cs @@ -0,0 +1,15 @@ +namespace NGrib.Grib1.PdsParameterTables; + +public class DefaultParameterTable:GribPdsParamTable +{ + public DefaultParameterTable(int tableNumber) + { + TableNumber = tableNumber; + } + + protected override int TableNumber { get; } + public override Parameter GetParameter(int parameterNumber) + { + return GetDefaultParameter(parameterNumber); + } +} \ No newline at end of file diff --git a/src/NGrib/Grib1/PdsParameterTables/ParameterTable001.cs b/src/NGrib/Grib1/PdsParameterTables/ParameterTable001.cs new file mode 100644 index 0000000..18f51e1 --- /dev/null +++ b/src/NGrib/Grib1/PdsParameterTables/ParameterTable001.cs @@ -0,0 +1,14 @@ +namespace NGrib.Grib1.PdsParameterTables; + +public class ParameterTable001:GribPdsParamTable +{ + protected override int TableNumber => 1; + public override Parameter GetParameter(int parameterNumber) + { + return parameterNumber switch + { + 10 => Parameters.TCO3, + _ => GetDefaultParameter(parameterNumber) + }; + } +} \ No newline at end of file diff --git a/src/NGrib/Grib1/PdsParameterTables/ParameterTable002.cs b/src/NGrib/Grib1/PdsParameterTables/ParameterTable002.cs new file mode 100644 index 0000000..44ee8af --- /dev/null +++ b/src/NGrib/Grib1/PdsParameterTables/ParameterTable002.cs @@ -0,0 +1,15 @@ +namespace NGrib.Grib1.PdsParameterTables; + +public class ParameterTable002:GribPdsParamTable +{ + protected override int TableNumber => 2; + + public override Parameter GetParameter(int parameterNumber) + { + return parameterNumber switch + { + 10 => Parameters.TCO3, + _ => GetDefaultParameter(parameterNumber) + }; + } +} \ No newline at end of file diff --git a/src/NGrib/Grib1/PdsParameterTables/ParameterTable003.cs b/src/NGrib/Grib1/PdsParameterTables/ParameterTable003.cs new file mode 100644 index 0000000..cde780b --- /dev/null +++ b/src/NGrib/Grib1/PdsParameterTables/ParameterTable003.cs @@ -0,0 +1,15 @@ +namespace NGrib.Grib1.PdsParameterTables; + +public class ParameterTable003:GribPdsParamTable +{ + protected override int TableNumber => 3; + + public override Parameter GetParameter(int parameterNumber) + { + return parameterNumber switch + { + 10 => Parameters.TCO3, + _ => GetDefaultParameter(parameterNumber) + }; + } +} \ No newline at end of file diff --git a/src/NGrib/Grib1/PdsParameterTables/ParameterTable128.cs b/src/NGrib/Grib1/PdsParameterTables/ParameterTable128.cs new file mode 100644 index 0000000..07e7540 --- /dev/null +++ b/src/NGrib/Grib1/PdsParameterTables/ParameterTable128.cs @@ -0,0 +1,16 @@ +namespace NGrib.Grib1.PdsParameterTables; + +public class ParameterTable128:GribPdsParamTable +{ + protected override int TableNumber => 128; + + public override Parameter GetParameter(int parameterNumber) + { + return parameterNumber switch + { + 206 => Parameters.GTCO3, + _ => GetDefaultParameter(parameterNumber) + }; + } + +} \ No newline at end of file diff --git a/src/NGrib/Grib1/PdsParameterTables/ParameterTable210.cs b/src/NGrib/Grib1/PdsParameterTables/ParameterTable210.cs new file mode 100644 index 0000000..9ab22fb --- /dev/null +++ b/src/NGrib/Grib1/PdsParameterTables/ParameterTable210.cs @@ -0,0 +1,26 @@ +namespace NGrib.Grib1.PdsParameterTables; + +public class ParameterTable210 : GribPdsParamTable +{ + protected override int TableNumber => 210; + + public override Parameter GetParameter(int parameterNumber) + { + return parameterNumber switch + { + 6=> Parameters.AERMR06, + + 206 => Parameters.GTCO3, + + //73 => Parameters.PM2P5, + + 121 => Parameters.NO2, + + 123 => Parameters.CO, + + 126 => Parameters.TCSO2, + + _ => GetDefaultParameter(parameterNumber) + }; + } +} \ No newline at end of file diff --git a/src/NGrib/Grib1/PdsParameterTables/Parameters.cs b/src/NGrib/Grib1/PdsParameterTables/Parameters.cs new file mode 100644 index 0000000..198a19b --- /dev/null +++ b/src/NGrib/Grib1/PdsParameterTables/Parameters.cs @@ -0,0 +1,47 @@ +namespace NGrib.Grib1.PdsParameterTables; + +public static class Parameters +{ + /// + /// Ozone + /// + public static Parameter GTCO3 { get; }=new Parameter(206, "GTCO3 Total column ozone", + @"(TCO3) This parameter is the total amount of ozone in a column of air extending from the surface of the Earth to the top of the atmosphere. This parameter can also be referred to as total ozone, or vertically integrated ozone. The values are dominated by ozone within the stratosphere. +In the ECMWF Integrated Forecasting System (IFS), there is a simplified representation of ozone chemistry (including representation of the chemistry which has caused the ozone hole). Ozone is also transported around in the atmosphere through the motion of air. See further documentation . +Naturally occurring ozone in the stratosphere helps protect organisms at the surface of the Earth from the harmful effects of ultraviolet (UV) radiation from the Sun. Ozone near the surface, often produced because of pollution, is harmful to organisms. +In the IFS, the units for total ozone are kilograms per square metre, but before 12/06/2001 dobson units were used. Dobson units (DU) are still used extensively for total column ozone. 1 DU = 2.1415E-5 kg m-2", + "kg m^(-2)"); + + public static Parameter TCO3 { get; }=new Parameter(10, "TCO3 Total column ozone", + @"(TCO3) This parameter is the total amount of ozone in a column of air extending from the surface of the Earth to the top of the atmosphere. This parameter can also be referred to as total ozone, or vertically integrated ozone. The values are dominated by ozone within the stratosphere. +In the ECMWF Integrated Forecasting System (IFS), there is a simplified representation of ozone chemistry (including representation of the chemistry which has caused the ozone hole). Ozone is also transported around in the atmosphere through the motion of air. See further documentation . +Naturally occurring ozone in the stratosphere helps protect organisms at the surface of the Earth from the harmful effects of ultraviolet (UV) radiation from the Sun. Ozone near the surface, often produced because of pollution, is harmful to organisms. +In the IFS, the units for total ozone are kilograms per square metre, but before 12/06/2001 dobson units were used. Dobson units (DU) are still used extensively for total column ozone. 1 DU = 2.1415E-5 kg m-2", + "kg m^(-2)"); + + /// + /// Particulate matter d <= 2.5 um + /// + public static Parameter PM2P5 { get; }= new Parameter(210073, "PM2P5 Particulate matter d <= 2.5 um", "pm2p5", "kg m-3"); + + /// + /// Nitrogen dioxide + /// + public static Parameter NO2 { get; } = new(210121, "NO2 Nitrogen dioxide mass mixing ratio", "NO2", "kg kg-1"); + + /// + /// Carbon monoxide + /// + public static Parameter CO { get; } = new(210123, "CO Carbon monoxide mass mixing ratio", "CO", "kg kg-1"); + + /// + /// Total column Sulphur dioxide + /// + public static Parameter TCSO2 { get; } = new(210126, "TCSO2 Total column Sulphur dioxide", "TCSO2", "kg m-2"); + + /// + /// Dust Aerosol (0.9 - 20 um) Mixing Ratio + /// + public static Parameter AERMR06 { get; } = new(210006, "AERMR06 Dust Aerosol (0.9 - 20 um) Mixing Ratio", "AERMR06", "kg kg-1"); + +} \ No newline at end of file diff --git a/src/NGrib/Grib1/PdsParameterTables/TimeRangeUnitGrib1.cs b/src/NGrib/Grib1/PdsParameterTables/TimeRangeUnitGrib1.cs new file mode 100644 index 0000000..7240dd0 --- /dev/null +++ b/src/NGrib/Grib1/PdsParameterTables/TimeRangeUnitGrib1.cs @@ -0,0 +1,23 @@ +using System.ComponentModel; + +namespace NGrib.Grib1.PdsParameterTables; + +public enum TimeRangeUnitGrib1 +{ + [Description("Missing")] Missing = 255, + [Description("Minute")] Minute = 0, + [Description("Hour")] Hour = 1, + [Description("Day")] Day = 2, + [Description("Month")] Month = 3, + [Description("Year")] Year = 4, + [Description("Decade")] Decade = 5, + [Description("Normal")] Normal = 6, + [Description("Century")] Century = 7, + [Description("3 Hours")] Hours3 = 10, + [Description("6 Hours")] Hours6 = 11, + [Description("12 Hours")] Hours12 = 12, + [Description("15 Minutes")] Minutes15 = 13, + [Description("30 Minutes")] Minutes30 = 14, + [Description("Reserved")] Reserved = 253, + [Description("Second")] Second = 254 +} \ No newline at end of file diff --git a/src/NGrib/Grib1/SupportClass.cs b/src/NGrib/Grib1/SupportClass.cs index a8136a1..4f62d83 100644 --- a/src/NGrib/Grib1/SupportClass.cs +++ b/src/NGrib/Grib1/SupportClass.cs @@ -24,919 +24,869 @@ * along with NGrib. If not, see . */ -using System; +namespace NGrib.Grib1; -namespace NGrib.Grib1 +/// +/// Contains conversion support elements such as classes, interfaces and static methods. +/// +internal class SupportClass { - /// - /// Contains conversion support elements such as classes, interfaces and static methods. - /// - internal class SupportClass - { - /// - /// Try to skip bytes in the input stream and return the actual number of bytes skipped. - /// - /// Input stream that will be used to skip the bytes - /// Number of bytes to be skipped - /// Actual number of bytes skipped - public static int Skip(System.IO.Stream stream, int skipBytes) - { - long oldPosition = stream.Position; - long result = stream.Seek(skipBytes, System.IO.SeekOrigin.Current) - oldPosition; - return (int) result; - } - - /// - /// Skips a given number of characters into a given Stream. - /// - /// The stream in which the skips are done. - /// The number of caracters to skip. - /// The number of characters skipped. - public static long Skip(System.IO.StreamReader stream, long number) - { - long skippedBytes = 0; - for (long index = 0; index < number; index++) - { - stream.Read(); - skippedBytes++; - } - - return skippedBytes; - } - - /// - /// Skips a given number of characters into a given StringReader. - /// - /// The StringReader in which the skips are done. - /// The number of caracters to skip. - /// The number of characters skipped. - public static long Skip(System.IO.StringReader strReader, long number) - { - long skippedBytes = 0; - for (long index = 0; index < number; index++) - { - strReader.Read(); - skippedBytes++; - } - - return skippedBytes; - } - - - /*******************************/ - /// Reads a number of characters from the current source Stream and writes the data to the target array at the specified index. - /// The source Stream to read from. - /// Contains the array of characteres read from the source Stream. - /// The starting index of the target array. - /// The maximum number of characters to read from the source Stream. - /// The number of characters read. The number will be less than or equal to count depending on the data available in the source Stream. Returns -1 if the end of the stream is reached. - public static Int32 ReadInput(System.IO.Stream sourceStream, sbyte[] target, int start, int count) - { - // Returns 0 bytes if not enough space in target - if (target.Length == 0) - return 0; - - byte[] receiver = new byte[target.Length]; - int bytesRead = sourceStream.Read(receiver, start, count); - - // Returns -1 if EOF - if (bytesRead == 0) - return -1; - - for (int i = start; i < start + bytesRead; i++) - target[i] = (sbyte) receiver[i]; - - return bytesRead; - } - - /// Reads a number of characters from the current source TextReader and writes the data to the target array at the specified index. - /// The source TextReader to read from - /// Contains the array of characteres read from the source TextReader. - /// The starting index of the target array. - /// The maximum number of characters to read from the source TextReader. - /// The number of characters read. The number will be less than or equal to count depending on the data available in the source TextReader. Returns -1 if the end of the stream is reached. - public static Int32 ReadInput(System.IO.TextReader sourceTextReader, sbyte[] target, int start, int count) - { - // Returns 0 bytes if not enough space in target - if (target.Length == 0) return 0; - - char[] charArray = new char[target.Length]; - int bytesRead = sourceTextReader.Read(charArray, start, count); - - // Returns -1 if EOF - if (bytesRead == 0) return -1; - - for (int index = start; index < start + bytesRead; index++) - target[index] = (sbyte) charArray[index]; - - return bytesRead; - } - - /// Converts an array of sbytes to an array of bytes - /// - /// The array of sbytes to be converted - /// The new array of bytes - public static byte[] ToByteArray(sbyte[] sbyteArray) - { - byte[] byteArray = null; - - if (sbyteArray != null) - { - byteArray = new byte[sbyteArray.Length]; - for (int index = 0; index < sbyteArray.Length; index++) - byteArray[index] = (byte) sbyteArray[index]; - } - - return byteArray; - } - - /// - /// Converts a string to an array of bytes - /// - /// The string to be converted - /// The new array of bytes - public static byte[] ToByteArray(String sourceString) - { - return System.Text.Encoding.UTF8.GetBytes(sourceString); - } - - /// - /// Converts a array of object-type instances to a byte-type array. - /// - /// Array to convert. - /// An array of byte type elements. - public static byte[] ToByteArray(Object[] tempObjectArray) - { - byte[] byteArray = null; - if (tempObjectArray != null) - { - byteArray = new byte[tempObjectArray.Length]; - for (int index = 0; index < tempObjectArray.Length; index++) - byteArray[index] = (byte) tempObjectArray[index]; - } - - return byteArray; - } - - /*******************************/ - - /*******************************/ - /// - /// Provides support for DateFormat - /// - public class DateTimeFormatManager - { - static public DateTimeFormatHashTable manager = new DateTimeFormatHashTable(); - - /// - /// Hashtable class to provide functionality for dateformat properties - /// - public class DateTimeFormatHashTable : System.Collections.Hashtable - { - /// - /// Sets the format for datetime. - /// - /// DateTimeFormat instance to set the pattern - /// A string with the pattern format - public void SetDateFormatPattern(System.Globalization.DateTimeFormatInfo format, String newPattern) - { - if (this[format] != null) - ((DateTimeFormatProperties) this[format]).DateFormatPattern = newPattern; - else - { - DateTimeFormatProperties tempProps = new DateTimeFormatProperties(); - tempProps.DateFormatPattern = newPattern; - Add(format, tempProps); - } - } - - /// - /// Gets the current format pattern of the DateTimeFormat instance - /// - /// The DateTimeFormat instance which the value will be obtained - /// The string representing the current datetimeformat pattern - public String GetDateFormatPattern(System.Globalization.DateTimeFormatInfo format) - { - if (this[format] == null) - return "d-MMM-yy"; - else - return ((DateTimeFormatProperties) this[format]).DateFormatPattern; - } - - /// - /// Sets the datetimeformat pattern to the giving format - /// - /// The datetimeformat instance to set - /// The new datetimeformat pattern - public void SetTimeFormatPattern(System.Globalization.DateTimeFormatInfo format, String newPattern) - { - if (this[format] != null) - ((DateTimeFormatProperties) this[format]).TimeFormatPattern = newPattern; - else - { - DateTimeFormatProperties tempProps = new DateTimeFormatProperties(); - tempProps.TimeFormatPattern = newPattern; - Add(format, tempProps); - } - } - - /// - /// Gets the current format pattern of the DateTimeFormat instance - /// - /// The DateTimeFormat instance which the value will be obtained - /// The string representing the current datetimeformat pattern - public String GetTimeFormatPattern(System.Globalization.DateTimeFormatInfo format) - { - if (this[format] == null) - return "h:mm:ss tt"; - else - return ((DateTimeFormatProperties) this[format]).TimeFormatPattern; - } - - /// - /// Internal class to provides the DateFormat and TimeFormat pattern properties on .NET - /// - class DateTimeFormatProperties - { - public String DateFormatPattern = "d-MMM-yy"; - public String TimeFormatPattern = "h:mm:ss tt"; - } - } - } - - /*******************************/ - /// - /// Gets the DateTimeFormat instance and date instance to obtain the date with the format passed - /// - /// The DateTimeFormat to obtain the time and date pattern - /// The date instance used to get the date - /// A string representing the date with the time and date patterns - public static String FormatDateTime(System.Globalization.DateTimeFormatInfo format, DateTime date) - { - String timePattern = DateTimeFormatManager.manager.GetTimeFormatPattern(format); - String datePattern = DateTimeFormatManager.manager.GetDateFormatPattern(format); - return date.ToString(datePattern + " " + timePattern, format); - } - - /*******************************/ - /// - /// Represents a collection ob objects that contains no duplicate elements. - /// - public interface SetSupport : System.Collections.ICollection, System.Collections.IList - { - /// - /// Adds a new element to the Collection if it is not already present. - /// - /// The object to add to the collection. - /// Returns true if the object was added to the collection, otherwise false. - new bool Add(Object obj); - - /// - /// Adds all the elements of the specified collection to the Set. - /// - /// Collection of objects to add. - /// true - bool AddAll(System.Collections.ICollection c); - } - - - /*******************************/ - /// - /// SupportClass for the HashSet class. - /// - [Serializable] - public class HashSetSupport : System.Collections.ArrayList, SetSupport - { - public HashSetSupport() : base() - { - } - - public HashSetSupport(System.Collections.ICollection c) - { - AddAll(c); - } - - public HashSetSupport(int capacity) : base(capacity) - { - } - - /// - /// Adds a new element to the ArrayList if it is not already present. - /// - /// Element to insert to the ArrayList. - /// Returns true if the new element was inserted, false otherwise. - new public virtual bool Add(Object obj) - { - bool inserted; - - if ((inserted = Contains(obj)) == false) - { - base.Add(obj); - } - - return !inserted; - } - - /// - /// Adds all the elements of the specified collection that are not present to the list. - /// - /// Collection where the new elements will be added - /// Returns true if at least one element was added, false otherwise. - public bool AddAll(System.Collections.ICollection c) - { - System.Collections.IEnumerator e = new System.Collections.ArrayList(c).GetEnumerator(); - bool added = false; - - while (e.MoveNext() == true) - { - if (Add(e.Current) == true) - added = true; - } - - return added; - } - - /// - /// Returns a copy of the HashSet instance. - /// - /// Returns a shallow copy of the current HashSet. - public override Object Clone() - { - return MemberwiseClone(); - } - } - - - /*******************************/ - /// - /// This class provides functionality not found in .NET collection-related interfaces. - /// - public class ICollectionSupport - { - /// - /// Adds a new element to the specified collection. - /// - /// Collection where the new element will be added. - /// Object to add. - /// true - public static bool Add(System.Collections.ICollection c, Object obj) - { - bool added = false; - //Reflection. Invoke either the "add" or "Add" method. - System.Reflection.MethodInfo method; - try - { - //Get the "add" method for proprietary classes - method = c.GetType().GetMethod("Add"); - if (method == null) - method = c.GetType().GetMethod("add"); - int index = (int) method.Invoke(c, new Object[] {obj}); - if (index >= 0) - added = true; - } - catch (Exception e) - { - throw e; - } - - return added; - } - - /// - /// Adds all of the elements of the "c" collection to the "target" collection. - /// - /// Collection where the new elements will be added. - /// Collection whose elements will be added. - /// Returns true if at least one element was added, false otherwise. - public static bool AddAll(System.Collections.ICollection target, System.Collections.ICollection c) - { - System.Collections.IEnumerator e = new System.Collections.ArrayList(c).GetEnumerator(); - bool added = false; - - //Reflection. Invoke "addAll" method for proprietary classes - System.Reflection.MethodInfo method; - try - { - method = target.GetType().GetMethod("addAll"); - - if (method != null) - added = (bool) method.Invoke(target, new Object[] {c}); - else - { - method = target.GetType().GetMethod("Add"); - while (e.MoveNext() == true) - { - bool tempBAdded = (int) method.Invoke(target, new Object[] {e.Current}) >= 0; - added = added ? added : tempBAdded; - } - } - } - catch (Exception ex) - { - throw ex; - } - - return added; - } - - /// - /// Removes all the elements from the collection. - /// - /// The collection to remove elements. - public static void Clear(System.Collections.ICollection c) - { - //Reflection. Invoke "Clear" method or "clear" method for proprietary classes - System.Reflection.MethodInfo method; - try - { - method = c.GetType().GetMethod("Clear"); - - if (method == null) - method = c.GetType().GetMethod("clear"); - - method.Invoke(c, new Object[] { }); - } - catch (Exception e) - { - throw e; - } - } - - /// - /// Determines whether the collection contains the specified element. - /// - /// The collection to check. - /// The object to locate in the collection. - /// true if the element is in the collection. - public static bool Contains(System.Collections.ICollection c, Object obj) - { - bool contains = false; - - //Reflection. Invoke "contains" method for proprietary classes - System.Reflection.MethodInfo method; - try - { - method = c.GetType().GetMethod("Contains"); - - if (method == null) - method = c.GetType().GetMethod("contains"); - - contains = (bool) method.Invoke(c, new Object[] {obj}); - } - catch (Exception e) - { - throw e; - } - - return contains; - } - - /// - /// Determines whether the collection contains all the elements in the specified collection. - /// - /// The collection to check. - /// Collection whose elements would be checked for containment. - /// true id the target collection contains all the elements of the specified collection. - public static bool ContainsAll(System.Collections.ICollection target, System.Collections.ICollection c) - { - System.Collections.IEnumerator e = c.GetEnumerator(); - - bool contains = false; - - //Reflection. Invoke "containsAll" method for proprietary classes or "Contains" method for each element in the collection - System.Reflection.MethodInfo method; - try - { - method = target.GetType().GetMethod("containsAll"); - - if (method != null) - contains = (bool) method.Invoke(target, new Object[] {c}); - else - { - method = target.GetType().GetMethod("Contains"); - while (e.MoveNext() == true) - { - if ((contains = (bool) method.Invoke(target, new Object[] {e.Current})) == false) - break; - } - } - } - catch (Exception ex) - { - throw ex; - } - - return contains; - } - - /// - /// Removes the specified element from the collection. - /// - /// The collection where the element will be removed. - /// The element to remove from the collection. - public static bool Remove(System.Collections.ICollection c, Object obj) - { - bool changed = false; - - //Reflection. Invoke "remove" method for proprietary classes or "Remove" method - System.Reflection.MethodInfo method; - try - { - method = c.GetType().GetMethod("remove"); - - if (method != null) - method.Invoke(c, new Object[] {obj}); - else - { - method = c.GetType().GetMethod("Contains"); - changed = (bool) method.Invoke(c, new Object[] {obj}); - method = c.GetType().GetMethod("Remove"); - method.Invoke(c, new Object[] {obj}); - } - } - catch (Exception e) - { - throw e; - } - - return changed; - } - - /// - /// Removes all the elements from the specified collection that are contained in the target collection. - /// - /// Collection where the elements will be removed. - /// Elements to remove from the target collection. - /// true - public static bool RemoveAll(System.Collections.ICollection target, System.Collections.ICollection c) - { - System.Collections.ArrayList al = ToArrayList(c); - System.Collections.IEnumerator e = al.GetEnumerator(); - - //Reflection. Invoke "removeAll" method for proprietary classes or "Remove" for each element in the collection - System.Reflection.MethodInfo method; - try - { - method = target.GetType().GetMethod("removeAll"); - - if (method != null) - method.Invoke(target, new Object[] {al}); - else - { - method = target.GetType().GetMethod("Remove"); - System.Reflection.MethodInfo methodContains = target.GetType().GetMethod("Contains"); - - while (e.MoveNext() == true) - { - while ((bool) methodContains.Invoke(target, new Object[] {e.Current}) == true) - method.Invoke(target, new Object[] {e.Current}); - } - } - } - catch (Exception ex) - { - throw ex; - } - - return true; - } - - /// - /// Retains the elements in the target collection that are contained in the specified collection - /// - /// Collection where the elements will be removed. - /// Elements to be retained in the target collection. - /// true - public static bool RetainAll(System.Collections.ICollection target, System.Collections.ICollection c) - { - System.Collections.IEnumerator e = new System.Collections.ArrayList(target).GetEnumerator(); - System.Collections.ArrayList al = new System.Collections.ArrayList(c); - - //Reflection. Invoke "retainAll" method for proprietary classes or "Remove" for each element in the collection - System.Reflection.MethodInfo method; - try - { - method = c.GetType().GetMethod("retainAll"); - - if (method != null) - method.Invoke(target, new Object[] {c}); - else - { - method = c.GetType().GetMethod("Remove"); - - while (e.MoveNext() == true) - { - if (al.Contains(e.Current) == false) - method.Invoke(target, new Object[] {e.Current}); - } - } - } - catch (Exception ex) - { - throw ex; - } - - return true; - } - - /// - /// Returns an array containing all the elements of the collection. - /// - /// The array containing all the elements of the collection. - public static Object[] ToArray(System.Collections.ICollection c) - { - int index = 0; - Object[] objects = new Object[c.Count]; - System.Collections.IEnumerator e = c.GetEnumerator(); - - while (e.MoveNext()) - objects[index++] = e.Current; - - return objects; - } - - /// - /// Obtains an array containing all the elements of the collection. - /// - /// The array into which the elements of the collection will be stored. - /// The array containing all the elements of the collection. - public static Object[] ToArray(System.Collections.ICollection c, Object[] objects) - { - int index = 0; - - Type type = objects.GetType().GetElementType(); - Object[] objs = (Object[]) Array.CreateInstance(type, c.Count); - - System.Collections.IEnumerator e = c.GetEnumerator(); - - while (e.MoveNext()) - objs[index++] = e.Current; - - //If objects is smaller than c then do not return the new array in the parameter - if (objects.Length >= c.Count) - objs.CopyTo(objects, 0); - - return objs; - } - - /// - /// Converts an ICollection instance to an ArrayList instance. - /// - /// The ICollection instance to be converted. - /// An ArrayList instance in which its elements are the elements of the ICollection instance. - public static System.Collections.ArrayList ToArrayList(System.Collections.ICollection c) - { - System.Collections.ArrayList tempArrayList = new System.Collections.ArrayList(); - System.Collections.IEnumerator tempEnumerator = c.GetEnumerator(); - while (tempEnumerator.MoveNext()) - tempArrayList.Add(tempEnumerator.Current); - return tempArrayList; - } - } - - - /*******************************/ - /// - /// This method returns the literal value received - /// - /// The literal to return - /// The received value - public static long Identity(long literal) - { - return literal; - } - - /// - /// This method returns the literal value received - /// - /// The literal to return - /// The received value - public static ulong Identity(ulong literal) - { - return literal; - } - - /// - /// This method returns the literal value received - /// - /// The literal to return - /// The received value - public static float Identity(float literal) - { - return literal; - } - - /// - /// This method returns the literal value received - /// - /// The literal to return - /// The received value - public static double Identity(double literal) - { - return literal; - } - - /*******************************/ - /// - /// Writes the exception stack trace to the received stream - /// - /// Exception to obtain information from - /// Output sream used to write to - public static void WriteStackTrace(Exception throwable, System.IO.TextWriter stream) - { - stream.Write(throwable.StackTrace); - stream.Flush(); - } - - /*******************************/ - /// - /// The class performs token processing in strings - /// - public class Tokenizer : System.Collections.IEnumerator - { - /// Position over the string - private long currentPos; - - /// Include demiliters in the results. - private bool includeDelims; - - /// Char representation of the String to tokenize. - private char[] chars; - - //The tokenizer uses the default delimiter set: the space character, the tab character, the newline character, and the carriage-return character and the form-feed character - private string delimiters = " \t\n\r\f"; - - /// - /// Initializes a new class instance with a specified string to process - /// - /// String to tokenize - public Tokenizer(String source) - { - chars = source.ToCharArray(); - } - - /// - /// Initializes a new class instance with a specified string to process - /// and the specified token delimiters to use - /// - /// String to tokenize - /// String containing the delimiters - public Tokenizer(String source, String delimiters) : this(source) - { - this.delimiters = delimiters; - } - - - /// - /// Initializes a new class instance with a specified string to process, the specified token - /// delimiters to use, and whether the delimiters must be included in the results. - /// - /// String to tokenize - /// String containing the delimiters - /// Determines if delimiters are included in the results. - public Tokenizer(String source, String delimiters, bool includeDelims) : this(source, delimiters) - { - this.includeDelims = includeDelims; - } - - - /// - /// Returns the next token from the token list - /// - /// The string value of the token - public String NextToken() - { - return NextToken(delimiters); - } - - /// - /// Returns the next token from the source string, using the provided - /// token delimiters - /// - /// String containing the delimiters to use - /// The string value of the token - public String NextToken(String delimiters) - { - //According to documentation, the usage of the received delimiters should be temporary (only for this call). - //However, it seems it is not true, so the following line is necessary. - this.delimiters = delimiters; - - //at the end - if (currentPos == chars.Length) - throw new ArgumentOutOfRangeException(); - //if over a delimiter and delimiters must be returned - else if ((Array.IndexOf(delimiters.ToCharArray(), chars[currentPos]) != -1) - && includeDelims) - return "" + chars[currentPos++]; - //need to get the token wo delimiters. - else - return nextToken(delimiters.ToCharArray()); - } - - //Returns the nextToken wo delimiters - private String nextToken(char[] delimiters) - { - string token = ""; - long pos = currentPos; - - //skip possible delimiters - while (Array.IndexOf(delimiters, chars[currentPos]) != -1) - //The last one is a delimiter (i.e there is no more tokens) - if (++currentPos == chars.Length) - { - currentPos = pos; - throw new ArgumentOutOfRangeException(); - } - - //getting the token - while (Array.IndexOf(delimiters, chars[currentPos]) == -1) - { - token += chars[currentPos]; - //the last one is not a delimiter - if (++currentPos == chars.Length) - break; - } - - return token; - } - - - /// - /// Determines if there are more tokens to return from the source string - /// - /// True or false, depending if there are more tokens - public bool HasMoreTokens() - { - //keeping the current pos - long pos = currentPos; - - try - { - NextToken(); - } - catch (ArgumentOutOfRangeException) - { - return false; - } - finally - { - currentPos = pos; - } - - return true; - } - - /// - /// Remaining tokens count - /// - public int Count - { - get - { - //keeping the current pos - long pos = currentPos; - int i = 0; - - try - { - while (true) - { - NextToken(); - i++; - } - } - catch (ArgumentOutOfRangeException) - { - currentPos = pos; - return i; - } - } - } - - /// - /// Performs the same action as NextToken. - /// - public Object Current - { - get { return (Object) NextToken(); } - } - - /// - // Performs the same action as HasMoreTokens. - /// - /// True or false, depending if there are more tokens - public bool MoveNext() - { - return HasMoreTokens(); - } - - /// - /// Does nothing. - /// - public void Reset() - { - ; - } - } - } + /// + /// Try to skip bytes in the input stream and return the actual number of bytes skipped. + /// + /// Input stream that will be used to skip the bytes + /// Number of bytes to be skipped + /// Actual number of bytes skipped + public static int Skip(System.IO.Stream stream, int skipBytes) + { + long oldPosition = stream.Position; + long result = stream.Seek(skipBytes, System.IO.SeekOrigin.Current) - oldPosition; + return (int) result; + } + + /// + /// Skips a given number of characters into a given Stream. + /// + /// The stream in which the skips are done. + /// The number of caracters to skip. + /// The number of characters skipped. + public static long Skip(System.IO.StreamReader stream, long number) + { + long skippedBytes = 0; + for (long index = 0; index < number; index++) + { + stream.Read(); + skippedBytes++; + } + + return skippedBytes; + } + + /// + /// Skips a given number of characters into a given StringReader. + /// + /// The StringReader in which the skips are done. + /// The number of caracters to skip. + /// The number of characters skipped. + public static long Skip(System.IO.StringReader strReader, long number) + { + long skippedBytes = 0; + for (long index = 0; index < number; index++) + { + strReader.Read(); + skippedBytes++; + } + + return skippedBytes; + } + + + /*******************************/ + /// Reads a number of characters from the current source Stream and writes the data to the target array at the specified index. + /// The source Stream to read from. + /// Contains the array of characteres read from the source Stream. + /// The starting index of the target array. + /// The maximum number of characters to read from the source Stream. + /// The number of characters read. The number will be less than or equal to count depending on the data available in the source Stream. Returns -1 if the end of the stream is reached. + public static Int32 ReadInput(System.IO.Stream sourceStream, sbyte[] target, int start, int count) + { + // Returns 0 bytes if not enough space in target + if (target.Length == 0) + return 0; + + byte[] receiver = new byte[target.Length]; + int bytesRead = sourceStream.Read(receiver, start, count); + + // Returns -1 if EOF + if (bytesRead == 0) + return -1; + + for (int i = start; i < start + bytesRead; i++) + target[i] = (sbyte) receiver[i]; + + return bytesRead; + } + + /// Reads a number of characters from the current source TextReader and writes the data to the target array at the specified index. + /// The source TextReader to read from + /// Contains the array of characteres read from the source TextReader. + /// The starting index of the target array. + /// The maximum number of characters to read from the source TextReader. + /// The number of characters read. The number will be less than or equal to count depending on the data available in the source TextReader. Returns -1 if the end of the stream is reached. + public static Int32 ReadInput(System.IO.TextReader sourceTextReader, sbyte[] target, int start, int count) + { + // Returns 0 bytes if not enough space in target + if (target.Length == 0) return 0; + + char[] charArray = new char[target.Length]; + int bytesRead = sourceTextReader.Read(charArray, start, count); + + // Returns -1 if EOF + if (bytesRead == 0) return -1; + + for (int index = start; index < start + bytesRead; index++) + target[index] = (sbyte) charArray[index]; + + return bytesRead; + } + + /// Converts an array of sbytes to an array of bytes + /// + /// The array of sbytes to be converted + /// The new array of bytes + public static byte[] ToByteArray(sbyte[] sbyteArray) + { + byte[] byteArray = null; + + if (sbyteArray != null) + { + byteArray = new byte[sbyteArray.Length]; + for (int index = 0; index < sbyteArray.Length; index++) + byteArray[index] = (byte) sbyteArray[index]; + } + + return byteArray; + } + + /// + /// Converts a string to an array of bytes + /// + /// The string to be converted + /// The new array of bytes + public static byte[] ToByteArray(String sourceString) + { + return System.Text.Encoding.UTF8.GetBytes(sourceString); + } + + /// + /// Converts a array of object-type instances to a byte-type array. + /// + /// Array to convert. + /// An array of byte type elements. + public static byte[] ToByteArray(Object[] tempObjectArray) + { + byte[] byteArray = null; + if (tempObjectArray != null) + { + byteArray = new byte[tempObjectArray.Length]; + for (int index = 0; index < tempObjectArray.Length; index++) + byteArray[index] = (byte) tempObjectArray[index]; + } + + return byteArray; + } + + /*******************************/ + + /*******************************/ + /// + /// Provides support for DateFormat + /// + public class DateTimeFormatManager + { + static public DateTimeFormatHashTable manager = new DateTimeFormatHashTable(); + + /// + /// Hashtable class to provide functionality for dateformat properties + /// + public class DateTimeFormatHashTable : System.Collections.Hashtable + { + /// + /// Sets the format for datetime. + /// + /// DateTimeFormat instance to set the pattern + /// A string with the pattern format + public void SetDateFormatPattern(System.Globalization.DateTimeFormatInfo format, String newPattern) + { + if (this[format] != null) + ((DateTimeFormatProperties) this[format]).DateFormatPattern = newPattern; + else + { + DateTimeFormatProperties tempProps = new DateTimeFormatProperties(); + tempProps.DateFormatPattern = newPattern; + Add(format, tempProps); + } + } + + /// + /// Gets the current format pattern of the DateTimeFormat instance + /// + /// The DateTimeFormat instance which the value will be obtained + /// The string representing the current datetimeformat pattern + public String GetDateFormatPattern(System.Globalization.DateTimeFormatInfo format) + { + if (this[format] == null) + return "d-MMM-yy"; + else + return ((DateTimeFormatProperties) this[format]).DateFormatPattern; + } + + /// + /// Sets the datetimeformat pattern to the giving format + /// + /// The datetimeformat instance to set + /// The new datetimeformat pattern + public void SetTimeFormatPattern(System.Globalization.DateTimeFormatInfo format, String newPattern) + { + if (this[format] != null) + ((DateTimeFormatProperties) this[format]).TimeFormatPattern = newPattern; + else + { + DateTimeFormatProperties tempProps = new DateTimeFormatProperties(); + tempProps.TimeFormatPattern = newPattern; + Add(format, tempProps); + } + } + + /// + /// Gets the current format pattern of the DateTimeFormat instance + /// + /// The DateTimeFormat instance which the value will be obtained + /// The string representing the current datetimeformat pattern + public String GetTimeFormatPattern(System.Globalization.DateTimeFormatInfo format) + { + if (this[format] == null) + return "h:mm:ss tt"; + else + return ((DateTimeFormatProperties) this[format]).TimeFormatPattern; + } + + /// + /// Internal class to provides the DateFormat and TimeFormat pattern properties on .NET + /// + class DateTimeFormatProperties + { + public String DateFormatPattern = "d-MMM-yy"; + public String TimeFormatPattern = "h:mm:ss tt"; + } + } + } + + /*******************************/ + /// + /// Gets the DateTimeFormat instance and date instance to obtain the date with the format passed + /// + /// The DateTimeFormat to obtain the time and date pattern + /// The date instance used to get the date + /// A string representing the date with the time and date patterns + public static String FormatDateTime(System.Globalization.DateTimeFormatInfo format, DateTime date) + { + String timePattern = DateTimeFormatManager.manager.GetTimeFormatPattern(format); + String datePattern = DateTimeFormatManager.manager.GetDateFormatPattern(format); + return date.ToString(datePattern + " " + timePattern, format); + } + + /*******************************/ + /// + /// Represents a collection ob objects that contains no duplicate elements. + /// + public interface SetSupport : System.Collections.ICollection, System.Collections.IList + { + /// + /// Adds a new element to the Collection if it is not already present. + /// + /// The object to add to the collection. + /// Returns true if the object was added to the collection, otherwise false. + new bool Add(Object obj); + + /// + /// Adds all the elements of the specified collection to the Set. + /// + /// Collection of objects to add. + /// true + bool AddAll(System.Collections.ICollection c); + } + + + /*******************************/ + /// + /// SupportClass for the HashSet class. + /// + [Serializable] + public class HashSetSupport : System.Collections.ArrayList, SetSupport + { + public HashSetSupport() : base() + { + } + + public HashSetSupport(System.Collections.ICollection c) + { + AddAll(c); + } + + public HashSetSupport(int capacity) : base(capacity) + { + } + + /// + /// Adds a new element to the ArrayList if it is not already present. + /// + /// Element to insert to the ArrayList. + /// Returns true if the new element was inserted, false otherwise. + new public virtual bool Add(Object obj) + { + bool inserted; + + if ((inserted = Contains(obj)) == false) + { + base.Add(obj); + } + + return !inserted; + } + + /// + /// Adds all the elements of the specified collection that are not present to the list. + /// + /// Collection where the new elements will be added + /// Returns true if at least one element was added, false otherwise. + public bool AddAll(System.Collections.ICollection c) + { + System.Collections.IEnumerator e = new System.Collections.ArrayList(c).GetEnumerator(); + bool added = false; + + while (e.MoveNext() == true) + { + if (Add(e.Current) == true) + added = true; + } + + return added; + } + + /// + /// Returns a copy of the HashSet instance. + /// + /// Returns a shallow copy of the current HashSet. + public override Object Clone() + { + return MemberwiseClone(); + } + } + + + /*******************************/ + /// + /// This class provides functionality not found in .NET collection-related interfaces. + /// + public class ICollectionSupport + { + /// + /// Adds a new element to the specified collection. + /// + /// Collection where the new element will be added. + /// Object to add. + /// true + public static bool Add(System.Collections.ICollection c, Object obj) + { + bool added = false; + //Reflection. Invoke either the "add" or "Add" method. + System.Reflection.MethodInfo method; + + //Get the "add" method for proprietary classes + method = c.GetType().GetMethod("Add"); + if (method == null) + method = c.GetType().GetMethod("add"); + int index = (int) method.Invoke(c, new Object[] {obj}); + if (index >= 0) + added = true; + + return added; + } + + /// + /// Adds all of the elements of the "c" collection to the "target" collection. + /// + /// Collection where the new elements will be added. + /// Collection whose elements will be added. + /// Returns true if at least one element was added, false otherwise. + public static bool AddAll(System.Collections.ICollection target, System.Collections.ICollection c) + { + System.Collections.IEnumerator e = new System.Collections.ArrayList(c).GetEnumerator(); + bool added = false; + + //Reflection. Invoke "addAll" method for proprietary classes + System.Reflection.MethodInfo method; + + method = target.GetType().GetMethod("addAll"); + + if (method != null) + added = (bool) method.Invoke(target, new Object[] {c}); + else + { + method = target.GetType().GetMethod("Add"); + while (e.MoveNext() == true) + { + bool tempBAdded = (int) method.Invoke(target, new Object[] {e.Current}) >= 0; + added = added ? added : tempBAdded; + } + } + + return added; + } + + /// + /// Removes all the elements from the collection. + /// + /// The collection to remove elements. + public static void Clear(System.Collections.ICollection c) + { + //Reflection. Invoke "Clear" method or "clear" method for proprietary classes + System.Reflection.MethodInfo method; + + method = c.GetType().GetMethod("Clear"); + + if (method == null) + method = c.GetType().GetMethod("clear"); + + method.Invoke(c, new Object[] { }); + } + + /// + /// Determines whether the collection contains the specified element. + /// + /// The collection to check. + /// The object to locate in the collection. + /// true if the element is in the collection. + public static bool Contains(System.Collections.ICollection c, Object obj) + { + bool contains = false; + + //Reflection. Invoke "contains" method for proprietary classes + System.Reflection.MethodInfo method; + + method = c.GetType().GetMethod("Contains"); + + if (method == null) + method = c.GetType().GetMethod("contains"); + + contains = (bool) method.Invoke(c, new Object[] {obj}); + + + return contains; + } + + /// + /// Determines whether the collection contains all the elements in the specified collection. + /// + /// The collection to check. + /// Collection whose elements would be checked for containment. + /// true id the target collection contains all the elements of the specified collection. + public static bool ContainsAll(System.Collections.ICollection target, System.Collections.ICollection c) + { + System.Collections.IEnumerator e = c.GetEnumerator(); + + bool contains = false; + + //Reflection. Invoke "containsAll" method for proprietary classes or "Contains" method for each element in the collection + System.Reflection.MethodInfo method; + + method = target.GetType().GetMethod("containsAll"); + + if (method != null) + contains = (bool) method.Invoke(target, new Object[] {c}); + else + { + method = target.GetType().GetMethod("Contains"); + while (e.MoveNext() == true) + { + if ((contains = (bool) method.Invoke(target, new Object[] {e.Current})) == false) + break; + } + } + + return contains; + } + + /// + /// Removes the specified element from the collection. + /// + /// The collection where the element will be removed. + /// The element to remove from the collection. + public static bool Remove(System.Collections.ICollection c, Object obj) + { + bool changed = false; + + //Reflection. Invoke "remove" method for proprietary classes or "Remove" method + System.Reflection.MethodInfo method; + + method = c.GetType().GetMethod("remove"); + + if (method != null) + method.Invoke(c, new Object[] {obj}); + else + { + method = c.GetType().GetMethod("Contains"); + changed = (bool) method.Invoke(c, new Object[] {obj}); + method = c.GetType().GetMethod("Remove"); + method.Invoke(c, new Object[] {obj}); + } + + return changed; + } + + /// + /// Removes all the elements from the specified collection that are contained in the target collection. + /// + /// Collection where the elements will be removed. + /// Elements to remove from the target collection. + /// true + public static bool RemoveAll(System.Collections.ICollection target, System.Collections.ICollection c) + { + System.Collections.ArrayList al = ToArrayList(c); + System.Collections.IEnumerator e = al.GetEnumerator(); + + //Reflection. Invoke "removeAll" method for proprietary classes or "Remove" for each element in the collection + System.Reflection.MethodInfo method; + + method = target.GetType().GetMethod("removeAll"); + + if (method != null) + method.Invoke(target, new Object[] {al}); + else + { + method = target.GetType().GetMethod("Remove"); + System.Reflection.MethodInfo methodContains = target.GetType().GetMethod("Contains"); + + while (e.MoveNext() == true) + { + while ((bool) methodContains.Invoke(target, new Object[] {e.Current}) == true) + method.Invoke(target, new Object[] {e.Current}); + } + } + + return true; + } + + /// + /// Retains the elements in the target collection that are contained in the specified collection + /// + /// Collection where the elements will be removed. + /// Elements to be retained in the target collection. + /// true + public static bool RetainAll(System.Collections.ICollection target, System.Collections.ICollection c) + { + System.Collections.IEnumerator e = new System.Collections.ArrayList(target).GetEnumerator(); + System.Collections.ArrayList al = new System.Collections.ArrayList(c); + + //Reflection. Invoke "retainAll" method for proprietary classes or "Remove" for each element in the collection + System.Reflection.MethodInfo method; + + method = c.GetType().GetMethod("retainAll"); + + if (method != null) + method.Invoke(target, new Object[] {c}); + else + { + method = c.GetType().GetMethod("Remove"); + + while (e.MoveNext() == true) + { + if (al.Contains(e.Current) == false) + method.Invoke(target, new Object[] {e.Current}); + } + } + + return true; + } + + /// + /// Returns an array containing all the elements of the collection. + /// + /// The array containing all the elements of the collection. + public static Object[] ToArray(System.Collections.ICollection c) + { + int index = 0; + Object[] objects = new Object[c.Count]; + System.Collections.IEnumerator e = c.GetEnumerator(); + + while (e.MoveNext()) + objects[index++] = e.Current; + + return objects; + } + + /// + /// Obtains an array containing all the elements of the collection. + /// + /// The array into which the elements of the collection will be stored. + /// The array containing all the elements of the collection. + public static Object[] ToArray(System.Collections.ICollection c, Object[] objects) + { + int index = 0; + + Type type = objects.GetType().GetElementType(); + Object[] objs = (Object[]) Array.CreateInstance(type, c.Count); + + System.Collections.IEnumerator e = c.GetEnumerator(); + + while (e.MoveNext()) + objs[index++] = e.Current; + + //If objects is smaller than c then do not return the new array in the parameter + if (objects.Length >= c.Count) + objs.CopyTo(objects, 0); + + return objs; + } + + /// + /// Converts an ICollection instance to an ArrayList instance. + /// + /// The ICollection instance to be converted. + /// An ArrayList instance in which its elements are the elements of the ICollection instance. + public static System.Collections.ArrayList ToArrayList(System.Collections.ICollection c) + { + System.Collections.ArrayList tempArrayList = new System.Collections.ArrayList(); + System.Collections.IEnumerator tempEnumerator = c.GetEnumerator(); + while (tempEnumerator.MoveNext()) + tempArrayList.Add(tempEnumerator.Current); + return tempArrayList; + } + } + + + /*******************************/ + /// + /// This method returns the literal value received + /// + /// The literal to return + /// The received value + public static long Identity(long literal) + { + return literal; + } + + /// + /// This method returns the literal value received + /// + /// The literal to return + /// The received value + public static ulong Identity(ulong literal) + { + return literal; + } + + /// + /// This method returns the literal value received + /// + /// The literal to return + /// The received value + public static float Identity(float literal) + { + return literal; + } + + /// + /// This method returns the literal value received + /// + /// The literal to return + /// The received value + public static double Identity(double literal) + { + return literal; + } + + /*******************************/ + /// + /// Writes the exception stack trace to the received stream + /// + /// Exception to obtain information from + /// Output sream used to write to + public static void WriteStackTrace(Exception throwable, System.IO.TextWriter stream) + { + stream.Write(throwable.StackTrace); + stream.Flush(); + } + + /*******************************/ + /// + /// The class performs token processing in strings + /// + public class Tokenizer : System.Collections.IEnumerator + { + /// Position over the string + private long currentPos; + + /// Include demiliters in the results. + private bool includeDelims; + + /// Char representation of the String to tokenize. + private char[] chars; + + //The tokenizer uses the default delimiter set: the space character, the tab character, the newline character, and the carriage-return character and the form-feed character + private string delimiters = " \t\n\r\f"; + + /// + /// Initializes a new class instance with a specified string to process + /// + /// String to tokenize + public Tokenizer(String source) + { + chars = source.ToCharArray(); + } + + /// + /// Initializes a new class instance with a specified string to process + /// and the specified token delimiters to use + /// + /// String to tokenize + /// String containing the delimiters + public Tokenizer(String source, String delimiters) : this(source) + { + this.delimiters = delimiters; + } + + + /// + /// Initializes a new class instance with a specified string to process, the specified token + /// delimiters to use, and whether the delimiters must be included in the results. + /// + /// String to tokenize + /// String containing the delimiters + /// Determines if delimiters are included in the results. + public Tokenizer(String source, String delimiters, bool includeDelims) : this(source, delimiters) + { + this.includeDelims = includeDelims; + } + + + /// + /// Returns the next token from the token list + /// + /// The string value of the token + public String NextToken() + { + return NextToken(delimiters); + } + + /// + /// Returns the next token from the source string, using the provided + /// token delimiters + /// + /// String containing the delimiters to use + /// The string value of the token + public String NextToken(String delimiters) + { + //According to documentation, the usage of the received delimiters should be temporary (only for this call). + //However, it seems it is not true, so the following line is necessary. + this.delimiters = delimiters; + + //at the end + if (currentPos == chars.Length) + throw new ArgumentOutOfRangeException(); + //if over a delimiter and delimiters must be returned + else if ((Array.IndexOf(delimiters.ToCharArray(), chars[currentPos]) != -1) + && includeDelims) + return "" + chars[currentPos++]; + //need to get the token wo delimiters. + else + return nextToken(delimiters.ToCharArray()); + } + + //Returns the nextToken wo delimiters + private String nextToken(char[] delimiters) + { + string token = ""; + long pos = currentPos; + + //skip possible delimiters + while (Array.IndexOf(delimiters, chars[currentPos]) != -1) + //The last one is a delimiter (i.e there is no more tokens) + if (++currentPos == chars.Length) + { + currentPos = pos; + throw new ArgumentOutOfRangeException(); + } + + //getting the token + while (Array.IndexOf(delimiters, chars[currentPos]) == -1) + { + token += chars[currentPos]; + //the last one is not a delimiter + if (++currentPos == chars.Length) + break; + } + + return token; + } + + + /// + /// Determines if there are more tokens to return from the source string + /// + /// True or false, depending if there are more tokens + public bool HasMoreTokens() + { + //keeping the current pos + long pos = currentPos; + + try + { + NextToken(); + } + catch (ArgumentOutOfRangeException) + { + return false; + } + finally + { + currentPos = pos; + } + + return true; + } + + /// + /// Remaining tokens count + /// + public int Count + { + get + { + //keeping the current pos + long pos = currentPos; + int i = 0; + + try + { + while (true) + { + NextToken(); + i++; + } + } + catch (ArgumentOutOfRangeException) + { + currentPos = pos; + return i; + } + } + } + + /// + /// Performs the same action as NextToken. + /// + public Object Current + { + get { return (Object) NextToken(); } + } + + /// + // Performs the same action as HasMoreTokens. + /// + /// True or false, depending if there are more tokens + public bool MoveNext() + { + return HasMoreTokens(); + } + + /// + /// Does nothing. + /// + public void Reset() + { + ; + } + } } \ No newline at end of file diff --git a/src/NGrib/Grib1Reader.cs b/src/NGrib/Grib1Reader.cs index c129652..ec966d2 100644 --- a/src/NGrib/Grib1Reader.cs +++ b/src/NGrib/Grib1Reader.cs @@ -1,77 +1,76 @@ -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using NGrib.Grib1; +using NGrib.Grib1; -namespace NGrib -{ - public class Grib1Reader : IDisposable - { - private readonly bool leaveOpen; - private Grib1Input input; - private Grib1Data data; +namespace NGrib; - /// - /// Initializes a new instance of the Grib2Reader class - /// based on the specified file. - /// - /// The GRIB 2 file path. - public Grib1Reader(string filePath) : this(File.OpenRead(filePath)) - { } +public class Grib1Reader : IDisposable +{ + private readonly bool leaveOpen; + private Grib1File _grib1File; + private Grib1Input input; + private Grib1Data data; + - /// - /// Initializes a new instance of the Grib2Reader class - /// based on the specified stream. - /// - /// The GRIB 2 input stream. - /// trueto leave the stream open after the object is disposed; otherwise, false. - public Grib1Reader(Stream input, bool leaveOpen = false) - { - if (input == null) throw new ArgumentNullException(nameof(input)); - if (!input.CanRead) throw new ArgumentException("The stream must support reading.", nameof(input)); - if (!input.CanSeek) throw new ArgumentException("The stream must support seeking.", nameof(input)); - this.leaveOpen = leaveOpen; + /// + /// Initializes a new instance of the Grib2Reader class + /// based on the specified file. + /// + /// The GRIB 2 file path. + public Grib1Reader(string filePath) : this(File.OpenRead(filePath)) + { } - this.input = new Grib1Input(input); - data = new Grib1Data(input); - } + /// + /// Initializes a new instance of the Grib2Reader class + /// based on the specified stream. + /// + /// The GRIB 2 input stream. + /// trueto leave the stream open after the object is disposed; otherwise, false. + public Grib1Reader(Stream input, bool leaveOpen = false) + { + + if (input == null) throw new ArgumentNullException(nameof(input)); + if (!input.CanRead) throw new ArgumentException("The stream must support reading.", nameof(input)); + if (!input.CanSeek) throw new ArgumentException("The stream must support seeking.", nameof(input)); + this.leaveOpen = leaveOpen; + _grib1File = new Grib1File(); + this.input = new Grib1Input(input, _grib1File); + data = new Grib1Data(input, _grib1File); + } - /// - /// Enumerates the records in the underlying stream. - /// - /// The records in the GRIB11 stream. - public IEnumerable ReadRecords() => input.scanRecords(); + /// + /// Enumerates the records in the underlying stream. + /// + /// The records in the GRIB11 stream. + public IEnumerable ReadRecords() => input.ScanRecords(); - /// - /// Read the data set floating point values. - /// - /// The record to read. - /// Indicates whether the Bit-map section was used by the GRIB file producer. - /// The data set point values. - public float[] ReadRecordRawData(Grib1Record record, bool hasBitmapSection = false) => data.getData(record.DataOffset, record.ProductDefinitionSection.DecimalScale, false); + /// + /// Read the data set floating point values. + /// + /// The record to read. + /// Indicates whether the Bit-map section was used by the GRIB file producer. + /// The data set point values. + public double[] ReadRecordRawData(Grib1Record record, bool hasBitmapSection = false) => + data.getData(record.DataOffset, record.ProductDefinitionSection.DecimalScale, false); - /// - /// Read the records grid value. - /// - /// The record to read. - /// Indicates whether the Bit-map section was used by the GRIB file producer. - /// The record grid points and the corresponding values. - public IEnumerable> ReadRecordValues(Grib1Record record, bool hasBitmapSection = false) - { - var rawData = ReadRecordRawData(record, hasBitmapSection); + /// + /// Read the records grid value. + /// + /// The record to read. + /// Indicates whether the Bit-map section was used by the GRIB file producer. + /// The record grid points and the corresponding values. + public IEnumerable> ReadRecordValues(Grib1Record record, bool hasBitmapSection = false) + { + var rawData = ReadRecordRawData(record, hasBitmapSection); - return record.GridDefinitionSection.EnumerateGridPoints() - .Zip(rawData, (c, v) => new KeyValuePair(c, v)); - } + return record.GridDefinitionSection.EnumerateGridPoints() + .Zip(rawData, (c, v) => new KeyValuePair(c, v)); + } - public void Dispose() - { - if (!leaveOpen) - { - input.InputStream.Close(); - } - } - } -} + public void Dispose() + { + if (!leaveOpen) + { + input.InputStream.Close(); + } + } +} \ No newline at end of file diff --git a/src/NGrib/Grib2/CodeTables/0_0_Discipline.cs b/src/NGrib/Grib2/CodeTables/0_0_Discipline.cs index 5074377..8c68655 100644 --- a/src/NGrib/Grib2/CodeTables/0_0_Discipline.cs +++ b/src/NGrib/Grib2/CodeTables/0_0_Discipline.cs @@ -17,18 +17,17 @@ * along with NGrib. If not, see . */ -namespace NGrib.Grib2.CodeTables +namespace NGrib.Grib2.CodeTables; + +/// +/// Discipline of processed data in the GRIB message. +/// +public enum Discipline { - /// - /// Discipline of processed data in the GRIB message. - /// - public enum Discipline - { - MeteorologicalProducts = 0, - HydrologicalProducts = 1, - LandSurfaceProducts = 2, - SpaceProducts = 3, - OceanographicProducts = 10, - Missing = 255, - } + MeteorologicalProducts = 0, + HydrologicalProducts = 1, + LandSurfaceProducts = 2, + SpaceProducts = 3, + OceanographicProducts = 10, + Missing = 255, } \ No newline at end of file diff --git a/src/NGrib/Grib2/CodeTables/1_2_ReferenceTimeSignificance.cs b/src/NGrib/Grib2/CodeTables/1_2_ReferenceTimeSignificance.cs index 279a074..a4f4f2b 100644 --- a/src/NGrib/Grib2/CodeTables/1_2_ReferenceTimeSignificance.cs +++ b/src/NGrib/Grib2/CodeTables/1_2_ReferenceTimeSignificance.cs @@ -17,36 +17,35 @@ * along with NGrib. If not, see . */ -namespace NGrib.Grib2.CodeTables +namespace NGrib.Grib2.CodeTables; + +/// +/// Code Table 1.2: Significance of Reference Time +/// +public enum ReferenceTimeSignificance { - /// - /// Code Table 1.2: Significance of Reference Time - /// - public enum ReferenceTimeSignificance - { - /// - /// Analysis. - /// - Analysis = 0, + /// + /// Analysis. + /// + Analysis = 0, - /// - /// Start of forecast. - /// - ForecastStart = 1, + /// + /// Start of forecast. + /// + ForecastStart = 1, - /// - /// Verifying time of forecast. - /// - ForecastVerifyingTime = 2, + /// + /// Verifying time of forecast. + /// + ForecastVerifyingTime = 2, - /// - /// Observation time. - /// - ObservationTime = 3, + /// + /// Observation time. + /// + ObservationTime = 3, - /// - /// Missing. - /// - Missing = 255 - } + /// + /// Missing. + /// + Missing = 255 } \ No newline at end of file diff --git a/src/NGrib/Grib2/CodeTables/1_3_ProductStatus.cs b/src/NGrib/Grib2/CodeTables/1_3_ProductStatus.cs index 814afb1..e8aa7b7 100644 --- a/src/NGrib/Grib2/CodeTables/1_3_ProductStatus.cs +++ b/src/NGrib/Grib2/CodeTables/1_3_ProductStatus.cs @@ -17,36 +17,35 @@ * along with NGrib. If not, see . */ -namespace NGrib.Grib2.CodeTables +namespace NGrib.Grib2.CodeTables; + +/// +/// Code Table 1.3: Production status of data +/// +public enum ProductStatus { - /// - /// Code Table 1.3: Production status of data - /// - public enum ProductStatus - { - /// - /// Operational products - /// - OperationalProducts = 0, + /// + /// Operational products + /// + OperationalProducts = 0, - /// - /// Operational test products - /// - OperationalTestProducts = 1, + /// + /// Operational test products + /// + OperationalTestProducts = 1, - /// - /// Research products - /// - ResearchProducts = 2, + /// + /// Research products + /// + ResearchProducts = 2, - /// - /// Re-analysis products - /// - ReanalysisProducts = 3, + /// + /// Re-analysis products + /// + ReanalysisProducts = 3, - /// - /// Missing - /// - Missing = 255 - } + /// + /// Missing + /// + Missing = 255 } \ No newline at end of file diff --git a/src/NGrib/Grib2/CodeTables/1_4_ProductType.cs b/src/NGrib/Grib2/CodeTables/1_4_ProductType.cs index eeacc8e..ea1418e 100644 --- a/src/NGrib/Grib2/CodeTables/1_4_ProductType.cs +++ b/src/NGrib/Grib2/CodeTables/1_4_ProductType.cs @@ -17,56 +17,55 @@ * along with NGrib. If not, see . */ -namespace NGrib.Grib2.CodeTables +namespace NGrib.Grib2.CodeTables; + +/// +/// Code Table 1.4: Type of data +/// +public enum ProductType { - /// - /// Code Table 1.4: Type of data - /// - public enum ProductType - { - /// - /// Analysis products - /// - AnalysisProducts = 0, + /// + /// Analysis products + /// + AnalysisProducts = 0, - /// - /// Forecast products - /// - ForecastProducts = 1, + /// + /// Forecast products + /// + ForecastProducts = 1, - /// - /// Analysis and forecast products - /// - AnalysisAndForecastProducts = 2, + /// + /// Analysis and forecast products + /// + AnalysisAndForecastProducts = 2, - /// - /// Control forecast products - /// - ControlForecastProducts = 3, + /// + /// Control forecast products + /// + ControlForecastProducts = 3, - /// - /// Perturbed forecast products - /// - PerturbedForecastProducts = 4, + /// + /// Perturbed forecast products + /// + PerturbedForecastProducts = 4, - /// - /// Control and perturbed forecast products - /// - ControlAndPerturbedForecastProducts = 5, + /// + /// Control and perturbed forecast products + /// + ControlAndPerturbedForecastProducts = 5, - /// - /// Processed satellite observations - /// - ProcessedSatelliteObservations = 6, + /// + /// Processed satellite observations + /// + ProcessedSatelliteObservations = 6, - /// - /// Processed radar observations - /// - ProcessedRadarObservations = 7, + /// + /// Processed radar observations + /// + ProcessedRadarObservations = 7, - /// - /// Missing - /// - Missing = 255 - } + /// + /// Missing + /// + Missing = 255 } \ No newline at end of file diff --git a/src/NGrib/Grib2/CodeTables/3_2_EarthShape.cs b/src/NGrib/Grib2/CodeTables/3_2_EarthShape.cs index 64f2984..7604a42 100644 --- a/src/NGrib/Grib2/CodeTables/3_2_EarthShape.cs +++ b/src/NGrib/Grib2/CodeTables/3_2_EarthShape.cs @@ -17,47 +17,46 @@ * along with NGrib. If not, see . */ -namespace NGrib.Grib2.CodeTables +namespace NGrib.Grib2.CodeTables; + +/// +/// Code Table 3.2: Shape of the Earth +/// +public enum EarthShape { - /// - /// Code Table 3.2: Shape of the Earth - /// - public enum EarthShape - { - /// - /// Earth assumed spherical with radius = 6,367,470.0 m. - /// - DefaultSpherical, - - /// - /// Earth assumed spherical with radius specified by data producer. - /// - CustomSpherical, - - /// - /// Earth assumed oblate spheroid with size as determined by IAU in 1965 (major axis = 6,378,160.0 m, minor axis = 6,356,775.0 m, f = 1/297.0). - /// - Iau1965OblateSpheroid, - - /// - /// Earth assumed oblate spheroid with major and minor axes specified by data producer. - /// - CustomOblateSpheroid, - - /// - /// Earth assumed oblate spheroid as defined in IAG-GRS80 model (major axis = 6,378,137.0 m, minor axis = 6,356,752.314 m, f = 1/298.257222101). - /// - IagGr80OblateSpheroid, - - /// - /// Earth assumed represented by WGS84 (as used by ICAO since 1998). - /// - Wgs84, - - /// - /// Earth model assumed spherical with radius 6,371,200.0 m, - /// but the horizontal datum of the resulting Latitude/Longitude field is the WGS84 reference frame. - /// - Wgs84Spherical - } + /// + /// Earth assumed spherical with radius = 6,367,470.0 m. + /// + DefaultSpherical, + + /// + /// Earth assumed spherical with radius specified by data producer. + /// + CustomSpherical, + + /// + /// Earth assumed oblate spheroid with size as determined by IAU in 1965 (major axis = 6,378,160.0 m, minor axis = 6,356,775.0 m, f = 1/297.0). + /// + Iau1965OblateSpheroid, + + /// + /// Earth assumed oblate spheroid with major and minor axes specified by data producer. + /// + CustomOblateSpheroid, + + /// + /// Earth assumed oblate spheroid as defined in IAG-GRS80 model (major axis = 6,378,137.0 m, minor axis = 6,356,752.314 m, f = 1/298.257222101). + /// + IagGr80OblateSpheroid, + + /// + /// Earth assumed represented by WGS84 (as used by ICAO since 1998). + /// + Wgs84, + + /// + /// Earth model assumed spherical with radius 6,371,200.0 m, + /// but the horizontal datum of the resulting Latitude/Longitude field is the WGS84 reference frame. + /// + Wgs84Spherical } \ No newline at end of file diff --git a/src/NGrib/Grib2/CodeTables/3_3_ResolutionAndComponent.cs b/src/NGrib/Grib2/CodeTables/3_3_ResolutionAndComponent.cs index 1a2fc4e..966cee1 100644 --- a/src/NGrib/Grib2/CodeTables/3_3_ResolutionAndComponent.cs +++ b/src/NGrib/Grib2/CodeTables/3_3_ResolutionAndComponent.cs @@ -17,15 +17,12 @@ * along with NGrib. If not, see . */ -using System; +namespace NGrib.Grib2.CodeTables; -namespace NGrib.Grib2.CodeTables +[Flags] +public enum ResolutionAndComponent { - [Flags] - public enum ResolutionAndComponent - { - IDirectionIncrementGiven = 32, - JDirectionIncrementGiven = 16, - RelativeDefinedGrid = 8 - } + IDirectionIncrementGiven = 32, + JDirectionIncrementGiven = 16, + RelativeDefinedGrid = 8 } \ No newline at end of file diff --git a/src/NGrib/Grib2/CodeTables/3_4_ScanningMode.cs b/src/NGrib/Grib2/CodeTables/3_4_ScanningMode.cs index 8dccc91..05a491c 100644 --- a/src/NGrib/Grib2/CodeTables/3_4_ScanningMode.cs +++ b/src/NGrib/Grib2/CodeTables/3_4_ScanningMode.cs @@ -17,21 +17,18 @@ * along with NGrib. If not, see . */ -using System; +namespace NGrib.Grib2.CodeTables; -namespace NGrib.Grib2.CodeTables +[Flags] +public enum ScanningMode { - [Flags] - public enum ScanningMode - { - ScanIReverse = 128, - ScanJPositive = 64, - AdjacentPointsInJConsecutive = 32, - AdjacentRowsScanInOppositeDirection = 16, - DxOffOdd = 8, - DxOffEven = 4, - DyOff = 2, - ReducedGrid = 1, - Default = 0 - } + ScanIReverse = 128, + ScanJPositive = 64, + AdjacentPointsInJConsecutive = 32, + AdjacentRowsScanInOppositeDirection = 16, + DxOffOdd = 8, + DxOffEven = 4, + DyOff = 2, + ReducedGrid = 1, + Default = 0 } \ No newline at end of file diff --git a/src/NGrib/Grib2/CodeTables/4_1_ParameterCategory.cs b/src/NGrib/Grib2/CodeTables/4_1_ParameterCategory.cs index fc1d5fb..b30ca9c 100644 --- a/src/NGrib/Grib2/CodeTables/4_1_ParameterCategory.cs +++ b/src/NGrib/Grib2/CodeTables/4_1_ParameterCategory.cs @@ -17,210 +17,210 @@ * along with NGrib. If not, see . */ -using System.Collections.Generic; using System.Collections.Immutable; -using System.Linq; -namespace NGrib.Grib2.CodeTables +namespace NGrib.Grib2.CodeTables; + +/// +/// Represents a category parameters by product discipline. +/// +public struct ParameterCategory { - /// - /// Represents a category parameters by product discipline. - /// - public struct ParameterCategory - { - /// - /// Product discipline. - /// - public Discipline Discipline { get; } + /// + /// Product discipline. + /// + public Discipline Discipline { get; } + + /// + /// Parameter category code. + /// + public int Code { get; } - /// - /// Parameter category code. - /// - public int Code { get; } + /// + /// Parameter category description. + /// + public string Description { get; } - /// - /// Parameter category description. - /// - public string Description { get; } + private ParameterCategory(Discipline discipline, int code, string description) + { + Discipline = discipline; + Code = code; + Description = description; + } - private ParameterCategory(Discipline discipline, int code, string description) - { - Discipline = discipline; - Code = code; - Description = description; - } + ///Temperature + public static ParameterCategory Temperature { get; } = new ParameterCategory(Discipline.MeteorologicalProducts, 0, "Temperature"); - ///Temperature - public static ParameterCategory Temperature { get; } = new ParameterCategory(Discipline.MeteorologicalProducts, 0, "Temperature"); + ///Moisture + public static ParameterCategory Moisture { get; } = new ParameterCategory(Discipline.MeteorologicalProducts, 1, "Moisture"); - ///Moisture - public static ParameterCategory Moisture { get; } = new ParameterCategory(Discipline.MeteorologicalProducts, 1, "Moisture"); + ///Momentum + public static ParameterCategory Momentum { get; } = new ParameterCategory(Discipline.MeteorologicalProducts, 2, "Momentum"); - ///Momentum - public static ParameterCategory Momentum { get; } = new ParameterCategory(Discipline.MeteorologicalProducts, 2, "Momentum"); + ///Mass + public static ParameterCategory Mass { get; } = new ParameterCategory(Discipline.MeteorologicalProducts, 3, "Mass"); - ///Mass - public static ParameterCategory Mass { get; } = new ParameterCategory(Discipline.MeteorologicalProducts, 3, "Mass"); + ///Short-wave Radiation + public static ParameterCategory ShortWaveRadiation { get; } = + new ParameterCategory(Discipline.MeteorologicalProducts, 4, "Short-wave Radiation"); - ///Short-wave Radiation - public static ParameterCategory ShortWaveRadiation { get; } = - new ParameterCategory(Discipline.MeteorologicalProducts, 4, "Short-wave Radiation"); + ///Long-wave Radiation + public static ParameterCategory LongWaveRadiation { get; } = + new ParameterCategory(Discipline.MeteorologicalProducts, 5, "Long-wave Radiation"); - ///Long-wave Radiation - public static ParameterCategory LongWaveRadiation { get; } = - new ParameterCategory(Discipline.MeteorologicalProducts, 5, "Long-wave Radiation"); + ///Cloud + public static ParameterCategory Cloud { get; } = new ParameterCategory(Discipline.MeteorologicalProducts, 6, "Cloud"); - ///Cloud - public static ParameterCategory Cloud { get; } = new ParameterCategory(Discipline.MeteorologicalProducts, 6, "Cloud"); + ///Thermodynamic Stability indices + public static ParameterCategory ThermodynamicStabilityIndices { get; } = new ParameterCategory(Discipline.MeteorologicalProducts, + 7, "Thermodynamic Stability indices"); - ///Thermodynamic Stability indices - public static ParameterCategory ThermodynamicStabilityIndices { get; } = new ParameterCategory(Discipline.MeteorologicalProducts, - 7, "Thermodynamic Stability indices"); + ///Kinematic Stability indices + public static ParameterCategory KinematicStabilityIndices { get; } = + new ParameterCategory(Discipline.MeteorologicalProducts, 8, "Kinematic Stability indices"); - ///Kinematic Stability indices - public static ParameterCategory KinematicStabilityIndices { get; } = - new ParameterCategory(Discipline.MeteorologicalProducts, 8, "Kinematic Stability indices"); + ///Temperature Probabilities + public static ParameterCategory TemperatureProbabilities { get; } = + new ParameterCategory(Discipline.MeteorologicalProducts, 9, "Temperature Probabilities"); - ///Temperature Probabilities - public static ParameterCategory TemperatureProbabilities { get; } = - new ParameterCategory(Discipline.MeteorologicalProducts, 9, "Temperature Probabilities"); + ///Moisture Probabilities + public static ParameterCategory MoistureProbabilities { get; } = + new ParameterCategory(Discipline.MeteorologicalProducts, 10, "Moisture Probabilities"); - ///Moisture Probabilities - public static ParameterCategory MoistureProbabilities { get; } = - new ParameterCategory(Discipline.MeteorologicalProducts, 10, "Moisture Probabilities"); + ///Momentum Probabilities + public static ParameterCategory MomentumProbabilities { get; } = + new ParameterCategory(Discipline.MeteorologicalProducts, 11, "Momentum Probabilities"); - ///Momentum Probabilities - public static ParameterCategory MomentumProbabilities { get; } = - new ParameterCategory(Discipline.MeteorologicalProducts, 11, "Momentum Probabilities"); + ///Mass Probabilities + public static ParameterCategory MassProbabilities { get; } = + new ParameterCategory(Discipline.MeteorologicalProducts, 12, "Mass Probabilities"); - ///Mass Probabilities - public static ParameterCategory MassProbabilities { get; } = - new ParameterCategory(Discipline.MeteorologicalProducts, 12, "Mass Probabilities"); + ///Aerosols + public static ParameterCategory Aerosols { get; } = new ParameterCategory(Discipline.MeteorologicalProducts, 13, "Aerosols"); - ///Aerosols - public static ParameterCategory Aerosols { get; } = new ParameterCategory(Discipline.MeteorologicalProducts, 13, "Aerosols"); - - ///Trace gases (e.g., ozone, CO2) - public static ParameterCategory TraceGases { get; } = - new ParameterCategory(Discipline.MeteorologicalProducts, 14, "Trace gases (e.g., ozone, CO2)"); - - ///Radar - public static ParameterCategory Radar { get; } = new ParameterCategory(Discipline.MeteorologicalProducts, 15, "Radar"); - - ///Forecast Radar Imagery - public static ParameterCategory ForecastRadarImagery { get; } = - new ParameterCategory(Discipline.MeteorologicalProducts, 16, "Forecast Radar Imagery"); - - ///Electro-dynamics - public static ParameterCategory Electrodynamics { get; } = - new ParameterCategory(Discipline.MeteorologicalProducts, 17, "Electro-dynamics"); - - ///Nuclear/radiology - public static ParameterCategory NuclearRadiology { get; } = - new ParameterCategory(Discipline.MeteorologicalProducts, 18, "Nuclear/radiology"); - - ///Physical atmospheric properties - public static ParameterCategory PhysicalAtmosphericProperties { get; } = new ParameterCategory(Discipline.MeteorologicalProducts, - 19, "Physical atmospheric properties"); - - ///CCITT IA5 string - public static ParameterCategory CcittIa5String { get; } = - new ParameterCategory(Discipline.MeteorologicalProducts, 190, "CCITT IA5 string"); - - ///Miscellaneous - public static ParameterCategory Miscellaneous { get; } = - new ParameterCategory(Discipline.MeteorologicalProducts, 191, "Miscellaneous"); - - - ///Hydrology basic products - public static ParameterCategory HydrologyBasicProducts { get; } = - new ParameterCategory(Discipline.HydrologicalProducts, 0, "Hydrology basic products"); - - ///Hydrology probabilities - public static ParameterCategory HydrologyProbabilities { get; } = - new ParameterCategory(Discipline.HydrologicalProducts, 1, "Hydrology probabilities"); - - - ///Vegetation/Biomass - public static ParameterCategory VegetationBiomass { get; } = - new ParameterCategory(Discipline.LandSurfaceProducts, 0, "Vegetation/Biomass"); - - ///Agri-/aquacultural Special Products - public static ParameterCategory AgriAquaCulturalSpecialProducts { get; } = new ParameterCategory(Discipline.LandSurfaceProducts, - 1, "Agri-/aquacultural Special Products"); - - ///Transportation-related Products - public static ParameterCategory TransportationRelatedProducts { get; } = - new ParameterCategory(Discipline.LandSurfaceProducts, 2, "Transportation-related Products"); - - ///Soil Products - public static ParameterCategory SoilProducts { get; } = new ParameterCategory(Discipline.LandSurfaceProducts, 3, "Soil Products"); - - - ///Image format products - public static ParameterCategory ImageFormatProducts { get; } = - new ParameterCategory(Discipline.SpaceProducts, 0, "Image format products"); - - ///Quantitative products - public static ParameterCategory QuantitativeProducts { get; } = - new ParameterCategory(Discipline.SpaceProducts, 1, "Quantitative products"); - - - ///Waves - public static ParameterCategory Waves { get; } = new ParameterCategory(Discipline.OceanographicProducts, 0, "Waves"); - - ///Currents - public static ParameterCategory Currents { get; } = new ParameterCategory(Discipline.OceanographicProducts, 1, "Currents"); - - ///Ice - public static ParameterCategory Ice { get; } = new ParameterCategory(Discipline.OceanographicProducts, 2, "Ice"); - - ///Surface Properties - public static ParameterCategory SurfaceProperties { get; } = - new ParameterCategory(Discipline.OceanographicProducts, 3, "Surface Properties"); - - ///Sub-surface Properties - public static ParameterCategory SubSurfaceProperties { get; } = - new ParameterCategory(Discipline.OceanographicProducts, 4, "Sub-surface Properties"); - - public static IReadOnlyDictionary> CategoriesByDiscipline { get; } = - ImmutableList.Empty - .Add(Temperature) - .Add(Moisture) - .Add(Momentum) - .Add(Mass) - .Add(ShortWaveRadiation) - .Add(LongWaveRadiation) - .Add(Cloud) - .Add(ThermodynamicStabilityIndices) - .Add(KinematicStabilityIndices) - .Add(TemperatureProbabilities) - .Add(MoistureProbabilities) - .Add(MomentumProbabilities) - .Add(MassProbabilities) - .Add(Aerosols) - .Add(TraceGases) - .Add(Radar) - .Add(ForecastRadarImagery) - .Add(Electrodynamics) - .Add(NuclearRadiology) - .Add(PhysicalAtmosphericProperties) - .Add(CcittIa5String) - .Add(Miscellaneous) - .Add(HydrologyBasicProducts) - .Add(HydrologyProbabilities) - .Add(VegetationBiomass) - .Add(AgriAquaCulturalSpecialProducts) - .Add(TransportationRelatedProducts) - .Add(SoilProducts) - .Add(ImageFormatProducts) - .Add(QuantitativeProducts) - .Add(Waves) - .Add(Currents) - .Add(Ice) - .Add(SurfaceProperties) - .Add(SubSurfaceProperties) - .GroupBy(c => c.Discipline) - .ToDictionary(g => g.Key, g => (IReadOnlyCollection) g.ToImmutableList()); - } + ///Trace gases (e.g., ozone, CO2) + public static ParameterCategory TraceGases { get; } = + new ParameterCategory(Discipline.MeteorologicalProducts, 14, "Trace gases (e.g., ozone, CO2)"); + + ///Radar + public static ParameterCategory Radar { get; } = new ParameterCategory(Discipline.MeteorologicalProducts, 15, "Radar"); + + ///Forecast Radar Imagery + public static ParameterCategory ForecastRadarImagery { get; } = + new ParameterCategory(Discipline.MeteorologicalProducts, 16, "Forecast Radar Imagery"); + + ///Electro-dynamics + public static ParameterCategory Electrodynamics { get; } = + new ParameterCategory(Discipline.MeteorologicalProducts, 17, "Electro-dynamics"); + + ///Nuclear/radiology + public static ParameterCategory NuclearRadiology { get; } = + new ParameterCategory(Discipline.MeteorologicalProducts, 18, "Nuclear/radiology"); + ///Physical atmospheric properties + public static ParameterCategory PhysicalAtmosphericProperties { get; } = new ParameterCategory(Discipline.MeteorologicalProducts, + 19, "Physical atmospheric properties"); + + /// Atmospheric chemical Constituents + public static ParameterCategory AtmosphericChemicalConstituents { get; } = + new ParameterCategory(Discipline.MeteorologicalProducts, 20, "Atmospheric chemical Constituents"); + + ///CCITT IA5 string + public static ParameterCategory CcittIa5String { get; } = + new ParameterCategory(Discipline.MeteorologicalProducts, 190, "CCITT IA5 string"); + + ///Miscellaneous + public static ParameterCategory Miscellaneous { get; } = + new ParameterCategory(Discipline.MeteorologicalProducts, 191, "Miscellaneous"); + + + ///Hydrology basic products + public static ParameterCategory HydrologyBasicProducts { get; } = + new ParameterCategory(Discipline.HydrologicalProducts, 0, "Hydrology basic products"); + + ///Hydrology probabilities + public static ParameterCategory HydrologyProbabilities { get; } = + new ParameterCategory(Discipline.HydrologicalProducts, 1, "Hydrology probabilities"); + + + ///Vegetation/Biomass + public static ParameterCategory VegetationBiomass { get; } = + new ParameterCategory(Discipline.LandSurfaceProducts, 0, "Vegetation/Biomass"); + + ///Agri-/aquacultural Special Products + public static ParameterCategory AgriAquaCulturalSpecialProducts { get; } = new ParameterCategory(Discipline.LandSurfaceProducts, + 1, "Agri-/aquacultural Special Products"); + + ///Transportation-related Products + public static ParameterCategory TransportationRelatedProducts { get; } = + new ParameterCategory(Discipline.LandSurfaceProducts, 2, "Transportation-related Products"); + + ///Soil Products + public static ParameterCategory SoilProducts { get; } = new ParameterCategory(Discipline.LandSurfaceProducts, 3, "Soil Products"); + + + ///Image format products + public static ParameterCategory ImageFormatProducts { get; } = + new ParameterCategory(Discipline.SpaceProducts, 0, "Image format products"); + + ///Quantitative products + public static ParameterCategory QuantitativeProducts { get; } = + new ParameterCategory(Discipline.SpaceProducts, 1, "Quantitative products"); + + + ///Waves + public static ParameterCategory Waves { get; } = new ParameterCategory(Discipline.OceanographicProducts, 0, "Waves"); + + ///Currents + public static ParameterCategory Currents { get; } = new ParameterCategory(Discipline.OceanographicProducts, 1, "Currents"); + + ///Ice + public static ParameterCategory Ice { get; } = new ParameterCategory(Discipline.OceanographicProducts, 2, "Ice"); + + ///Surface Properties + public static ParameterCategory SurfaceProperties { get; } = + new ParameterCategory(Discipline.OceanographicProducts, 3, "Surface Properties"); + + ///Sub-surface Properties + public static ParameterCategory SubSurfaceProperties { get; } = + new ParameterCategory(Discipline.OceanographicProducts, 4, "Sub-surface Properties"); + + public static IReadOnlyDictionary> CategoriesByDiscipline { get; } = + ImmutableList.Empty + .Add(Temperature) + .Add(Moisture) + .Add(Momentum) + .Add(Mass) + .Add(ShortWaveRadiation) + .Add(LongWaveRadiation) + .Add(Cloud) + .Add(ThermodynamicStabilityIndices) + .Add(KinematicStabilityIndices) + .Add(TemperatureProbabilities) + .Add(MoistureProbabilities) + .Add(MomentumProbabilities) + .Add(MassProbabilities) + .Add(Aerosols) + .Add(TraceGases) + .Add(Radar) + .Add(ForecastRadarImagery) + .Add(Electrodynamics) + .Add(NuclearRadiology) + .Add(PhysicalAtmosphericProperties) + .Add(CcittIa5String) + .Add(Miscellaneous) + .Add(HydrologyBasicProducts) + .Add(HydrologyProbabilities) + .Add(VegetationBiomass) + .Add(AgriAquaCulturalSpecialProducts) + .Add(TransportationRelatedProducts) + .Add(SoilProducts) + .Add(ImageFormatProducts) + .Add(QuantitativeProducts) + .Add(Waves) + .Add(Currents) + .Add(Ice) + .Add(SurfaceProperties) + .Add(SubSurfaceProperties) + .GroupBy(c => c.Discipline) + .ToDictionary(g => g.Key, g => (IReadOnlyCollection) g.ToImmutableList()); } \ No newline at end of file diff --git a/src/NGrib/Grib2/CodeTables/4_2_Parameter.cs b/src/NGrib/Grib2/CodeTables/4_2_Parameter.cs index 2b7ad6a..d44f131 100644 --- a/src/NGrib/Grib2/CodeTables/4_2_Parameter.cs +++ b/src/NGrib/Grib2/CodeTables/4_2_Parameter.cs @@ -17,1746 +17,1998 @@ * along with NGrib. If not, see . */ -using System.Collections.Generic; using System.Collections.Immutable; -using System.Linq; -namespace NGrib.Grib2.CodeTables +namespace NGrib.Grib2.CodeTables; + +/// +/// Represents a parameter. +/// +public readonly struct Parameter { - /// - /// Represents a parameter. - /// - public readonly struct Parameter - { - /// - /// Parameter category. - /// - public ParameterCategory Category { get; } - - /// - /// Parameter number. - /// - public int Code { get; } - - /// - /// Parameter name. - /// - public string Name { get; } - - /// - /// Units. - /// - public string Unit { get; } - - private Parameter(ParameterCategory category, int code, string name, string unit) - { - Category = category; - Code = code; - Name = name; - Unit = unit; - } - - public static Parameter? Get(Discipline d, int parameterCategory, int parameterNumber) - { - if (ParameterCategory.CategoriesByDiscipline.TryGetValue(d, out var categories)) - { - var category = categories.Where(c => c.Code == parameterCategory).ToArray(); - if (category.Any() && ParametersByCategory.TryGetValue(category[0], out var parameters)) - { - var parameter = parameters.Where(p => p.Code == parameterNumber).ToArray(); - if (parameter.Any()) - { - return parameter[0]; - } - } - } - - return null; - } - - #region Product Discipline 0: Meteorological products, Parameter Category 0: Temperature - - ///Temperature (K) - public static Parameter Temperature { get; } = new Parameter(ParameterCategory.Temperature, 0, "Temperature", "K"); - - ///Virtual temperature (K) - public static Parameter VirtualTemperature { get; } = - new Parameter(ParameterCategory.Temperature, 1, "Virtual temperature", "K"); - - ///Potential temperature (K) - public static Parameter PotentialTemperature { get; } = - new Parameter(ParameterCategory.Temperature, 2, "Potential temperature", "K"); - - ///Pseudo-adiabatic potential temperature or equivalent potential temperature (K) - public static Parameter PseudoAdiabaticPotentialTemperatureOrEquivalentPotentialTemperature { get; } = - new Parameter(ParameterCategory.Temperature, 3, - "Pseudo-adiabatic potential temperature or equivalent potential temperature", "K"); - - ///Maximum temperature (K) - public static Parameter MaximumTemperature { get; } = - new Parameter(ParameterCategory.Temperature, 4, "Maximum temperature", "K"); - - ///Minimum temperature (K) - public static Parameter MinimumTemperature { get; } = - new Parameter(ParameterCategory.Temperature, 5, "Minimum temperature", "K"); - - ///Dew point temperature (K) - public static Parameter DewPointTemperature { get; } = - new Parameter(ParameterCategory.Temperature, 6, "Dew point temperature", "K"); - - ///Dew point depression (or deficit) (K) - public static Parameter DewPointDepression { get; } = - new Parameter(ParameterCategory.Temperature, 7, "Dew point depression (or deficit)", "K"); - - ///Lapse rate (K m-1) - public static Parameter LapseRate { get; } = new Parameter(ParameterCategory.Temperature, 8, "Lapse rate", "K m-1"); - - ///Temperature anomaly (K) - public static Parameter TemperatureAnomaly { get; } = - new Parameter(ParameterCategory.Temperature, 9, "Temperature anomaly", "K"); - - ///Latent heat net flux (W m-2) - public static Parameter LatentHeatNetFlux { get; } = - new Parameter(ParameterCategory.Temperature, 10, "Latent heat net flux", "W m-2"); - - ///Sensible heat net flux (W m-2) - public static Parameter SensibleHeatNetFlux { get; } = - new Parameter(ParameterCategory.Temperature, 11, "Sensible heat net flux", "W m-2"); - - ///Heat index (K) - public static Parameter HeatIndex { get; } = new Parameter(ParameterCategory.Temperature, 12, "Heat index", "K"); - - ///Wind chill factor (K) - public static Parameter WindChillFactor { get; } = - new Parameter(ParameterCategory.Temperature, 13, "Wind chill factor", "K"); - - ///Minimum dew point depression (K) - public static Parameter MinimumDewPointDepression { get; } = - new Parameter(ParameterCategory.Temperature, 14, "Minimum dew point depression", "K"); - - ///Virtual potential temperature (K) - public static Parameter VirtualPotentialTemperature { get; } = - new Parameter(ParameterCategory.Temperature, 15, "Virtual potential temperature", "K"); - - ///Snow Phase Change Heat Flux (W m-2) - public static Parameter SnowPhaseChangeHeatFlux { get; } = - new Parameter(ParameterCategory.Temperature, 16, "Snow Phase Change Heat Flux", "W m-2"); + /// + /// Parameter category. + /// + public ParameterCategory Category { get; } + + /// + /// Parameter number. + /// + public int Code { get; } + + /// + /// Parameter name. + /// + public string Name { get; } + + /// + /// Units. + /// + public string Unit { get; } + + private Parameter(ParameterCategory category, int code, string name, string unit) + { + Category = category; + Code = code; + Name = name; + Unit = unit; + } + + public static Parameter? Get(Discipline d, int parameterCategory, int parameterNumber) + { + if (ParameterCategory.CategoriesByDiscipline.TryGetValue(d, out var categories)) + { + var category = categories.Where(c => c.Code == parameterCategory).ToArray(); + if (category.Any() && ParametersByCategory.TryGetValue(category[0], out var parameters)) + { + var parameter = parameters.Where(p => p.Code == parameterNumber).ToArray(); + if (parameter.Any()) + { + return parameter[0]; + } + } + } + + return null; + } + + #region Product Discipline 0: Meteorological products, Parameter Category 0: Temperature + + ///Temperature (K) + public static Parameter Temperature { get; } = new Parameter(ParameterCategory.Temperature, 0, "Temperature", "K"); + + ///Virtual temperature (K) + public static Parameter VirtualTemperature { get; } = + new Parameter(ParameterCategory.Temperature, 1, "Virtual temperature", "K"); + + ///Potential temperature (K) + public static Parameter PotentialTemperature { get; } = + new Parameter(ParameterCategory.Temperature, 2, "Potential temperature", "K"); + + ///Pseudo-adiabatic potential temperature or equivalent potential temperature (K) + public static Parameter PseudoAdiabaticPotentialTemperatureOrEquivalentPotentialTemperature { get; } = + new Parameter(ParameterCategory.Temperature, 3, + "Pseudo-adiabatic potential temperature or equivalent potential temperature", "K"); + + ///Maximum temperature (K) + public static Parameter MaximumTemperature { get; } = + new Parameter(ParameterCategory.Temperature, 4, "Maximum temperature", "K"); + + ///Minimum temperature (K) + public static Parameter MinimumTemperature { get; } = + new Parameter(ParameterCategory.Temperature, 5, "Minimum temperature", "K"); + + ///Dew point temperature (K) + public static Parameter DewPointTemperature { get; } = + new Parameter(ParameterCategory.Temperature, 6, "Dew point temperature", "K"); + + ///Dew point depression (or deficit) (K) + public static Parameter DewPointDepression { get; } = + new Parameter(ParameterCategory.Temperature, 7, "Dew point depression (or deficit)", "K"); + + ///Lapse rate (K m-1) + public static Parameter LapseRate { get; } = new Parameter(ParameterCategory.Temperature, 8, "Lapse rate", "K m-1"); + + ///Temperature anomaly (K) + public static Parameter TemperatureAnomaly { get; } = + new Parameter(ParameterCategory.Temperature, 9, "Temperature anomaly", "K"); + + ///Latent heat net flux (W m-2) + public static Parameter LatentHeatNetFlux { get; } = + new Parameter(ParameterCategory.Temperature, 10, "Latent heat net flux", "W m-2"); + + ///Sensible heat net flux (W m-2) + public static Parameter SensibleHeatNetFlux { get; } = + new Parameter(ParameterCategory.Temperature, 11, "Sensible heat net flux", "W m-2"); + + ///Heat index (K) + public static Parameter HeatIndex { get; } = new Parameter(ParameterCategory.Temperature, 12, "Heat index", "K"); + + ///Wind chill factor (K) + public static Parameter WindChillFactor { get; } = + new Parameter(ParameterCategory.Temperature, 13, "Wind chill factor", "K"); + + ///Minimum dew point depression (K) + public static Parameter MinimumDewPointDepression { get; } = + new Parameter(ParameterCategory.Temperature, 14, "Minimum dew point depression", "K"); + + ///Virtual potential temperature (K) + public static Parameter VirtualPotentialTemperature { get; } = + new Parameter(ParameterCategory.Temperature, 15, "Virtual potential temperature", "K"); + + ///Snow Phase Change Heat Flux (W m-2) + public static Parameter SnowPhaseChangeHeatFlux { get; } = + new Parameter(ParameterCategory.Temperature, 16, "Snow Phase Change Heat Flux", "W m-2"); + + ///Skin Temperature (K) + public static Parameter SkinTemperature { get; } = + new Parameter(ParameterCategory.Temperature, 17, "Skin Temperature", "K"); + + ///Snow Temperature (top of snow) (K) + public static Parameter SnowTemperature { get; } = + new Parameter(ParameterCategory.Temperature, 18, "Snow Temperature (top of snow)", "K"); + + ///Turbulent Transfer Coefficient for Heat (Numeric) + public static Parameter TurbulentTransferCoefficientForHeat { get; } = + new Parameter(ParameterCategory.Temperature, 19, "Turbulent Transfer Coefficient for Heat", "Numeric"); + + ///Turbulent Diffusion Coefficient for Heat (m2s-1) + public static Parameter TurbulentDiffusionCoefficientForHeat { get; } = + new Parameter(ParameterCategory.Temperature, 20, "Turbulent Diffusion Coefficient for Heat", "m2s-1"); + + ///Apparent Temperature (K) + public static Parameter ApparentTemperature { get; } = + new Parameter(ParameterCategory.Temperature, 21, "Apparent Temperature ", "K"); + + ///Temperature Tendency due to Short-Wave Radiation (K s-1) + public static Parameter TemperatureTendencyDueToShortWaveRadiation { get; } = + new Parameter(ParameterCategory.Temperature, 22, "Temperature Tendency due to Short-Wave Radiation", "K s-1"); + + ///Temperature Tendency due to Long-Wave Radiation (K s-1) + public static Parameter TemperatureTendencyDueToLongWaveRadiation { get; } = + new Parameter(ParameterCategory.Temperature, 23, "Temperature Tendency due to Long-Wave Radiation", "K s-1"); + + ///Temperature Tendency due to Short-Wave Radiation,Clear Sky (K s-1) + public static Parameter TemperatureTendencyDueToShortWaveRadiationClearSky { get; } = + new Parameter(ParameterCategory.Temperature, 24, "Temperature Tendency due to Short-Wave Radiation,Clear Sky", "K s-1"); + + ///Temperature Tendency due to Long-Wave Radiation,Clear Sky (K s-1) + public static Parameter TemperatureTendencyDueToLongWaveRadiationClearSky { get; } = + new Parameter(ParameterCategory.Temperature, 25, "Temperature Tendency due to Long-Wave Radiation,Clear Sky", "K s-1"); + + ///Temperature Tendency due to parameterizations (K s-1) + public static Parameter TemperatureTendencyDueToParameterizations { get; } = + new Parameter(ParameterCategory.Temperature, 26, "Temperature Tendency due to parameterizations", "K s-1"); + + ///Wet Bulb Temperature (K) + public static Parameter WetBulbTemperature { get; } = + new Parameter(ParameterCategory.Temperature, 27, "Wet Bulb Temperature", "K"); + + ///Unbalanced Component of Temperature (K) + public static Parameter UnbalancedComponentOfTemperature { get; } = + new Parameter(ParameterCategory.Temperature, 28, "Unbalanced Component of Temperature", "K"); + + ///Temperature Advection (K s-1) + public static Parameter TemperatureAdvection { get; } = + new Parameter(ParameterCategory.Temperature, 29, "Temperature Advection", "K s-1"); + + #endregion + + #region Product Discipline 0: Meteorological products, Parameter Category 1: Moisture + + ///Specific humidity (kg kg-1) + public static Parameter SpecificHumidity { get; } = + new Parameter(ParameterCategory.Moisture, 0, "Specific humidity", "kg kg-1"); + + ///Relative humidity (%) + public static Parameter RelativeHumidity { get; } = new Parameter(ParameterCategory.Moisture, 1, "Relative humidity", "%"); + + ///Humidity mixing ratio (kg kg-1) + public static Parameter HumidityMixingRatio { get; } = + new Parameter(ParameterCategory.Moisture, 2, "Humidity mixing ratio", "kg kg-1"); + + ///Precipitable water (kg m-2) + public static Parameter PrecipitableWater { get; } = + new Parameter(ParameterCategory.Moisture, 3, "Precipitable water", "kg m-2"); + + ///Vapor pressure (Pa) + public static Parameter VaporPressure { get; } = new Parameter(ParameterCategory.Moisture, 4, "Vapor pressure", "Pa"); + + ///Saturation deficit (Pa) + public static Parameter SaturationDeficit { get; } = + new Parameter(ParameterCategory.Moisture, 5, "Saturation deficit", "Pa"); + + ///Evaporation (kg m-2) + public static Parameter Evaporation { get; } = new Parameter(ParameterCategory.Moisture, 6, "Evaporation", "kg m-2"); + + ///Precipitation rate (kg m-2 s-1) + public static Parameter PrecipitationRate { get; } = + new Parameter(ParameterCategory.Moisture, 7, "Precipitation rate", "kg m-2 s-1"); + + ///Total precipitation (kg m-2) + public static Parameter TotalPrecipitation { get; } = + new Parameter(ParameterCategory.Moisture, 8, "Total precipitation", "kg m-2"); + + ///Large scale precipitation (non-convective) (kg m-2) + public static Parameter LargeScalePrecipitationNonConvective { get; } = new Parameter(ParameterCategory.Moisture, 9, + "Large scale precipitation (non-convective)", "kg m-2"); + + ///Convective precipitation (kg m-2) + public static Parameter ConvectivePrecipitation { get; } = + new Parameter(ParameterCategory.Moisture, 10, "Convective precipitation", "kg m-2"); + + ///Snow depth (m) + public static Parameter SnowDepth { get; } = new Parameter(ParameterCategory.Moisture, 11, "Snow depth", "m"); + + ///Snowfall rate water equivalent (kg m-2 s-1) + public static Parameter SnowfallRateWaterEquivalent { get; } = + new Parameter(ParameterCategory.Moisture, 12, "Snowfall rate water equivalent", "kg m-2 s-1"); + + ///Water equivalent of accumulated snow depth (kg m-2) + public static Parameter WaterEquivalentOfAccumulatedSnowDepth { get; } = new Parameter(ParameterCategory.Moisture, 13, + "Water equivalent of accumulated snow depth", "kg m-2"); + + ///Convective snow (kg m-2) + public static Parameter ConvectiveSnow { get; } = + new Parameter(ParameterCategory.Moisture, 14, "Convective snow", "kg m-2"); + + ///Large scale snow (kg m-2) + public static Parameter LargeScaleSnow { get; } = + new Parameter(ParameterCategory.Moisture, 15, "Large scale snow", "kg m-2"); + + ///Snow melt (kg m-2) + public static Parameter SnowMelt { get; } = new Parameter(ParameterCategory.Moisture, 16, "Snow melt", "kg m-2"); + + ///Snow age (day) + public static Parameter SnowAge { get; } = new Parameter(ParameterCategory.Moisture, 17, "Snow age", "day"); + + ///Absolute humidity (kg m-3) + public static Parameter AbsoluteHumidity { get; } = + new Parameter(ParameterCategory.Moisture, 18, "Absolute humidity", "kg m-3"); + + ///Precipitation type (Code table (4.201)) + public static Parameter PrecipitationType { get; } = + new Parameter(ParameterCategory.Moisture, 19, "Precipitation type", "Code table (4.201)"); + + ///Integrated liquid water (kg m-2) + public static Parameter IntegratedLiquidWater { get; } = + new Parameter(ParameterCategory.Moisture, 20, "Integrated liquid water", "kg m-2"); + + ///Condensate (kg kg-1) + public static Parameter Condensate { get; } = new Parameter(ParameterCategory.Moisture, 21, "Condensate", "kg kg-1"); + + ///Cloud mixing ratio (kg kg-1) + public static Parameter CloudMixingRatio { get; } = + new Parameter(ParameterCategory.Moisture, 22, "Cloud mixing ratio", "kg kg-1"); + + ///Ice water mixing ratio (kg kg-1) + public static Parameter IceWaterMixingRatio { get; } = + new Parameter(ParameterCategory.Moisture, 23, "Ice water mixing ratio", "kg kg-1"); + + ///Rain mixing ratio (kg kg-1) + public static Parameter RainMixingRatio { get; } = + new Parameter(ParameterCategory.Moisture, 24, "Rain mixing ratio", "kg kg-1"); + + ///Snow mixing ratio (kg kg-1) + public static Parameter SnowMixingRatio { get; } = + new Parameter(ParameterCategory.Moisture, 25, "Snow mixing ratio", "kg kg-1"); + + ///Horizontal moisture convergence (kg kg-1 s-1) + public static Parameter HorizontalMoistureConvergence { get; } = new Parameter(ParameterCategory.Moisture, 26, + "Horizontal moisture convergence", "kg kg-1 s-1"); + + ///Maximum relative humidity (%) + public static Parameter MaximumRelativeHumidity { get; } = + new Parameter(ParameterCategory.Moisture, 27, "Maximum relative humidity", "%"); + + ///Maximum absolute humidity (kg m-3) + public static Parameter MaximumAbsoluteHumidity { get; } = + new Parameter(ParameterCategory.Moisture, 28, "Maximum absolute humidity", "kg m-3"); + + ///Total snowfall (m) + public static Parameter TotalSnowfall { get; } = new Parameter(ParameterCategory.Moisture, 29, "Total snowfall", "m"); + + ///Precipitable water category (Code table (4.202)) + public static Parameter PrecipitableWaterCategory { get; } = new Parameter(ParameterCategory.Moisture, 30, + "Precipitable water category", "Code table (4.202)"); + + ///Hail (m) + public static Parameter Hail { get; } = new Parameter(ParameterCategory.Moisture, 31, "Hail", "m"); + + ///Graupel (snow pellets) (kg kg-1) + public static Parameter Graupel { get; } = + new Parameter(ParameterCategory.Moisture, 32, "Graupel (snow pellets)", "kg kg-1"); + + ///Categorical Rain (Code table 4.222) + public static Parameter CategoricalRain { get; } = + new Parameter(ParameterCategory.Moisture, 33, "Categorical Rain", ""); + + ///Categorical Freezing Rain (Code table 4.222) + public static Parameter CategoricalFreezingRain { get; } = + new Parameter(ParameterCategory.Moisture, 34, "Categorical Freezing Rain", ""); + + ///Categorical Ice Pellets (Code table 4.222) + public static Parameter CategoricalIcePellets { get; } = + new Parameter(ParameterCategory.Moisture, 35, "Categorical Ice Pellets", ""); + + ///Categorical Snow (Code table 4.222) + public static Parameter CategoricalSnow { get; } = + new Parameter(ParameterCategory.Moisture, 36, "Categorical Snow", ""); + + ///Convective Precipitation Rate (kg m-2 s-1) + public static Parameter ConvectivePrecipitationRate { get; } = + new Parameter(ParameterCategory.Moisture, 37, "Convective Precipitation Rate", "kg m-2 s-1"); + + ///Horizontal Moisture Divergence (kg kg-1 s-1) + public static Parameter HorizontalMoistureDivergence { get; } = + new Parameter(ParameterCategory.Moisture, 38, "Horizontal Moisture Divergence", "kg kg-1 s-1"); + + ///Percent frozen precipitation (%) + public static Parameter PercentFrozenPrecipitation { get; } = + new Parameter(ParameterCategory.Moisture, 39, "Percent frozen precipitation", "%"); + + ///Potential Evaporation (kg m-2) + public static Parameter PotentialEvaporation { get; } = + new Parameter(ParameterCategory.Moisture, 40, "Potential Evaporation", "kg m-2"); + + ///Potential Evaporation Rate (W m-2) + public static Parameter PotentialEvaporationRate { get; } = + new Parameter(ParameterCategory.Moisture, 41, "Potential Evaporation Rate", "W m-2"); + + ///Snow Cover (%) + public static Parameter SnowCover { get; } = + new Parameter(ParameterCategory.Moisture, 42, "Snow Cover", "%"); + + ///Rain Fraction of Total Cloud Water (Proportion) + public static Parameter RainFractionOfTotalCloudWater { get; } = + new Parameter(ParameterCategory.Moisture, 43, "Rain Fraction of Total Cloud Water", "Proportion"); + + ///Rime Factor (Numeric) + public static Parameter RimeFactor { get; } = + new Parameter(ParameterCategory.Moisture, 44, "Rime Factor", "Numeric"); - ///Skin Temperature (K) - public static Parameter SkinTemperature { get; } = - new Parameter(ParameterCategory.Temperature, 17, "Skin Temperature", "K"); + ///Total Column Integrated Rain (kg m-2) + public static Parameter TotalColumnIntegratedRain { get; } = + new Parameter(ParameterCategory.Moisture, 45, "Total Column Integrated Rain", "kg m-2"); - ///Snow Temperature (top of snow) (K) - public static Parameter SnowTemperature { get; } = - new Parameter(ParameterCategory.Temperature, 18, "Snow Temperature (top of snow)", "K"); + ///Total Column Integrated Snow (kg m-2) + public static Parameter TotalColumnIntegratedSnow { get; } = + new Parameter(ParameterCategory.Moisture, 46, "Total Column Integrated Snow", "kg m-2"); - ///Turbulent Transfer Coefficient for Heat (Numeric) - public static Parameter TurbulentTransferCoefficientForHeat { get; } = - new Parameter(ParameterCategory.Temperature, 19, "Turbulent Transfer Coefficient for Heat", "Numeric"); + ///Large Scale Water Precipitation (Non-Convective) (kg m-2) + public static Parameter LargeScaleWaterPrecipitation { get; } = + new Parameter(ParameterCategory.Moisture, 47, "Large Scale Water Precipitation (Non-Convective) ", "kg m-2"); - ///Turbulent Diffusion Coefficient for Heat (m2s-1) - public static Parameter TurbulentDiffusionCoefficientForHeat { get; } = - new Parameter(ParameterCategory.Temperature, 20, "Turbulent Diffusion Coefficient for Heat", "m2s-1"); + ///Convective Water Precipitation (kg m-2) + public static Parameter ConvectiveWaterPrecipitation { get; } = + new Parameter(ParameterCategory.Moisture, 48, "Convective Water Precipitation ", "kg m-2"); - ///Apparent Temperature (K) - public static Parameter ApparentTemperature { get; } = - new Parameter(ParameterCategory.Temperature, 21, "Apparent Temperature ", "K"); + ///Total Water Precipitation (kg m-2) + public static Parameter TotalWaterPrecipitation { get; } = + new Parameter(ParameterCategory.Moisture, 49, "Total Water Precipitation ", "kg m-2"); - ///Temperature Tendency due to Short-Wave Radiation (K s-1) - public static Parameter TemperatureTendencyDueToShortWaveRadiation { get; } = - new Parameter(ParameterCategory.Temperature, 22, "Temperature Tendency due to Short-Wave Radiation", "K s-1"); + ///Total Snow Precipitation (kg m-2) + public static Parameter TotalSnowPrecipitation { get; } = + new Parameter(ParameterCategory.Moisture, 50, "Total Snow Precipitation ", "kg m-2"); - ///Temperature Tendency due to Long-Wave Radiation (K s-1) - public static Parameter TemperatureTendencyDueToLongWaveRadiation { get; } = - new Parameter(ParameterCategory.Temperature, 23, "Temperature Tendency due to Long-Wave Radiation", "K s-1"); + ///Total Column Water(Vertically integrated total water (vapour+cloud water/ice) (kg m-2) + public static Parameter TotalColumnWater { get; } = + new Parameter(ParameterCategory.Moisture, 51, "Total Column Water(Vertically integrated total water (vapour+cloud water/ice)", "kg m-2"); - ///Temperature Tendency due to Short-Wave Radiation,Clear Sky (K s-1) - public static Parameter TemperatureTendencyDueToShortWaveRadiationClearSky { get; } = - new Parameter(ParameterCategory.Temperature, 24, "Temperature Tendency due to Short-Wave Radiation,Clear Sky", "K s-1"); + ///Total Precipitation Rate (kg m-2 s-1) + public static Parameter TotalPrecipitationRate { get; } = + new Parameter(ParameterCategory.Moisture, 52, "Total Precipitation Rate ", "kg m-2 s-1"); - ///Temperature Tendency due to Long-Wave Radiation,Clear Sky (K s-1) - public static Parameter TemperatureTendencyDueToLongWaveRadiationClearSky { get; } = - new Parameter(ParameterCategory.Temperature, 25, "Temperature Tendency due to Long-Wave Radiation,Clear Sky", "K s-1"); + ///Total Snowfall Rate Water Equivalent (kg m-2 s-1) + public static Parameter TotalSnowfallRateWaterEquivalent { get; } = + new Parameter(ParameterCategory.Moisture, 53, "Total Snowfall Rate Water Equivalent ", "kg m-2 s-1"); - ///Temperature Tendency due to parameterizations (K s-1) - public static Parameter TemperatureTendencyDueToParameterizations { get; } = - new Parameter(ParameterCategory.Temperature, 26, "Temperature Tendency due to parameterizations", "K s-1"); + ///Large Scale Precipitation Rate (kg m-2 s-1) + public static Parameter LargeScalePrecipitationRate { get; } = + new Parameter(ParameterCategory.Moisture, 54, "Large Scale Precipitation Rate", "kg m-2 s-1"); - ///Wet Bulb Temperature (K) - public static Parameter WetBulbTemperature { get; } = - new Parameter(ParameterCategory.Temperature, 27, "Wet Bulb Temperature", "K"); + ///Convective Snowfall Rate Water Equivalent (kg m-2 s-1) + public static Parameter ConvectiveSnowfallRateWaterEquivalent { get; } = + new Parameter(ParameterCategory.Moisture, 55, "Convective Snowfall Rate Water Equivalent", "kg m-2 s-1"); - ///Unbalanced Component of Temperature (K) - public static Parameter UnbalancedComponentOfTemperature { get; } = - new Parameter(ParameterCategory.Temperature, 28, "Unbalanced Component of Temperature", "K"); + ///Large Scale Snowfall Rate Water Equivalent (kg m-2 s-1) + public static Parameter LargeScaleSnowfallRateWaterEquivalent { get; } = + new Parameter(ParameterCategory.Moisture, 56, "Large Scale Snowfall Rate Water Equivalent", "kg m-2 s-1"); - ///Temperature Advection (K s-1) - public static Parameter TemperatureAdvection { get; } = - new Parameter(ParameterCategory.Temperature, 29, "Temperature Advection", "K s-1"); + ///Total Snowfall Rate (m s-1) + public static Parameter TotalSnowfallRate { get; } = + new Parameter(ParameterCategory.Moisture, 57, "Total Snowfall Rate", "m s-1"); - #endregion + ///Convective Snowfall Rate (m s-1) + public static Parameter ConvectiveSnowfallRate { get; } = + new Parameter(ParameterCategory.Moisture, 58, "Convective Snowfall Rate", "m s-1"); - #region Product Discipline 0: Meteorological products, Parameter Category 1: Moisture + ///Large Scale Snowfall Rate (m s-1) + public static Parameter LargeScaleSnowfallRate { get; } = + new Parameter(ParameterCategory.Moisture, 59, "Large Scale Snowfall Rate", "m s-1"); - ///Specific humidity (kg kg-1) - public static Parameter SpecificHumidity { get; } = - new Parameter(ParameterCategory.Moisture, 0, "Specific humidity", "kg kg-1"); + ///Snow Depth Water Equivalent (kg m-2) + public static Parameter SnowDepthWaterEquivalent { get; } = + new Parameter(ParameterCategory.Moisture, 60, "Snow Depth Water Equivalent", "kg m-2"); - ///Relative humidity (%) - public static Parameter RelativeHumidity { get; } = new Parameter(ParameterCategory.Moisture, 1, "Relative humidity", "%"); + ///Snow Density (kg m-3) + public static Parameter SnowDensity { get; } = + new Parameter(ParameterCategory.Moisture, 61, "Snow Density", "kg m-3"); - ///Humidity mixing ratio (kg kg-1) - public static Parameter HumidityMixingRatio { get; } = - new Parameter(ParameterCategory.Moisture, 2, "Humidity mixing ratio", "kg kg-1"); + ///Snow Evaporation (kg m-2) + public static Parameter SnowEvaporation { get; } = + new Parameter(ParameterCategory.Moisture, 62, "Snow Evaporation", "kg m-2"); - ///Precipitable water (kg m-2) - public static Parameter PrecipitableWater { get; } = - new Parameter(ParameterCategory.Moisture, 3, "Precipitable water", "kg m-2"); + ///Total Column Integrated Water Vapour (kg m-2) + public static Parameter TotalColumnIntegratedWaterVapour { get; } = + new Parameter(ParameterCategory.Moisture, 64, "Total Column Integrated Water Vapour", "kg m-2"); - ///Vapor pressure (Pa) - public static Parameter VaporPressure { get; } = new Parameter(ParameterCategory.Moisture, 4, "Vapor pressure", "Pa"); + ///Rain Precipitation Rate (kg m-2 s-1) + public static Parameter RainPrecipitationRate { get; } = + new Parameter(ParameterCategory.Moisture, 65, "Rain Precipitation Rate", "kg m-2 s-1"); - ///Saturation deficit (Pa) - public static Parameter SaturationDeficit { get; } = - new Parameter(ParameterCategory.Moisture, 5, "Saturation deficit", "Pa"); + ///Snow Precipitation Rate (kg m-2 s-1) + public static Parameter SnowPrecipitationRate { get; } = + new Parameter(ParameterCategory.Moisture, 66, "Snow Precipitation Rate", "kg m-2 s-1"); - ///Evaporation (kg m-2) - public static Parameter Evaporation { get; } = new Parameter(ParameterCategory.Moisture, 6, "Evaporation", "kg m-2"); + ///Freezing Rain Precipitation Rate (kg m-2 s-1) + public static Parameter FreezingRainPrecipitationRate { get; } = + new Parameter(ParameterCategory.Moisture, 67, "Freezing Rain Precipitation Rate", "kg m-2 s-1"); - ///Precipitation rate (kg m-2 s-1) - public static Parameter PrecipitationRate { get; } = - new Parameter(ParameterCategory.Moisture, 7, "Precipitation rate", "kg m-2 s-1"); + ///Ice Pellets Precipitation Rate (kg m-2 s-1) + public static Parameter IcePelletsPrecipitationRate { get; } = + new Parameter(ParameterCategory.Moisture, 68, "Ice Pellets Precipitation Rate", "kg m-2 s-1"); - ///Total precipitation (kg m-2) - public static Parameter TotalPrecipitation { get; } = - new Parameter(ParameterCategory.Moisture, 8, "Total precipitation", "kg m-2"); + ///Total Column Integrate Cloud Water (kg m-2) + public static Parameter TotalColumnIntegrateCloudWater { get; } = + new Parameter(ParameterCategory.Moisture, 69, "Total Column Integrate Cloud Water", "kg m-2"); - ///Large scale precipitation (non-convective) (kg m-2) - public static Parameter LargeScalePrecipitationNonConvective { get; } = new Parameter(ParameterCategory.Moisture, 9, - "Large scale precipitation (non-convective)", "kg m-2"); + ///Total Column Integrate Cloud Ice (kg m-2) + public static Parameter TotalColumnIntegrateCloudIce { get; } = + new Parameter(ParameterCategory.Moisture, 70, "Total Column Integrate Cloud Ice", "kg m-2"); - ///Convective precipitation (kg m-2) - public static Parameter ConvectivePrecipitation { get; } = - new Parameter(ParameterCategory.Moisture, 10, "Convective precipitation", "kg m-2"); + ///Hail Mixing Ratio (kg kg-1) + public static Parameter HailMixingRatio { get; } = + new Parameter(ParameterCategory.Moisture, 71, "Hail Mixing Ratio", "kg kg-1"); - ///Snow depth (m) - public static Parameter SnowDepth { get; } = new Parameter(ParameterCategory.Moisture, 11, "Snow depth", "m"); + ///Total Column Integrate Hail (kg m-2) + public static Parameter TotalColumnIntegrateHail { get; } = + new Parameter(ParameterCategory.Moisture, 72, "Total Column Integrate Hail", "kg m-2"); - ///Snowfall rate water equivalent (kg m-2 s-1) - public static Parameter SnowfallRateWaterEquivalent { get; } = - new Parameter(ParameterCategory.Moisture, 12, "Snowfall rate water equivalent", "kg m-2 s-1"); + ///Hail Prepitation Rate (kg m-2 s-1) + public static Parameter HailPrepitationRate { get; } = + new Parameter(ParameterCategory.Moisture, 73, "Hail Prepitation Rate", "kg m-2 s-1"); - ///Water equivalent of accumulated snow depth (kg m-2) - public static Parameter WaterEquivalentOfAccumulatedSnowDepth { get; } = new Parameter(ParameterCategory.Moisture, 13, - "Water equivalent of accumulated snow depth", "kg m-2"); + ///Total Column Integrate Graupel (kg m-2) + public static Parameter TotalColumnIntegrateGraupel { get; } = + new Parameter(ParameterCategory.Moisture, 74, "Total Column Integrate Graupel", "kg m-2"); - ///Convective snow (kg m-2) - public static Parameter ConvectiveSnow { get; } = - new Parameter(ParameterCategory.Moisture, 14, "Convective snow", "kg m-2"); + ///Graupel (Snow Pellets) Prepitation Rate (kg m-2 s-1) + public static Parameter GraupelPrecipitationRate { get; } = + new Parameter(ParameterCategory.Moisture, 75, "Graupel (Snow Pellets) Prepitation Rate", "kg m-2 s-1"); - ///Large scale snow (kg m-2) - public static Parameter LargeScaleSnow { get; } = - new Parameter(ParameterCategory.Moisture, 15, "Large scale snow", "kg m-2"); + ///Convective Rain Rate (kg m-2 s-1) + public static Parameter ConvectiveRainRate { get; } = + new Parameter(ParameterCategory.Moisture, 76, "Convective Rain Rate", "kg m-2 s-1"); - ///Snow melt (kg m-2) - public static Parameter SnowMelt { get; } = new Parameter(ParameterCategory.Moisture, 16, "Snow melt", "kg m-2"); + ///Large Scale Rain Rate (kg m-2 s-1) + public static Parameter LargeScaleRainRate { get; } = + new Parameter(ParameterCategory.Moisture, 77, "Large Scale Rain Rate", "kg m-2 s-1"); - ///Snow age (day) - public static Parameter SnowAge { get; } = new Parameter(ParameterCategory.Moisture, 17, "Snow age", "day"); + ///Total Column Integrate Water (Allcomponents including precipitation) (kg m-2) + public static Parameter TotalColumnIntegrateWater { get; } = + new Parameter(ParameterCategory.Moisture, 78, "Total Column Integrate Water (Allcomponents including precipitation)", "kg m-2"); - ///Absolute humidity (kg m-3) - public static Parameter AbsoluteHumidity { get; } = - new Parameter(ParameterCategory.Moisture, 18, "Absolute humidity", "kg m-3"); + ///Evaporation Rate (kg m-2 s-1) + public static Parameter EvaporationRate { get; } = + new Parameter(ParameterCategory.Moisture, 79, "Evaporation Rate", "kg m-2 s-1"); - ///Precipitation type (Code table (4.201)) - public static Parameter PrecipitationType { get; } = - new Parameter(ParameterCategory.Moisture, 19, "Precipitation type", "Code table (4.201)"); + ///Total Condensate (kg kg-1) + public static Parameter TotalCondensate { get; } = + new Parameter(ParameterCategory.Moisture, 80, "Total Condensate", "kg kg-1"); - ///Integrated liquid water (kg m-2) - public static Parameter IntegratedLiquidWater { get; } = - new Parameter(ParameterCategory.Moisture, 20, "Integrated liquid water", "kg m-2"); + ///Total Column-Integrate Condensate (kg m-2) + public static Parameter TotalColumnIntegrateCondensate { get; } = + new Parameter(ParameterCategory.Moisture, 81, "Total Column-Integrate Condensate", "kg m-2"); - ///Condensate (kg kg-1) - public static Parameter Condensate { get; } = new Parameter(ParameterCategory.Moisture, 21, "Condensate", "kg kg-1"); + ///Cloud Ice Mixing Ratio (kg kg-1) + public static Parameter CloudIceMixingRatio { get; } = + new Parameter(ParameterCategory.Moisture, 82, "Cloud Ice Mixing Ratio", "kg kg-1"); - ///Cloud mixing ratio (kg kg-1) - public static Parameter CloudMixingRatio { get; } = - new Parameter(ParameterCategory.Moisture, 22, "Cloud mixing ratio", "kg kg-1"); + ///Specific Cloud Liquid Water Content (kg kg-1) + public static Parameter SpecificCloudLiquidWaterContent { get; } = + new Parameter(ParameterCategory.Moisture, 83, "Specific Cloud Liquid Water Content", "kg kg-1"); - ///Ice water mixing ratio (kg kg-1) - public static Parameter IceWaterMixingRatio { get; } = - new Parameter(ParameterCategory.Moisture, 23, "Ice water mixing ratio", "kg kg-1"); + ///Specific Cloud Ice Water Content (kg kg-1) + public static Parameter SpecificCloudIceWaterContent { get; } = + new Parameter(ParameterCategory.Moisture, 84, "Specific Cloud Ice Water Content", "kg kg-1"); - ///Rain mixing ratio (kg kg-1) - public static Parameter RainMixingRatio { get; } = - new Parameter(ParameterCategory.Moisture, 24, "Rain mixing ratio", "kg kg-1"); + ///Specific Rain Water Content (kg kg-1) + public static Parameter SpecificRainWaterContent { get; } = + new Parameter(ParameterCategory.Moisture, 85, "Specific Rain Water Content", "kg kg-1"); - ///Snow mixing ratio (kg kg-1) - public static Parameter SnowMixingRatio { get; } = - new Parameter(ParameterCategory.Moisture, 25, "Snow mixing ratio", "kg kg-1"); + ///Specific Snow Water Content (kg kg-1) + public static Parameter SpecificSnowWaterContent { get; } = + new Parameter(ParameterCategory.Moisture, 86, "Specific Snow Water Content", "kg kg-1"); - ///Horizontal moisture convergence (kg kg-1 s-1) - public static Parameter HorizontalMoistureConvergence { get; } = new Parameter(ParameterCategory.Moisture, 26, - "Horizontal moisture convergence", "kg kg-1 s-1"); + ///Stratiform Precipitation Rate (kg m-2 s-1) + public static Parameter StratiformPrecipitationRate { get; } = + new Parameter(ParameterCategory.Moisture, 87, "Stratiform Precipitation Rate", "kg m-2 s-1"); - ///Maximum relative humidity (%) - public static Parameter MaximumRelativeHumidity { get; } = - new Parameter(ParameterCategory.Moisture, 27, "Maximum relative humidity", "%"); + ///Categorical Convective Precipitation (Code table 4.222) + public static Parameter CategoricalConvectivePrecipitation { get; } = + new Parameter(ParameterCategory.Moisture, 88, "Categorical Convective Precipitation", ""); - ///Maximum absolute humidity (kg m-3) - public static Parameter MaximumAbsoluteHumidity { get; } = - new Parameter(ParameterCategory.Moisture, 28, "Maximum absolute humidity", "kg m-3"); + ///Total Kinematic Moisture Flux (kg kg-1 m s-1) + public static Parameter TotalKinematicMoistureFlux { get; } = + new Parameter(ParameterCategory.Moisture, 90, "Total Kinematic Moisture Flux", "kg kg-1 m s-1"); - ///Total snowfall (m) - public static Parameter TotalSnowfall { get; } = new Parameter(ParameterCategory.Moisture, 29, "Total snowfall", "m"); + ///U-component (zonal) Kinematic Moisture Flux (kg kg-1 m s-1) + public static Parameter Ucomponent { get; } = + new Parameter(ParameterCategory.Moisture, 91, "U-component (zonal) Kinematic Moisture Flux", "kg kg-1 m s-1"); - ///Precipitable water category (Code table (4.202)) - public static Parameter PrecipitableWaterCategory { get; } = new Parameter(ParameterCategory.Moisture, 30, - "Precipitable water category", "Code table (4.202)"); + ///V-component (meridional) Kinematic Moisture Flux (kg kg-1 m s-1) + public static Parameter Vcomponent { get; } = + new Parameter(ParameterCategory.Moisture, 92, "V-component (meridional) Kinematic Moisture Flux", "kg kg-1 m s-1"); - ///Hail (m) - public static Parameter Hail { get; } = new Parameter(ParameterCategory.Moisture, 31, "Hail", "m"); + ///Relative Humidity With Respect to Water (%) + public static Parameter RelativeHumidityWithRespectToWater { get; } = + new Parameter(ParameterCategory.Moisture, 93, "Relative Humidity With Respect to Water", "%"); - ///Graupel (snow pellets) (kg kg-1) - public static Parameter Graupel { get; } = - new Parameter(ParameterCategory.Moisture, 32, "Graupel (snow pellets)", "kg kg-1"); + ///Relative Humidity With Respect to Ice (%) + public static Parameter RelativeHumidityWithRespectToIce { get; } = + new Parameter(ParameterCategory.Moisture, 94, "Relative Humidity With Respect to Ice", "%"); - ///Categorical Rain (Code table 4.222) - public static Parameter CategoricalRain { get; } = - new Parameter(ParameterCategory.Moisture, 33, "Categorical Rain", ""); + ///Freezing or Frozen Precipitation Rate (kg m-2 s-1) + public static Parameter FreezingOrFrozenPrecipitationRate { get; } = + new Parameter(ParameterCategory.Moisture, 95, "Freezing or Frozen Precipitation Rate", "kg m-2 s-1"); - ///Categorical Freezing Rain (Code table 4.222) - public static Parameter CategoricalFreezingRain { get; } = - new Parameter(ParameterCategory.Moisture, 34, "Categorical Freezing Rain", ""); + ///Mass Density of Rain (kg m-3) + public static Parameter MassDensityOfRain { get; } = + new Parameter(ParameterCategory.Moisture, 96, "Mass Density of Rain", "kg m-3"); - ///Categorical Ice Pellets (Code table 4.222) - public static Parameter CategoricalIcePellets { get; } = - new Parameter(ParameterCategory.Moisture, 35, "Categorical Ice Pellets", ""); + ///Mass Density of Snow (kg m-3) + public static Parameter MassDensityOfSnow { get; } = + new Parameter(ParameterCategory.Moisture, 97, "Mass Density of Snow", "kg m-3"); - ///Categorical Snow (Code table 4.222) - public static Parameter CategoricalSnow { get; } = - new Parameter(ParameterCategory.Moisture, 36, "Categorical Snow", ""); + ///Mass Density of Graupel (kg m-3) + public static Parameter MassDensityOfGraupel { get; } = + new Parameter(ParameterCategory.Moisture, 98, "Mass Density of Graupel", "kg m-3"); - ///Convective Precipitation Rate (kg m-2 s-1) - public static Parameter ConvectivePrecipitationRate { get; } = - new Parameter(ParameterCategory.Moisture, 37, "Convective Precipitation Rate", "kg m-2 s-1"); + ///Mass Density of Hail (kg m-3) + public static Parameter MassDensityOfHail { get; } = + new Parameter(ParameterCategory.Moisture, 99, "Mass Density of Hail", "kg m-3"); - ///Horizontal Moisture Divergence (kg kg-1 s-1) - public static Parameter HorizontalMoistureDivergence { get; } = - new Parameter(ParameterCategory.Moisture, 38, "Horizontal Moisture Divergence", "kg kg-1 s-1"); + ///Specific Number Concentration of Rain (kg-1) + public static Parameter SpecificNumberConcentrationOfRain { get; } = + new Parameter(ParameterCategory.Moisture, 100, "Specific Number Concentration of Rain", "kg-1"); - ///Percent frozen precipitation (%) - public static Parameter PercentFrozenPrecipitation { get; } = - new Parameter(ParameterCategory.Moisture, 39, "Percent frozen precipitation", "%"); + ///Specific Number Concentration of Snow (kg-1) + public static Parameter SpecificNumberConcentrationOfSnow { get; } = + new Parameter(ParameterCategory.Moisture, 101, "Specific Number Concentration of Snow", "kg-1"); - ///Potential Evaporation (kg m-2) - public static Parameter PotentialEvaporation { get; } = - new Parameter(ParameterCategory.Moisture, 40, "Potential Evaporation", "kg m-2"); + ///Specific Number Concentration of Graupel (kg-1) + public static Parameter SpecificNumberConcentrationOfGraupel { get; } = + new Parameter(ParameterCategory.Moisture, 102, "Specific Number Concentration of Graupel", "kg-1"); - ///Potential Evaporation Rate (W m-2) - public static Parameter PotentialEvaporationRate { get; } = - new Parameter(ParameterCategory.Moisture, 41, "Potential Evaporation Rate", "W m-2"); + ///Specific Number Concentration of Hail (kg-1) + public static Parameter SpecificNumberConcentrationOfHail { get; } = + new Parameter(ParameterCategory.Moisture, 103, "Specific Number Concentration of Hail", "kg-1"); - ///Snow Cover (%) - public static Parameter SnowCover { get; } = - new Parameter(ParameterCategory.Moisture, 42, "Snow Cover", "%"); + ///Number Density of Rain (m-3) + public static Parameter NumberDensityOfRain { get; } = + new Parameter(ParameterCategory.Moisture, 104, "Number Density of Rain", "m-3"); - ///Rain Fraction of Total Cloud Water (Proportion) - public static Parameter RainFractionOfTotalCloudWater { get; } = - new Parameter(ParameterCategory.Moisture, 43, "Rain Fraction of Total Cloud Water", "Proportion"); + ///Number Density of Snow (m-3) + public static Parameter NumberDensityOfSnow { get; } = + new Parameter(ParameterCategory.Moisture, 105, "Number Density of Snow", "m-3"); - ///Rime Factor (Numeric) - public static Parameter RimeFactor { get; } = - new Parameter(ParameterCategory.Moisture, 44, "Rime Factor", "Numeric"); + ///Number Density of Graupel (m-3) + public static Parameter NumberDensityOfGraupel { get; } = + new Parameter(ParameterCategory.Moisture, 106, "Number Density of Graupel", "m-3"); - ///Total Column Integrated Rain (kg m-2) - public static Parameter TotalColumnIntegratedRain { get; } = - new Parameter(ParameterCategory.Moisture, 45, "Total Column Integrated Rain", "kg m-2"); + ///Number Density of Hail (m-3) + public static Parameter NumberDensityOfHail { get; } = + new Parameter(ParameterCategory.Moisture, 107, "Number Density of Hail", "m-3"); - ///Total Column Integrated Snow (kg m-2) - public static Parameter TotalColumnIntegratedSnow { get; } = - new Parameter(ParameterCategory.Moisture, 46, "Total Column Integrated Snow", "kg m-2"); + ///Specific Humidity Tendency due to Parameterizations (kg kg-1 s-1) + public static Parameter SpecificHumidityTendencyDueToParameterizations { get; } = + new Parameter(ParameterCategory.Moisture, 108, "Specific Humidity Tendency due to Parameterizations", "kg kg-1 s-1"); - ///Large Scale Water Precipitation (Non-Convective) (kg m-2) - public static Parameter LargeScaleWaterPrecipitation { get; } = - new Parameter(ParameterCategory.Moisture, 47, "Large Scale Water Precipitation (Non-Convective) ", "kg m-2"); + ///Mass Density of Liquid Water Coating on Hail Expressed as Mass of Liquid Water per Unit Volume of Air (kg m-3) + public static Parameter MassDensityOfLiquidWaterCoatingOnHail { get; } = + new Parameter(ParameterCategory.Moisture, 109, "Mass Density of Liquid Water Coating on Hail Expressed as Mass of Liquid Water per Unit Volume of Air", "kg m-3"); - ///Convective Water Precipitation (kg m-2) - public static Parameter ConvectiveWaterPrecipitation { get; } = - new Parameter(ParameterCategory.Moisture, 48, "Convective Water Precipitation ", "kg m-2"); + ///Specific Mass of Liquid Water Coating on HailExpressed as Mass of Liquid Water per Unit Mass of Moist Air (kg kg-1) + public static Parameter SpecificMassOfLiquidWaterCoatingOnHail { get; } = + new Parameter(ParameterCategory.Moisture, 110, "Specific Mass of Liquid Water Coating on HailExpressed as Mass of Liquid Water per Unit Mass of Moist Air", "kg kg-1"); - ///Total Water Precipitation (kg m-2) - public static Parameter TotalWaterPrecipitation { get; } = - new Parameter(ParameterCategory.Moisture, 49, "Total Water Precipitation ", "kg m-2"); + ///Mass Mixing Ratio of Liquid Water Coating on Hail Expressed as Mass of Liquid Water per Unit Mass of Dry Air (kg kg-1) + public static Parameter MassMixingRatioOfLiquidWaterCoatingOnHail { get; } = + new Parameter(ParameterCategory.Moisture, 111, "Mass Mixing Ratio of Liquid Water Coating on Hail Expressed as Mass of Liquid Water per Unit Mass of Dry Air", "kg kg-1"); - ///Total Snow Precipitation (kg m-2) - public static Parameter TotalSnowPrecipitation { get; } = - new Parameter(ParameterCategory.Moisture, 50, "Total Snow Precipitation ", "kg m-2"); + ///Mass Density of Liquid Water Coating on GraupelExpressed as Mass of Liquid Water per Unit Volume of Air (kg m-3) + public static Parameter MassDensityOfLiquidWaterCoatingOnGraupel { get; } = + new Parameter(ParameterCategory.Moisture, 112, "Mass Density of Liquid Water Coating on GraupelExpressed as Mass of Liquid Water per Unit Volume of Air", "kg m-3"); - ///Total Column Water(Vertically integrated total water (vapour+cloud water/ice) (kg m-2) - public static Parameter TotalColumnWater { get; } = - new Parameter(ParameterCategory.Moisture, 51, "Total Column Water(Vertically integrated total water (vapour+cloud water/ice)", "kg m-2"); + ///Specific Mass of Liquid Water Coating on Graupel Expressed as Mass of Liquid Water per Unit Mass of Moist Air (kg kg-1) + public static Parameter SpecificMassOfLiquidWaterCoatingOnGraupel { get; } = + new Parameter(ParameterCategory.Moisture, 113, "Specific Mass of Liquid Water Coating on Graupel Expressed as Mass of Liquid Water per Unit Mass of Moist Air", "kg kg-1"); - ///Total Precipitation Rate (kg m-2 s-1) - public static Parameter TotalPrecipitationRate { get; } = - new Parameter(ParameterCategory.Moisture, 52, "Total Precipitation Rate ", "kg m-2 s-1"); + ///Mass Mixing Ratio of Liquid Water Coating on Graupel Expressed as Mass of Liquid Water per Unit Mass of Dry Air (kg kg-1) + public static Parameter MassMixingRatioOfLiquidWaterCoatingOnGraupel { get; } = + new Parameter(ParameterCategory.Moisture, 114, "Mass Mixing Ratio of Liquid Water Coating on Graupel Expressed as Mass of Liquid Water per Unit Mass of Dry Air", "kg kg-1"); - ///Total Snowfall Rate Water Equivalent (kg m-2 s-1) - public static Parameter TotalSnowfallRateWaterEquivalent { get; } = - new Parameter(ParameterCategory.Moisture, 53, "Total Snowfall Rate Water Equivalent ", "kg m-2 s-1"); + ///Mass Density of Liquid Water Coating on Snow Expressed as Mass of Liquid Water per Unit Volume of Air (kg m-3) + public static Parameter MassDensityOfLiquidWaterCoatingOnSnow { get; } = + new Parameter(ParameterCategory.Moisture, 115, "Mass Density of Liquid Water Coating on Snow Expressed as Mass of Liquid Water per Unit Volume of Air", "kg m-3"); - ///Large Scale Precipitation Rate (kg m-2 s-1) - public static Parameter LargeScalePrecipitationRate { get; } = - new Parameter(ParameterCategory.Moisture, 54, "Large Scale Precipitation Rate", "kg m-2 s-1"); + ///Specific Mass of Liquid Water Coating on Snow Expressed as Mass of Liquid Water per Unit Mass of Moist Air (kg kg-1) + public static Parameter SpecificMassOfLiquidWaterCoatingOnSnow { get; } = + new Parameter(ParameterCategory.Moisture, 116, "Specific Mass of Liquid Water Coating on Snow Expressed as Mass of Liquid Water per Unit Mass of Moist Air", "kg kg-1"); - ///Convective Snowfall Rate Water Equivalent (kg m-2 s-1) - public static Parameter ConvectiveSnowfallRateWaterEquivalent { get; } = - new Parameter(ParameterCategory.Moisture, 55, "Convective Snowfall Rate Water Equivalent", "kg m-2 s-1"); + ///Mass Mixing Ratio of Liquid Water Coating on Snow Expressed as Mass of Liquid Water per Unit Mass of Dry Air (kg kg-1) + public static Parameter MassMixingRatioOfLiquidWaterCoatingOnSnow { get; } = + new Parameter(ParameterCategory.Moisture, 117, "Mass Mixing Ratio of Liquid Water Coating on Snow Expressed as Mass of Liquid Water per Unit Mass of Dry Air", "kg kg-1"); - ///Large Scale Snowfall Rate Water Equivalent (kg m-2 s-1) - public static Parameter LargeScaleSnowfallRateWaterEquivalent { get; } = - new Parameter(ParameterCategory.Moisture, 56, "Large Scale Snowfall Rate Water Equivalent", "kg m-2 s-1"); + ///Unbalanced Component of Specific Humidity (kg kg-1) + public static Parameter UnbalancedComponentOfSpecificHumidity { get; } = + new Parameter(ParameterCategory.Moisture, 118, "Unbalanced Component of Specific Humidity", "kg kg-1"); - ///Total Snowfall Rate (m s-1) - public static Parameter TotalSnowfallRate { get; } = - new Parameter(ParameterCategory.Moisture, 57, "Total Snowfall Rate", "m s-1"); + ///Unbalanced Component of Specific Cloud Liquid Water content (kg kg-1) + public static Parameter UnbalancedComponentOfSpecificCloudLiquidWaterContent { get; } = + new Parameter(ParameterCategory.Moisture, 119, "Unbalanced Component of Specific Cloud Liquid Water content", "kg kg-1"); - ///Convective Snowfall Rate (m s-1) - public static Parameter ConvectiveSnowfallRate { get; } = - new Parameter(ParameterCategory.Moisture, 58, "Convective Snowfall Rate", "m s-1"); + ///Unbalanced Component of Specific Cloud Ice Water content (kg kg-1) + public static Parameter UnbalancedComponentOfSpecificCloudIceWaterContent { get; } = + new Parameter(ParameterCategory.Moisture, 120, "Unbalanced Component of Specific Cloud Ice Water content", "kg kg-1"); - ///Large Scale Snowfall Rate (m s-1) - public static Parameter LargeScaleSnowfallRate { get; } = - new Parameter(ParameterCategory.Moisture, 59, "Large Scale Snowfall Rate", "m s-1"); + ///Fraction of Snow Cover (Proportion) + public static Parameter FractionOfSnowCover { get; } = + new Parameter(ParameterCategory.Moisture, 121, "Fraction of Snow Cover", "Proportion"); - ///Snow Depth Water Equivalent (kg m-2) - public static Parameter SnowDepthWaterEquivalent { get; } = - new Parameter(ParameterCategory.Moisture, 60, "Snow Depth Water Equivalent", "kg m-2"); + #endregion - ///Snow Density (kg m-3) - public static Parameter SnowDensity { get; } = - new Parameter(ParameterCategory.Moisture, 61, "Snow Density", "kg m-3"); + #region Product Discipline 0: Meteorological products, Parameter Category 2: Momentum - ///Snow Evaporation (kg m-2) - public static Parameter SnowEvaporation { get; } = - new Parameter(ParameterCategory.Moisture, 62, "Snow Evaporation", "kg m-2"); + ///Wind direction (from which blowing) (deg true) + public static Parameter WindDirection { get; } = + new Parameter(ParameterCategory.Momentum, 0, "Wind direction (from which blowing)", "deg true"); - ///Total Column Integrated Water Vapour (kg m-2) - public static Parameter TotalColumnIntegratedWaterVapour { get; } = - new Parameter(ParameterCategory.Moisture, 64, "Total Column Integrated Water Vapour", "kg m-2"); + ///Wind speed (m s-1) + public static Parameter WindSpeed { get; } = new Parameter(ParameterCategory.Momentum, 1, "Wind speed", "m s-1"); - ///Rain Precipitation Rate (kg m-2 s-1) - public static Parameter RainPrecipitationRate { get; } = - new Parameter(ParameterCategory.Moisture, 65, "Rain Precipitation Rate", "kg m-2 s-1"); + ///u-component of wind (m s-1) + public static Parameter UComponentOfWind { get; } = + new Parameter(ParameterCategory.Momentum, 2, "u-component of wind", "m s-1"); - ///Snow Precipitation Rate (kg m-2 s-1) - public static Parameter SnowPrecipitationRate { get; } = - new Parameter(ParameterCategory.Moisture, 66, "Snow Precipitation Rate", "kg m-2 s-1"); + ///v-component of wind (m s-1) + public static Parameter VComponentOfWind { get; } = + new Parameter(ParameterCategory.Momentum, 3, "v-component of wind", "m s-1"); - ///Freezing Rain Precipitation Rate (kg m-2 s-1) - public static Parameter FreezingRainPrecipitationRate { get; } = - new Parameter(ParameterCategory.Moisture, 67, "Freezing Rain Precipitation Rate", "kg m-2 s-1"); + ///Stream function (m2 s-1) + public static Parameter StreamFunction { get; } = + new Parameter(ParameterCategory.Momentum, 4, "Stream function", "m2 s-1"); - ///Ice Pellets Precipitation Rate (kg m-2 s-1) - public static Parameter IcePelletsPrecipitationRate { get; } = - new Parameter(ParameterCategory.Moisture, 68, "Ice Pellets Precipitation Rate", "kg m-2 s-1"); + ///Velocity potential (m2 s-1) + public static Parameter VelocityPotential { get; } = + new Parameter(ParameterCategory.Momentum, 5, "Velocity potential", "m2 s-1"); - ///Total Column Integrate Cloud Water (kg m-2) - public static Parameter TotalColumnIntegrateCloudWater { get; } = - new Parameter(ParameterCategory.Moisture, 69, "Total Column Integrate Cloud Water", "kg m-2"); + ///Montgomery stream function (m2 s-2) + public static Parameter MontgomeryStreamFunction { get; } = + new Parameter(ParameterCategory.Momentum, 6, "Montgomery stream function", "m2 s-2"); - ///Total Column Integrate Cloud Ice (kg m-2) - public static Parameter TotalColumnIntegrateCloudIce { get; } = - new Parameter(ParameterCategory.Moisture, 70, "Total Column Integrate Cloud Ice", "kg m-2"); + ///Sigma coordinate vertical velocity (s-1) + public static Parameter SigmaCoordinateVerticalVelocity { get; } = + new Parameter(ParameterCategory.Momentum, 7, "Sigma coordinate vertical velocity", "s-1"); - ///Hail Mixing Ratio (kg kg-1) - public static Parameter HailMixingRatio { get; } = - new Parameter(ParameterCategory.Moisture, 71, "Hail Mixing Ratio", "kg kg-1"); + ///Vertical velocity (pressure) (Pa s-1) + public static Parameter VerticalVelocityPressure { get; } = + new Parameter(ParameterCategory.Momentum, 8, "Vertical velocity (pressure)", "Pa s-1"); - ///Total Column Integrate Hail (kg m-2) - public static Parameter TotalColumnIntegrateHail { get; } = - new Parameter(ParameterCategory.Moisture, 72, "Total Column Integrate Hail", "kg m-2"); + ///Vertical velocity (geometric) (m s-1) + public static Parameter VerticalVelocityGeometric { get; } = + new Parameter(ParameterCategory.Momentum, 9, "Vertical velocity (geometric)", "m s-1"); - ///Hail Prepitation Rate (kg m-2 s-1) - public static Parameter HailPrepitationRate { get; } = - new Parameter(ParameterCategory.Moisture, 73, "Hail Prepitation Rate", "kg m-2 s-1"); + ///Absolute vorticity (s-1) + public static Parameter AbsoluteVorticity { get; } = + new Parameter(ParameterCategory.Momentum, 10, "Absolute vorticity", "s-1"); - ///Total Column Integrate Graupel (kg m-2) - public static Parameter TotalColumnIntegrateGraupel { get; } = - new Parameter(ParameterCategory.Moisture, 74, "Total Column Integrate Graupel", "kg m-2"); + ///Absolute divergence (s-1) + public static Parameter AbsoluteDivergence { get; } = + new Parameter(ParameterCategory.Momentum, 11, "Absolute divergence", "s-1"); - ///Graupel (Snow Pellets) Prepitation Rate (kg m-2 s-1) - public static Parameter GraupelPrecipitationRate { get; } = - new Parameter(ParameterCategory.Moisture, 75, "Graupel (Snow Pellets) Prepitation Rate", "kg m-2 s-1"); + ///Relative vorticity (s-1) + public static Parameter RelativeVorticity { get; } = + new Parameter(ParameterCategory.Momentum, 12, "Relative vorticity", "s-1"); - ///Convective Rain Rate (kg m-2 s-1) - public static Parameter ConvectiveRainRate { get; } = - new Parameter(ParameterCategory.Moisture, 76, "Convective Rain Rate", "kg m-2 s-1"); + ///Relative divergence (s-1) + public static Parameter RelativeDivergence { get; } = + new Parameter(ParameterCategory.Momentum, 13, "Relative divergence", "s-1"); - ///Large Scale Rain Rate (kg m-2 s-1) - public static Parameter LargeScaleRainRate { get; } = - new Parameter(ParameterCategory.Moisture, 77, "Large Scale Rain Rate", "kg m-2 s-1"); + ///Potential vorticity (K m2 kg-1 s-1) + public static Parameter PotentialVorticity { get; } = + new Parameter(ParameterCategory.Momentum, 14, "Potential vorticity", "K m2 kg-1 s-1"); - ///Total Column Integrate Water (Allcomponents including precipitation) (kg m-2) - public static Parameter TotalColumnIntegrateWater { get; } = - new Parameter(ParameterCategory.Moisture, 78, "Total Column Integrate Water (Allcomponents including precipitation)", "kg m-2"); + ///Vertical u-component shear (s-1) + public static Parameter VerticalUComponentShear { get; } = + new Parameter(ParameterCategory.Momentum, 15, "Vertical u-component shear", "s-1"); - ///Evaporation Rate (kg m-2 s-1) - public static Parameter EvaporationRate { get; } = - new Parameter(ParameterCategory.Moisture, 79, "Evaporation Rate", "kg m-2 s-1"); + ///Vertical v-component shear (s-1) + public static Parameter VerticalVComponentShear { get; } = + new Parameter(ParameterCategory.Momentum, 16, "Vertical v-component shear", "s-1"); - ///Total Condensate (kg kg-1) - public static Parameter TotalCondensate { get; } = - new Parameter(ParameterCategory.Moisture, 80, "Total Condensate", "kg kg-1"); + ///Momentum flux, u component (s-1) + public static Parameter MomentumFluxUComponent { get; } = + new Parameter(ParameterCategory.Momentum, 17, "Momentum flux, u component", "s-1"); - ///Total Column-Integrate Condensate (kg m-2) - public static Parameter TotalColumnIntegrateCondensate { get; } = - new Parameter(ParameterCategory.Moisture, 81, "Total Column-Integrate Condensate", "kg m-2"); + ///Momentum flux, v component (s-1) + public static Parameter MomentumFluxVComponent { get; } = + new Parameter(ParameterCategory.Momentum, 18, "Momentum flux, v component", "s-1"); - ///Cloud Ice Mixing Ratio (kg kg-1) - public static Parameter CloudIceMixingRatio { get; } = - new Parameter(ParameterCategory.Moisture, 82, "Cloud Ice Mixing Ratio", "kg kg-1"); + ///Wind mixing energy (J) + public static Parameter WindMixingEnergy { get; } = + new Parameter(ParameterCategory.Momentum, 19, "Wind mixing energy", "J"); - ///Specific Cloud Liquid Water Content (kg kg-1) - public static Parameter SpecificCloudLiquidWaterContent { get; } = - new Parameter(ParameterCategory.Moisture, 83, "Specific Cloud Liquid Water Content", "kg kg-1"); + ///Boundary layer dissipation (W m-2) + public static Parameter BoundaryLayerDissipation { get; } = + new Parameter(ParameterCategory.Momentum, 20, "Boundary layer dissipation", "W m-2"); - ///Specific Cloud Ice Water Content (kg kg-1) - public static Parameter SpecificCloudIceWaterContent { get; } = - new Parameter(ParameterCategory.Moisture, 84, "Specific Cloud Ice Water Content", "kg kg-1"); + ///Maximum wind speed (m s-1) + public static Parameter MaximumWindSpeed { get; } = + new Parameter(ParameterCategory.Momentum, 21, "Maximum wind speed", "m s-1"); - ///Specific Rain Water Content (kg kg-1) - public static Parameter SpecificRainWaterContent { get; } = - new Parameter(ParameterCategory.Moisture, 85, "Specific Rain Water Content", "kg kg-1"); + ///Wind speed (gust) (m s-1) + public static Parameter WindSpeedGust { get; } = + new Parameter(ParameterCategory.Momentum, 22, "Wind speed (gust)", "m s-1"); - ///Specific Snow Water Content (kg kg-1) - public static Parameter SpecificSnowWaterContent { get; } = - new Parameter(ParameterCategory.Moisture, 86, "Specific Snow Water Content", "kg kg-1"); + ///u-component of wind (gust) (m s-1) + public static Parameter UComponentOfWindGust { get; } = + new Parameter(ParameterCategory.Momentum, 23, "u-component of wind (gust)", "m s-1"); - ///Stratiform Precipitation Rate (kg m-2 s-1) - public static Parameter StratiformPrecipitationRate { get; } = - new Parameter(ParameterCategory.Moisture, 87, "Stratiform Precipitation Rate", "kg m-2 s-1"); + ///v-component of wind (gust) (m s-1) + public static Parameter VComponentOfWindGust { get; } = + new Parameter(ParameterCategory.Momentum, 24, "v-component of wind (gust)", "m s-1"); - ///Categorical Convective Precipitation (Code table 4.222) - public static Parameter CategoricalConvectivePrecipitation { get; } = - new Parameter(ParameterCategory.Moisture, 88, "Categorical Convective Precipitation", ""); + #endregion - ///Total Kinematic Moisture Flux (kg kg-1 m s-1) - public static Parameter TotalKinematicMoistureFlux { get; } = - new Parameter(ParameterCategory.Moisture, 90, "Total Kinematic Moisture Flux", "kg kg-1 m s-1"); + #region Product Discipline 0: Meteorological products, Parameter Category 3: Mass - ///U-component (zonal) Kinematic Moisture Flux (kg kg-1 m s-1) - public static Parameter Ucomponent { get; } = - new Parameter(ParameterCategory.Moisture, 91, "U-component (zonal) Kinematic Moisture Flux", "kg kg-1 m s-1"); + ///Pressure (Pa) + public static Parameter Pressure { get; } = new Parameter(ParameterCategory.Mass, 0, "Pressure", "Pa"); - ///V-component (meridional) Kinematic Moisture Flux (kg kg-1 m s-1) - public static Parameter Vcomponent { get; } = - new Parameter(ParameterCategory.Moisture, 92, "V-component (meridional) Kinematic Moisture Flux", "kg kg-1 m s-1"); + ///Pressure reduced to MSL (Pa) + public static Parameter PressureReducedToMsl { get; } = + new Parameter(ParameterCategory.Mass, 1, "Pressure reduced to MSL", "Pa"); - ///Relative Humidity With Respect to Water (%) - public static Parameter RelativeHumidityWithRespectToWater { get; } = - new Parameter(ParameterCategory.Moisture, 93, "Relative Humidity With Respect to Water", "%"); + ///Pressure tendency (Pa s-1) + public static Parameter PressureTendency { get; } = + new Parameter(ParameterCategory.Mass, 2, "Pressure tendency", "Pa s-1"); - ///Relative Humidity With Respect to Ice (%) - public static Parameter RelativeHumidityWithRespectToIce { get; } = - new Parameter(ParameterCategory.Moisture, 94, "Relative Humidity With Respect to Ice", "%"); + ///ICAO Standard Atmosphere Reference Height (m) + public static Parameter IcaoStandardAtmosphereReferenceHeight { get; } = + new Parameter(ParameterCategory.Mass, 3, "ICAO Standard Atmosphere Reference Height", "m"); - ///Freezing or Frozen Precipitation Rate (kg m-2 s-1) - public static Parameter FreezingOrFrozenPrecipitationRate { get; } = - new Parameter(ParameterCategory.Moisture, 95, "Freezing or Frozen Precipitation Rate", "kg m-2 s-1"); + ///Geopotential (m2 s-2) + public static Parameter Geopotential { get; } = new Parameter(ParameterCategory.Mass, 4, "Geopotential", "m2 s-2"); - ///Mass Density of Rain (kg m-3) - public static Parameter MassDensityOfRain { get; } = - new Parameter(ParameterCategory.Moisture, 96, "Mass Density of Rain", "kg m-3"); + ///Geopotential height (gpm) + public static Parameter GeopotentialHeight { get; } = + new Parameter(ParameterCategory.Mass, 5, "Geopotential height", "gpm"); - ///Mass Density of Snow (kg m-3) - public static Parameter MassDensityOfSnow { get; } = - new Parameter(ParameterCategory.Moisture, 97, "Mass Density of Snow", "kg m-3"); + ///Geometric height (m) + public static Parameter GeometricHeight { get; } = new Parameter(ParameterCategory.Mass, 6, "Geometric height", "m"); - ///Mass Density of Graupel (kg m-3) - public static Parameter MassDensityOfGraupel { get; } = - new Parameter(ParameterCategory.Moisture, 98, "Mass Density of Graupel", "kg m-3"); + ///Standard deviation of height (m) + public static Parameter StandardDeviationOfHeight { get; } = + new Parameter(ParameterCategory.Mass, 7, "Standard deviation of height", "m"); - ///Mass Density of Hail (kg m-3) - public static Parameter MassDensityOfHail { get; } = - new Parameter(ParameterCategory.Moisture, 99, "Mass Density of Hail", "kg m-3"); + ///Pressure anomaly (Pa) + public static Parameter PressureAnomaly { get; } = new Parameter(ParameterCategory.Mass, 8, "Pressure anomaly", "Pa"); - ///Specific Number Concentration of Rain (kg-1) - public static Parameter SpecificNumberConcentrationOfRain { get; } = - new Parameter(ParameterCategory.Moisture, 100, "Specific Number Concentration of Rain", "kg-1"); + ///Geopotential height anomaly (gpm) + public static Parameter GeopotentialHeightAnomaly { get; } = + new Parameter(ParameterCategory.Mass, 9, "Geopotential height anomaly", "gpm"); - ///Specific Number Concentration of Snow (kg-1) - public static Parameter SpecificNumberConcentrationOfSnow { get; } = - new Parameter(ParameterCategory.Moisture, 101, "Specific Number Concentration of Snow", "kg-1"); + ///Density (kg m-3) + public static Parameter Density { get; } = new Parameter(ParameterCategory.Mass, 10, "Density", "kg m-3"); - ///Specific Number Concentration of Graupel (kg-1) - public static Parameter SpecificNumberConcentrationOfGraupel { get; } = - new Parameter(ParameterCategory.Moisture, 102, "Specific Number Concentration of Graupel", "kg-1"); + ///Altimeter setting (Pa) + public static Parameter AltimeterSetting { get; } = new Parameter(ParameterCategory.Mass, 11, "Altimeter setting", "Pa"); - ///Specific Number Concentration of Hail (kg-1) - public static Parameter SpecificNumberConcentrationOfHail { get; } = - new Parameter(ParameterCategory.Moisture, 103, "Specific Number Concentration of Hail", "kg-1"); + ///Thickness (m) + public static Parameter Thickness { get; } = new Parameter(ParameterCategory.Mass, 12, "Thickness", "m"); - ///Number Density of Rain (m-3) - public static Parameter NumberDensityOfRain { get; } = - new Parameter(ParameterCategory.Moisture, 104, "Number Density of Rain", "m-3"); + ///Pressure altitude (m) + public static Parameter PressureAltitude { get; } = new Parameter(ParameterCategory.Mass, 13, "Pressure altitude", "m"); - ///Number Density of Snow (m-3) - public static Parameter NumberDensityOfSnow { get; } = - new Parameter(ParameterCategory.Moisture, 105, "Number Density of Snow", "m-3"); + ///Density altitude (m) + public static Parameter DensityAltitude { get; } = new Parameter(ParameterCategory.Mass, 14, "Density altitude", "m"); - ///Number Density of Graupel (m-3) - public static Parameter NumberDensityOfGraupel { get; } = - new Parameter(ParameterCategory.Moisture, 106, "Number Density of Graupel", "m-3"); + #endregion - ///Number Density of Hail (m-3) - public static Parameter NumberDensityOfHail { get; } = - new Parameter(ParameterCategory.Moisture, 107, "Number Density of Hail", "m-3"); + #region Product Discipline 0: Meteorological products, Parameter Category 4: Short-wave Radiation - ///Specific Humidity Tendency due to Parameterizations (kg kg-1 s-1) - public static Parameter SpecificHumidityTendencyDueToParameterizations { get; } = - new Parameter(ParameterCategory.Moisture, 108, "Specific Humidity Tendency due to Parameterizations", "kg kg-1 s-1"); + ///Net short-wave radiation flux (surface) (W m-2) + public static Parameter NetShortWaveRadiationFluxSurface { get; } = new Parameter(ParameterCategory.ShortWaveRadiation, 0, + "Net short-wave radiation flux (surface)", "W m-2"); - ///Mass Density of Liquid Water Coating on Hail Expressed as Mass of Liquid Water per Unit Volume of Air (kg m-3) - public static Parameter MassDensityOfLiquidWaterCoatingOnHail { get; } = - new Parameter(ParameterCategory.Moisture, 109, "Mass Density of Liquid Water Coating on Hail Expressed as Mass of Liquid Water per Unit Volume of Air", "kg m-3"); + ///Net short-wave radiation flux (top of atmosphere) (W m-2) + public static Parameter NetShortWaveRadiationFlux { get; } = new Parameter(ParameterCategory.ShortWaveRadiation, 1, + "Net short-wave radiation flux (top of atmosphere)", "W m-2"); - ///Specific Mass of Liquid Water Coating on HailExpressed as Mass of Liquid Water per Unit Mass of Moist Air (kg kg-1) - public static Parameter SpecificMassOfLiquidWaterCoatingOnHail { get; } = - new Parameter(ParameterCategory.Moisture, 110, "Specific Mass of Liquid Water Coating on HailExpressed as Mass of Liquid Water per Unit Mass of Moist Air", "kg kg-1"); + ///Short wave radiation flux (W m-2) + public static Parameter ShortWaveRadiationFlux { get; } = + new Parameter(ParameterCategory.ShortWaveRadiation, 2, "Short wave radiation flux", "W m-2"); - ///Mass Mixing Ratio of Liquid Water Coating on Hail Expressed as Mass of Liquid Water per Unit Mass of Dry Air (kg kg-1) - public static Parameter MassMixingRatioOfLiquidWaterCoatingOnHail { get; } = - new Parameter(ParameterCategory.Moisture, 111, "Mass Mixing Ratio of Liquid Water Coating on Hail Expressed as Mass of Liquid Water per Unit Mass of Dry Air", "kg kg-1"); + ///Global radiation flux (W m-2) + public static Parameter GlobalRadiationFlux { get; } = + new Parameter(ParameterCategory.ShortWaveRadiation, 3, "Global radiation flux", "W m-2"); - ///Mass Density of Liquid Water Coating on GraupelExpressed as Mass of Liquid Water per Unit Volume of Air (kg m-3) - public static Parameter MassDensityOfLiquidWaterCoatingOnGraupel { get; } = - new Parameter(ParameterCategory.Moisture, 112, "Mass Density of Liquid Water Coating on GraupelExpressed as Mass of Liquid Water per Unit Volume of Air", "kg m-3"); + ///Brightness temperature (K) + public static Parameter BrightnessTemperature { get; } = + new Parameter(ParameterCategory.ShortWaveRadiation, 4, "Brightness temperature", "K"); - ///Specific Mass of Liquid Water Coating on Graupel Expressed as Mass of Liquid Water per Unit Mass of Moist Air (kg kg-1) - public static Parameter SpecificMassOfLiquidWaterCoatingOnGraupel { get; } = - new Parameter(ParameterCategory.Moisture, 113, "Specific Mass of Liquid Water Coating on Graupel Expressed as Mass of Liquid Water per Unit Mass of Moist Air", "kg kg-1"); + ///Radiance (with respect to wave number) (W m-1 sr-1) + public static Parameter RadianceWaveNumber { get; } = new Parameter(ParameterCategory.ShortWaveRadiation, 5, + "Radiance (with respect to wave number)", "W m-1 sr-1"); - ///Mass Mixing Ratio of Liquid Water Coating on Graupel Expressed as Mass of Liquid Water per Unit Mass of Dry Air (kg kg-1) - public static Parameter MassMixingRatioOfLiquidWaterCoatingOnGraupel { get; } = - new Parameter(ParameterCategory.Moisture, 114, "Mass Mixing Ratio of Liquid Water Coating on Graupel Expressed as Mass of Liquid Water per Unit Mass of Dry Air", "kg kg-1"); + ///Radiance (with respect to wave length) (W m-3 sr-1) + public static Parameter RadianceWaveLength { get; } = new Parameter(ParameterCategory.ShortWaveRadiation, 6, + "Radiance (with respect to wave length)", "W m-3 sr-1"); - ///Mass Density of Liquid Water Coating on Snow Expressed as Mass of Liquid Water per Unit Volume of Air (kg m-3) - public static Parameter MassDensityOfLiquidWaterCoatingOnSnow { get; } = - new Parameter(ParameterCategory.Moisture, 115, "Mass Density of Liquid Water Coating on Snow Expressed as Mass of Liquid Water per Unit Volume of Air", "kg m-3"); + #endregion - ///Specific Mass of Liquid Water Coating on Snow Expressed as Mass of Liquid Water per Unit Mass of Moist Air (kg kg-1) - public static Parameter SpecificMassOfLiquidWaterCoatingOnSnow { get; } = - new Parameter(ParameterCategory.Moisture, 116, "Specific Mass of Liquid Water Coating on Snow Expressed as Mass of Liquid Water per Unit Mass of Moist Air", "kg kg-1"); + #region Product Discipline 0: Meteorological products, Parameter Category 5: Long-wave Radiation - ///Mass Mixing Ratio of Liquid Water Coating on Snow Expressed as Mass of Liquid Water per Unit Mass of Dry Air (kg kg-1) - public static Parameter MassMixingRatioOfLiquidWaterCoatingOnSnow { get; } = - new Parameter(ParameterCategory.Moisture, 117, "Mass Mixing Ratio of Liquid Water Coating on Snow Expressed as Mass of Liquid Water per Unit Mass of Dry Air", "kg kg-1"); + ///Net long wave radiation flux (surface) (W m-2) + public static Parameter NetLongWaveRadiationFluxSurface { get; } = new Parameter(ParameterCategory.LongWaveRadiation, 0, + "Net long wave radiation flux (surface)", "W m-2"); - ///Unbalanced Component of Specific Humidity (kg kg-1) - public static Parameter UnbalancedComponentOfSpecificHumidity { get; } = - new Parameter(ParameterCategory.Moisture, 118, "Unbalanced Component of Specific Humidity", "kg kg-1"); + ///Net long wave radiation flux (top of atmosphere) (W m-2) + public static Parameter NetLongWaveRadiationFlux { get; } = new Parameter(ParameterCategory.LongWaveRadiation, 1, + "Net long wave radiation flux (top of atmosphere)", "W m-2"); - ///Unbalanced Component of Specific Cloud Liquid Water content (kg kg-1) - public static Parameter UnbalancedComponentOfSpecificCloudLiquidWaterContent { get; } = - new Parameter(ParameterCategory.Moisture, 119, "Unbalanced Component of Specific Cloud Liquid Water content", "kg kg-1"); + ///Long wave radiation flux (W m-2) + public static Parameter LongWaveRadiationFlux { get; } = + new Parameter(ParameterCategory.LongWaveRadiation, 2, "Long wave radiation flux", "W m-2"); - ///Unbalanced Component of Specific Cloud Ice Water content (kg kg-1) - public static Parameter UnbalancedComponentOfSpecificCloudIceWaterContent { get; } = - new Parameter(ParameterCategory.Moisture, 120, "Unbalanced Component of Specific Cloud Ice Water content", "kg kg-1"); + #endregion - ///Fraction of Snow Cover (Proportion) - public static Parameter FractionOfSnowCover { get; } = - new Parameter(ParameterCategory.Moisture, 121, "Fraction of Snow Cover", "Proportion"); + #region Product Discipline 0: Meteorological products, Parameter Category 6: Cloud - #endregion + ///Cloud Ice (kg m-2) + public static Parameter CloudIce { get; } = new Parameter(ParameterCategory.Cloud, 0, "Cloud Ice", "kg m-2"); - #region Product Discipline 0: Meteorological products, Parameter Category 2: Momentum + ///Total cloud cover (%) + public static Parameter TotalCloudCover { get; } = new Parameter(ParameterCategory.Cloud, 1, "Total cloud cover", "%"); - ///Wind direction (from which blowing) (deg true) - public static Parameter WindDirection { get; } = - new Parameter(ParameterCategory.Momentum, 0, "Wind direction (from which blowing)", "deg true"); + ///Convective cloud cover (%) + public static Parameter ConvectiveCloudCover { get; } = + new Parameter(ParameterCategory.Cloud, 2, "Convective cloud cover", "%"); - ///Wind speed (m s-1) - public static Parameter WindSpeed { get; } = new Parameter(ParameterCategory.Momentum, 1, "Wind speed", "m s-1"); + ///Low cloud cover (%) + public static Parameter LowCloudCover { get; } = new Parameter(ParameterCategory.Cloud, 3, "Low cloud cover", "%"); - ///u-component of wind (m s-1) - public static Parameter UComponentOfWind { get; } = - new Parameter(ParameterCategory.Momentum, 2, "u-component of wind", "m s-1"); + ///Medium cloud cover (%) + public static Parameter MediumCloudCover { get; } = new Parameter(ParameterCategory.Cloud, 4, "Medium cloud cover", "%"); - ///v-component of wind (m s-1) - public static Parameter VComponentOfWind { get; } = - new Parameter(ParameterCategory.Momentum, 3, "v-component of wind", "m s-1"); + ///High cloud cover (%) + public static Parameter HighCloudCover { get; } = new Parameter(ParameterCategory.Cloud, 5, "High cloud cover", "%"); - ///Stream function (m2 s-1) - public static Parameter StreamFunction { get; } = - new Parameter(ParameterCategory.Momentum, 4, "Stream function", "m2 s-1"); + ///Cloud water (kg m-2) + public static Parameter CloudWater { get; } = new Parameter(ParameterCategory.Cloud, 6, "Cloud water", "kg m-2"); - ///Velocity potential (m2 s-1) - public static Parameter VelocityPotential { get; } = - new Parameter(ParameterCategory.Momentum, 5, "Velocity potential", "m2 s-1"); + ///Cloud amount (%) + public static Parameter CloudAmount { get; } = new Parameter(ParameterCategory.Cloud, 7, "Cloud amount", "%"); - ///Montgomery stream function (m2 s-2) - public static Parameter MontgomeryStreamFunction { get; } = - new Parameter(ParameterCategory.Momentum, 6, "Montgomery stream function", "m2 s-2"); + ///Cloud type (Code table (4.203)) + public static Parameter CloudType { get; } = new Parameter(ParameterCategory.Cloud, 8, "Cloud type", "Code table (4.203)"); - ///Sigma coordinate vertical velocity (s-1) - public static Parameter SigmaCoordinateVerticalVelocity { get; } = - new Parameter(ParameterCategory.Momentum, 7, "Sigma coordinate vertical velocity", "s-1"); + ///Thunderstorm maximum tops (m) + public static Parameter ThunderstormMaximumTops { get; } = + new Parameter(ParameterCategory.Cloud, 9, "Thunderstorm maximum tops", "m"); - ///Vertical velocity (pressure) (Pa s-1) - public static Parameter VerticalVelocityPressure { get; } = - new Parameter(ParameterCategory.Momentum, 8, "Vertical velocity (pressure)", "Pa s-1"); + ///Thunderstorm coverage (Code table (4.204)) + public static Parameter ThunderstormCoverage { get; } = + new Parameter(ParameterCategory.Cloud, 10, "Thunderstorm coverage", "Code table (4.204)"); - ///Vertical velocity (geometric) (m s-1) - public static Parameter VerticalVelocityGeometric { get; } = - new Parameter(ParameterCategory.Momentum, 9, "Vertical velocity (geometric)", "m s-1"); + ///Cloud base (m) + public static Parameter CloudBase { get; } = new Parameter(ParameterCategory.Cloud, 11, "Cloud base", "m"); - ///Absolute vorticity (s-1) - public static Parameter AbsoluteVorticity { get; } = - new Parameter(ParameterCategory.Momentum, 10, "Absolute vorticity", "s-1"); + ///Cloud top (m) + public static Parameter CloudTop { get; } = new Parameter(ParameterCategory.Cloud, 12, "Cloud top", "m"); - ///Absolute divergence (s-1) - public static Parameter AbsoluteDivergence { get; } = - new Parameter(ParameterCategory.Momentum, 11, "Absolute divergence", "s-1"); + ///Ceiling (m) + public static Parameter Ceiling { get; } = new Parameter(ParameterCategory.Cloud, 13, "Ceiling", "m"); - ///Relative vorticity (s-1) - public static Parameter RelativeVorticity { get; } = - new Parameter(ParameterCategory.Momentum, 12, "Relative vorticity", "s-1"); + #endregion - ///Relative divergence (s-1) - public static Parameter RelativeDivergence { get; } = - new Parameter(ParameterCategory.Momentum, 13, "Relative divergence", "s-1"); + #region Product Discipline 0: Meteorological products, Parameter Category 7: Thermodynamic Stability Indices - ///Potential vorticity (K m2 kg-1 s-1) - public static Parameter PotentialVorticity { get; } = - new Parameter(ParameterCategory.Momentum, 14, "Potential vorticity", "K m2 kg-1 s-1"); + ///Parcel lifted index (to 500 hPa) (K) + public static Parameter ParcelLiftedIndex { get; } = new Parameter(ParameterCategory.ThermodynamicStabilityIndices, 0, + "Parcel lifted index (to 500 hPa)", "K"); - ///Vertical u-component shear (s-1) - public static Parameter VerticalUComponentShear { get; } = - new Parameter(ParameterCategory.Momentum, 15, "Vertical u-component shear", "s-1"); + ///Best lifted index (to 500 hPa) (K) + public static Parameter BestLiftedIndex { get; } = new Parameter(ParameterCategory.ThermodynamicStabilityIndices, 1, + "Best lifted index (to 500 hPa)", "K"); - ///Vertical v-component shear (s-1) - public static Parameter VerticalVComponentShear { get; } = - new Parameter(ParameterCategory.Momentum, 16, "Vertical v-component shear", "s-1"); + ///K index (K) + public static Parameter KIndex { get; } = + new Parameter(ParameterCategory.ThermodynamicStabilityIndices, 2, "K index", "K"); - ///Momentum flux, u component (s-1) - public static Parameter MomentumFluxUComponent { get; } = - new Parameter(ParameterCategory.Momentum, 17, "Momentum flux, u component", "s-1"); + ///KO index (K) + public static Parameter KoIndex { get; } = + new Parameter(ParameterCategory.ThermodynamicStabilityIndices, 3, "KO index", "K"); - ///Momentum flux, v component (s-1) - public static Parameter MomentumFluxVComponent { get; } = - new Parameter(ParameterCategory.Momentum, 18, "Momentum flux, v component", "s-1"); + ///Total totals index (K) + public static Parameter TotalTotalsIndex { get; } = + new Parameter(ParameterCategory.ThermodynamicStabilityIndices, 4, "Total totals index", "K"); - ///Wind mixing energy (J) - public static Parameter WindMixingEnergy { get; } = - new Parameter(ParameterCategory.Momentum, 19, "Wind mixing energy", "J"); + ///Sweat index (numeric) + public static Parameter SweatIndex { get; } = + new Parameter(ParameterCategory.ThermodynamicStabilityIndices, 5, "Sweat index", "numeric"); - ///Boundary layer dissipation (W m-2) - public static Parameter BoundaryLayerDissipation { get; } = - new Parameter(ParameterCategory.Momentum, 20, "Boundary layer dissipation", "W m-2"); + ///Convective available potential energy (J kg-1) + public static Parameter ConvectiveAvailablePotentialEnergy { get; } = new Parameter( + ParameterCategory.ThermodynamicStabilityIndices, 6, "Convective available potential energy", "J kg-1"); - ///Maximum wind speed (m s-1) - public static Parameter MaximumWindSpeed { get; } = - new Parameter(ParameterCategory.Momentum, 21, "Maximum wind speed", "m s-1"); + ///Convective inhibition (J kg-1) + public static Parameter ConvectiveInhibition { get; } = new Parameter(ParameterCategory.ThermodynamicStabilityIndices, 7, + "Convective inhibition", "J kg-1"); - ///Wind speed (gust) (m s-1) - public static Parameter WindSpeedGust { get; } = - new Parameter(ParameterCategory.Momentum, 22, "Wind speed (gust)", "m s-1"); + ///Storm relative helicity (J kg-1) + public static Parameter StormRelativeHelicity { get; } = new Parameter(ParameterCategory.ThermodynamicStabilityIndices, 8, + "Storm relative helicity", "J kg-1"); - ///u-component of wind (gust) (m s-1) - public static Parameter UComponentOfWindGust { get; } = - new Parameter(ParameterCategory.Momentum, 23, "u-component of wind (gust)", "m s-1"); + ///Energy helicity index (numeric) + public static Parameter EnergyHelicityIndex { get; } = new Parameter(ParameterCategory.ThermodynamicStabilityIndices, 9, + "Energy helicity index", "numeric"); - ///v-component of wind (gust) (m s-1) - public static Parameter VComponentOfWindGust { get; } = - new Parameter(ParameterCategory.Momentum, 24, "v-component of wind (gust)", "m s-1"); + #endregion - #endregion + #region Product Discipline 0: Meteorological products, Parameter Category 13: Aerosols - #region Product Discipline 0: Meteorological products, Parameter Category 3: Mass + ///Aerosol type (Code table (4.205)) + public static Parameter AerosolType { get; } = + new Parameter(ParameterCategory.Aerosols, 0, "Aerosol type", "Code table (4.205)"); - ///Pressure (Pa) - public static Parameter Pressure { get; } = new Parameter(ParameterCategory.Mass, 0, "Pressure", "Pa"); + #endregion - ///Pressure reduced to MSL (Pa) - public static Parameter PressureReducedToMsl { get; } = - new Parameter(ParameterCategory.Mass, 1, "Pressure reduced to MSL", "Pa"); + #region Product Discipline 0: Meteorological products, Parameter Category 14: Trace Gases - ///Pressure tendency (Pa s-1) - public static Parameter PressureTendency { get; } = - new Parameter(ParameterCategory.Mass, 2, "Pressure tendency", "Pa s-1"); + ///Total ozone (Dobson) + public static Parameter TotalOzone { get; } = new Parameter(ParameterCategory.TraceGases, 0, "Total ozone", "Dobson"); - ///ICAO Standard Atmosphere Reference Height (m) - public static Parameter IcaoStandardAtmosphereReferenceHeight { get; } = - new Parameter(ParameterCategory.Mass, 3, "ICAO Standard Atmosphere Reference Height", "m"); + #endregion - ///Geopotential (m2 s-2) - public static Parameter Geopotential { get; } = new Parameter(ParameterCategory.Mass, 4, "Geopotential", "m2 s-2"); + #region Product Discipline 0 - Meteorological products, Parameter Category 15: Radar - ///Geopotential height (gpm) - public static Parameter GeopotentialHeight { get; } = - new Parameter(ParameterCategory.Mass, 5, "Geopotential height", "gpm"); + ///Base spectrum width (m s-1) + public static Parameter BaseSpectrumWidth { get; } = + new Parameter(ParameterCategory.Radar, 0, "Base spectrum width", "m s-1"); - ///Geometric height (m) - public static Parameter GeometricHeight { get; } = new Parameter(ParameterCategory.Mass, 6, "Geometric height", "m"); + ///Base reflectivity (dB) + public static Parameter BaseReflectivity { get; } = new Parameter(ParameterCategory.Radar, 1, "Base reflectivity", "dB"); - ///Standard deviation of height (m) - public static Parameter StandardDeviationOfHeight { get; } = - new Parameter(ParameterCategory.Mass, 7, "Standard deviation of height", "m"); + ///Base radial velocity (m s-1) + public static Parameter BaseRadialVelocity { get; } = + new Parameter(ParameterCategory.Radar, 2, "Base radial velocity", "m s-1"); - ///Pressure anomaly (Pa) - public static Parameter PressureAnomaly { get; } = new Parameter(ParameterCategory.Mass, 8, "Pressure anomaly", "Pa"); + ///Vertically-integrated liquid (kg m-1) + public static Parameter VerticallyIntegratedLiquid { get; } = + new Parameter(ParameterCategory.Radar, 3, "Vertically-integrated liquid", "kg m-1"); - ///Geopotential height anomaly (gpm) - public static Parameter GeopotentialHeightAnomaly { get; } = - new Parameter(ParameterCategory.Mass, 9, "Geopotential height anomaly", "gpm"); + ///Layer-maximum base reflectivity (dB) + public static Parameter LayerMaximumBaseReflectivity { get; } = + new Parameter(ParameterCategory.Radar, 4, "Layer-maximum base reflectivity", "dB"); - ///Density (kg m-3) - public static Parameter Density { get; } = new Parameter(ParameterCategory.Mass, 10, "Density", "kg m-3"); + ///Precipitation (kg m-2) + public static Parameter Precipitation { get; } = new Parameter(ParameterCategory.Radar, 5, "Precipitation", "kg m-2"); - ///Altimeter setting (Pa) - public static Parameter AltimeterSetting { get; } = new Parameter(ParameterCategory.Mass, 11, "Altimeter setting", "Pa"); + ///Radar spectra (1) (-) + public static Parameter RadarSpectra1 { get; } = new Parameter(ParameterCategory.Radar, 6, "Radar spectra (1)", "-"); - ///Thickness (m) - public static Parameter Thickness { get; } = new Parameter(ParameterCategory.Mass, 12, "Thickness", "m"); + ///Radar spectra (2) (-) + public static Parameter RadarSpectra2 { get; } = new Parameter(ParameterCategory.Radar, 7, "Radar spectra (2)", "-"); - ///Pressure altitude (m) - public static Parameter PressureAltitude { get; } = new Parameter(ParameterCategory.Mass, 13, "Pressure altitude", "m"); + ///Radar spectra (3) (-) + public static Parameter RadarSpectra3 { get; } = new Parameter(ParameterCategory.Radar, 8, "Radar spectra (3)", "-"); - ///Density altitude (m) - public static Parameter DensityAltitude { get; } = new Parameter(ParameterCategory.Mass, 14, "Density altitude", "m"); + #endregion - #endregion + #region Product Discipline 0: Meteorological products, Parameter Category 18: Nuclear/radiology - #region Product Discipline 0: Meteorological products, Parameter Category 4: Short-wave Radiation + ///Air concentration of Caesium 137 (Bq m-3) + public static Parameter AirConcentrationOfCaesium137 { get; } = new Parameter(ParameterCategory.NuclearRadiology, 0, + "Air concentration of Caesium 137", "Bq m-3"); - ///Net short-wave radiation flux (surface) (W m-2) - public static Parameter NetShortWaveRadiationFluxSurface { get; } = new Parameter(ParameterCategory.ShortWaveRadiation, 0, - "Net short-wave radiation flux (surface)", "W m-2"); + ///Air concentration of Iodine 131 (Bq m-3) + public static Parameter AirConcentrationOfIodine131 { get; } = new Parameter(ParameterCategory.NuclearRadiology, 1, + "Air concentration of Iodine 131", "Bq m-3"); - ///Net short-wave radiation flux (top of atmosphere) (W m-2) - public static Parameter NetShortWaveRadiationFlux { get; } = new Parameter(ParameterCategory.ShortWaveRadiation, 1, - "Net short-wave radiation flux (top of atmosphere)", "W m-2"); + ///Air concentration of radioactive pollutant (Bq m-3) + public static Parameter AirConcentrationOfRadioactivePollutant { get; } = new Parameter(ParameterCategory.NuclearRadiology, + 2, "Air concentration of radioactive pollutant", "Bq m-3"); - ///Short wave radiation flux (W m-2) - public static Parameter ShortWaveRadiationFlux { get; } = - new Parameter(ParameterCategory.ShortWaveRadiation, 2, "Short wave radiation flux", "W m-2"); + ///Ground deposition of Caesium 137 (Bq m-2) + public static Parameter GroundDepositionOfCaesium137 { get; } = new Parameter(ParameterCategory.NuclearRadiology, 3, + "Ground deposition of Caesium 137", "Bq m-2"); - ///Global radiation flux (W m-2) - public static Parameter GlobalRadiationFlux { get; } = - new Parameter(ParameterCategory.ShortWaveRadiation, 3, "Global radiation flux", "W m-2"); + ///Ground deposition of Iodine 131 (Bq m-2) + public static Parameter GroundDepositionOfIodine131 { get; } = new Parameter(ParameterCategory.NuclearRadiology, 4, + "Ground deposition of Iodine 131", "Bq m-2"); - ///Brightness temperature (K) - public static Parameter BrightnessTemperature { get; } = - new Parameter(ParameterCategory.ShortWaveRadiation, 4, "Brightness temperature", "K"); + ///Ground deposition of radioactive pollutant (Bq m-2) + public static Parameter GroundDepositionOfRadioactivePollutant { get; } = new Parameter(ParameterCategory.NuclearRadiology, + 5, "Ground deposition of radioactive pollutant", "Bq m-2"); - ///Radiance (with respect to wave number) (W m-1 sr-1) - public static Parameter RadianceWaveNumber { get; } = new Parameter(ParameterCategory.ShortWaveRadiation, 5, - "Radiance (with respect to wave number)", "W m-1 sr-1"); + ///Time-integrated air concentration of caesium pollutant (Bq s m-3) + public static Parameter TimeIntegratedAirConcentrationOfCaesiumPollutant { get; } = new Parameter( + ParameterCategory.NuclearRadiology, 6, "Time-integrated air concentration of caesium pollutant", "Bq s m-3"); - ///Radiance (with respect to wave length) (W m-3 sr-1) - public static Parameter RadianceWaveLength { get; } = new Parameter(ParameterCategory.ShortWaveRadiation, 6, - "Radiance (with respect to wave length)", "W m-3 sr-1"); + ///Time-integrated air concentration of iodine pollutant (Bq s m-3) + public static Parameter TimeIntegratedAirConcentrationOfIodinePollutant { get; } = new Parameter( + ParameterCategory.NuclearRadiology, 7, "Time-integrated air concentration of iodine pollutant", "Bq s m-3"); - #endregion + ///Time-integrated air concentration of radioactive pollutant (Bq s m-3) + public static Parameter TimeIntegratedAirConcentrationOfRadioactivePollutant { get; } = new Parameter( + ParameterCategory.NuclearRadiology, 8, "Time-integrated air concentration of radioactive pollutant", "Bq s m-3"); - #region Product Discipline 0: Meteorological products, Parameter Category 5: Long-wave Radiation + #endregion - ///Net long wave radiation flux (surface) (W m-2) - public static Parameter NetLongWaveRadiationFluxSurface { get; } = new Parameter(ParameterCategory.LongWaveRadiation, 0, - "Net long wave radiation flux (surface)", "W m-2"); + #region Product Discipline 0: Meteorological products, Parameter Category 19: Physical atmospheric properties - ///Net long wave radiation flux (top of atmosphere) (W m-2) - public static Parameter NetLongWaveRadiationFlux { get; } = new Parameter(ParameterCategory.LongWaveRadiation, 1, - "Net long wave radiation flux (top of atmosphere)", "W m-2"); + ///Visibility (m) + public static Parameter Visibility { get; } = + new Parameter(ParameterCategory.PhysicalAtmosphericProperties, 0, "Visibility", "m"); - ///Long wave radiation flux (W m-2) - public static Parameter LongWaveRadiationFlux { get; } = - new Parameter(ParameterCategory.LongWaveRadiation, 2, "Long wave radiation flux", "W m-2"); + ///Albedo (%) + public static Parameter Albedo { get; } = new Parameter(ParameterCategory.PhysicalAtmosphericProperties, 1, "Albedo", "%"); - #endregion + ///Thunderstorm probability (%) + public static Parameter ThunderstormProbability { get; } = new Parameter(ParameterCategory.PhysicalAtmosphericProperties, + 2, "Thunderstorm probability", "%"); - #region Product Discipline 0: Meteorological products, Parameter Category 6: Cloud + ///mixed layer depth (m) + public static Parameter MixedLayerDepth { get; } = + new Parameter(ParameterCategory.PhysicalAtmosphericProperties, 3, "mixed layer depth", "m"); - ///Cloud Ice (kg m-2) - public static Parameter CloudIce { get; } = new Parameter(ParameterCategory.Cloud, 0, "Cloud Ice", "kg m-2"); + ///Volcanic ash (Code table (4.206)) + public static Parameter VolcanicAsh { get; } = new Parameter(ParameterCategory.PhysicalAtmosphericProperties, 4, + "Volcanic ash", "Code table (4.206)"); - ///Total cloud cover (%) - public static Parameter TotalCloudCover { get; } = new Parameter(ParameterCategory.Cloud, 1, "Total cloud cover", "%"); + ///Icing top (m) + public static Parameter IcingTop { get; } = + new Parameter(ParameterCategory.PhysicalAtmosphericProperties, 5, "Icing top", "m"); - ///Convective cloud cover (%) - public static Parameter ConvectiveCloudCover { get; } = - new Parameter(ParameterCategory.Cloud, 2, "Convective cloud cover", "%"); + ///Icing base (m) + public static Parameter IcingBase { get; } = + new Parameter(ParameterCategory.PhysicalAtmosphericProperties, 6, "Icing base", "m"); - ///Low cloud cover (%) - public static Parameter LowCloudCover { get; } = new Parameter(ParameterCategory.Cloud, 3, "Low cloud cover", "%"); + ///Icing (Code table (4.207)) + public static Parameter Icing { get; } = + new Parameter(ParameterCategory.PhysicalAtmosphericProperties, 7, "Icing", "Code table (4.207)"); - ///Medium cloud cover (%) - public static Parameter MediumCloudCover { get; } = new Parameter(ParameterCategory.Cloud, 4, "Medium cloud cover", "%"); + ///Turbulence top (m) + public static Parameter TurbulenceTop { get; } = + new Parameter(ParameterCategory.PhysicalAtmosphericProperties, 8, "Turbulence top", "m"); - ///High cloud cover (%) - public static Parameter HighCloudCover { get; } = new Parameter(ParameterCategory.Cloud, 5, "High cloud cover", "%"); + ///Turbulence base (m) + public static Parameter TurbulenceBase { get; } = + new Parameter(ParameterCategory.PhysicalAtmosphericProperties, 9, "Turbulence base", "m"); - ///Cloud water (kg m-2) - public static Parameter CloudWater { get; } = new Parameter(ParameterCategory.Cloud, 6, "Cloud water", "kg m-2"); + ///Turbulence (Code table (4.208)) + public static Parameter Turbulence { get; } = new Parameter(ParameterCategory.PhysicalAtmosphericProperties, 10, + "Turbulence", "Code table (4.208)"); - ///Cloud amount (%) - public static Parameter CloudAmount { get; } = new Parameter(ParameterCategory.Cloud, 7, "Cloud amount", "%"); + ///Turbulent kinetic energy (J kg-1) + public static Parameter TurbulentKineticEnergy { get; } = new Parameter(ParameterCategory.PhysicalAtmosphericProperties, + 11, "Turbulent kinetic energy", "J kg-1"); - ///Cloud type (Code table (4.203)) - public static Parameter CloudType { get; } = new Parameter(ParameterCategory.Cloud, 8, "Cloud type", "Code table (4.203)"); + ///Planetary boundary layer regime (Code table (4.209)) + public static Parameter PlanetaryBoundaryLayerRegime { get; } = new Parameter( + ParameterCategory.PhysicalAtmosphericProperties, 12, "Planetary boundary layer regime", "Code table (4.209)"); - ///Thunderstorm maximum tops (m) - public static Parameter ThunderstormMaximumTops { get; } = - new Parameter(ParameterCategory.Cloud, 9, "Thunderstorm maximum tops", "m"); + ///Contrail intensity (Code table (4.210)) + public static Parameter ContrailIntensity { get; } = new Parameter(ParameterCategory.PhysicalAtmosphericProperties, 13, + "Contrail intensity", "Code table (4.210)"); - ///Thunderstorm coverage (Code table (4.204)) - public static Parameter ThunderstormCoverage { get; } = - new Parameter(ParameterCategory.Cloud, 10, "Thunderstorm coverage", "Code table (4.204)"); + ///Contrail engine type (Code table (4.211)) + public static Parameter ContrailEngineType { get; } = new Parameter(ParameterCategory.PhysicalAtmosphericProperties, 14, + "Contrail engine type", "Code table (4.211)"); - ///Cloud base (m) - public static Parameter CloudBase { get; } = new Parameter(ParameterCategory.Cloud, 11, "Cloud base", "m"); + ///Contrail top (m) + public static Parameter ContrailTop { get; } = + new Parameter(ParameterCategory.PhysicalAtmosphericProperties, 15, "Contrail top", "m"); - ///Cloud top (m) - public static Parameter CloudTop { get; } = new Parameter(ParameterCategory.Cloud, 12, "Cloud top", "m"); + ///Contrail (base) + public static Parameter Contrail { get; } = + new Parameter(ParameterCategory.PhysicalAtmosphericProperties, 16, "Contrail", "base"); - ///Ceiling (m) - public static Parameter Ceiling { get; } = new Parameter(ParameterCategory.Cloud, 13, "Ceiling", "m"); + #endregion + + #region Product Discipline 0: Meteorological products, ParameterCategory 20: Atmospheric chemical Constituents - #endregion + public static Parameter MassDensityConcentration { get; } = new( + ParameterCategory.AtmosphericChemicalConstituents, 0, "Mass Density (Concentration)", "kg m-3"); - #region Product Discipline 0: Meteorological products, Parameter Category 7: Thermodynamic Stability Indices + public static Parameter ColumnIntegratedMassDensitySeeNote1 { get; } = new( + ParameterCategory.AtmosphericChemicalConstituents, 1, "Column-Integrated Mass Density (See Note 1)", + "kg m-2"); - ///Parcel lifted index (to 500 hPa) (K) - public static Parameter ParcelLiftedIndex { get; } = new Parameter(ParameterCategory.ThermodynamicStabilityIndices, 0, - "Parcel lifted index (to 500 hPa)", "K"); + public static Parameter MassMixingRatioMassFractionInAir { get; } = new( + ParameterCategory.AtmosphericChemicalConstituents, 2, "Mass Mixing Ratio (Mass Fraction in Air)", + "kg kg-1"); - ///Best lifted index (to 500 hPa) (K) - public static Parameter BestLiftedIndex { get; } = new Parameter(ParameterCategory.ThermodynamicStabilityIndices, 1, - "Best lifted index (to 500 hPa)", "K"); + public static Parameter AtmosphereEmissionMassFlux { get; } = new( + ParameterCategory.AtmosphericChemicalConstituents, 3, "Atmosphere Emission Mass Flux", "kg m-2s-1"); - ///K index (K) - public static Parameter KIndex { get; } = - new Parameter(ParameterCategory.ThermodynamicStabilityIndices, 2, "K index", "K"); + public static Parameter AtmosphereNetProductionMassFlux { get; } = new( + ParameterCategory.AtmosphericChemicalConstituents, 4, "Atmosphere Net Production Mass Flux", "kg m-2s-1"); - ///KO index (K) - public static Parameter KoIndex { get; } = - new Parameter(ParameterCategory.ThermodynamicStabilityIndices, 3, "KO index", "K"); + public static Parameter AtmosphereNetProductionAndEmisionMassFlux { get; } = new( + ParameterCategory.AtmosphericChemicalConstituents, 5, "Atmosphere Net Production And Emision Mass Flux", + "kg m-2s-1"); - ///Total totals index (K) - public static Parameter TotalTotalsIndex { get; } = - new Parameter(ParameterCategory.ThermodynamicStabilityIndices, 4, "Total totals index", "K"); + public static Parameter SurfaceDryDepositionMassFlux { get; } = new( + ParameterCategory.AtmosphericChemicalConstituents, 6, "Surface Dry Deposition Mass Flux", "kg m-2s-1"); - ///Sweat index (numeric) - public static Parameter SweatIndex { get; } = - new Parameter(ParameterCategory.ThermodynamicStabilityIndices, 5, "Sweat index", "numeric"); + public static Parameter SurfaceWetDepositionMassFlux { get; } = new( + ParameterCategory.AtmosphericChemicalConstituents, 7, "Surface Wet Deposition Mass Flux", "kg m-2s-1"); - ///Convective available potential energy (J kg-1) - public static Parameter ConvectiveAvailablePotentialEnergy { get; } = new Parameter( - ParameterCategory.ThermodynamicStabilityIndices, 6, "Convective available potential energy", "J kg-1"); + public static Parameter AtmosphereReEmissionMassFlux { get; } = new( + ParameterCategory.AtmosphericChemicalConstituents, 8, "Atmosphere Re-Emission Mass Flux", "kg m-2s-1"); - ///Convective inhibition (J kg-1) - public static Parameter ConvectiveInhibition { get; } = new Parameter(ParameterCategory.ThermodynamicStabilityIndices, 7, - "Convective inhibition", "J kg-1"); + public static Parameter WetDepositionByLargeScalePrecipitationMassFlux { get; } = new( + ParameterCategory.AtmosphericChemicalConstituents, 9, + "Wet Deposition by Large-Scale Precipitation Mass Flux", "kg m-2s-1"); - ///Storm relative helicity (J kg-1) - public static Parameter StormRelativeHelicity { get; } = new Parameter(ParameterCategory.ThermodynamicStabilityIndices, 8, - "Storm relative helicity", "J kg-1"); + public static Parameter WetDepositionByConvectivePrecipitationMassFlux { get; } = new( + ParameterCategory.AtmosphericChemicalConstituents, 10, + "Wet Deposition by Convective Precipitation Mass Flux", "kg m-2s-1"); - ///Energy helicity index (numeric) - public static Parameter EnergyHelicityIndex { get; } = new Parameter(ParameterCategory.ThermodynamicStabilityIndices, 9, - "Energy helicity index", "numeric"); + public static Parameter SedimentationMassFlux { get; } = + new(ParameterCategory.AtmosphericChemicalConstituents, 11, "Sedimentation Mass Flux", "kg m-2s-1"); - #endregion + public static Parameter DryDepositionMassFlux { get; } = + new(ParameterCategory.AtmosphericChemicalConstituents, 12, "Dry Deposition Mass Flux", "kg m-2s-1"); - #region Product Discipline 0: Meteorological products, Parameter Category 13: Aerosols + public static Parameter TransferFromHydrophobicToHydrophilic { get; } = new( + ParameterCategory.AtmosphericChemicalConstituents, 13, "Transfer From Hydrophobic to Hydrophilic", + "kg kg-1s-1"); - ///Aerosol type (Code table (4.205)) - public static Parameter AerosolType { get; } = - new Parameter(ParameterCategory.Aerosols, 0, "Aerosol type", "Code table (4.205)"); + public static Parameter TransferFromSo2SulphurDioxideToSo4Sulphate { get; } = new( + ParameterCategory.AtmosphericChemicalConstituents, 14, + "Transfer From SO2 (Sulphur Dioxide) to SO4 (Sulphate)", "kg kg-1s-1"); - #endregion + public static Parameter DryDepositionVelocity { get; } = + new(ParameterCategory.AtmosphericChemicalConstituents, 15, "Dry deposition velocity", "m s-1"); - #region Product Discipline 0: Meteorological products, Parameter Category 14: Trace Gases + public static Parameter MassMixingRatioWithRespectToDryAir { get; } = new( + ParameterCategory.AtmosphericChemicalConstituents, 16, "Mass mixing ratio with respect to dry air", + "kg kg-1"); - ///Total ozone (Dobson) - public static Parameter TotalOzone { get; } = new Parameter(ParameterCategory.TraceGases, 0, "Total ozone", "Dobson"); + public static Parameter MassMixingRatioWithRespectToWetAir { get; } = new( + ParameterCategory.AtmosphericChemicalConstituents, 17, "Mass mixing ratio with respect to wet air", + "kg kg-1"); - #endregion + public static Parameter AmountInAtmosphere { get; } = new(ParameterCategory.AtmosphericChemicalConstituents, + 50, "Amount in Atmosphere", "mol"); - #region Product Discipline 0 - Meteorological products, Parameter Category 15: Radar + public static Parameter ConcentrationInAir { get; } = new(ParameterCategory.AtmosphericChemicalConstituents, + 51, "Concentration In Air", "mol m-3"); - ///Base spectrum width (m s-1) - public static Parameter BaseSpectrumWidth { get; } = - new Parameter(ParameterCategory.Radar, 0, "Base spectrum width", "m s-1"); + public static Parameter VolumeMixingRatioFractionInAir { get; } = new( + ParameterCategory.AtmosphericChemicalConstituents, 52, "Volume Mixing Ratio (Fraction in Air)", + "mol mol-1"); - ///Base reflectivity (dB) - public static Parameter BaseReflectivity { get; } = new Parameter(ParameterCategory.Radar, 1, "Base reflectivity", "dB"); + public static Parameter ChemicalGrossProductionRateOfConcentration { get; } = new( + ParameterCategory.AtmosphericChemicalConstituents, 53, "Chemical Gross Production Rate of Concentration", + "mol m-3s-1"); - ///Base radial velocity (m s-1) - public static Parameter BaseRadialVelocity { get; } = - new Parameter(ParameterCategory.Radar, 2, "Base radial velocity", "m s-1"); + public static Parameter ChemicalGrossDestructionRateOfConcentration { get; } = new( + ParameterCategory.AtmosphericChemicalConstituents, 54, "Chemical Gross Destruction Rate of Concentration", + "mol m-3s-1"); - ///Vertically-integrated liquid (kg m-1) - public static Parameter VerticallyIntegratedLiquid { get; } = - new Parameter(ParameterCategory.Radar, 3, "Vertically-integrated liquid", "kg m-1"); + public static Parameter SurfaceFlux { get; } = new(ParameterCategory.AtmosphericChemicalConstituents, 55, + "Surface Flux", "mol m-2s-1"); - ///Layer-maximum base reflectivity (dB) - public static Parameter LayerMaximumBaseReflectivity { get; } = - new Parameter(ParameterCategory.Radar, 4, "Layer-maximum base reflectivity", "dB"); + public static Parameter ChangesOfAmountInAtmosphereSeeNote1 { get; } = new( + ParameterCategory.AtmosphericChemicalConstituents, 56, "Changes Of Amount in Atmosphere (See Note 1)", + "mol s-1"); - ///Precipitation (kg m-2) - public static Parameter Precipitation { get; } = new Parameter(ParameterCategory.Radar, 5, "Precipitation", "kg m-2"); + public static Parameter TotalYearlyAverageBurdenOfTheAtmosphere { get; } = new( + ParameterCategory.AtmosphericChemicalConstituents, 57, "Total Yearly Average Burden of The Atmosphere>", + "mol"); - ///Radar spectra (1) (-) - public static Parameter RadarSpectra1 { get; } = new Parameter(ParameterCategory.Radar, 6, "Radar spectra (1)", "-"); + public static Parameter TotalYearlyAverageAtmosphericLossSeeNote1 { get; } = new( + ParameterCategory.AtmosphericChemicalConstituents, 58, "Total Yearly Average Atmospheric Loss (See Note 1)", + "mol s-1"); - ///Radar spectra (2) (-) - public static Parameter RadarSpectra2 { get; } = new Parameter(ParameterCategory.Radar, 7, "Radar spectra (2)", "-"); + public static Parameter AerosolNumberConcentrationSeeNote2 { get; } = new( + ParameterCategory.AtmosphericChemicalConstituents, 59, "Aerosol Number Concentration (See Note 2)", "m-3"); - ///Radar spectra (3) (-) - public static Parameter RadarSpectra3 { get; } = new Parameter(ParameterCategory.Radar, 8, "Radar spectra (3)", "-"); + public static Parameter AerosolSpecificNumberConcentrationSeeNote2 { get; } = new( + ParameterCategory.AtmosphericChemicalConstituents, 60, "Aerosol Specific Number Concentration (See Note 2)", + "kg-1"); - #endregion + public static Parameter MaximumOfMassDensitySeeNote1 { get; } = new( + ParameterCategory.AtmosphericChemicalConstituents, 61, "Maximum of Mass Density (See Note 1)", "kg m-3"); - #region Product Discipline 0: Meteorological products, Parameter Category 18: Nuclear/radiology + public static Parameter HeightOfMassDensity { get; } = new(ParameterCategory.AtmosphericChemicalConstituents, + 62, "Height of Mass Density", "m"); - ///Air concentration of Caesium 137 (Bq m-3) - public static Parameter AirConcentrationOfCaesium137 { get; } = new Parameter(ParameterCategory.NuclearRadiology, 0, - "Air concentration of Caesium 137", "Bq m-3"); + public static Parameter ColumnAveragedMassDensityInLayer { get; } = new( + ParameterCategory.AtmosphericChemicalConstituents, 63, "Column-Averaged Mass Density in Layer", "kg m-3"); - ///Air concentration of Iodine 131 (Bq m-3) - public static Parameter AirConcentrationOfIodine131 { get; } = new Parameter(ParameterCategory.NuclearRadiology, 1, - "Air concentration of Iodine 131", "Bq m-3"); + public static Parameter MoleFractionWithRespectToDryAir { get; } = new( + ParameterCategory.AtmosphericChemicalConstituents, 64, "Mole fraction with respect to dry air", + "mol mol-1"); - ///Air concentration of radioactive pollutant (Bq m-3) - public static Parameter AirConcentrationOfRadioactivePollutant { get; } = new Parameter(ParameterCategory.NuclearRadiology, - 2, "Air concentration of radioactive pollutant", "Bq m-3"); + public static Parameter MoleFractionWithRespectToWetAir { get; } = new( + ParameterCategory.AtmosphericChemicalConstituents, 65, "Mole fraction with respect to wet air", + "mol mol-1"); - ///Ground deposition of Caesium 137 (Bq m-2) - public static Parameter GroundDepositionOfCaesium137 { get; } = new Parameter(ParameterCategory.NuclearRadiology, 3, - "Ground deposition of Caesium 137", "Bq m-2"); + public static Parameter ColumnintegratedIncloudScavengingRateByPrecipitation { get; } = new( + ParameterCategory.AtmosphericChemicalConstituents, 66, + "Column-integrated in-cloud scavenging rate by precipitation", "kg m-2 s-1"); - ///Ground deposition of Iodine 131 (Bq m-2) - public static Parameter GroundDepositionOfIodine131 { get; } = new Parameter(ParameterCategory.NuclearRadiology, 4, - "Ground deposition of Iodine 131", "Bq m-2"); + public static Parameter ColumnintegratedBelowcloudScavengingRateByPrecipitation { get; } = new( + ParameterCategory.AtmosphericChemicalConstituents, 67, + "Column-integrated below-cloud scavenging rate by precipitation", "kg m-2 s-1"); - ///Ground deposition of radioactive pollutant (Bq m-2) - public static Parameter GroundDepositionOfRadioactivePollutant { get; } = new Parameter(ParameterCategory.NuclearRadiology, - 5, "Ground deposition of radioactive pollutant", "Bq m-2"); + public static Parameter ColumnintegratedReleaseRateFromEvaporatingPrecipitation { get; } = new( + ParameterCategory.AtmosphericChemicalConstituents, 68, + "Column-integrated release rate from evaporating precipitation", "kg m-2 s-1"); - ///Time-integrated air concentration of caesium pollutant (Bq s m-3) - public static Parameter TimeIntegratedAirConcentrationOfCaesiumPollutant { get; } = new Parameter( - ParameterCategory.NuclearRadiology, 6, "Time-integrated air concentration of caesium pollutant", "Bq s m-3"); + public static Parameter ColumnintegratedIncloudScavengingRateByLargescalePrecipitation { get; } = new( + ParameterCategory.AtmosphericChemicalConstituents, 69, + "Column-integrated in-cloud scavenging rate by large-scale precipitation", "kg m-2 s-1"); - ///Time-integrated air concentration of iodine pollutant (Bq s m-3) - public static Parameter TimeIntegratedAirConcentrationOfIodinePollutant { get; } = new Parameter( - ParameterCategory.NuclearRadiology, 7, "Time-integrated air concentration of iodine pollutant", "Bq s m-3"); + public static Parameter ColumnintegratedBelowcloudScavengingRateByLargescalePrecipitation { get; } = new( + ParameterCategory.AtmosphericChemicalConstituents, 70, + "Column-integrated below-cloud scavenging rate by large-scale precipitation", "kg m-2 s-1"); - ///Time-integrated air concentration of radioactive pollutant (Bq s m-3) - public static Parameter TimeIntegratedAirConcentrationOfRadioactivePollutant { get; } = new Parameter( - ParameterCategory.NuclearRadiology, 8, "Time-integrated air concentration of radioactive pollutant", "Bq s m-3"); + public static Parameter ColumnintegratedReleaseRateFromEvaporatingLargescalePrecipitation { get; } = new( + ParameterCategory.AtmosphericChemicalConstituents, 71, + "Column-integrated release rate from evaporating large-scale precipitation", "kg m-2 s-1"); - #endregion + public static Parameter ColumnintegratedIncloudScavengingRateByConvectivePrecipitation { get; } = new( + ParameterCategory.AtmosphericChemicalConstituents, 72, + "Column-integrated in-cloud scavenging rate by convective precipitation", "kg m-2 s-1"); - #region Product Discipline 0: Meteorological products, Parameter Category 19: Physical atmospheric properties + public static Parameter ColumnintegratedBelowcloudScavengingRateByConvectivePrecipitation { get; } = new( + ParameterCategory.AtmosphericChemicalConstituents, 73, + "Column-integrated below-cloud scavenging rate by convective precipitation", "kg m-2 s-1"); - ///Visibility (m) - public static Parameter Visibility { get; } = - new Parameter(ParameterCategory.PhysicalAtmosphericProperties, 0, "Visibility", "m"); + public static Parameter ColumnintegratedReleaseRateFromEvaporatingConvectivePrecipitation { get; } = new( + ParameterCategory.AtmosphericChemicalConstituents, 74, + "Column-integrated release rate from evaporating convective precipitation", "kg m-2 s-1"); - ///Albedo (%) - public static Parameter Albedo { get; } = new Parameter(ParameterCategory.PhysicalAtmosphericProperties, 1, "Albedo", "%"); + public static Parameter WildfireFlux { get; } = new(ParameterCategory.AtmosphericChemicalConstituents, 75, + "Wildfire flux", "kg m-2 s-1"); - ///Thunderstorm probability (%) - public static Parameter ThunderstormProbability { get; } = new Parameter(ParameterCategory.PhysicalAtmosphericProperties, - 2, "Thunderstorm probability", "%"); + public static Parameter EmissionRate { get; } = new(ParameterCategory.AtmosphericChemicalConstituents, 76, + "Emission Rate", "kg kg-1 s-1"); - ///mixed layer depth (m) - public static Parameter MixedLayerDepth { get; } = - new Parameter(ParameterCategory.PhysicalAtmosphericProperties, 3, "mixed layer depth", "m"); + public static Parameter SurfaceEmissionFlux { get; } = new(ParameterCategory.AtmosphericChemicalConstituents, + 77, "Surface Emission flux", "kg m-2 s-1"); - ///Volcanic ash (Code table (4.206)) - public static Parameter VolcanicAsh { get; } = new Parameter(ParameterCategory.PhysicalAtmosphericProperties, 4, - "Volcanic ash", "Code table (4.206)"); + public static Parameter SurfaceAreaDensityAerosol { get; } = new( + ParameterCategory.AtmosphericChemicalConstituents, 100, "Surface Area Density (Aerosol)", "m-1"); - ///Icing top (m) - public static Parameter IcingTop { get; } = - new Parameter(ParameterCategory.PhysicalAtmosphericProperties, 5, "Icing top", "m"); + public static Parameter VerticalVisualRange { get; } = new(ParameterCategory.AtmosphericChemicalConstituents, + 101, "Vertical Visual Range", "m"); - ///Icing base (m) - public static Parameter IcingBase { get; } = - new Parameter(ParameterCategory.PhysicalAtmosphericProperties, 6, "Icing base", "m"); + public static Parameter AerosolOpticalThickness { get; } = new( + ParameterCategory.AtmosphericChemicalConstituents, 102, "Aerosol Optical Thickness", "Numeric"); - ///Icing (Code table (4.207)) - public static Parameter Icing { get; } = - new Parameter(ParameterCategory.PhysicalAtmosphericProperties, 7, "Icing", "Code table (4.207)"); + public static Parameter SingleScatteringAlbedo { get; } = + new(ParameterCategory.AtmosphericChemicalConstituents, 103, "Single Scattering Albedo", "Numeric"); - ///Turbulence top (m) - public static Parameter TurbulenceTop { get; } = - new Parameter(ParameterCategory.PhysicalAtmosphericProperties, 8, "Turbulence top", "m"); + public static Parameter AsymmetryFactor { get; } = new(ParameterCategory.AtmosphericChemicalConstituents, 104, + "Asymmetry Factor", "Numeric"); - ///Turbulence base (m) - public static Parameter TurbulenceBase { get; } = - new Parameter(ParameterCategory.PhysicalAtmosphericProperties, 9, "Turbulence base", "m"); + public static Parameter AerosolExtinctionCoefficient { get; } = new( + ParameterCategory.AtmosphericChemicalConstituents, 105, "Aerosol Extinction Coefficient", "m-1"); - ///Turbulence (Code table (4.208)) - public static Parameter Turbulence { get; } = new Parameter(ParameterCategory.PhysicalAtmosphericProperties, 10, - "Turbulence", "Code table (4.208)"); + public static Parameter AerosolAbsorptionCoefficient { get; } = new( + ParameterCategory.AtmosphericChemicalConstituents, 106, "Aerosol Absorption Coefficient", "m-1"); - ///Turbulent kinetic energy (J kg-1) - public static Parameter TurbulentKineticEnergy { get; } = new Parameter(ParameterCategory.PhysicalAtmosphericProperties, - 11, "Turbulent kinetic energy", "J kg-1"); + public static Parameter AerosolLidarBackscatterFromSatellite { get; } = new( + ParameterCategory.AtmosphericChemicalConstituents, 107, "Aerosol Lidar Backscatter from Satellite", + "m-1sr-1"); - ///Planetary boundary layer regime (Code table (4.209)) - public static Parameter PlanetaryBoundaryLayerRegime { get; } = new Parameter( - ParameterCategory.PhysicalAtmosphericProperties, 12, "Planetary boundary layer regime", "Code table (4.209)"); + public static Parameter AerosolLidarBackscatterFromTheGround { get; } = new( + ParameterCategory.AtmosphericChemicalConstituents, 108, "Aerosol Lidar Backscatter from the Ground", + "m-1sr-1"); - ///Contrail intensity (Code table (4.210)) - public static Parameter ContrailIntensity { get; } = new Parameter(ParameterCategory.PhysicalAtmosphericProperties, 13, - "Contrail intensity", "Code table (4.210)"); + public static Parameter AerosolLidarExtinctionFromSatellite { get; } = new( + ParameterCategory.AtmosphericChemicalConstituents, 109, "Aerosol Lidar Extinction from Satellite", "m-1"); - ///Contrail engine type (Code table (4.211)) - public static Parameter ContrailEngineType { get; } = new Parameter(ParameterCategory.PhysicalAtmosphericProperties, 14, - "Contrail engine type", "Code table (4.211)"); + public static Parameter AerosolLidarExtinctionFromTheGround { get; } = new( + ParameterCategory.AtmosphericChemicalConstituents, 110, "Aerosol Lidar Extinction from the Ground", "m-1"); - ///Contrail top (m) - public static Parameter ContrailTop { get; } = - new Parameter(ParameterCategory.PhysicalAtmosphericProperties, 15, "Contrail top", "m"); + public static Parameter AngstromExponent { get; } = new(ParameterCategory.AtmosphericChemicalConstituents, 111, + "Angstrom Exponent", "Numeric"); - ///Contrail (base) - public static Parameter Contrail { get; } = - new Parameter(ParameterCategory.PhysicalAtmosphericProperties, 16, "Contrail", "base"); + public static Parameter ScatteringAerosolOpticalThickness { get; } = new( + ParameterCategory.AtmosphericChemicalConstituents, 112, "Scattering Aerosol Optical Thickness", "Numeric"); - #endregion + #endregion - #region Product Discipline 0: Meteorological products, Parameter Category 253: ASCII character string + #region Product Discipline 0: Meteorological products, Parameter Category 253: ASCII character string - ///Arbitrary text string CCITTIA5 - public static Parameter ArbitraryTextStringCcittia5 { get; } = - new Parameter(ParameterCategory.CcittIa5String, 0, "Arbitrary text string CCITTIA5", ""); + ///Arbitrary text string CCITTIA5 + public static Parameter ArbitraryTextStringCcittia5 { get; } = + new Parameter(ParameterCategory.CcittIa5String, 0, "Arbitrary text string CCITTIA5", ""); - #endregion + #endregion - #region Product Discipline 1: Hydrologic products, Parameter Category 0: Hydrology basic products + #region Product Discipline 1: Hydrologic products, Parameter Category 0: Hydrology basic products - ///Flash flood guidance (Encoded as an accumulation over a floating subinterval of time between the reference time and valid time) (kg m-2) - public static Parameter FlashFloodGuidance { get; } = new Parameter(ParameterCategory.HydrologyBasicProducts, 0, - "Flash flood guidance (Encoded as an accumulation over a floating subinterval of time between the reference time and valid time)", - "kg m-2"); + ///Flash flood guidance (Encoded as an accumulation over a floating subinterval of time between the reference time and valid time) (kg m-2) + public static Parameter FlashFloodGuidance { get; } = new Parameter(ParameterCategory.HydrologyBasicProducts, 0, + "Flash flood guidance (Encoded as an accumulation over a floating subinterval of time between the reference time and valid time)", + "kg m-2"); - ///Flash flood runoff (Encoded as an accumulation over a floating subinterval of time) (kg m-2) - public static Parameter FlashFloodRunoff { get; } = new Parameter(ParameterCategory.HydrologyBasicProducts, 1, - "Flash flood runoff (Encoded as an accumulation over a floating subinterval of time)", "kg m-2"); + ///Flash flood runoff (Encoded as an accumulation over a floating subinterval of time) (kg m-2) + public static Parameter FlashFloodRunoff { get; } = new Parameter(ParameterCategory.HydrologyBasicProducts, 1, + "Flash flood runoff (Encoded as an accumulation over a floating subinterval of time)", "kg m-2"); - ///Remotely sensed snow cover (code table 4.215) - public static Parameter RemotelySensedSnowCover { get; } = new Parameter(ParameterCategory.HydrologyBasicProducts, 2, - "Remotely sensed snow cover (code table 4.215)", ""); + ///Remotely sensed snow cover (code table 4.215) + public static Parameter RemotelySensedSnowCover { get; } = new Parameter(ParameterCategory.HydrologyBasicProducts, 2, + "Remotely sensed snow cover (code table 4.215)", ""); - ///Elevation of snow covered terrain (code table 4.216) - public static Parameter ElevationOfSnowCoveredTerrain { get; } = new Parameter(ParameterCategory.HydrologyBasicProducts, 3, - "Elevation of snow covered terrain (code table 4.216)", ""); + ///Elevation of snow covered terrain (code table 4.216) + public static Parameter ElevationOfSnowCoveredTerrain { get; } = new Parameter(ParameterCategory.HydrologyBasicProducts, 3, + "Elevation of snow covered terrain (code table 4.216)", ""); - ///Snow water equivalent percent of normal (%) - public static Parameter SnowWaterEquivalentPercentOfNormal { get; } = - new Parameter(ParameterCategory.HydrologyBasicProducts, 4, "Snow water equivalent percent of normal", "%"); + ///Snow water equivalent percent of normal (%) + public static Parameter SnowWaterEquivalentPercentOfNormal { get; } = + new Parameter(ParameterCategory.HydrologyBasicProducts, 4, "Snow water equivalent percent of normal", "%"); - #endregion + #endregion - #region Product Discipline 1: Hydrologic products, Parameter Category 1: Hydrology probabilities + #region Product Discipline 1: Hydrologic products, Parameter Category 1: Hydrology probabilities - ///Conditional percent precipitation amount fractile for an overall period (kg m-2(Encoded as an accumulation).) - public static Parameter ConditionalPercentPrecipitationAmountFractileForAnOverallPeriod { get; } = new Parameter( - ParameterCategory.HydrologyProbabilities, 0, "Conditional percent precipitation amount fractile for an overall period", - "kg m-2(Encoded as an accumulation)."); + ///Conditional percent precipitation amount fractile for an overall period (kg m-2(Encoded as an accumulation).) + public static Parameter ConditionalPercentPrecipitationAmountFractileForAnOverallPeriod { get; } = new Parameter( + ParameterCategory.HydrologyProbabilities, 0, "Conditional percent precipitation amount fractile for an overall period", + "kg m-2(Encoded as an accumulation)."); - ///Percent precipitation in a sub-period of an overall period (Encoded as per cent accumulation over the sub-period) (%) - public static Parameter PercentPrecipitationInASubPeriodOfAnOverallPeriod { get; } = new Parameter( - ParameterCategory.HydrologyProbabilities, 1, - "Percent precipitation in a sub-period of an overall period (Encoded as per cent accumulation over the sub-period)", - "%"); + ///Percent precipitation in a sub-period of an overall period (Encoded as per cent accumulation over the sub-period) (%) + public static Parameter PercentPrecipitationInASubPeriodOfAnOverallPeriod { get; } = new Parameter( + ParameterCategory.HydrologyProbabilities, 1, + "Percent precipitation in a sub-period of an overall period (Encoded as per cent accumulation over the sub-period)", + "%"); - ///Probability of 0.01 inch of precipitation (POP) (%) - public static Parameter ProbabilityOf001InchOfPrecipitationPop { get; } = - new Parameter(ParameterCategory.HydrologyProbabilities, 2, "Probability of 0.01 inch of precipitation (POP)", "%"); + ///Probability of 0.01 inch of precipitation (POP) (%) + public static Parameter ProbabilityOf001InchOfPrecipitationPop { get; } = + new Parameter(ParameterCategory.HydrologyProbabilities, 2, "Probability of 0.01 inch of precipitation (POP)", "%"); - #endregion + #endregion - #region Product Discipline 2: Land surface products, Parameter Category 0: Vegetation/Biomass + #region Product Discipline 2: Land surface products, Parameter Category 0: Vegetation/Biomass - ///Land cover (1=land, 2=sea) (Proportion) - public static Parameter LandCover { get; } = - new Parameter(ParameterCategory.VegetationBiomass, 0, "Land cover (1=land, 2=sea)", "Proportion"); + ///Land cover (1=land, 2=sea) (Proportion) + public static Parameter LandCover { get; } = + new Parameter(ParameterCategory.VegetationBiomass, 0, "Land cover (1=land, 2=sea)", "Proportion"); - ///Surface roughness (m) - public static Parameter SurfaceRoughness { get; } = - new Parameter(ParameterCategory.VegetationBiomass, 1, "Surface roughness", "m"); + ///Surface roughness (m) + public static Parameter SurfaceRoughness { get; } = + new Parameter(ParameterCategory.VegetationBiomass, 1, "Surface roughness", "m"); - ///Soil temperature - public static Parameter SoilTemperature { get; } = - new Parameter(ParameterCategory.VegetationBiomass, 2, "Soil temperature", ""); + ///Soil temperature + public static Parameter SoilTemperature { get; } = + new Parameter(ParameterCategory.VegetationBiomass, 2, "Soil temperature", ""); - ///Soil moisture content (kg m-2) - public static Parameter SoilMoistureContent { get; } = - new Parameter(ParameterCategory.VegetationBiomass, 3, "Soil moisture content", "kg m-2"); + ///Soil moisture content (kg m-2) + public static Parameter SoilMoistureContent { get; } = + new Parameter(ParameterCategory.VegetationBiomass, 3, "Soil moisture content", "kg m-2"); - ///Vegetation (%) - public static Parameter Vegetation { get; } = new Parameter(ParameterCategory.VegetationBiomass, 4, "Vegetation", "%"); + ///Vegetation (%) + public static Parameter Vegetation { get; } = new Parameter(ParameterCategory.VegetationBiomass, 4, "Vegetation", "%"); - ///Water runoff (kg m-2) - public static Parameter WaterRunoff { get; } = - new Parameter(ParameterCategory.VegetationBiomass, 5, "Water runoff", "kg m-2"); + ///Water runoff (kg m-2) + public static Parameter WaterRunoff { get; } = + new Parameter(ParameterCategory.VegetationBiomass, 5, "Water runoff", "kg m-2"); - ///Evapotranspiration (kg-2 s-1) - public static Parameter Evapotranspiration { get; } = - new Parameter(ParameterCategory.VegetationBiomass, 6, "Evapotranspiration", "kg-2 s-1"); + ///Evapotranspiration (kg-2 s-1) + public static Parameter Evapotranspiration { get; } = + new Parameter(ParameterCategory.VegetationBiomass, 6, "Evapotranspiration", "kg-2 s-1"); - ///Model terrain height (m) - public static Parameter ModelTerrainHeight { get; } = - new Parameter(ParameterCategory.VegetationBiomass, 7, "Model terrain height", "m"); + ///Model terrain height (m) + public static Parameter ModelTerrainHeight { get; } = + new Parameter(ParameterCategory.VegetationBiomass, 7, "Model terrain height", "m"); - ///Land use (Code table (4.212)) - public static Parameter LandUse { get; } = - new Parameter(ParameterCategory.VegetationBiomass, 8, "Land use", "Code table (4.212)"); + ///Land use (Code table (4.212)) + public static Parameter LandUse { get; } = + new Parameter(ParameterCategory.VegetationBiomass, 8, "Land use", "Code table (4.212)"); - #endregion + #endregion - #region Product Discipline 2: Land surface products, Parameter Category 3: Soil Products + #region Product Discipline 2: Land surface products, Parameter Category 3: Soil Products - ///Soil type (Code table (4.213)) - public static Parameter SoilType { get; } = - new Parameter(ParameterCategory.SoilProducts, 0, "Soil type", "Code table (4.213)"); + ///Soil type (Code table (4.213)) + public static Parameter SoilType { get; } = + new Parameter(ParameterCategory.SoilProducts, 0, "Soil type", "Code table (4.213)"); - ///Upper layer soil temperature (K) - public static Parameter UpperLayerSoilTemperature { get; } = - new Parameter(ParameterCategory.SoilProducts, 1, "Upper layer soil temperature", "K"); + ///Upper layer soil temperature (K) + public static Parameter UpperLayerSoilTemperature { get; } = + new Parameter(ParameterCategory.SoilProducts, 1, "Upper layer soil temperature", "K"); - ///Upper layer soil moisture (kg m-3) - public static Parameter UpperLayerSoilMoisture { get; } = - new Parameter(ParameterCategory.SoilProducts, 2, "Upper layer soil moisture", "kg m-3"); + ///Upper layer soil moisture (kg m-3) + public static Parameter UpperLayerSoilMoisture { get; } = + new Parameter(ParameterCategory.SoilProducts, 2, "Upper layer soil moisture", "kg m-3"); - ///Lower layer soil moisture (kg m-3) - public static Parameter LowerLayerSoilMoisture { get; } = - new Parameter(ParameterCategory.SoilProducts, 3, "Lower layer soil moisture", "kg m-3"); + ///Lower layer soil moisture (kg m-3) + public static Parameter LowerLayerSoilMoisture { get; } = + new Parameter(ParameterCategory.SoilProducts, 3, "Lower layer soil moisture", "kg m-3"); - ///Bottom layer soil temperature (K) - public static Parameter BottomLayerSoilTemperature { get; } = - new Parameter(ParameterCategory.SoilProducts, 4, "Bottom layer soil temperature", "K"); + ///Bottom layer soil temperature (K) + public static Parameter BottomLayerSoilTemperature { get; } = + new Parameter(ParameterCategory.SoilProducts, 4, "Bottom layer soil temperature", "K"); - #endregion + #endregion - #region Product Discipline 3: Space products, Parameter Category 0: Image format products + #region Product Discipline 3: Space products, Parameter Category 0: Image format products - ///Scaled radiance (numeric) - public static Parameter ScaledRadiance { get; } = - new Parameter(ParameterCategory.ImageFormatProducts, 0, "Scaled radiance", "numeric"); + ///Scaled radiance (numeric) + public static Parameter ScaledRadiance { get; } = + new Parameter(ParameterCategory.ImageFormatProducts, 0, "Scaled radiance", "numeric"); - ///Scaled albedo (numeric) - public static Parameter ScaledAlbedo { get; } = - new Parameter(ParameterCategory.ImageFormatProducts, 1, "Scaled albedo", "numeric"); + ///Scaled albedo (numeric) + public static Parameter ScaledAlbedo { get; } = + new Parameter(ParameterCategory.ImageFormatProducts, 1, "Scaled albedo", "numeric"); - ///Scaled brightness temperature (numeric) - public static Parameter ScaledBrightnessTemperature { get; } = new Parameter(ParameterCategory.ImageFormatProducts, 2, - "Scaled brightness temperature", "numeric"); + ///Scaled brightness temperature (numeric) + public static Parameter ScaledBrightnessTemperature { get; } = new Parameter(ParameterCategory.ImageFormatProducts, 2, + "Scaled brightness temperature", "numeric"); - ///Scaled precipitable water (numeric) - public static Parameter ScaledPrecipitableWater { get; } = - new Parameter(ParameterCategory.ImageFormatProducts, 3, "Scaled precipitable water", "numeric"); + ///Scaled precipitable water (numeric) + public static Parameter ScaledPrecipitableWater { get; } = + new Parameter(ParameterCategory.ImageFormatProducts, 3, "Scaled precipitable water", "numeric"); - ///Scaled lifted index (numeric) - public static Parameter ScaledLiftedIndex { get; } = - new Parameter(ParameterCategory.ImageFormatProducts, 4, "Scaled lifted index", "numeric"); + ///Scaled lifted index (numeric) + public static Parameter ScaledLiftedIndex { get; } = + new Parameter(ParameterCategory.ImageFormatProducts, 4, "Scaled lifted index", "numeric"); - ///Scaled cloud top pressure (numeric) - public static Parameter ScaledCloudTopPressure { get; } = - new Parameter(ParameterCategory.ImageFormatProducts, 5, "Scaled cloud top pressure", "numeric"); + ///Scaled cloud top pressure (numeric) + public static Parameter ScaledCloudTopPressure { get; } = + new Parameter(ParameterCategory.ImageFormatProducts, 5, "Scaled cloud top pressure", "numeric"); - ///Scaled skin temperature (numeric) - public static Parameter ScaledSkinTemperature { get; } = - new Parameter(ParameterCategory.ImageFormatProducts, 6, "Scaled skin temperature", "numeric"); + ///Scaled skin temperature (numeric) + public static Parameter ScaledSkinTemperature { get; } = + new Parameter(ParameterCategory.ImageFormatProducts, 6, "Scaled skin temperature", "numeric"); - ///Cloud mask (Code table 4.217) - public static Parameter CloudMask { get; } = - new Parameter(ParameterCategory.ImageFormatProducts, 7, "Cloud mask", "Code table 4.217"); + ///Cloud mask (Code table 4.217) + public static Parameter CloudMask { get; } = + new Parameter(ParameterCategory.ImageFormatProducts, 7, "Cloud mask", "Code table 4.217"); - #endregion + #endregion - #region Product Discipline 3: Space products, Parameter Category 1: Quantitative products + #region Product Discipline 3: Space products, Parameter Category 1: Quantitative products - ///Estimated precipitation (kg m-2) - public static Parameter EstimatedPrecipitation { get; } = - new Parameter(ParameterCategory.QuantitativeProducts, 0, "Estimated precipitation", "kg m-2"); + ///Estimated precipitation (kg m-2) + public static Parameter EstimatedPrecipitation { get; } = + new Parameter(ParameterCategory.QuantitativeProducts, 0, "Estimated precipitation", "kg m-2"); - #endregion + #endregion - #region Product Discipline 10: Oceanographic products, Parameter Category 0: Waves + #region Product Discipline 10: Oceanographic products, Parameter Category 0: Waves - ///Wave spectra (1) (-) - public static Parameter WaveSpectra1 { get; } = new Parameter(ParameterCategory.Waves, 0, "Wave spectra (1)", "-"); + ///Wave spectra (1) (-) + public static Parameter WaveSpectra1 { get; } = new Parameter(ParameterCategory.Waves, 0, "Wave spectra (1)", "-"); - ///Wave spectra (2) (-) - public static Parameter WaveSpectra2 { get; } = new Parameter(ParameterCategory.Waves, 1, "Wave spectra (2)", "-"); + ///Wave spectra (2) (-) + public static Parameter WaveSpectra2 { get; } = new Parameter(ParameterCategory.Waves, 1, "Wave spectra (2)", "-"); - ///Wave spectra (3) (-) - public static Parameter WaveSpectra3 { get; } = new Parameter(ParameterCategory.Waves, 2, "Wave spectra (3)", "-"); + ///Wave spectra (3) (-) + public static Parameter WaveSpectra3 { get; } = new Parameter(ParameterCategory.Waves, 2, "Wave spectra (3)", "-"); - ///Significant height of combined wind waves and swell (m) - public static Parameter SignificantHeightOfCombinedWindWavesAndSwell { get; } = new Parameter(ParameterCategory.Waves, 3, - "Significant height of combined wind waves and swell", "m"); + ///Significant height of combined wind waves and swell (m) + public static Parameter SignificantHeightOfCombinedWindWavesAndSwell { get; } = new Parameter(ParameterCategory.Waves, 3, + "Significant height of combined wind waves and swell", "m"); - ///Direction of wind waves (Degree true) - public static Parameter DirectionOfWindWaves { get; } = - new Parameter(ParameterCategory.Waves, 4, "Direction of wind waves", "Degree true"); + ///Direction of wind waves (Degree true) + public static Parameter DirectionOfWindWaves { get; } = + new Parameter(ParameterCategory.Waves, 4, "Direction of wind waves", "Degree true"); - ///Significant height of wind waves (m) - public static Parameter SignificantHeightOfWindWaves { get; } = - new Parameter(ParameterCategory.Waves, 5, "Significant height of wind waves", "m"); + ///Significant height of wind waves (m) + public static Parameter SignificantHeightOfWindWaves { get; } = + new Parameter(ParameterCategory.Waves, 5, "Significant height of wind waves", "m"); - ///Mean period of wind waves (s) - public static Parameter MeanPeriodOfWindWaves { get; } = - new Parameter(ParameterCategory.Waves, 6, "Mean period of wind waves", "s"); + ///Mean period of wind waves (s) + public static Parameter MeanPeriodOfWindWaves { get; } = + new Parameter(ParameterCategory.Waves, 6, "Mean period of wind waves", "s"); - ///Direction of swell waves (Degree true) - public static Parameter DirectionOfSwellWaves { get; } = - new Parameter(ParameterCategory.Waves, 7, "Direction of swell waves", "Degree true"); + ///Direction of swell waves (Degree true) + public static Parameter DirectionOfSwellWaves { get; } = + new Parameter(ParameterCategory.Waves, 7, "Direction of swell waves", "Degree true"); - ///Significant height of swell waves (m) - public static Parameter SignificantHeightOfSwellWaves { get; } = - new Parameter(ParameterCategory.Waves, 8, "Significant height of swell waves", "m"); + ///Significant height of swell waves (m) + public static Parameter SignificantHeightOfSwellWaves { get; } = + new Parameter(ParameterCategory.Waves, 8, "Significant height of swell waves", "m"); - ///Mean period of swell waves (s) - public static Parameter MeanPeriodOfSwellWaves { get; } = - new Parameter(ParameterCategory.Waves, 9, "Mean period of swell waves", "s"); + ///Mean period of swell waves (s) + public static Parameter MeanPeriodOfSwellWaves { get; } = + new Parameter(ParameterCategory.Waves, 9, "Mean period of swell waves", "s"); - ///Primary wave direction (Degree true) - public static Parameter PrimaryWaveDirection { get; } = - new Parameter(ParameterCategory.Waves, 10, "Primary wave direction", "Degree true"); + ///Primary wave direction (Degree true) + public static Parameter PrimaryWaveDirection { get; } = + new Parameter(ParameterCategory.Waves, 10, "Primary wave direction", "Degree true"); - ///Primary wave mean period (s) - public static Parameter PrimaryWaveMeanPeriod { get; } = - new Parameter(ParameterCategory.Waves, 11, "Primary wave mean period", "s"); + ///Primary wave mean period (s) + public static Parameter PrimaryWaveMeanPeriod { get; } = + new Parameter(ParameterCategory.Waves, 11, "Primary wave mean period", "s"); - ///Secondary wave direction (Degree true) - public static Parameter SecondaryWaveDirection { get; } = - new Parameter(ParameterCategory.Waves, 12, "Secondary wave direction", "Degree true"); + ///Secondary wave direction (Degree true) + public static Parameter SecondaryWaveDirection { get; } = + new Parameter(ParameterCategory.Waves, 12, "Secondary wave direction", "Degree true"); - ///Secondary wave mean period (s) - public static Parameter SecondaryWaveMeanPeriod { get; } = - new Parameter(ParameterCategory.Waves, 13, "Secondary wave mean period", "s"); + ///Secondary wave mean period (s) + public static Parameter SecondaryWaveMeanPeriod { get; } = + new Parameter(ParameterCategory.Waves, 13, "Secondary wave mean period", "s"); - #endregion + #endregion - #region Product Discipline 10: Oceanographic products, Parameter Category 1: Currents + #region Product Discipline 10: Oceanographic products, Parameter Category 1: Currents - ///Current direction (Degree true) - public static Parameter CurrentDirection { get; } = - new Parameter(ParameterCategory.Currents, 0, "Current direction", "Degree true"); + ///Current direction (Degree true) + public static Parameter CurrentDirection { get; } = + new Parameter(ParameterCategory.Currents, 0, "Current direction", "Degree true"); - ///Current speed (m s-1) - public static Parameter CurrentSpeed { get; } = new Parameter(ParameterCategory.Currents, 1, "Current speed", "m s-1"); + ///Current speed (m s-1) + public static Parameter CurrentSpeed { get; } = new Parameter(ParameterCategory.Currents, 1, "Current speed", "m s-1"); - ///u-component of current (m s-1) - public static Parameter UComponentOfCurrent { get; } = - new Parameter(ParameterCategory.Currents, 2, "u-component of current", "m s-1"); + ///u-component of current (m s-1) + public static Parameter UComponentOfCurrent { get; } = + new Parameter(ParameterCategory.Currents, 2, "u-component of current", "m s-1"); - ///v-component of current (m s-1) - public static Parameter VComponentOfCurrent { get; } = - new Parameter(ParameterCategory.Currents, 3, "v-component of current", "m s-1"); + ///v-component of current (m s-1) + public static Parameter VComponentOfCurrent { get; } = + new Parameter(ParameterCategory.Currents, 3, "v-component of current", "m s-1"); - #endregion + #endregion - #region Product Discipline 10: Oceanographic products, Parameter Category 2: Ice + #region Product Discipline 10: Oceanographic products, Parameter Category 2: Ice - ///Ice cover (Proportion) - public static Parameter IceCover { get; } = new Parameter(ParameterCategory.Ice, 0, "Ice cover", "Proportion"); - - ///Ice thickness (m) - public static Parameter IceThickness { get; } = new Parameter(ParameterCategory.Ice, 1, "Ice thickness", "m"); - - ///Direction of ice drift (Degree true) - public static Parameter DirectionOfIceDrift { get; } = - new Parameter(ParameterCategory.Ice, 2, "Direction of ice drift", "Degree true"); - - ///Speed of ice drift (m s-1) - public static Parameter SpeedOfIceDrift { get; } = new Parameter(ParameterCategory.Ice, 3, "Speed of ice drift", "m s-1"); - - ///u-component of ice drift (m s-1) - public static Parameter UComponentOfIceDrift { get; } = - new Parameter(ParameterCategory.Ice, 4, "u-component of ice drift", "m s-1"); - - ///v-component of ice drift (m s-1) - public static Parameter VComponentOfIceDrift { get; } = - new Parameter(ParameterCategory.Ice, 5, "v-component of ice drift", "m s-1"); - - ///Ice growth rate (m s-1) - public static Parameter IceGrowthRate { get; } = new Parameter(ParameterCategory.Ice, 6, "Ice growth rate", "m s-1"); - - ///Ice divergence (s-1) - public static Parameter IceDivergence { get; } = new Parameter(ParameterCategory.Ice, 7, "Ice divergence", "s-1"); - - #endregion - - #region Product Discipline 10: Oceanographic products, Parameter Category 3: Surface Properties - - ///Water temperature (K) - public static Parameter WaterTemperature { get; } = - new Parameter(ParameterCategory.SurfaceProperties, 0, "Water temperature", "K"); - - ///Deviation of sea level from mean (m) - public static Parameter DeviationOfSeaLevelFromMean { get; } = - new Parameter(ParameterCategory.SurfaceProperties, 1, "Deviation of sea level from mean", "m"); - - #endregion - - #region Product Discipline 10: Oceanographic products, Parameter Category 4: Sub-surface Properties - - ///Main thermocline depth (m) - public static Parameter MainThermoclineDepth { get; } = - new Parameter(ParameterCategory.SubSurfaceProperties, 0, "Main thermocline depth", "m"); - - ///Main thermocline anomaly (m) - public static Parameter MainThermoclineAnomaly { get; } = - new Parameter(ParameterCategory.SubSurfaceProperties, 1, "Main thermocline anomaly", "m"); - - ///Transient thermocline depth (m) - public static Parameter TransientThermoclineDepth { get; } = - new Parameter(ParameterCategory.SubSurfaceProperties, 2, "Transient thermocline depth", "m"); - - ///Salinity (kg kg-1) - public static Parameter Salinity { get; } = - new Parameter(ParameterCategory.SubSurfaceProperties, 3, "Salinity", "kg kg-1"); - - #endregion - - public static IReadOnlyDictionary> ParametersByCategory { get; } = - ImmutableList.Empty - .Add(Temperature) - .Add(VirtualTemperature) - .Add(PotentialTemperature) - .Add(PseudoAdiabaticPotentialTemperatureOrEquivalentPotentialTemperature) - .Add(MaximumTemperature) - .Add(MinimumTemperature) - .Add(DewPointTemperature) - .Add(DewPointDepression) - .Add(LapseRate) - .Add(TemperatureAnomaly) - .Add(LatentHeatNetFlux) - .Add(SensibleHeatNetFlux) - .Add(HeatIndex) - .Add(WindChillFactor) - .Add(MinimumDewPointDepression) - .Add(VirtualPotentialTemperature) - .Add(SnowPhaseChangeHeatFlux) - .Add(SkinTemperature) - .Add(SnowTemperature) - .Add(TurbulentTransferCoefficientForHeat) - .Add(TurbulentDiffusionCoefficientForHeat) - .Add(ApparentTemperature) - .Add(TemperatureTendencyDueToShortWaveRadiation) - .Add(TemperatureTendencyDueToLongWaveRadiation) - .Add(TemperatureTendencyDueToShortWaveRadiationClearSky) - .Add(TemperatureTendencyDueToLongWaveRadiationClearSky) - .Add(TemperatureTendencyDueToParameterizations) - .Add(WetBulbTemperature) - .Add(UnbalancedComponentOfTemperature) - .Add(TemperatureAdvection) - .Add(SpecificHumidity) - .Add(RelativeHumidity) - .Add(HumidityMixingRatio) - .Add(PrecipitableWater) - .Add(VaporPressure) - .Add(SaturationDeficit) - .Add(Evaporation) - .Add(PrecipitationRate) - .Add(TotalPrecipitation) - .Add(LargeScalePrecipitationNonConvective) - .Add(ConvectivePrecipitation) - .Add(SnowDepth) - .Add(SnowfallRateWaterEquivalent) - .Add(WaterEquivalentOfAccumulatedSnowDepth) - .Add(ConvectiveSnow) - .Add(LargeScaleSnow) - .Add(SnowMelt) - .Add(SnowAge) - .Add(AbsoluteHumidity) - .Add(PrecipitationType) - .Add(IntegratedLiquidWater) - .Add(Condensate) - .Add(CloudMixingRatio) - .Add(IceWaterMixingRatio) - .Add(RainMixingRatio) - .Add(SnowMixingRatio) - .Add(HorizontalMoistureConvergence) - .Add(MaximumRelativeHumidity) - .Add(MaximumAbsoluteHumidity) - .Add(TotalSnowfall) - .Add(PrecipitableWaterCategory) - .Add(Hail) - .Add(Graupel) - .Add(CategoricalRain) - .Add(CategoricalFreezingRain) - .Add(CategoricalIcePellets) - .Add(CategoricalSnow) - .Add(ConvectivePrecipitationRate) - .Add(HorizontalMoistureDivergence) - .Add(PercentFrozenPrecipitation) - .Add(PotentialEvaporation) - .Add(PotentialEvaporationRate) - .Add(SnowCover) - .Add(RainFractionOfTotalCloudWater) - .Add(RimeFactor) - .Add(TotalColumnIntegratedRain) - .Add(TotalColumnIntegratedSnow) - .Add(LargeScaleWaterPrecipitation) - .Add(ConvectiveWaterPrecipitation) - .Add(TotalWaterPrecipitation) - .Add(TotalSnowPrecipitation) - .Add(TotalColumnWater) - .Add(TotalPrecipitationRate) - .Add(TotalSnowfallRateWaterEquivalent) - .Add(LargeScalePrecipitationRate) - .Add(ConvectiveSnowfallRateWaterEquivalent) - .Add(LargeScaleSnowfallRateWaterEquivalent) - .Add(TotalSnowfallRate) - .Add(ConvectiveSnowfallRate) - .Add(LargeScaleSnowfallRate) - .Add(SnowDepthWaterEquivalent) - .Add(SnowDensity) - .Add(SnowEvaporation) - .Add(TotalColumnIntegratedWaterVapour) - .Add(RainPrecipitationRate) - .Add(SnowPrecipitationRate) - .Add(FreezingRainPrecipitationRate) - .Add(IcePelletsPrecipitationRate) - .Add(TotalColumnIntegrateCloudWater) - .Add(TotalColumnIntegrateCloudIce) - .Add(HailMixingRatio) - .Add(TotalColumnIntegrateHail) - .Add(HailPrepitationRate) - .Add(TotalColumnIntegrateGraupel) - .Add(GraupelPrecipitationRate) - .Add(ConvectiveRainRate) - .Add(LargeScaleRainRate) - .Add(TotalColumnIntegrateWater) - .Add(EvaporationRate) - .Add(TotalCondensate) - .Add(TotalColumnIntegrateCondensate) - .Add(CloudIceMixingRatio) - .Add(SpecificCloudLiquidWaterContent) - .Add(SpecificCloudIceWaterContent) - .Add(SpecificRainWaterContent) - .Add(SpecificSnowWaterContent) - .Add(StratiformPrecipitationRate) - .Add(CategoricalConvectivePrecipitation) - .Add(TotalKinematicMoistureFlux) - .Add(Ucomponent) - .Add(Vcomponent) - .Add(RelativeHumidityWithRespectToWater) - .Add(RelativeHumidityWithRespectToIce) - .Add(FreezingOrFrozenPrecipitationRate) - .Add(MassDensityOfRain) - .Add(MassDensityOfSnow) - .Add(MassDensityOfGraupel) - .Add(MassDensityOfHail) - .Add(SpecificNumberConcentrationOfRain) - .Add(SpecificNumberConcentrationOfSnow) - .Add(SpecificNumberConcentrationOfGraupel) - .Add(SpecificNumberConcentrationOfHail) - .Add(NumberDensityOfRain) - .Add(NumberDensityOfSnow) - .Add(NumberDensityOfGraupel) - .Add(NumberDensityOfHail) - .Add(SpecificHumidityTendencyDueToParameterizations) - .Add(MassDensityOfLiquidWaterCoatingOnHail) - .Add(SpecificMassOfLiquidWaterCoatingOnHail) - .Add(MassMixingRatioOfLiquidWaterCoatingOnHail) - .Add(MassDensityOfLiquidWaterCoatingOnGraupel) - .Add(SpecificMassOfLiquidWaterCoatingOnGraupel) - .Add(MassMixingRatioOfLiquidWaterCoatingOnGraupel) - .Add(MassDensityOfLiquidWaterCoatingOnSnow) - .Add(SpecificMassOfLiquidWaterCoatingOnSnow) - .Add(MassMixingRatioOfLiquidWaterCoatingOnSnow) - .Add(UnbalancedComponentOfSpecificHumidity) - .Add(UnbalancedComponentOfSpecificCloudLiquidWaterContent) - .Add(UnbalancedComponentOfSpecificCloudIceWaterContent) - .Add(FractionOfSnowCover) - .Add(WindDirection) - .Add(WindSpeed) - .Add(UComponentOfWind) - .Add(VComponentOfWind) - .Add(StreamFunction) - .Add(VelocityPotential) - .Add(MontgomeryStreamFunction) - .Add(SigmaCoordinateVerticalVelocity) - .Add(VerticalVelocityPressure) - .Add(VerticalVelocityGeometric) - .Add(AbsoluteVorticity) - .Add(AbsoluteDivergence) - .Add(RelativeVorticity) - .Add(RelativeDivergence) - .Add(PotentialVorticity) - .Add(VerticalUComponentShear) - .Add(VerticalVComponentShear) - .Add(MomentumFluxUComponent) - .Add(MomentumFluxVComponent) - .Add(WindMixingEnergy) - .Add(BoundaryLayerDissipation) - .Add(MaximumWindSpeed) - .Add(WindSpeedGust) - .Add(UComponentOfWindGust) - .Add(VComponentOfWindGust) - .Add(Pressure) - .Add(PressureReducedToMsl) - .Add(PressureTendency) - .Add(IcaoStandardAtmosphereReferenceHeight) - .Add(Geopotential) - .Add(GeopotentialHeight) - .Add(GeometricHeight) - .Add(StandardDeviationOfHeight) - .Add(PressureAnomaly) - .Add(GeopotentialHeightAnomaly) - .Add(Density) - .Add(AltimeterSetting) - .Add(Thickness) - .Add(PressureAltitude) - .Add(DensityAltitude) - .Add(NetShortWaveRadiationFluxSurface) - .Add(NetShortWaveRadiationFlux) - .Add(ShortWaveRadiationFlux) - .Add(GlobalRadiationFlux) - .Add(BrightnessTemperature) - .Add(RadianceWaveNumber) - .Add(RadianceWaveLength) - .Add(NetLongWaveRadiationFluxSurface) - .Add(NetLongWaveRadiationFlux) - .Add(LongWaveRadiationFlux) - .Add(CloudIce) - .Add(TotalCloudCover) - .Add(ConvectiveCloudCover) - .Add(LowCloudCover) - .Add(MediumCloudCover) - .Add(HighCloudCover) - .Add(CloudWater) - .Add(CloudAmount) - .Add(CloudType) - .Add(ThunderstormMaximumTops) - .Add(ThunderstormCoverage) - .Add(CloudBase) - .Add(CloudTop) - .Add(Ceiling) - .Add(ParcelLiftedIndex) - .Add(BestLiftedIndex) - .Add(KIndex) - .Add(KoIndex) - .Add(TotalTotalsIndex) - .Add(SweatIndex) - .Add(ConvectiveAvailablePotentialEnergy) - .Add(ConvectiveInhibition) - .Add(StormRelativeHelicity) - .Add(EnergyHelicityIndex) - .Add(AerosolType) - .Add(TotalOzone) - .Add(BaseSpectrumWidth) - .Add(BaseReflectivity) - .Add(BaseRadialVelocity) - .Add(VerticallyIntegratedLiquid) - .Add(LayerMaximumBaseReflectivity) - .Add(Precipitation) - .Add(RadarSpectra1) - .Add(RadarSpectra2) - .Add(RadarSpectra3) - .Add(AirConcentrationOfCaesium137) - .Add(AirConcentrationOfIodine131) - .Add(AirConcentrationOfRadioactivePollutant) - .Add(GroundDepositionOfCaesium137) - .Add(GroundDepositionOfIodine131) - .Add(GroundDepositionOfRadioactivePollutant) - .Add(TimeIntegratedAirConcentrationOfCaesiumPollutant) - .Add(TimeIntegratedAirConcentrationOfIodinePollutant) - .Add(TimeIntegratedAirConcentrationOfRadioactivePollutant) - .Add(Visibility) - .Add(Albedo) - .Add(ThunderstormProbability) - .Add(MixedLayerDepth) - .Add(VolcanicAsh) - .Add(IcingTop) - .Add(IcingBase) - .Add(Icing) - .Add(TurbulenceTop) - .Add(TurbulenceBase) - .Add(Turbulence) - .Add(TurbulentKineticEnergy) - .Add(PlanetaryBoundaryLayerRegime) - .Add(ContrailIntensity) - .Add(ContrailEngineType) - .Add(ContrailTop) - .Add(Contrail) - .Add(ArbitraryTextStringCcittia5) - .Add(FlashFloodGuidance) - .Add(FlashFloodRunoff) - .Add(RemotelySensedSnowCover) - .Add(ElevationOfSnowCoveredTerrain) - .Add(SnowWaterEquivalentPercentOfNormal) - .Add(ConditionalPercentPrecipitationAmountFractileForAnOverallPeriod) - .Add(PercentPrecipitationInASubPeriodOfAnOverallPeriod) - .Add(ProbabilityOf001InchOfPrecipitationPop) - .Add(LandCover) - .Add(SurfaceRoughness) - .Add(SoilTemperature) - .Add(SoilMoistureContent) - .Add(Vegetation) - .Add(WaterRunoff) - .Add(Evapotranspiration) - .Add(ModelTerrainHeight) - .Add(LandUse) - .Add(SoilType) - .Add(UpperLayerSoilTemperature) - .Add(UpperLayerSoilMoisture) - .Add(LowerLayerSoilMoisture) - .Add(BottomLayerSoilTemperature) - .Add(ScaledRadiance) - .Add(ScaledAlbedo) - .Add(ScaledBrightnessTemperature) - .Add(ScaledPrecipitableWater) - .Add(ScaledLiftedIndex) - .Add(ScaledCloudTopPressure) - .Add(ScaledSkinTemperature) - .Add(CloudMask) - .Add(EstimatedPrecipitation) - .Add(WaveSpectra1) - .Add(WaveSpectra2) - .Add(WaveSpectra3) - .Add(SignificantHeightOfCombinedWindWavesAndSwell) - .Add(DirectionOfWindWaves) - .Add(SignificantHeightOfWindWaves) - .Add(MeanPeriodOfWindWaves) - .Add(DirectionOfSwellWaves) - .Add(SignificantHeightOfSwellWaves) - .Add(MeanPeriodOfSwellWaves) - .Add(PrimaryWaveDirection) - .Add(PrimaryWaveMeanPeriod) - .Add(SecondaryWaveDirection) - .Add(SecondaryWaveMeanPeriod) - .Add(CurrentDirection) - .Add(CurrentSpeed) - .Add(UComponentOfCurrent) - .Add(VComponentOfCurrent) - .Add(IceCover) - .Add(IceThickness) - .Add(DirectionOfIceDrift) - .Add(SpeedOfIceDrift) - .Add(UComponentOfIceDrift) - .Add(VComponentOfIceDrift) - .Add(IceGrowthRate) - .Add(IceDivergence) - .Add(WaterTemperature) - .Add(DeviationOfSeaLevelFromMean) - .Add(MainThermoclineDepth) - .Add(MainThermoclineAnomaly) - .Add(TransientThermoclineDepth) - .Add(Salinity) - .GroupBy(c => c.Category) - .ToDictionary(g => g.Key, g => (IReadOnlyCollection) g.ToImmutableList()); - } + ///Ice cover (Proportion) + public static Parameter IceCover { get; } = new Parameter(ParameterCategory.Ice, 0, "Ice cover", "Proportion"); + + ///Ice thickness (m) + public static Parameter IceThickness { get; } = new Parameter(ParameterCategory.Ice, 1, "Ice thickness", "m"); + + ///Direction of ice drift (Degree true) + public static Parameter DirectionOfIceDrift { get; } = + new Parameter(ParameterCategory.Ice, 2, "Direction of ice drift", "Degree true"); + + ///Speed of ice drift (m s-1) + public static Parameter SpeedOfIceDrift { get; } = new Parameter(ParameterCategory.Ice, 3, "Speed of ice drift", "m s-1"); + + ///u-component of ice drift (m s-1) + public static Parameter UComponentOfIceDrift { get; } = + new Parameter(ParameterCategory.Ice, 4, "u-component of ice drift", "m s-1"); + + ///v-component of ice drift (m s-1) + public static Parameter VComponentOfIceDrift { get; } = + new Parameter(ParameterCategory.Ice, 5, "v-component of ice drift", "m s-1"); + + ///Ice growth rate (m s-1) + public static Parameter IceGrowthRate { get; } = new Parameter(ParameterCategory.Ice, 6, "Ice growth rate", "m s-1"); + + ///Ice divergence (s-1) + public static Parameter IceDivergence { get; } = new Parameter(ParameterCategory.Ice, 7, "Ice divergence", "s-1"); + + #endregion + + #region Product Discipline 10: Oceanographic products, Parameter Category 3: Surface Properties + + ///Water temperature (K) + public static Parameter WaterTemperature { get; } = + new Parameter(ParameterCategory.SurfaceProperties, 0, "Water temperature", "K"); + + ///Deviation of sea level from mean (m) + public static Parameter DeviationOfSeaLevelFromMean { get; } = + new Parameter(ParameterCategory.SurfaceProperties, 1, "Deviation of sea level from mean", "m"); + + #endregion + + #region Product Discipline 10: Oceanographic products, Parameter Category 4: Sub-surface Properties + + ///Main thermocline depth (m) + public static Parameter MainThermoclineDepth { get; } = + new Parameter(ParameterCategory.SubSurfaceProperties, 0, "Main thermocline depth", "m"); + + ///Main thermocline anomaly (m) + public static Parameter MainThermoclineAnomaly { get; } = + new Parameter(ParameterCategory.SubSurfaceProperties, 1, "Main thermocline anomaly", "m"); + + ///Transient thermocline depth (m) + public static Parameter TransientThermoclineDepth { get; } = + new Parameter(ParameterCategory.SubSurfaceProperties, 2, "Transient thermocline depth", "m"); + + ///Salinity (kg kg-1) + public static Parameter Salinity { get; } = + new Parameter(ParameterCategory.SubSurfaceProperties, 3, "Salinity", "kg kg-1"); + + #endregion + + public static IReadOnlyDictionary> ParametersByCategory { get; } = + ImmutableList.Empty + .Add(Temperature) + .Add(VirtualTemperature) + .Add(PotentialTemperature) + .Add(PseudoAdiabaticPotentialTemperatureOrEquivalentPotentialTemperature) + .Add(MaximumTemperature) + .Add(MinimumTemperature) + .Add(DewPointTemperature) + .Add(DewPointDepression) + .Add(LapseRate) + .Add(TemperatureAnomaly) + .Add(LatentHeatNetFlux) + .Add(SensibleHeatNetFlux) + .Add(HeatIndex) + .Add(WindChillFactor) + .Add(MinimumDewPointDepression) + .Add(VirtualPotentialTemperature) + .Add(SnowPhaseChangeHeatFlux) + .Add(SkinTemperature) + .Add(SnowTemperature) + .Add(TurbulentTransferCoefficientForHeat) + .Add(TurbulentDiffusionCoefficientForHeat) + .Add(ApparentTemperature) + .Add(TemperatureTendencyDueToShortWaveRadiation) + .Add(TemperatureTendencyDueToLongWaveRadiation) + .Add(TemperatureTendencyDueToShortWaveRadiationClearSky) + .Add(TemperatureTendencyDueToLongWaveRadiationClearSky) + .Add(TemperatureTendencyDueToParameterizations) + .Add(WetBulbTemperature) + .Add(UnbalancedComponentOfTemperature) + .Add(TemperatureAdvection) + .Add(SpecificHumidity) + .Add(RelativeHumidity) + .Add(HumidityMixingRatio) + .Add(PrecipitableWater) + .Add(VaporPressure) + .Add(SaturationDeficit) + .Add(Evaporation) + .Add(PrecipitationRate) + .Add(TotalPrecipitation) + .Add(LargeScalePrecipitationNonConvective) + .Add(ConvectivePrecipitation) + .Add(SnowDepth) + .Add(SnowfallRateWaterEquivalent) + .Add(WaterEquivalentOfAccumulatedSnowDepth) + .Add(ConvectiveSnow) + .Add(LargeScaleSnow) + .Add(SnowMelt) + .Add(SnowAge) + .Add(AbsoluteHumidity) + .Add(PrecipitationType) + .Add(IntegratedLiquidWater) + .Add(Condensate) + .Add(CloudMixingRatio) + .Add(IceWaterMixingRatio) + .Add(RainMixingRatio) + .Add(SnowMixingRatio) + .Add(HorizontalMoistureConvergence) + .Add(MaximumRelativeHumidity) + .Add(MaximumAbsoluteHumidity) + .Add(TotalSnowfall) + .Add(PrecipitableWaterCategory) + .Add(Hail) + .Add(Graupel) + .Add(CategoricalRain) + .Add(CategoricalFreezingRain) + .Add(CategoricalIcePellets) + .Add(CategoricalSnow) + .Add(ConvectivePrecipitationRate) + .Add(HorizontalMoistureDivergence) + .Add(PercentFrozenPrecipitation) + .Add(PotentialEvaporation) + .Add(PotentialEvaporationRate) + .Add(SnowCover) + .Add(RainFractionOfTotalCloudWater) + .Add(RimeFactor) + .Add(TotalColumnIntegratedRain) + .Add(TotalColumnIntegratedSnow) + .Add(LargeScaleWaterPrecipitation) + .Add(ConvectiveWaterPrecipitation) + .Add(TotalWaterPrecipitation) + .Add(TotalSnowPrecipitation) + .Add(TotalColumnWater) + .Add(TotalPrecipitationRate) + .Add(TotalSnowfallRateWaterEquivalent) + .Add(LargeScalePrecipitationRate) + .Add(ConvectiveSnowfallRateWaterEquivalent) + .Add(LargeScaleSnowfallRateWaterEquivalent) + .Add(TotalSnowfallRate) + .Add(ConvectiveSnowfallRate) + .Add(LargeScaleSnowfallRate) + .Add(SnowDepthWaterEquivalent) + .Add(SnowDensity) + .Add(SnowEvaporation) + .Add(TotalColumnIntegratedWaterVapour) + .Add(RainPrecipitationRate) + .Add(SnowPrecipitationRate) + .Add(FreezingRainPrecipitationRate) + .Add(IcePelletsPrecipitationRate) + .Add(TotalColumnIntegrateCloudWater) + .Add(TotalColumnIntegrateCloudIce) + .Add(HailMixingRatio) + .Add(TotalColumnIntegrateHail) + .Add(HailPrepitationRate) + .Add(TotalColumnIntegrateGraupel) + .Add(GraupelPrecipitationRate) + .Add(ConvectiveRainRate) + .Add(LargeScaleRainRate) + .Add(TotalColumnIntegrateWater) + .Add(EvaporationRate) + .Add(TotalCondensate) + .Add(TotalColumnIntegrateCondensate) + .Add(CloudIceMixingRatio) + .Add(SpecificCloudLiquidWaterContent) + .Add(SpecificCloudIceWaterContent) + .Add(SpecificRainWaterContent) + .Add(SpecificSnowWaterContent) + .Add(StratiformPrecipitationRate) + .Add(CategoricalConvectivePrecipitation) + .Add(TotalKinematicMoistureFlux) + .Add(Ucomponent) + .Add(Vcomponent) + .Add(RelativeHumidityWithRespectToWater) + .Add(RelativeHumidityWithRespectToIce) + .Add(FreezingOrFrozenPrecipitationRate) + .Add(MassDensityOfRain) + .Add(MassDensityOfSnow) + .Add(MassDensityOfGraupel) + .Add(MassDensityOfHail) + .Add(SpecificNumberConcentrationOfRain) + .Add(SpecificNumberConcentrationOfSnow) + .Add(SpecificNumberConcentrationOfGraupel) + .Add(SpecificNumberConcentrationOfHail) + .Add(NumberDensityOfRain) + .Add(NumberDensityOfSnow) + .Add(NumberDensityOfGraupel) + .Add(NumberDensityOfHail) + .Add(SpecificHumidityTendencyDueToParameterizations) + .Add(MassDensityOfLiquidWaterCoatingOnHail) + .Add(SpecificMassOfLiquidWaterCoatingOnHail) + .Add(MassMixingRatioOfLiquidWaterCoatingOnHail) + .Add(MassDensityOfLiquidWaterCoatingOnGraupel) + .Add(SpecificMassOfLiquidWaterCoatingOnGraupel) + .Add(MassMixingRatioOfLiquidWaterCoatingOnGraupel) + .Add(MassDensityOfLiquidWaterCoatingOnSnow) + .Add(SpecificMassOfLiquidWaterCoatingOnSnow) + .Add(MassMixingRatioOfLiquidWaterCoatingOnSnow) + .Add(UnbalancedComponentOfSpecificHumidity) + .Add(UnbalancedComponentOfSpecificCloudLiquidWaterContent) + .Add(UnbalancedComponentOfSpecificCloudIceWaterContent) + .Add(FractionOfSnowCover) + .Add(WindDirection) + .Add(WindSpeed) + .Add(UComponentOfWind) + .Add(VComponentOfWind) + .Add(StreamFunction) + .Add(VelocityPotential) + .Add(MontgomeryStreamFunction) + .Add(SigmaCoordinateVerticalVelocity) + .Add(VerticalVelocityPressure) + .Add(VerticalVelocityGeometric) + .Add(AbsoluteVorticity) + .Add(AbsoluteDivergence) + .Add(RelativeVorticity) + .Add(RelativeDivergence) + .Add(PotentialVorticity) + .Add(VerticalUComponentShear) + .Add(VerticalVComponentShear) + .Add(MomentumFluxUComponent) + .Add(MomentumFluxVComponent) + .Add(WindMixingEnergy) + .Add(BoundaryLayerDissipation) + .Add(MaximumWindSpeed) + .Add(WindSpeedGust) + .Add(UComponentOfWindGust) + .Add(VComponentOfWindGust) + .Add(Pressure) + .Add(PressureReducedToMsl) + .Add(PressureTendency) + .Add(IcaoStandardAtmosphereReferenceHeight) + .Add(Geopotential) + .Add(GeopotentialHeight) + .Add(GeometricHeight) + .Add(StandardDeviationOfHeight) + .Add(PressureAnomaly) + .Add(GeopotentialHeightAnomaly) + .Add(Density) + .Add(AltimeterSetting) + .Add(Thickness) + .Add(PressureAltitude) + .Add(DensityAltitude) + .Add(NetShortWaveRadiationFluxSurface) + .Add(NetShortWaveRadiationFlux) + .Add(ShortWaveRadiationFlux) + .Add(GlobalRadiationFlux) + .Add(BrightnessTemperature) + .Add(RadianceWaveNumber) + .Add(RadianceWaveLength) + .Add(NetLongWaveRadiationFluxSurface) + .Add(NetLongWaveRadiationFlux) + .Add(LongWaveRadiationFlux) + .Add(CloudIce) + .Add(TotalCloudCover) + .Add(ConvectiveCloudCover) + .Add(LowCloudCover) + .Add(MediumCloudCover) + .Add(HighCloudCover) + .Add(CloudWater) + .Add(CloudAmount) + .Add(CloudType) + .Add(ThunderstormMaximumTops) + .Add(ThunderstormCoverage) + .Add(CloudBase) + .Add(CloudTop) + .Add(Ceiling) + .Add(ParcelLiftedIndex) + .Add(BestLiftedIndex) + .Add(KIndex) + .Add(KoIndex) + .Add(TotalTotalsIndex) + .Add(SweatIndex) + .Add(ConvectiveAvailablePotentialEnergy) + .Add(ConvectiveInhibition) + .Add(StormRelativeHelicity) + .Add(EnergyHelicityIndex) + .Add(AerosolType) + .Add(TotalOzone) + .Add(BaseSpectrumWidth) + .Add(BaseReflectivity) + .Add(BaseRadialVelocity) + .Add(VerticallyIntegratedLiquid) + .Add(LayerMaximumBaseReflectivity) + .Add(Precipitation) + .Add(RadarSpectra1) + .Add(RadarSpectra2) + .Add(RadarSpectra3) + .Add(AirConcentrationOfCaesium137) + .Add(AirConcentrationOfIodine131) + .Add(AirConcentrationOfRadioactivePollutant) + .Add(GroundDepositionOfCaesium137) + .Add(GroundDepositionOfIodine131) + .Add(GroundDepositionOfRadioactivePollutant) + .Add(TimeIntegratedAirConcentrationOfCaesiumPollutant) + .Add(TimeIntegratedAirConcentrationOfIodinePollutant) + .Add(TimeIntegratedAirConcentrationOfRadioactivePollutant) + .Add(Visibility) + .Add(Albedo) + .Add(ThunderstormProbability) + .Add(MixedLayerDepth) + .Add(VolcanicAsh) + .Add(IcingTop) + .Add(IcingBase) + .Add(Icing) + .Add(TurbulenceTop) + .Add(TurbulenceBase) + .Add(Turbulence) + .Add(TurbulentKineticEnergy) + .Add(PlanetaryBoundaryLayerRegime) + .Add(ContrailIntensity) + .Add(ContrailEngineType) + .Add(ContrailTop) + .Add(Contrail) + .Add(MassDensityConcentration) + .Add(ColumnIntegratedMassDensitySeeNote1) + .Add(MassMixingRatioMassFractionInAir) + .Add(AtmosphereEmissionMassFlux) + .Add(AtmosphereNetProductionMassFlux) + .Add(AtmosphereNetProductionAndEmisionMassFlux) + .Add(SurfaceDryDepositionMassFlux) + .Add(SurfaceWetDepositionMassFlux) + .Add(AtmosphereReEmissionMassFlux) + .Add(WetDepositionByLargeScalePrecipitationMassFlux) + .Add(WetDepositionByConvectivePrecipitationMassFlux) + .Add(TransferFromHydrophobicToHydrophilic) + .Add(TransferFromSo2SulphurDioxideToSo4Sulphate) + .Add(MassMixingRatioWithRespectToDryAir) + .Add(MassMixingRatioWithRespectToWetAir) + .Add(VolumeMixingRatioFractionInAir) + .Add(ChemicalGrossProductionRateOfConcentration) + .Add(ChemicalGrossDestructionRateOfConcentration) + .Add(ChangesOfAmountInAtmosphereSeeNote1) + .Add(TotalYearlyAverageBurdenOfTheAtmosphere) + .Add(TotalYearlyAverageAtmosphericLossSeeNote1) + .Add(AerosolNumberConcentrationSeeNote2) + .Add(AerosolSpecificNumberConcentrationSeeNote2) + .Add(MaximumOfMassDensitySeeNote1) + .Add(ColumnAveragedMassDensityInLayer) + .Add(MoleFractionWithRespectToDryAir) + .Add(MoleFractionWithRespectToWetAir) + .Add(ColumnintegratedIncloudScavengingRateByPrecipitation) + .Add(ColumnintegratedBelowcloudScavengingRateByPrecipitation) + .Add(ColumnintegratedReleaseRateFromEvaporatingPrecipitation) + .Add(ColumnintegratedIncloudScavengingRateByLargescalePrecipitation) + .Add(ColumnintegratedBelowcloudScavengingRateByLargescalePrecipitation) + .Add(ColumnintegratedReleaseRateFromEvaporatingLargescalePrecipitation) + .Add(ColumnintegratedIncloudScavengingRateByConvectivePrecipitation) + .Add(ColumnintegratedBelowcloudScavengingRateByConvectivePrecipitation) + .Add(ColumnintegratedReleaseRateFromEvaporatingConvectivePrecipitation) + .Add(SurfaceAreaDensityAerosol) + .Add(AerosolOpticalThickness) + .Add(AerosolExtinctionCoefficient) + .Add(AerosolAbsorptionCoefficient) + .Add(AerosolLidarBackscatterFromSatellite) + .Add(AerosolLidarBackscatterFromTheGround) + .Add(AerosolLidarExtinctionFromSatellite) + .Add(AerosolLidarExtinctionFromTheGround) + .Add(ScatteringAerosolOpticalThickness) + .Add(ArbitraryTextStringCcittia5) + .Add(FlashFloodGuidance) + .Add(FlashFloodRunoff) + .Add(RemotelySensedSnowCover) + .Add(ElevationOfSnowCoveredTerrain) + .Add(SnowWaterEquivalentPercentOfNormal) + .Add(ConditionalPercentPrecipitationAmountFractileForAnOverallPeriod) + .Add(PercentPrecipitationInASubPeriodOfAnOverallPeriod) + .Add(ProbabilityOf001InchOfPrecipitationPop) + .Add(LandCover) + .Add(SurfaceRoughness) + .Add(SoilTemperature) + .Add(SoilMoistureContent) + .Add(Vegetation) + .Add(WaterRunoff) + .Add(Evapotranspiration) + .Add(ModelTerrainHeight) + .Add(LandUse) + .Add(SoilType) + .Add(UpperLayerSoilTemperature) + .Add(UpperLayerSoilMoisture) + .Add(LowerLayerSoilMoisture) + .Add(BottomLayerSoilTemperature) + .Add(ScaledRadiance) + .Add(ScaledAlbedo) + .Add(ScaledBrightnessTemperature) + .Add(ScaledPrecipitableWater) + .Add(ScaledLiftedIndex) + .Add(ScaledCloudTopPressure) + .Add(ScaledSkinTemperature) + .Add(CloudMask) + .Add(EstimatedPrecipitation) + .Add(WaveSpectra1) + .Add(WaveSpectra2) + .Add(WaveSpectra3) + .Add(SignificantHeightOfCombinedWindWavesAndSwell) + .Add(DirectionOfWindWaves) + .Add(SignificantHeightOfWindWaves) + .Add(MeanPeriodOfWindWaves) + .Add(DirectionOfSwellWaves) + .Add(SignificantHeightOfSwellWaves) + .Add(MeanPeriodOfSwellWaves) + .Add(PrimaryWaveDirection) + .Add(PrimaryWaveMeanPeriod) + .Add(SecondaryWaveDirection) + .Add(SecondaryWaveMeanPeriod) + .Add(CurrentDirection) + .Add(CurrentSpeed) + .Add(UComponentOfCurrent) + .Add(VComponentOfCurrent) + .Add(IceCover) + .Add(IceThickness) + .Add(DirectionOfIceDrift) + .Add(SpeedOfIceDrift) + .Add(UComponentOfIceDrift) + .Add(VComponentOfIceDrift) + .Add(IceGrowthRate) + .Add(IceDivergence) + .Add(WaterTemperature) + .Add(DeviationOfSeaLevelFromMean) + .Add(MainThermoclineDepth) + .Add(MainThermoclineAnomaly) + .Add(TransientThermoclineDepth) + .Add(Salinity) + .GroupBy(c => c.Category) + .ToDictionary(g => g.Key, g => (IReadOnlyCollection) g.ToImmutableList()); } \ No newline at end of file diff --git a/src/NGrib/Grib2/CodeTables/4_2_ParameterNumber.cs b/src/NGrib/Grib2/CodeTables/4_2_ParameterNumber.cs index 0fdc47a..ee01b1f 100644 --- a/src/NGrib/Grib2/CodeTables/4_2_ParameterNumber.cs +++ b/src/NGrib/Grib2/CodeTables/4_2_ParameterNumber.cs @@ -19,888 +19,887 @@ using System.ComponentModel; -namespace NGrib.Grib2.CodeTables +namespace NGrib.Grib2.CodeTables; + +/// +/// Code Table 4.2: Parameter number by product discipline and parameter category +/// +public enum ParameterNumber { - /// - /// Code Table 4.2: Parameter number by product discipline and parameter category - /// - public enum ParameterNumber - { - #region Product Discipline 0: Meteorological products, Parameter Category 0: Temperature + #region Product Discipline 0: Meteorological products, Parameter Category 0: Temperature - ///Temperature (K) - [Description("Temperature")] Temperature = 0, + ///Temperature (K) + [Description("Temperature")] Temperature = 0, - ///Virtual temperature (K) - [Description("Virtual temperature")] VirtualTemperature = 1, + ///Virtual temperature (K) + [Description("Virtual temperature")] VirtualTemperature = 1, - ///Potential temperature (K) - [Description("Potential temperature")] PotentialTemperature = 2, + ///Potential temperature (K) + [Description("Potential temperature")] PotentialTemperature = 2, - ///Pseudo-adiabatic potential temperature or equivalent potential temperature (K) - [Description("Pseudo-adiabatic potential temperature or equivalent potential temperature")] - PseudoAdiabaticPotentialTemperatureOrEquivalentPotentialTemperature = 3, + ///Pseudo-adiabatic potential temperature or equivalent potential temperature (K) + [Description("Pseudo-adiabatic potential temperature or equivalent potential temperature")] + PseudoAdiabaticPotentialTemperatureOrEquivalentPotentialTemperature = 3, - ///Maximum temperature (K) - [Description("Maximum temperature")] MaximumTemperature = 4, + ///Maximum temperature (K) + [Description("Maximum temperature")] MaximumTemperature = 4, - ///Minimum temperature (K) - [Description("Minimum temperature")] MinimumTemperature = 5, + ///Minimum temperature (K) + [Description("Minimum temperature")] MinimumTemperature = 5, - ///Dew point temperature (K) - [Description("Dew point temperature")] DewPointTemperature = 6, + ///Dew point temperature (K) + [Description("Dew point temperature")] DewPointTemperature = 6, - ///Dew point depression (or deficit) (K) - [Description("Dew point depression (or deficit)")] - DewPointDepression = 7, + ///Dew point depression (or deficit) (K) + [Description("Dew point depression (or deficit)")] + DewPointDepression = 7, - ///Lapse rate (K m-1) - [Description("Lapse rate")] LapseRate = 8, + ///Lapse rate (K m-1) + [Description("Lapse rate")] LapseRate = 8, - ///Temperature anomaly (K) - [Description("Temperature anomaly")] TemperatureAnomaly = 9, + ///Temperature anomaly (K) + [Description("Temperature anomaly")] TemperatureAnomaly = 9, - ///Latent heat net flux (W m-2) - [Description("Latent heat net flux")] LatentHeatNetFlux = 10, + ///Latent heat net flux (W m-2) + [Description("Latent heat net flux")] LatentHeatNetFlux = 10, - ///Sensible heat net flux (W m-2) - [Description("Sensible heat net flux")] - SensibleHeatNetFlux = 11, + ///Sensible heat net flux (W m-2) + [Description("Sensible heat net flux")] + SensibleHeatNetFlux = 11, - ///Heat index (K) - [Description("Heat index")] HeatIndex = 12, + ///Heat index (K) + [Description("Heat index")] HeatIndex = 12, - ///Wind chill factor (K) - [Description("Wind chill factor")] WindChillFactor = 13, + ///Wind chill factor (K) + [Description("Wind chill factor")] WindChillFactor = 13, - ///Minimum dew point depression (K) - [Description("Minimum dew point depression")] - MinimumDewPointDepression = 14, + ///Minimum dew point depression (K) + [Description("Minimum dew point depression")] + MinimumDewPointDepression = 14, - ///Virtual potential temperature (K) - [Description("Virtual potential temperature")] - VirtualPotentialTemperature = 15, + ///Virtual potential temperature (K) + [Description("Virtual potential temperature")] + VirtualPotentialTemperature = 15, - #endregion + #endregion - #region Product Discipline 0: Meteorological products, Parameter Category 1: Moisture + #region Product Discipline 0: Meteorological products, Parameter Category 1: Moisture - ///Specific humidity (kg kg-1) - [Description("Specific humidity")] SpecificHumidity = 0, + ///Specific humidity (kg kg-1) + [Description("Specific humidity")] SpecificHumidity = 0, - ///Relative humidity (%) - [Description("Relative humidity")] RelativeHumidity = 1, + ///Relative humidity (%) + [Description("Relative humidity")] RelativeHumidity = 1, - ///Humidity mixing ratio (kg kg-1) - [Description("Humidity mixing ratio")] HumidityMixingRatio = 2, + ///Humidity mixing ratio (kg kg-1) + [Description("Humidity mixing ratio")] HumidityMixingRatio = 2, - ///Precipitable water (kg m-2) - [Description("Precipitable water")] PrecipitableWater = 3, + ///Precipitable water (kg m-2) + [Description("Precipitable water")] PrecipitableWater = 3, - ///Vapor pressure (Pa) - [Description("Vapor pressure")] VaporPressure = 4, + ///Vapor pressure (Pa) + [Description("Vapor pressure")] VaporPressure = 4, - ///Saturation deficit (Pa) - [Description("Saturation deficit")] SaturationDeficit = 5, + ///Saturation deficit (Pa) + [Description("Saturation deficit")] SaturationDeficit = 5, - ///Evaporation (kg m-2) - [Description("Evaporation")] Evaporation = 6, + ///Evaporation (kg m-2) + [Description("Evaporation")] Evaporation = 6, - ///Precipitation rate (kg m-2 s-1) - [Description("Precipitation rate")] PrecipitationRate = 7, + ///Precipitation rate (kg m-2 s-1) + [Description("Precipitation rate")] PrecipitationRate = 7, - ///Total precipitation (kg m-2) - [Description("Total precipitation")] TotalPrecipitation = 8, + ///Total precipitation (kg m-2) + [Description("Total precipitation")] TotalPrecipitation = 8, - ///Large scale precipitation (non-convective) (kg m-2) - [Description("Large scale precipitation (non-convective)")] - LargeScalePrecipitationNonconvective = 9, + ///Large scale precipitation (non-convective) (kg m-2) + [Description("Large scale precipitation (non-convective)")] + LargeScalePrecipitationNonconvective = 9, - ///Convective precipitation (kg m-2) - [Description("Convective precipitation")] - ConvectivePrecipitation = 10, + ///Convective precipitation (kg m-2) + [Description("Convective precipitation")] + ConvectivePrecipitation = 10, - ///Snow depth (m) - [Description("Snow depth")] SnowDepth = 11, + ///Snow depth (m) + [Description("Snow depth")] SnowDepth = 11, - ///Snowfall rate water equivalent (kg m-2 s-1) - [Description("Snowfall rate water equivalent")] - SnowfallRateWaterEquivalent = 12, + ///Snowfall rate water equivalent (kg m-2 s-1) + [Description("Snowfall rate water equivalent")] + SnowfallRateWaterEquivalent = 12, - ///Water equivalent of accumulated snow depth (kg m-2) - [Description("Water equivalent of accumulated snow depth")] - WaterEquivalentOfAccumulatedSnowDepth = 13, + ///Water equivalent of accumulated snow depth (kg m-2) + [Description("Water equivalent of accumulated snow depth")] + WaterEquivalentOfAccumulatedSnowDepth = 13, - ///Convective snow (kg m-2) - [Description("Convective snow")] ConvectiveSnow = 14, + ///Convective snow (kg m-2) + [Description("Convective snow")] ConvectiveSnow = 14, - ///Large scale snow (kg m-2) - [Description("Large scale snow")] LargeScaleSnow = 15, + ///Large scale snow (kg m-2) + [Description("Large scale snow")] LargeScaleSnow = 15, - ///Snow melt (kg m-2) - [Description("Snow melt")] SnowMelt = 16, + ///Snow melt (kg m-2) + [Description("Snow melt")] SnowMelt = 16, - ///Snow age (day) - [Description("Snow age")] SnowAge = 17, + ///Snow age (day) + [Description("Snow age")] SnowAge = 17, - ///Absolute humidity (kg m-3) - [Description("Absolute humidity")] AbsoluteHumidity = 18, + ///Absolute humidity (kg m-3) + [Description("Absolute humidity")] AbsoluteHumidity = 18, - ///Precipitation type (Code table (4.201)) - [Description("Precipitation type")] PrecipitationType = 19, + ///Precipitation type (Code table (4.201)) + [Description("Precipitation type")] PrecipitationType = 19, - ///Integrated liquid water (kg m-2) - [Description("Integrated liquid water")] - IntegratedLiquidWater = 20, + ///Integrated liquid water (kg m-2) + [Description("Integrated liquid water")] + IntegratedLiquidWater = 20, - ///Condensate (kg kg-1) - [Description("Condensate")] Condensate = 21, + ///Condensate (kg kg-1) + [Description("Condensate")] Condensate = 21, - ///Cloud mixing ratio (kg kg-1) - [Description("Cloud mixing ratio")] CloudMixingRatio = 22, + ///Cloud mixing ratio (kg kg-1) + [Description("Cloud mixing ratio")] CloudMixingRatio = 22, - ///Ice water mixing ratio (kg kg-1) - [Description("Ice water mixing ratio")] - IceWaterMixingRatio = 23, + ///Ice water mixing ratio (kg kg-1) + [Description("Ice water mixing ratio")] + IceWaterMixingRatio = 23, - ///Rain mixing ratio (kg kg-1) - [Description("Rain mixing ratio")] RainMixingRatio = 24, + ///Rain mixing ratio (kg kg-1) + [Description("Rain mixing ratio")] RainMixingRatio = 24, - ///Snow mixing ratio (kg kg-1) - [Description("Snow mixing ratio")] SnowMixingRatio = 25, + ///Snow mixing ratio (kg kg-1) + [Description("Snow mixing ratio")] SnowMixingRatio = 25, - ///Horizontal moisture convergence (kg kg-1 s-1) - [Description("Horizontal moisture convergence")] - HorizontalMoistureConvergence = 26, + ///Horizontal moisture convergence (kg kg-1 s-1) + [Description("Horizontal moisture convergence")] + HorizontalMoistureConvergence = 26, - ///Maximum relative humidity (%) - [Description("Maximum relative humidity")] - MaximumRelativeHumidity = 27, + ///Maximum relative humidity (%) + [Description("Maximum relative humidity")] + MaximumRelativeHumidity = 27, - ///Maximum absolute humidity (kg m-3) - [Description("Maximum absolute humidity")] - MaximumAbsoluteHumidity = 28, + ///Maximum absolute humidity (kg m-3) + [Description("Maximum absolute humidity")] + MaximumAbsoluteHumidity = 28, - ///Total snowfall (m) - [Description("Total snowfall")] TotalSnowfall = 29, + ///Total snowfall (m) + [Description("Total snowfall")] TotalSnowfall = 29, - ///Precipitable water category (Code table (4.202)) - [Description("Precipitable water category")] - PrecipitableWaterCategory = 30, + ///Precipitable water category (Code table (4.202)) + [Description("Precipitable water category")] + PrecipitableWaterCategory = 30, - ///Hail (m) - [Description("Hail")] Hail = 31, + ///Hail (m) + [Description("Hail")] Hail = 31, - ///Graupel (snow pellets) (kg kg-1) - [Description("Graupel (snow pellets)")] - Graupel = 32, + ///Graupel (snow pellets) (kg kg-1) + [Description("Graupel (snow pellets)")] + Graupel = 32, - #endregion + #endregion - #region Product Discipline 0: Meteorological products, Parameter Category 2: Momentum + #region Product Discipline 0: Meteorological products, Parameter Category 2: Momentum - ///Wind direction (from which blowing) (deg true) - [Description("Wind direction (from which blowing)")] - WindDirection = 0, + ///Wind direction (from which blowing) (deg true) + [Description("Wind direction (from which blowing)")] + WindDirection = 0, - ///Wind speed (m s-1) - [Description("Wind speed")] WindSpeed = 1, + ///Wind speed (m s-1) + [Description("Wind speed")] WindSpeed = 1, - ///u-component of wind (m s-1) - [Description("u-component of wind")] UComponentOfWind = 2, + ///u-component of wind (m s-1) + [Description("u-component of wind")] UComponentOfWind = 2, - ///v-component of wind (m s-1) - [Description("v-component of wind")] VComponentOfWind = 3, + ///v-component of wind (m s-1) + [Description("v-component of wind")] VComponentOfWind = 3, - ///Stream function (m2 s-1) - [Description("Stream function")] StreamFunction = 4, + ///Stream function (m2 s-1) + [Description("Stream function")] StreamFunction = 4, - ///Velocity potential (m2 s-1) - [Description("Velocity potential")] VelocityPotential = 5, + ///Velocity potential (m2 s-1) + [Description("Velocity potential")] VelocityPotential = 5, - ///Montgomery stream function (m2 s-2) - [Description("Montgomery stream function")] - MontgomeryStreamFunction = 6, + ///Montgomery stream function (m2 s-2) + [Description("Montgomery stream function")] + MontgomeryStreamFunction = 6, - ///Sigma coordinate vertical velocity (s-1) - [Description("Sigma coordinate vertical velocity")] - SigmaCoordinateVerticalVelocity = 7, + ///Sigma coordinate vertical velocity (s-1) + [Description("Sigma coordinate vertical velocity")] + SigmaCoordinateVerticalVelocity = 7, - ///Vertical velocity (pressure) (Pa s-1) - [Description("Vertical velocity (pressure)")] - VerticalVelocityPressure = 8, + ///Vertical velocity (pressure) (Pa s-1) + [Description("Vertical velocity (pressure)")] + VerticalVelocityPressure = 8, - ///Vertical velocity (geometric) (m s-1) - [Description("Vertical velocity (geometric)")] - VerticalVelocityGeometric = 9, + ///Vertical velocity (geometric) (m s-1) + [Description("Vertical velocity (geometric)")] + VerticalVelocityGeometric = 9, - ///Absolute vorticity (s-1) - [Description("Absolute vorticity")] AbsoluteVorticity = 10, + ///Absolute vorticity (s-1) + [Description("Absolute vorticity")] AbsoluteVorticity = 10, - ///Absolute divergence (s-1) - [Description("Absolute divergence")] AbsoluteDivergence = 11, + ///Absolute divergence (s-1) + [Description("Absolute divergence")] AbsoluteDivergence = 11, - ///Relative vorticity (s-1) - [Description("Relative vorticity")] RelativeVorticity = 12, + ///Relative vorticity (s-1) + [Description("Relative vorticity")] RelativeVorticity = 12, - ///Relative divergence (s-1) - [Description("Relative divergence")] RelativeDivergence = 13, + ///Relative divergence (s-1) + [Description("Relative divergence")] RelativeDivergence = 13, - ///Potential vorticity (K m2 kg-1 s-1) - [Description("Potential vorticity")] PotentialVorticity = 14, + ///Potential vorticity (K m2 kg-1 s-1) + [Description("Potential vorticity")] PotentialVorticity = 14, - ///Vertical u-component shear (s-1) - [Description("Vertical u-component shear")] - VerticalUComponentShear = 15, + ///Vertical u-component shear (s-1) + [Description("Vertical u-component shear")] + VerticalUComponentShear = 15, - ///Vertical v-component shear (s-1) - [Description("Vertical v-component shear")] - VerticalVComponentShear = 16, + ///Vertical v-component shear (s-1) + [Description("Vertical v-component shear")] + VerticalVComponentShear = 16, - ///Momentum flux, u component (s-1) - [Description("Momentum flux, u component")] - MomentumFluxUComponent = 17, + ///Momentum flux, u component (s-1) + [Description("Momentum flux, u component")] + MomentumFluxUComponent = 17, - ///Momentum flux, v component (s-1) - [Description("Momentum flux, v component")] - MomentumFluxVComponent = 18, + ///Momentum flux, v component (s-1) + [Description("Momentum flux, v component")] + MomentumFluxVComponent = 18, - ///Wind mixing energy (J) - [Description("Wind mixing energy")] WindMixingEnergy = 19, + ///Wind mixing energy (J) + [Description("Wind mixing energy")] WindMixingEnergy = 19, - ///Boundary layer dissipation (W m-2) - [Description("Boundary layer dissipation")] - BoundaryLayerDissipation = 20, + ///Boundary layer dissipation (W m-2) + [Description("Boundary layer dissipation")] + BoundaryLayerDissipation = 20, - ///Maximum wind speed (m s-1) - [Description("Maximum wind speed")] MaximumWindSpeed = 21, + ///Maximum wind speed (m s-1) + [Description("Maximum wind speed")] MaximumWindSpeed = 21, - ///Wind speed (gust) (m s-1) - [Description("Wind speed (gust)")] WindSpeedGust = 22, + ///Wind speed (gust) (m s-1) + [Description("Wind speed (gust)")] WindSpeedGust = 22, - ///u-component of wind (gust) (m s-1) - [Description("u-component of wind (gust)")] - UComponentOfWindGust = 23, + ///u-component of wind (gust) (m s-1) + [Description("u-component of wind (gust)")] + UComponentOfWindGust = 23, - ///v-component of wind (gust) (m s-1) - [Description("v-component of wind (gust)")] - VComponentOfWindGust = 24, + ///v-component of wind (gust) (m s-1) + [Description("v-component of wind (gust)")] + VComponentOfWindGust = 24, - #endregion + #endregion - #region Product Discipline 0: Meteorological products, Parameter Category 3: Mass + #region Product Discipline 0: Meteorological products, Parameter Category 3: Mass - ///Pressure (Pa) - [Description("Pressure")] Pressure = 0, + ///Pressure (Pa) + [Description("Pressure")] Pressure = 0, - ///Pressure reduced to MSL (Pa) - [Description("Pressure reduced to MSL")] - PressureReducedToMsl = 1, + ///Pressure reduced to MSL (Pa) + [Description("Pressure reduced to MSL")] + PressureReducedToMsl = 1, - ///Pressure tendency (Pa s-1) - [Description("Pressure tendency")] PressureTendency = 2, + ///Pressure tendency (Pa s-1) + [Description("Pressure tendency")] PressureTendency = 2, - ///ICAO Standard Atmosphere Reference Height (m) - [Description("ICAO Standard Atmosphere Reference Height")] - IcaoStandardAtmosphereReferenceHeight = 3, + ///ICAO Standard Atmosphere Reference Height (m) + [Description("ICAO Standard Atmosphere Reference Height")] + IcaoStandardAtmosphereReferenceHeight = 3, - ///Geopotential (m2 s-2) - [Description("Geopotential")] Geopotential = 4, + ///Geopotential (m2 s-2) + [Description("Geopotential")] Geopotential = 4, - ///Geopotential height (gpm) - [Description("Geopotential height")] GeopotentialHeight = 5, + ///Geopotential height (gpm) + [Description("Geopotential height")] GeopotentialHeight = 5, - ///Geometric height (m) - [Description("Geometric height")] GeometricHeight = 6, + ///Geometric height (m) + [Description("Geometric height")] GeometricHeight = 6, - ///Standard deviation of height (m) - [Description("Standard deviation of height")] - StandardDeviationOfHeight = 7, + ///Standard deviation of height (m) + [Description("Standard deviation of height")] + StandardDeviationOfHeight = 7, - ///Pressure anomaly (Pa) - [Description("Pressure anomaly")] PressureAnomaly = 8, + ///Pressure anomaly (Pa) + [Description("Pressure anomaly")] PressureAnomaly = 8, - ///Geopotential height anomaly (gpm) - [Description("Geopotential height anomaly")] - GeopotentialHeightAnomaly = 9, + ///Geopotential height anomaly (gpm) + [Description("Geopotential height anomaly")] + GeopotentialHeightAnomaly = 9, - ///Density (kg m-3) - [Description("Density")] Density = 10, + ///Density (kg m-3) + [Description("Density")] Density = 10, - ///Altimeter setting (Pa) - [Description("Altimeter setting")] AltimeterSetting = 11, + ///Altimeter setting (Pa) + [Description("Altimeter setting")] AltimeterSetting = 11, - ///Thickness (m) - [Description("Thickness")] Thickness = 12, + ///Thickness (m) + [Description("Thickness")] Thickness = 12, - ///Pressure altitude (m) - [Description("Pressure altitude")] PressureAltitude = 13, + ///Pressure altitude (m) + [Description("Pressure altitude")] PressureAltitude = 13, - ///Density altitude (m) - [Description("Density altitude")] DensityAltitude = 14, + ///Density altitude (m) + [Description("Density altitude")] DensityAltitude = 14, - #endregion + #endregion - #region Product Discipline 0: Meteorological products, Parameter Category 4: Short-wave Radiation + #region Product Discipline 0: Meteorological products, Parameter Category 4: Short-wave Radiation - ///Net short-wave radiation flux (surface) (W m-2) - [Description("Net short-wave radiation flux (surface)")] - NetShortWaveRadiationFluxSurface = 0, + ///Net short-wave radiation flux (surface) (W m-2) + [Description("Net short-wave radiation flux (surface)")] + NetShortWaveRadiationFluxSurface = 0, - ///Net short-wave radiation flux (top of atmosphere) (W m-2) - [Description("Net short-wave radiation flux (top of atmosphere)")] - NetShortWaveRadiationFlux = 1, + ///Net short-wave radiation flux (top of atmosphere) (W m-2) + [Description("Net short-wave radiation flux (top of atmosphere)")] + NetShortWaveRadiationFlux = 1, - ///Short wave radiation flux (W m-2) - [Description("Short wave radiation flux")] - ShortWaveRadiationFlux = 2, + ///Short wave radiation flux (W m-2) + [Description("Short wave radiation flux")] + ShortWaveRadiationFlux = 2, - ///Global radiation flux (W m-2) - [Description("Global radiation flux")] GlobalRadiationFlux = 3, + ///Global radiation flux (W m-2) + [Description("Global radiation flux")] GlobalRadiationFlux = 3, - ///Brightness temperature (K) - [Description("Brightness temperature")] - BrightnessTemperature = 4, + ///Brightness temperature (K) + [Description("Brightness temperature")] + BrightnessTemperature = 4, - ///Radiance (with respect to wave number) (W m-1 sr-1) - [Description("Radiance (with respect to wave number)")] - RadianceWaveNumber = 5, + ///Radiance (with respect to wave number) (W m-1 sr-1) + [Description("Radiance (with respect to wave number)")] + RadianceWaveNumber = 5, - ///Radiance (with respect to wave length) (W m-3 sr-1) - [Description("Radiance (with respect to wave length)")] - RadianceWaveLength = 6, + ///Radiance (with respect to wave length) (W m-3 sr-1) + [Description("Radiance (with respect to wave length)")] + RadianceWaveLength = 6, - #endregion + #endregion - #region Product Discipline 0: Meteorological products, Parameter Category 5: Long-wave Radiation + #region Product Discipline 0: Meteorological products, Parameter Category 5: Long-wave Radiation - ///Net long wave radiation flux (surface) (W m-2) - [Description("Net long wave radiation flux (surface)")] - NetLongWaveRadiationFluxSurface = 0, + ///Net long wave radiation flux (surface) (W m-2) + [Description("Net long wave radiation flux (surface)")] + NetLongWaveRadiationFluxSurface = 0, - ///Net long wave radiation flux (top of atmosphere) (W m-2) - [Description("Net long wave radiation flux (top of atmosphere)")] - NetLongWaveRadiationFluxTopOfAtmosphere = 1, + ///Net long wave radiation flux (top of atmosphere) (W m-2) + [Description("Net long wave radiation flux (top of atmosphere)")] + NetLongWaveRadiationFluxTopOfAtmosphere = 1, - ///Long wave radiation flux (W m-2) - [Description("Long wave radiation flux")] - LongWaveRadiationFlux = 2, + ///Long wave radiation flux (W m-2) + [Description("Long wave radiation flux")] + LongWaveRadiationFlux = 2, - #endregion + #endregion - #region Product Discipline 0: Meteorological products, Parameter Category 6: Cloud + #region Product Discipline 0: Meteorological products, Parameter Category 6: Cloud - ///Cloud Ice (kg m-2) - [Description("Cloud Ice")] CloudIce = 0, + ///Cloud Ice (kg m-2) + [Description("Cloud Ice")] CloudIce = 0, - ///Total cloud cover (%) - [Description("Total cloud cover")] TotalCloudCover = 1, + ///Total cloud cover (%) + [Description("Total cloud cover")] TotalCloudCover = 1, - ///Convective cloud cover (%) - [Description("Convective cloud cover")] - ConvectiveCloudCover = 2, + ///Convective cloud cover (%) + [Description("Convective cloud cover")] + ConvectiveCloudCover = 2, - ///Low cloud cover (%) - [Description("Low cloud cover")] LowCloudCover = 3, + ///Low cloud cover (%) + [Description("Low cloud cover")] LowCloudCover = 3, - ///Medium cloud cover (%) - [Description("Medium cloud cover")] MediumCloudCover = 4, + ///Medium cloud cover (%) + [Description("Medium cloud cover")] MediumCloudCover = 4, - ///High cloud cover (%) - [Description("High cloud cover")] HighCloudCover = 5, + ///High cloud cover (%) + [Description("High cloud cover")] HighCloudCover = 5, - ///Cloud water (kg m-2) - [Description("Cloud water")] CloudWater = 6, + ///Cloud water (kg m-2) + [Description("Cloud water")] CloudWater = 6, - ///Cloud amount (%) - [Description("Cloud amount")] CloudAmount = 7, + ///Cloud amount (%) + [Description("Cloud amount")] CloudAmount = 7, - ///Cloud type (Code table (4.203)) - [Description("Cloud type")] CloudType = 8, + ///Cloud type (Code table (4.203)) + [Description("Cloud type")] CloudType = 8, - ///Thunderstorm maximum tops (m) - [Description("Thunderstorm maximum tops")] - ThunderstormMaximumTops = 9, + ///Thunderstorm maximum tops (m) + [Description("Thunderstorm maximum tops")] + ThunderstormMaximumTops = 9, - ///Thunderstorm coverage (Code table (4.204)) - [Description("Thunderstorm coverage")] ThunderstormCoverage = 10, + ///Thunderstorm coverage (Code table (4.204)) + [Description("Thunderstorm coverage")] ThunderstormCoverage = 10, - ///Cloud base (m) - [Description("Cloud base")] CloudBase = 11, + ///Cloud base (m) + [Description("Cloud base")] CloudBase = 11, - ///Cloud top (m) - [Description("Cloud top")] CloudTop = 12, + ///Cloud top (m) + [Description("Cloud top")] CloudTop = 12, - ///Ceiling (m) - [Description("Ceiling")] Ceiling = 13, + ///Ceiling (m) + [Description("Ceiling")] Ceiling = 13, - #endregion + #endregion - #region Product Discipline 0: Meteorological products, Parameter Category 7: Thermodynamic Stability Indices + #region Product Discipline 0: Meteorological products, Parameter Category 7: Thermodynamic Stability Indices - ///Parcel lifted index (to 500 hPa) (K) - [Description("Parcel lifted index (to 500 hPa)")] - ParcelLiftedIndex = 0, + ///Parcel lifted index (to 500 hPa) (K) + [Description("Parcel lifted index (to 500 hPa)")] + ParcelLiftedIndex = 0, - ///Best lifted index (to 500 hPa) (K) - [Description("Best lifted index (to 500 hPa)")] - BestLiftedIndex = 1, + ///Best lifted index (to 500 hPa) (K) + [Description("Best lifted index (to 500 hPa)")] + BestLiftedIndex = 1, - ///K index (K) - [Description("K index")] KIndex = 2, + ///K index (K) + [Description("K index")] KIndex = 2, - ///KO index (K) - [Description("KO index")] KoIndex = 3, + ///KO index (K) + [Description("KO index")] KoIndex = 3, - ///Total totals index (K) - [Description("Total totals index")] TotalTotalsIndex = 4, + ///Total totals index (K) + [Description("Total totals index")] TotalTotalsIndex = 4, - ///Sweat index (numeric) - [Description("Sweat index")] SweatIndex = 5, + ///Sweat index (numeric) + [Description("Sweat index")] SweatIndex = 5, - ///Convective available potential energy (J kg-1) - [Description("Convective available potential energy")] - ConvectiveAvailablePotentialEnergy = 6, + ///Convective available potential energy (J kg-1) + [Description("Convective available potential energy")] + ConvectiveAvailablePotentialEnergy = 6, - ///Convective inhibition (J kg-1) - [Description("Convective inhibition")] ConvectiveInhibition = 7, + ///Convective inhibition (J kg-1) + [Description("Convective inhibition")] ConvectiveInhibition = 7, - ///Storm relative helicity (J kg-1) - [Description("Storm relative helicity")] - StormRelativeHelicity = 8, + ///Storm relative helicity (J kg-1) + [Description("Storm relative helicity")] + StormRelativeHelicity = 8, - ///Energy helicity index (numeric) - [Description("Energy helicity index")] EnergyHelicityIndex = 9, + ///Energy helicity index (numeric) + [Description("Energy helicity index")] EnergyHelicityIndex = 9, - #endregion + #endregion - #region Product Discipline 0: Meteorological products, Parameter Category 13: Aerosols + #region Product Discipline 0: Meteorological products, Parameter Category 13: Aerosols - ///Aerosol type (Code table (4.205)) - [Description("Aerosol type")] AerosolType = 0, + ///Aerosol type (Code table (4.205)) + [Description("Aerosol type")] AerosolType = 0, - #endregion + #endregion - #region Product Discipline 0: Meteorological products, Parameter Category 14: Trace Gases + #region Product Discipline 0: Meteorological products, Parameter Category 14: Trace Gases - ///Total ozone (Dobson) - [Description("Total ozone")] TotalOzone = 0, + ///Total ozone (Dobson) + [Description("Total ozone")] TotalOzone = 0, - #endregion + #endregion - #region Product Discipline 0 - Meteorological products, Parameter Category 15: Radar + #region Product Discipline 0 - Meteorological products, Parameter Category 15: Radar - ///Base spectrum width (m s-1) - [Description("Base spectrum width")] BaseSpectrumWidth = 0, + ///Base spectrum width (m s-1) + [Description("Base spectrum width")] BaseSpectrumWidth = 0, - ///Base reflectivity (dB) - [Description("Base reflectivity")] BaseReflectivity = 1, + ///Base reflectivity (dB) + [Description("Base reflectivity")] BaseReflectivity = 1, - ///Base radial velocity (m s-1) - [Description("Base radial velocity")] BaseRadialVelocity = 2, + ///Base radial velocity (m s-1) + [Description("Base radial velocity")] BaseRadialVelocity = 2, - ///Vertically-integrated liquid (kg m-1) - [Description("Vertically-integrated liquid")] - VerticallyIntegratedLiquid = 3, + ///Vertically-integrated liquid (kg m-1) + [Description("Vertically-integrated liquid")] + VerticallyIntegratedLiquid = 3, - ///Layer-maximum base reflectivity (dB) - [Description("Layer-maximum base reflectivity")] - LayerMaximumBaseReflectivity = 4, + ///Layer-maximum base reflectivity (dB) + [Description("Layer-maximum base reflectivity")] + LayerMaximumBaseReflectivity = 4, - ///Precipitation (kg m-2) - [Description("Precipitation")] Precipitation = 5, + ///Precipitation (kg m-2) + [Description("Precipitation")] Precipitation = 5, - ///Radar spectra (1) (-) - [Description("Radar spectra (1)")] RadarSpectra1 = 6, + ///Radar spectra (1) (-) + [Description("Radar spectra (1)")] RadarSpectra1 = 6, - ///Radar spectra (2) (-) - [Description("Radar spectra (2)")] RadarSpectra2 = 7, + ///Radar spectra (2) (-) + [Description("Radar spectra (2)")] RadarSpectra2 = 7, - ///Radar spectra (3) (-) - [Description("Radar spectra (3)")] RadarSpectra3 = 8, + ///Radar spectra (3) (-) + [Description("Radar spectra (3)")] RadarSpectra3 = 8, - #endregion + #endregion - #region Product Discipline 0: Meteorological products, Parameter Category 18: Nuclear/radiology + #region Product Discipline 0: Meteorological products, Parameter Category 18: Nuclear/radiology - ///Air concentration of Caesium 137 (Bq m-3) - [Description("Air concentration of Caesium 137")] - AirConcentrationOfCaesium137 = 0, + ///Air concentration of Caesium 137 (Bq m-3) + [Description("Air concentration of Caesium 137")] + AirConcentrationOfCaesium137 = 0, - ///Air concentration of Iodine 131 (Bq m-3) - [Description("Air concentration of Iodine 131")] - AirConcentrationOfIodine131 = 1, + ///Air concentration of Iodine 131 (Bq m-3) + [Description("Air concentration of Iodine 131")] + AirConcentrationOfIodine131 = 1, - ///Air concentration of radioactive pollutant (Bq m-3) - [Description("Air concentration of radioactive pollutant")] - AirConcentrationOfRadioactivePollutant = 2, + ///Air concentration of radioactive pollutant (Bq m-3) + [Description("Air concentration of radioactive pollutant")] + AirConcentrationOfRadioactivePollutant = 2, - ///Ground deposition of Caesium 137 (Bq m-2) - [Description("Ground deposition of Caesium 137")] - GroundDepositionOfCaesium137 = 3, + ///Ground deposition of Caesium 137 (Bq m-2) + [Description("Ground deposition of Caesium 137")] + GroundDepositionOfCaesium137 = 3, - ///Ground deposition of Iodine 131 (Bq m-2) - [Description("Ground deposition of Iodine 131")] - GroundDepositionOfIodine131 = 4, + ///Ground deposition of Iodine 131 (Bq m-2) + [Description("Ground deposition of Iodine 131")] + GroundDepositionOfIodine131 = 4, - ///Ground deposition of radioactive pollutant (Bq m-2) - [Description("Ground deposition of radioactive pollutant")] - GroundDepositionOfRadioactivePollutant = 5, + ///Ground deposition of radioactive pollutant (Bq m-2) + [Description("Ground deposition of radioactive pollutant")] + GroundDepositionOfRadioactivePollutant = 5, - ///Time-integrated air concentration of caesium pollutant (Bq s m-3) - [Description("Time-integrated air concentration of caesium pollutant")] - TimeIntegratedAirConcentrationOfCaesiumPollutant = 6, + ///Time-integrated air concentration of caesium pollutant (Bq s m-3) + [Description("Time-integrated air concentration of caesium pollutant")] + TimeIntegratedAirConcentrationOfCaesiumPollutant = 6, - ///Time-integrated air concentration of iodine pollutant (Bq s m-3) - [Description("Time-integrated air concentration of iodine pollutant")] - TimeIntegratedAirConcentrationOfIodinePollutant = 7, + ///Time-integrated air concentration of iodine pollutant (Bq s m-3) + [Description("Time-integrated air concentration of iodine pollutant")] + TimeIntegratedAirConcentrationOfIodinePollutant = 7, - ///Time-integrated air concentration of radioactive pollutant (Bq s m-3) - [Description("Time-integrated air concentration of radioactive pollutant")] - TimeIntegratedAirConcentrationOfRadioactivePollutant = 8, + ///Time-integrated air concentration of radioactive pollutant (Bq s m-3) + [Description("Time-integrated air concentration of radioactive pollutant")] + TimeIntegratedAirConcentrationOfRadioactivePollutant = 8, - #endregion + #endregion - #region Product Discipline 0: Meteorological products, Parameter Category 19: Physical atmospheric properties + #region Product Discipline 0: Meteorological products, Parameter Category 19: Physical atmospheric properties - ///Visibility (m) - [Description("Visibility")] Visibility = 0, + ///Visibility (m) + [Description("Visibility")] Visibility = 0, - ///Albedo (%) - [Description("Albedo")] Albedo = 1, + ///Albedo (%) + [Description("Albedo")] Albedo = 1, - ///Thunderstorm probability (%) - [Description("Thunderstorm probability")] - ThunderstormProbability = 2, + ///Thunderstorm probability (%) + [Description("Thunderstorm probability")] + ThunderstormProbability = 2, - ///mixed layer depth (m) - [Description("mixed layer depth")] MixedLayerDepth = 3, + ///mixed layer depth (m) + [Description("mixed layer depth")] MixedLayerDepth = 3, - ///Volcanic ash (Code table (4.206)) - [Description("Volcanic ash")] VolcanicAsh = 4, + ///Volcanic ash (Code table (4.206)) + [Description("Volcanic ash")] VolcanicAsh = 4, - ///Icing top (m) - [Description("Icing top")] IcingTop = 5, + ///Icing top (m) + [Description("Icing top")] IcingTop = 5, - ///Icing base (m) - [Description("Icing base")] IcingBase = 6, + ///Icing base (m) + [Description("Icing base")] IcingBase = 6, - ///Icing (Code table (4.207)) - [Description("Icing")] Icing = 7, + ///Icing (Code table (4.207)) + [Description("Icing")] Icing = 7, - ///Turbulence top (m) - [Description("Turbulence top")] TurbulenceTop = 8, + ///Turbulence top (m) + [Description("Turbulence top")] TurbulenceTop = 8, - ///Turbulence base (m) - [Description("Turbulence base")] TurbulenceBase = 9, + ///Turbulence base (m) + [Description("Turbulence base")] TurbulenceBase = 9, - ///Turbulence (Code table (4.208)) - [Description("Turbulence")] Turbulence = 10, + ///Turbulence (Code table (4.208)) + [Description("Turbulence")] Turbulence = 10, - ///Turbulent kinetic energy (J kg-1) - [Description("Turbulent kinetic energy")] - TurbulentKineticEnergy = 11, + ///Turbulent kinetic energy (J kg-1) + [Description("Turbulent kinetic energy")] + TurbulentKineticEnergy = 11, - ///Planetary boundary layer regime (Code table (4.209)) - [Description("Planetary boundary layer regime")] - PlanetaryBoundaryLayerRegime = 12, + ///Planetary boundary layer regime (Code table (4.209)) + [Description("Planetary boundary layer regime")] + PlanetaryBoundaryLayerRegime = 12, - ///Contrail intensity (Code table (4.210)) - [Description("Contrail intensity")] ContrailIntensity = 13, + ///Contrail intensity (Code table (4.210)) + [Description("Contrail intensity")] ContrailIntensity = 13, - ///Contrail engine type (Code table (4.211)) - [Description("Contrail engine type")] ContrailEngineType = 14, + ///Contrail engine type (Code table (4.211)) + [Description("Contrail engine type")] ContrailEngineType = 14, - ///Contrail top (m) - [Description("Contrail top")] ContrailTop = 15, + ///Contrail top (m) + [Description("Contrail top")] ContrailTop = 15, - ///Contrail (base) - [Description("Contrail")] Contrail = 16, + ///Contrail (base) + [Description("Contrail")] Contrail = 16, - #endregion + #endregion - #region Product Discipline 0: Meteorological products, Parameter Category 253: ASCII character string + #region Product Discipline 0: Meteorological products, Parameter Category 253: ASCII character string - ///Arbitrary text string CCITTIA5 - [Description("Arbitrary text string CCITTIA5")] - ArbitraryTextStringCcittia5 = 0, + ///Arbitrary text string CCITTIA5 + [Description("Arbitrary text string CCITTIA5")] + ArbitraryTextStringCcittia5 = 0, - #endregion + #endregion - #region Product Discipline 1: Hydrologic products, Parameter Category 0: Hydrology basic products + #region Product Discipline 1: Hydrologic products, Parameter Category 0: Hydrology basic products - ///Flash flood guidance (Encoded as an accumulation over a floating subinterval of time between the reference time and valid time) (kg m-2) - [Description( - "Flash flood guidance (Encoded as an accumulation over a floating subinterval of time between the reference time and valid time)")] - FlashFloodGuidance = 0, + ///Flash flood guidance (Encoded as an accumulation over a floating subinterval of time between the reference time and valid time) (kg m-2) + [Description( + "Flash flood guidance (Encoded as an accumulation over a floating subinterval of time between the reference time and valid time)")] + FlashFloodGuidance = 0, - ///Flash flood runoff (Encoded as an accumulation over a floating subinterval of time) (kg m-2) - [Description("Flash flood runoff (Encoded as an accumulation over a floating subinterval of time)")] - FlashFloodRunoff = 1, + ///Flash flood runoff (Encoded as an accumulation over a floating subinterval of time) (kg m-2) + [Description("Flash flood runoff (Encoded as an accumulation over a floating subinterval of time)")] + FlashFloodRunoff = 1, - ///Remotely sensed snow cover (code table 4.215) - [Description("Remotely sensed snow cover (code table 4.215)")] - RemotelySensedSnowCover = 2, + ///Remotely sensed snow cover (code table 4.215) + [Description("Remotely sensed snow cover (code table 4.215)")] + RemotelySensedSnowCover = 2, - ///Elevation of snow covered terrain (code table 4.216) - [Description("Elevation of snow covered terrain (code table 4.216)")] - ElevationOfSnowCoveredTerrain = 3, + ///Elevation of snow covered terrain (code table 4.216) + [Description("Elevation of snow covered terrain (code table 4.216)")] + ElevationOfSnowCoveredTerrain = 3, - ///Snow water equivalent percent of normal (%) - [Description("Snow water equivalent percent of normal")] - SnowWaterEquivalentPercentOfNormal = 4, + ///Snow water equivalent percent of normal (%) + [Description("Snow water equivalent percent of normal")] + SnowWaterEquivalentPercentOfNormal = 4, - #endregion + #endregion - #region Product Discipline 1: Hydrologic products, Parameter Category 1: Hydrology probabilities + #region Product Discipline 1: Hydrologic products, Parameter Category 1: Hydrology probabilities - ///Conditional percent precipitation amount fractile for an overall period (kg m-2(Encoded as an accumulation).) - [Description("Conditional percent precipitation amount fractile for an overall period")] - ConditionalPercentPrecipitationAmountFractileForAnOverallPeriod = 0, + ///Conditional percent precipitation amount fractile for an overall period (kg m-2(Encoded as an accumulation).) + [Description("Conditional percent precipitation amount fractile for an overall period")] + ConditionalPercentPrecipitationAmountFractileForAnOverallPeriod = 0, - ///Percent precipitation in a sub-period of an overall period (Encoded as per cent accumulation over the sub-period) (%) - [Description( - "Percent precipitation in a sub-period of an overall period (Encoded as per cent accumulation over the sub-period)")] - PercentPrecipitationInASubPeriodOfAnOverallPeriod = 1, + ///Percent precipitation in a sub-period of an overall period (Encoded as per cent accumulation over the sub-period) (%) + [Description( + "Percent precipitation in a sub-period of an overall period (Encoded as per cent accumulation over the sub-period)")] + PercentPrecipitationInASubPeriodOfAnOverallPeriod = 1, - ///Probability of 0.01 inch of precipitation (POP) (%) - [Description("Probability of 0.01 inch of precipitation (POP)")] - ProbabilityOf001InchOfPrecipitationPop = 2, + ///Probability of 0.01 inch of precipitation (POP) (%) + [Description("Probability of 0.01 inch of precipitation (POP)")] + ProbabilityOf001InchOfPrecipitationPop = 2, - #endregion + #endregion - #region Product Discipline 2: Land surface products, Parameter Category 0: Vegetation/Biomass + #region Product Discipline 2: Land surface products, Parameter Category 0: Vegetation/Biomass - ///Land cover (1=land, 2=sea) (Proportion) - [Description("Land cover (1=land, 2=sea)")] - LandCover = 0, + ///Land cover (1=land, 2=sea) (Proportion) + [Description("Land cover (1=land, 2=sea)")] + LandCover = 0, - ///Surface roughness (m) - [Description("Surface roughness")] SurfaceRoughness = 1, + ///Surface roughness (m) + [Description("Surface roughness")] SurfaceRoughness = 1, - ///Soil temperature - [Description("Soil temperature")] SoilTemperature = 2, + ///Soil temperature + [Description("Soil temperature")] SoilTemperature = 2, - ///Soil moisture content (kg m-2) - [Description("Soil moisture content")] SoilMoistureContent = 3, + ///Soil moisture content (kg m-2) + [Description("Soil moisture content")] SoilMoistureContent = 3, - ///Vegetation (%) - [Description("Vegetation")] Vegetation = 4, + ///Vegetation (%) + [Description("Vegetation")] Vegetation = 4, - ///Water runoff (kg m-2) - [Description("Water runoff")] WaterRunoff = 5, + ///Water runoff (kg m-2) + [Description("Water runoff")] WaterRunoff = 5, - ///Evapotranspiration (kg-2 s-1) - [Description("Evapotranspiration")] Evapotranspiration = 6, + ///Evapotranspiration (kg-2 s-1) + [Description("Evapotranspiration")] Evapotranspiration = 6, - ///Model terrain height (m) - [Description("Model terrain height")] ModelTerrainHeight = 7, + ///Model terrain height (m) + [Description("Model terrain height")] ModelTerrainHeight = 7, - ///Land use (Code table (4.212)) - [Description("Land use")] LandUse = 8, + ///Land use (Code table (4.212)) + [Description("Land use")] LandUse = 8, - #endregion + #endregion - #region Product Discipline 2: Land surface products, Parameter Category 3: Soil Products + #region Product Discipline 2: Land surface products, Parameter Category 3: Soil Products - ///Soil type (Code table (4.213)) - [Description("Soil type")] SoilType = 0, + ///Soil type (Code table (4.213)) + [Description("Soil type")] SoilType = 0, - ///Upper layer soil temperature (K) - [Description("Upper layer soil temperature")] - UpperLayerSoilTemperature = 1, + ///Upper layer soil temperature (K) + [Description("Upper layer soil temperature")] + UpperLayerSoilTemperature = 1, - ///Upper layer soil moisture (kg m-3) - [Description("Upper layer soil moisture")] - UpperLayerSoilMoisture = 2, + ///Upper layer soil moisture (kg m-3) + [Description("Upper layer soil moisture")] + UpperLayerSoilMoisture = 2, - ///Lower layer soil moisture (kg m-3) - [Description("Lower layer soil moisture")] - LowerLayerSoilMoisture = 3, + ///Lower layer soil moisture (kg m-3) + [Description("Lower layer soil moisture")] + LowerLayerSoilMoisture = 3, - ///Bottom layer soil temperature (K) - [Description("Bottom layer soil temperature")] - BottomLayerSoilTemperature = 4, + ///Bottom layer soil temperature (K) + [Description("Bottom layer soil temperature")] + BottomLayerSoilTemperature = 4, - #endregion + #endregion - #region Product Discipline 3: Space products, Parameter Category 0: Image format products + #region Product Discipline 3: Space products, Parameter Category 0: Image format products - ///Scaled radiance (numeric) - [Description("Scaled radiance")] ScaledRadiance = 0, + ///Scaled radiance (numeric) + [Description("Scaled radiance")] ScaledRadiance = 0, - ///Scaled albedo (numeric) - [Description("Scaled albedo")] ScaledAlbedo = 1, + ///Scaled albedo (numeric) + [Description("Scaled albedo")] ScaledAlbedo = 1, - ///Scaled brightness temperature (numeric) - [Description("Scaled brightness temperature")] - ScaledBrightnessTemperature = 2, + ///Scaled brightness temperature (numeric) + [Description("Scaled brightness temperature")] + ScaledBrightnessTemperature = 2, - ///Scaled precipitable water (numeric) - [Description("Scaled precipitable water")] - ScaledPrecipitableWater = 3, + ///Scaled precipitable water (numeric) + [Description("Scaled precipitable water")] + ScaledPrecipitableWater = 3, - ///Scaled lifted index (numeric) - [Description("Scaled lifted index")] ScaledLiftedIndex = 4, + ///Scaled lifted index (numeric) + [Description("Scaled lifted index")] ScaledLiftedIndex = 4, - ///Scaled cloud top pressure (numeric) - [Description("Scaled cloud top pressure")] - ScaledCloudTopPressure = 5, + ///Scaled cloud top pressure (numeric) + [Description("Scaled cloud top pressure")] + ScaledCloudTopPressure = 5, - ///Scaled skin temperature (numeric) - [Description("Scaled skin temperature")] - ScaledSkinTemperature = 6, + ///Scaled skin temperature (numeric) + [Description("Scaled skin temperature")] + ScaledSkinTemperature = 6, - ///Cloud mask (Code table 4.217) - [Description("Cloud mask")] CloudMask = 7, + ///Cloud mask (Code table 4.217) + [Description("Cloud mask")] CloudMask = 7, - #endregion + #endregion - #region Product Discipline 3: Space products, Parameter Category 1: Quantitative products + #region Product Discipline 3: Space products, Parameter Category 1: Quantitative products - ///Estimated precipitation (kg m-2) - [Description("Estimated precipitation")] - EstimatedPrecipitation = 0, + ///Estimated precipitation (kg m-2) + [Description("Estimated precipitation")] + EstimatedPrecipitation = 0, - #endregion + #endregion - #region Product Discipline 10: Oceanographic products, Parameter Category 0: Waves + #region Product Discipline 10: Oceanographic products, Parameter Category 0: Waves - ///Wave spectra (1) (-) - [Description("Wave spectra (1)")] WaveSpectra1 = 0, + ///Wave spectra (1) (-) + [Description("Wave spectra (1)")] WaveSpectra1 = 0, - ///Wave spectra (2) (-) - [Description("Wave spectra (2)")] WaveSpectra2 = 1, + ///Wave spectra (2) (-) + [Description("Wave spectra (2)")] WaveSpectra2 = 1, - ///Wave spectra (3) (-) - [Description("Wave spectra (3)")] WaveSpectra3 = 2, + ///Wave spectra (3) (-) + [Description("Wave spectra (3)")] WaveSpectra3 = 2, - ///Significant height of combined wind waves and swell (m) - [Description("Significant height of combined wind waves and swell")] - SignificantHeightOfCombinedWindWavesAndSwell = 3, + ///Significant height of combined wind waves and swell (m) + [Description("Significant height of combined wind waves and swell")] + SignificantHeightOfCombinedWindWavesAndSwell = 3, - ///Direction of wind waves (Degree true) - [Description("Direction of wind waves")] - DirectionOfWindWaves = 4, + ///Direction of wind waves (Degree true) + [Description("Direction of wind waves")] + DirectionOfWindWaves = 4, - ///Significant height of wind waves (m) - [Description("Significant height of wind waves")] - SignificantHeightOfWindWaves = 5, + ///Significant height of wind waves (m) + [Description("Significant height of wind waves")] + SignificantHeightOfWindWaves = 5, - ///Mean period of wind waves (s) - [Description("Mean period of wind waves")] - MeanPeriodOfWindWaves = 6, + ///Mean period of wind waves (s) + [Description("Mean period of wind waves")] + MeanPeriodOfWindWaves = 6, - ///Direction of swell waves (Degree true) - [Description("Direction of swell waves")] - DirectionOfSwellWaves = 7, + ///Direction of swell waves (Degree true) + [Description("Direction of swell waves")] + DirectionOfSwellWaves = 7, - ///Significant height of swell waves (m) - [Description("Significant height of swell waves")] - SignificantHeightOfSwellWaves = 8, + ///Significant height of swell waves (m) + [Description("Significant height of swell waves")] + SignificantHeightOfSwellWaves = 8, - ///Mean period of swell waves (s) - [Description("Mean period of swell waves")] - MeanPeriodOfSwellWaves = 9, + ///Mean period of swell waves (s) + [Description("Mean period of swell waves")] + MeanPeriodOfSwellWaves = 9, - ///Primary wave direction (Degree true) - [Description("Primary wave direction")] - PrimaryWaveDirection = 10, + ///Primary wave direction (Degree true) + [Description("Primary wave direction")] + PrimaryWaveDirection = 10, - ///Primary wave mean period (s) - [Description("Primary wave mean period")] - PrimaryWaveMeanPeriod = 11, + ///Primary wave mean period (s) + [Description("Primary wave mean period")] + PrimaryWaveMeanPeriod = 11, - ///Secondary wave direction (Degree true) - [Description("Secondary wave direction")] - SecondaryWaveDirection = 12, + ///Secondary wave direction (Degree true) + [Description("Secondary wave direction")] + SecondaryWaveDirection = 12, - ///Secondary wave mean period (s) - [Description("Secondary wave mean period")] - SecondaryWaveMeanPeriod = 13, + ///Secondary wave mean period (s) + [Description("Secondary wave mean period")] + SecondaryWaveMeanPeriod = 13, - #endregion + #endregion - #region Product Discipline 10: Oceanographic products, Parameter Category 1: Currents + #region Product Discipline 10: Oceanographic products, Parameter Category 1: Currents - ///Current direction (Degree true) - [Description("Current direction")] CurrentDirection = 0, + ///Current direction (Degree true) + [Description("Current direction")] CurrentDirection = 0, - ///Current speed (m s-1) - [Description("Current speed")] CurrentSpeed = 1, + ///Current speed (m s-1) + [Description("Current speed")] CurrentSpeed = 1, - ///u-component of current (m s-1) - [Description("u-component of current")] - UComponentOfCurrent = 2, + ///u-component of current (m s-1) + [Description("u-component of current")] + UComponentOfCurrent = 2, - ///v-component of current (m s-1) - [Description("v-component of current")] - VComponentOfCurrent = 3, + ///v-component of current (m s-1) + [Description("v-component of current")] + VComponentOfCurrent = 3, - #endregion + #endregion - #region Product Discipline 10: Oceanographic products, Parameter Category 2: Ice + #region Product Discipline 10: Oceanographic products, Parameter Category 2: Ice - ///Ice cover (Proportion) - [Description("Ice cover")] IceCover = 0, + ///Ice cover (Proportion) + [Description("Ice cover")] IceCover = 0, - ///Ice thickness (m) - [Description("Ice thickness")] IceThickness = 1, + ///Ice thickness (m) + [Description("Ice thickness")] IceThickness = 1, - ///Direction of ice drift (Degree true) - [Description("Direction of ice drift")] - DirectionOfIceDrift = 2, + ///Direction of ice drift (Degree true) + [Description("Direction of ice drift")] + DirectionOfIceDrift = 2, - ///Speed of ice drift (m s-1) - [Description("Speed of ice drift")] SpeedOfIceDrift = 3, + ///Speed of ice drift (m s-1) + [Description("Speed of ice drift")] SpeedOfIceDrift = 3, - ///u-component of ice drift (m s-1) - [Description("u-component of ice drift")] - UComponentOfIceDrift = 4, + ///u-component of ice drift (m s-1) + [Description("u-component of ice drift")] + UComponentOfIceDrift = 4, - ///v-component of ice drift (m s-1) - [Description("v-component of ice drift")] - VComponentOfIceDrift = 5, + ///v-component of ice drift (m s-1) + [Description("v-component of ice drift")] + VComponentOfIceDrift = 5, - ///Ice growth rate (m s-1) - [Description("Ice growth rate")] IceGrowthRate = 6, + ///Ice growth rate (m s-1) + [Description("Ice growth rate")] IceGrowthRate = 6, - ///Ice divergence (s-1) - [Description("Ice divergence")] IceDivergence = 7, + ///Ice divergence (s-1) + [Description("Ice divergence")] IceDivergence = 7, - #endregion + #endregion - #region Product Discipline 10: Oceanographic products, Parameter Category 3: Surface Properties + #region Product Discipline 10: Oceanographic products, Parameter Category 3: Surface Properties - ///Water temperature (K) - [Description("Water temperature")] WaterTemperature = 0, + ///Water temperature (K) + [Description("Water temperature")] WaterTemperature = 0, - ///Deviation of sea level from mean (m) - [Description("Deviation of sea level from mean")] - DeviationOfSeaLevelFromMean = 1, + ///Deviation of sea level from mean (m) + [Description("Deviation of sea level from mean")] + DeviationOfSeaLevelFromMean = 1, - #endregion + #endregion - #region Product Discipline 10: Oceanographic products, Parameter Category 4: Sub-surface Properties + #region Product Discipline 10: Oceanographic products, Parameter Category 4: Sub-surface Properties - ///Main thermocline depth (m) - [Description("Main thermocline depth")] - MainThermoclineDepth = 0, + ///Main thermocline depth (m) + [Description("Main thermocline depth")] + MainThermoclineDepth = 0, - ///Main thermocline anomaly (m) - [Description("Main thermocline anomaly")] - MainThermoclineAnomaly = 1, + ///Main thermocline anomaly (m) + [Description("Main thermocline anomaly")] + MainThermoclineAnomaly = 1, - ///Transient thermocline depth (m) - [Description("Transient thermocline depth")] - TransientThermoclineDepth = 2, + ///Transient thermocline depth (m) + [Description("Transient thermocline depth")] + TransientThermoclineDepth = 2, - ///Salinity (kg kg-1) - [Description("Salinity")] Salinity = 3, + ///Salinity (kg kg-1) + [Description("Salinity")] Salinity = 3, - #endregion + #endregion - ///Missing - [Description("Missing")] Missing = 255, - } + ///Missing + [Description("Missing")] Missing = 255, } \ No newline at end of file diff --git a/src/NGrib/Grib2/CodeTables/4_3_GeneratingProcessType.cs b/src/NGrib/Grib2/CodeTables/4_3_GeneratingProcessType.cs index 811d394..6cc0828 100644 --- a/src/NGrib/Grib2/CodeTables/4_3_GeneratingProcessType.cs +++ b/src/NGrib/Grib2/CodeTables/4_3_GeneratingProcessType.cs @@ -19,42 +19,41 @@ using System.ComponentModel; -namespace NGrib.Grib2.CodeTables +namespace NGrib.Grib2.CodeTables; + +/// +/// Code table 4.3: Type of generating process +/// +public enum GeneratingProcessType { - /// - /// Code table 4.3: Type of generating process - /// - public enum GeneratingProcessType - { - ///Analysis - [Description("Analysis")] Analysis = 0, + ///Analysis + [Description("Analysis")] Analysis = 0, - ///Initialization - [Description("Initialization")] Initialization = 1, + ///Initialization + [Description("Initialization")] Initialization = 1, - ///Forecast - [Description("Forecast")] Forecast = 2, + ///Forecast + [Description("Forecast")] Forecast = 2, - ///Bias corrected forecast - [Description("Bias corrected forecast")] - BiasCorrectedForecast = 3, + ///Bias corrected forecast + [Description("Bias corrected forecast")] + BiasCorrectedForecast = 3, - ///Ensemble forecast - [Description("Ensemble forecast")] EnsembleForecast = 4, + ///Ensemble forecast + [Description("Ensemble forecast")] EnsembleForecast = 4, - ///Probability forecast - [Description("Probability forecast")] ProbabilityForecast = 5, + ///Probability forecast + [Description("Probability forecast")] ProbabilityForecast = 5, - ///Forecast error - [Description("Forecast error")] ForecastError = 6, + ///Forecast error + [Description("Forecast error")] ForecastError = 6, - ///Analysis error - [Description("Analysis error")] AnalysisError = 7, + ///Analysis error + [Description("Analysis error")] AnalysisError = 7, - ///Observation - [Description("Observation")] Observation = 8, + ///Observation + [Description("Observation")] Observation = 8, - ///Missing - [Description("Missing")] Missing = 255, - } + ///Missing + [Description("Missing")] Missing = 255, } \ No newline at end of file diff --git a/src/NGrib/Grib2/CodeTables/4_4_TimeRangeUnit.cs b/src/NGrib/Grib2/CodeTables/4_4_TimeRangeUnit.cs index 398ec75..92cfea2 100644 --- a/src/NGrib/Grib2/CodeTables/4_4_TimeRangeUnit.cs +++ b/src/NGrib/Grib2/CodeTables/4_4_TimeRangeUnit.cs @@ -19,50 +19,49 @@ using System.ComponentModel; -namespace NGrib.Grib2.CodeTables +namespace NGrib.Grib2.CodeTables; + +/// +/// Code Table 4.4: Indicator of unit of time range +/// +public enum TimeRangeUnitGrib2 { - /// - /// Code Table 4.4: Indicator of unit of time range - /// - public enum TimeRangeUnit - { - ///Minute - [Description("Minute")] Minute = 0, + ///Minute + [Description("Minute")] Minute = 0, - ///Hour - [Description("Hour")] Hour = 1, + ///Hour + [Description("Hour")] Hour = 1, - ///Day - [Description("Day")] Day = 2, + ///Day + [Description("Day")] Day = 2, - ///Month - [Description("Month")] Month = 3, + ///Month + [Description("Month")] Month = 3, - ///Year - [Description("Year")] Year = 4, + ///Year + [Description("Year")] Year = 4, - ///Decade (10 years) - [Description("Decade (10 years)")] Decade = 5, + ///Decade (10 years) + [Description("Decade (10 years)")] Decade = 5, - ///Normal (30 years) - [Description("Normal (30 years)")] Normal = 6, + ///Normal (30 years) + [Description("Normal (30 years)")] Normal = 6, - ///Century (100 years) - [Description("Century (100 years)")] Century = 7, + ///Century (100 years) + [Description("Century (100 years)")] Century = 7, - ///3 hours - [Description("3 hours")] Hours3 = 10, + ///3 hours + [Description("3 hours")] Hours3 = 10, - ///6 hours - [Description("6 hours")] Hours6 = 11, + ///6 hours + [Description("6 hours")] Hours6 = 11, - ///12 hours - [Description("12 hours")] Hours12 = 12, + ///12 hours + [Description("12 hours")] Hours12 = 12, - ///Second - [Description("Second")] Second = 13, + ///Second + [Description("Second")] Second = 13, - ///Missing - [Description("Missing")] Missing = 255, - } + ///Missing + [Description("Missing")] Missing = 255, } \ No newline at end of file diff --git a/src/NGrib/Grib2/CodeTables/4_5_FixedSurfaceType.cs b/src/NGrib/Grib2/CodeTables/4_5_FixedSurfaceType.cs index a47713b..2bb458d 100644 --- a/src/NGrib/Grib2/CodeTables/4_5_FixedSurfaceType.cs +++ b/src/NGrib/Grib2/CodeTables/4_5_FixedSurfaceType.cs @@ -19,93 +19,92 @@ using System.ComponentModel; -namespace NGrib.Grib2.CodeTables +namespace NGrib.Grib2.CodeTables; + +/// +/// Code table 4.5: Fixed surface types and units +/// +public enum FixedSurfaceType { - /// - /// Code table 4.5: Fixed surface types and units - /// - public enum FixedSurfaceType - { - ///Ground or water surface - [Description("Ground or water surface")] - GroundOrWaterSurface = 1, + ///Ground or water surface + [Description("Ground or water surface")] + GroundOrWaterSurface = 1, - ///Cloud base level - [Description("Cloud base level")] CloudBaseLevel = 2, + ///Cloud base level + [Description("Cloud base level")] CloudBaseLevel = 2, - ///Level of cloud tops - [Description("Level of cloud tops")] LevelOfCloudTops = 3, + ///Level of cloud tops + [Description("Level of cloud tops")] LevelOfCloudTops = 3, - ///Level of 0°C isotherm - [Description("Level of 0°C isotherm")] LevelOf0CIsotherm = 4, + ///Level of 0°C isotherm + [Description("Level of 0°C isotherm")] LevelOf0CIsotherm = 4, - ///Level of adiabatic condensation lifted from the surface - [Description("Level of adiabatic condensation lifted from the surface")] - LevelOfAdiabaticCondensationLiftedFromTheSurface = 5, + ///Level of adiabatic condensation lifted from the surface + [Description("Level of adiabatic condensation lifted from the surface")] + LevelOfAdiabaticCondensationLiftedFromTheSurface = 5, - ///Maximum wind level - [Description("Maximum wind level")] MaximumWindLevel = 6, + ///Maximum wind level + [Description("Maximum wind level")] MaximumWindLevel = 6, - ///Tropopause - [Description("Tropopause")] Tropopause = 7, + ///Tropopause + [Description("Tropopause")] Tropopause = 7, - ///Nominal top of the atmosphere - [Description("Nominal top of the atmosphere")] - NominalTopOfTheAtmosphere = 8, + ///Nominal top of the atmosphere + [Description("Nominal top of the atmosphere")] + NominalTopOfTheAtmosphere = 8, - ///Sea bottom - [Description("Sea bottom")] SeaBottom = 9, + ///Sea bottom + [Description("Sea bottom")] SeaBottom = 9, - ///Isothermal level (K) - [Description("Isothermal level")] IsothermalLevel = 20, + ///Isothermal level (K) + [Description("Isothermal level")] IsothermalLevel = 20, - ///Isobaric surface (Pa) - [Description("Isobaric surface")] IsobaricSurface = 100, + ///Isobaric surface (Pa) + [Description("Isobaric surface")] IsobaricSurface = 100, - ///Mean sea level - [Description("Mean sea level")] MeanSeaLevel = 101, + ///Mean sea level + [Description("Mean sea level")] MeanSeaLevel = 101, - ///Specific altitude above mean sea level (m) - [Description("Specific altitude above mean sea level")] - SpecificAltitudeAboveMeanSeaLevel = 102, + ///Specific altitude above mean sea level (m) + [Description("Specific altitude above mean sea level")] + SpecificAltitudeAboveMeanSeaLevel = 102, - ///Specified height level above ground (m) - [Description("Specified height level above ground")] - SpecifiedHeightLevelAboveGround = 103, + ///Specified height level above ground (m) + [Description("Specified height level above ground")] + SpecifiedHeightLevelAboveGround = 103, - ///Sigma level (sigma value) - [Description("Sigma level")] SigmaLevel = 104, + ///Sigma level (sigma value) + [Description("Sigma level")] SigmaLevel = 104, - ///Hybrid level - [Description("Hybrid level")] HybridLevel = 105, + ///Hybrid level + [Description("Hybrid level")] HybridLevel = 105, - ///Depth below land surface (m) - [Description("Depth below land surface")] - DepthBelowLandSurface = 106, + ///Depth below land surface (m) + [Description("Depth below land surface")] + DepthBelowLandSurface = 106, - ///Isentropic (theta) level (K) - [Description("Isentropic (theta) level")] - IsentropicLevel = 107, + ///Isentropic (theta) level (K) + [Description("Isentropic (theta) level")] + IsentropicLevel = 107, - ///Level at specified pressure difference from ground to level (Pa) - [Description("Level at specified pressure difference from ground to level")] - LevelAtSpecifiedPressureDifferenceFromGroundToLevel = 108, + ///Level at specified pressure difference from ground to level (Pa) + [Description("Level at specified pressure difference from ground to level")] + LevelAtSpecifiedPressureDifferenceFromGroundToLevel = 108, - ///Potential vorticity surface (K m2 kg-1 s-1) - [Description("Potential vorticity surface")] - PotentialVorticitySurface = 109, + ///Potential vorticity surface (K m2 kg-1 s-1) + [Description("Potential vorticity surface")] + PotentialVorticitySurface = 109, - ///Eta* level - [Description("Eta* level")] EtaLevel = 111, + ///Eta* level + [Description("Eta* level")] EtaLevel = 111, - ///Mixed layer depth (m) - [Description("Mixed layer depth")] MixedLayerDepth = 117, + ///Mixed layer depth (m) + [Description("Mixed layer depth")] MixedLayerDepth = 117, - ///Depth below sea level (m) - [Description("Depth below sea level")] - DepthBelowSeaLevel = 160, + ///Depth below sea level (m) + [Description("Depth below sea level")] + DepthBelowSeaLevel = 160, - ///Missing - [Description("Missing ")] Missing = 255, - } + ///Missing + [Description("Missing ")] Missing = 255, } \ No newline at end of file diff --git a/src/NGrib/Grib2/CodeTables/4_6_EnsembleForecastType.cs b/src/NGrib/Grib2/CodeTables/4_6_EnsembleForecastType.cs index ffbd17a..56daeac 100644 --- a/src/NGrib/Grib2/CodeTables/4_6_EnsembleForecastType.cs +++ b/src/NGrib/Grib2/CodeTables/4_6_EnsembleForecastType.cs @@ -1,38 +1,37 @@ -namespace NGrib.Grib2.CodeTables +namespace NGrib.Grib2.CodeTables; + +/// +/// Code table 4.6 - Type of ensemble forecast +/// +public enum EnsembleForecastType { - /// - /// Code table 4.6 - Type of ensemble forecast - /// - public enum EnsembleForecastType - { - /// - /// Unperturbed high-resolution control forecast - /// - UnperturbedHighResolutionControlForecast = 0, + /// + /// Unperturbed high-resolution control forecast + /// + UnperturbedHighResolutionControlForecast = 0, - /// - /// Unperturbed low-resolution control forecast - /// - UnperturbedLowResolutionControlForecast = 1, + /// + /// Unperturbed low-resolution control forecast + /// + UnperturbedLowResolutionControlForecast = 1, - /// - /// Negatively perturbed forecast - /// - NegativelyPerturbedForecast = 2, + /// + /// Negatively perturbed forecast + /// + NegativelyPerturbedForecast = 2, - /// - /// Positively perturbed forecast - /// - PositivelyPerturbedForecast = 3, + /// + /// Positively perturbed forecast + /// + PositivelyPerturbedForecast = 3, - /// - /// Multi-model forecast - /// - MultiModelForecast = 4, + /// + /// Multi-model forecast + /// + MultiModelForecast = 4, - /// - /// Missing - /// - Missing = 255, - } -} + /// + /// Missing + /// + Missing = 255, +} \ No newline at end of file diff --git a/src/NGrib/Grib2/CodeTables/5_1_OriginalFieldValuesType.cs b/src/NGrib/Grib2/CodeTables/5_1_OriginalFieldValuesType.cs index ed70b0f..6cf245e 100644 --- a/src/NGrib/Grib2/CodeTables/5_1_OriginalFieldValuesType.cs +++ b/src/NGrib/Grib2/CodeTables/5_1_OriginalFieldValuesType.cs @@ -17,26 +17,25 @@ * along with NGrib. If not, see . */ -namespace NGrib.Grib2.CodeTables +namespace NGrib.Grib2.CodeTables; + +/// +/// Code Table 5.1: Type of original field values +/// +public enum OriginalFieldValuesType { - /// - /// Code Table 5.1: Type of original field values - /// - public enum OriginalFieldValuesType - { - /// - /// Floating point - /// - FloatingPoint, + /// + /// Floating point + /// + FloatingPoint, - /// - /// Integer - /// - Integer, + /// + /// Integer + /// + Integer, - /// - /// Missing - /// - Missing = 255 - } + /// + /// Missing + /// + Missing = 255 } \ No newline at end of file diff --git a/src/NGrib/Grib2/CodeTables/5_4_GroupSplittingMethod.cs b/src/NGrib/Grib2/CodeTables/5_4_GroupSplittingMethod.cs index 1159a55..24cc874 100644 --- a/src/NGrib/Grib2/CodeTables/5_4_GroupSplittingMethod.cs +++ b/src/NGrib/Grib2/CodeTables/5_4_GroupSplittingMethod.cs @@ -17,26 +17,25 @@ * along with NGrib. If not, see . */ -namespace NGrib.Grib2.CodeTables +namespace NGrib.Grib2.CodeTables; + +/// +/// Code Table 5.4: Group Splitting Method +/// +public enum GroupSplittingMethod { - /// - /// Code Table 5.4: Group Splitting Method - /// - public enum GroupSplittingMethod - { - /// - /// Row by row splitting - /// - RowByRow, + /// + /// Row by row splitting + /// + RowByRow, - /// - /// General group splitting - /// - GeneralGroup, + /// + /// General group splitting + /// + GeneralGroup, - /// - /// Missing - /// - Missing, - } + /// + /// Missing + /// + Missing, } \ No newline at end of file diff --git a/src/NGrib/Grib2/CodeTables/5_5_ComplexPackingMissingValueManagement.cs b/src/NGrib/Grib2/CodeTables/5_5_ComplexPackingMissingValueManagement.cs index 6d72c2b..34f815b 100644 --- a/src/NGrib/Grib2/CodeTables/5_5_ComplexPackingMissingValueManagement.cs +++ b/src/NGrib/Grib2/CodeTables/5_5_ComplexPackingMissingValueManagement.cs @@ -17,31 +17,30 @@ * along with NGrib. If not, see . */ -namespace NGrib.Grib2.CodeTables +namespace NGrib.Grib2.CodeTables; + +/// +/// Code Table 5.5: Missing Value Management for Complex Packing +/// +public enum ComplexPackingMissingValueManagement { - /// - /// Code Table 5.5: Missing Value Management for Complex Packing - /// - public enum ComplexPackingMissingValueManagement - { - /// - /// No explicit missing values included within data values. - /// - None, + /// + /// No explicit missing values included within data values. + /// + None, - /// - /// Primary missing values included within data values. - /// - Primary, + /// + /// Primary missing values included within data values. + /// + Primary, - /// - /// Primary and secondary missing values included within data values. - /// - PrimaryAndSecondary, + /// + /// Primary and secondary missing values included within data values. + /// + PrimaryAndSecondary, - /// - /// Missing. - /// - Missing - } + /// + /// Missing. + /// + Missing } \ No newline at end of file diff --git a/src/NGrib/Grib2/CodeTables/5_6_SpatialDifferencingOrder.cs b/src/NGrib/Grib2/CodeTables/5_6_SpatialDifferencingOrder.cs index 6e50a77..c7adcfe 100644 --- a/src/NGrib/Grib2/CodeTables/5_6_SpatialDifferencingOrder.cs +++ b/src/NGrib/Grib2/CodeTables/5_6_SpatialDifferencingOrder.cs @@ -17,26 +17,25 @@ * along with NGrib. If not, see . */ -namespace NGrib.Grib2.CodeTables +namespace NGrib.Grib2.CodeTables; + +/// +/// Code Table 5.6: Order of Spatial Differencing +/// +public enum SpatialDifferencingOrder { - /// - /// Code Table 5.6: Order of Spatial Differencing - /// - public enum SpatialDifferencingOrder - { - /// - /// First-order spatial differencing. - /// - FirstOrder = 1, + /// + /// First-order spatial differencing. + /// + FirstOrder = 1, - /// - /// Second-order spatial differencing. - /// - SecondOrder = 2, + /// + /// Second-order spatial differencing. + /// + SecondOrder = 2, - /// - /// Missing. - /// - Missing = 255, - } + /// + /// Missing. + /// + Missing = 255, } \ No newline at end of file diff --git a/src/NGrib/Grib2/CodeTables/C_1_Center.cs b/src/NGrib/Grib2/CodeTables/C_1_Center.cs index 173b5db..7be72da 100644 --- a/src/NGrib/Grib2/CodeTables/C_1_Center.cs +++ b/src/NGrib/Grib2/CodeTables/C_1_Center.cs @@ -17,970 +17,967 @@ * along with NGrib. If not, see . */ -using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; -using System.Linq; -namespace NGrib.Grib2.CodeTables +namespace NGrib.Grib2.CodeTables; + +[SuppressMessage("ReSharper", "IdentifierTypo")] +[SuppressMessage("ReSharper", "CommentTypo")] +[SuppressMessage("ReSharper", "StringLiteralTypo")] +public readonly struct Center { - [SuppressMessage("ReSharper", "IdentifierTypo")] - [SuppressMessage("ReSharper", "CommentTypo")] - [SuppressMessage("ReSharper", "StringLiteralTypo")] - public readonly struct Center - { - public int Id { get; } - public string Name { get; } + public int Id { get; } + public string Name { get; } - private Center(int id, string name = null) - { - Id = id; - Name = name; - } + private Center(int id, string name = null) + { + Id = id; + Name = name; + } - public bool Equals(Center other) => Id == other.Id; + public bool Equals(Center other) => Id == other.Id; - public override bool Equals(object obj) => obj is Center other && Equals(other); + public override bool Equals(object obj) => obj is Center other && Equals(other); - public override int GetHashCode() => Id.GetHashCode(); + public override int GetHashCode() => Id.GetHashCode(); - public static Center GetCenterById(int centerId) - { - var centers = AllCenters.Where(c => c.Id == centerId).ToArray(); - return centers.Any() ? centers[0] : new Center(centerId); - } + public static Center GetCenterById(int centerId) + { + var centers = AllCenters.Where(c => c.Id == centerId).ToArray(); + return centers.Any() ? centers[0] : new Center(centerId); + } - ///WMO Secretariat (0) - public static Center WmoSecretariat { get; } = new Center(0, "WMO Secretariat"); + ///WMO Secretariat (0) + public static Center WmoSecretariat { get; } = new Center(0, "WMO Secretariat"); - ///Melbourne (1) - public static Center Melbourne { get; } = new Center(1, "Melbourne"); + ///Melbourne (1) + public static Center Melbourne { get; } = new Center(1, "Melbourne"); - ///Melbourne (2) - public static Center Melbourne2 { get; } = new Center(2, "Melbourne"); + ///Melbourne (2) + public static Center Melbourne2 { get; } = new Center(2, "Melbourne"); - ///Melbourne (3) - public static Center Melbourne3 { get; } = new Center(3, "Melbourne"); + ///Melbourne (3) + public static Center Melbourne3 { get; } = new Center(3, "Melbourne"); - ///Moscow (4) - public static Center Moscow { get; } = new Center(4, "Moscow"); + ///Moscow (4) + public static Center Moscow { get; } = new Center(4, "Moscow"); - ///Moscow (5) - public static Center Moscow5 { get; } = new Center(5, "Moscow"); + ///Moscow (5) + public static Center Moscow5 { get; } = new Center(5, "Moscow"); - ///Moscow (6) - public static Center Moscow6 { get; } = new Center(6, "Moscow"); + ///Moscow (6) + public static Center Moscow6 { get; } = new Center(6, "Moscow"); - ///US National Weather Service, National Centers for Environmental Prediction (NCEP) (7) - public static Center UsNcep { get; } = new Center(7, - "US National Weather Service, National Centers for Environmental Prediction (NCEP)"); + ///US National Weather Service, National Centers for Environmental Prediction (NCEP) (7) + public static Center UsNcep { get; } = new Center(7, + "US National Weather Service, National Centers for Environmental Prediction (NCEP)"); - ///US National Weather Service Telecommunications Gateway (NWSTG) (8) - public static Center UsNwstg { get; } = - new Center(8, "US National Weather Service Telecommunications Gateway (NWSTG)"); + ///US National Weather Service Telecommunications Gateway (NWSTG) (8) + public static Center UsNwstg { get; } = + new Center(8, "US National Weather Service Telecommunications Gateway (NWSTG)"); - ///US National Weather Service - Other (9) - public static Center UsNwsOther { get; } = new Center(9, "US National Weather Service - Other"); + ///US National Weather Service - Other (9) + public static Center UsNwsOther { get; } = new Center(9, "US National Weather Service - Other"); - ///Cairo (RSMC) (10) - public static Center Cairo { get; } = new Center(10, "Cairo (RSMC)"); + ///Cairo (RSMC) (10) + public static Center Cairo { get; } = new Center(10, "Cairo (RSMC)"); - ///Cairo (RSMC) (11) - public static Center CairoReserved { get; } = new Center(11, "Cairo (RSMC)"); + ///Cairo (RSMC) (11) + public static Center CairoReserved { get; } = new Center(11, "Cairo (RSMC)"); - ///Dakar (RSMC) (12) - public static Center Dakar { get; } = new Center(12, "Dakar (RSMC)"); + ///Dakar (RSMC) (12) + public static Center Dakar { get; } = new Center(12, "Dakar (RSMC)"); - ///Dakar (RSMC) (13) - public static Center DakarReserved { get; } = new Center(13, "Dakar (RSMC)"); + ///Dakar (RSMC) (13) + public static Center DakarReserved { get; } = new Center(13, "Dakar (RSMC)"); - ///Nairobi (RSMC) (14) - public static Center Nairobi { get; } = new Center(14, "Nairobi (RSMC)"); + ///Nairobi (RSMC) (14) + public static Center Nairobi { get; } = new Center(14, "Nairobi (RSMC)"); - ///Nairobi (RSMC) (15) - public static Center NairobiReserved { get; } = new Center(15, "Nairobi (RSMC)"); + ///Nairobi (RSMC) (15) + public static Center NairobiReserved { get; } = new Center(15, "Nairobi (RSMC)"); - ///Casablanca (RSMC) (16) - public static Center Casablanca { get; } = new Center(16, "Casablanca (RSMC)"); + ///Casablanca (RSMC) (16) + public static Center Casablanca { get; } = new Center(16, "Casablanca (RSMC)"); - ///Tunis (RSMC) (17) - public static Center Tunis { get; } = new Center(17, "Tunis (RSMC)"); + ///Tunis (RSMC) (17) + public static Center Tunis { get; } = new Center(17, "Tunis (RSMC)"); - ///Tunis-Casablanca (RSMC) (18) - public static Center TunisCasablanca { get; } = new Center(18, "Tunis-Casablanca (RSMC)"); + ///Tunis-Casablanca (RSMC) (18) + public static Center TunisCasablanca { get; } = new Center(18, "Tunis-Casablanca (RSMC)"); - ///Tunis-Casablanca (RSMC) (19) - public static Center TunisCasablancaReserved { get; } = new Center(19, "Tunis-Casablanca (RSMC)"); + ///Tunis-Casablanca (RSMC) (19) + public static Center TunisCasablancaReserved { get; } = new Center(19, "Tunis-Casablanca (RSMC)"); - ///Las Palmas (20) - public static Center LasPalmas { get; } = new Center(20, "Las Palmas"); + ///Las Palmas (20) + public static Center LasPalmas { get; } = new Center(20, "Las Palmas"); - ///Algiers (RSMC) (21) - public static Center Algiers { get; } = new Center(21, "Algiers (RSMC)"); + ///Algiers (RSMC) (21) + public static Center Algiers { get; } = new Center(21, "Algiers (RSMC)"); - ///ACMAD (22) - public static Center Acmad { get; } = new Center(22, "ACMAD"); + ///ACMAD (22) + public static Center Acmad { get; } = new Center(22, "ACMAD"); - ///Mozambique (NMC) (23) - public static Center Mozambique { get; } = new Center(23, "Mozambique (NMC)"); + ///Mozambique (NMC) (23) + public static Center Mozambique { get; } = new Center(23, "Mozambique (NMC)"); - ///Pretoria (RSMC) (24) - public static Center Pretoria { get; } = new Center(24, "Pretoria (RSMC)"); + ///Pretoria (RSMC) (24) + public static Center Pretoria { get; } = new Center(24, "Pretoria (RSMC)"); - ///La Réunion (RSMC) (25) - public static Center LaReunion { get; } = new Center(25, "La Réunion (RSMC)"); + ///La Réunion (RSMC) (25) + public static Center LaReunion { get; } = new Center(25, "La Réunion (RSMC)"); - ///Khabarovsk (RSMC) (26) - public static Center Khabarovsk { get; } = new Center(26, "Khabarovsk (RSMC)"); + ///Khabarovsk (RSMC) (26) + public static Center Khabarovsk { get; } = new Center(26, "Khabarovsk (RSMC)"); - ///Khabarovsk (RSMC) (27) - public static Center KhabarovskReserved { get; } = new Center(27, "Khabarovsk (RSMC)"); + ///Khabarovsk (RSMC) (27) + public static Center KhabarovskReserved { get; } = new Center(27, "Khabarovsk (RSMC)"); - ///New Delhi (RSMC) (28) - public static Center NewDelhi { get; } = new Center(28, "New Delhi (RSMC)"); + ///New Delhi (RSMC) (28) + public static Center NewDelhi { get; } = new Center(28, "New Delhi (RSMC)"); - ///New Delhi (RSMC) (29) - public static Center NewDelhiReserved { get; } = new Center(29, "New Delhi (RSMC)"); + ///New Delhi (RSMC) (29) + public static Center NewDelhiReserved { get; } = new Center(29, "New Delhi (RSMC)"); - ///Novosibirsk (RSMC) (30) - public static Center Novosibirsk { get; } = new Center(30, "Novosibirsk (RSMC)"); + ///Novosibirsk (RSMC) (30) + public static Center Novosibirsk { get; } = new Center(30, "Novosibirsk (RSMC)"); - ///Novosibirsk (RSMC) (31) - public static Center NovosibirskReserved { get; } = new Center(31, "Novosibirsk (RSMC)"); + ///Novosibirsk (RSMC) (31) + public static Center NovosibirskReserved { get; } = new Center(31, "Novosibirsk (RSMC)"); - ///Tashkent (RSMC) (32) - public static Center Tashkent { get; } = new Center(32, "Tashkent (RSMC)"); + ///Tashkent (RSMC) (32) + public static Center Tashkent { get; } = new Center(32, "Tashkent (RSMC)"); - ///Jeddah (RSMC) (33) - public static Center Jeddah { get; } = new Center(33, "Jeddah (RSMC)"); + ///Jeddah (RSMC) (33) + public static Center Jeddah { get; } = new Center(33, "Jeddah (RSMC)"); - ///Tokyo (RSMC), Japan Meteorological Agency (34) - public static Center Tokyo { get; } = new Center(34, "Tokyo (RSMC), Japan Meteorological Agency"); + ///Tokyo (RSMC), Japan Meteorological Agency (34) + public static Center Tokyo { get; } = new Center(34, "Tokyo (RSMC), Japan Meteorological Agency"); - ///Tokyo (RSMC), Japan Meteorological Agency (35) - public static Center TokyoReserved { get; } = new Center(35, "Tokyo (RSMC), Japan Meteorological Agency"); + ///Tokyo (RSMC), Japan Meteorological Agency (35) + public static Center TokyoReserved { get; } = new Center(35, "Tokyo (RSMC), Japan Meteorological Agency"); - ///Bangkok (36) - public static Center Bangkok { get; } = new Center(36, "Bangkok"); + ///Bangkok (36) + public static Center Bangkok { get; } = new Center(36, "Bangkok"); - ///Ulaanbaatar (37) - public static Center Ulaanbaatar { get; } = new Center(37, "Ulaanbaatar"); + ///Ulaanbaatar (37) + public static Center Ulaanbaatar { get; } = new Center(37, "Ulaanbaatar"); - ///Beijing (RSMC) (38) - public static Center Beijing { get; } = new Center(38, "Beijing (RSMC)"); + ///Beijing (RSMC) (38) + public static Center Beijing { get; } = new Center(38, "Beijing (RSMC)"); - ///Beijing (RSMC) (39) - public static Center BeijingReserved { get; } = new Center(39, "Beijing (RSMC)"); + ///Beijing (RSMC) (39) + public static Center BeijingReserved { get; } = new Center(39, "Beijing (RSMC)"); - ///Seoul (40) - public static Center Seoul { get; } = new Center(40, "Seoul"); + ///Seoul (40) + public static Center Seoul { get; } = new Center(40, "Seoul"); - ///Buenos Aires (RSMC) (41) - public static Center BuenosAires { get; } = new Center(41, "Buenos Aires (RSMC)"); + ///Buenos Aires (RSMC) (41) + public static Center BuenosAires { get; } = new Center(41, "Buenos Aires (RSMC)"); - ///Buenos Aires (RSMC) (42) - public static Center BuenosAiresReserved { get; } = new Center(42, "Buenos Aires (RSMC)"); + ///Buenos Aires (RSMC) (42) + public static Center BuenosAiresReserved { get; } = new Center(42, "Buenos Aires (RSMC)"); - ///Brasilia (RSMC) (43) - public static Center Brasilia { get; } = new Center(43, "Brasilia (RSMC)"); + ///Brasilia (RSMC) (43) + public static Center Brasilia { get; } = new Center(43, "Brasilia (RSMC)"); - ///Brasilia (RSMC) (44) - public static Center BrasiliaReserved { get; } = new Center(44, "Brasilia (RSMC)"); + ///Brasilia (RSMC) (44) + public static Center BrasiliaReserved { get; } = new Center(44, "Brasilia (RSMC)"); - ///Santiago (45) - public static Center Santiago { get; } = new Center(45, "Santiago"); + ///Santiago (45) + public static Center Santiago { get; } = new Center(45, "Santiago"); - ///Brazilian Space Agency ­ - INPE (46) - public static Center BrazilianSpaceAgencyInpe { get; } = new Center(46, "Brazilian Space Agency ­ - INPE"); + ///Brazilian Space Agency ­ - INPE (46) + public static Center BrazilianSpaceAgencyInpe { get; } = new Center(46, "Brazilian Space Agency ­ - INPE"); - ///Colombia (NMC) (47) - public static Center Colombia { get; } = new Center(47, "Colombia (NMC)"); + ///Colombia (NMC) (47) + public static Center Colombia { get; } = new Center(47, "Colombia (NMC)"); - ///Ecuador (NMC) (48) - public static Center Ecuador { get; } = new Center(48, "Ecuador (NMC)"); + ///Ecuador (NMC) (48) + public static Center Ecuador { get; } = new Center(48, "Ecuador (NMC)"); - ///Peru (NMC) (49) - public static Center Peru { get; } = new Center(49, "Peru (NMC)"); + ///Peru (NMC) (49) + public static Center Peru { get; } = new Center(49, "Peru (NMC)"); - ///Venezuela (Bolivarian Republic of) (NMC) (50) - public static Center Venezuela { get; } = new Center(50, "Venezuela (Bolivarian Republic of) (NMC)"); + ///Venezuela (Bolivarian Republic of) (NMC) (50) + public static Center Venezuela { get; } = new Center(50, "Venezuela (Bolivarian Republic of) (NMC)"); - ///Miami (RSMC) (51) - public static Center Miami { get; } = new Center(51, "Miami (RSMC)"); + ///Miami (RSMC) (51) + public static Center Miami { get; } = new Center(51, "Miami (RSMC)"); - ///Miami (RSMC), National Hurricane Center (52) - public static Center MiamiNhc { get; } = new Center(52, "Miami (RSMC), National Hurricane Center"); + ///Miami (RSMC), National Hurricane Center (52) + public static Center MiamiNhc { get; } = new Center(52, "Miami (RSMC), National Hurricane Center"); - ///Montreal (RSMC) (53) - public static Center Montreal { get; } = new Center(53, "Montreal (RSMC)"); + ///Montreal (RSMC) (53) + public static Center Montreal { get; } = new Center(53, "Montreal (RSMC)"); - ///Montreal (RSMC) (54) - public static Center MontrealReserved { get; } = new Center(54, "Montreal (RSMC)"); + ///Montreal (RSMC) (54) + public static Center MontrealReserved { get; } = new Center(54, "Montreal (RSMC)"); - ///San Francisco (55) - public static Center SanFrancisco { get; } = new Center(55, "San Francisco"); + ///San Francisco (55) + public static Center SanFrancisco { get; } = new Center(55, "San Francisco"); - ///ARINC Center (56) - public static Center ArincCenter { get; } = new Center(56, "ARINC Center"); + ///ARINC Center (56) + public static Center ArincCenter { get; } = new Center(56, "ARINC Center"); - ///U.S. Air Force - Air Force Global Weather Central (57) - public static Center UsAfGwc { get; } = new Center(57, "U.S. Air Force - Air Force Global Weather Central"); + ///U.S. Air Force - Air Force Global Weather Central (57) + public static Center UsAfGwc { get; } = new Center(57, "U.S. Air Force - Air Force Global Weather Central"); - ///Fleet Numerical Meteorology and Oceanography Center, Monterey, CA, USA (58) - public static Center CaFnmoc { get; } = - new Center(58, "Fleet Numerical Meteorology and Oceanography Center, Monterey, CA, USA"); + ///Fleet Numerical Meteorology and Oceanography Center, Monterey, CA, USA (58) + public static Center CaFnmoc { get; } = + new Center(58, "Fleet Numerical Meteorology and Oceanography Center, Monterey, CA, USA"); - ///The NOAA Forecast Systems Laboratory, Boulder, CO, USA (59) - public static Center UsNoaaForecastSystemsLaboratory { get; } = - new Center(59, "The NOAA Forecast Systems Laboratory, Boulder, CO, USA"); + ///The NOAA Forecast Systems Laboratory, Boulder, CO, USA (59) + public static Center UsNoaaForecastSystemsLaboratory { get; } = + new Center(59, "The NOAA Forecast Systems Laboratory, Boulder, CO, USA"); - ///United States National Center for Atmospheric Research (NCAR) (60) - public static Center UsNcar { get; } = - new Center(60, "United States National Center for Atmospheric Research (NCAR)"); + ///United States National Center for Atmospheric Research (NCAR) (60) + public static Center UsNcar { get; } = + new Center(60, "United States National Center for Atmospheric Research (NCAR)"); - ///Service ARGOS - Landover (61) - public static Center ArgosLandover { get; } = new Center(61, "Service ARGOS - Landover"); + ///Service ARGOS - Landover (61) + public static Center ArgosLandover { get; } = new Center(61, "Service ARGOS - Landover"); - ///U.S. Naval Oceanographic Office (62) - public static Center UsNoo { get; } = new Center(62, "U.S. Naval Oceanographic Office"); + ///U.S. Naval Oceanographic Office (62) + public static Center UsNoo { get; } = new Center(62, "U.S. Naval Oceanographic Office"); - ///International Research Institute for Climate and Society (IRI ) (63) - public static Center Iri { get; } = - new Center(63, "International Research Institute for Climate and Society (IRI )"); + ///International Research Institute for Climate and Society (IRI ) (63) + public static Center Iri { get; } = + new Center(63, "International Research Institute for Climate and Society (IRI )"); - ///Honolulu (RSMC) (64) - public static Center Honolulu { get; } = new Center(64, "Honolulu (RSMC)"); + ///Honolulu (RSMC) (64) + public static Center Honolulu { get; } = new Center(64, "Honolulu (RSMC)"); - ///Darwin (RSMC) (65) - public static Center Darwin { get; } = new Center(65, "Darwin (RSMC)"); + ///Darwin (RSMC) (65) + public static Center Darwin { get; } = new Center(65, "Darwin (RSMC)"); - ///Darwin (RSMC) (66) - public static Center DarwinReserved { get; } = new Center(66, "Darwin (RSMC)"); + ///Darwin (RSMC) (66) + public static Center DarwinReserved { get; } = new Center(66, "Darwin (RSMC)"); - ///Melbourne (RSMC) (67) - public static Center Melbourne67 { get; } = new Center(67, "Melbourne (RSMC)"); + ///Melbourne (RSMC) (67) + public static Center Melbourne67 { get; } = new Center(67, "Melbourne (RSMC)"); - ///Wellington (RSMC) (69) - public static Center Wellington { get; } = new Center(69, "Wellington (RSMC)"); + ///Wellington (RSMC) (69) + public static Center Wellington { get; } = new Center(69, "Wellington (RSMC)"); - ///Wellington (RSMC) (70) - public static Center WellingtonReserved { get; } = new Center(70, "Wellington (RSMC)"); + ///Wellington (RSMC) (70) + public static Center WellingtonReserved { get; } = new Center(70, "Wellington (RSMC)"); - ///Nadi (RSMC) (71) - public static Center Nadi { get; } = new Center(71, "Nadi (RSMC)"); + ///Nadi (RSMC) (71) + public static Center Nadi { get; } = new Center(71, "Nadi (RSMC)"); - ///Singapore (72) - public static Center Singapore { get; } = new Center(72, "Singapore"); + ///Singapore (72) + public static Center Singapore { get; } = new Center(72, "Singapore"); - ///Malaysia (NMC) (73) - public static Center Malaysia { get; } = new Center(73, "Malaysia (NMC)"); + ///Malaysia (NMC) (73) + public static Center Malaysia { get; } = new Center(73, "Malaysia (NMC)"); - ///UK Meteorological Office - ­ Exeter (RSMC) (74) - public static Center UkMeteorologicalOffice { get; } = new Center(74, "UK Meteorological Office - ­ Exeter (RSMC)"); + ///UK Meteorological Office - ­ Exeter (RSMC) (74) + public static Center UkMeteorologicalOffice { get; } = new Center(74, "UK Meteorological Office - ­ Exeter (RSMC)"); - ///UK Meteorological Office - ­ Exeter (RSMC) (75) - public static Center UkMeteorologicalOfficeReserved { get; } = - new Center(75, "UK Meteorological Office - ­ Exeter (RSMC)"); + ///UK Meteorological Office - ­ Exeter (RSMC) (75) + public static Center UkMeteorologicalOfficeReserved { get; } = + new Center(75, "UK Meteorological Office - ­ Exeter (RSMC)"); - ///Moscow (RSMC) (76) - public static Center Moscow76 { get; } = new Center(76, "Moscow (RSMC)"); + ///Moscow (RSMC) (76) + public static Center Moscow76 { get; } = new Center(76, "Moscow (RSMC)"); - ///Offenbach (RSMC) (78) - public static Center Offenbach { get; } = new Center(78, "Offenbach (RSMC)"); + ///Offenbach (RSMC) (78) + public static Center Offenbach { get; } = new Center(78, "Offenbach (RSMC)"); - ///Offenbach (RSMC) (79) - public static Center OffenbachReserved { get; } = new Center(79, "Offenbach (RSMC)"); + ///Offenbach (RSMC) (79) + public static Center OffenbachReserved { get; } = new Center(79, "Offenbach (RSMC)"); - ///Rome (RSMC) (80) - public static Center Rome { get; } = new Center(80, "Rome (RSMC)"); + ///Rome (RSMC) (80) + public static Center Rome { get; } = new Center(80, "Rome (RSMC)"); - ///Rome (RSMC) (81) - public static Center RomeReserved { get; } = new Center(81, "Rome (RSMC)"); + ///Rome (RSMC) (81) + public static Center RomeReserved { get; } = new Center(81, "Rome (RSMC)"); - ///Norrköping (82) - public static Center Norrkoping { get; } = new Center(82, "Norrköping"); + ///Norrköping (82) + public static Center Norrkoping { get; } = new Center(82, "Norrköping"); - ///Norrköping (83) - public static Center NorrkopingReserved { get; } = new Center(83, "Norrköping"); + ///Norrköping (83) + public static Center NorrkopingReserved { get; } = new Center(83, "Norrköping"); - ///Toulouse (RSMC) (84) - public static Center Toulouse { get; } = new Center(84, "Toulouse (RSMC)"); + ///Toulouse (RSMC) (84) + public static Center Toulouse { get; } = new Center(84, "Toulouse (RSMC)"); - ///Toulouse (RSMC) (85) - public static Center Toulouse85 { get; } = new Center(85, "Toulouse (RSMC)"); + ///Toulouse (RSMC) (85) + public static Center Toulouse85 { get; } = new Center(85, "Toulouse (RSMC)"); - ///Helsinki (86) - public static Center Helsinki { get; } = new Center(86, "Helsinki"); + ///Helsinki (86) + public static Center Helsinki { get; } = new Center(86, "Helsinki"); - ///Belgrade (87) - public static Center Belgrade { get; } = new Center(87, "Belgrade"); + ///Belgrade (87) + public static Center Belgrade { get; } = new Center(87, "Belgrade"); - ///Oslo (88) - public static Center Oslo { get; } = new Center(88, "Oslo"); + ///Oslo (88) + public static Center Oslo { get; } = new Center(88, "Oslo"); - ///Prague (89) - public static Center Prague { get; } = new Center(89, "Prague"); + ///Prague (89) + public static Center Prague { get; } = new Center(89, "Prague"); - ///Episkopi (90) - public static Center Episkopi { get; } = new Center(90, "Episkopi"); + ///Episkopi (90) + public static Center Episkopi { get; } = new Center(90, "Episkopi"); - ///Ankara (91) - public static Center Ankara { get; } = new Center(91, "Ankara"); + ///Ankara (91) + public static Center Ankara { get; } = new Center(91, "Ankara"); - ///Frankfurt/Main (92) - public static Center FrankfurtMain { get; } = new Center(92, "Frankfurt/Main"); + ///Frankfurt/Main (92) + public static Center FrankfurtMain { get; } = new Center(92, "Frankfurt/Main"); - ///London (WAFC) (93) - public static Center London { get; } = new Center(93, "London (WAFC)"); + ///London (WAFC) (93) + public static Center London { get; } = new Center(93, "London (WAFC)"); - ///Copenhagen (94) - public static Center Copenhagen { get; } = new Center(94, "Copenhagen"); + ///Copenhagen (94) + public static Center Copenhagen { get; } = new Center(94, "Copenhagen"); - ///Rota (95) - public static Center Rota { get; } = new Center(95, "Rota"); + ///Rota (95) + public static Center Rota { get; } = new Center(95, "Rota"); - ///Athens (96) - public static Center Athens { get; } = new Center(96, "Athens"); + ///Athens (96) + public static Center Athens { get; } = new Center(96, "Athens"); - ///European Space Agency (ESA) (97) - public static Center Esa { get; } = new Center(97, "European Space Agency (ESA)"); + ///European Space Agency (ESA) (97) + public static Center Esa { get; } = new Center(97, "European Space Agency (ESA)"); - ///European Center for Medium Range Weather Forecasts (ECMWF) (RSMC) (98) - public static Center Ecmwf { get; } = - new Center(98, "European Center for Medium Range Weather Forecasts (ECMWF) (RSMC)"); + ///European Center for Medium Range Weather Forecasts (ECMWF) (RSMC) (98) + public static Center Ecmwf { get; } = + new Center(98, "European Center for Medium Range Weather Forecasts (ECMWF) (RSMC)"); - ///De Bilt (99) - public static Center DeBilt { get; } = new Center(99, "De Bilt"); + ///De Bilt (99) + public static Center DeBilt { get; } = new Center(99, "De Bilt"); - ///Brazzaville (100) - public static Center Brazzaville { get; } = new Center(100, "Brazzaville"); + ///Brazzaville (100) + public static Center Brazzaville { get; } = new Center(100, "Brazzaville"); - ///Abidjan (101) - public static Center Abidjan { get; } = new Center(101, "Abidjan"); + ///Abidjan (101) + public static Center Abidjan { get; } = new Center(101, "Abidjan"); - ///Libya (NMC) (102) - public static Center Libya { get; } = new Center(102, "Libya (NMC)"); + ///Libya (NMC) (102) + public static Center Libya { get; } = new Center(102, "Libya (NMC)"); - ///Madagascar (NMC) (103) - public static Center Madagascar { get; } = new Center(103, "Madagascar (NMC)"); + ///Madagascar (NMC) (103) + public static Center Madagascar { get; } = new Center(103, "Madagascar (NMC)"); - ///Mauritius (NMC) (104) - public static Center Mauritius { get; } = new Center(104, "Mauritius (NMC)"); + ///Mauritius (NMC) (104) + public static Center Mauritius { get; } = new Center(104, "Mauritius (NMC)"); - ///Niger (NMC) (105) - public static Center Niger { get; } = new Center(105, "Niger (NMC)"); + ///Niger (NMC) (105) + public static Center Niger { get; } = new Center(105, "Niger (NMC)"); - ///Seychelles (NMC) (106) - public static Center Seychelles { get; } = new Center(106, "Seychelles (NMC)"); + ///Seychelles (NMC) (106) + public static Center Seychelles { get; } = new Center(106, "Seychelles (NMC)"); - ///Uganda (NMC) (107) - public static Center Uganda { get; } = new Center(107, "Uganda (NMC)"); + ///Uganda (NMC) (107) + public static Center Uganda { get; } = new Center(107, "Uganda (NMC)"); - ///United Republic of Tanzania (NMC) (108) - public static Center Tanzania { get; } = new Center(108, "United Republic of Tanzania (NMC)"); + ///United Republic of Tanzania (NMC) (108) + public static Center Tanzania { get; } = new Center(108, "United Republic of Tanzania (NMC)"); - ///Zimbabwe (NMC) (109) - public static Center Zimbabwe { get; } = new Center(109, "Zimbabwe (NMC)"); + ///Zimbabwe (NMC) (109) + public static Center Zimbabwe { get; } = new Center(109, "Zimbabwe (NMC)"); - ///Hong-Kong, China (110) - public static Center HongKong { get; } = new Center(110, "Hong-Kong, China"); + ///Hong-Kong, China (110) + public static Center HongKong { get; } = new Center(110, "Hong-Kong, China"); - ///Afghanistan (NMC) (111) - public static Center Afghanistan { get; } = new Center(111, "Afghanistan (NMC)"); + ///Afghanistan (NMC) (111) + public static Center Afghanistan { get; } = new Center(111, "Afghanistan (NMC)"); - ///Bahrain (NMC) (112) - public static Center Bahrain { get; } = new Center(112, "Bahrain (NMC)"); + ///Bahrain (NMC) (112) + public static Center Bahrain { get; } = new Center(112, "Bahrain (NMC)"); - ///Bangladesh (NMC) (113) - public static Center Bangladesh { get; } = new Center(113, "Bangladesh (NMC)"); + ///Bangladesh (NMC) (113) + public static Center Bangladesh { get; } = new Center(113, "Bangladesh (NMC)"); - ///Bhutan (NMC) (114) - public static Center Bhutan { get; } = new Center(114, "Bhutan (NMC)"); + ///Bhutan (NMC) (114) + public static Center Bhutan { get; } = new Center(114, "Bhutan (NMC)"); - ///Cambodia (NMC) (115) - public static Center Cambodia { get; } = new Center(115, "Cambodia (NMC)"); + ///Cambodia (NMC) (115) + public static Center Cambodia { get; } = new Center(115, "Cambodia (NMC)"); - ///Democratic People's Republic of Korea (NMC) (116) - public static Center DprKorea { get; } = new Center(116, "Democratic People's Republic of Korea (NMC)"); + ///Democratic People's Republic of Korea (NMC) (116) + public static Center DprKorea { get; } = new Center(116, "Democratic People's Republic of Korea (NMC)"); - ///Islamic Republic of Iran (NMC) (117) - public static Center Iran { get; } = new Center(117, "Islamic Republic of Iran (NMC)"); + ///Islamic Republic of Iran (NMC) (117) + public static Center Iran { get; } = new Center(117, "Islamic Republic of Iran (NMC)"); - ///Iraq (NMC) (118) - public static Center Iraq { get; } = new Center(118, "Iraq (NMC)"); + ///Iraq (NMC) (118) + public static Center Iraq { get; } = new Center(118, "Iraq (NMC)"); - ///Kazakhstan (NMC) (119) - public static Center Kazakhstan { get; } = new Center(119, "Kazakhstan (NMC)"); + ///Kazakhstan (NMC) (119) + public static Center Kazakhstan { get; } = new Center(119, "Kazakhstan (NMC)"); - ///Kuwait (NMC) (120) - public static Center Kuwait { get; } = new Center(120, "Kuwait (NMC)"); + ///Kuwait (NMC) (120) + public static Center Kuwait { get; } = new Center(120, "Kuwait (NMC)"); - ///Kyrgyzstan (NMC) (121) - public static Center Kyrgyzstan { get; } = new Center(121, "Kyrgyzstan (NMC)"); + ///Kyrgyzstan (NMC) (121) + public static Center Kyrgyzstan { get; } = new Center(121, "Kyrgyzstan (NMC)"); - ///Lao People's Democratic Republic (NMC) (122) - public static Center Laos { get; } = new Center(122, "Lao People's Democratic Republic (NMC)"); + ///Lao People's Democratic Republic (NMC) (122) + public static Center Laos { get; } = new Center(122, "Lao People's Democratic Republic (NMC)"); - ///Macao, China (123) - public static Center Macao { get; } = new Center(123, "Macao, China"); + ///Macao, China (123) + public static Center Macao { get; } = new Center(123, "Macao, China"); - ///Maldives (NMC) (124) - public static Center Maldives { get; } = new Center(124, "Maldives (NMC)"); + ///Maldives (NMC) (124) + public static Center Maldives { get; } = new Center(124, "Maldives (NMC)"); - ///Myanmar (NMC) (125) - public static Center Myanmar { get; } = new Center(125, "Myanmar (NMC)"); + ///Myanmar (NMC) (125) + public static Center Myanmar { get; } = new Center(125, "Myanmar (NMC)"); - ///Nepal (NMC) (126) - public static Center Nepal { get; } = new Center(126, "Nepal (NMC)"); + ///Nepal (NMC) (126) + public static Center Nepal { get; } = new Center(126, "Nepal (NMC)"); - ///Oman (NMC) (127) - public static Center Oman { get; } = new Center(127, "Oman (NMC)"); + ///Oman (NMC) (127) + public static Center Oman { get; } = new Center(127, "Oman (NMC)"); - ///Pakistan (NMC) (128) - public static Center Pakistan { get; } = new Center(128, "Pakistan (NMC)"); + ///Pakistan (NMC) (128) + public static Center Pakistan { get; } = new Center(128, "Pakistan (NMC)"); - ///Qatar (NMC) (129) - public static Center Qatar { get; } = new Center(129, "Qatar (NMC)"); + ///Qatar (NMC) (129) + public static Center Qatar { get; } = new Center(129, "Qatar (NMC)"); - ///Yemen (NMC) (130) - public static Center Yemen { get; } = new Center(130, "Yemen (NMC)"); + ///Yemen (NMC) (130) + public static Center Yemen { get; } = new Center(130, "Yemen (NMC)"); - ///Sri Lanka, (NMC) (131) - public static Center SriLanka { get; } = new Center(131, "Sri Lanka, (NMC)"); + ///Sri Lanka, (NMC) (131) + public static Center SriLanka { get; } = new Center(131, "Sri Lanka, (NMC)"); - ///Tajikistan (NMC) (132) - public static Center Tajikistan { get; } = new Center(132, "Tajikistan (NMC)"); + ///Tajikistan (NMC) (132) + public static Center Tajikistan { get; } = new Center(132, "Tajikistan (NMC)"); - ///Turkmenistan (NMC) (133) - public static Center Turkmenistan { get; } = new Center(133, "Turkmenistan (NMC)"); + ///Turkmenistan (NMC) (133) + public static Center Turkmenistan { get; } = new Center(133, "Turkmenistan (NMC)"); - ///United Arab Emirates (NMC) (134) - public static Center Emirates { get; } = new Center(134, "United Arab Emirates (NMC)"); + ///United Arab Emirates (NMC) (134) + public static Center Emirates { get; } = new Center(134, "United Arab Emirates (NMC)"); - ///Uzbekistan, (NMC) (135) - public static Center Uzbekistan { get; } = new Center(135, "Uzbekistan, (NMC)"); + ///Uzbekistan, (NMC) (135) + public static Center Uzbekistan { get; } = new Center(135, "Uzbekistan, (NMC)"); - ///Viet Nam (NMC) (136) - public static Center Vietnam { get; } = new Center(136, "Viet Nam (NMC)"); + ///Viet Nam (NMC) (136) + public static Center Vietnam { get; } = new Center(136, "Viet Nam (NMC)"); - ///Bolivia (Plurinational State of) (NMC) (140) - public static Center Bolivia { get; } = new Center(140, "Bolivia (Plurinational State of) (NMC)"); + ///Bolivia (Plurinational State of) (NMC) (140) + public static Center Bolivia { get; } = new Center(140, "Bolivia (Plurinational State of) (NMC)"); - ///Guyana (NMC) (141) - public static Center Guyana { get; } = new Center(141, "Guyana (NMC)"); + ///Guyana (NMC) (141) + public static Center Guyana { get; } = new Center(141, "Guyana (NMC)"); - ///Paraguay (NMC) (142) - public static Center Paraguay { get; } = new Center(142, "Paraguay (NMC)"); + ///Paraguay (NMC) (142) + public static Center Paraguay { get; } = new Center(142, "Paraguay (NMC)"); - ///Suriname (NMC) (143) - public static Center Suriname { get; } = new Center(143, "Suriname (NMC)"); + ///Suriname (NMC) (143) + public static Center Suriname { get; } = new Center(143, "Suriname (NMC)"); - ///Uruguay (NMC) (144) - public static Center Uruguay { get; } = new Center(144, "Uruguay (NMC)"); + ///Uruguay (NMC) (144) + public static Center Uruguay { get; } = new Center(144, "Uruguay (NMC)"); - ///French Guyana (145) - public static Center FrenchGuyana { get; } = new Center(145, "French Guyana"); + ///French Guyana (145) + public static Center FrenchGuyana { get; } = new Center(145, "French Guyana"); - ///Brazilian Navy Hydrographic Center (146) - public static Center BrNhc { get; } = new Center(146, "Brazilian Navy Hydrographic Center"); + ///Brazilian Navy Hydrographic Center (146) + public static Center BrNhc { get; } = new Center(146, "Brazilian Navy Hydrographic Center"); - ///National Commission on Space Activities  (CONAE) - Argentina (147) - public static Center ArConaz { get; } = - new Center(147, "National Commission on Space Activities  (CONAE) - Argentina"); + ///National Commission on Space Activities  (CONAE) - Argentina (147) + public static Center ArConaz { get; } = + new Center(147, "National Commission on Space Activities  (CONAE) - Argentina"); - ///Antigua and Barbuda (NMC) (150) - public static Center AntiguaBarbuda { get; } = new Center(150, "Antigua and Barbuda (NMC)"); + ///Antigua and Barbuda (NMC) (150) + public static Center AntiguaBarbuda { get; } = new Center(150, "Antigua and Barbuda (NMC)"); - ///Bahamas (NMC) (151) - public static Center Bahamas { get; } = new Center(151, "Bahamas (NMC)"); + ///Bahamas (NMC) (151) + public static Center Bahamas { get; } = new Center(151, "Bahamas (NMC)"); - ///Barbados (NMC) (152) - public static Center Barbados { get; } = new Center(152, "Barbados (NMC)"); + ///Barbados (NMC) (152) + public static Center Barbados { get; } = new Center(152, "Barbados (NMC)"); - ///Belize (NMC) (153) - public static Center Belize { get; } = new Center(153, "Belize (NMC)"); + ///Belize (NMC) (153) + public static Center Belize { get; } = new Center(153, "Belize (NMC)"); - ///British Caribbean Territories Center (154) - public static Center Caribbean { get; } = new Center(154, "British Caribbean Territories Center"); + ///British Caribbean Territories Center (154) + public static Center Caribbean { get; } = new Center(154, "British Caribbean Territories Center"); - ///San José (155) - public static Center SanJose { get; } = new Center(155, "San José"); + ///San José (155) + public static Center SanJose { get; } = new Center(155, "San José"); - ///Cuba (NMC) (156) - public static Center Cuba { get; } = new Center(156, "Cuba (NMC)"); + ///Cuba (NMC) (156) + public static Center Cuba { get; } = new Center(156, "Cuba (NMC)"); - ///Dominica (NMC) (157) - public static Center Dominica { get; } = new Center(157, "Dominica (NMC)"); + ///Dominica (NMC) (157) + public static Center Dominica { get; } = new Center(157, "Dominica (NMC)"); - ///Dominican Republic (NMC) (158) - public static Center DominicanRepublic { get; } = new Center(158, "Dominican Republic (NMC)"); + ///Dominican Republic (NMC) (158) + public static Center DominicanRepublic { get; } = new Center(158, "Dominican Republic (NMC)"); - ///El Salvador (NMC) (159) - public static Center ElSalvador { get; } = new Center(159, "El Salvador (NMC)"); + ///El Salvador (NMC) (159) + public static Center ElSalvador { get; } = new Center(159, "El Salvador (NMC)"); - ///US NOAA/NESDIS  (160) - public static Center UsNoaaNesdis { get; } = new Center(160, "US NOAA/NESDIS "); + ///US NOAA/NESDIS  (160) + public static Center UsNoaaNesdis { get; } = new Center(160, "US NOAA/NESDIS "); - ///US NOAA Office of Oceanic and Atmospheric Research (161) - public static Center UsNoaaOar { get; } = new Center(161, "US NOAA Office of Oceanic and Atmospheric Research"); + ///US NOAA Office of Oceanic and Atmospheric Research (161) + public static Center UsNoaaOar { get; } = new Center(161, "US NOAA Office of Oceanic and Atmospheric Research"); - ///Guatemala (NMC) (162) - public static Center Guatemala { get; } = new Center(162, "Guatemala (NMC)"); + ///Guatemala (NMC) (162) + public static Center Guatemala { get; } = new Center(162, "Guatemala (NMC)"); - ///Haiti (NMC) (163) - public static Center Haiti { get; } = new Center(163, "Haiti (NMC)"); + ///Haiti (NMC) (163) + public static Center Haiti { get; } = new Center(163, "Haiti (NMC)"); - ///Honduras (NMC) (164) - public static Center Honduras { get; } = new Center(164, "Honduras (NMC)"); + ///Honduras (NMC) (164) + public static Center Honduras { get; } = new Center(164, "Honduras (NMC)"); - ///Jamaica (NMC) (165) - public static Center Jamaica { get; } = new Center(165, "Jamaica (NMC)"); + ///Jamaica (NMC) (165) + public static Center Jamaica { get; } = new Center(165, "Jamaica (NMC)"); - ///Mexico City (166) - public static Center MexicoCity { get; } = new Center(166, "Mexico City"); + ///Mexico City (166) + public static Center MexicoCity { get; } = new Center(166, "Mexico City"); - ///Curaçao and Sint Maarten (NMC) (167) - public static Center CuracaoSintMaarten { get; } = new Center(167, "Curaçao and Sint Maarten (NMC)"); + ///Curaçao and Sint Maarten (NMC) (167) + public static Center CuracaoSintMaarten { get; } = new Center(167, "Curaçao and Sint Maarten (NMC)"); - ///Nicaragua (NMC) (168) - public static Center Nicaragua { get; } = new Center(168, "Nicaragua (NMC)"); + ///Nicaragua (NMC) (168) + public static Center Nicaragua { get; } = new Center(168, "Nicaragua (NMC)"); - ///Panama (NMC) (169) - public static Center Panama { get; } = new Center(169, "Panama (NMC)"); + ///Panama (NMC) (169) + public static Center Panama { get; } = new Center(169, "Panama (NMC)"); - ///Saint Lucia (NMC) (170) - public static Center SaintLucia { get; } = new Center(170, "Saint Lucia (NMC)"); + ///Saint Lucia (NMC) (170) + public static Center SaintLucia { get; } = new Center(170, "Saint Lucia (NMC)"); - ///Trinidad and Tobago (NMC) (171) - public static Center TrinidadTobago { get; } = new Center(171, "Trinidad and Tobago (NMC)"); + ///Trinidad and Tobago (NMC) (171) + public static Center TrinidadTobago { get; } = new Center(171, "Trinidad and Tobago (NMC)"); - ///French Departments in RA IV (172) - public static Center FrenchDepartments { get; } = new Center(172, "French Departments in RA IV"); + ///French Departments in RA IV (172) + public static Center FrenchDepartments { get; } = new Center(172, "French Departments in RA IV"); - ///US National Aeronautics and Space Administration (NASA) (173) - public static Center UsNasa { get; } = new Center(173, "US National Aeronautics and Space Administration (NASA)"); + ///US National Aeronautics and Space Administration (NASA) (173) + public static Center UsNasa { get; } = new Center(173, "US National Aeronautics and Space Administration (NASA)"); - ///Integrated System Data Management/Marine Environmental Data Service (ISDM/MEDS) - Canada (174) - public static Center CaIsdmMeds { get; } = new Center(174, - "Integrated System Data Management/Marine Environmental Data Service (ISDM/MEDS) - Canada"); + ///Integrated System Data Management/Marine Environmental Data Service (ISDM/MEDS) - Canada (174) + public static Center CaIsdmMeds { get; } = new Center(174, + "Integrated System Data Management/Marine Environmental Data Service (ISDM/MEDS) - Canada"); - ///University Corporation for Atmospheric Research (UCAR) - United States (175) - public static Center UsUcar { get; } = - new Center(175, "University Corporation for Atmospheric Research (UCAR) - United States"); + ///University Corporation for Atmospheric Research (UCAR) - United States (175) + public static Center UsUcar { get; } = + new Center(175, "University Corporation for Atmospheric Research (UCAR) - United States"); - ///Cooperative Institute for Meteorological Satellite Studies (CIMSS) - United States (176) - public static Center UsCimss { get; } = new Center(176, - "Cooperative Institute for Meteorological Satellite Studies (CIMSS) - United States"); + ///Cooperative Institute for Meteorological Satellite Studies (CIMSS) - United States (176) + public static Center UsCimss { get; } = new Center(176, + "Cooperative Institute for Meteorological Satellite Studies (CIMSS) - United States"); - ///NOAA National Ocean Service - United States (177) - public static Center UsNoaaNos { get; } = new Center(177, "NOAA National Ocean Service - United States"); + ///NOAA National Ocean Service - United States (177) + public static Center UsNoaaNos { get; } = new Center(177, "NOAA National Ocean Service - United States"); - ///Cook Islands (NMC) (190) - public static Center CookIslands { get; } = new Center(190, "Cook Islands (NMC)"); + ///Cook Islands (NMC) (190) + public static Center CookIslands { get; } = new Center(190, "Cook Islands (NMC)"); - ///French Polynesia (NMC) (191) - public static Center FrenchPolynesia { get; } = new Center(191, "French Polynesia (NMC)"); + ///French Polynesia (NMC) (191) + public static Center FrenchPolynesia { get; } = new Center(191, "French Polynesia (NMC)"); - ///Tonga (NMC) (192) - public static Center Tonga { get; } = new Center(192, "Tonga (NMC)"); + ///Tonga (NMC) (192) + public static Center Tonga { get; } = new Center(192, "Tonga (NMC)"); - ///Vanuatu (NMC) (193) - public static Center Vanuatu { get; } = new Center(193, "Vanuatu (NMC)"); + ///Vanuatu (NMC) (193) + public static Center Vanuatu { get; } = new Center(193, "Vanuatu (NMC)"); - ///Brunei Darussalam (NMC) (194) - public static Center BruneiDarussalam { get; } = new Center(194, "Brunei Darussalam (NMC)"); + ///Brunei Darussalam (NMC) (194) + public static Center BruneiDarussalam { get; } = new Center(194, "Brunei Darussalam (NMC)"); - ///Indonesia (NMC) (195) - public static Center Indonesia { get; } = new Center(195, "Indonesia (NMC)"); + ///Indonesia (NMC) (195) + public static Center Indonesia { get; } = new Center(195, "Indonesia (NMC)"); - ///Kiribati (NMC) (196) - public static Center Kiribati { get; } = new Center(196, "Kiribati (NMC)"); + ///Kiribati (NMC) (196) + public static Center Kiribati { get; } = new Center(196, "Kiribati (NMC)"); - ///Federated States of Micronesia (NMC) (197) - public static Center Micronesia { get; } = new Center(197, "Federated States of Micronesia (NMC)"); + ///Federated States of Micronesia (NMC) (197) + public static Center Micronesia { get; } = new Center(197, "Federated States of Micronesia (NMC)"); - ///New Caledonia (NMC) (198) - public static Center NewCaledonia { get; } = new Center(198, "New Caledonia (NMC)"); + ///New Caledonia (NMC) (198) + public static Center NewCaledonia { get; } = new Center(198, "New Caledonia (NMC)"); - ///Niue (199) - public static Center Niue { get; } = new Center(199, "Niue"); + ///Niue (199) + public static Center Niue { get; } = new Center(199, "Niue"); - ///Papua New Guinea (NMC) (200) - public static Center PapuaNewGuinea { get; } = new Center(200, "Papua New Guinea (NMC)"); + ///Papua New Guinea (NMC) (200) + public static Center PapuaNewGuinea { get; } = new Center(200, "Papua New Guinea (NMC)"); - ///Philippines (NMC) (201) - public static Center Philippines { get; } = new Center(201, "Philippines (NMC)"); + ///Philippines (NMC) (201) + public static Center Philippines { get; } = new Center(201, "Philippines (NMC)"); - ///Samoa (NMC) (202) - public static Center Samoa { get; } = new Center(202, "Samoa (NMC)"); + ///Samoa (NMC) (202) + public static Center Samoa { get; } = new Center(202, "Samoa (NMC)"); - ///Solomon Islands (NMC) (203) - public static Center SolomonIslands { get; } = new Center(203, "Solomon Islands (NMC)"); + ///Solomon Islands (NMC) (203) + public static Center SolomonIslands { get; } = new Center(203, "Solomon Islands (NMC)"); - ///National Institute of Water and Atmospheric Research (NIWA - New Zealand) (204) - public static Center NzNiwa { get; } = - new Center(204, "National Institute of Water and Atmospheric Research (NIWA - New Zealand)"); + ///National Institute of Water and Atmospheric Research (NIWA - New Zealand) (204) + public static Center NzNiwa { get; } = + new Center(204, "National Institute of Water and Atmospheric Research (NIWA - New Zealand)"); - ///Frascati (ESA/ESRIN) (210) - public static Center Frascati { get; } = new Center(210, "Frascati (ESA/ESRIN)"); + ///Frascati (ESA/ESRIN) (210) + public static Center Frascati { get; } = new Center(210, "Frascati (ESA/ESRIN)"); - ///Lanion (211) - public static Center Lanion { get; } = new Center(211, "Lanion"); + ///Lanion (211) + public static Center Lanion { get; } = new Center(211, "Lanion"); - ///Lisboa (212) - public static Center Lisboa { get; } = new Center(212, "Lisboa"); + ///Lisboa (212) + public static Center Lisboa { get; } = new Center(212, "Lisboa"); - ///Reykjavik (213) - public static Center Reykjavik { get; } = new Center(213, "Reykjavik"); + ///Reykjavik (213) + public static Center Reykjavik { get; } = new Center(213, "Reykjavik"); - ///Madrid (214) - public static Center Madrid { get; } = new Center(214, "Madrid"); + ///Madrid (214) + public static Center Madrid { get; } = new Center(214, "Madrid"); - ///Zürich (215) - public static Center Zurich { get; } = new Center(215, "Zürich"); + ///Zürich (215) + public static Center Zurich { get; } = new Center(215, "Zürich"); - ///Service ARGOS - Toulouse (216) - public static Center ToulouseArgos { get; } = new Center(216, "Service ARGOS - Toulouse"); + ///Service ARGOS - Toulouse (216) + public static Center ToulouseArgos { get; } = new Center(216, "Service ARGOS - Toulouse"); - ///Bratislava (217) - public static Center Bratislava { get; } = new Center(217, "Bratislava"); + ///Bratislava (217) + public static Center Bratislava { get; } = new Center(217, "Bratislava"); - ///Budapest (218) - public static Center Budapest { get; } = new Center(218, "Budapest"); + ///Budapest (218) + public static Center Budapest { get; } = new Center(218, "Budapest"); - ///Ljubljana (219) - public static Center Ljubljana { get; } = new Center(219, "Ljubljana"); + ///Ljubljana (219) + public static Center Ljubljana { get; } = new Center(219, "Ljubljana"); - ///Warsaw (220) - public static Center Warsaw { get; } = new Center(220, "Warsaw"); + ///Warsaw (220) + public static Center Warsaw { get; } = new Center(220, "Warsaw"); - ///Zagreb (221) - public static Center Zagreb { get; } = new Center(221, "Zagreb"); + ///Zagreb (221) + public static Center Zagreb { get; } = new Center(221, "Zagreb"); - ///Albania (NMC) (222) - public static Center Albania { get; } = new Center(222, "Albania (NMC)"); + ///Albania (NMC) (222) + public static Center Albania { get; } = new Center(222, "Albania (NMC)"); - ///Armenia (NMC) (223) - public static Center Armenia { get; } = new Center(223, "Armenia (NMC)"); + ///Armenia (NMC) (223) + public static Center Armenia { get; } = new Center(223, "Armenia (NMC)"); - ///Austria (NMC) (224) - public static Center Austria { get; } = new Center(224, "Austria (NMC)"); + ///Austria (NMC) (224) + public static Center Austria { get; } = new Center(224, "Austria (NMC)"); - ///Azerbaijan (NMC) (225) - public static Center Azerbaijan { get; } = new Center(225, "Azerbaijan (NMC)"); + ///Azerbaijan (NMC) (225) + public static Center Azerbaijan { get; } = new Center(225, "Azerbaijan (NMC)"); - ///Belarus (NMC) (226) - public static Center Belarus { get; } = new Center(226, "Belarus (NMC)"); + ///Belarus (NMC) (226) + public static Center Belarus { get; } = new Center(226, "Belarus (NMC)"); - ///Belgium (NMC) (227) - public static Center Belgium { get; } = new Center(227, "Belgium (NMC)"); + ///Belgium (NMC) (227) + public static Center Belgium { get; } = new Center(227, "Belgium (NMC)"); - ///Bosnia and Herzegovina (NMC) (228) - public static Center BosniaHerzegovina { get; } = new Center(228, "Bosnia and Herzegovina (NMC)"); + ///Bosnia and Herzegovina (NMC) (228) + public static Center BosniaHerzegovina { get; } = new Center(228, "Bosnia and Herzegovina (NMC)"); - ///Bulgaria (NMC) (229) - public static Center Bulgaria { get; } = new Center(229, "Bulgaria (NMC)"); + ///Bulgaria (NMC) (229) + public static Center Bulgaria { get; } = new Center(229, "Bulgaria (NMC)"); - ///Cyprus (NMC) (230) - public static Center Cyprus { get; } = new Center(230, "Cyprus (NMC)"); + ///Cyprus (NMC) (230) + public static Center Cyprus { get; } = new Center(230, "Cyprus (NMC)"); - ///Estonia (NMC) (231) - public static Center Estonia { get; } = new Center(231, "Estonia (NMC)"); + ///Estonia (NMC) (231) + public static Center Estonia { get; } = new Center(231, "Estonia (NMC)"); - ///Georgia (NMC) (232) - public static Center Georgia { get; } = new Center(232, "Georgia (NMC)"); + ///Georgia (NMC) (232) + public static Center Georgia { get; } = new Center(232, "Georgia (NMC)"); - ///Dublin (233) - public static Center Dublin { get; } = new Center(233, "Dublin"); + ///Dublin (233) + public static Center Dublin { get; } = new Center(233, "Dublin"); - ///Israel (NMC) (234) - public static Center Israel { get; } = new Center(234, "Israel (NMC)"); + ///Israel (NMC) (234) + public static Center Israel { get; } = new Center(234, "Israel (NMC)"); - ///Jordan (NMC) (235) - public static Center Jordan { get; } = new Center(235, "Jordan (NMC)"); + ///Jordan (NMC) (235) + public static Center Jordan { get; } = new Center(235, "Jordan (NMC)"); - ///Latvia (NMC) (236) - public static Center Latvia { get; } = new Center(236, "Latvia (NMC)"); + ///Latvia (NMC) (236) + public static Center Latvia { get; } = new Center(236, "Latvia (NMC)"); - ///Lebanon (NMC) (237) - public static Center Lebanon { get; } = new Center(237, "Lebanon (NMC)"); - - ///Lithuania (NMC) (238) - public static Center Lithuania { get; } = new Center(238, "Lithuania (NMC)"); - - ///Luxembourg (239) - public static Center Luxembourg { get; } = new Center(239, "Luxembourg"); - - ///Malta (NMC) (240) - public static Center Malta { get; } = new Center(240, "Malta (NMC)"); - - ///Monaco (241) - public static Center Monaco { get; } = new Center(241, "Monaco"); - - ///Romania (NMC) (242) - public static Center Romania { get; } = new Center(242, "Romania (NMC)"); - - ///Syrian Arab Republic (NMC) (243) - public static Center Syria { get; } = new Center(243, "Syrian Arab Republic (NMC)"); - - ///The former Yugoslav Republic of Macedonia (NMC) (244) - public static Center NorthMacedonia { get; } = new Center(244, "The former Yugoslav Republic of Macedonia (NMC)"); - - ///Ukraine (NMC) (245) - public static Center Ukraine { get; } = new Center(245, "Ukraine (NMC)"); - - ///Republic of Moldova (NMC) (246) - public static Center Moldova { get; } = new Center(246, "Republic of Moldova (NMC)"); - - ///Operational Programme for the Exchange of weather RAdar information (OPERA) - EUMETNET (247) - public static Center EumetnetOpera { get; } = new Center(247, - "Operational Programme for the Exchange of weather RAdar information (OPERA) - EUMETNET"); - - ///Montenegro (NMC) (248) - public static Center Montenegro { get; } = new Center(248, "Montenegro (NMC)"); - - ///COnsortium for Small scale MOdelling (COSMO) (250) - public static Center Cosmo { get; } = new Center(250, "COnsortium for Small scale MOdelling (COSMO)"); - - ///Meteorological Cooperation on Operational NWP (MetCoOp) (251) - public static Center MetCoOp { get; } = new Center(251, "Meteorological Cooperation on Operational NWP (MetCoOp)"); - - ///Max Planck Institute for Meteorology (MPI-M) (252) - public static Center MpiM { get; } = new Center(252, "Max Planck Institute for Meteorology (MPI-M)"); - - ///EUMETSAT Operation Center (254) - public static Center Eumetsat { get; } = new Center(254, "EUMETSAT Operation Center"); - - public static IReadOnlyCollection
AllCenters = new List
- { - WmoSecretariat, - Melbourne, - Melbourne2, - Melbourne3, - Moscow, - Moscow5, - Moscow6, - UsNcep, - UsNwstg, - UsNwsOther, - Cairo, - CairoReserved, - Dakar, - DakarReserved, - Nairobi, - NairobiReserved, - Casablanca, - Tunis, - TunisCasablanca, - TunisCasablancaReserved, - LasPalmas, - Algiers, - Acmad, - Mozambique, - Pretoria, - LaReunion, - Khabarovsk, - KhabarovskReserved, - NewDelhi, - NewDelhiReserved, - Novosibirsk, - NovosibirskReserved, - Tashkent, - Jeddah, - Tokyo, - TokyoReserved, - Bangkok, - Ulaanbaatar, - Beijing, - BeijingReserved, - Seoul, - BuenosAires, - BuenosAiresReserved, - Brasilia, - BrasiliaReserved, - Santiago, - BrazilianSpaceAgencyInpe, - Colombia, - Ecuador, - Peru, - Venezuela, - Miami, - MiamiNhc, - Montreal, - MontrealReserved, - SanFrancisco, - ArincCenter, - UsAfGwc, - CaFnmoc, - UsNoaaForecastSystemsLaboratory, - UsNcar, - ArgosLandover, - UsNoo, - Iri, - Honolulu, - Darwin, - DarwinReserved, - Melbourne67, - Wellington, - WellingtonReserved, - Nadi, - Singapore, - Malaysia, - UkMeteorologicalOffice, - UkMeteorologicalOfficeReserved, - Moscow76, - Offenbach, - OffenbachReserved, - Rome, - RomeReserved, - Norrkoping, - NorrkopingReserved, - Toulouse, - Toulouse85, - Helsinki, - Belgrade, - Oslo, - Prague, - Episkopi, - Ankara, - FrankfurtMain, - London, - Copenhagen, - Rota, - Athens, - Esa, - Ecmwf, - DeBilt, - Brazzaville, - Abidjan, - Libya, - Madagascar, - Mauritius, - Niger, - Seychelles, - Uganda, - Tanzania, - Zimbabwe, - HongKong, - Afghanistan, - Bahrain, - Bangladesh, - Bhutan, - Cambodia, - DprKorea, - Iran, - Iraq, - Kazakhstan, - Kuwait, - Kyrgyzstan, - Laos, - Macao, - Maldives, - Myanmar, - Nepal, - Oman, - Pakistan, - Qatar, - Yemen, - SriLanka, - Tajikistan, - Turkmenistan, - Emirates, - Uzbekistan, - Vietnam, - Bolivia, - Guyana, - Paraguay, - Suriname, - Uruguay, - FrenchGuyana, - BrNhc, - ArConaz, - AntiguaBarbuda, - Bahamas, - Barbados, - Belize, - Caribbean, - SanJose, - Cuba, - Dominica, - DominicanRepublic, - ElSalvador, - UsNoaaNesdis, - UsNoaaOar, - Guatemala, - Haiti, - Honduras, - Jamaica, - MexicoCity, - CuracaoSintMaarten, - Nicaragua, - Panama, - SaintLucia, - TrinidadTobago, - FrenchDepartments, - UsNasa, - CaIsdmMeds, - UsUcar, - UsCimss, - UsNoaaNos, - CookIslands, - FrenchPolynesia, - Tonga, - Vanuatu, - BruneiDarussalam, - Indonesia, - Kiribati, - Micronesia, - NewCaledonia, - Niue, - PapuaNewGuinea, - Philippines, - Samoa, - SolomonIslands, - NzNiwa, - Frascati, - Lanion, - Lisboa, - Reykjavik, - Madrid, - Zurich, - ToulouseArgos, - Bratislava, - Budapest, - Ljubljana, - Warsaw, - Zagreb, - Albania, - Armenia, - Austria, - Azerbaijan, - Belarus, - Belgium, - BosniaHerzegovina, - Bulgaria, - Cyprus, - Estonia, - Georgia, - Dublin, - Israel, - Jordan, - Latvia, - Lebanon, - Lithuania, - Luxembourg, - Malta, - Monaco, - Romania, - Syria, - NorthMacedonia, - Ukraine, - Moldova, - EumetnetOpera, - Montenegro, - Cosmo, - MetCoOp, - MpiM, - Eumetsat, - }; - } + ///Lebanon (NMC) (237) + public static Center Lebanon { get; } = new Center(237, "Lebanon (NMC)"); + + ///Lithuania (NMC) (238) + public static Center Lithuania { get; } = new Center(238, "Lithuania (NMC)"); + + ///Luxembourg (239) + public static Center Luxembourg { get; } = new Center(239, "Luxembourg"); + + ///Malta (NMC) (240) + public static Center Malta { get; } = new Center(240, "Malta (NMC)"); + + ///Monaco (241) + public static Center Monaco { get; } = new Center(241, "Monaco"); + + ///Romania (NMC) (242) + public static Center Romania { get; } = new Center(242, "Romania (NMC)"); + + ///Syrian Arab Republic (NMC) (243) + public static Center Syria { get; } = new Center(243, "Syrian Arab Republic (NMC)"); + + ///The former Yugoslav Republic of Macedonia (NMC) (244) + public static Center NorthMacedonia { get; } = new Center(244, "The former Yugoslav Republic of Macedonia (NMC)"); + + ///Ukraine (NMC) (245) + public static Center Ukraine { get; } = new Center(245, "Ukraine (NMC)"); + + ///Republic of Moldova (NMC) (246) + public static Center Moldova { get; } = new Center(246, "Republic of Moldova (NMC)"); + + ///Operational Programme for the Exchange of weather RAdar information (OPERA) - EUMETNET (247) + public static Center EumetnetOpera { get; } = new Center(247, + "Operational Programme for the Exchange of weather RAdar information (OPERA) - EUMETNET"); + + ///Montenegro (NMC) (248) + public static Center Montenegro { get; } = new Center(248, "Montenegro (NMC)"); + + ///COnsortium for Small scale MOdelling (COSMO) (250) + public static Center Cosmo { get; } = new Center(250, "COnsortium for Small scale MOdelling (COSMO)"); + + ///Meteorological Cooperation on Operational NWP (MetCoOp) (251) + public static Center MetCoOp { get; } = new Center(251, "Meteorological Cooperation on Operational NWP (MetCoOp)"); + + ///Max Planck Institute for Meteorology (MPI-M) (252) + public static Center MpiM { get; } = new Center(252, "Max Planck Institute for Meteorology (MPI-M)"); + + ///EUMETSAT Operation Center (254) + public static Center Eumetsat { get; } = new Center(254, "EUMETSAT Operation Center"); + + public static IReadOnlyCollection
AllCenters = new List
+ { + WmoSecretariat, + Melbourne, + Melbourne2, + Melbourne3, + Moscow, + Moscow5, + Moscow6, + UsNcep, + UsNwstg, + UsNwsOther, + Cairo, + CairoReserved, + Dakar, + DakarReserved, + Nairobi, + NairobiReserved, + Casablanca, + Tunis, + TunisCasablanca, + TunisCasablancaReserved, + LasPalmas, + Algiers, + Acmad, + Mozambique, + Pretoria, + LaReunion, + Khabarovsk, + KhabarovskReserved, + NewDelhi, + NewDelhiReserved, + Novosibirsk, + NovosibirskReserved, + Tashkent, + Jeddah, + Tokyo, + TokyoReserved, + Bangkok, + Ulaanbaatar, + Beijing, + BeijingReserved, + Seoul, + BuenosAires, + BuenosAiresReserved, + Brasilia, + BrasiliaReserved, + Santiago, + BrazilianSpaceAgencyInpe, + Colombia, + Ecuador, + Peru, + Venezuela, + Miami, + MiamiNhc, + Montreal, + MontrealReserved, + SanFrancisco, + ArincCenter, + UsAfGwc, + CaFnmoc, + UsNoaaForecastSystemsLaboratory, + UsNcar, + ArgosLandover, + UsNoo, + Iri, + Honolulu, + Darwin, + DarwinReserved, + Melbourne67, + Wellington, + WellingtonReserved, + Nadi, + Singapore, + Malaysia, + UkMeteorologicalOffice, + UkMeteorologicalOfficeReserved, + Moscow76, + Offenbach, + OffenbachReserved, + Rome, + RomeReserved, + Norrkoping, + NorrkopingReserved, + Toulouse, + Toulouse85, + Helsinki, + Belgrade, + Oslo, + Prague, + Episkopi, + Ankara, + FrankfurtMain, + London, + Copenhagen, + Rota, + Athens, + Esa, + Ecmwf, + DeBilt, + Brazzaville, + Abidjan, + Libya, + Madagascar, + Mauritius, + Niger, + Seychelles, + Uganda, + Tanzania, + Zimbabwe, + HongKong, + Afghanistan, + Bahrain, + Bangladesh, + Bhutan, + Cambodia, + DprKorea, + Iran, + Iraq, + Kazakhstan, + Kuwait, + Kyrgyzstan, + Laos, + Macao, + Maldives, + Myanmar, + Nepal, + Oman, + Pakistan, + Qatar, + Yemen, + SriLanka, + Tajikistan, + Turkmenistan, + Emirates, + Uzbekistan, + Vietnam, + Bolivia, + Guyana, + Paraguay, + Suriname, + Uruguay, + FrenchGuyana, + BrNhc, + ArConaz, + AntiguaBarbuda, + Bahamas, + Barbados, + Belize, + Caribbean, + SanJose, + Cuba, + Dominica, + DominicanRepublic, + ElSalvador, + UsNoaaNesdis, + UsNoaaOar, + Guatemala, + Haiti, + Honduras, + Jamaica, + MexicoCity, + CuracaoSintMaarten, + Nicaragua, + Panama, + SaintLucia, + TrinidadTobago, + FrenchDepartments, + UsNasa, + CaIsdmMeds, + UsUcar, + UsCimss, + UsNoaaNos, + CookIslands, + FrenchPolynesia, + Tonga, + Vanuatu, + BruneiDarussalam, + Indonesia, + Kiribati, + Micronesia, + NewCaledonia, + Niue, + PapuaNewGuinea, + Philippines, + Samoa, + SolomonIslands, + NzNiwa, + Frascati, + Lanion, + Lisboa, + Reykjavik, + Madrid, + Zurich, + ToulouseArgos, + Bratislava, + Budapest, + Ljubljana, + Warsaw, + Zagreb, + Albania, + Armenia, + Austria, + Azerbaijan, + Belarus, + Belgium, + BosniaHerzegovina, + Bulgaria, + Cyprus, + Estonia, + Georgia, + Dublin, + Israel, + Jordan, + Latvia, + Lebanon, + Lithuania, + Luxembourg, + Malta, + Monaco, + Romania, + Syria, + NorthMacedonia, + Ukraine, + Moldova, + EumetnetOpera, + Montenegro, + Cosmo, + MetCoOp, + MpiM, + Eumetsat, + }; } \ No newline at end of file diff --git a/src/NGrib/Grib2/Dataset.cs b/src/NGrib/Grib2/Dataset.cs index c5abe88..7e82e6c 100644 --- a/src/NGrib/Grib2/Dataset.cs +++ b/src/NGrib/Grib2/Dataset.cs @@ -24,102 +24,98 @@ * along with NGrib. If not, see . */ -using System; -using System.Collections.Generic; -using System.Linq; using NGrib.Grib2.CodeTables; using NGrib.Grib2.Sections; -namespace NGrib.Grib2 +namespace NGrib.Grib2; + +/// +/// Represents a data set in a GRIB2 message. +/// +public sealed class DataSet { - /// - /// Represents a data set in a GRIB2 message. - /// - public sealed class DataSet - { - /// - /// Message in which the data set is provided. - /// - public Message Message { get; } - - /// - /// Local Use Section. - /// - /// null if not used. - public LocalUseSection LocalUseSection { get; } - - /// - /// Grid Definition Section. - /// - public GridDefinitionSection GridDefinitionSection { get; } - - /// - /// Product Definition Section. - /// - public ProductDefinitionSection ProductDefinitionSection { get; } - - /// - /// Bitmap Section. - /// - public BitmapSection BitmapSection { get; } - - /// - /// Data Representation Section. - /// - public DataRepresentationSection DataRepresentationSection { get; } - - /// - /// Data Section. - /// - public DataSection DataSection { get; } - - /// - /// Parameter defined in the Product Definition Section. - /// - public Parameter? Parameter => ProductDefinitionSection.ProductDefinition?.Parameter; - - internal DataSet( - Message message, - LocalUseSection localUseSection, - GridDefinitionSection gridDefinitionSection, - ProductDefinitionSection productDefinitionSection, - DataRepresentationSection dataRepresentationSection, - BitmapSection bitmapSection, - DataSection dataSection) - { - Message = message; - GridDefinitionSection = gridDefinitionSection; - ProductDefinitionSection = productDefinitionSection; - DataRepresentationSection = dataRepresentationSection; - BitmapSection = bitmapSection; - DataSection = dataSection; - LocalUseSection = localUseSection; - } - - internal IEnumerable> GetData(BufferedBinaryReader reader) - { - return GridDefinitionSection.GridDefinition.EnumerateGridPoints() - .Zip(GetRawData(reader), (p, v) => new KeyValuePair(p, v)); - } - - internal IEnumerable GetRawData(BufferedBinaryReader reader) - { - if (DataRepresentationSection.DataRepresentation == null) - { - throw new NotSupportedException($"Data Representation Template {DataRepresentationSection.TemplateNumber} is not supported."); - } - - var bitmap = BitmapSection.GetBitmap(reader); - - using var valuesEnumerator = DataRepresentationSection.DataRepresentation - .EnumerateDataValues(reader, DataSection, DataRepresentationSection.DataPointsNumber) - .GetEnumerator(); - - foreach (var isValueDefined in bitmap) - { - var v = isValueDefined && valuesEnumerator.MoveNext() ? valuesEnumerator.Current : (float?) null; - yield return v; - } - } - } + /// + /// Message in which the data set is provided. + /// + public Message Message { get; } + + /// + /// Local Use Section. + /// + /// null if not used. + public LocalUseSection LocalUseSection { get; } + + /// + /// Grid Definition Section. + /// + public GridDefinitionSection GridDefinitionSection { get; } + + /// + /// Product Definition Section. + /// + public ProductDefinitionSection ProductDefinitionSection { get; } + + /// + /// Bitmap Section. + /// + public BitmapSection BitmapSection { get; } + + /// + /// Data Representation Section. + /// + public DataRepresentationSection DataRepresentationSection { get; } + + /// + /// Data Section. + /// + public DataSection DataSection { get; } + + /// + /// Parameter defined in the Product Definition Section. + /// + public Parameter? Parameter => ProductDefinitionSection.ProductDefinition?.Parameter; + + internal DataSet( + Message message, + LocalUseSection localUseSection, + GridDefinitionSection gridDefinitionSection, + ProductDefinitionSection productDefinitionSection, + DataRepresentationSection dataRepresentationSection, + BitmapSection bitmapSection, + DataSection dataSection) + { + Message = message; + GridDefinitionSection = gridDefinitionSection; + ProductDefinitionSection = productDefinitionSection; + DataRepresentationSection = dataRepresentationSection; + BitmapSection = bitmapSection; + DataSection = dataSection; + LocalUseSection = localUseSection; + } + + internal IEnumerable> GetData(BufferedBinaryReader reader) + { + return GridDefinitionSection.GridDefinition.EnumerateGridPoints() + .Zip(GetRawData(reader), (p, v) => new KeyValuePair(p, v)); + } + + internal IEnumerable GetRawData(BufferedBinaryReader reader) + { + if (DataRepresentationSection.DataRepresentation == null) + { + throw new NotSupportedException($"Data Representation Template {DataRepresentationSection.TemplateNumber} is not supported."); + } + + var bitmap = BitmapSection.GetBitmap(reader); + + using var valuesEnumerator = DataRepresentationSection.DataRepresentation + .EnumerateDataValues(reader, DataSection, DataRepresentationSection.DataPointsNumber) + .GetEnumerator(); + + foreach (var isValueDefined in bitmap) + { + var v = isValueDefined && valuesEnumerator.MoveNext() ? valuesEnumerator.Current : (double?)null; + yield return v; + } + } } \ No newline at end of file diff --git a/src/NGrib/Grib2/Grib2File.cs b/src/NGrib/Grib2/Grib2File.cs new file mode 100644 index 0000000..3639184 --- /dev/null +++ b/src/NGrib/Grib2/Grib2File.cs @@ -0,0 +1,59 @@ +using NGrib.Grib2.Sections; + +namespace NGrib.Grib2; + +public class Grib2File +{ + public Message ReadGrib2Message(BufferedBinaryReader reader, out long currentPosition) + { + var indicatorSection = IndicatorSection.BuildFrom(reader); + var identificationSection = IdentificationSection.BuildFrom(reader); + + var message = new Message(indicatorSection, identificationSection); + + LocalUseSection localUseSection = null; + do + { + if (reader.PeekSection().Is(SectionCode.LocalUseSection)) + { + localUseSection = LocalUseSection.BuildFrom(reader); + } + + while (reader.PeekSection().Is(SectionCode.GridDefinitionSection)) + { + var gridDefinitionSection = GridDefinitionSection.BuildFrom(reader); + + while (reader.PeekSection().Is(SectionCode.ProductDefinitionSection)) + { + var productDefinitionSection = ProductDefinitionSection.BuildFrom(reader, indicatorSection.Discipline); + var dataRepresentationSection = DataRepresentationSection.BuildFrom(reader); + + var bitmapSection = BitmapSection.BuildFrom(reader, dataRepresentationSection.DataPointsNumber); + + var dataSection = DataSection.BuildFrom(reader); + + message.AddDataset( + localUseSection, + gridDefinitionSection, + productDefinitionSection, + dataRepresentationSection, + bitmapSection, + dataSection); + } + } + } while (!reader.PeekSection().Is(SectionCode.EndSection)); + + EndSection.BuildFrom(reader); + + // Saves and restore the current position + // to avoid losing track of the current message + // if a data set read happens during the enumeration + currentPosition = reader.Position; + return message; + } + + public IEnumerable>> GetData(BufferedBinaryReader reader, Message message) + { + return message.DataSets.Select(x => x.GetData(reader)); + } +} \ No newline at end of file diff --git a/src/NGrib/Grib2/Message.cs b/src/NGrib/Grib2/Message.cs index 09b2b1d..46b31cc 100644 --- a/src/NGrib/Grib2/Message.cs +++ b/src/NGrib/Grib2/Message.cs @@ -24,59 +24,56 @@ * along with NGrib. If not, see . */ -using System; -using System.Collections.Generic; using NGrib.Grib2.Sections; -namespace NGrib.Grib2 +namespace NGrib.Grib2; + +/// +/// Represents a GRIB2 message. +/// +public sealed class Message { - /// - /// Represents a GRIB2 message. - /// - public sealed class Message - { - /// - /// Indicator Section. - /// - public IndicatorSection IndicatorSection { get; } + /// + /// Indicator Section. + /// + public IndicatorSection IndicatorSection { get; } - /// - /// Identification Section. - /// - public IdentificationSection IdentificationSection { get; } + /// + /// Identification Section. + /// + public IdentificationSection IdentificationSection { get; } - /// - /// Data sets in the message. - /// - public IReadOnlyCollection DataSets => dataSets; + /// + /// Data sets in the message. + /// + public IReadOnlyCollection DataSets => dataSets; - private readonly List dataSets; + private readonly List dataSets; - internal Message(IndicatorSection indicatorSection, IdentificationSection identificationSection) - { - IndicatorSection = indicatorSection ?? throw new ArgumentNullException(nameof(indicatorSection)); - IdentificationSection = identificationSection ?? throw new ArgumentNullException(nameof(identificationSection)); - dataSets = new List(); - } + internal Message(IndicatorSection indicatorSection, IdentificationSection identificationSection) + { + IndicatorSection = indicatorSection ?? throw new ArgumentNullException(nameof(indicatorSection)); + IdentificationSection = identificationSection ?? throw new ArgumentNullException(nameof(identificationSection)); + dataSets = new List(); + } - internal void AddDataset( - LocalUseSection lus, - GridDefinitionSection gds, - ProductDefinitionSection pds, - DataRepresentationSection drs, - BitmapSection bs, - DataSection ds) - { - var record = new DataSet( - this, - lus, - gds, - pds, - drs, - bs, - ds); + internal void AddDataset( + LocalUseSection lus, + GridDefinitionSection gds, + ProductDefinitionSection pds, + DataRepresentationSection drs, + BitmapSection bs, + DataSection ds) + { + var record = new DataSet( + this, + lus, + gds, + pds, + drs, + bs, + ds); - dataSets.Add(record); - } - } + dataSets.Add(record); + } } \ No newline at end of file diff --git a/src/NGrib/Grib2/Sections/0_IndicatorSection.cs b/src/NGrib/Grib2/Sections/0_IndicatorSection.cs index 21641b8..ff5df8c 100644 --- a/src/NGrib/Grib2/Sections/0_IndicatorSection.cs +++ b/src/NGrib/Grib2/Sections/0_IndicatorSection.cs @@ -24,76 +24,73 @@ * along with NGrib. If not, see . */ -using System; -using System.Linq; using System.Numerics; using NGrib.Grib2.CodeTables; -namespace NGrib.Grib2.Sections +namespace NGrib.Grib2.Sections; + +/// +/// Section 0 - Indicator Section +/// +public sealed class IndicatorSection { - /// - /// Section 0 - Indicator Section - /// - public sealed class IndicatorSection - { - private const int INDICATOR_SECTION_LENGTH = 16; + private const int INDICATOR_SECTION_LENGTH = 16; - /// - /// Length of section in octets. - /// - public long Length { get; } + /// + /// Length of section in octets. + /// + public long Length { get; } - /// - /// Number of section. - /// - public int Section { get; } + /// + /// Number of section. + /// + public int Section { get; } - /// - /// Discipline from the GRIB Code Table 0.0. - /// - public Discipline Discipline { get; } + /// + /// Discipline from the GRIB Code Table 0.0. + /// + public Discipline Discipline { get; } - /// - /// GRIB Edition Number. - /// - public int GribEdition { get; } + /// + /// GRIB Edition Number. + /// + public int GribEdition { get; } - /// - /// Total length of GRIB message in octets (including Section 0). - /// - public BigInteger TotalLength { get; } + /// + /// Total length of GRIB message in octets (including Section 0). + /// + public BigInteger TotalLength { get; } - private IndicatorSection(int disciplineCode, int gribEdition, BigInteger totalLength) - { - Length = INDICATOR_SECTION_LENGTH; - Section = (int) SectionCode.IndicatorSection; - Discipline = (Discipline)disciplineCode; + private IndicatorSection(int disciplineCode, int gribEdition, BigInteger totalLength) + { + Length = INDICATOR_SECTION_LENGTH; + Section = (int) SectionCode.IndicatorSection; + Discipline = (Discipline)disciplineCode; - GribEdition = gribEdition; - TotalLength = totalLength; - } + GribEdition = gribEdition; + TotalLength = totalLength; + } - internal static IndicatorSection BuildFrom(BufferedBinaryReader reader) - { - var fileStart = reader.Read(Constants.GribFileStart.Length); - if (!Constants.GribFileStart.SequenceEqual(fileStart)) - { - throw new BadGribFormatException("Invalid file start."); - } + internal static IndicatorSection BuildFrom(BufferedBinaryReader reader) + { + var fileStart = reader.Read(Constants.GribFileStart.Length); + if (!Constants.GribFileStart.SequenceEqual(fileStart)) + { + throw new BadGribFormatException("Invalid file start."); + } - // Ignore the 2 reserved bytes - reader.Skip(2); + // Ignore the 2 reserved bytes + reader.Skip(2); - var disciplineNumber = reader.ReadUInt8(); - var gribEdition = reader.ReadUInt8(); - if (gribEdition != 2) - { - throw new NotSupportedException($"Only GRIB edition 2 is supported. GRIB edition {gribEdition} is not yet supported"); - } + var disciplineNumber = reader.ReadUInt8(); + var gribEdition = reader.ReadUInt8(); + if (gribEdition != 2) + { + throw new NotSupportedException($"Only GRIB edition 2 is supported. GRIB edition {gribEdition} is not yet supported"); + } - var totalLength = reader.ReadUInt64(); + var totalLength = reader.ReadUInt64(); - return new IndicatorSection(disciplineNumber, 2, totalLength); - } - } + return new IndicatorSection(disciplineNumber, 2, totalLength); + } } \ No newline at end of file diff --git a/src/NGrib/Grib2/Sections/1_IdentificationSection.cs b/src/NGrib/Grib2/Sections/1_IdentificationSection.cs index 596c5a7..ea9270b 100644 --- a/src/NGrib/Grib2/Sections/1_IdentificationSection.cs +++ b/src/NGrib/Grib2/Sections/1_IdentificationSection.cs @@ -24,129 +24,127 @@ * along with NGrib. If not, see . */ -using System; using NGrib.Grib2.CodeTables; -namespace NGrib.Grib2.Sections +namespace NGrib.Grib2.Sections; + +/// +/// Section 1 - Identification Section +/// +public sealed record IdentificationSection { - /// - /// Section 1 - Identification Section - /// - public sealed class IdentificationSection - { - /// - /// Length of section in octets. - /// - public long Length { get; } - - /// - /// Number of section. - /// - public int Section { get; } - - /// - /// Identification of originating/generating center. - /// - public int CenterCode { get; } - - /// - /// Originating/generating center. - /// - public Center Center { get; } - - /// - /// Identification of originating/generating sub-centre (allocated by originating/generating Centre) - /// - public int SubCenterCode { get; } - - /// - /// GRIB Master Tables Version Number. - /// - public int MasterTableVersion { get; } - - /// - /// Version number of GRIB Local Tables used to augment Master Tables. - /// - public int LocalTableVersion { get; } - - /// - /// Significance of Reference Time. - /// - public ReferenceTimeSignificance ReferenceTimeSignificance { get; } - - /// - /// Reference time of data. - /// - public DateTime ReferenceTime { get; } - - /// - /// Production status of processed data in this GRIB message. - /// - public ProductStatus ProductStatus { get; } - - /// - /// Type of processed data in this GRIB message. - /// - public ProductType ProductType { get; } - - private IdentificationSection(long length, int section, int centerCode, int subCenterCode, int masterTableVersion, int localTableVersion, int referenceTimeSignificanceCode, DateTime referenceTime, int productStatusCode, int productTypeCode) - { - Length = length; - Section = section; - CenterCode = centerCode; - Center = Center.GetCenterById(CenterCode); - SubCenterCode = subCenterCode; - MasterTableVersion = masterTableVersion; - LocalTableVersion = localTableVersion; - ReferenceTimeSignificance = (ReferenceTimeSignificance)referenceTimeSignificanceCode; - ReferenceTime = referenceTime; - ProductStatus = (ProductStatus)productStatusCode; - ProductType = (ProductType)productTypeCode; - } - - internal static IdentificationSection BuildFrom(BufferedBinaryReader reader) - { - // section 1 octet 1-4 (length of section) - var length = reader.ReadUInt32(); - - var section = reader.ReadUInt8(); - if (section != (int) SectionCode.IdentificationSection) - { - return null; - } - - // Center octet 6-7 - var centerCode = reader.ReadUInt16(); - - // Center octet 8-9 - var subCenterCode = reader.ReadUInt16(); - - // Parameter master table octet 10 - var masterTableVersion = reader.ReadUInt8(); - - // Parameter local table octet 11 - var localTableVersion = reader.ReadUInt8(); - - // significanceOfRT octet 12 - var significanceOfRt = reader.ReadUInt8(); - - // octets 13-19 (base time of forecast) - var refTime = reader.ReadDateTime(); - - var productStatusCode = reader.ReadUInt8(); - - var productTypeCode = reader.ReadUInt8(); - return new IdentificationSection( - length, - section, - centerCode, - subCenterCode, - masterTableVersion, - localTableVersion, - significanceOfRt, - refTime, - productStatusCode, - productTypeCode); - } - } + /// + /// Length of section in octets. + /// + public long Length { get; } + + /// + /// Number of section. + /// + public int Section { get; } + + /// + /// Identification of originating/generating center. + /// + public int CenterCode { get; } + + /// + /// Originating/generating center. + /// + public Center Center { get; } + + /// + /// Identification of originating/generating sub-centre (allocated by originating/generating Centre) + /// + public int SubCenterCode { get; } + + /// + /// GRIB Master Tables Version Number. + /// + public int MasterTableVersion { get; } + + /// + /// Version number of GRIB Local Tables used to augment Master Tables. + /// + public int LocalTableVersion { get; } + + /// + /// Significance of Reference Time. + /// + public ReferenceTimeSignificance ReferenceTimeSignificance { get; } + + /// + /// Reference time of data. + /// + public DateTime ReferenceTime { get; } + + /// + /// Production status of processed data in this GRIB message. + /// + public ProductStatus ProductStatus { get; } + + /// + /// Type of processed data in this GRIB message. + /// + public ProductType ProductType { get; } + + private IdentificationSection(long length, int section, int centerCode, int subCenterCode, int masterTableVersion, int localTableVersion, int referenceTimeSignificanceCode, DateTime referenceTime, int productStatusCode, int productTypeCode) + { + Length = length; + Section = section; + CenterCode = centerCode; + Center = Center.GetCenterById(CenterCode); + SubCenterCode = subCenterCode; + MasterTableVersion = masterTableVersion; + LocalTableVersion = localTableVersion; + ReferenceTimeSignificance = (ReferenceTimeSignificance)referenceTimeSignificanceCode; + ReferenceTime = referenceTime; + ProductStatus = (ProductStatus)productStatusCode; + ProductType = (ProductType)productTypeCode; + } + + internal static IdentificationSection BuildFrom(BufferedBinaryReader reader) + { + // section 1 octet 1-4 (length of section) + var length = reader.ReadUInt32(); + + var section = reader.ReadUInt8(); + if (section != (int) SectionCode.IdentificationSection) + { + return null; + } + + // Center octet 6-7 + var centerCode = reader.ReadUInt16(); + + // Center octet 8-9 + var subCenterCode = reader.ReadUInt16(); + + // Parameter master table octet 10 + var masterTableVersion = reader.ReadUInt8(); + + // Parameter local table octet 11 + var localTableVersion = reader.ReadUInt8(); + + // significanceOfRT octet 12 + var significanceOfRt = reader.ReadUInt8(); + + // octets 13-19 (base time of forecast) + var refTime = reader.ReadDateTime(); + + var productStatusCode = reader.ReadUInt8(); + + var productTypeCode = reader.ReadUInt8(); + return new IdentificationSection( + length, + section, + centerCode, + subCenterCode, + masterTableVersion, + localTableVersion, + significanceOfRt, + refTime, + productStatusCode, + productTypeCode); + } } \ No newline at end of file diff --git a/src/NGrib/Grib2/Sections/2_LocalUseSection.cs b/src/NGrib/Grib2/Sections/2_LocalUseSection.cs index 2d3a115..9fd09e7 100644 --- a/src/NGrib/Grib2/Sections/2_LocalUseSection.cs +++ b/src/NGrib/Grib2/Sections/2_LocalUseSection.cs @@ -24,49 +24,48 @@ * along with NGrib. If not, see . */ -namespace NGrib.Grib2.Sections +namespace NGrib.Grib2.Sections; + +/// +/// Section 2 - Local Use Section +/// +public sealed class LocalUseSection { - /// - /// Section 2 - Local Use Section - /// - public sealed class LocalUseSection - { - /// - /// Length of section in octets. - /// - public long Length { get; } + /// + /// Length of section in octets. + /// + public long Length { get; } - /// - /// Number of section. - /// - public int Section { get; } + /// + /// Number of section. + /// + public int Section { get; } - /// - /// Position at which the local use data begins. - /// - internal long ContentOffset { get; } + /// + /// Position at which the local use data begins. + /// + internal long ContentOffset { get; } - private LocalUseSection(long length, int section, long contentOffset) - { - Length = length; - Section = section; - ContentOffset = contentOffset; - } + private LocalUseSection(long length, int section, long contentOffset) + { + Length = length; + Section = section; + ContentOffset = contentOffset; + } - internal static LocalUseSection BuildFrom(BufferedBinaryReader reader) - { - // octets 1-4 (Length of GDS) - var length = reader.ReadUInt32(); + internal static LocalUseSection BuildFrom(BufferedBinaryReader reader) + { + // octets 1-4 (Length of GDS) + var length = reader.ReadUInt32(); - var section = reader.ReadUInt8(); - if (section != (int) SectionCode.LocalUseSection) - { - return null; - } + var section = reader.ReadUInt8(); + if (section != (int) SectionCode.LocalUseSection) + { + return null; + } - var contentOffset = reader.Position; - reader.Skip((int) length - 5); - return new LocalUseSection(length, section, contentOffset); - } - } + var contentOffset = reader.Position; + reader.Skip((int) length - 5); + return new LocalUseSection(length, section, contentOffset); + } } \ No newline at end of file diff --git a/src/NGrib/Grib2/Sections/3_GridDefinitionSection.cs b/src/NGrib/Grib2/Sections/3_GridDefinitionSection.cs index b9481cf..76d9021 100644 --- a/src/NGrib/Grib2/Sections/3_GridDefinitionSection.cs +++ b/src/NGrib/Grib2/Sections/3_GridDefinitionSection.cs @@ -24,130 +24,128 @@ * along with NGrib. If not, see . */ -using System.IO; using NGrib.Grib2.Templates; using NGrib.Grib2.Templates.GridDefinitions; -namespace NGrib.Grib2.Sections +namespace NGrib.Grib2.Sections; + +/// +/// Section 3 - Grid Definition Section +/// +public sealed class GridDefinitionSection { - /// - /// Section 3 - Grid Definition Section - /// - public sealed class GridDefinitionSection - { - /// - /// Length of section in octets. - /// - public long Length { get; } - - /// - /// Number of section. - /// - public int Section { get; } - - /// - /// Source of grid definition. - /// - public int Source { get; } - - /// - /// Number of data points. - /// - public long DataPointsNumber { get; } - - /// - /// Number of octets for optional list of numbers defining number of points. - /// - public int OptionalListNumberLength { get; } - - /// - /// Interpretation of list of numbers defining number of points. - /// - public int OptionalListInterpretationCode { get; } - - /// - /// Grid Definition Template Number - /// - public int TemplateNumber { get; } - - /// - /// Grid Definition Template - /// - public GridDefinition GridDefinition { get; } - - private GridDefinitionSection( - long length, - int section, - int source, - long dataPointsNumber, - int oLon, - int ioLon, - int templateNumber, - GridDefinition gridDefinition) - { - TemplateNumber = templateNumber; - Length = length; - Section = section; - Source = source; - DataPointsNumber = dataPointsNumber; - OptionalListNumberLength = oLon; - OptionalListInterpretationCode = ioLon; - GridDefinition = gridDefinition; - } - - internal static GridDefinitionSection BuildFrom(BufferedBinaryReader reader) - { - var currentPosition = reader.Position; - var length = reader.ReadUInt32(); - - var section = reader.ReadUInt8(); // This is section 3 - - if (section != (int) SectionCode.GridDefinitionSection) - { - throw new UnexpectedGribSectionException(SectionCode.GridDefinitionSection, section); - } - - var source = reader.ReadUInt8(); - - var numberPoints = reader.ReadUInt32(); - - var olLength = reader.ReadUInt8(); - - var olInterpretation = reader.ReadUInt8(); - - var templateNumber = reader.ReadUInt16(); - - var gridDefinition = GridDefinitionFactories.Build(reader, templateNumber); - - // Prevent from over-reading the stream - reader.Seek(currentPosition + length, SeekOrigin.Begin); - - return new GridDefinitionSection(length, section, source, numberPoints, olLength, olInterpretation, - templateNumber, gridDefinition); - } - - private static readonly TemplateFactory GridDefinitionFactories = - new TemplateFactory - { - {0, r => new LatLonGridDefinition(r)}, - {1, r => new RotatedLatLonGridDefinition(r)}, - {2, r => new StretchedLatLonGridDefinition(r)}, - {3, r => new StretchedRotatedLatLonGridDefinition(r)}, - {10, r => new MercatorGridDefinition(r)}, - {20, r => new PolarStereographicProjectionGridDefinition(r)}, - {30, r => new LambertConformalGridDefinition(r)}, - {31, r => new AlbersEqualAreaGridDefinition(r)}, - {40, r => new GaussianLatLonGridDefinition(r)}, - {41, r => new RotatedGaussianLatLonGridDefinition(r)}, - {42, r => new StretchedGaussianLatLonGridDefinition(r)}, - {43, r => new StretchedRotatedGaussianLatLonGridDefinition(r)}, - {50, r => new SphericalHarmonicCoefficientsGridDefinition(r)}, - {51, r => new RotatedSphericalHarmonicCoefficientsGridDefinition(r)}, - {52, r => new StretchedSphericalHarmonicCoefficientsGridDefinition(r)}, - {53, r => new StretchedRotatedSphericalHarmonicCoefficientsGridDefinition(r)}, - {90, r => new SpaceViewPerspectiveOrOrthographicGridDefinition(r)}, - {100, r => new TriangularGridBasedOnAnIcosahedronGridDefinition(r)}, - {110, r => new EquatorialAzimuthalEquidistantProjectionGridDefinition(r)} - }; - } + /// + /// Length of section in octets. + /// + public long Length { get; } + + /// + /// Number of section. + /// + public int Section { get; } + + /// + /// Source of grid definition. + /// + public int Source { get; } + + /// + /// Number of data points. + /// + public long DataPointsNumber { get; } + + /// + /// Number of octets for optional list of numbers defining number of points. + /// + public int OptionalListNumberLength { get; } + + /// + /// Interpretation of list of numbers defining number of points. + /// + public int OptionalListInterpretationCode { get; } + + /// + /// Grid Definition Template Number + /// + public int TemplateNumber { get; } + + /// + /// Grid Definition Template + /// + public GridDefinition GridDefinition { get; } + + private GridDefinitionSection( + long length, + int section, + int source, + long dataPointsNumber, + int oLon, + int ioLon, + int templateNumber, + GridDefinition gridDefinition) + { + TemplateNumber = templateNumber; + Length = length; + Section = section; + Source = source; + DataPointsNumber = dataPointsNumber; + OptionalListNumberLength = oLon; + OptionalListInterpretationCode = ioLon; + GridDefinition = gridDefinition; + } + + internal static GridDefinitionSection BuildFrom(BufferedBinaryReader reader) + { + var currentPosition = reader.Position; + var length = reader.ReadUInt32(); + + var section = reader.ReadUInt8(); // This is section 3 + + if (section != (int) SectionCode.GridDefinitionSection) + { + throw new UnexpectedGribSectionException(SectionCode.GridDefinitionSection, section); + } + + var source = reader.ReadUInt8(); + + var numberPoints = reader.ReadUInt32(); + + var olLength = reader.ReadUInt8(); + + var olInterpretation = reader.ReadUInt8(); + + var templateNumber = reader.ReadUInt16(); + + var gridDefinition = GridDefinitionFactories.Build(reader, templateNumber); + + // Prevent from over-reading the stream + reader.Seek(currentPosition + length, SeekOrigin.Begin); + + return new GridDefinitionSection(length, section, source, numberPoints, olLength, olInterpretation, + templateNumber, gridDefinition); + } + + private static readonly TemplateFactory GridDefinitionFactories = + new TemplateFactory + { + {0, r => new LatLonGridDefinition(r)}, + {1, r => new RotatedLatLonGridDefinition(r)}, + {2, r => new StretchedLatLonGridDefinition(r)}, + {3, r => new StretchedRotatedLatLonGridDefinition(r)}, + {10, r => new MercatorGridDefinition(r)}, + {20, r => new PolarStereographicProjectionGridDefinition(r)}, + {30, r => new LambertConformalGridDefinition(r)}, + {31, r => new AlbersEqualAreaGridDefinition(r)}, + {40, r => new GaussianLatLonGridDefinition(r)}, + {41, r => new RotatedGaussianLatLonGridDefinition(r)}, + {42, r => new StretchedGaussianLatLonGridDefinition(r)}, + {43, r => new StretchedRotatedGaussianLatLonGridDefinition(r)}, + {50, r => new SphericalHarmonicCoefficientsGridDefinition(r)}, + {51, r => new RotatedSphericalHarmonicCoefficientsGridDefinition(r)}, + {52, r => new StretchedSphericalHarmonicCoefficientsGridDefinition(r)}, + {53, r => new StretchedRotatedSphericalHarmonicCoefficientsGridDefinition(r)}, + {90, r => new SpaceViewPerspectiveOrOrthographicGridDefinition(r)}, + {100, r => new TriangularGridBasedOnAnIcosahedronGridDefinition(r)}, + {110, r => new EquatorialAzimuthalEquidistantProjectionGridDefinition(r)} + }; } \ No newline at end of file diff --git a/src/NGrib/Grib2/Sections/4_ProductDefinitionSection.cs b/src/NGrib/Grib2/Sections/4_ProductDefinitionSection.cs index 8d4a441..7d6cf9b 100644 --- a/src/NGrib/Grib2/Sections/4_ProductDefinitionSection.cs +++ b/src/NGrib/Grib2/Sections/4_ProductDefinitionSection.cs @@ -27,91 +27,89 @@ using NGrib.Grib2.CodeTables; using NGrib.Grib2.Templates; using NGrib.Grib2.Templates.ProductDefinitions; -using System.IO; -using System.Runtime.InteropServices; -namespace NGrib.Grib2.Sections +namespace NGrib.Grib2.Sections; + +/// +/// Section 4 - Product Definition Section +/// +public sealed class ProductDefinitionSection { - /// - /// Section 4 - Product Definition Section - /// - public sealed class ProductDefinitionSection - { - /// - /// Length of section in octets. - /// - public long Length { get; } - - /// - /// Number of section. - /// - public int Section { get; } - - /// - /// Number of coordinates values after Template. - /// - public int CoordinatesAfterTemplateNumber { get; } - - /// - /// Product Definition Template Number - /// - public int ProductDefinitionTemplateNumber { get; } - - /// - /// Product Definition Template. - /// - public ProductDefinition ProductDefinition { get; } - - private ProductDefinitionSection( - long length, - int section, - int coordinatesAfterTemplateNumber, - int productDefinitionTemplateNumber, - ProductDefinition productDefinition) - { - CoordinatesAfterTemplateNumber = coordinatesAfterTemplateNumber; - ProductDefinitionTemplateNumber = productDefinitionTemplateNumber; - ProductDefinition = productDefinition; - Length = length; - Section = section; - } - - internal static ProductDefinitionSection BuildFrom(BufferedBinaryReader reader, Discipline discipline) - { - var currentPosition = reader.Position; - - // octets 1-4 (Length of PDS) - var length = reader.ReadUInt32(); - - // octet 5 - var section = reader.ReadUInt8(); - - // octet 6-7 - var coordinates = reader.ReadUInt16(); - - // octet 8-9 - var productDefinitionTemplateNumber = reader.ReadUInt16(); - - var productDefinition = ProductDefinitionFactories.Build(reader, productDefinitionTemplateNumber, discipline); - - // Prevent from over-reading the stream - reader.Seek(currentPosition + length, SeekOrigin.Begin); - - return new ProductDefinitionSection(length, section, coordinates, productDefinitionTemplateNumber, - productDefinition); - } - - public bool TryGet(TemplateContent content, out T value) => ProductDefinition.TryGet(content, out value); - - private static readonly TemplateFactory ProductDefinitionFactories = - new TemplateFactory - { - { 0, (r, args) => new ProductDefinition0000(r, (Discipline) args[0]) }, - { 1, (r, args) => new ProductDefinition0001(r, (Discipline) args[0]) }, - { 2, (r, args) => new ProductDefinition0002(r, (Discipline) args[0]) }, - { 8, (r, args) => new ProductDefinition0008(r, (Discipline) args[0]) }, - { 11, (r, args) => new ProductDefinition0011(r, (Discipline) args[0]) }, - { 12, (r, args) => new ProductDefinition0012(r, (Discipline) args[0]) } - }; - } + /// + /// Length of section in octets. + /// + public long Length { get; } + + /// + /// Number of section. + /// + public int Section { get; } + + /// + /// Number of coordinates values after Template. + /// + public int CoordinatesAfterTemplateNumber { get; } + + /// + /// Product Definition Template Number + /// + public int ProductDefinitionTemplateNumber { get; } + + /// + /// Product Definition Template. + /// + public ProductDefinition ProductDefinition { get; } + + private ProductDefinitionSection( + long length, + int section, + int coordinatesAfterTemplateNumber, + int productDefinitionTemplateNumber, + ProductDefinition productDefinition) + { + CoordinatesAfterTemplateNumber = coordinatesAfterTemplateNumber; + ProductDefinitionTemplateNumber = productDefinitionTemplateNumber; + ProductDefinition = productDefinition; + Length = length; + Section = section; + } + + internal static ProductDefinitionSection BuildFrom(BufferedBinaryReader reader, Discipline discipline) + { + var currentPosition = reader.Position; + + // octets 1-4 (Length of PDS) + var length = reader.ReadUInt32(); + + // octet 5 + var section = reader.ReadUInt8(); + + // octet 6-7 + var coordinates = reader.ReadUInt16(); + + // octet 8-9 + var productDefinitionTemplateNumber = reader.ReadUInt16(); + + var productDefinition = ProductDefinitionFactories.Build(reader, productDefinitionTemplateNumber, discipline); + + // Prevent from over-reading the stream + reader.Seek(currentPosition + length, SeekOrigin.Begin); + + return new ProductDefinitionSection(length, section, coordinates, productDefinitionTemplateNumber, + productDefinition); + } + + public bool TryGet(TemplateContent content, out T value) => ProductDefinition.TryGet(content, out value); + + private static readonly TemplateFactory ProductDefinitionFactories = + new TemplateFactory + { + {0, (r, args) => new ProductDefinition0000(r, (Discipline) args[0])}, + {1, (r, args) => new ProductDefinition0001(r, (Discipline) args[0])}, + {2, (r, args) => new ProductDefinition0002(r, (Discipline) args[0])}, + {8, (r, args) => new ProductDefinition0008(r, (Discipline) args[0])}, + {11, (r, args) => new ProductDefinition0011(r, (Discipline) args[0])}, + {12, (r, args) => new ProductDefinition0012(r, (Discipline) args[0])}, + {40, (r, args) => new ProductDefinition0040(r, (Discipline) args[0])} + }; } \ No newline at end of file diff --git a/src/NGrib/Grib2/Sections/5_DataRepresentationSection.cs b/src/NGrib/Grib2/Sections/5_DataRepresentationSection.cs index ff61113..3bb18dc 100644 --- a/src/NGrib/Grib2/Sections/5_DataRepresentationSection.cs +++ b/src/NGrib/Grib2/Sections/5_DataRepresentationSection.cs @@ -26,92 +26,90 @@ using NGrib.Grib2.Templates; using NGrib.Grib2.Templates.DataRepresentations; -using System.IO; -namespace NGrib.Grib2.Sections +namespace NGrib.Grib2.Sections; + +/// +/// Section 5 - Data Representation Section +/// +public sealed class DataRepresentationSection { - /// - /// Section 5 - Data Representation Section - /// - public sealed class DataRepresentationSection - { - /// - /// Length of section in octets. - /// - public long Length { get; } - - /// - /// Number of section. - /// - public int Section { get; } - - /// - /// Number of data points where one or more values are specified in Section 7 - /// when a bit map is present, total number of data points when a bit map is absent. - /// - public long DataPointsNumber { get; } - - /// - /// Data Representation Template Number. - /// - public int TemplateNumber { get; } - - /// - /// Data Representation Template. - /// - public DataRepresentation DataRepresentation { get; } - - private DataRepresentationSection( - long length, - int section, - long dataPointsNumber, - int templateNumber, - DataRepresentation dataRepresentation) - { - Section = section; - Length = length; - DataPointsNumber = dataPointsNumber; - TemplateNumber = templateNumber; - DataRepresentation = dataRepresentation; - } - - internal static DataRepresentationSection BuildFrom(BufferedBinaryReader reader) - { - var sectionStartPosition = reader.Position; - - // octets 1-4 (Length of DRS) - var length = reader.ReadUInt32(); - - var section = reader.ReadUInt8(); - if (section != (int) SectionCode.DataRepresentationSection) - { - throw new UnexpectedGribSectionException( - SectionCode.DataRepresentationSection, - section - ); - } - - var dataPoints = reader.ReadUInt32(); - - var dataTemplateNumber = reader.ReadUInt16(); - - var dataRepresentation = DataRepresentationFactory.Build(reader, dataTemplateNumber); - - // Prevent from over-reading the stream - reader.Seek(sectionStartPosition + length, SeekOrigin.Begin); - - return new DataRepresentationSection(length, section, dataPoints, dataTemplateNumber, dataRepresentation); - } - - private static readonly TemplateFactory DataRepresentationFactory = - new TemplateFactory - { - { 0, r => new GridPointDataSimplePacking(r) }, - { 2, r => new GridPointDataComplexPacking(r) }, - { 3, r => new GridPointDataComplexPackingAndSpatialDifferencing(r) }, - { 40, r => new GridPointDataJpeg2000CodeStream(r) }, - { 40000, r => new GridPointDataJpeg2000CodeStream(r) }, - { 50002, r => new GridPointDataEcmwfSecondOrderPacking(r) }, - }; - } + /// + /// Length of section in octets. + /// + public long Length { get; } + + /// + /// Number of section. + /// + public int Section { get; } + + /// + /// Number of data points where one or more values are specified in Section 7 + /// when a bit map is present, total number of data points when a bit map is absent. + /// + public long DataPointsNumber { get; } + + /// + /// Data Representation Template Number. + /// + public int TemplateNumber { get; } + + /// + /// Data Representation Template. + /// + public DataRepresentation DataRepresentation { get; } + + private DataRepresentationSection( + long length, + int section, + long dataPointsNumber, + int templateNumber, + DataRepresentation dataRepresentation) + { + Section = section; + Length = length; + DataPointsNumber = dataPointsNumber; + TemplateNumber = templateNumber; + DataRepresentation = dataRepresentation; + } + + internal static DataRepresentationSection BuildFrom(BufferedBinaryReader reader) + { + var sectionStartPosition = reader.Position; + + // octets 1-4 (Length of DRS) + var length = reader.ReadUInt32(); + + var section = reader.ReadUInt8(); + if (section != (int) SectionCode.DataRepresentationSection) + { + throw new UnexpectedGribSectionException( + SectionCode.DataRepresentationSection, + section + ); + } + + var dataPoints = reader.ReadUInt32(); + + var dataTemplateNumber = reader.ReadUInt16(); + + var dataRepresentation = DataRepresentationFactory.Build(reader, dataTemplateNumber); + + // Prevent from over-reading the stream + reader.Seek(sectionStartPosition + length, SeekOrigin.Begin); + + return new DataRepresentationSection(length, section, dataPoints, dataTemplateNumber, dataRepresentation); + } + + private static readonly TemplateFactory DataRepresentationFactory = + new TemplateFactory + { + { 0, r => new GridPointDataSimplePacking(r) }, + { 2, r => new GridPointDataComplexPacking(r) }, + { 3, r => new GridPointDataComplexPackingAndSpatialDifferencing(r) }, + { 40, r => new GridPointDataJpeg2000CodeStream(r) }, + { 40000, r => new GridPointDataJpeg2000CodeStream(r) }, + { 50002, r => new GridPointDataEcmwfSecondOrderPacking(r) }, + }; } \ No newline at end of file diff --git a/src/NGrib/Grib2/Sections/6_BitmapSection.cs b/src/NGrib/Grib2/Sections/6_BitmapSection.cs index 47dc71e..44a8378 100644 --- a/src/NGrib/Grib2/Sections/6_BitmapSection.cs +++ b/src/NGrib/Grib2/Sections/6_BitmapSection.cs @@ -24,145 +24,141 @@ * along with NGrib. If not, see . */ -using System; using System.Collections; -using System.Collections.Generic; -using System.IO; -namespace NGrib.Grib2.Sections +namespace NGrib.Grib2.Sections; + +/// +/// Section 6 - Bitmap Section +/// +public sealed class BitmapSection { - /// - /// Section 6 - Bitmap Section - /// - public sealed class BitmapSection - { - /// - /// Length of section in octets. - /// - public long Length { get; } - - /// - /// Number of section. - /// - public int Section { get; } - - /// - /// Bit-map indicator code. - /// - public int BitMapIndicatorCode { get; } - - /// - /// Position of the bitmap start. - /// - public long BitmapOffset { get; } - - /// - /// Number of data points. - /// - /// - /// As defined in the Grid Definition Section when there is no bitmap. - /// - private readonly long dataPointsNumber; - - private BitmapSection(long length, int section, int bitmapIndicatorCode, long dataPointsNumber, long bitmapOffset) - { - BitmapOffset = bitmapOffset; - Length = length; - Section = section; - BitMapIndicatorCode = bitmapIndicatorCode; - this.dataPointsNumber = bitmapIndicatorCode == 0 ? (length - 6) * 8 : dataPointsNumber; - } - - internal static BitmapSection BuildFrom(BufferedBinaryReader raf, long dataPointsNumber) - { - var length = raf.ReadUInt32(); - - var section = raf.ReadUInt8(); - if (section != (int) SectionCode.BitmapSection) - { - throw new UnexpectedGribSectionException( - SectionCode.BitmapSection, - section - ); - } - - var bitmapIndicator = raf.ReadUInt8(); - var bitmapOffset = raf.Position; - - // Skip through the bitmap data - // There is no need to load it now - raf.Skip((int) length - 6); - - return new BitmapSection(length, section, bitmapIndicator, dataPointsNumber, bitmapOffset); - } - - internal IEnumerable GetBitmap(BufferedBinaryReader reader) - { - if (BitMapIndicatorCode == 0) - { - reader.Seek(BitmapOffset, SeekOrigin.Begin); - - var bitmap = new BitArray((int)dataPointsNumber, true); - - void TrySet(int i, bool value) - { - if (i < bitmap.Length) - { - bitmap[i] = value; - } - } - - // create new bit map, octet 4 contains number of unused bits at the end - var i = 0; - while (i < bitmap.Length) - { - var bitmapByte = (Bitmask)reader.ReadByte(); - - TrySet(i++, bitmapByte.HasFlag(Bitmask.Bit1)); - TrySet(i++, bitmapByte.HasFlag(Bitmask.Bit2)); - TrySet(i++, bitmapByte.HasFlag(Bitmask.Bit3)); - TrySet(i++, bitmapByte.HasFlag(Bitmask.Bit4)); - TrySet(i++, bitmapByte.HasFlag(Bitmask.Bit5)); - TrySet(i++, bitmapByte.HasFlag(Bitmask.Bit6)); - TrySet(i++, bitmapByte.HasFlag(Bitmask.Bit7)); - TrySet(i++, bitmapByte.HasFlag(Bitmask.Bit8)); - } - - IEnumerable EnumerateBitArray() - { - foreach (bool item in bitmap) - { - yield return item; - } - } - - return EnumerateBitArray(); - } - else - { - IEnumerable EnumerateTrue() - { - for (int i = 0; i < dataPointsNumber; i++) - { - yield return true; - } - } - - return EnumerateTrue(); - } - } - - [Flags] - private enum Bitmask : byte - { - Bit1 = 1 << 7, - Bit2 = 1 << 6, - Bit3 = 1 << 5, - Bit4 = 1 << 4, - Bit5 = 1 << 3, - Bit6 = 1 << 2, - Bit7 = 1 << 1, - Bit8 = 1, - } - } + /// + /// Length of section in octets. + /// + public long Length { get; } + + /// + /// Number of section. + /// + public int Section { get; } + + /// + /// Bit-map indicator code. + /// + public int BitMapIndicatorCode { get; } + + /// + /// Position of the bitmap start. + /// + public long BitmapOffset { get; } + + /// + /// Number of data points. + /// + /// + /// As defined in the Grid Definition Section when there is no bitmap. + /// + private readonly long dataPointsNumber; + + private BitmapSection(long length, int section, int bitmapIndicatorCode, long dataPointsNumber, long bitmapOffset) + { + BitmapOffset = bitmapOffset; + Length = length; + Section = section; + BitMapIndicatorCode = bitmapIndicatorCode; + this.dataPointsNumber = bitmapIndicatorCode == 0 ? (length - 6) * 8 : dataPointsNumber; + } + + internal static BitmapSection BuildFrom(BufferedBinaryReader raf, long dataPointsNumber) + { + var length = raf.ReadUInt32(); + + var section = raf.ReadUInt8(); + if (section != (int) SectionCode.BitmapSection) + { + throw new UnexpectedGribSectionException( + SectionCode.BitmapSection, + section + ); + } + + var bitmapIndicator = raf.ReadUInt8(); + var bitmapOffset = raf.Position; + + // Skip through the bitmap data + // There is no need to load it now + raf.Skip((int) length - 6); + + return new BitmapSection(length, section, bitmapIndicator, dataPointsNumber, bitmapOffset); + } + + internal IEnumerable GetBitmap(BufferedBinaryReader reader) + { + if (BitMapIndicatorCode == 0) + { + reader.Seek(BitmapOffset, SeekOrigin.Begin); + + var bitmap = new BitArray((int)dataPointsNumber, true); + + void TrySet(int i, bool value) + { + if (i < bitmap.Length) + { + bitmap[i] = value; + } + } + + // create new bit map, octet 4 contains number of unused bits at the end + var i = 0; + while (i < bitmap.Length) + { + var bitmapByte = (Bitmask)reader.ReadByte(); + + TrySet(i++, bitmapByte.HasFlag(Bitmask.Bit1)); + TrySet(i++, bitmapByte.HasFlag(Bitmask.Bit2)); + TrySet(i++, bitmapByte.HasFlag(Bitmask.Bit3)); + TrySet(i++, bitmapByte.HasFlag(Bitmask.Bit4)); + TrySet(i++, bitmapByte.HasFlag(Bitmask.Bit5)); + TrySet(i++, bitmapByte.HasFlag(Bitmask.Bit6)); + TrySet(i++, bitmapByte.HasFlag(Bitmask.Bit7)); + TrySet(i++, bitmapByte.HasFlag(Bitmask.Bit8)); + } + + IEnumerable EnumerateBitArray() + { + foreach (bool item in bitmap) + { + yield return item; + } + } + + return EnumerateBitArray(); + } + else + { + IEnumerable EnumerateTrue() + { + for (int i = 0; i < dataPointsNumber; i++) + { + yield return true; + } + } + + return EnumerateTrue(); + } + } + + [Flags] + private enum Bitmask : byte + { + Bit1 = 1 << 7, + Bit2 = 1 << 6, + Bit3 = 1 << 5, + Bit4 = 1 << 4, + Bit5 = 1 << 3, + Bit6 = 1 << 2, + Bit7 = 1 << 1, + Bit8 = 1, + } } \ No newline at end of file diff --git a/src/NGrib/Grib2/Sections/7_DataSection.cs b/src/NGrib/Grib2/Sections/7_DataSection.cs index 0418e17..abebad8 100644 --- a/src/NGrib/Grib2/Sections/7_DataSection.cs +++ b/src/NGrib/Grib2/Sections/7_DataSection.cs @@ -24,62 +24,61 @@ * along with NGrib. If not, see . */ -namespace NGrib.Grib2.Sections +namespace NGrib.Grib2.Sections; + +/// +/// Section 6 - Data Section +/// +public sealed class DataSection { - /// - /// Section 6 - Data Section - /// - public sealed class DataSection - { - /// - /// Length of section in octets. - /// - public long Length { get; } + /// + /// Length of section in octets. + /// + public long Length { get; } - /// - /// Number of section. - /// - public int Section { get; } + /// + /// Number of section. + /// + public int Section { get; } - /// - /// Position of the data start. - /// - public long DataOffset { get; } + /// + /// Position of the data start. + /// + public long DataOffset { get; } - /// - /// Data part length. - /// - public long DataLength { get; } + /// + /// Data part length. + /// + public long DataLength { get; } - private DataSection(long length, int section, long dataOffset, long dataLength) - { - DataOffset = dataOffset; - Length = length; - Section = section; - DataLength = dataLength; - } + private DataSection(long length, int section, long dataOffset, long dataLength) + { + DataOffset = dataOffset; + Length = length; + Section = section; + DataLength = dataLength; + } - internal static DataSection BuildFrom(BufferedBinaryReader reader) - { - // octets 1-4 (Length of DS) - var length = reader.ReadUInt32(); + internal static DataSection BuildFrom(BufferedBinaryReader reader) + { + // octets 1-4 (Length of DS) + var length = reader.ReadUInt32(); - // octet 5 section 7 - var section = reader.ReadUInt8(); - if (section != (int) SectionCode.DataSection) - { - throw new UnexpectedGribSectionException( - SectionCode.DataSection, - section - ); - } + // octet 5 section 7 + var section = reader.ReadUInt8(); + if (section != (int) SectionCode.DataSection) + { + throw new UnexpectedGribSectionException( + SectionCode.DataSection, + section + ); + } - var dataOffset = reader.Position; + var dataOffset = reader.Position; - var dataLength = length - 5; - reader.Skip((int) dataLength); + var dataLength = length - 5; + reader.Skip((int) dataLength); - return new DataSection(length, section, dataOffset, dataLength); - } - } + return new DataSection(length, section, dataOffset, dataLength); + } } \ No newline at end of file diff --git a/src/NGrib/Grib2/Sections/8_EndSection.cs b/src/NGrib/Grib2/Sections/8_EndSection.cs index 209cbf0..aba08c1 100644 --- a/src/NGrib/Grib2/Sections/8_EndSection.cs +++ b/src/NGrib/Grib2/Sections/8_EndSection.cs @@ -24,41 +24,40 @@ * along with NGrib. If not, see . */ -namespace NGrib.Grib2.Sections +namespace NGrib.Grib2.Sections; + +/// +/// Section 8 - End Section +/// +public sealed class EndSection { - /// - /// Section 8 - End Section - /// - public sealed class EndSection - { - /// - /// Length of section in octets. - /// - public long Length { get; } + /// + /// Length of section in octets. + /// + public long Length { get; } - /// - /// Number of section. - /// - public int Section { get; } + /// + /// Number of section. + /// + public int Section { get; } - private EndSection(long length, int section) - { - Length = length; - Section = section; - } + private EndSection(long length, int section) + { + Length = length; + Section = section; + } - internal static EndSection BuildFrom(BufferedBinaryReader reader) - { - var sectionInfos = reader.ReadSectionInfo(); - if (!sectionInfos.Is(SectionCode.EndSection)) - { - throw new UnexpectedGribSectionException( - SectionCode.DataSection, - sectionInfos.SectionCode - ); - } + internal static EndSection BuildFrom(BufferedBinaryReader reader) + { + var sectionInfos = reader.ReadSectionInfo(); + if (!sectionInfos.Is(SectionCode.EndSection)) + { + throw new UnexpectedGribSectionException( + SectionCode.DataSection, + sectionInfos.SectionCode + ); + } - return new EndSection(sectionInfos.Length, sectionInfos.SectionCode); - } - } + return new EndSection(sectionInfos.Length, sectionInfos.SectionCode); + } } \ No newline at end of file diff --git a/src/NGrib/Grib2/Sections/SectionCode.cs b/src/NGrib/Grib2/Sections/SectionCode.cs index dab5936..20d81ad 100644 --- a/src/NGrib/Grib2/Sections/SectionCode.cs +++ b/src/NGrib/Grib2/Sections/SectionCode.cs @@ -17,17 +17,17 @@ * along with NGrib. If not, see . */ -namespace NGrib.Grib2.Sections +namespace NGrib.Grib2.Sections; + +/// +/// Section Codes. +/// +public enum SectionCode { - /// - /// Section Codes. - /// - public enum SectionCode - { /// /// Indicator Section Code. /// - IndicatorSection, + IndicatorSection, /// /// Identification Section Code. @@ -37,36 +37,35 @@ public enum SectionCode /// /// Local Use Section Code. /// - LocalUseSection, + LocalUseSection, - /// - /// Grid Definition Section Code. - /// - GridDefinitionSection, + /// + /// Grid Definition Section Code. + /// + GridDefinitionSection, - /// - /// Product Definition Section Code. - /// - ProductDefinitionSection, + /// + /// Product Definition Section Code. + /// + ProductDefinitionSection, - /// - /// Data Representation Section Code. - /// - DataRepresentationSection, + /// + /// Data Representation Section Code. + /// + DataRepresentationSection, - /// - /// Bitmap Section Code. - /// - BitmapSection, + /// + /// Bitmap Section Code. + /// + BitmapSection, - /// - /// Data Section Code. - /// - DataSection, + /// + /// Data Section Code. + /// + DataSection, - /// - /// End Section Code. - /// - EndSection - } + /// + /// End Section Code. + /// + EndSection } \ No newline at end of file diff --git a/src/NGrib/Grib2/Sections/SectionInfo.cs b/src/NGrib/Grib2/Sections/SectionInfo.cs index 894ee8b..1b1ec51 100644 --- a/src/NGrib/Grib2/Sections/SectionInfo.cs +++ b/src/NGrib/Grib2/Sections/SectionInfo.cs @@ -17,48 +17,47 @@ * along with NGrib. If not, see . */ -namespace NGrib.Grib2.Sections +namespace NGrib.Grib2.Sections; + +/// +/// Represents basic section information. +/// +public readonly struct SectionInfo { - /// - /// Represents basic section information. - /// - public readonly struct SectionInfo - { - /// - /// Length of section in octets. - /// - public long Length { get; } + /// + /// Length of section in octets. + /// + public long Length { get; } - /// - /// Number of section. - /// - public int SectionCode { get; } + /// + /// Number of section. + /// + public int SectionCode { get; } - /// - /// Initialize a new instance. - /// - /// Section length. - /// Section code. - public SectionInfo(long length, int sectionCode) - { - Length = length; - SectionCode = sectionCode; - } + /// + /// Initialize a new instance. + /// + /// Section length. + /// Section code. + public SectionInfo(long length, int sectionCode) + { + Length = length; + SectionCode = sectionCode; + } - /// - /// Initialize a new instance. - /// - /// Section length. - /// Section code. - public SectionInfo(long length, SectionCode sectionCode) : this(length, (int) sectionCode) - { - } + /// + /// Initialize a new instance. + /// + /// Section length. + /// Section code. + public SectionInfo(long length, SectionCode sectionCode) : this(length, (int) sectionCode) + { + } - /// - /// Indicates whether this instance section code is equal to a specified section code. - /// - /// A section code. - /// true if this instance section is the same as the parameter, false otherwise. - public bool Is(SectionCode sectionCode) => SectionCode == (int) sectionCode; - } -} + /// + /// Indicates whether this instance section code is equal to a specified section code. + /// + /// A section code. + /// true if this instance section is the same as the parameter, false otherwise. + public bool Is(SectionCode sectionCode) => SectionCode == (int) sectionCode; +} \ No newline at end of file diff --git a/src/NGrib/Grib2/Templates/DataRepresentations/0000_GridPointDataSimplePacking.cs b/src/NGrib/Grib2/Templates/DataRepresentations/0000_GridPointDataSimplePacking.cs index ba7dbd5..7eb67a9 100644 --- a/src/NGrib/Grib2/Templates/DataRepresentations/0000_GridPointDataSimplePacking.cs +++ b/src/NGrib/Grib2/Templates/DataRepresentations/0000_GridPointDataSimplePacking.cs @@ -24,91 +24,88 @@ * along with NGrib. If not, see . */ -using System; -using System.Collections.Generic; using NGrib.Grib2.CodeTables; using NGrib.Grib2.Sections; -namespace NGrib.Grib2.Templates.DataRepresentations +namespace NGrib.Grib2.Templates.DataRepresentations; + +/// +/// Data Representation Template 5.0: Grid point data - simple packing +/// +public class GridPointDataSimplePacking : DataRepresentation { - /// - /// Data Representation Template 5.0: Grid point data - simple packing - /// - public class GridPointDataSimplePacking : DataRepresentation - { - /// - /// Reference value (R) . - /// - public float ReferenceValue { get; } - - /// - /// Binary scale factor (E). - /// - public int BinaryScaleFactor { get; } - - /// - /// Decimal scale factor (D). - /// - public int DecimalScaleFactor { get; } - - /// - /// Number of bits used for each packed value for simple packing, or for each group reference value for complex packing or spatial differencing. - /// - public int NumberOfBits { get; } - - /// - /// Type of original field values. - /// - public OriginalFieldValuesType OriginalFieldValuesType { get; } - - internal GridPointDataSimplePacking(BufferedBinaryReader reader) - { - ReferenceValue = reader.ReadSingle(); - BinaryScaleFactor = reader.ReadInt16(); - DecimalScaleFactor = reader.ReadInt16(); - NumberOfBits = reader.ReadUInt8(); - - OriginalFieldValuesType = (OriginalFieldValuesType) reader.ReadUInt8(); - } - - private protected override IEnumerable DoEnumerateDataValues(BufferedBinaryReader reader, DataSection dataSection, long dataPointsNumber) - { - IEnumerable ReadPackedValues() - { - reader.NextUIntN(); - for (var i = 0; i < dataPointsNumber; i++) - { - yield return reader.ReadUIntN(NumberOfBits); - } - } - - return Unpack(ReadPackedValues()); - - } - - protected IEnumerable Unpack(IEnumerable packedValues) - { - var d = DecimalScaleFactor; - - var dd = Math.Pow(10, d); - - var r = ReferenceValue; - - var e = BinaryScaleFactor; - - var ee = Math.Pow(2.0, e); - - // Y * 10**D = R + (X1 + X2) * 2**E - // E = binary scale factor - // D = decimal scale factor - // R = reference value - // X1 = 0 - // X2 = scaled encoded value - foreach(var item in packedValues) - { - // (R + ( X1 + X2) * EE)/DD ; - yield return (float) ((r + item * ee) / dd); - } - } - } + /// + /// Reference value (R) . + /// + public double ReferenceValue { get; } + + /// + /// Binary scale factor (E). + /// + public int BinaryScaleFactor { get; } + + /// + /// Decimal scale factor (D). + /// + public int DecimalScaleFactor { get; } + + /// + /// Number of bits used for each packed value for simple packing, or for each group reference value for complex packing or spatial differencing. + /// + public int NumberOfBits { get; } + + /// + /// Type of original field values. + /// + public OriginalFieldValuesType OriginalFieldValuesType { get; } + + internal GridPointDataSimplePacking(BufferedBinaryReader reader) + { + ReferenceValue = reader.ReadSingle(); + BinaryScaleFactor = reader.ReadInt16(); + DecimalScaleFactor = reader.ReadInt16(); + NumberOfBits = reader.ReadUInt8(); + + OriginalFieldValuesType = (OriginalFieldValuesType) reader.ReadUInt8(); + } + + private protected override IEnumerable DoEnumerateDataValues(BufferedBinaryReader reader, DataSection dataSection, long dataPointsNumber) + { + IEnumerable ReadPackedValues() + { + reader.NextUIntN(); + for (var i = 0; i < dataPointsNumber; i++) + { + yield return reader.ReadUIntN(NumberOfBits); + } + } + + return Unpack(ReadPackedValues()); + + } + + protected IEnumerable Unpack(IEnumerable packedValues) + { + var d = DecimalScaleFactor; + + var dd = Math.Pow(10, d); + + var r = ReferenceValue; + + var e = BinaryScaleFactor; + + var ee = Math.Pow(2.0, e); + + // Y * 10**D = R + (X1 + X2) * 2**E + // E = binary scale factor + // D = decimal scale factor + // R = reference value + // X1 = 0 + // X2 = scaled encoded value + foreach(var item in packedValues) + { + // (R + ( X1 + X2) * EE)/DD ; + yield return ((r + item * ee) / dd); + } + } } \ No newline at end of file diff --git a/src/NGrib/Grib2/Templates/DataRepresentations/0002_GridPointDataComplexPacking.cs b/src/NGrib/Grib2/Templates/DataRepresentations/0002_GridPointDataComplexPacking.cs index c218059..580f2ed 100644 --- a/src/NGrib/Grib2/Templates/DataRepresentations/0002_GridPointDataComplexPacking.cs +++ b/src/NGrib/Grib2/Templates/DataRepresentations/0002_GridPointDataComplexPacking.cs @@ -24,246 +24,243 @@ * along with NGrib. If not, see . */ -using System; -using System.Collections.Generic; using NGrib.Grib2.CodeTables; using NGrib.Grib2.Sections; -namespace NGrib.Grib2.Templates.DataRepresentations +namespace NGrib.Grib2.Templates.DataRepresentations; + +/// +/// Data Representation Template 5.2: Grid point data - complex packing +/// +public class GridPointDataComplexPacking : GridPointDataSimplePacking { - /// - /// Data Representation Template 5.2: Grid point data - complex packing - /// - public class GridPointDataComplexPacking : GridPointDataSimplePacking - { - /// - /// Group splitting method used. - /// - public GroupSplittingMethod GroupSplittingMethod { get; } - - /// - /// Group splitting method used. - /// - public ComplexPackingMissingValueManagement MissingValueManagement { get; } - - /// - /// Primary missing value substitute. - /// - public float PrimaryMissingValue { get; } - - /// - /// Secondary missing value substitute. - /// - public float SecondaryMissingValue { get; } - - /// - /// Number of groups of data values into which field is split (NG). - /// - public long NumberOfGroups { get; } - - /// - /// Reference for group widths. - /// - public int ReferenceGroupWidths { get; } - - /// - /// Number of bits used for the group widths. - /// - public int BitsGroupWidths { get; } + /// + /// Group splitting method used. + /// + public GroupSplittingMethod GroupSplittingMethod { get; } + + /// + /// Group splitting method used. + /// + public ComplexPackingMissingValueManagement MissingValueManagement { get; } + + /// + /// Primary missing value substitute. + /// + public float PrimaryMissingValue { get; } + + /// + /// Secondary missing value substitute. + /// + public float SecondaryMissingValue { get; } + + /// + /// Number of groups of data values into which field is split (NG). + /// + public long NumberOfGroups { get; } + + /// + /// Reference for group widths. + /// + public int ReferenceGroupWidths { get; } + + /// + /// Number of bits used for the group widths. + /// + public int BitsGroupWidths { get; } + + /// + /// Reference for group lengths. + /// + public long ReferenceGroupLength { get; } - /// - /// Reference for group lengths. - /// - public long ReferenceGroupLength { get; } + /// + /// Length increment for the group lengths. + /// + public int LengthIncrement { get; } - /// - /// Length increment for the group lengths. - /// - public int LengthIncrement { get; } + /// + /// True length of last group. + /// + public long LastGroupLength { get; } - /// - /// True length of last group. - /// - public long LastGroupLength { get; } + /// + /// Number of bits used for the scaled group lengths. + /// + /// + /// After subtraction of the reference value given in octets 38-41 and division by the length increment given in octet 42. + /// + public int BitsScaledGroupLength { get; } - /// - /// Number of bits used for the scaled group lengths. - /// - /// - /// After subtraction of the reference value given in octets 38-41 and division by the length increment given in octet 42. - /// - public int BitsScaledGroupLength { get; } - - internal GridPointDataComplexPacking(BufferedBinaryReader reader) : base(reader) - { - GroupSplittingMethod = (GroupSplittingMethod) reader.ReadUInt8(); - - MissingValueManagement = (ComplexPackingMissingValueManagement) reader.ReadUInt8(); - - PrimaryMissingValue = reader.ReadSingle(); - SecondaryMissingValue = reader.ReadSingle(); - NumberOfGroups = reader.ReadUInt32(); - - ReferenceGroupWidths = reader.ReadUInt8(); - - BitsGroupWidths = reader.ReadUInt8(); - // according to documentation subtract referenceGroupWidths - BitsGroupWidths = BitsGroupWidths - ReferenceGroupWidths; - - ReferenceGroupLength = reader.ReadUInt32(); - - LengthIncrement = reader.ReadUInt8(); - - LastGroupLength = reader.ReadUInt32(); - - BitsScaledGroupLength = reader.ReadUInt8(); - } - - private protected override IEnumerable DoEnumerateDataValues(BufferedBinaryReader reader, DataSection dataSection, long dataPointsNumber) - { - var mvm = MissingValueManagement; - - var pmv = PrimaryMissingValue; - - var ng = (int) NumberOfGroups; - - // 6-xx Get reference values for groups (X1's) - var x1 = new int[ng]; - var nbBits = NumberOfBits; - - for (var i = 0; i < ng; i++) - { - x1[i] = reader.ReadUIntN(nbBits); - } - - // [xx + 1 ]-yy Get number of bits used to encode each group - var nb = new int[ng]; - nbBits = BitsGroupWidths; - - reader.NextUIntN(); - for (var i = 0; i < ng; i++) - { - nb[i] = reader.ReadUIntN(nbBits); - } - - // [yy +1 ]-zz Get the scaled group lengths using formula - // Ln = ref + Kn * len_inc, where n = 1-NG, - // ref = referenceGroupLength, and len_inc = lengthIncrement - - var l = new int[ng]; - var rgLength = (int) ReferenceGroupLength; - - var lenInc = LengthIncrement; - - nbBits = BitsScaledGroupLength; - - reader.NextUIntN(); - for (var i = 0; i < ng; i++) - { - // NG - l[i] = rgLength + reader.ReadUIntN(nbBits) * lenInc; - } - - // [zz +1 ]-nn get X2 values and calculate the results Y using formula - // Y * 10**D = R + (X1 + X2) * 2**E - - var d = DecimalScaleFactor; - - var dd = Math.Pow(10, d); - - var r = ReferenceValue; - - var e = BinaryScaleFactor; - - var ee = Math.Pow(2.0, e); - - // used to check missing values when X2 is packed with all 1's - var bitsmv1 = new int[31]; - for (var i = 0; i < 31; i++) - { - bitsmv1[i] = (int) Math.Pow(2, i) - 1; - } - - int x2; - reader.NextUIntN(); - for (var i = 0; i < ng - 1; i++) - { - for (var j = 0; j < l[i]; j++) - { - if (nb[i] == 0) - { - if (mvm == 0) - { - // X2 = 0 - yield return (float) ((r + x1[i] * ee) / dd); - } - else if (mvm == ComplexPackingMissingValueManagement.Primary) - { - yield return pmv; - } - } - else - { - x2 = reader.ReadUIntN(nb[i]); - if (mvm == 0) - { - yield return (float) ((r + (x1[i] + x2) * ee) / dd); - } - else if (mvm == ComplexPackingMissingValueManagement.Primary) - { - // X2 is also set to missing value is all bits set to 1's - if (x2 == bitsmv1[nb[i]]) - { - yield return pmv; - } - else - { - yield return (float) ((r + (x1[i] + x2) * ee) / dd); - } - } - } - } // end for j - } // end for i - - // process last group - var last = (int) LastGroupLength; - - for (var j = 0; j < last; j++) - { - // last group - if (nb[ng - 1] == 0) - { - if (mvm == 0) - { - // X2 = 0 - yield return (float) ((r + x1[ng - 1] * ee) / dd); - } - else if (mvm == ComplexPackingMissingValueManagement.Primary) - { - yield return pmv; - } - } - else - { - x2 = reader.ReadUIntN(nb[ng - 1]); - if (mvm == 0) - { - yield return (float) ((r + (x1[ng - 1] + x2) * ee) / dd); - } - else if (mvm == ComplexPackingMissingValueManagement.Primary) - { - // X2 is also set to missing value is all bits set to 1's - if (x2 == bitsmv1[nb[ng - 1]]) - { - yield return pmv; - } - else - { - yield return (float) ((r + (x1[ng - 1] + x2) * ee) / dd); - } - } - } - } // end for j - } - } + internal GridPointDataComplexPacking(BufferedBinaryReader reader) : base(reader) + { + GroupSplittingMethod = (GroupSplittingMethod) reader.ReadUInt8(); + + MissingValueManagement = (ComplexPackingMissingValueManagement) reader.ReadUInt8(); + + PrimaryMissingValue = reader.ReadSingle(); + SecondaryMissingValue = reader.ReadSingle(); + NumberOfGroups = reader.ReadUInt32(); + + ReferenceGroupWidths = reader.ReadUInt8(); + + BitsGroupWidths = reader.ReadUInt8(); + // according to documentation subtract referenceGroupWidths + BitsGroupWidths = BitsGroupWidths - ReferenceGroupWidths; + + ReferenceGroupLength = reader.ReadUInt32(); + + LengthIncrement = reader.ReadUInt8(); + + LastGroupLength = reader.ReadUInt32(); + + BitsScaledGroupLength = reader.ReadUInt8(); + } + + private protected override IEnumerable DoEnumerateDataValues(BufferedBinaryReader reader, DataSection dataSection, long dataPointsNumber) + { + var mvm = MissingValueManagement; + + var pmv = PrimaryMissingValue; + + var ng = (int) NumberOfGroups; + + // 6-xx Get reference values for groups (X1's) + var x1 = new int[ng]; + var nbBits = NumberOfBits; + + for (var i = 0; i < ng; i++) + { + x1[i] = reader.ReadUIntN(nbBits); + } + + // [xx + 1 ]-yy Get number of bits used to encode each group + var nb = new int[ng]; + nbBits = BitsGroupWidths; + + reader.NextUIntN(); + for (var i = 0; i < ng; i++) + { + nb[i] = reader.ReadUIntN(nbBits); + } + + // [yy +1 ]-zz Get the scaled group lengths using formula + // Ln = ref + Kn * len_inc, where n = 1-NG, + // ref = referenceGroupLength, and len_inc = lengthIncrement + + var l = new int[ng]; + var rgLength = (int) ReferenceGroupLength; + + var lenInc = LengthIncrement; + + nbBits = BitsScaledGroupLength; + + reader.NextUIntN(); + for (var i = 0; i < ng; i++) + { + // NG + l[i] = rgLength + reader.ReadUIntN(nbBits) * lenInc; + } + + // [zz +1 ]-nn get X2 values and calculate the results Y using formula + // Y * 10**D = R + (X1 + X2) * 2**E + + var d = DecimalScaleFactor; + + var dd = Math.Pow(10, d); + + var r = ReferenceValue; + + var e = BinaryScaleFactor; + + var ee = Math.Pow(2.0, e); + + // used to check missing values when X2 is packed with all 1's + var bitsmv1 = new int[31]; + for (var i = 0; i < 31; i++) + { + bitsmv1[i] = (int) Math.Pow(2, i) - 1; + } + + int x2; + reader.NextUIntN(); + for (var i = 0; i < ng - 1; i++) + { + for (var j = 0; j < l[i]; j++) + { + if (nb[i] == 0) + { + if (mvm == 0) + { + // X2 = 0 + yield return (float) ((r + x1[i] * ee) / dd); + } + else if (mvm == ComplexPackingMissingValueManagement.Primary) + { + yield return pmv; + } + } + else + { + x2 = reader.ReadUIntN(nb[i]); + if (mvm == 0) + { + yield return (float) ((r + (x1[i] + x2) * ee) / dd); + } + else if (mvm == ComplexPackingMissingValueManagement.Primary) + { + // X2 is also set to missing value is all bits set to 1's + if (x2 == bitsmv1[nb[i]]) + { + yield return pmv; + } + else + { + yield return (float) ((r + (x1[i] + x2) * ee) / dd); + } + } + } + } // end for j + } // end for i + + // process last group + var last = (int) LastGroupLength; + + for (var j = 0; j < last; j++) + { + // last group + if (nb[ng - 1] == 0) + { + if (mvm == 0) + { + // X2 = 0 + yield return (float) ((r + x1[ng - 1] * ee) / dd); + } + else if (mvm == ComplexPackingMissingValueManagement.Primary) + { + yield return pmv; + } + } + else + { + x2 = reader.ReadUIntN(nb[ng - 1]); + if (mvm == 0) + { + yield return (float) ((r + (x1[ng - 1] + x2) * ee) / dd); + } + else if (mvm == ComplexPackingMissingValueManagement.Primary) + { + // X2 is also set to missing value is all bits set to 1's + if (x2 == bitsmv1[nb[ng - 1]]) + { + yield return pmv; + } + else + { + yield return (float) ((r + (x1[ng - 1] + x2) * ee) / dd); + } + } + } + } // end for j + } } \ No newline at end of file diff --git a/src/NGrib/Grib2/Templates/DataRepresentations/0003_GridPointDataComplexPackingAndSpatialDifferencing.cs b/src/NGrib/Grib2/Templates/DataRepresentations/0003_GridPointDataComplexPackingAndSpatialDifferencing.cs index b8259ae..6d2d2e4 100644 --- a/src/NGrib/Grib2/Templates/DataRepresentations/0003_GridPointDataComplexPackingAndSpatialDifferencing.cs +++ b/src/NGrib/Grib2/Templates/DataRepresentations/0003_GridPointDataComplexPackingAndSpatialDifferencing.cs @@ -24,400 +24,397 @@ * along with NGrib. If not, see . */ -using System; -using System.Collections.Generic; using NGrib.Grib2.CodeTables; using NGrib.Grib2.Sections; -namespace NGrib.Grib2.Templates.DataRepresentations +namespace NGrib.Grib2.Templates.DataRepresentations; + +/// +/// Data Representation Template 5.3: Grid point data - complex packing and spatial differencing +/// +public class GridPointDataComplexPackingAndSpatialDifferencing : GridPointDataComplexPacking { - /// - /// Data Representation Template 5.3: Grid point data - complex packing and spatial differencing - /// - public class GridPointDataComplexPackingAndSpatialDifferencing : GridPointDataComplexPacking - { - /// - /// Order of spatial differencing. - /// - public SpatialDifferencingOrder OrderSpatial { get; } - - /// - /// Number of octets required in the Data Section to specify extra - /// descriptors needed for spatial differencing. - /// - public int ExtraDescriptorsLength { get; } - - internal GridPointDataComplexPackingAndSpatialDifferencing(BufferedBinaryReader reader) : base(reader) - { - OrderSpatial = (SpatialDifferencingOrder) reader.ReadUInt8(); - ExtraDescriptorsLength = reader.ReadUInt8(); - } - - private protected override IEnumerable DoEnumerateDataValues(BufferedBinaryReader reader, DataSection dataSection, long dataPointsNumber) - { - var mvm = MissingValueManagement; - - float pmv = PrimaryMissingValue; - - int ng = (int) NumberOfGroups; - - int g1 = 0, gMin = 0, h1 = 0, h2 = 0, hMin = 0; - // [6-ww] 1st values of undifferenced scaled values and minimums - var os = OrderSpatial; - int ds = ExtraDescriptorsLength; - - reader.NextUIntN(); - int sign; - // ds is number of bytes, convert to bits -1 for sign bit - ds = ds * 8 - 1; - if (os == SpatialDifferencingOrder.FirstOrder) - { - // first order spatial differencing g1 and gMin - sign = reader.ReadUIntN(1); - g1 = reader.ReadUIntN(ds); - if (sign == 1) - { - g1 *= (-1); - } - - sign = reader.ReadUIntN(1); - gMin = reader.ReadUIntN(ds); - if (sign == 1) - { - gMin *= (-1); - } - } - else if (os == SpatialDifferencingOrder.SecondOrder) - { - //second order spatial differencing h1, h2, hMin - sign = reader.ReadUIntN(1); - h1 = reader.ReadUIntN(ds); - if (sign == 1) - { - h1 *= (-1); - } - - sign = reader.ReadUIntN(1); - h2 = reader.ReadUIntN(ds); - if (sign == 1) - { - h2 *= (-1); - } - - sign = reader.ReadUIntN(1); - hMin = reader.ReadUIntN(ds); - if (sign == 1) - { - hMin *= (-1); - } - } - else - { - throw new BadGribFormatException("DS Error"); - } - - // [ww +1]-xx Get reference values for groups (X1's) - int[] x1 = new int[ng]; - int nbBits = NumberOfBits; - - reader.NextUIntN(); - for (int i = 0; i < ng; i++) - { - x1[i] = reader.ReadUIntN(nbBits); - } - - // [xx +1 ]-yy Get number of bits used to encode each group - int[] nb = new int[ng]; - nbBits = BitsGroupWidths; - - reader.NextUIntN(); - for (int i = 0; i < ng; i++) - { - nb[i] = reader.ReadUIntN(nbBits); - } - - // [yy +1 ]-zz Get the scaled group lengths using formula - // Ln = ref + Kn * len_inc, where n = 1-NG, - // ref = referenceGroupLength, and len_inc = lengthIncrement - - int[] l = new int[ng]; - int countL = 0; - int rgLength = (int) ReferenceGroupLength; - - int lenInc = LengthIncrement; - - nbBits = BitsScaledGroupLength; - - reader.NextUIntN(); - for (int i = 0; i < ng; i++) - { - // NG - l[i] = rgLength + reader.ReadUIntN(nbBits) * lenInc; - - countL += l[i]; - } - - // [zz +1 ]-nn get X2 values and add X1[ i ] + X2 - - var data = new float[countL]; - - //gds.getNumberPoints() ); - // used to check missing values when X2 is packed with all 1's - int[] bitsmv1 = new int[31]; - //int bitsmv2[] = new int[ 31 ]; didn't code cuz number larger the # of bits - for (int i = 0; i < 31; i++) - { - bitsmv1[i] = (int) Math.Pow(2, i) - 1; - } - - var count = 0; - int x2; - reader.NextUIntN(); - for (int i = 0; i < ng - 1; i++) - { - for (int j = 0; j < l[i]; j++) - { - if (nb[i] == 0) - { - if (mvm == 0) - { - // X2 = 0 - data[count++] = x1[i]; - } - else if (mvm == ComplexPackingMissingValueManagement.Primary) - { - data[count++] = pmv; - } - } - else - { - x2 = reader.ReadUIntN(nb[i]); - - if (mvm == 0) - { - data[count++] = x1[i] + x2; - } - else if (mvm == ComplexPackingMissingValueManagement.Primary) - { - // X2 is also set to missing value is all bits set to 1's - if (x2 == bitsmv1[nb[i]]) - { - data[count++] = pmv; - } - else - { - data[count++] = x1[i] + x2; - } - } - } - } // end for j - } // end for i - - // process last group - int last = (int) LastGroupLength; - - for (int j = 0; j < last; j++) - { - // last group - if (nb[ng - 1] == 0) - { - if (mvm == 0) - { - // X2 = 0 - data[count++] = x1[ng - 1]; - } - else if (mvm == ComplexPackingMissingValueManagement.Primary) - { - data[count++] = pmv; - } - } - else - { - x2 = reader.ReadUIntN(nb[ng - 1]); - if (mvm == 0) - { - data[count++] = x1[ng - 1] + x2; - } - else if (mvm == ComplexPackingMissingValueManagement.Primary) - { - // X2 is also set to missing value is all bits set to 1's - if (x2 == bitsmv1[nb[ng - 1]]) - { - data[count++] = pmv; - } - else - { - data[count++] = x1[ng - 1] + x2; - } - } - } - } // end for j - - if (os == SpatialDifferencingOrder.FirstOrder) - { - // g1 and gMin this coding is a sort of guess, no doc - float sum = 0; - if (mvm == 0) - { - // no missing values - for (int i = 1; i < data.Length; i++) - { - data[i] += gMin; // add minimum back - } - - data[0] = g1; - for (int i = 1; i < data.Length; i++) - { - sum += data[i]; - data[i] = data[i - 1] + sum; - } - } - else - { - // contains missing values - float lastOne = pmv; - // add the minimum back and set g1 - int idx = 0; - for (int i = 0; i < data.Length; i++) - { - if (data[i] != pmv) - { - if (idx == 0) - { - // set g1 - data[i] = g1; - lastOne = data[i]; - idx = i + 1; - } - else - { - data[i] += gMin; - } - } - } - - if (lastOne == pmv) - { - throw new BadGribFormatException("DS bad spatial differencing data"); - } - - for (int i = idx; i < data.Length; i++) - { - if (data[i] != pmv) - { - sum += data[i]; - data[i] = lastOne + sum; - lastOne = data[i]; - } - } - } - } - else if (os == SpatialDifferencingOrder.SecondOrder) - { - //h1, h2, hMin - float hDiff = h2 - h1; - float sum = 0; - if (mvm == 0) - { - // no missing values - for (int i = 2; i < data.Length; i++) - { - data[i] += hMin; // add minimum back - } - - data[0] = h1; - data[1] = h2; - sum = hDiff; - for (int i = 2; i < data.Length; i++) - { - sum += data[i]; - data[i] = data[i - 1] + sum; - } - } - else - { - // contains missing values - int idx = 0; - float lastOne = pmv; - // add the minimum back and set h1 and h2 - for (int i = 0; i < data.Length; i++) - { - if (data[i] != pmv) - { - if (idx == 0) - { - // set h1 - data[i] = h1; - sum = 0; - lastOne = data[i]; - idx++; - } - else if (idx == 1) - { - // set h2 - data[i] = h1 + hDiff; - sum = hDiff; - lastOne = data[i]; - idx = i + 1; - } - else - { - data[i] += hMin; - } - } - } - - if (lastOne == pmv) - { - throw new BadGribFormatException("DS bad spatial differencing data"); - } - - for (int i = idx; i < data.Length; i++) - { - if (data[i] != pmv) - { - sum += data[i]; - - data[i] = lastOne + sum; - lastOne = data[i]; - } - } - } - } // end h1, h2, hMin - - // formula used to create values, Y * 10**D = R + (X1 + X2) * 2**E - - var d = DecimalScaleFactor; - - var dd = Math.Pow(10, d); - - var r = ReferenceValue; - - var e = BinaryScaleFactor; - - var ee = Math.Pow(2.0, e); - - if (mvm == 0) - { - // no missing values - for (int i = 0; i < data.Length; i++) - { - data[i] = (float) ((r + data[i] * ee) / dd); - } - } - else - { - // missing value == 1 - for (int i = 0; i < data.Length; i++) - { - if (data[i] != pmv) - { - data[i] = (float) ((r + data[i] * ee) / dd); - } - } - } - - return data; - } - } + /// + /// Order of spatial differencing. + /// + public SpatialDifferencingOrder OrderSpatial { get; } + + /// + /// Number of octets required in the Data Section to specify extra + /// descriptors needed for spatial differencing. + /// + public int ExtraDescriptorsLength { get; } + + internal GridPointDataComplexPackingAndSpatialDifferencing(BufferedBinaryReader reader) : base(reader) + { + OrderSpatial = (SpatialDifferencingOrder) reader.ReadUInt8(); + ExtraDescriptorsLength = reader.ReadUInt8(); + } + + private protected override IEnumerable DoEnumerateDataValues(BufferedBinaryReader reader, DataSection dataSection, long dataPointsNumber) + { + var mvm = MissingValueManagement; + + double pmv = PrimaryMissingValue; + + int ng = (int) NumberOfGroups; + + int g1 = 0, gMin = 0, h1 = 0, h2 = 0, hMin = 0; + // [6-ww] 1st values of undifferenced scaled values and minimums + var os = OrderSpatial; + int ds = ExtraDescriptorsLength; + + reader.NextUIntN(); + int sign; + // ds is number of bytes, convert to bits -1 for sign bit + ds = ds * 8 - 1; + if (os == SpatialDifferencingOrder.FirstOrder) + { + // first order spatial differencing g1 and gMin + sign = reader.ReadUIntN(1); + g1 = reader.ReadUIntN(ds); + if (sign == 1) + { + g1 *= (-1); + } + + sign = reader.ReadUIntN(1); + gMin = reader.ReadUIntN(ds); + if (sign == 1) + { + gMin *= (-1); + } + } + else if (os == SpatialDifferencingOrder.SecondOrder) + { + //second order spatial differencing h1, h2, hMin + sign = reader.ReadUIntN(1); + h1 = reader.ReadUIntN(ds); + if (sign == 1) + { + h1 *= (-1); + } + + sign = reader.ReadUIntN(1); + h2 = reader.ReadUIntN(ds); + if (sign == 1) + { + h2 *= (-1); + } + + sign = reader.ReadUIntN(1); + hMin = reader.ReadUIntN(ds); + if (sign == 1) + { + hMin *= (-1); + } + } + else + { + throw new BadGribFormatException("DS Error"); + } + + // [ww +1]-xx Get reference values for groups (X1's) + int[] x1 = new int[ng]; + int nbBits = NumberOfBits; + + reader.NextUIntN(); + for (int i = 0; i < ng; i++) + { + x1[i] = reader.ReadUIntN(nbBits); + } + + // [xx +1 ]-yy Get number of bits used to encode each group + int[] nb = new int[ng]; + nbBits = BitsGroupWidths; + + reader.NextUIntN(); + for (int i = 0; i < ng; i++) + { + nb[i] = reader.ReadUIntN(nbBits); + } + + // [yy +1 ]-zz Get the scaled group lengths using formula + // Ln = ref + Kn * len_inc, where n = 1-NG, + // ref = referenceGroupLength, and len_inc = lengthIncrement + + int[] l = new int[ng]; + int countL = 0; + int rgLength = (int) ReferenceGroupLength; + + int lenInc = LengthIncrement; + + nbBits = BitsScaledGroupLength; + + reader.NextUIntN(); + for (int i = 0; i < ng; i++) + { + // NG + l[i] = rgLength + reader.ReadUIntN(nbBits) * lenInc; + + countL += l[i]; + } + + // [zz +1 ]-nn get X2 values and add X1[ i ] + X2 + + var data = new double[countL]; + + //gds.getNumberPoints() ); + // used to check missing values when X2 is packed with all 1's + int[] bitsmv1 = new int[31]; + //int bitsmv2[] = new int[ 31 ]; didn't code cuz number larger the # of bits + for (int i = 0; i < 31; i++) + { + bitsmv1[i] = (int) Math.Pow(2, i) - 1; + } + + var count = 0; + int x2; + reader.NextUIntN(); + for (int i = 0; i < ng - 1; i++) + { + for (int j = 0; j < l[i]; j++) + { + if (nb[i] == 0) + { + if (mvm == 0) + { + // X2 = 0 + data[count++] = x1[i]; + } + else if (mvm == ComplexPackingMissingValueManagement.Primary) + { + data[count++] = pmv; + } + } + else + { + x2 = reader.ReadUIntN(nb[i]); + + if (mvm == 0) + { + data[count++] = x1[i] + x2; + } + else if (mvm == ComplexPackingMissingValueManagement.Primary) + { + // X2 is also set to missing value is all bits set to 1's + if (x2 == bitsmv1[nb[i]]) + { + data[count++] = pmv; + } + else + { + data[count++] = x1[i] + x2; + } + } + } + } // end for j + } // end for i + + // process last group + int last = (int) LastGroupLength; + + for (int j = 0; j < last; j++) + { + // last group + if (nb[ng - 1] == 0) + { + if (mvm == 0) + { + // X2 = 0 + data[count++] = x1[ng - 1]; + } + else if (mvm == ComplexPackingMissingValueManagement.Primary) + { + data[count++] = pmv; + } + } + else + { + x2 = reader.ReadUIntN(nb[ng - 1]); + if (mvm == 0) + { + data[count++] = x1[ng - 1] + x2; + } + else if (mvm == ComplexPackingMissingValueManagement.Primary) + { + // X2 is also set to missing value is all bits set to 1's + if (x2 == bitsmv1[nb[ng - 1]]) + { + data[count++] = pmv; + } + else + { + data[count++] = x1[ng - 1] + x2; + } + } + } + } // end for j + + if (os == SpatialDifferencingOrder.FirstOrder) + { + // g1 and gMin this coding is a sort of guess, no doc + double sum = 0; + if (mvm == 0) + { + // no missing values + for (int i = 1; i < data.Length; i++) + { + data[i] += gMin; // add minimum back + } + + data[0] = g1; + for (int i = 1; i < data.Length; i++) + { + sum += data[i]; + data[i] = data[i - 1] + sum; + } + } + else + { + // contains missing values + double lastOne = pmv; + // add the minimum back and set g1 + int idx = 0; + for (int i = 0; i < data.Length; i++) + { + if (data[i] != pmv) + { + if (idx == 0) + { + // set g1 + data[i] = g1; + lastOne = data[i]; + idx = i + 1; + } + else + { + data[i] += gMin; + } + } + } + + if (lastOne == pmv) + { + throw new BadGribFormatException("DS bad spatial differencing data"); + } + + for (int i = idx; i < data.Length; i++) + { + if (data[i] != pmv) + { + sum += data[i]; + data[i] = lastOne + sum; + lastOne = data[i]; + } + } + } + } + else if (os == SpatialDifferencingOrder.SecondOrder) + { + //h1, h2, hMin + double hDiff = h2 - h1; + double sum = 0; + if (mvm == 0) + { + // no missing values + for (int i = 2; i < data.Length; i++) + { + data[i] += hMin; // add minimum back + } + + data[0] = h1; + data[1] = h2; + sum = hDiff; + for (int i = 2; i < data.Length; i++) + { + sum += data[i]; + data[i] = data[i - 1] + sum; + } + } + else + { + // contains missing values + int idx = 0; + double lastOne = pmv; + // add the minimum back and set h1 and h2 + for (int i = 0; i < data.Length; i++) + { + if (data[i] != pmv) + { + if (idx == 0) + { + // set h1 + data[i] = h1; + sum = 0; + lastOne = data[i]; + idx++; + } + else if (idx == 1) + { + // set h2 + data[i] = h1 + hDiff; + sum = hDiff; + lastOne = data[i]; + idx = i + 1; + } + else + { + data[i] += hMin; + } + } + } + + if (lastOne == pmv) + { + throw new BadGribFormatException("DS bad spatial differencing data"); + } + + for (int i = idx; i < data.Length; i++) + { + if (data[i] != pmv) + { + sum += data[i]; + + data[i] = lastOne + sum; + lastOne = data[i]; + } + } + } + } // end h1, h2, hMin + + // formula used to create values, Y * 10**D = R + (X1 + X2) * 2**E + + var d = DecimalScaleFactor; + + var dd = Math.Pow(10, d); + + var r = ReferenceValue; + + var e = BinaryScaleFactor; + + var ee = Math.Pow(2.0, e); + + if (mvm == 0) + { + // no missing values + for (int i = 0; i < data.Length; i++) + { + data[i] = ((r + data[i] * ee) / dd); + } + } + else + { + // missing value == 1 + for (int i = 0; i < data.Length; i++) + { + if (data[i] != pmv) + { + data[i] = ((r + data[i] * ee) / dd); + } + } + } + + return data; + } } \ No newline at end of file diff --git a/src/NGrib/Grib2/Templates/DataRepresentations/0040_GridPointDataJpeg2000CodeStream.cs b/src/NGrib/Grib2/Templates/DataRepresentations/0040_GridPointDataJpeg2000CodeStream.cs index cda8451..6f3c70b 100644 --- a/src/NGrib/Grib2/Templates/DataRepresentations/0040_GridPointDataJpeg2000CodeStream.cs +++ b/src/NGrib/Grib2/Templates/DataRepresentations/0040_GridPointDataJpeg2000CodeStream.cs @@ -26,42 +26,40 @@ using CSJ2K; using NGrib.Grib2.Sections; -using System.Collections.Generic; -namespace NGrib.Grib2.Templates.DataRepresentations +namespace NGrib.Grib2.Templates.DataRepresentations; + +public class GridPointDataJpeg2000CodeStream : GridPointDataSimplePacking { - public class GridPointDataJpeg2000CodeStream : GridPointDataSimplePacking - { - /// Type compression method used (see Code Table 5.40000). - /// CompressionMethod - /// - public int CompressionMethod { get; } + /// Type compression method used (see Code Table 5.40000). + /// CompressionMethod + /// + public int CompressionMethod { get; } - /// Compression ratio used . - /// CompressionRatio - /// - public int CompressionRatio { get; } + /// Compression ratio used . + /// CompressionRatio + /// + public int CompressionRatio { get; } - internal GridPointDataJpeg2000CodeStream(BufferedBinaryReader reader) : base(reader) - { - CompressionMethod = reader.ReadUInt8(); + internal GridPointDataJpeg2000CodeStream(BufferedBinaryReader reader) : base(reader) + { + CompressionMethod = reader.ReadUInt8(); - CompressionRatio = reader.ReadUInt8(); - } + CompressionRatio = reader.ReadUInt8(); + } - private protected override IEnumerable DoEnumerateDataValues(BufferedBinaryReader reader, DataSection dataSection, long dataPointsNumber) - { - var data = reader.Read((int) dataSection.DataLength); - var img = J2kImage.FromBytes(data); + private protected override IEnumerable DoEnumerateDataValues(BufferedBinaryReader reader, DataSection dataSection, long dataPointsNumber) + { + var data = reader.Read((int) dataSection.DataLength); + var img = J2kImage.FromBytes(data); - if (img.NumberOfComponents <= 0) - { - return new float[0]; - } + if (img.NumberOfComponents <= 0) + { + return new double[0]; + } - var values = img.GetComponent(0); + var values = img.GetComponent(0); - return Unpack(values); - } - } + return Unpack(values); + } } \ No newline at end of file diff --git a/src/NGrib/Grib2/Templates/DataRepresentations/50002_GridPointDataEcmwfSecondOrderPacking.cs b/src/NGrib/Grib2/Templates/DataRepresentations/50002_GridPointDataEcmwfSecondOrderPacking.cs index c620b09..9c2a4d5 100644 --- a/src/NGrib/Grib2/Templates/DataRepresentations/50002_GridPointDataEcmwfSecondOrderPacking.cs +++ b/src/NGrib/Grib2/Templates/DataRepresentations/50002_GridPointDataEcmwfSecondOrderPacking.cs @@ -25,224 +25,221 @@ */ using NGrib.Grib2.Sections; -using System; -using System.Collections.Generic; using System.Collections.Immutable; -namespace NGrib.Grib2.Templates.DataRepresentations +namespace NGrib.Grib2.Templates.DataRepresentations; + +/// +/// Data Representation Template 5.0: Grid point data - second order packing +/// +/// +/// https://apps.ecmwf.int/codes/grib/format/grib2/templates/5/50002 +/// +public class GridPointDataEcmwfSecondOrderPacking : DataRepresentation { - /// - /// Data Representation Template 5.0: Grid point data - second order packing - /// - /// - /// https://apps.ecmwf.int/codes/grib/format/grib2/templates/5/50002 - /// - public class GridPointDataEcmwfSecondOrderPacking : DataRepresentation - { - /// - /// Reference value (R) . - /// - public float ReferenceValue { get; } - - /// - /// Binary scale factor (E). - /// - public int BinaryScaleFactor { get; } - - /// - /// Decimal scale factor (D). - /// - public int DecimalScaleFactor { get; } - - /// - /// Number of bits used for each packed value. - /// - public int NumberOfBits { get; } - - /// - /// Width of first order values - /// - public int WidthOfFirstOrderValues { get; } - - /// - /// Number of groups - /// - public long P1 { get; } - - /// - /// Number of second order packed values - /// - public long P2 { get; } - - /// - /// Width of widths - /// - public int WidthOfWidths { get; } - - /// - /// Width of lengths - /// - public int WidthOfLengths { get; } - - /// - /// Ordering flags (Flag table 5.50002) - /// - public int SecondOrderFlags { get; } - - /// - /// Order of spatial differencing - /// - public int OrderOfSpd { get; } - - /// - /// Width of spatial differencing - /// - public int WidthOfSpd { get; } - - /// - /// SPD - /// - public IReadOnlyList Spd { get; } - - internal GridPointDataEcmwfSecondOrderPacking(BufferedBinaryReader reader) - { - ReferenceValue = reader.ReadSingle(); - BinaryScaleFactor = reader.ReadInt16(); - DecimalScaleFactor = reader.ReadInt16(); - NumberOfBits = reader.ReadUInt8(); - - WidthOfFirstOrderValues = reader.ReadUInt8(); - P1 = reader.ReadUInt32(); - P2 = reader.ReadUInt32(); - WidthOfWidths = reader.ReadUInt8(); - WidthOfLengths = reader.ReadUInt8(); - SecondOrderFlags = reader.ReadUInt8(); - OrderOfSpd = reader.ReadUInt8(); - WidthOfSpd = reader.ReadUInt8(); - var spdA = new int [OrderOfSpd + 1]; - - reader.NextUIntN(); - for (var i = 0; i < OrderOfSpd; i++) - { - spdA[i] = reader.ReadUIntN(WidthOfSpd); - } - - spdA[OrderOfSpd] = reader.ReadIntN(WidthOfSpd); - Spd = spdA.ToImmutableList(); - } - - private protected override IEnumerable DoEnumerateDataValues(BufferedBinaryReader reader, DataSection dataSection, long dataPointsNumber) - { - // Implementation based on NetCDF-Java - // https://github.com/Unidata/netcdf-java/blob/v5.4.2/grib/src/main/java/ucar/nc2/grib/grib2/Grib2DataReader.java#L972 - reader.NextUIntN(); - var groupWidth = new int[P1]; - for (var i = 0; i < P1; i++) - { - groupWidth[i] = reader.ReadUIntN(WidthOfWidths); - } - - reader.NextUIntN(); - var groupLength = new int[P1]; - for (var i = 0; i < P1; i++) - { - groupLength[i] = reader.ReadUIntN(WidthOfLengths); - } - - reader.NextUIntN(); - var firstOrderValues = new int[P1]; - for (var i = 0; i < P1; i++) - { - firstOrderValues[i] = reader.ReadUIntN(WidthOfFirstOrderValues); - } - - var bias = 0; - if (OrderOfSpd > 0) - { - bias = Spd[OrderOfSpd]; - } - - reader.NextUIntN(); - var cnt = OrderOfSpd; - var data = new int[dataPointsNumber]; - for (var i = 0; i < P1; i++) - { - if (groupWidth[i] > 0) - { - for (var j = 0; j < groupLength[i]; j++) - { - data[cnt] = reader.ReadUIntN(groupWidth[i]); - data[cnt] += firstOrderValues[i]; - cnt++; - } - } - else - { - for (var j = 0; j < groupLength[i]; j++) - { - data[cnt] = firstOrderValues[i]; - cnt++; - } - } - } - - for (var i = 0; i < OrderOfSpd; i++) - { - data[i] = Spd[i]; - } - - int y, z, w; - switch (OrderOfSpd) - { - case 1: - y = data[0]; - for (var i = 1; i < dataPointsNumber; i++) - { - y += data[i] + bias; - data[i] = y; - } - - break; - case 2: - y = data[1] - data[0]; - z = data[1]; - for (var i = 2; i < dataPointsNumber; i++) - { - y += data[i] + bias; - z += y; - data[i] = z; - } - - break; - case 3: - y = data[2] - data[1]; - z = y - (data[1] - data[0]); - w = data[2]; - for (var i = 3; i < dataPointsNumber; i++) - { - z += data[i] + bias; - y += z; - w += y; - data[i] = w; - } - - break; - } - - var d = DecimalScaleFactor; - - var dd = Math.Pow(10, -d); - - var r = ReferenceValue; - - var e = BinaryScaleFactor; - - var ee = Math.Pow(2.0, e); - - for (var i = 0; i < dataPointsNumber; i++) - { - yield return (float)((data[i] * ee + r) * dd); - } - } - } + /// + /// Reference value (R) . + /// + public float ReferenceValue { get; } + + /// + /// Binary scale factor (E). + /// + public int BinaryScaleFactor { get; } + + /// + /// Decimal scale factor (D). + /// + public int DecimalScaleFactor { get; } + + /// + /// Number of bits used for each packed value. + /// + public int NumberOfBits { get; } + + /// + /// Width of first order values + /// + public int WidthOfFirstOrderValues { get; } + + /// + /// Number of groups + /// + public long P1 { get; } + + /// + /// Number of second order packed values + /// + public long P2 { get; } + + /// + /// Width of widths + /// + public int WidthOfWidths { get; } + + /// + /// Width of lengths + /// + public int WidthOfLengths { get; } + + /// + /// Ordering flags (Flag table 5.50002) + /// + public int SecondOrderFlags { get; } + + /// + /// Order of spatial differencing + /// + public int OrderOfSpd { get; } + + /// + /// Width of spatial differencing + /// + public int WidthOfSpd { get; } + + /// + /// SPD + /// + public IReadOnlyList Spd { get; } + + internal GridPointDataEcmwfSecondOrderPacking(BufferedBinaryReader reader) + { + ReferenceValue = reader.ReadSingle(); + BinaryScaleFactor = reader.ReadInt16(); + DecimalScaleFactor = reader.ReadInt16(); + NumberOfBits = reader.ReadUInt8(); + + WidthOfFirstOrderValues = reader.ReadUInt8(); + P1 = reader.ReadUInt32(); + P2 = reader.ReadUInt32(); + WidthOfWidths = reader.ReadUInt8(); + WidthOfLengths = reader.ReadUInt8(); + SecondOrderFlags = reader.ReadUInt8(); + OrderOfSpd = reader.ReadUInt8(); + WidthOfSpd = reader.ReadUInt8(); + var spdA = new int [OrderOfSpd + 1]; + + reader.NextUIntN(); + for (var i = 0; i < OrderOfSpd; i++) + { + spdA[i] = reader.ReadUIntN(WidthOfSpd); + } + + spdA[OrderOfSpd] = reader.ReadIntN(WidthOfSpd); + Spd = spdA.ToImmutableList(); + } + + private protected override IEnumerable DoEnumerateDataValues(BufferedBinaryReader reader, DataSection dataSection, long dataPointsNumber) + { + // Implementation based on NetCDF-Java + // https://github.com/Unidata/netcdf-java/blob/v5.4.2/grib/src/main/java/ucar/nc2/grib/grib2/Grib2DataReader.java#L972 + reader.NextUIntN(); + var groupWidth = new int[P1]; + for (var i = 0; i < P1; i++) + { + groupWidth[i] = reader.ReadUIntN(WidthOfWidths); + } + + reader.NextUIntN(); + var groupLength = new int[P1]; + for (var i = 0; i < P1; i++) + { + groupLength[i] = reader.ReadUIntN(WidthOfLengths); + } + + reader.NextUIntN(); + var firstOrderValues = new int[P1]; + for (var i = 0; i < P1; i++) + { + firstOrderValues[i] = reader.ReadUIntN(WidthOfFirstOrderValues); + } + + var bias = 0; + if (OrderOfSpd > 0) + { + bias = Spd[OrderOfSpd]; + } + + reader.NextUIntN(); + var cnt = OrderOfSpd; + var data = new int[dataPointsNumber]; + for (var i = 0; i < P1; i++) + { + if (groupWidth[i] > 0) + { + for (var j = 0; j < groupLength[i]; j++) + { + data[cnt] = reader.ReadUIntN(groupWidth[i]); + data[cnt] += firstOrderValues[i]; + cnt++; + } + } + else + { + for (var j = 0; j < groupLength[i]; j++) + { + data[cnt] = firstOrderValues[i]; + cnt++; + } + } + } + + for (var i = 0; i < OrderOfSpd; i++) + { + data[i] = Spd[i]; + } + + int y, z, w; + switch (OrderOfSpd) + { + case 1: + y = data[0]; + for (var i = 1; i < dataPointsNumber; i++) + { + y += data[i] + bias; + data[i] = y; + } + + break; + case 2: + y = data[1] - data[0]; + z = data[1]; + for (var i = 2; i < dataPointsNumber; i++) + { + y += data[i] + bias; + z += y; + data[i] = z; + } + + break; + case 3: + y = data[2] - data[1]; + z = y - (data[1] - data[0]); + w = data[2]; + for (var i = 3; i < dataPointsNumber; i++) + { + z += data[i] + bias; + y += z; + w += y; + data[i] = w; + } + + break; + } + + var d = DecimalScaleFactor; + + var dd = Math.Pow(10, -d); + + var r = ReferenceValue; + + var e = BinaryScaleFactor; + + var ee = Math.Pow(2.0, e); + + for (var i = 0; i < dataPointsNumber; i++) + { + yield return (float)((data[i] * ee + r) * dd); + } + } } \ No newline at end of file diff --git a/src/NGrib/Grib2/Templates/DataRepresentations/DataRepresentation.cs b/src/NGrib/Grib2/Templates/DataRepresentations/DataRepresentation.cs index bcd3d01..3213f2b 100644 --- a/src/NGrib/Grib2/Templates/DataRepresentations/DataRepresentation.cs +++ b/src/NGrib/Grib2/Templates/DataRepresentations/DataRepresentation.cs @@ -18,19 +18,16 @@ */ using NGrib.Grib2.Sections; -using System.Collections.Generic; -using System.IO; -namespace NGrib.Grib2.Templates.DataRepresentations +namespace NGrib.Grib2.Templates.DataRepresentations; + +public abstract class DataRepresentation { - public abstract class DataRepresentation - { - internal IEnumerable EnumerateDataValues(BufferedBinaryReader reader, DataSection dataSection, long dataPointsNumber) - { - reader.Seek(dataSection.DataOffset, SeekOrigin.Begin); - return DoEnumerateDataValues(reader, dataSection, dataPointsNumber); - } + internal IEnumerable EnumerateDataValues(BufferedBinaryReader reader, DataSection dataSection, long dataPointsNumber) + { + reader.Seek(dataSection.DataOffset, SeekOrigin.Begin); + return DoEnumerateDataValues(reader, dataSection, dataPointsNumber); + } - private protected abstract IEnumerable DoEnumerateDataValues(BufferedBinaryReader reader, DataSection dataSection, long dataPointsNumber); - } + private protected abstract IEnumerable DoEnumerateDataValues(BufferedBinaryReader reader, DataSection dataSection, long dataPointsNumber); } \ No newline at end of file diff --git a/src/NGrib/Grib2/Templates/GridDefinitions/0000_LatLonGridDefinition.cs b/src/NGrib/Grib2/Templates/GridDefinitions/0000_LatLonGridDefinition.cs index a8acd89..a3d2cac 100644 --- a/src/NGrib/Grib2/Templates/GridDefinitions/0000_LatLonGridDefinition.cs +++ b/src/NGrib/Grib2/Templates/GridDefinitions/0000_LatLonGridDefinition.cs @@ -24,123 +24,120 @@ * along with NGrib. If not, see . */ -using System; -using System.Collections.Generic; using System.Diagnostics; using NGrib.Grib2.CodeTables; -namespace NGrib.Grib2.Templates.GridDefinitions +namespace NGrib.Grib2.Templates.GridDefinitions; + +public class LatLonGridDefinition : XyEarthGridDefinition { - public class LatLonGridDefinition : XyEarthGridDefinition - { - /// - /// Basic angle of the initial production domain. - /// - public long Angle { get; } - - /// - /// Subdivisions of basic angle used to define extreme longitudes and latitudes, and direction increments. - /// - public long SubdivisionsAngle { get; } - - /// - /// Latitude of first grid point. - /// - public double La1 { get; } - - /// - /// Longitude of first grid point. - /// - public double Lo1 { get; } - - /// - /// Resolution and component flags value. - /// - public ResolutionAndComponent ResolutionAndComponent { get; } - - /// - /// Latitude of last grid point. - /// - public double La2 { get; } - - /// - /// Longitude of last grid point. - /// - public double Lo2 { get; } - - /// - /// X-direction increment. - /// - public double Dx { get; } - - /// - /// Y-direction increment. - /// - public double Dy { get; } - - /// - /// Scanning mode. - /// - public int ScanMode { get; } - - internal LatLonGridDefinition(BufferedBinaryReader reader) : base(reader) - { - Angle = reader.ReadUInt32(); - SubdivisionsAngle = reader.ReadUInt32(); - double ratio; - if (Angle == 0) - { - ratio = 1e-6; - } - else - { - ratio = Angle / (double) SubdivisionsAngle; - } - - La1 = reader.ReadInt32() * ratio; - Lo1 = reader.ReadInt32() * ratio; - ResolutionAndComponent = (ResolutionAndComponent) reader.ReadUInt8(); - La2 = reader.ReadInt32() * ratio; - Lo2 = reader.ReadInt32() * ratio; - Dx = reader.ReadInt32() * ratio; - Dy = reader.ReadInt32() * ratio; - ScanMode = reader.ReadUInt8(); - } - - public override IEnumerable EnumerateGridPoints() - { - var scanningMode = (ScanningMode) ScanMode; - var resolution = ResolutionAndComponent; - - if (resolution != (ResolutionAndComponent.JDirectionIncrementGiven | ResolutionAndComponent.IDirectionIncrementGiven) || - (scanningMode & ~(ScanningMode.ScanJPositive | ScanningMode.ScanIReverse)) != ScanningMode.Default) - { - throw new NotImplementedException(); - } - - var firstGridPoint = new Coordinate(La1, Lo1); - var lastGridPoint = new Coordinate(La2, Lo2); - - var xStep = Dx * (scanningMode.HasFlag(ScanningMode.ScanIReverse) ? -1 : 1); - var yStep = Dy * (scanningMode.HasFlag(ScanningMode.ScanJPositive) ? 1 : -1); - var currentGridPoint = firstGridPoint; - - // Adjacent points in x direction are consecutive - var latitudeOffset = 0d; - for (var y = 0; y < Ny; y++) - { - var longitudeOffset = 0d; - for (var x = 0; x < Nx; x++) - { - currentGridPoint = firstGridPoint.Add(latitudeOffset, longitudeOffset); - yield return currentGridPoint; - - longitudeOffset += xStep; - } - latitudeOffset += yStep; - } - - Debug.Assert(lastGridPoint.Equals(currentGridPoint)); - } - } + /// + /// Basic angle of the initial production domain. + /// + public long Angle { get; } + + /// + /// Subdivisions of basic angle used to define extreme longitudes and latitudes, and direction increments. + /// + public long SubdivisionsAngle { get; } + + /// + /// Latitude of first grid point. + /// + public double La1 { get; } + + /// + /// Longitude of first grid point. + /// + public double Lo1 { get; } + + /// + /// Resolution and component flags value. + /// + public ResolutionAndComponent ResolutionAndComponent { get; } + + /// + /// Latitude of last grid point. + /// + public double La2 { get; } + + /// + /// Longitude of last grid point. + /// + public double Lo2 { get; } + + /// + /// X-direction increment. + /// + public double Dx { get; } + + /// + /// Y-direction increment. + /// + public double Dy { get; } + + /// + /// Scanning mode. + /// + public int ScanMode { get; } + + internal LatLonGridDefinition(BufferedBinaryReader reader) : base(reader) + { + Angle = reader.ReadUInt32(); + SubdivisionsAngle = reader.ReadUInt32(); + double ratio; + if (Angle == 0) + { + ratio = 1e-6; + } + else + { + ratio = Angle / (double) SubdivisionsAngle; + } + + La1 = reader.ReadInt32() * ratio; + Lo1 = reader.ReadInt32() * ratio; + ResolutionAndComponent = (ResolutionAndComponent) reader.ReadUInt8(); + La2 = reader.ReadInt32() * ratio; + Lo2 = reader.ReadInt32() * ratio; + Dx = reader.ReadInt32() * ratio; + Dy = reader.ReadInt32() * ratio; + ScanMode = reader.ReadUInt8(); + } + + public override IEnumerable EnumerateGridPoints() + { + var scanningMode = (ScanningMode) ScanMode; + var resolution = ResolutionAndComponent; + + if (resolution != (ResolutionAndComponent.JDirectionIncrementGiven | ResolutionAndComponent.IDirectionIncrementGiven) || + (scanningMode & ~(ScanningMode.ScanJPositive | ScanningMode.ScanIReverse)) != ScanningMode.Default) + { + throw new NotImplementedException(); + } + + var firstGridPoint = new Coordinate(La1, Lo1); + var lastGridPoint = new Coordinate(La2, Lo2); + + var xStep = Dx * (scanningMode.HasFlag(ScanningMode.ScanIReverse) ? -1 : 1); + var yStep = Dy * (scanningMode.HasFlag(ScanningMode.ScanJPositive) ? 1 : -1); + var currentGridPoint = firstGridPoint; + + // Adjacent points in x direction are consecutive + var latitudeOffset = 0d; + for (var y = 0; y < Ny; y++) + { + var longitudeOffset = 0d; + for (var x = 0; x < Nx; x++) + { + currentGridPoint = firstGridPoint.Add(latitudeOffset, longitudeOffset); + yield return currentGridPoint; + + longitudeOffset += xStep; + } + latitudeOffset += yStep; + } + + Debug.Assert(lastGridPoint.Equals(currentGridPoint)); + } } \ No newline at end of file diff --git a/src/NGrib/Grib2/Templates/GridDefinitions/0001_RotatedLatLon.cs b/src/NGrib/Grib2/Templates/GridDefinitions/0001_RotatedLatLon.cs index 28f9ffa..df4da9c 100644 --- a/src/NGrib/Grib2/Templates/GridDefinitions/0001_RotatedLatLon.cs +++ b/src/NGrib/Grib2/Templates/GridDefinitions/0001_RotatedLatLon.cs @@ -24,33 +24,32 @@ * along with NGrib. If not, see . */ -namespace NGrib.Grib2.Templates.GridDefinitions +namespace NGrib.Grib2.Templates.GridDefinitions; + +public class RotatedLatLonGridDefinition : LatLonGridDefinition { - public class RotatedLatLonGridDefinition : LatLonGridDefinition - { - /// . - /// SpLat as a float - /// - /// - public float SpLat { get; } + /// . + /// SpLat as a float + /// + /// + public float SpLat { get; } - /// . - /// SpLon as a float - /// - /// - public float SpLon { get; } + /// . + /// SpLon as a float + /// + /// + public float SpLon { get; } - /// . - /// Rotationangle as a float - /// - /// - public float Rotationangle { get; } + /// . + /// Rotationangle as a float + /// + /// + public float Rotationangle { get; } - internal RotatedLatLonGridDefinition(BufferedBinaryReader reader) : base(reader) - { - SpLat = reader.ReadInt32() * 1e-6f; - SpLon = reader.ReadUInt32() * 1e-6f; - Rotationangle = reader.ReadSingle(); - } - } + internal RotatedLatLonGridDefinition(BufferedBinaryReader reader) : base(reader) + { + SpLat = reader.ReadInt32() * 1e-6f; + SpLon = reader.ReadUInt32() * 1e-6f; + Rotationangle = reader.ReadSingle(); + } } \ No newline at end of file diff --git a/src/NGrib/Grib2/Templates/GridDefinitions/0002_StretchedLatLonGridDefinition.cs b/src/NGrib/Grib2/Templates/GridDefinitions/0002_StretchedLatLonGridDefinition.cs index b27fcff..dbbba37 100644 --- a/src/NGrib/Grib2/Templates/GridDefinitions/0002_StretchedLatLonGridDefinition.cs +++ b/src/NGrib/Grib2/Templates/GridDefinitions/0002_StretchedLatLonGridDefinition.cs @@ -24,34 +24,33 @@ * along with NGrib. If not, see . */ -namespace NGrib.Grib2.Templates.GridDefinitions +namespace NGrib.Grib2.Templates.GridDefinitions; + +public class StretchedLatLonGridDefinition : LatLonGridDefinition { - public class StretchedLatLonGridDefinition : LatLonGridDefinition - { - /// . - /// PoleLat as a float - /// - /// - public float PoleLat { get; } + /// . + /// PoleLat as a float + /// + /// + public float PoleLat { get; } - /// . - /// PoleLon as a float - /// - /// - public float PoleLon { get; } + /// . + /// PoleLon as a float + /// + /// + public float PoleLon { get; } - /// . - /// Factor as a float - /// - /// - public float Factor { get; } + /// . + /// Factor as a float + /// + /// + public float Factor { get; } - internal StretchedLatLonGridDefinition(BufferedBinaryReader reader) : base(reader) - { - //Stretched Latitude/longitude - PoleLat = reader.ReadInt32() * 1e-6f; - PoleLon = reader.ReadUInt32() * 1e-6f; - Factor = reader.ReadUInt32(); - } - } + internal StretchedLatLonGridDefinition(BufferedBinaryReader reader) : base(reader) + { + //Stretched Latitude/longitude + PoleLat = reader.ReadInt32() * 1e-6f; + PoleLon = reader.ReadUInt32() * 1e-6f; + Factor = reader.ReadUInt32(); + } } \ No newline at end of file diff --git a/src/NGrib/Grib2/Templates/GridDefinitions/0003_StretchedRotatedLatLonGridDefinition.cs b/src/NGrib/Grib2/Templates/GridDefinitions/0003_StretchedRotatedLatLonGridDefinition.cs index 1fe58a0..18c2b62 100644 --- a/src/NGrib/Grib2/Templates/GridDefinitions/0003_StretchedRotatedLatLonGridDefinition.cs +++ b/src/NGrib/Grib2/Templates/GridDefinitions/0003_StretchedRotatedLatLonGridDefinition.cs @@ -24,35 +24,34 @@ * along with NGrib. If not, see . */ -namespace NGrib.Grib2.Templates.GridDefinitions +namespace NGrib.Grib2.Templates.GridDefinitions; + +public class StretchedRotatedLatLonGridDefinition : RotatedLatLonGridDefinition { - public class StretchedRotatedLatLonGridDefinition : RotatedLatLonGridDefinition - { - /// . - /// PoleLat as a float - /// - /// - public float PoleLat { get; } + /// . + /// PoleLat as a float + /// + /// + public float PoleLat { get; } - /// . - /// PoleLon as a float - /// - /// - public float PoleLon { get; } + /// . + /// PoleLon as a float + /// + /// + public float PoleLon { get; } - /// . - /// Factor as a float - /// - /// - public float Factor { get; } + /// . + /// Factor as a float + /// + /// + public float Factor { get; } - internal StretchedRotatedLatLonGridDefinition(BufferedBinaryReader reader) : base(reader) - { - //Stretched and Rotated - // Latitude/longitude - PoleLat = reader.ReadInt32() * 1e-6f; - PoleLon = reader.ReadUInt32() * 1e-6f; - Factor = reader.ReadUInt32(); - } - } + internal StretchedRotatedLatLonGridDefinition(BufferedBinaryReader reader) : base(reader) + { + //Stretched and Rotated + // Latitude/longitude + PoleLat = reader.ReadInt32() * 1e-6f; + PoleLon = reader.ReadUInt32() * 1e-6f; + Factor = reader.ReadUInt32(); + } } \ No newline at end of file diff --git a/src/NGrib/Grib2/Templates/GridDefinitions/0010_MercatorGridDefinition.cs b/src/NGrib/Grib2/Templates/GridDefinitions/0010_MercatorGridDefinition.cs index c29199e..5ff31c8 100644 --- a/src/NGrib/Grib2/Templates/GridDefinitions/0010_MercatorGridDefinition.cs +++ b/src/NGrib/Grib2/Templates/GridDefinitions/0010_MercatorGridDefinition.cs @@ -24,69 +24,65 @@ * along with NGrib. If not, see . */ -using System; -using System.Collections.Generic; +namespace NGrib.Grib2.Templates.GridDefinitions; -namespace NGrib.Grib2.Templates.GridDefinitions +public class MercatorGridDefinition : GridPointEarthGridDefinition { - public class MercatorGridDefinition : GridPointEarthGridDefinition - { - /// . - /// Lad as a float - /// - /// - public double Lad { get; } + /// . + /// Lad as a float + /// + /// + public double Lad { get; } - /// . - /// La2 as a float - /// - /// - public double La2 { get; } + /// . + /// La2 as a float + /// + /// + public double La2 { get; } - /// . - /// Lo2 as a float - /// - /// - public double Lo2 { get; } + /// . + /// Lo2 as a float + /// + /// + public double Lo2 { get; } - /// Get scan mode. - /// - /// - /// scan mode - /// - public int ScanMode { get; } + /// Get scan mode. + /// + /// + /// scan mode + /// + public int ScanMode { get; } - /// . - /// Angle as a int - /// - /// - public long Angle { get; } + /// . + /// Angle as a int + /// + /// + public long Angle { get; } - /// Get x-increment/distance between two grid points. - /// - /// - /// x-increment - /// - public double Dx { get; } + /// Get x-increment/distance between two grid points. + /// + /// + /// x-increment + /// + public double Dx { get; } - /// Get y-increment/distance between two grid points. - /// - /// - /// y-increment - /// - public double Dy { get; } + /// Get y-increment/distance between two grid points. + /// + /// + /// y-increment + /// + public double Dy { get; } - internal MercatorGridDefinition(BufferedBinaryReader reader) : base(reader) - { - Lad = reader.ReadInt32() * 1e-6; - La2 = reader.ReadInt32() * 1e-6; - Lo2 = reader.ReadUInt32() * 1e-6; - ScanMode = reader.ReadUInt8(); - Angle = reader.ReadUInt32(); - Dx = reader.ReadUInt32() * 1e-3; - Dy = reader.ReadUInt32() * 1e-3; - } + internal MercatorGridDefinition(BufferedBinaryReader reader) : base(reader) + { + Lad = reader.ReadInt32() * 1e-6; + La2 = reader.ReadInt32() * 1e-6; + Lo2 = reader.ReadUInt32() * 1e-6; + ScanMode = reader.ReadUInt8(); + Angle = reader.ReadUInt32(); + Dx = reader.ReadUInt32() * 1e-3; + Dy = reader.ReadUInt32() * 1e-3; + } - public override IEnumerable EnumerateGridPoints() => throw new NotImplementedException(); - } + public override IEnumerable EnumerateGridPoints() => throw new NotImplementedException(); } \ No newline at end of file diff --git a/src/NGrib/Grib2/Templates/GridDefinitions/0020_PolarStereographicProjectionGridDefinition.cs b/src/NGrib/Grib2/Templates/GridDefinitions/0020_PolarStereographicProjectionGridDefinition.cs index 5d5b67b..ad5324b 100644 --- a/src/NGrib/Grib2/Templates/GridDefinitions/0020_PolarStereographicProjectionGridDefinition.cs +++ b/src/NGrib/Grib2/Templates/GridDefinitions/0020_PolarStereographicProjectionGridDefinition.cs @@ -24,62 +24,58 @@ * along with NGrib. If not, see . */ -using System; -using System.Collections.Generic; +namespace NGrib.Grib2.Templates.GridDefinitions; -namespace NGrib.Grib2.Templates.GridDefinitions +public class PolarStereographicProjectionGridDefinition : GridPointEarthGridDefinition { - public class PolarStereographicProjectionGridDefinition : GridPointEarthGridDefinition - { - /// . - /// Lad as a float - /// - /// - public double Lad { get; } + /// . + /// Lad as a float + /// + /// + public double Lad { get; } - /// . - /// Lov as a float - /// - /// - public double Lov { get; } + /// . + /// Lov as a float + /// + /// + public double Lov { get; } - /// Get x-increment/distance between two grid points. - /// - /// - /// x-increment - /// - public double Dx { get; } + /// Get x-increment/distance between two grid points. + /// + /// + /// x-increment + /// + public double Dx { get; } - /// Get y-increment/distance between two grid points. - /// - /// - /// y-increment - /// - public double Dy { get; } + /// Get y-increment/distance between two grid points. + /// + /// + /// y-increment + /// + public double Dy { get; } - /// . - /// ProjectionCenter as a int - /// - /// - public int ProjectionCenter { get; } + /// . + /// ProjectionCenter as a int + /// + /// + public int ProjectionCenter { get; } - /// Get scan mode. - /// - /// - /// scan mode - /// - public int ScanMode { get; } + /// Get scan mode. + /// + /// + /// scan mode + /// + public int ScanMode { get; } - internal PolarStereographicProjectionGridDefinition(BufferedBinaryReader reader) : base(reader) - { - Lad = reader.ReadInt32() * 1e-6; - Lov = reader.ReadUInt32() * 1e-6; - Dx = reader.ReadUInt32() * 1e-3; - Dy = reader.ReadUInt32() * 1e-3; - ProjectionCenter = reader.ReadUInt8(); - ScanMode = reader.ReadUInt8(); - } + internal PolarStereographicProjectionGridDefinition(BufferedBinaryReader reader) : base(reader) + { + Lad = reader.ReadInt32() * 1e-6; + Lov = reader.ReadUInt32() * 1e-6; + Dx = reader.ReadUInt32() * 1e-3; + Dy = reader.ReadUInt32() * 1e-3; + ProjectionCenter = reader.ReadUInt8(); + ScanMode = reader.ReadUInt8(); + } - public override IEnumerable EnumerateGridPoints() => throw new NotImplementedException(); - } + public override IEnumerable EnumerateGridPoints() => throw new NotImplementedException(); } \ No newline at end of file diff --git a/src/NGrib/Grib2/Templates/GridDefinitions/0030_LambertConformalGridDefinition.cs b/src/NGrib/Grib2/Templates/GridDefinitions/0030_LambertConformalGridDefinition.cs index 19a7325..308cf4d 100644 --- a/src/NGrib/Grib2/Templates/GridDefinitions/0030_LambertConformalGridDefinition.cs +++ b/src/NGrib/Grib2/Templates/GridDefinitions/0030_LambertConformalGridDefinition.cs @@ -24,41 +24,40 @@ * along with NGrib. If not, see . */ -namespace NGrib.Grib2.Templates.GridDefinitions +namespace NGrib.Grib2.Templates.GridDefinitions; + +public class LambertConformalGridDefinition : PolarStereographicProjectionGridDefinition { - public class LambertConformalGridDefinition : PolarStereographicProjectionGridDefinition - { - /// . - /// Latin1 as a float - /// - /// - public float Latin1 { get; } + /// . + /// Latin1 as a float + /// + /// + public float Latin1 { get; } - /// . - /// Latin2 as a float - /// - /// - public float Latin2 { get; } + /// . + /// Latin2 as a float + /// + /// + public float Latin2 { get; } - /// . - /// SpLat as a float - /// - /// - public float SpLat { get; } + /// . + /// SpLat as a float + /// + /// + public float SpLat { get; } - /// . - /// SpLon as a float - /// - /// - public float SpLon { get; } + /// . + /// SpLon as a float + /// + /// + public float SpLon { get; } - internal LambertConformalGridDefinition(BufferedBinaryReader reader) : base(reader) - { - Latin1 = reader.ReadUInt32() * 1e-6f; - Latin2 = reader.ReadUInt32() * 1e-6f; + internal LambertConformalGridDefinition(BufferedBinaryReader reader) : base(reader) + { + Latin1 = reader.ReadUInt32() * 1e-6f; + Latin2 = reader.ReadUInt32() * 1e-6f; - SpLat = reader.ReadInt32() * 1e-6f; - SpLon = reader.ReadUInt32() * 1e-6f; - } - } + SpLat = reader.ReadInt32() * 1e-6f; + SpLon = reader.ReadUInt32() * 1e-6f; + } } \ No newline at end of file diff --git a/src/NGrib/Grib2/Templates/GridDefinitions/0031_AlbersEqualAreaGridDefinition.cs b/src/NGrib/Grib2/Templates/GridDefinitions/0031_AlbersEqualAreaGridDefinition.cs index 8e1fdd7..78ae9dd 100644 --- a/src/NGrib/Grib2/Templates/GridDefinitions/0031_AlbersEqualAreaGridDefinition.cs +++ b/src/NGrib/Grib2/Templates/GridDefinitions/0031_AlbersEqualAreaGridDefinition.cs @@ -24,12 +24,11 @@ * along with NGrib. If not, see . */ -namespace NGrib.Grib2.Templates.GridDefinitions +namespace NGrib.Grib2.Templates.GridDefinitions; + +public class AlbersEqualAreaGridDefinition : LambertConformalGridDefinition { - public class AlbersEqualAreaGridDefinition : LambertConformalGridDefinition + internal AlbersEqualAreaGridDefinition(BufferedBinaryReader reader) : base(reader) { - internal AlbersEqualAreaGridDefinition(BufferedBinaryReader reader) : base(reader) - { - } } } \ No newline at end of file diff --git a/src/NGrib/Grib2/Templates/GridDefinitions/0040_GaussianLatLonGridDefinition.cs b/src/NGrib/Grib2/Templates/GridDefinitions/0040_GaussianLatLonGridDefinition.cs index 7004fbf..bf1a5b4 100644 --- a/src/NGrib/Grib2/Templates/GridDefinitions/0040_GaussianLatLonGridDefinition.cs +++ b/src/NGrib/Grib2/Templates/GridDefinitions/0040_GaussianLatLonGridDefinition.cs @@ -22,103 +22,252 @@ * * You should have received a copy of the GNU Lesser General Public License * along with NGrib. If not, see . + * + * Edited by reagafonov@yandex.ru + * Adopted from GribApi.Xp */ -using System; -using System.Collections.Generic; +using System.Data; +using NGrib.Helpers; + +namespace NGrib.Grib2.Templates.GridDefinitions; -namespace NGrib.Grib2.Templates.GridDefinitions +public class GaussianLatLonGridDefinition : XyEarthGridDefinition { - public class GaussianLatLonGridDefinition : XyEarthGridDefinition - { - protected double Ratio { get; } - - /// . - /// Angle as a int - /// - /// - public long Angle { get; } - - /// . - /// Subdivisionsangle as a int - /// - /// - public long Subdivisionsangle { get; } - - /// . - /// La1 as a float - /// - /// - public double La1 { get; } - - /// . - /// Lo1 as a float - /// - /// - public double Lo1 { get; } - - /// . - /// Resolution as a int - /// - /// - public int Resolution { get; } - - /// . - /// La2 as a float - /// - /// - public double La2 { get; } - - /// . - /// Lo2 as a float - /// - /// - public double Lo2 { get; } - - /// Get x-increment/distance between two grid points. - /// - /// - /// x-increment - /// - public double Dx { get; } - - /// Get y-increment/distance between two grid points. - /// - /// - /// y-increment - /// - public long N { get; } - - /// Get scan mode. - /// - /// - /// scan mode - /// - public int ScanMode { get; } - - internal GaussianLatLonGridDefinition(BufferedBinaryReader reader) : base(reader) - { - Angle = reader.ReadUInt32(); - Subdivisionsangle = reader.ReadUInt32(); - if (Angle == 0) - { - Ratio = 1e-6; - } - else - { - Ratio = Angle / (double)Subdivisionsangle; - } - - La1 = reader.ReadInt32() * Ratio; - Lo1 = reader.ReadInt32() * Ratio; - Resolution = reader.ReadUInt8(); - La2 = reader.ReadUInt32() * Ratio; - Lo2 = reader.ReadUInt32() * Ratio; - Dx = reader.ReadUInt32() * Ratio; - N = reader.ReadUInt32(); - ScanMode = reader.ReadUInt8(); - } - - public override IEnumerable EnumerateGridPoints() => throw new NotImplementedException(); - } + private const long Maxiter = 1000; + + private const double MPi = Math.PI; + + private static readonly double[] GaussValues; + protected double Ratio { get; } + + /// . + /// Angle as a int + /// + /// + public long Angle { get; } + + /// . + /// Subdivisionsangle as a int + /// + /// + public long Subdivisionsangle { get; } + + /// . + /// La1 as a double + /// + /// + public double La1 { get; } + + /// . + /// Lo1 as a double + /// + /// + public double Lo1 { get; } + + /// . + /// Resolution as a int + /// + /// + public int Resolution { get; } + + /// . + /// La2 as a double + /// + /// + public double La2 { get; } + + /// . + /// Lo2 as a double + /// + /// + public double Lo2 { get; } + + /// Get x-increment/distance between two grid points. + /// + /// + /// x-increment + /// + public double Dx { get; } + + /// Number of latitudes in full grid. + /// + /// + /// + /// + public long N { get; } + + /// Get scan mode. + /// + /// + /// scan mode + /// + public ScanMode ScanMode { get; } + + public IEnumerable Latitudes { get; } + + static GaussianLatLonGridDefinition() + { + GaussValues = new[] + { + 2.4048255577E0, 5.5200781103E0, + 8.6537279129E0, 11.7915344391E0, 14.9309177086E0, + 18.0710639679E0, 21.2116366299E0, 24.3524715308E0, + 27.4934791320E0, 30.6346064684E0, 33.7758202136E0, + 36.9170983537E0, 40.0584257646E0, 43.1997917132E0, + 46.3411883717E0, 49.4826098974E0, 52.6240518411E0, + 55.7655107550E0, 58.9069839261E0, 62.0484691902E0, + 65.1899648002E0, 68.3314693299E0, 71.4729816036E0, + 74.6145006437E0, 77.7560256304E0, 80.8975558711E0, + 84.0390907769E0, 87.1806298436E0, 90.3221726372E0, + 93.4637187819E0, 96.6052679510E0, 99.7468198587E0, + 102.8883742542E0, 106.0299309165E0, 109.1714896498E0, + 112.3130502805E0, 115.4546126537E0, 118.5961766309E0, + 121.7377420880E0, 124.8793089132E0, 128.0208770059E0, + 131.1624462752E0, 134.3040166383E0, 137.4455880203E0, + 140.5871603528E0, 143.7287335737E0, 146.8703076258E0, + 150.0118824570E0, 153.1534580192E0, 156.2950342685E0 + }; + } + + + static void gauss_first_guess(long trunc, ref double[] vals) + { + long i, numVals; + + numVals = GaussValues.Length; + for (i = 0; i < trunc; i++) + { + if (i < numVals) + vals[i] = GaussValues[i]; + else + vals[i] = vals[i - 1] + MPi; + } + } + + internal GaussianLatLonGridDefinition(BufferedBinaryReader reader) : base(reader) + { + Angle = reader.ReadUInt32(); + Subdivisionsangle = reader.ReadUInt32(); + if (Angle == 0) + { + Ratio = 1e-6; + } + else + { + Ratio = (double)Angle / Subdivisionsangle; + } + + La1 = reader.ReadInt32() * Ratio; + Lo1 = reader.ReadInt32() * Ratio; + Resolution = reader.ReadUInt8(); + La2 = reader.ReadUInt32() * Ratio; + Lo2 = reader.ReadUInt32() * Ratio; + Dx = reader.ReadUInt32() * Ratio; + N = reader.ReadUInt32(); + + ScanMode = new ScanMode(reader.ReadUInt8()); + + var latitudes = new double[2 * N]; + grib_get_gaussian_latitudes(N, ref latitudes); + + var minLat = Math.Min(La1, La2); + + Latitudes = latitudes.OrderBy(x => x).SkipWhile(x => minLat > x).Take((int) Ny); + + if (minLat > La1) + Latitudes = Latitudes.Reverse(); + + Latitudes = Latitudes.ToList(); + } + + private void grib_get_gaussian_latitudes(long trunc, ref double[] lats) + { + long jlat; + long iter; + long legi; + double convval; + double root; + double legfonc = 0; + double mem1, mem2, conv; + double denom; + double precision = 1.0E-14; + long nlat = trunc * 2; + + var rad2deg = 180.0d / MPi; + + convval = (1.0d - ((2.0d / MPi) * (2.0d / MPi)) * 0.25d); + + gauss_first_guess(trunc, ref lats); + denom = Math.Sqrt(((nlat + 0.5d) * (nlat + 0.5d)) + convval); + + for (jlat = 0; jlat < trunc; jlat++) + { + /* First approximation for root */ + root = Math.Cos(lats[jlat] / denom); + + /* Perform loop of Newton iterations */ + iter = 0; + conv = 1; + + while (Math.Abs(conv) >= precision) + { + mem2 = 1.0; + mem1 = root; + + /* Compute Legendre polynomial */ + for (legi = 0; legi < nlat; legi++) + { + legfonc = ((2.0 * (legi + 1) - 1.0) * root * mem1 - legi * mem2) / (legi + 1); + mem2 = mem1; + mem1 = legfonc; + } + + /* Perform Newton iteration */ + conv = legfonc / ((nlat * (mem2 - root * legfonc)) / (1.0d - (root * root))); + root -= conv; + + /* Routine fails if no convergence after MAXITER iterations */ + if (iter++ > Maxiter) + { + throw new DataException("Non converge"); + } + } + + /* Set North and South values using symmetry */ + lats[jlat] = Math.Asin(root) * rad2deg; + lats[nlat - 1 - jlat] = -lats[jlat]; + } + + if (nlat != (trunc * 2)) + lats[trunc + 1] = 0.0; + } + + public override IEnumerable EnumerateGridPoints() + { + if (ScanMode.RowsZigzag || ScanMode.IsYDirectionOffset + || ScanMode.IsXDirectionEvenOffset || ScanMode.RowsNxNyPoints + || ScanMode.IsXDirectionOddRowsOffset + || ScanMode.IsXIncrement + || ScanMode.IsYIncrement + || ScanMode.IsNortherly + || Lo2<=Lo1) + throw new NotImplementedException(); + + var dx = (Lo2 - Lo1) / (Nx - 1); + return GetXConsecutiveCoordinates(dx); + } + + private IEnumerable GetXConsecutiveCoordinates(double dx) + { + foreach (var lat in Latitudes) + { + for (var x = 0; x < Nx; x++) + { + var lon = Lo1 + x * dx; + var coordinate = new Coordinate(lat, lon); + yield return coordinate; + } + } + } } \ No newline at end of file diff --git a/src/NGrib/Grib2/Templates/GridDefinitions/0041_RotatedGaussianLatLonGridDefinition.cs b/src/NGrib/Grib2/Templates/GridDefinitions/0041_RotatedGaussianLatLonGridDefinition.cs index 46be16d..e07fa75 100644 --- a/src/NGrib/Grib2/Templates/GridDefinitions/0041_RotatedGaussianLatLonGridDefinition.cs +++ b/src/NGrib/Grib2/Templates/GridDefinitions/0041_RotatedGaussianLatLonGridDefinition.cs @@ -24,33 +24,32 @@ * along with NGrib. If not, see . */ -namespace NGrib.Grib2.Templates.GridDefinitions +namespace NGrib.Grib2.Templates.GridDefinitions; + +public class RotatedGaussianLatLonGridDefinition : GaussianLatLonGridDefinition { - public class RotatedGaussianLatLonGridDefinition : GaussianLatLonGridDefinition - { - /// . - /// SpLat as a float - /// - /// - public double SpLat { get; } + /// . + /// SpLat as a float + /// + /// + public double SpLat { get; } - /// . - /// SpLon as a float - /// - /// - public double SpLon { get; } + /// . + /// SpLon as a float + /// + /// + public double SpLon { get; } - /// . - /// Rotationangle as a float - /// - /// - public long Rotationangle { get; } + /// . + /// Rotationangle as a float + /// + /// + public long Rotationangle { get; } - internal RotatedGaussianLatLonGridDefinition(BufferedBinaryReader reader) : base(reader) - { - SpLat = reader.ReadInt32() * Ratio; - SpLon = reader.ReadUInt32() * Ratio; - Rotationangle = reader.ReadUInt32(); - } - } + internal RotatedGaussianLatLonGridDefinition(BufferedBinaryReader reader) : base(reader) + { + SpLat = reader.ReadInt32() * Ratio; + SpLon = reader.ReadUInt32() * Ratio; + Rotationangle = reader.ReadUInt32(); + } } \ No newline at end of file diff --git a/src/NGrib/Grib2/Templates/GridDefinitions/0042_StretchedGaussianLatLonGridDefinition.cs b/src/NGrib/Grib2/Templates/GridDefinitions/0042_StretchedGaussianLatLonGridDefinition.cs index 6ddcddc..abb919b 100644 --- a/src/NGrib/Grib2/Templates/GridDefinitions/0042_StretchedGaussianLatLonGridDefinition.cs +++ b/src/NGrib/Grib2/Templates/GridDefinitions/0042_StretchedGaussianLatLonGridDefinition.cs @@ -24,33 +24,32 @@ * along with NGrib. If not, see . */ -namespace NGrib.Grib2.Templates.GridDefinitions +namespace NGrib.Grib2.Templates.GridDefinitions; + +public class StretchedGaussianLatLonGridDefinition : GaussianLatLonGridDefinition { - public class StretchedGaussianLatLonGridDefinition : GaussianLatLonGridDefinition - { - /// . - /// PoleLat as a float - /// - /// - public double PoleLat { get; } + /// . + /// PoleLat as a float + /// + /// + public double PoleLat { get; } - /// . - /// PoleLon as a float - /// - /// - public double PoleLon { get; } + /// . + /// PoleLon as a float + /// + /// + public double PoleLon { get; } - /// . - /// Factor as a float - /// - /// - public long Factor { get; } + /// . + /// Factor as a float + /// + /// + public long Factor { get; } - internal StretchedGaussianLatLonGridDefinition(BufferedBinaryReader reader) : base(reader) - { - PoleLat = reader.ReadInt32() * Ratio; - PoleLon = reader.ReadUInt32() * Ratio; - Factor = reader.ReadUInt32(); - } - } + internal StretchedGaussianLatLonGridDefinition(BufferedBinaryReader reader) : base(reader) + { + PoleLat = reader.ReadInt32() * Ratio; + PoleLon = reader.ReadUInt32() * Ratio; + Factor = reader.ReadUInt32(); + } } \ No newline at end of file diff --git a/src/NGrib/Grib2/Templates/GridDefinitions/0043_StretchedRotatedGaussianLatLonGridDefinition.cs b/src/NGrib/Grib2/Templates/GridDefinitions/0043_StretchedRotatedGaussianLatLonGridDefinition.cs index d799578..0daa88d 100644 --- a/src/NGrib/Grib2/Templates/GridDefinitions/0043_StretchedRotatedGaussianLatLonGridDefinition.cs +++ b/src/NGrib/Grib2/Templates/GridDefinitions/0043_StretchedRotatedGaussianLatLonGridDefinition.cs @@ -24,33 +24,32 @@ * along with NGrib. If not, see . */ -namespace NGrib.Grib2.Templates.GridDefinitions +namespace NGrib.Grib2.Templates.GridDefinitions; + +public class StretchedRotatedGaussianLatLonGridDefinition : RotatedGaussianLatLonGridDefinition { - public class StretchedRotatedGaussianLatLonGridDefinition : RotatedGaussianLatLonGridDefinition - { - /// . - /// PoleLat as a float - /// - /// - public double PoleLat { get; } + /// . + /// PoleLat as a float + /// + /// + public double PoleLat { get; } - /// . - /// PoleLon as a float - /// - /// - public double PoleLon { get; } + /// . + /// PoleLon as a float + /// + /// + public double PoleLon { get; } - /// . - /// Factor as a float - /// - /// - public long Factor { get; } + /// . + /// Factor as a float + /// + /// + public long Factor { get; } - internal StretchedRotatedGaussianLatLonGridDefinition(BufferedBinaryReader reader) : base(reader) - { - PoleLat = reader.ReadInt32() * Ratio; - PoleLon = reader.ReadUInt32() * Ratio; - Factor = reader.ReadUInt32(); - } - } + internal StretchedRotatedGaussianLatLonGridDefinition(BufferedBinaryReader reader) : base(reader) + { + PoleLat = reader.ReadInt32() * Ratio; + PoleLon = reader.ReadUInt32() * Ratio; + Factor = reader.ReadUInt32(); + } } \ No newline at end of file diff --git a/src/NGrib/Grib2/Templates/GridDefinitions/0050_SphericalHarmonicCoefficientsGridDefinition.cs b/src/NGrib/Grib2/Templates/GridDefinitions/0050_SphericalHarmonicCoefficientsGridDefinition.cs index d2e12eb..1405ad4 100644 --- a/src/NGrib/Grib2/Templates/GridDefinitions/0050_SphericalHarmonicCoefficientsGridDefinition.cs +++ b/src/NGrib/Grib2/Templates/GridDefinitions/0050_SphericalHarmonicCoefficientsGridDefinition.cs @@ -24,52 +24,48 @@ * along with NGrib. If not, see . */ -using System; -using System.Collections.Generic; +namespace NGrib.Grib2.Templates.GridDefinitions; -namespace NGrib.Grib2.Templates.GridDefinitions +public class SphericalHarmonicCoefficientsGridDefinition : GridDefinition { - public class SphericalHarmonicCoefficientsGridDefinition : GridDefinition - { - /// . - /// J as a float - /// - /// - public float J { get; } + /// . + /// J as a float + /// + /// + public float J { get; } - /// . - /// K as a float - /// - /// - public float K { get; } + /// . + /// K as a float + /// + /// + public float K { get; } - /// . - /// M as a float - /// - /// - public float M { get; } + /// . + /// M as a float + /// + /// + public float M { get; } - /// . - /// Method as a int - /// - /// - public int Method { get; } + /// . + /// Method as a int + /// + /// + public int Method { get; } - /// . - /// Mode as a int - /// - /// - public int Mode { get; } + /// . + /// Mode as a int + /// + /// + public int Mode { get; } - internal SphericalHarmonicCoefficientsGridDefinition(BufferedBinaryReader reader) : base(reader) - { - J = reader.ReadSingle(); - K = reader.ReadSingle(); - M = reader.ReadSingle(); - Method = reader.ReadUInt8(); - Mode = reader.ReadUInt8(); - } + internal SphericalHarmonicCoefficientsGridDefinition(BufferedBinaryReader reader) : base(reader) + { + J = reader.ReadSingle(); + K = reader.ReadSingle(); + M = reader.ReadSingle(); + Method = reader.ReadUInt8(); + Mode = reader.ReadUInt8(); + } - public override IEnumerable EnumerateGridPoints() => throw new NotImplementedException(); - } + public override IEnumerable EnumerateGridPoints() => throw new NotImplementedException(); } \ No newline at end of file diff --git a/src/NGrib/Grib2/Templates/GridDefinitions/0051_RotatedSphericalHarmonicCoefficientsGridDefinition.cs b/src/NGrib/Grib2/Templates/GridDefinitions/0051_RotatedSphericalHarmonicCoefficientsGridDefinition.cs index 080ba6c..2acd016 100644 --- a/src/NGrib/Grib2/Templates/GridDefinitions/0051_RotatedSphericalHarmonicCoefficientsGridDefinition.cs +++ b/src/NGrib/Grib2/Templates/GridDefinitions/0051_RotatedSphericalHarmonicCoefficientsGridDefinition.cs @@ -24,33 +24,32 @@ * along with NGrib. If not, see . */ -namespace NGrib.Grib2.Templates.GridDefinitions +namespace NGrib.Grib2.Templates.GridDefinitions; + +public class RotatedSphericalHarmonicCoefficientsGridDefinition : SphericalHarmonicCoefficientsGridDefinition { - public class RotatedSphericalHarmonicCoefficientsGridDefinition : SphericalHarmonicCoefficientsGridDefinition - { - /// . - /// SpLat as a float - /// - /// - public float SpLat { get; } + /// . + /// SpLat as a float + /// + /// + public float SpLat { get; } - /// . - /// SpLon as a float - /// - /// - public float SpLon { get; } + /// . + /// SpLon as a float + /// + /// + public float SpLon { get; } - /// . - /// Rotationangle as a float - /// - /// - public long Rotationangle { get; } + /// . + /// Rotationangle as a float + /// + /// + public long Rotationangle { get; } - internal RotatedSphericalHarmonicCoefficientsGridDefinition(BufferedBinaryReader reader) : base(reader) - { - SpLat = reader.ReadInt32() * 1e-6f; - SpLon = reader.ReadUInt32() * 1e-6f; - Rotationangle = reader.ReadUInt32(); - } - } + internal RotatedSphericalHarmonicCoefficientsGridDefinition(BufferedBinaryReader reader) : base(reader) + { + SpLat = reader.ReadInt32() * 1e-6f; + SpLon = reader.ReadUInt32() * 1e-6f; + Rotationangle = reader.ReadUInt32(); + } } \ No newline at end of file diff --git a/src/NGrib/Grib2/Templates/GridDefinitions/0052_StretchedSphericalHarmonicCoefficientsGridDefinition.cs b/src/NGrib/Grib2/Templates/GridDefinitions/0052_StretchedSphericalHarmonicCoefficientsGridDefinition.cs index 4bcc994..8ae28ab 100644 --- a/src/NGrib/Grib2/Templates/GridDefinitions/0052_StretchedSphericalHarmonicCoefficientsGridDefinition.cs +++ b/src/NGrib/Grib2/Templates/GridDefinitions/0052_StretchedSphericalHarmonicCoefficientsGridDefinition.cs @@ -24,33 +24,32 @@ * along with NGrib. If not, see . */ -namespace NGrib.Grib2.Templates.GridDefinitions +namespace NGrib.Grib2.Templates.GridDefinitions; + +public class StretchedSphericalHarmonicCoefficientsGridDefinition : SphericalHarmonicCoefficientsGridDefinition { - public class StretchedSphericalHarmonicCoefficientsGridDefinition : SphericalHarmonicCoefficientsGridDefinition - { - /// . - /// PoleLat as a float - /// - /// - public float PoleLat { get; } + /// . + /// PoleLat as a float + /// + /// + public float PoleLat { get; } - /// . - /// PoleLon as a float - /// - /// - public float PoleLon { get; } + /// . + /// PoleLon as a float + /// + /// + public float PoleLon { get; } - /// . - /// Factor as a float - /// - /// - public float Factor { get; } + /// . + /// Factor as a float + /// + /// + public float Factor { get; } - internal StretchedSphericalHarmonicCoefficientsGridDefinition(BufferedBinaryReader reader) : base(reader) - { - PoleLat = reader.ReadInt32() * 1e-6f; - PoleLon = reader.ReadUInt32() * 1e-6f; - Factor = reader.ReadSingle(); - } - } + internal StretchedSphericalHarmonicCoefficientsGridDefinition(BufferedBinaryReader reader) : base(reader) + { + PoleLat = reader.ReadInt32() * 1e-6f; + PoleLon = reader.ReadUInt32() * 1e-6f; + Factor = reader.ReadSingle(); + } } \ No newline at end of file diff --git a/src/NGrib/Grib2/Templates/GridDefinitions/0053_StretchedRotatedSphericalHarmonicCoefficientsGridDefinition.cs b/src/NGrib/Grib2/Templates/GridDefinitions/0053_StretchedRotatedSphericalHarmonicCoefficientsGridDefinition.cs index 9363961..bb5eefb 100644 --- a/src/NGrib/Grib2/Templates/GridDefinitions/0053_StretchedRotatedSphericalHarmonicCoefficientsGridDefinition.cs +++ b/src/NGrib/Grib2/Templates/GridDefinitions/0053_StretchedRotatedSphericalHarmonicCoefficientsGridDefinition.cs @@ -24,33 +24,32 @@ * along with NGrib. If not, see . */ -namespace NGrib.Grib2.Templates.GridDefinitions +namespace NGrib.Grib2.Templates.GridDefinitions; + +public class StretchedRotatedSphericalHarmonicCoefficientsGridDefinition : RotatedSphericalHarmonicCoefficientsGridDefinition { - public class StretchedRotatedSphericalHarmonicCoefficientsGridDefinition : RotatedSphericalHarmonicCoefficientsGridDefinition - { - /// . - /// PoleLat as a float - /// - /// - public float PoleLat { get; } + /// . + /// PoleLat as a float + /// + /// + public float PoleLat { get; } - /// . - /// PoleLon as a float - /// - /// - public float PoleLon { get; } + /// . + /// PoleLon as a float + /// + /// + public float PoleLon { get; } - /// . - /// Factor as a float - /// - /// - public float Factor { get; } + /// . + /// Factor as a float + /// + /// + public float Factor { get; } - internal StretchedRotatedSphericalHarmonicCoefficientsGridDefinition(BufferedBinaryReader reader) : base(reader) - { - PoleLat = reader.ReadInt32() * 1e-6f; - PoleLon = reader.ReadUInt32() * 1e-6f; - Factor = reader.ReadSingle(); - } - } + internal StretchedRotatedSphericalHarmonicCoefficientsGridDefinition(BufferedBinaryReader reader) : base(reader) + { + PoleLat = reader.ReadInt32() * 1e-6f; + PoleLon = reader.ReadUInt32() * 1e-6f; + Factor = reader.ReadSingle(); + } } \ No newline at end of file diff --git a/src/NGrib/Grib2/Templates/GridDefinitions/0090_SpaceViewPerspectiveOrOrthographicGridDefinition.cs b/src/NGrib/Grib2/Templates/GridDefinitions/0090_SpaceViewPerspectiveOrOrthographicGridDefinition.cs index 40bc503..65ae4a5 100644 --- a/src/NGrib/Grib2/Templates/GridDefinitions/0090_SpaceViewPerspectiveOrOrthographicGridDefinition.cs +++ b/src/NGrib/Grib2/Templates/GridDefinitions/0090_SpaceViewPerspectiveOrOrthographicGridDefinition.cs @@ -24,81 +24,77 @@ * along with NGrib. If not, see . */ -using System; -using System.Collections.Generic; +namespace NGrib.Grib2.Templates.GridDefinitions; -namespace NGrib.Grib2.Templates.GridDefinitions +public class SpaceViewPerspectiveOrOrthographicGridDefinition : XyEarthGridDefinition { - public class SpaceViewPerspectiveOrOrthographicGridDefinition : XyEarthGridDefinition - { - public long Lap { get; } - public long Lop { get; } - public long Xo { get; } - public long Yo { get; } - public long Altitude { get; } + public long Lap { get; } + public long Lop { get; } + public long Xo { get; } + public long Yo { get; } + public long Altitude { get; } - /// . - /// Resolution as a int - /// - /// - public int Resolution { get; } + /// . + /// Resolution as a int + /// + /// + public int Resolution { get; } - /// Get x-increment/distance between two grid points. - /// - /// - /// x-increment - /// - public float Dx { get; } + /// Get x-increment/distance between two grid points. + /// + /// + /// x-increment + /// + public float Dx { get; } - /// Get y-increment/distance between two grid points. - /// - /// - /// y-increment - /// - public float Dy { get; } + /// Get y-increment/distance between two grid points. + /// + /// + /// y-increment + /// + public float Dy { get; } - /// Get scan mode. - /// - /// - /// scan mode - /// - public int ScanMode { get; } + /// Get scan mode. + /// + /// + /// scan mode + /// + public int ScanMode { get; } - /// . - /// Xp as a float - /// - /// - public float Xp { get; } + /// . + /// Xp as a float + /// + /// + public float Xp { get; } - /// . - /// Yp as a float - /// - /// - public float Yp { get; } + /// . + /// Yp as a float + /// + /// + public float Yp { get; } - /// . - /// Angle as a int - /// - /// - public long Angle { get; } + /// . + /// Angle as a int + /// + /// + public long Angle { get; } - internal SpaceViewPerspectiveOrOrthographicGridDefinition(BufferedBinaryReader reader) : base(reader) - { - Lap = reader.ReadInt32(); - Lop = reader.ReadUInt32(); - Resolution = reader.ReadUInt8(); - Dx = reader.ReadUInt32(); - Dy = reader.ReadUInt32(); - Xp = reader.ReadUInt32() * 1e-3f; - Yp = reader.ReadUInt32() * 1e-3f; - ScanMode = reader.ReadUInt8(); - Angle = reader.ReadUInt32(); - Altitude = reader.ReadUInt32() * 1_000_000; - Xo = reader.ReadUInt32(); - Yo = reader.ReadUInt32(); - } + internal SpaceViewPerspectiveOrOrthographicGridDefinition(BufferedBinaryReader reader) : base(reader) + { + Lap = reader.ReadInt32(); + Lop = reader.ReadUInt32(); + Resolution = reader.ReadUInt8(); + Dx = reader.ReadUInt32(); + Dy = reader.ReadUInt32(); + Xp = reader.ReadUInt32() * 1e-3f; + Yp = reader.ReadUInt32() * 1e-3f; + ScanMode = reader.ReadUInt8(); + Angle = reader.ReadUInt32(); + Altitude = reader.ReadUInt32() * 1_000_000; + Xo = reader.ReadUInt32(); + Yo = reader.ReadUInt32(); + } - public override IEnumerable EnumerateGridPoints() => throw new NotImplementedException(); - } + public override IEnumerable EnumerateGridPoints() => throw new NotImplementedException(); } \ No newline at end of file diff --git a/src/NGrib/Grib2/Templates/GridDefinitions/0100_TriangularGridBasedOnAnIcosahedronGridDefinition.cs b/src/NGrib/Grib2/Templates/GridDefinitions/0100_TriangularGridBasedOnAnIcosahedronGridDefinition.cs index b3d2b64..f0cc308 100644 --- a/src/NGrib/Grib2/Templates/GridDefinitions/0100_TriangularGridBasedOnAnIcosahedronGridDefinition.cs +++ b/src/NGrib/Grib2/Templates/GridDefinitions/0100_TriangularGridBasedOnAnIcosahedronGridDefinition.cs @@ -24,91 +24,87 @@ * along with NGrib. If not, see . */ -using System; -using System.Collections.Generic; +namespace NGrib.Grib2.Templates.GridDefinitions; -namespace NGrib.Grib2.Templates.GridDefinitions +public class TriangularGridBasedOnAnIcosahedronGridDefinition : GridDefinition { - public class TriangularGridBasedOnAnIcosahedronGridDefinition : GridDefinition - { - /// . - /// N2 as a int - /// - /// - public int N2 { get; } + /// . + /// N2 as a int + /// + /// + public int N2 { get; } - /// . - /// N3 as a int - /// - /// - public int N3 { get; } + /// . + /// N3 as a int + /// + /// + public int N3 { get; } - /// . - /// Ni as a int - /// - /// - public int Ni { get; } + /// . + /// Ni as a int + /// + /// + public int Ni { get; } - /// . - /// Nd as a int - /// - /// - public int Nd { get; } + /// . + /// Nd as a int + /// + /// + public int Nd { get; } - /// . - /// PoleLat as a float - /// - /// - public float PoleLat { get; } + /// . + /// PoleLat as a float + /// + /// + public float PoleLat { get; } - /// . - /// PoleLon as a float - /// - /// - public float PoleLon { get; } + /// . + /// PoleLon as a float + /// + /// + public float PoleLon { get; } - public long Lonofcenter { get; } + public long Lonofcenter { get; } - /// . - /// Position as a int - /// - /// - public int Position { get; } + /// . + /// Position as a int + /// + /// + public int Position { get; } - /// . - /// Order as a int - /// - /// - public int Order { get; } + /// . + /// Order as a int + /// + /// + public int Order { get; } - /// Get scan mode. - /// - /// - /// scan mode - /// - public int ScanMode { get; } + /// Get scan mode. + /// + /// + /// scan mode + /// + public int ScanMode { get; } - /// . - /// N as a int - /// - /// - public long N { get; } + /// . + /// N as a int + /// + /// + public long N { get; } - internal TriangularGridBasedOnAnIcosahedronGridDefinition(BufferedBinaryReader reader) : base(reader) - { - N2 = reader.ReadUInt8(); - N3 = reader.ReadUInt8(); - Ni = reader.ReadUInt16(); - Nd = reader.ReadUInt8(); - PoleLat = reader.ReadInt32() * 1e-6f; - PoleLon = reader.ReadUInt32() * 1e-6f; - Lonofcenter = reader.ReadUInt32(); - Position = reader.ReadUInt8(); - Order = reader.ReadUInt8(); - ScanMode = reader.ReadUInt8(); - N = reader.ReadUInt32(); - } + internal TriangularGridBasedOnAnIcosahedronGridDefinition(BufferedBinaryReader reader) : base(reader) + { + N2 = reader.ReadUInt8(); + N3 = reader.ReadUInt8(); + Ni = reader.ReadUInt16(); + Nd = reader.ReadUInt8(); + PoleLat = reader.ReadInt32() * 1e-6f; + PoleLon = reader.ReadUInt32() * 1e-6f; + Lonofcenter = reader.ReadUInt32(); + Position = reader.ReadUInt8(); + Order = reader.ReadUInt8(); + ScanMode = reader.ReadUInt8(); + N = reader.ReadUInt32(); + } - public override IEnumerable EnumerateGridPoints() => throw new NotImplementedException(); - } + public override IEnumerable EnumerateGridPoints() => throw new NotImplementedException(); } \ No newline at end of file diff --git a/src/NGrib/Grib2/Templates/GridDefinitions/0110_EquatorialAzimuthalEquidistantProjectionGridDefinition.cs b/src/NGrib/Grib2/Templates/GridDefinitions/0110_EquatorialAzimuthalEquidistantProjectionGridDefinition.cs index f025c9a..371ff9c 100644 --- a/src/NGrib/Grib2/Templates/GridDefinitions/0110_EquatorialAzimuthalEquidistantProjectionGridDefinition.cs +++ b/src/NGrib/Grib2/Templates/GridDefinitions/0110_EquatorialAzimuthalEquidistantProjectionGridDefinition.cs @@ -24,48 +24,44 @@ * along with NGrib. If not, see . */ -using System; -using System.Collections.Generic; +namespace NGrib.Grib2.Templates.GridDefinitions; -namespace NGrib.Grib2.Templates.GridDefinitions +public class EquatorialAzimuthalEquidistantProjectionGridDefinition : GridPointEarthGridDefinition { - public class EquatorialAzimuthalEquidistantProjectionGridDefinition : GridPointEarthGridDefinition - { - /// Get x-increment/distance between two grid points. - /// - /// - /// x-increment - /// - public float Dx { get; } + /// Get x-increment/distance between two grid points. + /// + /// + /// x-increment + /// + public float Dx { get; } - /// Get y-increment/distance between two grid points. - /// - /// - /// y-increment - /// - public float Dy { get; } + /// Get y-increment/distance between two grid points. + /// + /// + /// y-increment + /// + public float Dy { get; } - /// Get scan mode. - /// - /// - /// scan mode - /// - public int ScanMode { get; } + /// Get scan mode. + /// + /// + /// scan mode + /// + public int ScanMode { get; } - /// . - /// ProjectionCenter as a int - /// - /// - public int ProjectionCenter { get; } + /// . + /// ProjectionCenter as a int + /// + /// + public int ProjectionCenter { get; } - internal EquatorialAzimuthalEquidistantProjectionGridDefinition(BufferedBinaryReader reader) : base(reader) - { - Dx = reader.ReadUInt32() * 1e-3f; - Dy = reader.ReadUInt32() * 1e-3f; - ProjectionCenter = reader.ReadUInt8(); - ScanMode = reader.ReadUInt8(); - } + internal EquatorialAzimuthalEquidistantProjectionGridDefinition(BufferedBinaryReader reader) : base(reader) + { + Dx = reader.ReadUInt32() * 1e-3f; + Dy = reader.ReadUInt32() * 1e-3f; + ProjectionCenter = reader.ReadUInt8(); + ScanMode = reader.ReadUInt8(); + } - public override IEnumerable EnumerateGridPoints() => throw new NotImplementedException(); - } + public override IEnumerable EnumerateGridPoints() => throw new NotImplementedException(); } \ No newline at end of file diff --git a/src/NGrib/Grib2/Templates/GridDefinitions/Earth.cs b/src/NGrib/Grib2/Templates/GridDefinitions/Earth.cs index a2b40cf..69bd201 100644 --- a/src/NGrib/Grib2/Templates/GridDefinitions/Earth.cs +++ b/src/NGrib/Grib2/Templates/GridDefinitions/Earth.cs @@ -17,53 +17,51 @@ * along with NGrib. If not, see . */ -using System; using NGrib.Grib2.CodeTables; -namespace NGrib.Grib2.Templates.GridDefinitions +namespace NGrib.Grib2.Templates.GridDefinitions; + +public abstract class Earth { - public abstract class Earth - { - public EarthShape Shape { get; } + public EarthShape Shape { get; } - protected Earth(int shapeCode) - { - Shape = shapeCode.As() ?? throw new ArgumentException("Unknown shape code.", nameof(shapeCode)); - } - } + protected Earth(int shapeCode) + { + Shape = shapeCode.As() ?? throw new ArgumentException("Unknown shape code.", nameof(shapeCode)); + } +} - public class SphericalEarth : Earth - { - /// . - /// EarthRadius as a float - /// - /// - public double Radius { get; } +public class SphericalEarth : Earth +{ + /// . + /// EarthRadius as a float + /// + /// + public double Radius { get; } - public SphericalEarth(int shapeCode, double radius) : base(shapeCode) - { - Radius = radius; - } - } + public SphericalEarth(int shapeCode, double radius) : base(shapeCode) + { + Radius = radius; + } +} - public class OblateSpheroidEarth : Earth - { - /// . - /// MajorAxis as a float - /// - /// - public double MajorAxis { get; } +public class OblateSpheroidEarth : Earth +{ + /// . + /// MajorAxis as a float + /// + /// + public double MajorAxis { get; } - /// . - /// MinorAxis as a float - /// - /// - public double MinorAxis { get; } + /// . + /// MinorAxis as a float + /// + /// + public double MinorAxis { get; } - public OblateSpheroidEarth(int shapeCode, double majorAxis, double minorAxis) : base(shapeCode) - { - MajorAxis = majorAxis; - MinorAxis = minorAxis; - } - } + public OblateSpheroidEarth(int shapeCode, double majorAxis, double minorAxis) : base(shapeCode) + { + MajorAxis = majorAxis; + MinorAxis = minorAxis; + } } \ No newline at end of file diff --git a/src/NGrib/Grib2/Templates/GridDefinitions/EarthGridDefinition.cs b/src/NGrib/Grib2/Templates/GridDefinitions/EarthGridDefinition.cs index 6df7dbb..2d94346 100644 --- a/src/NGrib/Grib2/Templates/GridDefinitions/EarthGridDefinition.cs +++ b/src/NGrib/Grib2/Templates/GridDefinitions/EarthGridDefinition.cs @@ -24,83 +24,82 @@ * along with NGrib. If not, see . */ -namespace NGrib.Grib2.Templates.GridDefinitions +namespace NGrib.Grib2.Templates.GridDefinitions; + +public abstract class EarthGridDefinition : GridDefinition { - public abstract class EarthGridDefinition : GridDefinition - { - /// - /// Shape of the earth code. - /// - public int EarthShapeCode { get; } + /// + /// Shape of the earth code. + /// + public int EarthShapeCode { get; } - /// - /// Radius of spherical earth. - /// - public double? EarthRadius { get; } + /// + /// Radius of spherical earth. + /// + public double? EarthRadius { get; } - /// - /// Major axis of oblate spheroid earth. - /// - public double? EarthMajorAxis { get; } + /// + /// Major axis of oblate spheroid earth. + /// + public double? EarthMajorAxis { get; } - /// - /// Minor axis of oblate spheroid earth. - /// - public double? EarthMinorAxis { get; } + /// + /// Minor axis of oblate spheroid earth. + /// + public double? EarthMinorAxis { get; } - /// - /// Computed Earth shape (with default values). - /// - public Earth EarthShape { get; } + /// + /// Computed Earth shape (with default values). + /// + public Earth EarthShape { get; } - private protected EarthGridDefinition(BufferedBinaryReader reader) : base(reader) - { - EarthShapeCode = reader.ReadUInt8(); + private protected EarthGridDefinition(BufferedBinaryReader reader) : base(reader) + { + EarthShapeCode = reader.ReadUInt8(); - EarthRadius = reader.ReadScaledValue(); - EarthMajorAxis = reader.ReadScaledValue(); - EarthMinorAxis = reader.ReadScaledValue(); + EarthRadius = reader.ReadScaledValue(); + EarthMajorAxis = reader.ReadScaledValue(); + EarthMinorAxis = reader.ReadScaledValue(); - EarthShape = ComputeEarthShape(); - } + EarthShape = ComputeEarthShape(); + } - private Earth ComputeEarthShape() - { - Earth earthShape; + private Earth ComputeEarthShape() + { + Earth earthShape; - switch (EarthShapeCode) - { - case (int) CodeTables.EarthShape.DefaultSpherical: - earthShape = new SphericalEarth(EarthShapeCode, 6367470); - break; - case (int) CodeTables.EarthShape.CustomSpherical: - earthShape = new SphericalEarth(EarthShapeCode, EarthRadius ?? throw new BadGribFormatException("Missing Earth radius value.")); - break; - case (int) CodeTables.EarthShape.Iau1965OblateSpheroid: - earthShape = new OblateSpheroidEarth(EarthShapeCode, 6378160.0f, 6356775.0f); - break; - case (int) CodeTables.EarthShape.CustomOblateSpheroid: - earthShape = new OblateSpheroidEarth(EarthShapeCode, - EarthMajorAxis ?? throw new BadGribFormatException("Missing Earth major axis value."), - EarthMinorAxis ?? throw new BadGribFormatException("Missing Earth minor axis value.") - ); - break; - case (int) CodeTables.EarthShape.IagGr80OblateSpheroid: - earthShape = new OblateSpheroidEarth(EarthShapeCode, - 6378137.0f, - 6356752.314f); - break; - case (int) CodeTables.EarthShape.Wgs84: - earthShape = new OblateSpheroidEarth(EarthShapeCode, 6_378_137.0f, 6_356_752.314245179497563967f); - break; - case (int) CodeTables.EarthShape.Wgs84Spherical: - earthShape = new SphericalEarth(EarthShapeCode, 6371229); - break; - default: - return null; - } + switch (EarthShapeCode) + { + case (int) CodeTables.EarthShape.DefaultSpherical: + earthShape = new SphericalEarth(EarthShapeCode, 6367470); + break; + case (int) CodeTables.EarthShape.CustomSpherical: + earthShape = new SphericalEarth(EarthShapeCode, EarthRadius ?? throw new BadGribFormatException("Missing Earth radius value.")); + break; + case (int) CodeTables.EarthShape.Iau1965OblateSpheroid: + earthShape = new OblateSpheroidEarth(EarthShapeCode, 6378160.0f, 6356775.0f); + break; + case (int) CodeTables.EarthShape.CustomOblateSpheroid: + earthShape = new OblateSpheroidEarth(EarthShapeCode, + EarthMajorAxis ?? throw new BadGribFormatException("Missing Earth major axis value."), + EarthMinorAxis ?? throw new BadGribFormatException("Missing Earth minor axis value.") + ); + break; + case (int) CodeTables.EarthShape.IagGr80OblateSpheroid: + earthShape = new OblateSpheroidEarth(EarthShapeCode, + 6378137.0f, + 6356752.314f); + break; + case (int) CodeTables.EarthShape.Wgs84: + earthShape = new OblateSpheroidEarth(EarthShapeCode, 6_378_137.0f, 6_356_752.314245179497563967f); + break; + case (int) CodeTables.EarthShape.Wgs84Spherical: + earthShape = new SphericalEarth(EarthShapeCode, 6371229); + break; + default: + return null; + } - return earthShape; - } - } + return earthShape; + } } \ No newline at end of file diff --git a/src/NGrib/Grib2/Templates/GridDefinitions/GridDefinition.cs b/src/NGrib/Grib2/Templates/GridDefinitions/GridDefinition.cs index 9a68b1e..b1eb372 100644 --- a/src/NGrib/Grib2/Templates/GridDefinitions/GridDefinition.cs +++ b/src/NGrib/Grib2/Templates/GridDefinitions/GridDefinition.cs @@ -17,34 +17,31 @@ * along with NGrib. If not, see . */ -using System.Collections.Generic; +namespace NGrib.Grib2.Templates.GridDefinitions; -namespace NGrib.Grib2.Templates.GridDefinitions +/// +/// Represents a GRIB2 Grid Definition +/// +public abstract class GridDefinition { - /// - /// Represents a GRIB2 Grid Definition - /// - public abstract class GridDefinition - { - /// - /// Grid Definition Offset. - /// - public long Offset { get; } + /// + /// Grid Definition Offset. + /// + public long Offset { get; } - private protected GridDefinition(BufferedBinaryReader reader) - { - Offset = reader.Position; - } + private protected GridDefinition(BufferedBinaryReader reader) + { + Offset = reader.Position; + } - /// - /// Enumerated the point coordinates within the current grid. - /// - /// - /// The points are returned in the order defined by the grid (i.e. scanning mode). - /// - /// - /// Grid points coordinates. - /// - public abstract IEnumerable EnumerateGridPoints(); - } + /// + /// Enumerated the point coordinates within the current grid. + /// + /// + /// The points are returned in the order defined by the grid (i.e. scanning mode). + /// + /// + /// Grid points coordinates. + /// + public abstract IEnumerable EnumerateGridPoints(); } \ No newline at end of file diff --git a/src/NGrib/Grib2/Templates/GridDefinitions/GridPointEarthGridDefinition.cs b/src/NGrib/Grib2/Templates/GridDefinitions/GridPointEarthGridDefinition.cs index 3b3b3c0..92358a9 100644 --- a/src/NGrib/Grib2/Templates/GridDefinitions/GridPointEarthGridDefinition.cs +++ b/src/NGrib/Grib2/Templates/GridDefinitions/GridPointEarthGridDefinition.cs @@ -17,34 +17,33 @@ * along with NGrib. If not, see . */ -namespace NGrib.Grib2.Templates.GridDefinitions +namespace NGrib.Grib2.Templates.GridDefinitions; + +public abstract class GridPointEarthGridDefinition : XyEarthGridDefinition { - public abstract class GridPointEarthGridDefinition : XyEarthGridDefinition - { - /// . - /// La1 as a float - /// - /// - public double La1 { get; } + /// . + /// La1 as a float + /// + /// + public double La1 { get; } - /// . - /// Lo1 as a float - /// - /// - public double Lo1 { get; } + /// . + /// Lo1 as a float + /// + /// + public double Lo1 { get; } - /// . - /// Resolution as a int - /// - /// - public int Resolution { get; } + /// . + /// Resolution as a int + /// + /// + public int Resolution { get; } - private protected GridPointEarthGridDefinition(BufferedBinaryReader reader) : base(reader) - { - La1 = reader.ReadInt32() * 1e-6; - Lo1 = reader.ReadUInt32() * 1e-6; - Resolution = reader.ReadUInt8(); - } - } + private protected GridPointEarthGridDefinition(BufferedBinaryReader reader) : base(reader) + { + La1 = reader.ReadInt32() * 1e-6; + Lo1 = reader.ReadUInt32() * 1e-6; + Resolution = reader.ReadUInt8(); + } } \ No newline at end of file diff --git a/src/NGrib/Grib2/Templates/GridDefinitions/XyEarthGridDefinition.cs b/src/NGrib/Grib2/Templates/GridDefinitions/XyEarthGridDefinition.cs index f2b0a49..0c0a19e 100644 --- a/src/NGrib/Grib2/Templates/GridDefinitions/XyEarthGridDefinition.cs +++ b/src/NGrib/Grib2/Templates/GridDefinitions/XyEarthGridDefinition.cs @@ -17,24 +17,23 @@ * along with NGrib. If not, see . */ -namespace NGrib.Grib2.Templates.GridDefinitions +namespace NGrib.Grib2.Templates.GridDefinitions; + +public abstract class XyEarthGridDefinition : EarthGridDefinition { - public abstract class XyEarthGridDefinition : EarthGridDefinition - { - /// - /// Number of points along x-axis or a parallel. - /// - public long Nx { get; } + /// + /// Number of points along x-axis or a parallel. + /// + public long Nx { get; } - /// - /// Number of points along y-axis or a meridian. - /// - public long Ny { get; } + /// + /// Number of points along y-axis or a meridian. + /// + public long Ny { get; } - private protected XyEarthGridDefinition(BufferedBinaryReader reader) : base(reader) - { - Nx = reader.ReadUInt32(); - Ny = reader.ReadUInt32(); - } - } + private protected XyEarthGridDefinition(BufferedBinaryReader reader) : base(reader) + { + Nx = reader.ReadUInt32(); + Ny = reader.ReadUInt32(); + } } \ No newline at end of file diff --git a/src/NGrib/Grib2/Templates/ProductDefinitions/ChemicalOrPhysicalConsistent.cs b/src/NGrib/Grib2/Templates/ProductDefinitions/ChemicalOrPhysicalConsistent.cs new file mode 100644 index 0000000..3a4102e --- /dev/null +++ b/src/NGrib/Grib2/Templates/ProductDefinitions/ChemicalOrPhysicalConsistent.cs @@ -0,0 +1,252 @@ +namespace NGrib.Grib2.Templates.ProductDefinitions; + +public enum ChemicalOrPhysicalConsistent : ushort +{ + Ozone = 0, + + WaterVapour, + + Methane, + + CarbonDioxide, + + CarbonMonoxide, + + NitrogenDioxide, + + NitrousOxide, + + Formaldehyde, + + SulphurDioxide, + + Ammonia, + + Ammonium, + + NitrogenMonoxide, + + AtomicOxygen, + + NitrateRadical, + + HydroperoxylRadical, + + DinitrogenPentoxide, + + NitrousAcid, + + NitricAcid, + + PeroxynitricAcid, + + HydrogenPeroxide, + + MolecularHydrogen, + + AtomicNitrogen, + + Sulphate, + + Radon, + + ElementalMercury, + + DivalentMercury, + + AtomicChlorine, + + ChlorineMonoxide, + + DichlorinePeroxide, + + HypochlorousAcid, + + ChlorineNitrate, + + ChlorineDioxide, + + AtomicBromide, + + BromineMonoxide, + + BromineChloride, + + HydrogenBromide, + + HypobromousAcid, + + BromineNitrate, + + Oxygen, + + HydroxylRadical = 10000, + + MethylPeroxyRadical, + + MethylHydroperoxide, + + Methanol = 10004, + + FormicAcid, + + HydrogenCyanide, + + AcetoNitrile, + + Ethane, + + EtheneEthylene, + + EthyneAcetylene, + + Ethanol, + + AceticAcid, + + PeroxyacetylNitrate, + + Propane, + + Propene, + + Butanes, + + Isoprene, + + AlphaPinene, + + BetaPinene, + + Limonene, + + Benzene, + + Toluene, + + Xylene, + + DimethylSulphide = 10500, + + HydrogenChloride = 20000, + + Cfc11, + + Cfc12, + + Cfc113, + + Cfc113A, + + Cfc114, + + Cfc115, + + Hcfc22, + + Hcfc141B, + + Hcfc142B, + + Halon1202, + + Halon1211, + + Halon1301, + + Halon2402, + + MethylChlorideHcc40, + + CarbonTetrachlorideHcc10, + + Hcc140A, + + MethylBromideHbc40B1, + + HexachlorocyclohexaneHch, + + AlphaHexachlorocyclohexane, + + HexachlorobiphenylPcb153, + + /// + /// Tracer, defined by originating centre + /// + RadioactivePollutant = 30000, + + /// + /// OH+HO2 + /// + HOxRadical, + + /// + /// HO2+RO2 + /// + TotalInorganicAndOrganicPeroxyRadicals, + + PassiveOzone, + + NOxExpressedAsNitrogen, + + AllNitrogenOxidesNOyExpressedAsNitrogen, + + TotalInorganicChlorine, + + TotalInorganicBromine, + + /// + ///Total Inorganic Chlorine Except HCl, ClONO2: ClOx + /// + TotalInorganicChlorineExceptHClClOno2ClOx, + + /// + /// Total Inorganic Bromine Except Hbr, BrONO2:BrOx + /// + TotalInorganicBromineExceptHbrBrOno2BrOx, + + LumpedAlkanes, + + LumpedAlkenes, + + LumpedAromaticCoumpounds, + + LumpedTerpenes, + + NonMethaneVolatileOrganicCompoundsExpressedAsCarbon, + + AnthropogenicNonMethaneVolatileOrganicCompoundsExpressedAsCarbon, + + BiogenicNonMethaneVolatileOrganicCompoundsExpressedAsCarbon, + + LumpedOxygenatedHydrocarbons, + + TotalAerosol = 62000, + + DustDry, + + WaterInAmbient, + + AmmoniumDry, + + NitrateDry, + + NitricAcidTrihydrate, + + SulphateDry, + + MercuryDry, + + SeaSaltDry, + + BlackCarbonDry, + + ParticulateOrganicMatterDry, + + PrimaryParticulateOrganicMatterDry, + + SecondaryParticulateOrganicMatterDry, + + Missing = 65535 +} + diff --git a/src/NGrib/Grib2/Templates/ProductDefinitions/ProductDefinition.cs b/src/NGrib/Grib2/Templates/ProductDefinitions/ProductDefinition.cs index 14812a9..50cb9c0 100644 --- a/src/NGrib/Grib2/Templates/ProductDefinitions/ProductDefinition.cs +++ b/src/NGrib/Grib2/Templates/ProductDefinitions/ProductDefinition.cs @@ -19,58 +19,63 @@ using NGrib.Grib2.CodeTables; -namespace NGrib.Grib2.Templates.ProductDefinitions -{ - /// - /// Represents a GRIB2 Product Definition. - /// - public abstract class ProductDefinition : Template - { - /// - /// Start position on the product definition. - /// - public long Offset { get; } - - /// - /// Parameter category. - /// - public int ParameterCategory { get; } +namespace NGrib.Grib2.Templates.ProductDefinitions; - /// - /// Parameter number. - /// - public int ParameterNumber { get; } +/// +/// Represents a GRIB2 Product Definition. +/// +public abstract class ProductDefinition : Template +{ + /// + /// Start position on the product definition. + /// + public long Offset { get; } - /// - /// Parameter informations. - /// - /// - /// null if a unknown discipline/category/number is used. - /// - public Parameter? Parameter { get; } + /// + /// Parameter category. + /// + public int ParameterCategory { get; } - /// - /// Type of generating process. - /// - public GeneratingProcessType GeneratingProcessType { get; } + /// + /// Parameter number. + /// + public int ParameterNumber { get; } - private protected ProductDefinition(BufferedBinaryReader reader, Discipline discipline) - { - Offset = reader.Position; - ParameterCategory = reader.ReadUInt8(); - ParameterNumber = reader.ReadUInt8(); - Parameter = CodeTables.Parameter.Get(discipline, ParameterCategory, ParameterNumber); - GeneratingProcessType = (GeneratingProcessType) reader.ReadUInt8(); + /// + /// Parameter informations. + /// + /// + /// null if a unknown discipline/category/number is used. + /// + public Parameter? Parameter { get; } - RegisterContent(ProductDefinitionContent.ParameterCategory, () => ParameterCategory); - RegisterContent(ProductDefinitionContent.ParameterNumber, () => ParameterNumber); + /// + /// Type of generating process. + /// + public GeneratingProcessType GeneratingProcessType { get; set; } - if (Parameter.HasValue) - { - RegisterContent(ProductDefinitionContent.Parameter, () => Parameter.Value); - } + private protected ProductDefinition(BufferedBinaryReader reader, Discipline discipline) + { + Offset = reader.Position; + ParameterCategory = reader.ReadUInt8(); + RegisterContent(ProductDefinitionContent.ParameterCategory, () => ParameterCategory); - RegisterContent(ProductDefinitionContent.GeneratingProcessType, () => GeneratingProcessType); - } - } + ParameterNumber = reader.ReadUInt8(); + RegisterContent(ProductDefinitionContent.ParameterNumber, () => ParameterNumber); + + Parameter = CodeTables.Parameter.Get(discipline, ParameterCategory, ParameterNumber); + if (Parameter.HasValue) + { + RegisterContent(ProductDefinitionContent.Parameter, () => Parameter.Value); + } + + InitGeneratingProcessType(reader); + } + + //Todo: сделать красивее + protected virtual void InitGeneratingProcessType(BufferedBinaryReader reader) + { + GeneratingProcessType = (GeneratingProcessType) reader.ReadUInt8(); + RegisterContent(ProductDefinitionContent.GeneratingProcessType, () => GeneratingProcessType); + } } \ No newline at end of file diff --git a/src/NGrib/Grib2/Templates/ProductDefinitions/ProductDefinition0000.cs b/src/NGrib/Grib2/Templates/ProductDefinitions/ProductDefinition0000.cs index 79528eb..31d6009 100644 --- a/src/NGrib/Grib2/Templates/ProductDefinitions/ProductDefinition0000.cs +++ b/src/NGrib/Grib2/Templates/ProductDefinitions/ProductDefinition0000.cs @@ -18,99 +18,96 @@ */ using NGrib.Grib2.CodeTables; -using System; -namespace NGrib.Grib2.Templates.ProductDefinitions -{ +namespace NGrib.Grib2.Templates.ProductDefinitions; - /// - /// Product Definition Template 4.0: Analysis or forecast at a horizontal level or in a horizontal layer at a point in time - /// - public class ProductDefinition0000 : WithBackgroundProductDefinition - { - /// - /// Analysis or forecast generating processes identifier. - /// - public int GeneratingProcessIdentifier { get; } - - /// - /// Hours of observational data cutoff after reference time. - /// - public int HoursAfter { get; } - - /// - /// Minutes of observational data cutoff after reference time. - /// - public int MinutesAfter { get; } - - /// - /// Timespan of observational data cutoff after reference time. - /// - public TimeSpan ObservationalDataCutoff { get; } - - /// - /// Indicator of unit of time range. - /// - public TimeRangeUnit TimeRangeUnit { get; } - - /// - /// Forecast time in units defined by indicator of unit of time range. - /// - public int ForecastTime { get; } - - /// - /// Type of first fixed surface. - /// - public FixedSurfaceType FirstFixedSurfaceType { get; } - - /// - /// Value of first fixed surface. - /// - public double? FirstFixedSurfaceValue { get; } - - /// - /// Type of second fixed surface. - /// - public FixedSurfaceType SecondFixedSurfaceType { get; } - - /// - /// Value of second fixed surface. - /// - public double? SecondFixedSurfaceValue { get; } - - internal ProductDefinition0000(BufferedBinaryReader reader, Discipline discipline) : base( - reader, discipline) - { - GeneratingProcessIdentifier = reader.ReadUInt8(); - HoursAfter = reader.ReadUInt16(); - MinutesAfter = reader.ReadUInt8(); - ObservationalDataCutoff = TimeSpan.FromHours(HoursAfter) + TimeSpan.FromMinutes(MinutesAfter); - TimeRangeUnit = (TimeRangeUnit) reader.ReadUInt8(); - ForecastTime = reader.ReadInt32(); - - FirstFixedSurfaceType = (FixedSurfaceType) reader.ReadUInt8(); - FirstFixedSurfaceValue = reader.ReadScaledValue(); - - SecondFixedSurfaceType = (FixedSurfaceType) reader.ReadUInt8(); - SecondFixedSurfaceValue = reader.ReadScaledValue(); - - RegisterContent(ProductDefinitionContent.GeneratingProcessId, () => GeneratingProcessIdentifier); - RegisterContent(ProductDefinitionContent.ObservationalDataCutoff, () => ObservationalDataCutoff); - var forecastTime = CalculateTimeRangeFrom(TimeRangeUnit, ForecastTime); - if (forecastTime.HasValue) { - RegisterContent(ProductDefinitionContent.ForecastTime, () => forecastTime.Value); - } - - RegisterContent(ProductDefinitionContent.FirstFixedSurfaceType, () => FirstFixedSurfaceType); - if (FirstFixedSurfaceValue.HasValue) - { - RegisterContent(ProductDefinitionContent.FirstFixedSurfaceValue, () => FirstFixedSurfaceValue.Value); - } - RegisterContent(ProductDefinitionContent.SecondFixedSurfaceType, () => SecondFixedSurfaceType); - if (SecondFixedSurfaceValue.HasValue) - { - RegisterContent(ProductDefinitionContent.SecondFixedSurfaceValue, () => SecondFixedSurfaceValue.Value); - } - } - } +/// +/// Product Definition Template 4.0: Analysis or forecast at a horizontal level or in a horizontal layer at a point in time +/// +public class ProductDefinition0000 : WithBackgroundProductDefinition +{ + /// + /// Analysis or forecast generating processes identifier. + /// + public int GeneratingProcessIdentifier { get; } + + /// + /// Hours of observational data cutoff after reference time. + /// + public int HoursAfter { get; } + + /// + /// Minutes of observational data cutoff after reference time. + /// + public int MinutesAfter { get; } + + /// + /// Timespan of observational data cutoff after reference time. + /// + public TimeSpan ObservationalDataCutoff { get; } + + /// + /// Indicator of unit of time range. + /// + public TimeRangeUnitGrib2 TimeRangeUnitGrib2 { get; } + + /// + /// Forecast time in units defined by indicator of unit of time range. + /// + public int ForecastTime { get; } + + /// + /// Type of first fixed surface. + /// + public FixedSurfaceType FirstFixedSurfaceType { get; } + + /// + /// Value of first fixed surface. + /// + public double? FirstFixedSurfaceValue { get; } + + /// + /// Type of second fixed surface. + /// + public FixedSurfaceType SecondFixedSurfaceType { get; } + + /// + /// Value of second fixed surface. + /// + public double? SecondFixedSurfaceValue { get; } + + internal ProductDefinition0000(BufferedBinaryReader reader, Discipline discipline) : base( + reader, discipline) + { + GeneratingProcessIdentifier = reader.ReadUInt8(); + HoursAfter = reader.ReadUInt16(); + MinutesAfter = reader.ReadUInt8(); + ObservationalDataCutoff = TimeSpan.FromHours(HoursAfter) + TimeSpan.FromMinutes(MinutesAfter); + TimeRangeUnitGrib2 = (TimeRangeUnitGrib2) reader.ReadUInt8(); + ForecastTime = reader.ReadInt32(); + + FirstFixedSurfaceType = (FixedSurfaceType) reader.ReadUInt8(); + FirstFixedSurfaceValue = reader.ReadScaledValue(); + + SecondFixedSurfaceType = (FixedSurfaceType) reader.ReadUInt8(); + SecondFixedSurfaceValue = reader.ReadScaledValue(); + + RegisterContent(ProductDefinitionContent.GeneratingProcessId, () => GeneratingProcessIdentifier); + RegisterContent(ProductDefinitionContent.ObservationalDataCutoff, () => ObservationalDataCutoff); + var forecastTime = CalculateTimeRangeFrom(TimeRangeUnitGrib2, ForecastTime); + if (forecastTime.HasValue) { + RegisterContent(ProductDefinitionContent.ForecastTime, () => forecastTime.Value); + } + + RegisterContent(ProductDefinitionContent.FirstFixedSurfaceType, () => FirstFixedSurfaceType); + if (FirstFixedSurfaceValue.HasValue) + { + RegisterContent(ProductDefinitionContent.FirstFixedSurfaceValue, () => FirstFixedSurfaceValue.Value); + } + RegisterContent(ProductDefinitionContent.SecondFixedSurfaceType, () => SecondFixedSurfaceType); + if (SecondFixedSurfaceValue.HasValue) + { + RegisterContent(ProductDefinitionContent.SecondFixedSurfaceValue, () => SecondFixedSurfaceValue.Value); + } + } } \ No newline at end of file diff --git a/src/NGrib/Grib2/Templates/ProductDefinitions/ProductDefinition0001.cs b/src/NGrib/Grib2/Templates/ProductDefinitions/ProductDefinition0001.cs index 4f85dc6..174b69a 100644 --- a/src/NGrib/Grib2/Templates/ProductDefinitions/ProductDefinition0001.cs +++ b/src/NGrib/Grib2/Templates/ProductDefinitions/ProductDefinition0001.cs @@ -19,37 +19,36 @@ using NGrib.Grib2.CodeTables; -namespace NGrib.Grib2.Templates.ProductDefinitions +namespace NGrib.Grib2.Templates.ProductDefinitions; + +/// +/// Product Definition Template 4.1: Individual ensemble forecast, control and perturbed, at ahorizontal level or in a horizontal layer at a point in time. +/// +public class ProductDefinition0001 : ProductDefinition0000 { - /// - /// Product Definition Template 4.1: Individual ensemble forecast, control and perturbed, at ahorizontal level or in a horizontal layer at a point in time. - /// - public class ProductDefinition0001 : ProductDefinition0000 - { - /// - /// Type of ensemble forecast (see Code table 4.6). - /// - public EnsembleForecastType EnsembleForecastType { get; } + /// + /// Type of ensemble forecast (see Code table 4.6). + /// + public EnsembleForecastType EnsembleForecastType { get; } - /// - /// Perturbation number. - /// - public int PerturbationNumber { get; } + /// + /// Perturbation number. + /// + public int PerturbationNumber { get; } - /// - /// Number of forecasts in ensemble - /// - public int EnsembleForecastsNumber { get; } + /// + /// Number of forecasts in ensemble + /// + public int EnsembleForecastsNumber { get; } - internal ProductDefinition0001(BufferedBinaryReader reader, Discipline discipline) : base(reader, discipline) - { - EnsembleForecastType = (EnsembleForecastType) reader.ReadByte(); - PerturbationNumber = reader.ReadByte(); - EnsembleForecastsNumber = reader.ReadByte(); + internal ProductDefinition0001(BufferedBinaryReader reader, Discipline discipline) : base(reader, discipline) + { + EnsembleForecastType = (EnsembleForecastType) reader.ReadByte(); + PerturbationNumber = reader.ReadByte(); + EnsembleForecastsNumber = reader.ReadByte(); - RegisterContent(ProductDefinitionContent.EnsembleForecastType, () => EnsembleForecastType); - RegisterContent(ProductDefinitionContent.PerturbationNumber, () => PerturbationNumber); - RegisterContent(ProductDefinitionContent.EnsembleForecastsNumber, () => EnsembleForecastsNumber); - } - } -} + RegisterContent(ProductDefinitionContent.EnsembleForecastType, () => EnsembleForecastType); + RegisterContent(ProductDefinitionContent.PerturbationNumber, () => PerturbationNumber); + RegisterContent(ProductDefinitionContent.EnsembleForecastsNumber, () => EnsembleForecastsNumber); + } +} \ No newline at end of file diff --git a/src/NGrib/Grib2/Templates/ProductDefinitions/ProductDefinition0002.cs b/src/NGrib/Grib2/Templates/ProductDefinitions/ProductDefinition0002.cs index 24da846..cfbf7e0 100644 --- a/src/NGrib/Grib2/Templates/ProductDefinitions/ProductDefinition0002.cs +++ b/src/NGrib/Grib2/Templates/ProductDefinitions/ProductDefinition0002.cs @@ -19,31 +19,30 @@ using NGrib.Grib2.CodeTables; -namespace NGrib.Grib2.Templates.ProductDefinitions +namespace NGrib.Grib2.Templates.ProductDefinitions; + +/// +/// Product Definition Template 4.2: Derived forecast based on all ensemble members at a horizontal level +/// or in a horizontal layer at a point in time. +/// +public class ProductDefinition0002 : ProductDefinition0000 { - /// - /// Product Definition Template 4.2: Derived forecast based on all ensemble members at a horizontal level - /// or in a horizontal layer at a point in time. - /// - public class ProductDefinition0002 : ProductDefinition0000 - { - /// - /// Derived forecast (see Code Table 4.7) - /// - public int DerivedForecast { get; } + /// + /// Derived forecast (see Code Table 4.7) + /// + public int DerivedForecast { get; } - /// - /// Number of forecasts in ensemble - /// - public int EnsembleForecastsNumber { get; } + /// + /// Number of forecasts in ensemble + /// + public int EnsembleForecastsNumber { get; } - internal ProductDefinition0002(BufferedBinaryReader reader, Discipline discipline) : base(reader, discipline) - { - DerivedForecast = reader.ReadByte(); - EnsembleForecastsNumber = reader.ReadByte(); + internal ProductDefinition0002(BufferedBinaryReader reader, Discipline discipline) : base(reader, discipline) + { + DerivedForecast = reader.ReadByte(); + EnsembleForecastsNumber = reader.ReadByte(); - RegisterContent(ProductDefinitionContent.DerivedForecast, () => DerivedForecast); - RegisterContent(ProductDefinitionContent.EnsembleForecastsNumber, () => EnsembleForecastsNumber); - } - } + RegisterContent(ProductDefinitionContent.DerivedForecast, () => DerivedForecast); + RegisterContent(ProductDefinitionContent.EnsembleForecastsNumber, () => EnsembleForecastsNumber); + } } \ No newline at end of file diff --git a/src/NGrib/Grib2/Templates/ProductDefinitions/ProductDefinition0008.cs b/src/NGrib/Grib2/Templates/ProductDefinitions/ProductDefinition0008.cs index a7286b9..1585d74 100644 --- a/src/NGrib/Grib2/Templates/ProductDefinitions/ProductDefinition0008.cs +++ b/src/NGrib/Grib2/Templates/ProductDefinitions/ProductDefinition0008.cs @@ -17,105 +17,103 @@ * along with NGrib. If not, see . */ -using System; using NGrib.Grib2.CodeTables; -namespace NGrib.Grib2.Templates.ProductDefinitions +namespace NGrib.Grib2.Templates.ProductDefinitions; + +/// +/// Product Definition Template 4.8: Average, accumulation, and/or extreme values +/// or other statistically processed values at a horizontal level or in a horizontal +/// layer in a continuous or non-continuous time interval +/// +public class ProductDefinition0008 : ProductDefinition0000 { - /// - /// Product Definition Template 4.8: Average, accumulation, and/or extreme values - /// or other statistically processed values at a horizontal level or in a horizontal - /// layer in a continuous or non-continuous time interval - /// - public class ProductDefinition0008 : ProductDefinition0000 - { - /// - /// Time of end of overall time interval. - /// - public DateTime OverallTimeIntervalEnd { get; } - - /// - /// Number of time range specifications describing the time intervals used to calculate the statistically processed field. - /// - public int TimeRangeNumber { get; } - - /// - /// Total number of data values missing in statistical process. - /// - public long MissingDataValuesTotalNumber { get; } - - /// - /// Statistical process used to calculate the processed field from the field at each time increment during the time range. - /// - public int StatisticalProcess { get; } - - /// - /// Type of time increment between successive fields used in the statistical processing. - /// - public long StatisticalProcessingTimeIncrementType { get; } - - /// - /// Indicator of unit of time for time range over which statistical processing is done. - /// - public TimeRangeUnit StatisticalProcessingTimeRangeUnit { get; } - - /// - /// Length of the time range over which statistical processing is done, in units defined by StatisticalProcessingTimeRangeUnit. - /// - public long StatisticalProcessingTimeRangeLength { get; } - - /// - /// Indicator of unit of time for the increment between the successive fields used. - /// - public TimeRangeUnit SuccessiveFieldsIncrementUnit { get; } - - /// - /// Time increment between successive fields, in units defined by SuccessiveFieldsIncrementUnit. - /// - public long SuccessiveFieldsTimeIncrement { get; } - - internal ProductDefinition0008( - BufferedBinaryReader reader, - Discipline discipline) : base(reader, discipline) - { - OverallTimeIntervalEnd = reader.ReadDateTime(); - RegisterContent(ProductDefinitionContent.OverallTimeIntervalEnd, () => OverallTimeIntervalEnd); - - // 42 - TimeRangeNumber = reader.ReadUInt8(); - - // 43-46 - MissingDataValuesTotalNumber = reader.ReadUInt32(); - - //47 - StatisticalProcess = reader.ReadUInt8(); - - //48 - StatisticalProcessingTimeIncrementType = reader.ReadUInt8(); - - //49 - StatisticalProcessingTimeRangeUnit = (TimeRangeUnit) reader.ReadUInt8(); - - //50-53 - StatisticalProcessingTimeRangeLength = reader.ReadUInt32(); - - var timeRange = CalculateTimeRangeFrom(StatisticalProcessingTimeRangeUnit, StatisticalProcessingTimeRangeLength); - if (timeRange.HasValue) - { - RegisterContent(ProductDefinitionContent.StatisticalProcessingTimeRange, () => timeRange.Value); - } - - //54 - SuccessiveFieldsIncrementUnit = (TimeRangeUnit) reader.ReadUInt8(); - - //55-58 - SuccessiveFieldsTimeIncrement = reader.ReadUInt32(); - - var successiveFieldsTimeIncrement = CalculateTimeRangeFrom(SuccessiveFieldsIncrementUnit, SuccessiveFieldsTimeIncrement); - if (successiveFieldsTimeIncrement.HasValue) - { - RegisterContent(ProductDefinitionContent.StatisticalProcessingTimeRange, () => successiveFieldsTimeIncrement.Value); - } - } - } + /// + /// Time of end of overall time interval. + /// + public DateTime OverallTimeIntervalEnd { get; } + + /// + /// Number of time range specifications describing the time intervals used to calculate the statistically processed field. + /// + public int TimeRangeNumber { get; } + + /// + /// Total number of data values missing in statistical process. + /// + public long MissingDataValuesTotalNumber { get; } + + /// + /// Statistical process used to calculate the processed field from the field at each time increment during the time range. + /// + public int StatisticalProcess { get; } + + /// + /// Type of time increment between successive fields used in the statistical processing. + /// + public long StatisticalProcessingTimeIncrementType { get; } + + /// + /// Indicator of unit of time for time range over which statistical processing is done. + /// + public TimeRangeUnitGrib2 StatisticalProcessingTimeRangeUnitGrib2 { get; } + + /// + /// Length of the time range over which statistical processing is done, in units defined by StatisticalProcessingTimeRangeUnit. + /// + public long StatisticalProcessingTimeRangeLength { get; } + + /// + /// Indicator of unit of time for the increment between the successive fields used. + /// + public TimeRangeUnitGrib2 SuccessiveFieldsIncrementRangeUnitGrib2 { get; } + + /// + /// Time increment between successive fields, in units defined by SuccessiveFieldsIncrementUnit. + /// + public long SuccessiveFieldsTimeIncrement { get; } + + internal ProductDefinition0008( + BufferedBinaryReader reader, + Discipline discipline) : base(reader, discipline) + { + OverallTimeIntervalEnd = reader.ReadDateTime(); + RegisterContent(ProductDefinitionContent.OverallTimeIntervalEnd, () => OverallTimeIntervalEnd); + + // 42 + TimeRangeNumber = reader.ReadUInt8(); + + // 43-46 + MissingDataValuesTotalNumber = reader.ReadUInt32(); + + //47 + StatisticalProcess = reader.ReadUInt8(); + + //48 + StatisticalProcessingTimeIncrementType = reader.ReadUInt8(); + + //49 + StatisticalProcessingTimeRangeUnitGrib2 = (TimeRangeUnitGrib2) reader.ReadUInt8(); + + //50-53 + StatisticalProcessingTimeRangeLength = reader.ReadUInt32(); + + var timeRange = CalculateTimeRangeFrom(StatisticalProcessingTimeRangeUnitGrib2, StatisticalProcessingTimeRangeLength); + if (timeRange.HasValue) + { + RegisterContent(ProductDefinitionContent.StatisticalProcessingTimeRange, () => timeRange.Value); + } + + //54 + SuccessiveFieldsIncrementRangeUnitGrib2 = (TimeRangeUnitGrib2) reader.ReadUInt8(); + + //55-58 + SuccessiveFieldsTimeIncrement = reader.ReadUInt32(); + + var successiveFieldsTimeIncrement = CalculateTimeRangeFrom(SuccessiveFieldsIncrementRangeUnitGrib2, SuccessiveFieldsTimeIncrement); + if (successiveFieldsTimeIncrement.HasValue) + { + RegisterContent(ProductDefinitionContent.StatisticalProcessingTimeRange, () => successiveFieldsTimeIncrement.Value); + } + } } \ No newline at end of file diff --git a/src/NGrib/Grib2/Templates/ProductDefinitions/ProductDefinition0011.cs b/src/NGrib/Grib2/Templates/ProductDefinitions/ProductDefinition0011.cs index 5f8571f..a14a352 100644 --- a/src/NGrib/Grib2/Templates/ProductDefinitions/ProductDefinition0011.cs +++ b/src/NGrib/Grib2/Templates/ProductDefinitions/ProductDefinition0011.cs @@ -17,102 +17,100 @@ * along with NGrib. If not, see . */ -using System; using NGrib.Grib2.CodeTables; -namespace NGrib.Grib2.Templates.ProductDefinitions +namespace NGrib.Grib2.Templates.ProductDefinitions; + +/// +/// Product definition template 4.11 – Individual ensemble forecast, control and perturbed, +/// at ahorizontal level or in a horizontal layer in a continuous or non-continuous time interval. +/// +public class ProductDefinition0011 : ProductDefinition0001 { - /// - /// Product definition template 4.11 – Individual ensemble forecast, control and perturbed, - /// at ahorizontal level or in a horizontal layer in a continuous or non-continuous time interval. - /// - public class ProductDefinition0011 : ProductDefinition0001 - { - /// - /// Time of end of overall time interval - /// - public DateTime OverallTimeIntervalEnd { get; } - - /// - /// Number of time range specifications describing the time intervals used to calculate the statistically processed field. - /// - public int TimeRangeNumber { get; } - - /// - /// Total number of data values missing in statistical process. - /// - public long MissingDataValuesTotalNumber { get; } - - /// - /// Statistical process used to calculate the processed field from the field at each time increment during the time range. - /// - public int StatisticalProcess { get; } - - /// - /// Type of time increment between successive fields used in the statistical processing. - /// - public long StatisticalProcessingTimeIncrementType { get; } - - /// - /// Indicator of unit of time for time range over which statistical processing is done. - /// - public TimeRangeUnit StatisticalProcessingTimeRangeUnit { get; } - - /// - /// Length of the time range over which statistical processing is done, in units defined by StatisticalProcessingTimeRangeUnit. - /// - public long StatisticalProcessingTimeRangeLength { get; } - - /// - /// Indicator of unit of time for the increment between the successive fields used. - /// - public TimeRangeUnit SuccessiveFieldsIncrementUnit { get; } - - /// - /// Time increment between successive fields, in units defined by SuccessiveFieldsIncrementUnit. - /// - public long SuccessiveFieldsTimeIncrement { get; } - - internal ProductDefinition0011(BufferedBinaryReader reader, Discipline discipline) : base(reader, discipline) - { - OverallTimeIntervalEnd = reader.ReadDateTime(); - RegisterContent(ProductDefinitionContent.OverallTimeIntervalEnd, () => OverallTimeIntervalEnd); - - // 42 - TimeRangeNumber = reader.ReadUInt8(); - - // 43-46 - MissingDataValuesTotalNumber = reader.ReadUInt32(); - - //47 - StatisticalProcess = reader.ReadUInt8(); - - //48 - StatisticalProcessingTimeIncrementType = reader.ReadUInt8(); - - //49 - StatisticalProcessingTimeRangeUnit = (TimeRangeUnit)reader.ReadUInt8(); - - //50-53 - StatisticalProcessingTimeRangeLength = reader.ReadUInt32(); - - var timeRange = CalculateTimeRangeFrom(StatisticalProcessingTimeRangeUnit, StatisticalProcessingTimeRangeLength); - if (timeRange.HasValue) - { - RegisterContent(ProductDefinitionContent.StatisticalProcessingTimeRange, () => timeRange.Value); - } - - //54 - SuccessiveFieldsIncrementUnit = (TimeRangeUnit)reader.ReadUInt8(); - - //55-58 - SuccessiveFieldsTimeIncrement = reader.ReadUInt32(); - - var successiveFieldsTimeIncrement = CalculateTimeRangeFrom(SuccessiveFieldsIncrementUnit, SuccessiveFieldsTimeIncrement); - if (successiveFieldsTimeIncrement.HasValue) - { - RegisterContent(ProductDefinitionContent.StatisticalProcessingTimeRange, () => successiveFieldsTimeIncrement.Value); - } - } - } -} + /// + /// Time of end of overall time interval + /// + public DateTime OverallTimeIntervalEnd { get; } + + /// + /// Number of time range specifications describing the time intervals used to calculate the statistically processed field. + /// + public int TimeRangeNumber { get; } + + /// + /// Total number of data values missing in statistical process. + /// + public long MissingDataValuesTotalNumber { get; } + + /// + /// Statistical process used to calculate the processed field from the field at each time increment during the time range. + /// + public int StatisticalProcess { get; } + + /// + /// Type of time increment between successive fields used in the statistical processing. + /// + public long StatisticalProcessingTimeIncrementType { get; } + + /// + /// Indicator of unit of time for time range over which statistical processing is done. + /// + public TimeRangeUnitGrib2 StatisticalProcessingTimeRangeUnitGrib2 { get; } + + /// + /// Length of the time range over which statistical processing is done, in units defined by StatisticalProcessingTimeRangeUnit. + /// + public long StatisticalProcessingTimeRangeLength { get; } + + /// + /// Indicator of unit of time for the increment between the successive fields used. + /// + public TimeRangeUnitGrib2 SuccessiveFieldsIncrementRangeUnitGrib2 { get; } + + /// + /// Time increment between successive fields, in units defined by SuccessiveFieldsIncrementUnit. + /// + public long SuccessiveFieldsTimeIncrement { get; } + + internal ProductDefinition0011(BufferedBinaryReader reader, Discipline discipline) : base(reader, discipline) + { + OverallTimeIntervalEnd = reader.ReadDateTime(); + RegisterContent(ProductDefinitionContent.OverallTimeIntervalEnd, () => OverallTimeIntervalEnd); + + // 42 + TimeRangeNumber = reader.ReadUInt8(); + + // 43-46 + MissingDataValuesTotalNumber = reader.ReadUInt32(); + + //47 + StatisticalProcess = reader.ReadUInt8(); + + //48 + StatisticalProcessingTimeIncrementType = reader.ReadUInt8(); + + //49 + StatisticalProcessingTimeRangeUnitGrib2 = (TimeRangeUnitGrib2)reader.ReadUInt8(); + + //50-53 + StatisticalProcessingTimeRangeLength = reader.ReadUInt32(); + + var timeRange = CalculateTimeRangeFrom(StatisticalProcessingTimeRangeUnitGrib2, StatisticalProcessingTimeRangeLength); + if (timeRange.HasValue) + { + RegisterContent(ProductDefinitionContent.StatisticalProcessingTimeRange, () => timeRange.Value); + } + + //54 + SuccessiveFieldsIncrementRangeUnitGrib2 = (TimeRangeUnitGrib2)reader.ReadUInt8(); + + //55-58 + SuccessiveFieldsTimeIncrement = reader.ReadUInt32(); + + var successiveFieldsTimeIncrement = CalculateTimeRangeFrom(SuccessiveFieldsIncrementRangeUnitGrib2, SuccessiveFieldsTimeIncrement); + if (successiveFieldsTimeIncrement.HasValue) + { + RegisterContent(ProductDefinitionContent.StatisticalProcessingTimeRange, () => successiveFieldsTimeIncrement.Value); + } + } +} \ No newline at end of file diff --git a/src/NGrib/Grib2/Templates/ProductDefinitions/ProductDefinition0012.cs b/src/NGrib/Grib2/Templates/ProductDefinitions/ProductDefinition0012.cs index 150b719..41e54ba 100644 --- a/src/NGrib/Grib2/Templates/ProductDefinitions/ProductDefinition0012.cs +++ b/src/NGrib/Grib2/Templates/ProductDefinitions/ProductDefinition0012.cs @@ -18,101 +18,99 @@ */ using NGrib.Grib2.CodeTables; -using System; -namespace NGrib.Grib2.Templates.ProductDefinitions +namespace NGrib.Grib2.Templates.ProductDefinitions; + +/// +/// Product definition template 4.12: Derived forecasts based on all ensemble members at a horizontal level +/// or in a horizontal layer in a continuous or non-continuous time interval. +/// +public class ProductDefinition0012 : ProductDefinition0002 { - /// - /// Product definition template 4.12: Derived forecasts based on all ensemble members at a horizontal level - /// or in a horizontal layer in a continuous or non-continuous time interval. - /// - public class ProductDefinition0012 : ProductDefinition0002 - { - /// - /// Time of end of overall time interval - /// - public DateTime OverallTimeIntervalEnd { get; } - - /// - /// Number of time range specifications describing the time intervals used to calculate the statistically processed field. - /// - public int TimeRangeNumber { get; } - - /// - /// Total number of data values missing in statistical process. - /// - public long MissingDataValuesTotalNumber { get; } - - /// - /// Statistical process used to calculate the processed field from the field at each time increment during the time range. - /// - public int StatisticalProcess { get; } - - /// - /// Type of time increment between successive fields used in the statistical processing. - /// - public long StatisticalProcessingTimeIncrementType { get; } - - /// - /// Indicator of unit of time for time range over which statistical processing is done. - /// - public TimeRangeUnit StatisticalProcessingTimeRangeUnit { get; } - - /// - /// Length of the time range over which statistical processing is done, in units defined by StatisticalProcessingTimeRangeUnit. - /// - public long StatisticalProcessingTimeRangeLength { get; } - - /// - /// Indicator of unit of time for the increment between the successive fields used. - /// - public TimeRangeUnit SuccessiveFieldsIncrementUnit { get; } - - /// - /// Time increment between successive fields, in units defined by SuccessiveFieldsIncrementUnit. - /// - public long SuccessiveFieldsTimeIncrement { get; } - - internal ProductDefinition0012(BufferedBinaryReader reader, Discipline discipline) : base(reader, discipline) - { - OverallTimeIntervalEnd = reader.ReadDateTime(); - RegisterContent(ProductDefinitionContent.OverallTimeIntervalEnd, () => OverallTimeIntervalEnd); - - // 42 - TimeRangeNumber = reader.ReadUInt8(); - - // 43-46 - MissingDataValuesTotalNumber = reader.ReadUInt32(); - - //47 - StatisticalProcess = reader.ReadUInt8(); - - //48 - StatisticalProcessingTimeIncrementType = reader.ReadUInt8(); - - //49 - StatisticalProcessingTimeRangeUnit = (TimeRangeUnit)reader.ReadUInt8(); - - //50-53 - StatisticalProcessingTimeRangeLength = reader.ReadUInt32(); - - var timeRange = CalculateTimeRangeFrom(StatisticalProcessingTimeRangeUnit, StatisticalProcessingTimeRangeLength); - if (timeRange.HasValue) - { - RegisterContent(ProductDefinitionContent.StatisticalProcessingTimeRange, () => timeRange.Value); - } - - //54 - SuccessiveFieldsIncrementUnit = (TimeRangeUnit)reader.ReadUInt8(); - - //55-58 - SuccessiveFieldsTimeIncrement = reader.ReadUInt32(); - - var successiveFieldsTimeIncrement = CalculateTimeRangeFrom(SuccessiveFieldsIncrementUnit, SuccessiveFieldsTimeIncrement); - if (successiveFieldsTimeIncrement.HasValue) - { - RegisterContent(ProductDefinitionContent.StatisticalProcessingTimeRange, () => successiveFieldsTimeIncrement.Value); - } - } - } + /// + /// Time of end of overall time interval + /// + public DateTime OverallTimeIntervalEnd { get; } + + /// + /// Number of time range specifications describing the time intervals used to calculate the statistically processed field. + /// + public int TimeRangeNumber { get; } + + /// + /// Total number of data values missing in statistical process. + /// + public long MissingDataValuesTotalNumber { get; } + + /// + /// Statistical process used to calculate the processed field from the field at each time increment during the time range. + /// + public int StatisticalProcess { get; } + + /// + /// Type of time increment between successive fields used in the statistical processing. + /// + public long StatisticalProcessingTimeIncrementType { get; } + + /// + /// Indicator of unit of time for time range over which statistical processing is done. + /// + public TimeRangeUnitGrib2 StatisticalProcessingTimeRangeUnitGrib2 { get; } + + /// + /// Length of the time range over which statistical processing is done, in units defined by StatisticalProcessingTimeRangeUnit. + /// + public long StatisticalProcessingTimeRangeLength { get; } + + /// + /// Indicator of unit of time for the increment between the successive fields used. + /// + public TimeRangeUnitGrib2 SuccessiveFieldsIncrementRangeUnitGrib2 { get; } + + /// + /// Time increment between successive fields, in units defined by SuccessiveFieldsIncrementUnit. + /// + public long SuccessiveFieldsTimeIncrement { get; } + + internal ProductDefinition0012(BufferedBinaryReader reader, Discipline discipline) : base(reader, discipline) + { + OverallTimeIntervalEnd = reader.ReadDateTime(); + RegisterContent(ProductDefinitionContent.OverallTimeIntervalEnd, () => OverallTimeIntervalEnd); + + // 42 + TimeRangeNumber = reader.ReadUInt8(); + + // 43-46 + MissingDataValuesTotalNumber = reader.ReadUInt32(); + + //47 + StatisticalProcess = reader.ReadUInt8(); + + //48 + StatisticalProcessingTimeIncrementType = reader.ReadUInt8(); + + //49 + StatisticalProcessingTimeRangeUnitGrib2 = (TimeRangeUnitGrib2)reader.ReadUInt8(); + + //50-53 + StatisticalProcessingTimeRangeLength = reader.ReadUInt32(); + + var timeRange = CalculateTimeRangeFrom(StatisticalProcessingTimeRangeUnitGrib2, StatisticalProcessingTimeRangeLength); + if (timeRange.HasValue) + { + RegisterContent(ProductDefinitionContent.StatisticalProcessingTimeRange, () => timeRange.Value); + } + + //54 + SuccessiveFieldsIncrementRangeUnitGrib2 = (TimeRangeUnitGrib2)reader.ReadUInt8(); + + //55-58 + SuccessiveFieldsTimeIncrement = reader.ReadUInt32(); + + var successiveFieldsTimeIncrement = CalculateTimeRangeFrom(SuccessiveFieldsIncrementRangeUnitGrib2, SuccessiveFieldsTimeIncrement); + if (successiveFieldsTimeIncrement.HasValue) + { + RegisterContent(ProductDefinitionContent.StatisticalProcessingTimeRange, () => successiveFieldsTimeIncrement.Value); + } + } } \ No newline at end of file diff --git a/src/NGrib/Grib2/Templates/ProductDefinitions/ProductDefinition0040.cs b/src/NGrib/Grib2/Templates/ProductDefinitions/ProductDefinition0040.cs new file mode 100644 index 0000000..c924ac6 --- /dev/null +++ b/src/NGrib/Grib2/Templates/ProductDefinitions/ProductDefinition0040.cs @@ -0,0 +1,20 @@ +using NGrib.Grib2.CodeTables; + +namespace NGrib.Grib2.Templates.ProductDefinitions; + +public class ProductDefinition0040:ProductDefinition0000 +{ + public ChemicalOrPhysicalConsistent ChemicalOrPhysicalConsistent { get; set; } + + protected override void InitGeneratingProcessType(BufferedBinaryReader reader) + { + ChemicalOrPhysicalConsistent = (ChemicalOrPhysicalConsistent)reader.ReadUInt16(); + RegisterContent(ProductDefinitionContent.ChemicalOrPhysicalConsistent, ()=>ChemicalOrPhysicalConsistent); + + base.InitGeneratingProcessType(reader); + } + + internal ProductDefinition0040(BufferedBinaryReader reader, Discipline discipline) : base(reader, discipline) + { + } +} \ No newline at end of file diff --git a/src/NGrib/Grib2/Templates/ProductDefinitions/ProductDefinitionContent.cs b/src/NGrib/Grib2/Templates/ProductDefinitions/ProductDefinitionContent.cs index c23ef35..a3cf7fe 100644 --- a/src/NGrib/Grib2/Templates/ProductDefinitions/ProductDefinitionContent.cs +++ b/src/NGrib/Grib2/Templates/ProductDefinitions/ProductDefinitionContent.cs @@ -18,108 +18,118 @@ */ using NGrib.Grib2.CodeTables; -using System; -namespace NGrib.Grib2.Templates.ProductDefinitions +namespace NGrib.Grib2.Templates.ProductDefinitions; + +/// +/// Catalog of the product definition contents. +/// +public static class ProductDefinitionContent { - /// - /// Catalog of the product definition contents. - /// - public static class ProductDefinitionContent - { - /// - /// Parameter category (see Code Table 4.1). - /// - public static TemplateContent ParameterCategory { get; } = new TemplateContent(); - - /// - /// Parameter number (see Code Table 4.2). - /// - public static TemplateContent ParameterNumber { get; } = new TemplateContent(); - - /// - /// Parameter. - /// - public static TemplateContent Parameter { get; } = new TemplateContent(); - - /// - /// Type of generating process (see Code Table 4.3). - /// - public static TemplateContent GeneratingProcessType { get; } = new TemplateContent(); - - /// - /// Background generating process identifier (defined by originating centre). - /// - public static TemplateContent BackgroundGeneratingProcessId { get; } = new TemplateContent(); - - /// - /// Analysis or forecast generating processes identifier (defined by originating centre). - /// - public static TemplateContent GeneratingProcessId { get; } = new TemplateContent(); - - /// - /// Time span of observational data cutoff after reference time. - /// - public static TemplateContent ObservationalDataCutoff { get; } = new TemplateContent(); - - /// - /// Forecast time. - /// - public static TemplateContent ForecastTime { get; } = new TemplateContent(); - - /// - /// Type of first fixed surface (see Code Table 4.5). - /// - public static TemplateContent FirstFixedSurfaceType { get; } = new TemplateContent(); - - /// - /// Value of first fixed surface. - /// - public static TemplateContent FirstFixedSurfaceValue { get; } = new TemplateContent(); - - /// - /// Type of second fixed surface (see Code Table 4.5). - /// - public static TemplateContent SecondFixedSurfaceType { get; } = new TemplateContent(); - - /// - /// Value of second fixed surface. - /// - public static TemplateContent SecondFixedSurfaceValue { get; } = new TemplateContent(); - - /// - /// Type of ensemble forecast (see Code Table 4.6). - /// - public static TemplateContent EnsembleForecastType { get; } = new TemplateContent(); - - /// - /// Perturbation number. - /// - public static TemplateContent PerturbationNumber { get; } = new TemplateContent(); - - /// - /// Number of forecasts in ensemble. - /// - public static TemplateContent EnsembleForecastsNumber { get; } = new TemplateContent(); - - /// - /// Derived forecast (see Code Table 4.7). - /// - public static TemplateContent DerivedForecast { get; } = new TemplateContent(); - - /// - /// Datetime of end of overall time interval. - /// - public static TemplateContent OverallTimeIntervalEnd { get; } = new TemplateContent(); - - /// - /// Time range over which statistical processing is done. - /// - public static TemplateContent StatisticalProcessingTimeRange { get; } = new TemplateContent(); - - /// - /// Time increment between successive fields. - /// - public static TemplateContent SuccessiveFieldsTimeIncrement { get; } = new TemplateContent(); - } -} + /// + /// Parameter category (see Code Table 4.1). + /// + public static TemplateContent ParameterCategory { get; } = new TemplateContent(); + + /// + /// Parameter number (see Code Table 4.2). + /// + public static TemplateContent ParameterNumber { get; } = new TemplateContent(); + + /// + /// Parameter. + /// + public static TemplateContent Parameter { get; } = new TemplateContent(); + + /// + /// Type of generating process (see Code Table 4.3). + /// + public static TemplateContent GeneratingProcessType { get; } = + new TemplateContent(); + + /// + /// Background generating process identifier (defined by originating centre). + /// + public static TemplateContent BackgroundGeneratingProcessId { get; } = new TemplateContent(); + + /// + /// Analysis or forecast generating processes identifier (defined by originating centre). + /// + public static TemplateContent GeneratingProcessId { get; } = new TemplateContent(); + + /// + /// Time span of observational data cutoff after reference time. + /// + public static TemplateContent ObservationalDataCutoff { get; } = new TemplateContent(); + + /// + /// Forecast time. + /// + public static TemplateContent ForecastTime { get; } = new TemplateContent(); + + /// + /// Type of first fixed surface (see Code Table 4.5). + /// + public static TemplateContent FirstFixedSurfaceType { get; } = + new TemplateContent(); + + /// + /// Value of first fixed surface. + /// + public static TemplateContent FirstFixedSurfaceValue { get; } = new TemplateContent(); + + /// + /// Type of second fixed surface (see Code Table 4.5). + /// + public static TemplateContent SecondFixedSurfaceType { get; } = + new TemplateContent(); + + /// + /// Value of second fixed surface. + /// + public static TemplateContent SecondFixedSurfaceValue { get; } = new TemplateContent(); + + /// + /// Type of ensemble forecast (see Code Table 4.6). + /// + public static TemplateContent EnsembleForecastType { get; } = + new TemplateContent(); + + /// + /// Perturbation number. + /// + public static TemplateContent PerturbationNumber { get; } = new TemplateContent(); + + /// + /// Number of forecasts in ensemble. + /// + public static TemplateContent EnsembleForecastsNumber { get; } = new TemplateContent(); + + /// + /// Derived forecast (see Code Table 4.7). + /// + public static TemplateContent DerivedForecast { get; } = new TemplateContent(); + + /// + /// Datetime of end of overall time interval. + /// + public static TemplateContent OverallTimeIntervalEnd { get; } = new TemplateContent(); + + /// + /// Time range over which statistical processing is done. + /// + public static TemplateContent StatisticalProcessingTimeRange { get; } = + new TemplateContent(); + + /// + /// Time increment between successive fields. + /// + public static TemplateContent SuccessiveFieldsTimeIncrement { get; } = + new TemplateContent(); + + /// + /// Atmospheric Chemical Constituent Type + /// + public static TemplateContent ChemicalOrPhysicalConsistent { get; } + = new TemplateContent(); +} \ No newline at end of file diff --git a/src/NGrib/Grib2/Templates/ProductDefinitions/WithBackgroundProductDefinition.cs b/src/NGrib/Grib2/Templates/ProductDefinitions/WithBackgroundProductDefinition.cs index dbb354f..e3402d7 100644 --- a/src/NGrib/Grib2/Templates/ProductDefinitions/WithBackgroundProductDefinition.cs +++ b/src/NGrib/Grib2/Templates/ProductDefinitions/WithBackgroundProductDefinition.cs @@ -19,19 +19,18 @@ using NGrib.Grib2.CodeTables; -namespace NGrib.Grib2.Templates.ProductDefinitions +namespace NGrib.Grib2.Templates.ProductDefinitions; + +public class WithBackgroundProductDefinition : ProductDefinition { - public class WithBackgroundProductDefinition : ProductDefinition - { - /// - /// Background generating process identifier. - /// - public int BackgroundGeneratingProcessIdentifier { get; } + /// + /// Background generating process identifier. + /// + public int BackgroundGeneratingProcessIdentifier { get; } - internal WithBackgroundProductDefinition(BufferedBinaryReader reader, Discipline discipline) : base(reader, - discipline) - { - BackgroundGeneratingProcessIdentifier = reader.ReadUInt8(); - } - } + internal WithBackgroundProductDefinition(BufferedBinaryReader reader, Discipline discipline) : base(reader, + discipline) + { + BackgroundGeneratingProcessIdentifier = reader.ReadUInt8(); + } } \ No newline at end of file diff --git a/src/NGrib/Grib2/Templates/Template.cs b/src/NGrib/Grib2/Templates/Template.cs index 5324c87..91a5d77 100644 --- a/src/NGrib/Grib2/Templates/Template.cs +++ b/src/NGrib/Grib2/Templates/Template.cs @@ -18,61 +18,58 @@ */ using NGrib.Grib2.CodeTables; -using System; -using System.Collections.Generic; -namespace NGrib.Grib2.Templates +namespace NGrib.Grib2.Templates; + +public abstract class Template { - public abstract class Template - { - private readonly Dictionary> _accessors = new Dictionary>(); + private readonly Dictionary> _accessors = new Dictionary>(); - protected Template() - { - } + protected Template() + { + } - protected void RegisterContent(TemplateContent content, Func accesor) - { - _accessors[content] = () => accesor(); - } + protected void RegisterContent(TemplateContent content, Func accesor) + { + _accessors[content] = () => accesor(); + } - public bool TryGet(TemplateContent content, out T result) - { - if (_accessors.TryGetValue(content, out var methodInfo)) - { - result = (T) methodInfo.Invoke(); - return true; - } + public bool TryGet(TemplateContent content, out T result) + { + if (_accessors.TryGetValue(content, out var methodInfo)) + { + result = (T) methodInfo.Invoke(); + return true; + } - result = default; - return false; - } + result = default; + return false; + } - protected TimeSpan? CalculateTimeRangeFrom(TimeRangeUnit rangeUnit, long value) - { - switch(rangeUnit) - { - case TimeRangeUnit.Minute: - return TimeSpan.FromMinutes(value); - case TimeRangeUnit.Hour: - return TimeSpan.FromHours(value); - case TimeRangeUnit.Day: - return TimeSpan.FromDays(value); - case TimeRangeUnit.Month: - return TimeSpan.FromDays(value); - case TimeRangeUnit.Hours3: - return TimeSpan.FromHours(value*3); - case TimeRangeUnit.Hours6: - return TimeSpan.FromDays(value*6); - case TimeRangeUnit.Hours12: - return TimeSpan.FromDays(value*12); - case TimeRangeUnit.Second: - return TimeSpan.FromSeconds(value); - default: - // The other TimeRangeUnit (i.e. Month) can't be - // converted to a TimeSpan without some convention. - return null; - } - } - } -} + protected TimeSpan? CalculateTimeRangeFrom(TimeRangeUnitGrib2 rangeUnitGrib2, long value) + { + switch(rangeUnitGrib2) + { + case TimeRangeUnitGrib2.Minute: + return TimeSpan.FromMinutes(value); + case TimeRangeUnitGrib2.Hour: + return TimeSpan.FromHours(value); + case TimeRangeUnitGrib2.Day: + return TimeSpan.FromDays(value); + case TimeRangeUnitGrib2.Month: + return TimeSpan.FromDays(value); + case TimeRangeUnitGrib2.Hours3: + return TimeSpan.FromHours(value*3); + case TimeRangeUnitGrib2.Hours6: + return TimeSpan.FromDays(value*6); + case TimeRangeUnitGrib2.Hours12: + return TimeSpan.FromDays(value*12); + case TimeRangeUnitGrib2.Second: + return TimeSpan.FromSeconds(value); + default: + // The other TimeRangeUnit (i.e. Month) can't be + // converted to a TimeSpan without some convention. + return null; + } + } +} \ No newline at end of file diff --git a/src/NGrib/Grib2/Templates/TemplateContent.cs b/src/NGrib/Grib2/Templates/TemplateContent.cs index bd1b5c0..8043127 100644 --- a/src/NGrib/Grib2/Templates/TemplateContent.cs +++ b/src/NGrib/Grib2/Templates/TemplateContent.cs @@ -17,21 +17,20 @@ * along with NGrib. If not, see . */ -namespace NGrib.Grib2.Templates +namespace NGrib.Grib2.Templates; + +public abstract class TemplateContent { - public abstract class TemplateContent - { - protected TemplateContent() - { - } - } + protected TemplateContent() + { + } +} #pragma warning disable S2326 // Unused type parameters should be removed - public class TemplateContent : TemplateContent +public class TemplateContent : TemplateContent #pragma warning restore S2326 // Unused type parameters should be removed - { - internal TemplateContent() : base() - { - } - } -} +{ + internal TemplateContent() : base() + { + } +} \ No newline at end of file diff --git a/src/NGrib/Grib2/Templates/TemplateFactory.cs b/src/NGrib/Grib2/Templates/TemplateFactory.cs index da2159c..b68c196 100644 --- a/src/NGrib/Grib2/Templates/TemplateFactory.cs +++ b/src/NGrib/Grib2/Templates/TemplateFactory.cs @@ -17,56 +17,53 @@ * along with NGrib. If not, see . */ -using System; using System.Collections; -using System.Collections.Generic; -namespace NGrib.Grib2.Templates +namespace NGrib.Grib2.Templates; + +internal class TemplateFactory : IEnumerable>> { - internal class TemplateFactory : IEnumerable>> - { - /// - /// Methods available to build T from a templateNumber. - /// - /// - /// We use Stack instead of List (or even Dictionary) to provide an easy way to override or extend - /// the default factories. - /// - private readonly Dictionary> factories; + /// + /// Methods available to build T from a templateNumber. + /// + /// + /// We use Stack instead of List (or even Dictionary) to provide an easy way to override or extend + /// the default factories. + /// + private readonly Dictionary> factories; - public TemplateFactory() - { - factories = new Dictionary>(); - } + public TemplateFactory() + { + factories = new Dictionary>(); + } - /// - /// Add a new factory method. - /// - internal void Add(int templateNumber, Func factoryMethod) - { - if (factoryMethod == null) throw new ArgumentNullException(nameof(factoryMethod)); + /// + /// Add a new factory method. + /// + internal void Add(int templateNumber, Func factoryMethod) + { + if (factoryMethod == null) throw new ArgumentNullException(nameof(factoryMethod)); - factories[templateNumber] = (reader, objects) => factoryMethod(reader); - } + factories[templateNumber] = (reader, objects) => factoryMethod(reader); + } - /// - /// Add a new factory method. - /// - internal void Add(int templateNumber, Func factoryMethod) - { - factories[templateNumber] = factoryMethod ?? throw new ArgumentNullException(nameof(factoryMethod)); - } + /// + /// Add a new factory method. + /// + internal void Add(int templateNumber, Func factoryMethod) + { + factories[templateNumber] = factoryMethod ?? throw new ArgumentNullException(nameof(factoryMethod)); + } - internal T Build(BufferedBinaryReader reader, int templateNumber, params object[] args) - { - return factories.TryGetValue(templateNumber, out var factory) - ? factory(reader, args) - : default; - } + internal T Build(BufferedBinaryReader reader, int templateNumber, params object[] args) + { + return factories.TryGetValue(templateNumber, out var factory) + ? factory(reader, args) + : default; + } - public IEnumerator>> GetEnumerator() => - factories.GetEnumerator(); + public IEnumerator>> GetEnumerator() => + factories.GetEnumerator(); - IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); - } + IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); } \ No newline at end of file diff --git a/src/NGrib/Grib2Reader.cs b/src/NGrib/Grib2Reader.cs index 0df870d..20f5558 100644 --- a/src/NGrib/Grib2Reader.cs +++ b/src/NGrib/Grib2Reader.cs @@ -24,129 +24,84 @@ * along with NGrib. If not, see . */ -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; using NGrib.Grib2; using NGrib.Grib2.Sections; -namespace NGrib -{ - /// - /// Reads GRIB 2 data format. - /// - public class Grib2Reader : IDisposable - { - private readonly BufferedBinaryReader reader; - - /// - /// Initializes a new instance of the Grib2Reader class - /// based on the specified file. - /// - /// The GRIB 2 file path. - public Grib2Reader(string filePath, int bufferSize = 4096) : this(File.OpenRead(filePath), false, bufferSize) - { } - - /// - /// Initializes a new instance of the Grib2Reader class - /// based on the specified stream. - /// - /// The GRIB 2 input stream. - /// trueto leave the stream open after the object is disposed; otherwise, false. - public Grib2Reader(Stream input, bool leaveOpen = false, int bufferSize = 4096) - { - if (input == null) throw new ArgumentNullException(nameof(input)); - if (!input.CanRead) throw new ArgumentException("The stream must support reading.", nameof(input)); - if (!input.CanSeek) throw new ArgumentException("The stream must support seeking.", nameof(input)); - - reader = new BufferedBinaryReader(input, leaveOpen, bufferSize); - } - - /// - /// Enumerates the messages in the underlying stream. - /// - /// The messages in the GRIB 2 stream. - public IEnumerable ReadMessages() - { - reader.Seek(0, SeekOrigin.Begin); - - do - { - var indicatorSection = IndicatorSection.BuildFrom(reader); - var identificationSection = IdentificationSection.BuildFrom(reader); - - var message = new Message(indicatorSection, identificationSection); - - LocalUseSection localUseSection = null; - do - { - if (reader.PeekSection().Is(SectionCode.LocalUseSection)) - { - localUseSection = LocalUseSection.BuildFrom(reader); - } - - while (reader.PeekSection().Is(SectionCode.GridDefinitionSection)) - { - var gridDefinitionSection = GridDefinitionSection.BuildFrom(reader); - - while (reader.PeekSection().Is(SectionCode.ProductDefinitionSection)) - { - var productDefinitionSection = ProductDefinitionSection.BuildFrom(reader, indicatorSection.Discipline); - var dataRepresentationSection = DataRepresentationSection.BuildFrom(reader); +namespace NGrib; - var bitmapSection = BitmapSection.BuildFrom(reader, dataRepresentationSection.DataPointsNumber); - - var dataSection = DataSection.BuildFrom(reader); - - message.AddDataset( - localUseSection, - gridDefinitionSection, - productDefinitionSection, - dataRepresentationSection, - bitmapSection, - dataSection); - } - } - } while (!reader.PeekSection().Is(SectionCode.EndSection)); - EndSection.BuildFrom(reader); - - // Saves and restore the current position - // to avoid losing track of the current message - // if a data set read happens during the enumeration - var currentPosition = reader.Position; - yield return message; - reader.Seek(currentPosition, SeekOrigin.Begin); - - } while (!reader.HasReachedStreamEnd && reader.PeekSection().Is(SectionCode.IndicatorSection)); - } - - /// - /// Enumerates every data sets for each messages in the underlying GRIB 2 stream. - /// - /// Enumeration of every data sets in the underlying GRIB 2 stream. - public IEnumerable ReadAllDataSets() => ReadMessages().SelectMany(m => m.DataSets); - - /// - /// Read the data set floating point values. - /// - /// The data set to read. - /// The data set point values. - public IEnumerable ReadDataSetRawData(DataSet dataSet) => dataSet.GetRawData(reader); - - /// - /// Read the data set grid value. - /// - /// The data set to read. - /// The data set grid points and the corresponding values. - public IEnumerable> ReadDataSetValues(DataSet dataSet) => dataSet.GetData(reader); - - /// - /// Releases the resources used by the . - /// - public void Dispose() - { - reader?.Dispose(); - } - } -} +/// +/// Reads GRIB 2 data format. +/// +public class Grib2Reader : IDisposable +{ + private readonly BufferedBinaryReader reader; + private readonly Grib2File _grib2File = new(); + + /// + /// Initializes a new instance of the Grib2Reader class + /// based on the specified file. + /// + /// The GRIB 2 file path. + public Grib2Reader(string filePath, int bufferSize = 4096) : this(File.OpenRead(filePath), false, bufferSize) + { } + + /// + /// Initializes a new instance of the Grib2Reader class + /// based on the specified stream. + /// + /// The GRIB 2 input stream. + /// trueto leave the stream open after the object is disposed; otherwise, false. + public Grib2Reader(Stream input, bool leaveOpen = false, int bufferSize = 4096) + { + if (input == null) throw new ArgumentNullException(nameof(input)); + if (!input.CanRead) throw new ArgumentException("The stream must support reading.", nameof(input)); + if (!input.CanSeek) throw new ArgumentException("The stream must support seeking.", nameof(input)); + + reader = new BufferedBinaryReader(input, leaveOpen, bufferSize); + } + + /// + /// Enumerates the messages in the underlying stream. + /// + /// The messages in the GRIB 2 stream. + public IEnumerable ReadMessages() + { + reader.Seek(0, SeekOrigin.Begin); + + do + { + var message = _grib2File.ReadGrib2Message(reader, out var currentPosition); + yield return message; + reader.Seek(currentPosition, SeekOrigin.Begin); + + } while (!reader.HasReachedStreamEnd && reader.PeekSection().Is(SectionCode.IndicatorSection)); + } + + /// + /// Enumerates every data sets for each messages in the underlying GRIB 2 stream. + /// + /// Enumeration of every data sets in the underlying GRIB 2 stream. + public IEnumerable ReadAllDataSets() => ReadMessages().SelectMany(m => m.DataSets); + + /// + /// Read the data set floating point values. + /// + /// The data set to read. + /// The data set point values. + public IEnumerable ReadDataSetRawData(DataSet dataSet) => dataSet.GetRawData(reader); + + /// + /// Read the data set grid value. + /// + /// The data set to read. + /// The data set grid points and the corresponding values. + public IEnumerable> ReadDataSetValues(DataSet dataSet) => dataSet.GetData(reader); + + /// + /// Releases the resources used by the . + /// + public void Dispose() + { + reader?.Dispose(); + } +} \ No newline at end of file diff --git a/src/NGrib/GribReader.cs b/src/NGrib/GribReader.cs new file mode 100644 index 0000000..cdd43ab --- /dev/null +++ b/src/NGrib/GribReader.cs @@ -0,0 +1,38 @@ +using NGrib.Common; + +namespace NGrib; + +public class GribReader:IDisposable +{ + private readonly Stream _stream; + private readonly bool _leaveOpen; + private readonly CommonGribFile _common = new(); + public GribReader(Stream stream, bool leaveOpen = false) + { + _stream = stream; + _leaveOpen = leaveOpen; + } + + public IEnumerable GetMessages() + { + var position = _stream.Position; + + while(true) + { + var message = _common.GetMessage(_stream); + if (message ==null) + break; + var positionInner = _stream.Position; + yield return message; + _stream.Seek(positionInner, SeekOrigin.Begin); + }; + + _stream.Position = position; + } + + public void Dispose() + { + if (!_leaveOpen) + _stream?.Dispose(); + } +} \ No newline at end of file diff --git a/src/NGrib/Helpers/ScanMode.cs b/src/NGrib/Helpers/ScanMode.cs new file mode 100644 index 0000000..0c50171 --- /dev/null +++ b/src/NGrib/Helpers/ScanMode.cs @@ -0,0 +1,28 @@ +namespace NGrib.Helpers; +/// +/// Adopted from JGribX +/// +public class ScanMode +{ + public bool IsXIncrement { get; set; } + + public bool IsYIncrement { get; set; } + + public bool IsNortherly { get; set; } + + public bool RowsZigzag { get; set; } + + public bool IsXDirectionEvenOffset { get; set; } + + public bool IsXDirectionOddRowsOffset { get; set; } + + public bool IsYDirectionOffset { get; set; } + + public bool RowsNxNyPoints { get; set; } + public ScanMode(int formatCode) + { + IsXIncrement = formatCode.GetBit(3); + IsYIncrement = formatCode.GetBit(4); + IsNortherly = formatCode.GetBit(5); + } +} \ No newline at end of file diff --git a/src/NGrib/NGrib.csproj b/src/NGrib/NGrib.csproj index 4b40cfc..70e3ea9 100644 --- a/src/NGrib/NGrib.csproj +++ b/src/NGrib/NGrib.csproj @@ -1,36 +1,39 @@ - - - - netstandard2.0 - latest - true - 0.8.0 - Nicolas Mangué - - NGrib is a .NET Standard library to read GRIB (GRid in Binary) files. GRIB is a gridded data standard from WMO (World Meteorological Organisation) and is used by many meteorological organisation. - Copyright ©2021 - LGPL-3.0-or-later - https://github.com/nmangue/NGrib - https://github.com/nmangue/NGrib.git - git - Add support for Data Representation Template 5.50002 - 0.8.0.0 - 0.8.0.0 - - - - true - snupkg - - - - - - - - - - - - - + + + + net6.0 + latest + true + 0.8.0 + Nicolas Mangué + + NGrib is a .NET Standard library to read GRIB (GRid in Binary) files. GRIB is a gridded data standard from WMO (World Meteorological Organisation) and is used by many meteorological organisation. + Copyright ©2021 + LGPL-3.0-or-later + https://github.com/nmangue/NGrib + https://github.com/nmangue/NGrib.git + git + Add support for Data Representation Template 5.50002 + 0.8.0.0 + 0.8.0.0 + + + + true + snupkg + disable + enable + + + + + + + + + + + + + + diff --git a/src/NGrib/UnexpectedGribSectionException.cs b/src/NGrib/UnexpectedGribSectionException.cs index 28c0bfd..02035c4 100644 --- a/src/NGrib/UnexpectedGribSectionException.cs +++ b/src/NGrib/UnexpectedGribSectionException.cs @@ -19,22 +19,21 @@ using NGrib.Grib2.Sections; -namespace NGrib +namespace NGrib; + +/// +/// The exception that is thrown when the read section number is not +/// the expected one. +/// +public class UnexpectedGribSectionException : BadGribFormatException { - /// - /// The exception that is thrown when the read section number is not - /// the expected one. - /// - public class UnexpectedGribSectionException : BadGribFormatException - { - /// - /// Initializes a new instance of the class. - /// - /// The expected section code. - /// The section code actually read. - public UnexpectedGribSectionException(SectionCode expectedSectionCode, int readSectionCode) - : base($"Expected section {expectedSectionCode} but found {readSectionCode}") - { - } - } + /// + /// Initializes a new instance of the class. + /// + /// The expected section code. + /// The section code actually read. + public UnexpectedGribSectionException(SectionCode expectedSectionCode, int readSectionCode) + : base($"Expected section {expectedSectionCode} but found {readSectionCode}") + { + } } \ No newline at end of file diff --git a/tmp/BadGribFormatException.cs b/tmp/BadGribFormatException.cs new file mode 100644 index 0000000..8200e7f --- /dev/null +++ b/tmp/BadGribFormatException.cs @@ -0,0 +1,43 @@ +/* + * This file is part of NGrib. + * + * Copyright © 2020 Nicolas Mangué + * + * Copyright 2006-2010 Seaware AB, PO Box 1244, SE-131 28 + * Nacka Strand, Sweden, info@seaware.se. + * + * Copyright 1997-2006 Unidata Program Center/University + * Corporation for Atmospheric Research, P.O. Box 3000, Boulder, CO 80307, + * support@unidata.ucar.edu. + * + * NGrib is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * NGrib is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with NGrib. If not, see . + */ + +namespace NGrib; + +/// +/// The exception that is thrown when the read stream does not +/// respect the GRIB 2 data format. +/// +public class BadGribFormatException : Exception +{ + /// + /// Initializes a new instance of the class + /// with a specified error message. + /// + /// The message that describes the error. + public BadGribFormatException(string message) : base(message) + { + } +} \ No newline at end of file diff --git a/tmp/BigEndianBitConverter.cs b/tmp/BigEndianBitConverter.cs new file mode 100644 index 0000000..b7d3a12 --- /dev/null +++ b/tmp/BigEndianBitConverter.cs @@ -0,0 +1,98 @@ +/* + * This file is part of NGrib. + * + * Copyright © 2020 Nicolas Mangué + * + * Copyright 2006-2010 Seaware AB, PO Box 1244, SE-131 28 + * Nacka Strand, Sweden, info@seaware.se. + * + * Copyright 1997-2006 Unidata Program Center/University + * Corporation for Atmospheric Research, P.O. Box 3000, Boulder, CO 80307, + * support@unidata.ucar.edu. + * + * NGrib is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * NGrib is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with NGrib. If not, see . + */ + +using System.Numerics; + +namespace NGrib; + +internal static class BigEndianBitConverter +{ + public const int Int8MinValue = -127; + public const int Int32MinValue = -2147483647; + + public static int ToInt8(byte[] data, int startIndex) => ToInt8(data[startIndex]); + + public static int ToInt8(byte data) => (1 - ((data & 128) >> 6)) * (data & 127); + + public static int ToUInt16(byte[] data, int startIndex) + { + var index = startIndex; + return (data[index++] << 8) | data[index]; + } + + public static int ToInt16(byte[] data, int startIndex) + { + var index = startIndex; + return (1 - ((data[index] & 128) >> 6)) * ((data[index++] & 127) << 8 | data[index]); + } + + public static long ToUInt32(byte[] data, int startIndex) + { + var index = startIndex; + return ((uint) data[index++] << 24) | + ((uint) data[index++] << 16) | + ((uint) data[index++] << 8) | + data[index]; + } + + public static BigInteger ToUInt64(byte[] data, int startIndex) + { + var index = startIndex; + return ((ulong) data[index++] << 56) | + ((ulong) data[index++] << 48) | + ((ulong) data[index++] << 40) | + ((ulong) data[index++] << 32) | + ((ulong) data[index++] << 24) | + ((ulong) data[index++] << 16) | + ((ulong) data[index++] << 8) | + data[index]; + } + + public static int ToInt32(byte[] data, int startIndex) + { + var index = startIndex; + return (1 - ((data[index] & 128) >> 6)) * ((data[index++] & 127) << 24 | + data[index++] << 16 | + data[index++] << 8 | + data[index]); + } + + public static float ToSingle(byte[] data, int startIndex) + { + if (BitConverter.IsLittleEndian) + { + var reversedBytes = new[] + { + data[startIndex+3], + data[startIndex+2], + data[startIndex+1], + data[startIndex] + }; + return BitConverter.ToSingle(reversedBytes, 0); + } + return BitConverter.ToSingle(data, startIndex); + } +} \ No newline at end of file diff --git a/tmp/BufferedBinaryReader.cs b/tmp/BufferedBinaryReader.cs new file mode 100644 index 0000000..5e9fc1a --- /dev/null +++ b/tmp/BufferedBinaryReader.cs @@ -0,0 +1,323 @@ +/* + * This file is part of NGrib. + * + * Copyright © 2020 Nicolas Mangué + * + * NGrib is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * NGrib is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with NGrib. If not, see . + */ + +using System.Numerics; +using NGrib.Grib2.Sections; + +namespace NGrib; + +/// +/// Based on Jackson Dunstan implementation . +/// +public class BufferedBinaryReader : IDisposable +{ + private readonly Stream stream; + private readonly bool leaveOpen; + private readonly byte[] buffer; + private readonly int bufferSize; + private int bufferOffset; + private int numBufferedBytes; + private long savedPosition; + private int NumBytesAvailable => Math.Max(0, numBufferedBytes - bufferOffset); + + public bool HasReachedStreamEnd => stream.Position >= stream.Length && NumBytesAvailable <= 0; + + public BufferedBinaryReader(Stream stream, bool leaveOpen = false, int bufferSize = 4096) + { + this.stream = stream; + this.leaveOpen = leaveOpen; + this.bufferSize = bufferSize; + buffer = new byte[bufferSize]; + MarkBufferAsUsed(); + SaveCurrentPosition(); + } + + private bool FillBuffer() + { + var numBytesUnread = bufferSize - bufferOffset; + var numBytesToRead = bufferSize - numBytesUnread; + bufferOffset = 0; + numBufferedBytes = numBytesUnread; + if (numBytesUnread > 0) + { + Buffer.BlockCopy(buffer, numBytesToRead, buffer, 0, numBytesUnread); + } + while (numBytesToRead > 0) + { + var numBytesRead = stream.Read(buffer, numBytesUnread, numBytesToRead); + if (numBytesRead == 0) + { + return false; + } + numBufferedBytes += numBytesRead; + numBytesToRead -= numBytesRead; + numBytesUnread += numBytesRead; + } + return true; + } + + private void EnsureAvailable(int numBytes) + { + if (NumBytesAvailable >= numBytes) return; + + // Try to read from the stream + // and check that we were able to read the bytes we wanted + if (!FillBuffer() && NumBytesAvailable < numBytes) + { + throw new IndexOutOfRangeException(); + } + } + + public byte ReadByte() + { + EnsureAvailable(sizeof(byte)); + var val = buffer[bufferOffset]; + bufferOffset += sizeof(byte); + return val; + } + + public int ReadUInt8() => ReadByte(); + + public int ReadInt8() => BigEndianBitConverter.ToInt8(ReadByte()); + + public int ReadUInt16() + { + EnsureAvailable(sizeof(short)); + var val = BigEndianBitConverter.ToUInt16(buffer, bufferOffset); + bufferOffset += sizeof(short); + return val; + } + + public int ReadInt16() + { + EnsureAvailable(sizeof(short)); + var val = BigEndianBitConverter.ToInt16(buffer, bufferOffset); + bufferOffset += sizeof(short); + return val; + } + + public long ReadUInt32() + { + EnsureAvailable(sizeof(uint)); + var val = BigEndianBitConverter.ToUInt32(buffer, bufferOffset); + bufferOffset += sizeof(uint); + return val; + } + + public int ReadInt32() + { + EnsureAvailable(sizeof(int)); + var val = BigEndianBitConverter.ToInt32(buffer, bufferOffset); + bufferOffset += sizeof(int); + return val; + } + + /// + /// Read a double value (L) represented by : + /// - a scale factor F (UInt8); + /// - a scaled value V (UInt32); + /// where L * 10^F = V. + /// + /// Original value + public double? ReadScaledValue() + { + var scaleFactor = ReadInt8(); + var scaledValue = ReadInt32(); + + if (scaleFactor == BigEndianBitConverter.Int8MinValue && scaledValue == BigEndianBitConverter.Int32MinValue) + { + // All bits set to 1 means that no value is provided. + return null; + } + + return scaledValue * Math.Pow(10, -scaleFactor); + } + + public void NextUIntN() + { + positionInBbbReadBuffer = 0; + bitByBitReadBuffer = 0; + } + + private int bitByBitReadBuffer; + private int positionInBbbReadBuffer; + public int ReadUIntN(int nbBit) + { + int bitsLeft = nbBit; + int result = 0; + + if (positionInBbbReadBuffer == 0) + { + bitByBitReadBuffer = ReadByte(); + positionInBbbReadBuffer = 8; + } + + while (true) + { + int shift = bitsLeft - positionInBbbReadBuffer; + if (shift > 0) + { + // Consume the entire buffer + result |= bitByBitReadBuffer << shift; + bitsLeft -= positionInBbbReadBuffer; + + // Get the next byte from the RandomAccessFile + bitByBitReadBuffer = ReadByte(); + positionInBbbReadBuffer = 8; + } + else + { + // Consume a portion of the buffer + result |= bitByBitReadBuffer >> -shift; + positionInBbbReadBuffer -= bitsLeft; + bitByBitReadBuffer &= 0xff >> (8 - positionInBbbReadBuffer); // mask off consumed bits + + return result; + } + } + } + + public int ReadIntN(int nbBit) + { + var result = ReadUIntN(nbBit); + return result.AsSignedInt(nbBit); + } + + public BigInteger ReadUInt64() + { + EnsureAvailable(sizeof(ulong)); + var val = BigEndianBitConverter.ToUInt64(buffer, bufferOffset); + bufferOffset += sizeof(ulong); + return val; + } + + public float ReadSingle() + { + EnsureAvailable(sizeof(float)); + var val = BigEndianBitConverter.ToSingle(buffer, bufferOffset); + bufferOffset += sizeof(float); + return val; + } + + public byte[] Read(int numBytes) + { + var result = new byte[numBytes]; + + var numBytesLeftToRead = numBytes; + var resultOffset = 0; + while (numBytesLeftToRead > 0) + { + var numBytesRead = Math.Min(bufferSize, numBytesLeftToRead); + + EnsureAvailable(numBytesRead); + Buffer.BlockCopy(buffer, bufferOffset, result, resultOffset, numBytesRead); + bufferOffset += numBytesRead; + + resultOffset += numBytesRead; + numBytesLeftToRead -= numBytesRead; + } + + return result; + } + + public DateTime ReadDateTime() + { + var year = ReadUInt16(); + var month = ReadUInt8(); + var day = ReadUInt8(); + var hour = ReadUInt8(); + var minute = ReadUInt8(); + var second = ReadUInt8(); + + return new DateTime(year, month, day, hour, minute, second, DateTimeKind.Utc); + } + + public SectionInfo PeekSection() + { + SaveCurrentPosition(); + var info = ReadSectionInfo(); + SeekToSavedPosition(); + return info; + } + + public SectionInfo ReadSectionInfo() + { + var sectionLength = ReadUInt32(); + + if (sectionLength == Constants.GribFileStartCode) + { + return new SectionInfo(Constants.IndicatorSectionLength, SectionCode.IndicatorSection); + } + + if (sectionLength == Constants.GribFileEndCode) + { + return new SectionInfo(Constants.EndSectionLength, SectionCode.EndSection); + } + + var sectionCode = ReadUInt8(); + return new SectionInfo(sectionLength, sectionCode); + } + + public void Skip(int numBytes) + { + if (numBytes <= NumBytesAvailable) + { + bufferOffset += numBytes; + } + else + { + var offset = numBytes - NumBytesAvailable; + stream.Seek(offset, SeekOrigin.Current); + MarkBufferAsUsed(); + } + } + + public void Seek(long offset, SeekOrigin origin) + { + stream.Seek(offset, origin); + MarkBufferAsUsed(); + } + + private void MarkBufferAsUsed() + { + // Mark the buffer as completely used + // to trigger a refill + bufferOffset = bufferSize; + } + + public void Dispose() + { + if (!leaveOpen) + { + stream.Close(); + } + } + + public void SaveCurrentPosition() + { + savedPosition = Position; + } + + public long Position => stream.Position - NumBytesAvailable; + + public void SeekToSavedPosition() + { + Seek(savedPosition, SeekOrigin.Begin); + } +} \ No newline at end of file diff --git a/tmp/Common/Adapters/Grib1FileAdapter.cs b/tmp/Common/Adapters/Grib1FileAdapter.cs new file mode 100644 index 0000000..ea4012f --- /dev/null +++ b/tmp/Common/Adapters/Grib1FileAdapter.cs @@ -0,0 +1,23 @@ +using System.Collections; +using NGrib.Grib1; + +namespace NGrib.Common.Adapters; + +public class Grib1FileAdapter:IGribFile +{ + private readonly Grib1File _grib1File; + private readonly Hashtable _hashtable = new(); + Grib1GridDefinitionSection gds = null; + public Grib1FileAdapter(Grib1File grib1File) + { + _grib1File = grib1File; + } + + public IGribMessage GetMessage(Stream stream) + { + var message = + _grib1File.ReadGrib1Record(stream, stream.Position, _hashtable, ref gds); + return new Grib1MessageAdapter(message, _grib1File, stream); + } + +} \ No newline at end of file diff --git a/tmp/Common/Adapters/Grib1MessageAdapter.cs b/tmp/Common/Adapters/Grib1MessageAdapter.cs new file mode 100644 index 0000000..822e020 --- /dev/null +++ b/tmp/Common/Adapters/Grib1MessageAdapter.cs @@ -0,0 +1,84 @@ +using System.Data; +using System.Diagnostics; +using NGrib.Grib1; +using NGrib.Grib1.PdsParameterTables; + +namespace NGrib.Common.Adapters; + +public class Grib1MessageAdapter : IGribMessage +{ + private Grib1Record _record; + private Grib1File _grib1File; + private readonly Stream _stream; + + public Grib1MessageAdapter(Grib1Record @record, Grib1File grib1File, Stream stream) + { + _record = record; + _grib1File = grib1File; + _stream = stream; + } + + public string Name => _record.ProductDefinitionSection.Parameter.Name; + + public DateTime Time => GetForecastTime(); + + + public IEnumerable> GetData() + { + var rawData = + _grib1File.getData(_stream, _record.DataOffset, + _record.ProductDefinitionSection.DecimalScale, false); + return _record.GridDefinitionSection.EnumerateGridPoints() + .Zip(rawData, (c, v) => new KeyValuePair(c, v)); + } + + public int Version => 1; + + public int ParameterHash + { + get + { + var parametr = _record.ProductDefinitionSection; + if (parametr.WaveSpectra2DDirFreq != null) + throw new DataException("Нестандартная секция"); + return (parametr.Center, parametr.Description, parametr.P1, parametr.P2, parametr.Parameter.Description, + parametr.Parameter.Name, parametr.Parameter.Number, parametr.Parameter.Unit, + parametr.Type, parametr.Unit, parametr.CustomData, parametr.DecimalScale, parametr.Grid_Id, + parametr.LengthErr, parametr.LevelName, parametr.LevelValue1, parametr.LevelValue2, + parametr.ParameterNumber, parametr.Process_Id, parametr.ProductDefinition, + parametr.SubCenter, parametr.TableVersion, parametr.TimeUnit, parametr.TimeRangeUnit) + .GetHashCode(); + } + } + + private DateTime GetForecastTime() + { + var productSection = _record.ProductDefinitionSection; + var baseTime = productSection.BaseTime; + var unit = productSection.TimeRangeUnit; + var unitNumber = productSection.ForecastTime; + + return unit switch + { + TimeRangeUnitGrib1.Day => baseTime.AddDays(unitNumber), + TimeRangeUnitGrib1.Minute => baseTime.AddMinutes(unitNumber), + TimeRangeUnitGrib1.Hour => baseTime.AddHours(unitNumber), + TimeRangeUnitGrib1.Month => baseTime.AddMonths(unitNumber), + TimeRangeUnitGrib1.Year => baseTime.AddYears(unitNumber), + TimeRangeUnitGrib1.Decade => baseTime.AddYears(10 * unitNumber), + TimeRangeUnitGrib1.Normal => baseTime.AddYears(30 * unitNumber), + TimeRangeUnitGrib1.Century => baseTime.AddYears(100 * unitNumber), + TimeRangeUnitGrib1.Hours3 => baseTime.AddHours(3 * unitNumber), + TimeRangeUnitGrib1.Hours6 => baseTime.AddHours(6 * unitNumber), + TimeRangeUnitGrib1.Hours12 => baseTime.AddHours(12 * unitNumber), + TimeRangeUnitGrib1.Minutes15 => baseTime.AddMinutes(15 * unitNumber), + TimeRangeUnitGrib1.Minutes30 => baseTime.AddMinutes(30 * unitNumber), + TimeRangeUnitGrib1.Second => baseTime.AddSeconds(unitNumber), + TimeRangeUnitGrib1.Reserved => + throw new NotSupportedException("Ключ формата был зарезервирован в стандарте и не реализован"), + TimeRangeUnitGrib1.Missing => + throw new NotSupportedException("Ключ формата отсутствовал в стандарте и не реализован"), + _ => throw new NotSupportedException("Поведение для этого заначения ключа не было реализовано") + }; + } +} \ No newline at end of file diff --git a/tmp/Common/Adapters/Grib2FileAdapter.cs b/tmp/Common/Adapters/Grib2FileAdapter.cs new file mode 100644 index 0000000..5caad8d --- /dev/null +++ b/tmp/Common/Adapters/Grib2FileAdapter.cs @@ -0,0 +1,21 @@ +using NGrib.Grib2; + +namespace NGrib.Common.Adapters; + +public class Grib2FileAdapter:IGribFile +{ + private readonly Grib2File _grib2File; + + public Grib2FileAdapter(Grib2File grib2File) + { + _grib2File = grib2File; + } + + public IGribMessage GetMessage(Stream stream) + { + using var reader = new BufferedBinaryReader(stream, true); + var message = _grib2File.ReadGrib2Message(reader, out var currentPosition); + stream.Seek(currentPosition, SeekOrigin.Begin); + return new Grib2MessageAdapter(message, stream); + } +} \ No newline at end of file diff --git a/tmp/Common/Adapters/Grib2MessageAdapter.cs b/tmp/Common/Adapters/Grib2MessageAdapter.cs new file mode 100644 index 0000000..13561ce --- /dev/null +++ b/tmp/Common/Adapters/Grib2MessageAdapter.cs @@ -0,0 +1,85 @@ +using NGrib.Grib2; +using NGrib.Grib2.CodeTables; +using NGrib.Grib2.Templates.ProductDefinitions; + +namespace NGrib.Common.Adapters; + +public class Grib2MessageAdapter : IGribMessage +{ + private readonly Message _message; + private readonly Stream _stream; + + public Grib2MessageAdapter(Message message, Stream stream) + { + _message = message; + _stream = stream; + } + + public int GribVersion => 2; + + public string Name => _message.DataSets.Single() + .ProductDefinitionSection.ProductDefinition?.Parameter?.Name ?? + (ChemicalOrPhysicalConsistent.HasValue + ? Enum.GetName(typeof(ChemicalOrPhysicalConsistent), ChemicalOrPhysicalConsistent.Value) + : (string) null); + + public DateTime Time + { + get + { + var reference = _message.IdentificationSection.ReferenceTime; + var productDefinition = + (ProductDefinition0000) _message.DataSets.Single().ProductDefinitionSection.ProductDefinition; + var time = productDefinition + .ForecastTime; + var unit = productDefinition.TimeRangeUnitGrib2; + var result = unit switch + { + TimeRangeUnitGrib2.Minute => reference.AddMinutes(time), + TimeRangeUnitGrib2.Hour => reference.AddHours(time), + TimeRangeUnitGrib2.Day => reference.AddDays(time), + TimeRangeUnitGrib2.Month => reference.AddMonths(time), + TimeRangeUnitGrib2.Year => reference.AddYears(time), + TimeRangeUnitGrib2.Decade => reference.AddYears(10 * time), + TimeRangeUnitGrib2.Normal => reference.AddYears(30 * time), + TimeRangeUnitGrib2.Century => reference.AddYears(100 * time), + TimeRangeUnitGrib2.Hours3 => reference.AddHours(3 * time), + TimeRangeUnitGrib2.Hours6 => reference.AddHours(6 * time), + TimeRangeUnitGrib2.Hours12 => reference.AddHours(12 * time), + TimeRangeUnitGrib2.Second => reference.AddSeconds(time), + TimeRangeUnitGrib2.Missing => + throw new NotSupportedException("Код единицы измерения на момент реализации отсустствовал"), + _ => throw new NotSupportedException("Логика для этого кода единицы измерения не была примененена в этой функции") + }; + return result; + } + } + + public ChemicalOrPhysicalConsistent? ChemicalOrPhysicalConsistent => + (_message.DataSets.Single().ProductDefinitionSection.ProductDefinition as ProductDefinition0040) + ?.ChemicalOrPhysicalConsistent; + + public int? StartStep => + (_message.DataSets.Single().ProductDefinitionSection.ProductDefinition as ProductDefinition0000) + ?.HoursAfter; + + + public IEnumerable> GetData() + { + using var reader = new BufferedBinaryReader(_stream, true); + return _message.DataSets.Single().GetData(reader); + } + + public int Version => 2; + + public int ParameterHash + { + get + { + var param = _message.IdentificationSection; + return (param.Section,param.Length,param.Center,param.CenterCode,param.ProductStatus, + param.ProductType,param.LocalTableVersion,param.MasterTableVersion, + param.ReferenceTimeSignificance,param.SubCenterCode,param).GetHashCode(); + } + } +} \ No newline at end of file diff --git a/tmp/Common/CommonGribFile.cs b/tmp/Common/CommonGribFile.cs new file mode 100644 index 0000000..f9f3da2 --- /dev/null +++ b/tmp/Common/CommonGribFile.cs @@ -0,0 +1,95 @@ +using System.Text; +using NGrib.Common.Adapters; +using NGrib.Grib1; +using NGrib.Grib2; + +namespace NGrib.Common; + +public class CommonGribFile : IGribFile +{ + private readonly Grib1FileAdapter _grib1File = new(new Grib1File()); + private readonly Grib2FileAdapter _grib2File = new(new Grib2File()); + + + public static bool SeekHeader(Stream raf, long stop, out long startOffset) + { + // seek header + StringBuilder hdr = new StringBuilder(); + int match = 0; + startOffset = -1; + + while (raf.Position < stop && raf.Position Grib edition number 1, 2 or 0 not a Grib file. + /// + /// + /// NotSupportedException + /// int 0 not a Grib file, 1 Grib1, 2 Grib2 + /// + private static int GetEdition(Stream InputStream, out long offset) + { + long length = (InputStream.Length < 4000L) ? InputStream.Length :InputStream.Position + 4000L; + if (!SeekHeader(InputStream, length, out offset)) + { + return 0; // not valid Grib file + } + + // Read Section 0 Indicator Section to get Edition number + Grib1IndicatorSection isRenamed = new Grib1IndicatorSection(InputStream); // section 0 + return isRenamed.GribEdition; + } + + public IGribMessage GetMessage(Stream stream) + { + var edition = GetEdition(stream, out var offset); + if (edition == 0 && offset == -1) + return null; + switch (edition) + { + case 1: + stream.Seek(offset+4, SeekOrigin.Begin); + return _grib1File.GetMessage(stream); + case 2: + stream.Seek(offset, SeekOrigin.Begin); + return _grib2File.GetMessage(stream); + default: + throw new NotSupportedException(); + } + } +} \ No newline at end of file diff --git a/tmp/Common/IGribFile.cs b/tmp/Common/IGribFile.cs new file mode 100644 index 0000000..5768a43 --- /dev/null +++ b/tmp/Common/IGribFile.cs @@ -0,0 +1,6 @@ +namespace NGrib.Common; + +public interface IGribFile +{ + IGribMessage GetMessage(Stream stream); +} \ No newline at end of file diff --git a/tmp/Common/IGribMessage.cs b/tmp/Common/IGribMessage.cs new file mode 100644 index 0000000..2271c5c --- /dev/null +++ b/tmp/Common/IGribMessage.cs @@ -0,0 +1,15 @@ +namespace NGrib.Common; + +public interface IGribMessage +{ + DateTime Time { get; } + + string Name { get; } + + IEnumerable> GetData(); + + int Version { get; } + //int ParameterNumber { get; set; } + + int ParameterHash { get; } +} \ No newline at end of file diff --git a/tmp/Constants.cs b/tmp/Constants.cs new file mode 100644 index 0000000..60c57a7 --- /dev/null +++ b/tmp/Constants.cs @@ -0,0 +1,42 @@ +/* + * This file is part of NGrib. + * + * Copyright © 2020 Nicolas Manguй + * + * NGrib is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * NGrib is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with NGrib. If not, see . + */ + +namespace NGrib; + +internal class Constants +{ + public static byte[] GribFileStart = { 0x47, 0x52, 0x49, 0x42 }; + + /// + /// "GRIB" (coded according to the International Alphabet No. 5.) + /// converted to long. + /// + public static long GribFileStartCode = 1196575042; + + public static byte[] GribFileEnd = { 0x37, 0x37, 0x37, 0x37 }; + + /// + /// "7777" (coded according to the International Alphabet No. 5.) + /// converted to long. + /// + public static long GribFileEndCode = 926365495; + + public static long IndicatorSectionLength = 16; + public static long EndSectionLength = 16; +} \ No newline at end of file diff --git a/tmp/Coordinate.cs b/tmp/Coordinate.cs new file mode 100644 index 0000000..8c43548 --- /dev/null +++ b/tmp/Coordinate.cs @@ -0,0 +1,91 @@ +/* + * This file is part of NGrib. + * + * Copyright © 2020 Nicolas Mangué + * + * NGrib is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * NGrib is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with NGrib. If not, see . + */ + +namespace NGrib; + +/// +/// Represents a location on the Earth surface. +/// +public readonly struct Coordinate +{ + private const int CoordinateNbDecimals = 9; // 9 decimals means a 110 microns precision. + private const double CoordinatePrecision = 1e-9; + + private static double ConvertLongitude(double longitude) => longitude >= 180d ? longitude - 360d : longitude; + + /// + /// Specifies the north–south position. + /// + public double Latitude { get; } + + /// + /// Specifies the east–west position. + /// + public double Longitude { get; } + + /// + /// Initializes a new instance of the Coordinate class + /// based on the specified file. + /// + /// Latitude of the point. + /// Longitude of the point. + public Coordinate(double latitude, double longitude) + { + Latitude = Math.Round(Math.Max(Math.Min(latitude, 90d), -90d), CoordinateNbDecimals); + var simplyConverted = ConvertLongitude(longitude); + Longitude = Math.Round(simplyConverted is >= -180d and <= 180d ? simplyConverted : SimplifyLongitude(longitude), CoordinateNbDecimals); + + } + + private bool IsOnSameLongitude(Coordinate other) => EqualsWithTolerance(Longitude, other.Longitude) || IsAntimeridian(Longitude) && IsAntimeridian(other.Longitude); + + private static bool IsAntimeridian(double longitude) => EqualsWithTolerance(Math.Abs(longitude), 180); + + public bool Equals(Coordinate other) => EqualsWithTolerance(Latitude, other.Latitude) && IsOnSameLongitude(other); + + public override bool Equals(object obj) => obj is Coordinate other && Equals(other); + + private static bool EqualsWithTolerance(double a, double b) => Math.Abs(a - b) <= CoordinatePrecision; + + public override int GetHashCode() + { + unchecked + { + return (Latitude.GetHashCode() * 397) ^ Longitude.GetHashCode(); + } + } + + public Coordinate Add(double latitudeIncrement, double longitudeIncrement) + { + return new Coordinate(Latitude + latitudeIncrement, Longitude + longitudeIncrement); + } + + private static double SimplifyLongitude(double longitude) + { + var radians = longitude.ToRadians(); + return Math.Atan2(Math.Sin(radians), Math.Cos(radians)).ToDegrees(); + } + + public static implicit operator Coordinate(ValueTuple latLon) => new Coordinate(latLon.Item1, latLon.Item2); + + public override string ToString() + { + return $"{nameof(Latitude)}: {Latitude}, {nameof(Longitude)}: {Longitude}"; + } +} \ No newline at end of file diff --git a/tmp/Extensions.cs b/tmp/Extensions.cs new file mode 100644 index 0000000..2d7d6f0 --- /dev/null +++ b/tmp/Extensions.cs @@ -0,0 +1,74 @@ +/* + * This file is part of NGrib. + * + * Copyright © 2020 Nicolas Mangué + * + * NGrib is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * NGrib is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with NGrib. If not, see . + */ + +namespace NGrib; + +internal static class Extensions +{ + /// + /// Convert to radians. + /// + /// The value to convert to radians + /// The value in radians + public static double ToRadians(this double val) => Math.PI / 180d * val; + + /// + /// Convert to degrees. + /// + /// The value to convert to degrees + /// The value in degrees + public static double ToDegrees(this double val) => 180d / Math.PI * val; + + public static T? As(this int val) where T : struct, Enum, IConvertible + { + if (IsFlagEnum(typeof(T))) + { + + } + return (T?) (Enum.IsDefined(typeof(T), val) ? Enum.ToObject(typeof(T), val) : null); + } + + public static bool IsFlagEnum(Type t) => t.IsEnum && !Attribute.IsDefined(t, typeof(FlagsAttribute)); + + public static int AsSignedInt(this int value, int nbBit) + { + if (value.GetBit(nbBit)) + { + // The sign bit is on => it's negative! + // Reset leading bit + value = value.SetBit(nbBit, false); + // build 2's-complement + value = ~value; + value += 1; + } + + return value; + } + + public static bool GetBit(this int value, int index) + { + var mask = 1 << (index -1); + return (value & mask) > 0; + } + + public static int SetBit(this int value, int index, bool bitValue) + { + return bitValue ? value | (1 << (index - 1)) : value & ~(1 << (index - 1)); + } +} \ No newline at end of file diff --git a/tmp/Grib1/GdsKeys.cs b/tmp/Grib1/GdsKeys.cs new file mode 100644 index 0000000..2ebae55 --- /dev/null +++ b/tmp/Grib1/GdsKeys.cs @@ -0,0 +1,81 @@ +namespace NGrib.Grib1; + +public sealed class GdsKeys +{ + /* + * stores GDS of Grib1 file, there is possibility of more than 1 + */ + //UPGRADE_NOTE: Final was removed from the declaration of 'gdsHM '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'" + //UPGRADE_TODO: Class 'java.util.HashMap' was converted to 'System.Collections.Hashtable' which has a different behavior. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1073_javautilHashMap'" + /// Get GDS's of the GRIB file. + /// + /// + /// gdsHM + /// + //UPGRADE_TODO: Class 'java.util.HashMap' was converted to 'System.Collections.Hashtable' which has a different behavior. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1073_javautilHashMap'" + public System.Collections.Hashtable GdSs { get; } = new(); + + /* + * stores products of Grib file, products have enough info to get the + * metadata about a parameter and the data. products are lightweight + * records. + */ + //UPGRADE_NOTE: Final was removed from the declaration of 'products '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'" + //private Grib1Input _grib1Input; + /// Get products of the GRIB file. + /// + /// + /// products + /// + public System.Collections.ArrayList Products { get; } = new(); + + public void CheckGdSkeys(Grib1GridDefinitionSection gds, System.Collections.Hashtable gdsCounter) + { + // lat/lon grids can have > 1 GDSs + if (gds.GridType == 0 || gds.GridType == 4) + { + return; + } + + String bestKey = ""; + int count = 0; + // find bestKey with the most counts + //UPGRADE_TODO: Method 'java.util.HashMap.keySet' was converted to 'SupportClass.HashSetSupport' which has a different behavior. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1073_javautilHashMapkeySet'" + //UPGRADE_TODO: Method 'java.util.Iterator.hasNext' was converted to 'System.Collections.IEnumerator.MoveNext' which has a different behavior. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1073_javautilIteratorhasNext'" + for (System.Collections.IEnumerator it = new SupportClass.HashSetSupport(gdsCounter.Keys).GetEnumerator(); + it.MoveNext();) + { + //UPGRADE_TODO: Method 'java.util.Iterator.next' was converted to 'System.Collections.IEnumerator.Current' which has a different behavior. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1073_javautilIteratornext'" + String key = (String) it.Current; + //UPGRADE_TODO: Method 'java.util.HashMap.get' was converted to 'System.Collections.Hashtable.Item' which has a different behavior. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1073_javautilHashMapget_javalangObject'" + int gdsCount = Int32.Parse((String) gdsCounter[key]); + if (gdsCount > count) + { + count = gdsCount; + bestKey = key; + } + } + + // remove best key from gdsCounter, others will be removed from gdsHM + gdsCounter.Remove(bestKey); + // remove all GDSs using the gdsCounter + //UPGRADE_TODO: Method 'java.util.HashMap.keySet' was converted to 'SupportClass.HashSetSupport' which has a different behavior. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1073_javautilHashMapkeySet'" + //UPGRADE_TODO: Method 'java.util.Iterator.hasNext' was converted to 'System.Collections.IEnumerator.MoveNext' which has a different behavior. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1073_javautilIteratorhasNext'" + for (System.Collections.IEnumerator it = new SupportClass.HashSetSupport(gdsCounter.Keys).GetEnumerator(); + it.MoveNext();) + { + //UPGRADE_TODO: Method 'java.util.Iterator.next' was converted to 'System.Collections.IEnumerator.Current' which has a different behavior. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1073_javautilIteratornext'" + String key = (String) it.Current; + GdSs.Remove(key); + } + + // reset GDS keys in products too + for (int i = 0; i < Products.Count; i++) + { + Grib1Product g1P = (Grib1Product) Products[i]; + g1P.GDSkey = bestKey; + } + + return; + } +} \ No newline at end of file diff --git a/tmp/Grib1/Grib1BinaryDataSection.cs b/tmp/Grib1/Grib1BinaryDataSection.cs new file mode 100644 index 0000000..7fcf245 --- /dev/null +++ b/tmp/Grib1/Grib1BinaryDataSection.cs @@ -0,0 +1,248 @@ +/* + * This file is part of NGrib. + * + * Copyright � 2020 Nicolas Mangu� + * + * Copyright 2006-2010 Seaware AB, PO Box 1244, SE-131 28 + * Nacka Strand, Sweden, info@seaware.se. + * + * Copyright 1997-2006 Unidata Program Center/University + * Corporation for Atmospheric Research, P.O. Box 3000, Boulder, CO 80307, + * support@unidata.ucar.edu. + * + * NGrib is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * NGrib is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with NGrib. If not, see . + */ + +namespace NGrib.Grib1; + +/// +/// A class representing the binary data section (BDS) of a GRIB record. +/// +public sealed class Grib1BinaryDataSection +{ + /// + /// Grid values as an array of float. + /// + public double[] Values { get; } + + /// + /// Constant value for an undefined grid value. + /// + public static double MissingValue { get; } = -9999d; + + /// + /// Length in bytes of this BDS. + /// + private int length; + + /// + /// Buffer for one byte which will be processed bit by bit. + /// + private int bitBuf; + + /// + /// Current bit position in bitBuf. + /// + private int bitPos; + + /// Indicates whether the BMS is represented by a single value + /// Octet 12 is empty, and the data is represented by the reference value. + /// + private bool isConstant; + + /// Constructs a Grib1BinaryDataSection object from a raf. + /// A bit map is defined. + /// + /// + /// raf with BDS content + /// + /// the exponent of the decimal scale + /// + /// bit map section of GRIB record + /// + /// + /// NotSupportedException if stream contains no valid GRIB file + //UPGRADE_TODO: Class 'java.io.RandomAccessFile' was converted to 'System.IO.FileStream' which has a different behavior. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1073_javaioRandomAccessFile'" + internal Grib1BinaryDataSection(System.IO.Stream raf, int decimalscale, Grib1BitMapSection bms) + { + // octets 1-3 (section length) + length = (int) GribNumbers.uint3(raf); + + + // octet 4, 1st half (packing flag) + int unusedbits = raf.ReadByte(); + + // TODO Check this!!! + if ((unusedbits & 192) != 0) + throw new NotSupportedException("BDS: (octet 4, 1st half) not grid point data and simple packing "); + + // octet 4, 2nd half (number of unused bits at end of this section) + unusedbits = unusedbits & 15; + + + // octets 5-6 (binary scale factor) + int binscale = GribNumbers.int2(raf); + + // octets 7-10 (reference point = minimum value) + double refvalue = GribNumbers.double4(raf); + + // octet 11 (number of bits per value) + int numbits = raf.ReadByte(); + + if (numbits == 0) + isConstant = true; + + + // *** read values ******************************************************* + + //UPGRADE_WARNING: Data types in Visual C# might be different. Verify the accuracy of narrowing conversions. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1042'" + double ref_Renamed = (Math.Pow(10.0d, -decimalscale) * refvalue); + //UPGRADE_WARNING: Data types in Visual C# might be different. Verify the accuracy of narrowing conversions. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1042'" + double scale = (Math.Pow(10.0d, -decimalscale) * Math.Pow(2.0d, binscale)); + + if (bms != null) + { + bool[] bitmap = bms.Bitmap; + + Values = new double[bitmap.Length]; + for (int i = 0; i < bitmap.Length; i++) + { + if (bitmap[i]) + { + if (!isConstant) + { + Values[i] = ref_Renamed + scale * bits2UInt(numbits, raf); + } + else + { + // rdg - added this to handle a constant valued parameter + Values[i] = ref_Renamed; + } + } + else + Values[i] = MissingValue; + } + } + else + { + // bms is null + if (!isConstant) + { + + //(((length - 11) * 8 - unusedbits) / numbits)); + Values = new double[((length - 11) * 8 - unusedbits) / numbits]; + + for (int i = 0; i < Values.Length; i++) + { + Values[i] = ref_Renamed + scale * bits2UInt(numbits, raf); + } + } + else + { + // constant valued - same min and max + int x = 0, y = 0; + raf.Seek(raf.Position - 53, System.IO.SeekOrigin.Begin); // return to start of GDS + length = (int) GribNumbers.uint3(raf); + if (length == 42) + { + // Lambert/Mercator offset + SupportClass.Skip(raf, 3); + x = GribNumbers.int2(raf); + y = GribNumbers.int2(raf); + } + else + { + SupportClass.Skip(raf, 7); + length = (int) GribNumbers.uint3(raf); + if (length == 32) + { + // Polar sterographic + SupportClass.Skip(raf, 3); + x = GribNumbers.int2(raf); + y = GribNumbers.int2(raf); + } + else + { + x = y = 1; + Console.Out.WriteLine("BDS constant value, can't determine array size"); + } + } + + Values = new double[x * y]; + for (int i = 0; i < Values.Length; i++) + Values[i] = ref_Renamed; + } + } + } // end Grib1BinaryDataSection + + /// Convert bits (nb) to Unsigned Int . + /// + /// + /// + /// + /// + /// + /// int of BinaryDataSection section + /// + //UPGRADE_TODO: Class 'java.io.RandomAccessFile' was converted to 'System.IO.FileStream' which has a different behavior. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1073_javaioRandomAccessFile'" + private int bits2UInt(int nb, System.IO.Stream raf) + { + int bitsLeft = nb; + int result = 0; + + if (bitPos == 0) + { + bitBuf = raf.ReadByte(); + bitPos = 8; + } + + while (true) + { + int shift = bitsLeft - bitPos; + if (shift > 0) + { + // Consume the entire buffer + result |= bitBuf << shift; + bitsLeft -= bitPos; + + // Get the next byte from the RandomAccessFile + bitBuf = raf.ReadByte(); + bitPos = 8; + } + else + { + // Consume a portion of the buffer + result |= bitBuf >> -shift; + bitPos -= bitsLeft; + bitBuf &= 0xff >> (8 - bitPos); // mask off consumed bits + + return result; + } + } // end while + } // end bits2Int + + // *** public methods **************************************************** + + // --Commented out by Inspection START (11/17/05 1:25 PM): + // /** + // * Get the length in bytes of this section. + // * + // * @return length in bytes of this section + // */ + // public int getLength() + // { + // return length; + // } + // --Commented out by Inspection STOP (11/17/05 1:25 PM) +} // end class Grib1BinaryDataSection \ No newline at end of file diff --git a/tmp/Grib1/Grib1BitMapSection.cs b/tmp/Grib1/Grib1BitMapSection.cs new file mode 100644 index 0000000..2a146b6 --- /dev/null +++ b/tmp/Grib1/Grib1BitMapSection.cs @@ -0,0 +1,90 @@ +/* + * This file is part of NGrib. + * + * Copyright 2020 Nicolas Mangu + * + * Copyright 2006-2010 Seaware AB, PO Box 1244, SE-131 28 + * Nacka Strand, Sweden, info@seaware.se. + * + * Copyright 1997-2006 Unidata Program Center/University + * Corporation for Atmospheric Research, P.O. Box 3000, Boulder, CO 80307, + * support@unidata.ucar.edu. + * + * NGrib is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * NGrib is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with NGrib. If not, see . + */ + +namespace NGrib.Grib1; + +/// A class that represents the bitmap section (BMS) of a GRIB record. It +/// indicates grid points where no grid value is defined by a 0. +/// +/// +/// 1.0 +/// +public sealed class Grib1BitMapSection +{ + /// Get bit map. + /// + /// + /// bit map as array of boolean values + /// + public bool[] Bitmap { get; } + + /// Length in bytes of this section. + //UPGRADE_NOTE: Final was removed from the declaration of 'length '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'" + private int length; + + /// Constructs a Grib1BitMapSection object from a raf input stream. + /// + /// + /// input stream with BMS content + /// + /// + //UPGRADE_TODO: Class 'java.io.RandomAccessFile' was converted to 'System.IO.FileStream' which has a different behavior. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1073_javaioRandomAccessFile'" + internal Grib1BitMapSection(System.IO.Stream raf) + { + int[] bitmask = new int[] {128, 64, 32, 16, 8, 4, 2, 1}; + + // octet 1-3 (length of section) + length = (int) GribNumbers.uint3(raf); + + + // octet 4 unused bits + int unused = raf.ReadByte(); + + + // octets 5-6 + int bm = GribNumbers.int2(raf); + if (bm != 0) + { + System.Console.Out.WriteLine("BMS pre-defined BM provided by center"); + if ((length - 6) == 0) + return; + sbyte[] data = new sbyte[length - 6]; + SupportClass.ReadInput(raf, data, 0, data.Length); + return; + } + + sbyte[] data2 = new sbyte[length - 6]; + SupportClass.ReadInput(raf, data2, 0, data2.Length); + + // create new bit map, octet 4 contains number of unused bits at the end + Bitmap = new bool[(length - 6) * 8 - unused]; + + + // fill bit map + for (int i = 0; i < Bitmap.Length; i++) + Bitmap[i] = (data2[i / 8] & bitmask[i % 8]) != 0; + } // end Grib1BitMapSection +} // end Grib1BitMapSection \ No newline at end of file diff --git a/tmp/Grib1/Grib1Data.cs b/tmp/Grib1/Grib1Data.cs new file mode 100644 index 0000000..314cda1 --- /dev/null +++ b/tmp/Grib1/Grib1Data.cs @@ -0,0 +1,71 @@ +/* + * This file is part of NGrib. + * + * Copyright � 2020 Nicolas Mangu� + * + * Copyright 2006-2010 Seaware AB, PO Box 1244, SE-131 28 + * Nacka Strand, Sweden, info@seaware.se. + * + * Copyright 1997-2006 Unidata Program Center/University + * Corporation for Atmospheric Research, P.O. Box 3000, Boulder, CO 80307, + * support@unidata.ucar.edu. + * + * NGrib is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * NGrib is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with NGrib. If not, see . + */ + +namespace NGrib.Grib1; + +/// A class used to extract data from a GRIB1 file. +/// see IndexFormat.txt +/// +public sealed class Grib1Data +{ + /* + * used to hold open file descriptor + */ + //UPGRADE_TODO: Class 'java.io.RandomAccessFile' was converted to 'System.IO.FileStream' which has a different behavior. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1073_javaioRandomAccessFile'" + private System.IO.Stream raf; + + private readonly Grib1File _grib1File; + + // *** constructors ******************************************************* + + /// Constructs a Grib2Data object from a stream. + /// + /// + /// ucar.unidata.io.RandomAccessFile with GRIB content. + /// + /// + //UPGRADE_TODO: Class 'java.io.RandomAccessFile' was converted to 'System.IO.FileStream' which has a different behavior. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1073_javaioRandomAccessFile'" + public Grib1Data(System.IO.Stream raf, Grib1File grib1File) + { + this.raf = raf; + _grib1File = grib1File; + } + + public void setFilename(string filename) + { + raf = new System.IO.FileStream(filename, System.IO.FileMode.Open, System.IO.FileAccess.Read); + } + + public void closeFile() + { + raf.Close(); + } + + public double[] getData(long offset, int DecimalScale, bool bmsExists) => + _grib1File.getData(raf, offset, DecimalScale, bmsExists); + + // end getData +} // end Grib1Data \ No newline at end of file diff --git a/tmp/Grib1/Grib1EndSection.cs b/tmp/Grib1/Grib1EndSection.cs new file mode 100644 index 0000000..f979f9f --- /dev/null +++ b/tmp/Grib1/Grib1EndSection.cs @@ -0,0 +1,102 @@ +/* + * This file is part of NGrib. + * + * Copyright 2020 Nicolas Mangu + * + * Copyright 2006-2010 Seaware AB, PO Box 1244, SE-131 28 + * Nacka Strand, Sweden, info@seaware.se. + * + * Copyright 1997-2006 Unidata Program Center/University + * Corporation for Atmospheric Research, P.O. Box 3000, Boulder, CO 80307, + * support@unidata.ucar.edu. + * + * NGrib is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * NGrib is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with NGrib. If not, see . + */ + +namespace NGrib.Grib1; + +/// A class that represents the EndSection of a GRIB1 product. +/// +/// +sealed class Grib1EndSection +{ + /// Get ending flag for Grib record. + /// + /// + /// true if "7777" found + /// + public bool EndFound + { + get { return endFound; } + + // --Commented out by Inspection START (11/17/05 1:32 PM): + // /** + // * how long was the ending, should be 4 bytes. + // * @return int + // */ + // public static final int getLength() + // { + // return length; + // } + // --Commented out by Inspection STOP (11/17/05 1:32 PM) + } + + /* + * was the grib endding 7777 found. + */ + private bool endFound; + + /* + * how long was the ending, should be 4 bytes. + */ + private int length; + + // *** constructors ******************************************************* + + /// Constructs a Grib1EndSection object from a byteBuffer. + /// + /// + /// RandomAccessFile with EndSection content + /// + /// + //UPGRADE_TODO: Class 'java.io.RandomAccessFile' was converted to 'System.IO.FileStream' which has a different behavior. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1073_javaioRandomAccessFile'" + internal Grib1EndSection(System.IO.Stream raf) + { + int match = 0; + while (raf.Position < raf.Length) + { + // code must be "7" "7" "7" "7" + sbyte c = (sbyte) raf.ReadByte(); + + length++; + if (c == '7') + { + match += 1; + + } + else + { + + match = 0; /* Needed to protect against bad ending case. */ + } + + if (match == 4) + { + endFound = true; + + break; + } + } + } // end Grib1EndSection +} // end Grib1EndSection \ No newline at end of file diff --git a/tmp/Grib1/Grib1Ensemble.cs b/tmp/Grib1/Grib1Ensemble.cs new file mode 100644 index 0000000..2870112 --- /dev/null +++ b/tmp/Grib1/Grib1Ensemble.cs @@ -0,0 +1,151 @@ +/* + * This file is part of NGrib. + * + * Copyright 2020 Nicolas Mangu + * + * Copyright 2006-2010 Seaware AB, PO Box 1244, SE-131 28 + * Nacka Strand, Sweden, info@seaware.se. + * + * Copyright 1997-2006 Unidata Program Center/University + * Corporation for Atmospheric Research, P.O. Box 3000, Boulder, CO 80307, + * support@unidata.ucar.edu. + * + * NGrib is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * NGrib is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with NGrib. If not, see . + */ + +/// Grib1Ensemble class 12/30/04. +/// Robb Kambic +/// code is not complete. +/// + +namespace NGrib.Grib1; + +/// Represents an Ensemble product. +/// +/// +public sealed class Grib1Ensemble +{ + /// The Type. + private int eType; + + /// The Identification number. + private int eId; + + /// The Product Identifier. + private int eProd; + + /// The Spatial Identifier. + private int eSpatial; + + /// Probability product definition. + private int epd; + + private int ept; + private int epll; + private int epul; + private int eSize; + private int eCSize; + private int eCNumber; + private int eCMethod; + private int nLat; + private int sLat; + private int eLat; + private int wLat; + private sbyte[] cm; + + /// Creates an ensemble object for the product PDS. + /// RandomAccessFile. + /// + /// + /// + /// IOException + //UPGRADE_TODO: Class 'java.io.RandomAccessFile' was converted to 'System.IO.FileStream' which has a different behavior. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1073_javaioRandomAccessFile'" + internal Grib1Ensemble(System.IO.Stream raf, int parameterNumber) + { + // skip 12 bytes to start of ensemble + SupportClass.Skip(raf, 12); + + // octet 41 id's ensemble + int app = raf.ReadByte(); + if (app != 1) + { + System.Console.Out.WriteLine("not ensemble product"); + return; + } + + // octet 42 Type + eType = raf.ReadByte(); + + // octet 43 Identification number + eId = raf.ReadByte(); + + // octet 44 Product Identifier + eProd = raf.ReadByte(); + + // octet 45 Spatial Identifier + eSpatial = raf.ReadByte(); + + if (parameterNumber == 191 || parameterNumber == 192) + { + // octet 46 Probability product definition + epd = raf.ReadByte(); + + // octet 47 Probability type + ept = raf.ReadByte(); + + // octet 48-51 Probability lower limit + epll = GribNumbers.int4(raf); + + // octet 52-55 Probability upper limit + epul = GribNumbers.int4(raf); + + // octet 56-60 reserved + int reserved = GribNumbers.int4(raf); + + if (eType == 4 || eType == 5) + { + // octet 61 Ensemble size + eSize = raf.ReadByte(); + + // octet 62 Cluster size + eCSize = raf.ReadByte(); + + // octet 63 Number of clusters + eCNumber = raf.ReadByte(); + + // octet 64 Clustering Method + eCMethod = raf.ReadByte(); + + // octet 65-67 Northern latitude of clustering domain + nLat = GribNumbers.int3(raf); + + // octet 68-70 Southern latitude of clustering domain + sLat = GribNumbers.int3(raf); + + // octet 71-73 Eastern latitude of clustering domain + eLat = GribNumbers.int3(raf); + + // octet 74-76 Western latitude of clustering domain + wLat = GribNumbers.int3(raf); + + if (eType == 4) + { + // octets 77-86 Cluster Membership + cm = new sbyte[10]; + SupportClass.ReadInput(raf, cm, 0, cm.Length); + } + } + } + } +} // end Grib1Ensemble \ No newline at end of file diff --git a/tmp/Grib1/Grib1File.cs b/tmp/Grib1/Grib1File.cs new file mode 100644 index 0000000..0366c94 --- /dev/null +++ b/tmp/Grib1/Grib1File.cs @@ -0,0 +1,125 @@ +using System.Collections; + +namespace NGrib.Grib1; + +public sealed class Grib1File +{ + /* + * the header of Grib record + */ + private const string _header = "GRIB"; + + private readonly GdsKeys _keys = new(); + + private readonly GdsKeys _gdsKeys = new(); + + + + public Grib1Record ReadGrib1Record(Stream InputStream, long startOffset, Hashtable gdsCounter, ref Grib1GridDefinitionSection gds) + { + Grib1ProductDefinitionSection pds; + // Read Section 0 Indicator Section + Grib1IndicatorSection isRenamed = new Grib1IndicatorSection(InputStream); + + // EOR (EndOfRecord) calculated so skipping data sections is faster + long eor = InputStream.Position + isRenamed.GribLength - isRenamed.Length; + + // Read Section 1 Product Definition Section PDS + pds = new Grib1ProductDefinitionSection(InputStream); + if (pds.LengthErr) + return null; + + if (pds.gdsExists()) + { + // Read Section 2 Grid Definition Section GDS + gds = new Grib1GridDefinitionSection(InputStream); + } + else + { + // GDS doesn't exist so make one + + + gds = (Grib1GridDefinitionSection) new Grib1Grid(pds); + } + + // obtain BMS or BDS offset in the file for this product + long dataOffset; + if (pds.Center == 98) + { + // check for ecmwf offset by 1 bug + int length = (int) GribNumbers.uint3(InputStream); // should be length of BMS + if ((length + InputStream.Position) < eor) + { + dataOffset = InputStream.Position - 3; // ok + } + else + { + dataOffset = InputStream.Position - 2; + } + } + else + { + dataOffset = InputStream.Position; + } + + // position filePointer to EndOfRecord + InputStream.Seek(eor, SeekOrigin.Begin); + + + // assume scan ok + Grib1Record gr = new Grib1Record(_header, isRenamed, pds, gds, dataOffset, InputStream.Position, + startOffset); + + var currentPosition = InputStream.Position; + + InputStream.Position = currentPosition; + + // early return because ending "7777" missing + if (InputStream.Position > InputStream.Length) + { + InputStream.Seek(0, SeekOrigin.Begin); + _gdsKeys.CheckGdSkeys(gds, gdsCounter); + throw new BadGribFormatException("Grib1Input: GRIB ending missing. Possible file corruption"); + } + + return gr; + } + + /// Reads the Grib data + /// + /// + /// offset into file. + /// + /// + /// + /// + /// + /// NotSupportedException + /// float[] + /// + public double[] getData(Stream raf, long offset, int DecimalScale, bool bmsExists) + { + long start = (System.DateTime.Now.Ticks - 621355968000000000) / 10000; + + raf.Seek(offset, System.IO.SeekOrigin.Begin); + + + // Need section 3 and 4 to read/interpet the data, section 5 + // as a check that all data read and sections are correct + + Grib1BitMapSection bms = null; + if (bmsExists) + // read Bit Mapped Section 3 + bms = new Grib1BitMapSection(raf); + + // read Binary Data Section 4 + Grib1BinaryDataSection bds = new Grib1BinaryDataSection(raf, DecimalScale, bms); + + return bds.Values; + } + + public void CheckGdSkeys(Grib1GridDefinitionSection gds, Hashtable gdsCounter) + { + _keys.CheckGdSkeys(gds, gdsCounter); + } +} \ No newline at end of file diff --git a/tmp/Grib1/Grib1Grid.cs b/tmp/Grib1/Grib1Grid.cs new file mode 100644 index 0000000..1dbefe4 --- /dev/null +++ b/tmp/Grib1/Grib1Grid.cs @@ -0,0 +1,281 @@ +/* + * This file is part of NGrib. + * + * Copyright 2020 Nicolas Mangu + * + * Copyright 2006-2010 Seaware AB, PO Box 1244, SE-131 28 + * Nacka Strand, Sweden, info@seaware.se. + * + * Copyright 1997-2006 Unidata Program Center/University + * Corporation for Atmospheric Research, P.O. Box 3000, Boulder, CO 80307, + * support@unidata.ucar.edu. + * + * NGrib is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * NGrib is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with NGrib. If not, see . + */ + +namespace NGrib.Grib1; + +/// A class that represents a canned grid definition section (GDS) . +public sealed class Grib1Grid : Grib1GridDefinitionSection +{ + /// Constructs a Grib1Grid object from a pds. + /// + /// + /// Grib1ProductDefinitionSection to formulate grib + /// + /// + internal Grib1Grid(Grib1ProductDefinitionSection pds) : base() + { + int generatingProcess = pds.Process_Id; + int gridNumber = pds.Grid_Id; + + // checksum = 1000 + grid number + checksum = "1000" + System.Convert.ToString(gridNumber); + + switch (gridNumber) + { + case 21: + case 22: + case 23: + case 24: + { + type = 0; // Latitude/Longitude + name = getName(type); + + // (Nx - number of points along x-axis) + nx = 37; + + // (Ny - number of points along y-axis) + ny = 37; + + // (resolution and component flags). See Table 7 + resolution = 0x88; + + // (Dx - Longitudinal Direction Increment ) + dx = 5.0; + + // (Dy - Latitudinal Direction Increment ) + dy = 2.5; + + // (Scanning mode) See Table 8 + scan = 64; + + if (gridNumber == 21) + { + // (La1 - latitude of first grid point) + lat1 = 0.0; + + // (Lo1 - longitude of first grid point) + lon1 = 0.0; + + // (La2 - latitude of last grid point) + lat2 = 90.0; + + // (Lo2 - longitude of last grid point) + lon2 = 180.0; + } + else if (gridNumber == 22) + { + // (La1 - latitude of first grid point) + lat1 = 0.0; + + // (Lo1 - longitude of first grid point) + lon1 = -180.0; + + // (La2 - latitude of last grid point) + lat2 = 90.0; + + // (Lo2 - longitude of last grid point) + lon2 = 0.0; + } + else if (gridNumber == 23) + { + // (La1 - latitude of first grid point) + lat1 = -90.0; + + // (Lo1 - longitude of first grid point) + lon1 = 0.0; + + // (La2 - latitude of last grid point) + lat2 = 0.0; + + // (Lo2 - longitude of last grid point) + lon2 = 180.0; + } + else if (gridNumber == 24) + { + // (La1 - latitude of first grid point) + lat1 = -90.0; + + // (Lo1 - longitude of first grid point) + lon1 = -180.0; + + // (La2 - latitude of last grid point) + lat2 = 0.0; + + // (Lo2 - longitude of last grid point) + lon2 = 0.0; + } + } + break; + + + case 25: + case 26: + { + type = 0; // Latitude/Longitude + name = getName(type); + + // (Nx - number of points along x-axis) + nx = 72; + + // (Ny - number of points along y-axis) + ny = 19; + + // (resolution and component flags). See Table 7 + resolution = 0x88; + + // (Dx - Longitudinal Direction Increment ) + dx = 5.0; + + // (Dy - Latitudinal Direction Increment ) + dy = 5.0; + + // (Scanning mode) See Table 8 + scan = 64; + + if (gridNumber == 25) + { + // (La1 - latitude of first grid point) + lat1 = 0.0; + + // (Lo1 - longitude of first grid point) + lon1 = 0.0; + + // (La2 - latitude of last grid point) + lat2 = 90.0; + + // (Lo2 - longitude of last grid point) + lon2 = 355.0; + } + else if (gridNumber == 26) + { + // (La1 - latitude of first grid point) + lat1 = -90.0; + + // (Lo1 - longitude of first grid point) + lon1 = 0.0; + + // (La2 - latitude of last grid point) + lat2 = 0.0; + + // (Lo2 - longitude of last grid point) + lon2 = 355.0; + } + } + break; + + + case 61: + case 62: + case 63: + case 64: + { + type = 0; // Latitude/Longitude + name = getName(type); + + // (Nx - number of points along x-axis) + nx = 91; + + // (Ny - number of points along y-axis) + ny = 46; + + // (resolution and component flags). See Table 7 + resolution = 0x88; + + // (Dx - Longitudinal Direction Increment ) + dx = 2.0; + + // (Dy - Latitudinal Direction Increment ) + dy = 2.0; + + // (Scanning mode) See Table 8 + scan = 64; + + if (gridNumber == 61) + { + // (La1 - latitude of first grid point) + lat1 = 0.0; + + // (Lo1 - longitude of first grid point) + lon1 = 0.0; + + // (La2 - latitude of last grid point) + lat2 = 90.0; + + // (Lo2 - longitude of last grid point) + lon2 = 180.0; + } + else if (gridNumber == 62) + { + // (La1 - latitude of first grid point) + lat1 = 0.0; + + // (Lo1 - longitude of first grid point) + lon1 = -180.0; + + // (La2 - latitude of last grid point) + lat2 = 90.0; + + // (Lo2 - longitude of last grid point) + lon2 = 0.0; + } + else if (gridNumber == 63) + { + // (La1 - latitude of first grid point) + lat1 = -90.0; + + // (Lo1 - longitude of first grid point) + lon1 = 0.0; + + // (La2 - latitude of last grid point) + lat2 = 0.0; + + // (Lo2 - longitude of last grid point) + lon2 = 180.0; + } + else if (gridNumber == 64) + { + // (La1 - latitude of first grid point) + lat1 = -90.0; + + // (Lo1 - longitude of first grid point) + lon1 = -180.0; + + // (La2 - latitude of last grid point) + lat2 = 0.0; + + // (Lo2 - longitude of last grid point) + lon2 = 0.0; + } + + break; + } + + default: + System.Console.Out.WriteLine("Grid " + gridNumber + " not configured yet"); + break; + } + } // end Grib1Grid +} // end Grib1Grid \ No newline at end of file diff --git a/tmp/Grib1/Grib1GridDefinitionSection.cs b/tmp/Grib1/Grib1GridDefinitionSection.cs new file mode 100644 index 0000000..1a99ec2 --- /dev/null +++ b/tmp/Grib1/Grib1GridDefinitionSection.cs @@ -0,0 +1,812 @@ +/* + * This file is part of NGrib. + * + * Copyright © 2020 Nicolas Manguй + * + * Copyright 2006-2010 Seaware AB, PO Box 1244, SE-131 28 + * Nacka Strand, Sweden, info@seaware.se. + * + * Copyright 1997-2006 Unidata Program Center/University + * Corporation for Atmospheric Research, P.O. Box 3000, Boulder, CO 80307, + * support@unidata.ucar.edu. + * + * NGrib is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * NGrib is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with NGrib. If not, see . + */ + +using System.Diagnostics; + +namespace NGrib.Grib1; + +/// A class that represents the grid definition section (GDS) of a GRIB record. +public class Grib1GridDefinitionSection +{ + /// is this a thin grid. + /// + /// + /// isThin grid boolean + /// + virtual public bool IsThin + { + get { return isThin; } + // --Commented out by Inspection START (11/17/05 1:42 PM): + // public final int[] getNumPlPts() + // { + // return numPlPts; + // } + // --Commented out by Inspection STOP (11/17/05 1:42 PM) + } + + /// Get type of grid. + /// + /// + /// type of grid + /// + virtual public int GridType + { + get { return type; } + } + + /// Get type of grid. + /// + /// + /// type of grid + /// + virtual public int Gdtn + { + get { return type; } + } + + /// Get number of grid columns. + /// + /// + /// number of grid columns + /// + virtual public int Nx + { + get { return nx; } + } + + /// Get number of grid rows. + /// + /// + /// number of grid rows. + /// + virtual public int Ny + { + get { return ny; } + } + + /// Get y-coordinate/latitude of grid start point. + /// + /// + /// y-coordinate/latitude of grid start point + /// + virtual public double La1 + { + get { return lat1; } + } + + /// Get x-coordinate/longitude of grid start point. + /// + /// + /// x-coordinate/longitude of grid start point + /// + virtual public double Lo1 + { + get { return lon1; } + } + + /// Get grid resolution. + /// + /// + /// resolution + /// + virtual public int Resolution + { + get { return resolution; } + } + + /// grid shape spherical or oblate. + /// int grid shape code 1 or 3 + /// + virtual public int Shape + { + get + { + int res = resolution >> 6; + if (res == 1 || res == 3) + { + return 1; + } + else + { + return 0; + } + } + } + + /// Grib 1 has static radius. + /// ShapeRadius of 6367.47 + /// + public static double ShapeRadius + { + get { return 6367.47; } + } + + /// Grib 1 has static MajorAxis. + /// ShapeMajorAxis of 6378.160 + /// + public static double ShapeMajorAxis + { + get { return 6378.160; } + } + + /// Grib 1 has static MinorAxis. + /// + /// + /// ShapeMinorAxis of 6356.775 + /// + public static double ShapeMinorAxis + { + get { return 6356.775; } + } + + /// Get y-coordinate/latitude of grid end point. + /// + /// + /// y-coordinate/latitude of grid end point + /// + virtual public double La2 + { + get { return lat2; } + } + + /// Get x-coordinate/longitude of grid end point. + /// + /// + /// x-coordinate/longitude of grid end point + /// + virtual public double Lo2 + { + get { return lon2; } + } + + /// orientation of the grid. + /// lov + /// + virtual public double Lov + { + get { return lov; } + } + + /// not defined in Grib1. + /// lad + /// + virtual public double Lad + { + get { return 0; } + } + + /// Get x-increment/distance between two grid points. + /// + /// + /// x-increment + /// + virtual public double Dx + { + get { return dx; } + } + + /// Get y-increment/distance between two grid points. + /// + /// + /// y-increment + /// + virtual public double Dy + { + get { return dy; } + } + + /// Get parallels between a pole and the equator. + /// + /// + /// np + /// + virtual public double Np + { + get { return np; } + } + + /// Get scan mode. + /// + /// + /// scan mode + /// + virtual public int ScanMode + { + get { return scan; } + } + + /// Get Projection Center flag - see note 5 of Table D. + /// + /// + /// Projection Center flag + /// + virtual public int ProjectionCenter + { + get { return proj_center; } + } + + /// Get first latitude from the pole at which cylinder cuts spherical earth - + /// see note 8 of Table D. + /// + /// + /// latitude + /// + virtual public double Latin + { + get { return latin1; } + } + + /// Get first latitude from the pole at which cone cuts spherical earth - + /// see note 8 of Table D. + /// + /// + /// latitude of south pole + /// + virtual public double Latin1 + { + get { return latin1; } + } + + /// Get second latitude from the pole at which cone cuts spherical earth - + /// see note 8 of Table D. + /// + /// + /// latitude of south pole + /// + virtual public double Latin2 + { + get { return latin2; } + } + + /// Get latitude of south pole. + /// + /// + /// latitude + /// + virtual public double SpLat + { + get { return latsp; } + } + + /// Get longitude of south pole of a rotated latitude/longitude grid. + /// + /// + /// longitude + /// + virtual public double SpLon + { + get { return lonsp; } + } + + /// MD5 checksum of this gds, used for comparisons. + /// + /// + /// string representation of this GDS checksum + /// + virtual public String CheckSum + { + get { return checksum; } + } + + /// Length in bytes of this section. + private int length; + + /// P(V|L). + /// PV - list of vertical coordinate parameters. + /// PL - list of numbers of points in each row. + /// or 255 missing. + /// + private int P_VorL; + //UPGRADE_NOTE: Final was removed from the declaration of 'numPlPts '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'" + // private int[] numPlPts = null; + + /// Is this a thin grid code not implemented. + private bool isThin; + + /// Type of grid (See table 6)ie 1 == Mercator Projection Grid. + protected internal int type; + + /// Grid name. + protected internal String name = ""; + + /// Number of grid columns. (Also Ni). + protected internal int nx; + + /// Number of grid rows. (Also Nj). + protected internal int ny; + + /// Latitude of grid start point. + protected internal double lat1; + + /// Longitude of grid start point. + protected internal double lon1; + + /// Latitude of grid last point. + protected internal double lat2; + + /// Longitude of grid last point. + protected internal double lon2; + + /// orientation of the grid. + private double lov; + + /// Resolution of grid (See table 7). + protected internal int resolution; + + /// x-distance between two grid points + /// can be delta-Lon or delta x. + /// + protected internal double dx; + + /// y-distance of two grid points + /// can be delta-Lat or delta y. + /// + protected internal double dy; + + /// Number of parallels between a pole and the equator. + private int np; + + /// Scanning mode (See table 8). + protected internal int scan; + + /// Projection Center Flag. + private int proj_center; + + /// Latin 1 - The first latitude from pole at which secant cone cuts the + /// sperical earth. See Note 8 of ON388. + /// + private double latin1; + + /// Latin 2 - The second latitude from pole at which secant cone cuts the + /// sperical earth. See Note 8 of ON388. + /// + private double latin2; + + /// latitude of south pole. + private double latsp; + + /// longitude of south pole. + private double lonsp; + + /// checksum value for this gds. + protected internal String checksum = ""; + + // *** constructors ******************************************************* + /// constructor + internal Grib1GridDefinitionSection() + { + } + + /// Constructs a Grib1GridDefinitionSection object from a raf. + /// + /// + /// RandomAccessFile with GDS content + /// + /// + /// NoValidGribException if raf contains no valid GRIB info + //UPGRADE_TODO: Class 'java.io.RandomAccessFile' was converted to 'System.IO.FileStream' which has a different behavior. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1073_javaioRandomAccessFile'" + internal Grib1GridDefinitionSection(System.IO.Stream raf) + { + int reserved; // used to read empty space + + // octets 1-3 (Length of GDS) + length = (int) GribNumbers.uint3(raf); + if (length == 0) + { + // there's a extra byte between PDS and GDS + SupportClass.Skip(raf, -2); + length = (int) GribNumbers.uint3(raf); + } + + + // TODO Fix Checksum stuff + // get byte array for this gds, then reset raf to same position + // calculate checksum for this gds via the byte array + /* + long mark = raf.Position; + sbyte[] dst = new sbyte[length - 3]; + SupportClass.ReadInput(raf, dst, 0, dst.Length); + raf.Seek(mark, System.IO.SeekOrigin.Begin); + //UPGRADE_ISSUE: Class 'java.util.zip.CRC32' was not converted. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1000_javautilzipCRC32'" + //UPGRADE_ISSUE: Constructor 'java.util.zip.CRC32.CRC32' was not converted. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1000_javautilzipCRC32'" + CRC32 cs = new CRC32(); + //UPGRADE_ISSUE: Method 'java.util.zip.CRC32.update' was not converted. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1000_javautilzipCRC32'" + cs.update(dst); + //UPGRADE_ISSUE: Method 'java.util.zip.CRC32.getValue' was not converted. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1000_javautilzipCRC32'" + checksum = System.Convert.ToString(cs.getValue()); + + */ + + // octets 4 NV + int NV = raf.ReadByte(); + + + // octet 5 PL the location (octet number) of the list of numbers of points in each row + P_VorL = raf.ReadByte(); + + + // octet 6 (grid type) + type = raf.ReadByte(); + + name = getName(type); + + if (type != 50) + { + // values same up to resolution + + // octets 7-8 (Nx - number of points along x-axis) + nx = GribNumbers.int2(raf); + nx = (nx == -1) ? 1 : nx; + + // octets 9-10 (Ny - number of points along y-axis) + ny = GribNumbers.int2(raf); + ny = (ny == -1) ? 1 : ny; + + // octets 11-13 (La1 - latitude of first grid point) + lat1 = GribNumbers.int3(raf) / 1000.0; + + // octets 14-16 (Lo1 - longitude of first grid point) + lon1 = GribNumbers.int3(raf) / 1000.0; + + // octet 17 (resolution and component flags). See Table 7 + resolution = raf.ReadByte(); + } + + switch (type) + { + // Latitude/Longitude grids , Arakawa semi-staggered e-grid rotated + // Arakawa filled e-grid rotated + case 0: + case 4: + case 40: + case 201: + case 202: + + // octets 18-20 (La2 - latitude of last grid point) + lat2 = GribNumbers.int3(raf) / 1000.0; + + // octets 21-23 (Lo2 - longitude of last grid point) + lon2 = GribNumbers.int3(raf) / 1000.0; + + // octets 24-25 (Dx - Longitudinal Direction Increment ) + dx = GribNumbers.int2(raf) / 1000.0; + + // octets 26-27 (Dy - Latitudinal Direction Increment ) + // Np - parallels between a pole and the equator + if (type == 4) + { + np = GribNumbers.int2(raf); + } + else + { + dy = GribNumbers.int2(raf) / 1000.0; + } + + // octet 28 (Scanning mode) See Table 8 + scan = raf.ReadByte(); + + // octet 29-32 reserved + reserved = GribNumbers.int4(raf); + + if (length > 32) + { + // getP_VorL(raf); + // Vertical coordinates (NV) and thinned grids (PL) not supported - skip this + SupportClass.Skip(raf, length - 32); + } + + break; // end Latitude/Longitude grids + + + case 1: // Mercator grids + + // octets 18-20 (La2 - latitude of last grid point) + lat2 = GribNumbers.int3(raf) / 1000.0; + + // octets 21-23 (Lo2 - longitude of last grid point) + lon2 = GribNumbers.int3(raf) / 1000.0; + + // octets 24-26 (Latin - latitude where cylinder intersects the earth + latin1 = GribNumbers.int3(raf) / 1000.0; + + // octet 27 reserved + reserved = raf.ReadByte(); + + // octet 28 (Scanning mode) See Table 8 + scan = raf.ReadByte(); + + // octets 29-31 (Dx - Longitudinal Direction Increment ) + dx = GribNumbers.int3(raf); + + // octets 32-34 (Dx - Longitudinal Direction Increment ) + dy = GribNumbers.int3(raf); + + // octet 35-42 reserved + reserved = GribNumbers.int4(raf); + reserved = GribNumbers.int4(raf); + + if (length > 42) + { + // getP_VorL(raf); + // Vertical coordinates (NV) and thinned grids (PL) not supported - skip this + SupportClass.Skip(raf, length - 42); + } + + break; // end Mercator grids + + + case 3: // Lambert Conformal + + // octets 18-20 (Lov - Orientation of the grid - east lon parallel to y axis) + lov = GribNumbers.int3(raf) / 1000.0; + + // octets 21-23 (Dx - the X-direction grid length) See Note 2 of Table D + dx = GribNumbers.int3(raf); + + // octets 24-26 (Dy - the Y-direction grid length) See Note 2 of Table D + dy = GribNumbers.int3(raf); + + // octets 27 (Projection Center flag) See Note 5 of Table D + proj_center = raf.ReadByte(); + + // octet 28 (Scanning mode) See Table 8 + scan = raf.ReadByte(); + + // octets 29-31 (Latin1 - first lat where secant cone cuts spherical earth + latin1 = GribNumbers.int3(raf) / 1000.0; + + // octets 32-34 (Latin2 - second lat where secant cone cuts spherical earth) + latin2 = GribNumbers.int3(raf) / 1000.0; + + // octets 35-37 (lat of southern pole) + latsp = GribNumbers.int3(raf) / 1000.0; + + // octets 38-40 (lon of southern pole) + lonsp = GribNumbers.int3(raf) / 1000.0; + + // octets 41-42 + reserved = GribNumbers.int2(raf); + + if (length > 42) + { + // getP_VorL(raf); + // Vertical coordinates (NV) and thinned grids (PL) not supported - skip this + SupportClass.Skip(raf, length - 42); + } + + break; // end Lambert Conformal + + + case 5: // Polar Stereographic grids + + // octets 18-20 (Lov - Orientation of the grid - east lon parallel to y axis) + lov = GribNumbers.int3(raf) / 1000.0; + + // octets 21-23 (Dx - Longitudinal Direction Increment ) + dx = GribNumbers.int3(raf); + + // octets 24-26(Dy - Latitudinal Direction Increment ) + dy = GribNumbers.int3(raf); + + // octets 27 (Projection Center flag) See Note 5 of Table D + proj_center = raf.ReadByte(); + + // octet 28 (Scanning mode) See Table 8 + scan = raf.ReadByte(); + + // octet 29-32 reserved + reserved = GribNumbers.int4(raf); + + if (length > 32) + { + // getP_VorL(raf); + // Vertical coordinates (NV) and thinned grids (PL) not supported - skip this + SupportClass.Skip(raf, length - 32); + } + + break; // end Polar Stereographic grids + + + default: + Console.Out.WriteLine("Unknown Grid Type : " + type); + break; + } // end switch grid_type + + + if ((scan & 63) != 0) + throw new BadGribFormatException("GDS: This scanning mode (" + scan + ") is not supported."); + } // end Grib1GridDefinitionSection( raf ) + + //UPGRADE_TODO: Class 'java.io.RandomAccessFile' was converted to 'System.IO.FileStream' which has a different behavior. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1073_javaioRandomAccessFile'" + private void getP_VorL(System.IO.Stream raf) + { + isThin = true; + int numPts; + if (ny != 1) + { + dx = (float) GribNumbers.UNDEFINED; + numPts = ny; + } + else + { + dx = (float) GribNumbers.UNDEFINED; + numPts = nx; + } + + + int[] numPlPts = new int[numPts]; + for (int i = 0; i < numPts; i++) + { + numPlPts[i] = GribNumbers.int2(raf); + + } + } + + // *** public methods *************************************************** + + // --Commented out by Inspection START (11/17/05 1:43 PM): + // /** + // * Get length in bytes of this section. + // * + // * @return length in bytes of this section + // */ + // public final int getLength() + // { + // return length; + // } + // --Commented out by Inspection STOP (11/17/05 1:43 PM) + + /// Get Grid name. + /// + /// + /// name + /// + public String getName() + { + return name; + } + + /// Get Grid name. + /// + /// + /// + /// + /// name + /// + static public String getName(int type) + { + switch (type) + { + case 0: return "Latitude/Longitude Grid"; + + case 1: return "Mercator Projection Grid"; + + case 2: return "Gnomonic Projection Grid"; + + case 3: return "Lambert Conformal"; + + case 4: return "Gaussian Latitude/Longitude"; + + case 5: return "Polar Stereographic projection Grid"; + + case 6: return "Universal Transverse Mercator"; + + case 7: return "Simple polyconic projection"; + + case 8: return "Albers equal-area, secant or tangent, conic or bi-polar, projection"; + + case 9: return "Miller's cylindrical projection"; + + case 10: return "Rotated latitude/longitude grid"; + + case 13: return "Oblique Lambert conformal, secant or tangent, conical or bipolar, projection"; + + case 14: return "Rotated Gaussian latitude/longitude grid"; + + case 20: return "Stretched latitude/longitude grid"; + + case 24: return "Stretched Gaussian latitude/longitude grid"; + + case 30: return "Stretched and rotated latitude/longitude grids"; + + case 34: return "Stretched and rotated Gaussian latitude/longitude grids"; + + case 50: return "Spherical Harmonic Coefficients"; + + case 60: return "Rotated spherical harmonic coefficients"; + + case 70: return "Stretched spherical harmonics"; + + case 80: return "Stretched and rotated spherical harmonic coefficients"; + + case 90: return "Space view perspective or orthographic"; + + case 201: return "Arakawa semi-staggered E-grid on rotated latitude/longitude grid-point array"; + + case 202: return "Arakawa filled E-grid on rotated latitude/longitude grid-point array"; + } + + return "Unknown"; + } // end getName + + /// shape of grid. + /// grid shape name + /// + public String getShapeName() + { + return getShapeName(Shape); + } + + /// shape of grid. + /// grid shape code + /// + /// String grid shape name + /// + static public String getShapeName(int code) + { + if (code == 1) + { + return "oblate spheroid"; + } + else + { + return "spherical"; + } + } + + public IEnumerable EnumerateGridPoints() + { + if ((Resolution & 128) == 0 || // The direction increments have to be given + ScanMode != 0) // Expect to scan the grid from North to South and West to East, and consecutive in i direction + { + throw new NotSupportedException(); + } + + var firstGridPoint = new Coordinate(La1, Lo1); + var lastGridPoint = new Coordinate(La2, Lo2); + + var xStep = Dx; + var yStep = -Dy; + var currentGridPoint = firstGridPoint; + + // Adjacent points in x direction are consecutive + var latitudeOffset = 0d; + for (var y = 0; y < Ny; y++) + { + var longitudeOffset = 0d; + for (var x = 0; x < Nx; x++) + { + currentGridPoint = firstGridPoint.Add(latitudeOffset, longitudeOffset); + yield return currentGridPoint; + + longitudeOffset += xStep; + } + latitudeOffset += yStep; + } + + Debug.Assert(lastGridPoint.Equals(currentGridPoint)); + } +} // end Grib1GridDefinitionSection \ No newline at end of file diff --git a/tmp/Grib1/Grib1IndicatorSection.cs b/tmp/Grib1/Grib1IndicatorSection.cs new file mode 100644 index 0000000..f4df8b2 --- /dev/null +++ b/tmp/Grib1/Grib1IndicatorSection.cs @@ -0,0 +1,166 @@ +/* + * This file is part of NGrib. + * + * Copyright © 2020 Nicolas Manguй + * + * Copyright 2006-2010 Seaware AB, PO Box 1244, SE-131 28 + * Nacka Strand, Sweden, info@seaware.se. + * + * Copyright 1997-2006 Unidata Program Center/University + * Corporation for Atmospheric Research, P.O. Box 3000, Boulder, CO 80307, + * support@unidata.ucar.edu. + * + * NGrib is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * NGrib is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with NGrib. If not, see . + */ + +namespace NGrib.Grib1; + +/// A class that represents the IndicatorSection of a GRIB record. +/// +/// +/// Robb Kambic +/// +/// 1.0 +/// +/// +public sealed class Grib1IndicatorSection +{ + /// Get the byte length of this GRIB record. + /// + /// + /// length in bytes of GRIB record + /// + public long GribLength + { + get { return gribLength; } + } + + /// Get the byte length of the IndicatorSection0 section. + /// + /// + /// length in bytes of IndicatorSection0 section + /// + public int Length + { + get { return length; } + } + + /// Get the edition of the GRIB specification used. + /// + /// + /// edition number of GRIB specification + /// + public int GribEdition + { + get { return edition; } + } + + /// Length in bytes of GRIB record. + private long gribLength; + + /// Length in bytes of IndicatorSection. + /// Section length differs between GRIB editions 1 and 2 + /// Currently only GRIB edition 1 supported - length is 16 octets/bytes. + /// + private int length; + + /// Discipline - GRIB Master Table Number. + private int discipline; + + /// Edition of GRIB specification used. + //UPGRADE_NOTE: Final was removed from the declaration of 'edition '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'" + private int edition; + + // *** constructors ******************************************************* + + /// Constructs a Grib1IndicatorSection object from a byteBuffer. + /// + /// + /// RandomAccessFile with IndicatorSection content + /// + /// + /// NotSupportedException if raf contains no valid GRIB file + /// IOException + //UPGRADE_TODO: Class 'java.io.RandomAccessFile' was converted to 'System.IO.FileStream' which has a different behavior. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1073_javaioRandomAccessFile'" + internal Grib1IndicatorSection(System.IO.Stream raf) + { + long mark = raf.Position; + //if Grib edition 1, get bytes for the gribLength + int[] data = new int[3]; + for (int i = 0; i < 3; i++) + { + data[i] = raf.ReadByte(); + } + + + // edition of GRIB specification + edition = raf.ReadByte(); + + if (edition == 1) + { + // length of GRIB record + // Reset to beginning, then read 3 bytes + raf.Position = mark; + gribLength = (long) GribNumbers.uint3(raf); + // Skip next byte, edition already read + raf.ReadByte(); + + length = 8; + } + else if (edition == 2) + { + // length of GRIB record + discipline = data[2]; + + gribLength = GribNumbers.int8(raf); + + length = 16; + } + else + { + throw new NotSupportedException("GRIB edition " + edition + " is not yet supported"); + } + } // end Grib1IndicatorSection + + // --Commented out by Inspection START (12/5/05 3:52 PM): + // /** + // * Discipline - GRIB Master Table Number. + // * @return discipline as a number + // */ + // public final int getDiscipline() + // { + // return discipline; + // } + // --Commented out by Inspection STOP (12/5/05 3:52 PM) + + // --Commented out by Inspection START (12/5/05 3:52 PM): + // /** + // * Discipline - GRIB Master Table Name. + // * @return return Discipline Name as String + // */ + // public final String getDisciplineName() + // { + // switch( discipline ) { + // + // case 0: return "Meteorological products" ; + // case 1: return "Hydrological products"; + // case 2: return "Land surface products"; + // case 3: return "Space products"; + // case 10: return "Oceanographic products"; + // default: return "Unknown"; + // } + // + // } + // --Commented out by Inspection STOP (12/5/05 3:52 PM) +} \ No newline at end of file diff --git a/tmp/Grib1/Grib1Input.cs b/tmp/Grib1/Grib1Input.cs new file mode 100644 index 0000000..ceeb719 --- /dev/null +++ b/tmp/Grib1/Grib1Input.cs @@ -0,0 +1,160 @@ +/* + * This file is part of NGrib. + * + * Copyright � 2020 Nicolas Mangu� + * + * Copyright 2006-2010 Seaware AB, PO Box 1244, SE-131 28 + * Nacka Strand, Sweden, info@seaware.se. + * + * Copyright 1997-2006 Unidata Program Center/University + * Corporation for Atmospheric Research, P.O. Box 3000, Boulder, CO 80307, + * support@unidata.ucar.edu. + * + * NGrib is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * NGrib is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with NGrib. If not, see . + */ + +using NGrib.Common; + +namespace NGrib.Grib1; + +/// A class that scans a GRIB file to extract product information. +public sealed class Grib1Input +{ + #region Fields + /* + * stores records of Grib file, records consist of objects for each section. + * there are 5 sections to a Grib1 record. + */ + //UPGRADE_NOTE: Final was removed from the declaration of 'records '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'" + private List _records = new(); + + private readonly Grib1File _grib1File; + + + #endregion + + + #region Properties + + #region Internal + + /* + * raf for grib file + */ + internal Stream InputStream { get; private set; } + + #endregion + + + #region Public + + /// Get records of the GRIB file. + /// + /// + /// records + /// + public IReadOnlyList Records => _records; + + #endregion + + #endregion + + + #region Constructors + + // *** constructors ******************************************************* + + + /// Constructs a Grib1Input object from a raf. + /// + /// + /// with GRIB content + /// + /// + //UPGRADE_TODO: Class 'java.io.RandomAccessFile' was converted to 'System.IO.FileStream' which has a different behavior. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1073_javaioRandomAccessFile'" + public Grib1Input(System.IO.Stream raf, Grib1File grib1File) + { + this.InputStream = raf; + _grib1File = grib1File; + } + + #endregion + + + #region Methods + + + /// scans a Grib file to gather information that could be used to + /// create an index or dump the metadata contents. + /// + /// + /// products have enough information for data extractions + /// + /// returns after processing one record in the Grib file + /// + /// NotSupportedException + public IEnumerable ScanRecords() + { + + InputStream.Seek(0, SeekOrigin.Begin); + + // stores the number of times a particular GDS is used + //UPGRADE_TODO: Class 'java.util.HashMap' was converted to 'System.Collections.Hashtable' which has a different behavior. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1073_javautilHashMap'" + System.Collections.Hashtable gdsCounter = new System.Collections.Hashtable(); + //Grib1ProductDefinitionSection pds; + Grib1GridDefinitionSection gds = null; + long startOffset; + + + while (InputStream.Position < InputStream.Length) + { + if (!CommonGribFile.SeekHeader(InputStream, InputStream.Length, out startOffset)) continue; + var gr = _grib1File.ReadGrib1Record(InputStream, startOffset, gdsCounter, ref gds); + if (gr == null) + continue; + yield return gr; + } // end while raf.Position < raf.Length + + _grib1File.CheckGdSkeys(gds, gdsCounter); + } + + // end scan + + public Grib1Record GetRecord(int idx) + { + if (idx < 0 || idx >= _records.Count) + { + throw new IndexOutOfRangeException(); + } + + return _records[idx] as Grib1Record; + } + + public void SetFilename(string filename) + { + InputStream = new System.IO.FileStream(filename, System.IO.FileMode.Open, System.IO.FileAccess.Read); + } + + public void CloseFile() + { + InputStream.Close(); + } + + public double MissingValue + { + get { return Grib1BinaryDataSection.MissingValue; } + } + + #endregion +} // end Grib1Input \ No newline at end of file diff --git a/tmp/Grib1/Grib1Product.cs b/tmp/Grib1/Grib1Product.cs new file mode 100644 index 0000000..83787ab --- /dev/null +++ b/tmp/Grib1/Grib1Product.cs @@ -0,0 +1,133 @@ +/* + * This file is part of NGrib. + * + * Copyright 2020 Nicolas Mangu + * + * Copyright 2006-2010 Seaware AB, PO Box 1244, SE-131 28 + * Nacka Strand, Sweden, info@seaware.se. + * + * Copyright 1997-2006 Unidata Program Center/University + * Corporation for Atmospheric Research, P.O. Box 3000, Boulder, CO 80307, + * support@unidata.ucar.edu. + * + * NGrib is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * NGrib is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with NGrib. If not, see . + */ + +namespace NGrib.Grib1; + +/// Title: Grib1 +/// Description: Class which has the necessary information about +/// a product in a Grib1 File to extract the data for the product. +/// +/// Robb Kambic +/// +/// 1.0 +/// +public sealed class Grib1Product +{ + /// get the discipline of product as int. + /// discipline + /// + public int Discipline + { + get { return discipline; } + } + + /// get category of this product as int. + /// category as a int + /// + public int Category + { + get { return category; } + } + + //UPGRADE_NOTE: Respective javadoc comments were merged. It should be changed in order to comply with .NET documentation conventions. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1199'" + /// gets GDS key for this product. + /// gdsKey + /// + /// sets the GDS key for this product. + /// MD5 checksum as text + /// + public System.String GDSkey + { + get { return gdsKey; } + + set { gdsKey = value; } + } + + /// get the PDS for this product. + /// pds + /// + public Grib1ProductDefinitionSection PDS + { + get { return pds; } + } + + /// offset to where to start reading data for this product. + /// dataOffset + /// + public long DataOffset + { + get { return dataOffset; } + } + + /// where this record ends in the Grib File. + /// endRecordOffset + /// + public long EndRecordOffset + { + get { return endRecordOffset; } + } + + //UPGRADE_NOTE: Final was removed from the declaration of 'header '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'" + private System.String header; + + //UPGRADE_NOTE: Final was removed from the declaration of 'discipline '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'" + private int discipline = 0; + + //UPGRADE_NOTE: Final was removed from the declaration of 'category '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'" + private int category = -1; + + // --Commented out by Inspection (11/17/05 2:14 PM): protected Grib1IndicatorSection is = null; + private Grib1ProductDefinitionSection pds; + private System.String gdsKey; + private long dataOffset = -1; + private long endRecordOffset = -1; + + /// Constructor. + /// + /// + /// + /// + /// + /// + /// + /// + /// endRecordOffset in file + /// + internal Grib1Product(System.String header, Grib1ProductDefinitionSection pds, System.String gdsKey, long offset, long size) + { + this.header = header; + this.gdsKey = gdsKey; + this.pds = pds; + dataOffset = offset; + endRecordOffset = size; + } + + // --Commented out by Inspection START (11/17/05 2:15 PM): + // public final String getHeader(){ + // return header; + // } + // --Commented out by Inspection STOP (11/17/05 2:15 PM) +} // end Grib1Product \ No newline at end of file diff --git a/tmp/Grib1/Grib1ProductDefinitionSection.cs b/tmp/Grib1/Grib1ProductDefinitionSection.cs new file mode 100644 index 0000000..d87759b --- /dev/null +++ b/tmp/Grib1/Grib1ProductDefinitionSection.cs @@ -0,0 +1,999 @@ +/* + * This file is part of NGrib. + * + * Copyright © 2020 Nicolas Manguй + * + * Copyright 2006-2010 Seaware AB, PO Box 1244, SE-131 28 + * Nacka Strand, Sweden, info@seaware.se. + * + * Copyright 1997-2006 Unidata Program Center/University + * Corporation for Atmospheric Research, P.O. Box 3000, Boulder, CO 80307, + * support@unidata.ucar.edu. + * + * NGrib is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * NGrib is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with NGrib. If not, see . + */ + +/// Grib1ProductDefinitionSection.java 1.1 09/30/2004 +/// +/// Parameters use external tables, so program does not have to be modified to +/// add support for new tables. +/// +/// +/// + +using System.Diagnostics.CodeAnalysis; +using NGrib.Grib1.PdsParameterTables; +using NGrib.Grib2.CodeTables; + +namespace NGrib.Grib1; + +/// A class representing the product definition section (PDS) of a GRIB record. +/// +/// +public sealed record Grib1ProductDefinitionSection +{ + /// Center as int. + /// center_id + /// + public int Center + { + get { return center_id; } + } + + /// Process Id as int. + /// process_id + /// + public int Process_Id + { + get { return process_id; } + } + + /// Grid ID as int. + /// grid_id + /// + public int Grid_Id + { + get { return grid_id; } + } + + /// SubCenter as int. + /// subCenter + /// + public int SubCenter + { + get { return subcenter_id; } + } + + /// gets the Table version as a int. + /// table_version + /// + public int TableVersion + { + get { return table_version; } + } + + /// Get the exponent of the decimal scale used for all data values. + /// + /// + /// exponent of decimal scale + /// + public int DecimalScale + { + get { return decscale; } + } + + /// Get the number of the parameter. + /// + /// + /// index number of parameter in table + /// + public int ParameterNumber + { + get { return parameterNumber; } + } + + /// Get the type of the parameter. + /// + /// + /// type of parameter + /// + public String Type + { + get { return parameter.Name; } + } + + /// Get a descritpion of the parameter. + /// + /// + /// descritpion of parameter + /// + public String Description + { + get { return parameter.Description; } + } + + /// Get the name of the unit of the parameter. + /// + /// + /// name of the unit of the parameter + /// + public String Unit + { + get { return parameter.Unit; } + } + + /// Get the name for the type of level for forecast/analysis. + /// + /// + /// name of level (height or pressure) + /// + public String LevelName + { + get { return level.Name; } + } + + /// Get the numeric value for this level. + /// + /// + /// name of level (height or pressure) + /// + public int LevelType + { + get { return level.Index; } + } + + /// Get the numeric value for this level. + /// + /// + /// name of level (height or pressure) + /// + public int LevelValue1 + { + get + { + //UPGRADE_WARNING: Data types in Visual C# might be different. Verify the accuracy of narrowing conversions. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1042'" + return (int) level.Value1; + } + } + + /// Get value 2 (if it exists) for this level. + /// + /// + /// name of level (height or pressure) + /// + public int LevelValue2 + { + get + { + //UPGRADE_WARNING: Data types in Visual C# might be different. Verify the accuracy of narrowing conversions. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1042'" + return (int) level.Value2; + } + } + + /// Get the base (analysis) time of the forecast. + /// + /// + /// date and time + /// + public DateTime BaseTime + { + get { return baseTime; } + } + + /// gets reference time as a String. + /// referenceTime + /// + public String ReferenceTime + { + get { return referenceTime; } + } + + /// Get the time of the forecast. + /// + /// + /// date and time + /// + public int ForecastTime + { + get { return forecastTime; } + } + + /// Get the time unit. + /// + /// + /// time unit + /// + public int TimeUnitValue + { + get { return timeUnit; } + } + + + /// P1. + /// p1 + /// + public int P1 + { + get { return p1; } + } + + /// P2. + /// p2 + /// + public int P2 + { + get { return p2; } + } + + /// Get the parameter for this pds. + /// parameter + /// + public Parameter Parameter + { + get { return parameter; } + } + + /// gets the time unit ie hour. + /// tUnit + /// + public String TimeUnit + { + get { return tUnit; } + } + + public TimeRangeUnitGrib1 TimeRangeUnit => _tRangeUnitGrib1; + + /// ProductDefinition as a int. + /// timeRangeValue + /// + public int ProductDefinition + { + get { return timeRangeValue; } + } + + /// TimeRange as int. + /// timeRangeValue + /// + public int TimeRange + { + get { return timeRangeValue; } + } + + /// TimeRange as String. + /// timeRange + /// + public String TimeRangeString + { + get { return timeRange; } + } + + /// PDS length did not correspond with read . + /// lengthErr + /// + public bool LengthErr + { + get { return lengthErr; } + } + + public int RefTimeT + { + get + { + DateTime startTime = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc); + TimeSpan rt = refTime - startTime; + int t = Convert.ToInt32(rt.TotalSeconds); + return t; + } + } + + public Grib1WaveSpectra2DDirFreq WaveSpectra2DDirFreq + { + get { return waveSpectra2DDirFreq; } + } + + //UPGRADE_ISSUE: Class 'java.text.SimpleDateFormat' was not converted. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1000_javatextSimpleDateFormat'" + private static System.Globalization.DateTimeFormatInfo dateFormat; + + /// Length in bytes of this PDS. + //UPGRADE_NOTE: Final was removed from the declaration of 'length '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'" + private int length; + + /// Exponent of decimal scale. + //UPGRADE_NOTE: Final was removed from the declaration of 'decscale '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'" + private int decscale; + + /// ID of grid type. + //UPGRADE_NOTE: Final was removed from the declaration of 'grid_id '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'" + private int grid_id; + + /// True, if GDS exists. + //UPGRADE_NOTE: Final was removed from the declaration of 'gds_exists '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'" + private bool gds_exists; + + /// True, if BMS exists. + //UPGRADE_NOTE: Final was removed from the declaration of 'bms_exists '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'" + private bool bms_exists; + + /// The parameter as defined in the Parameter Table. + //UPGRADE_NOTE: Final was removed from the declaration of 'parameter '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'" + private Parameter parameter; + + /// parameterNumber. + //UPGRADE_NOTE: Final was removed from the declaration of 'parameterNumber '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'" + private int parameterNumber; + + /// Class containing the information about the level. This helps to actually + /// use the data, otherwise the string for level will have to be parsed. + /// + //UPGRADE_NOTE: Final was removed from the declaration of 'level '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'" + private GribPDSLevel level; + + /// Model Run/Analysis/Reference time. + /// + /// + // TODO Why baseTime??? + private DateTime baseTime; + + private String referenceTime = ""; + + /// Forecast time (valid time). + private int forecastTime; + + /// Forecast time. (valid time 1) + /// Also used as starting time when times represent a period. + /// + private int p1; + + /// Ending time when times represent a period (valid time 2). + private int p2; + + /// Strings used in building a string to represent the time(s) for this PDS + /// See the decoder for octet 21 to get an understanding. + /// + private String timeRange; + + //UPGRADE_NOTE: Final was removed from the declaration of 'timeRangeValue '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'" + private int timeRangeValue; + private String tUnit; + + private TimeRangeUnitGrib1 _tRangeUnitGrib1 = TimeRangeUnitGrib1.Missing; + + /// Parameter Table Version number. + //UPGRADE_NOTE: Final was removed from the declaration of 'table_version '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'" + private int table_version; + + /// Identification of center e.g. 88 for Oslo. + //UPGRADE_NOTE: Final was removed from the declaration of 'center_id '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'" + private int center_id; + + /// Identification of subcenter. + //UPGRADE_NOTE: Final was removed from the declaration of 'subcenter_id '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'" + private int subcenter_id; + + /// Identification of Generating Process. + //UPGRADE_NOTE: Final was removed from the declaration of 'process_id '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'" + private int process_id; + + /// ensemble products have more information. + private Grib1Ensemble epds; + + /// PDS length not equal to number bytes read. + //UPGRADE_NOTE: Final was removed from the declaration of 'lengthErr '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'" + private bool lengthErr = false; + + private DateTime refTime; + + private int timeUnit; + + private Grib1WaveSpectra2DDirFreq waveSpectra2DDirFreq; + + /// + /// Data reserved for originating centre use + /// at the end of the section. + /// + /// + /// Each byte is stored as an item in the array. + /// + public int[] CustomData { get; } + + // *** constructors ******************************************************* + + /// Constructs a Grib1ProductDefinitionSection object from a raf. + /// + /// + /// with PDS content + /// + /// + /// NotSupportedException if raf contains no valid GRIB file + //UPGRADE_TODO: Class 'java.io.RandomAccessFile' was converted to 'System.IO.FileStream' which has a different behavior. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1073_javaioRandomAccessFile'" + internal Grib1ProductDefinitionSection(System.IO.Stream raf) + { + // octets 1-3 PDS length + length = (int) GribNumbers.uint3(raf); + + + // Paramter table octet 4 + table_version = raf.ReadByte(); + + // Center octet 5 + center_id = raf.ReadByte(); + + // octet 6 Generating Process - See Table A + process_id = raf.ReadByte(); + + // octet 7 (id of grid type) - not supported yet + grid_id = raf.ReadByte(); + + //octet 8 (flag for presence of GDS and BMS) + int exists = raf.ReadByte(); + //BKSystem.IO.BitStream s = new BKSystem.IO.BitStream(8); +// s.WriteByte((byte)raf.ReadByte()); +// s.Position = 0; +// sbyte exists; +// s.Read(out exists); +// bms_exists = (exists & 64) == 64; + + gds_exists = (exists & 128) == 128; + bms_exists = (exists & 64) == 64; + + // octet 9 (parameter and unit) + parameterNumber = raf.ReadByte(); + + // octets 10-12 (level) + int levelType = raf.ReadByte(); + int levelValue1 = raf.ReadByte(); + int levelValue2 = raf.ReadByte(); + level = new GribPDSLevel(levelType, levelValue1, levelValue2); + + // octets 13-17 (base time for reference time) + int year = raf.ReadByte(); + int month = raf.ReadByte(); + int day = raf.ReadByte(); + int hour = raf.ReadByte(); + int minute = raf.ReadByte(); + + // get info for forecast time + // octet 18 Forecast time unit + timeUnit = raf.ReadByte(); + + switch (timeUnit) + { + case 0: // minute + tUnit = "minute"; + _tRangeUnitGrib1 = TimeRangeUnitGrib1.Minute; + break; + + case 1: // hours + tUnit = "hour"; + _tRangeUnitGrib1 = TimeRangeUnitGrib1.Hour; + break; + + case 2: // day + tUnit = "day"; + _tRangeUnitGrib1 = TimeRangeUnitGrib1.Day; + break; + + case 3: // month + tUnit = "month"; + _tRangeUnitGrib1 = TimeRangeUnitGrib1.Month; + break; + + case 4: //1 year + tUnit = "1year"; + _tRangeUnitGrib1 = TimeRangeUnitGrib1.Year; + break; + + case 5: // decade + tUnit = "decade"; + _tRangeUnitGrib1 = TimeRangeUnitGrib1.Decade; + break; + + case 6: // normal + tUnit = "normal"; + _tRangeUnitGrib1 = TimeRangeUnitGrib1.Normal; + break; + + case 7: // century + tUnit = "century"; + _tRangeUnitGrib1 = TimeRangeUnitGrib1.Century; + break; + + case 10: //3 hours + tUnit = "3hours"; + _tRangeUnitGrib1 = TimeRangeUnitGrib1.Hours3; + break; + + case 11: // 6 hours + tUnit = "6hours"; + _tRangeUnitGrib1 = TimeRangeUnitGrib1.Hours6; + break; + + case 12: // 12 hours + tUnit = "12hours"; + _tRangeUnitGrib1 = TimeRangeUnitGrib1.Hours12; + break; + + case 13: + tUnit = "15 minutes"; + _tRangeUnitGrib1 = TimeRangeUnitGrib1.Minutes15; + break; + + case 14: + tUnit = "30 minutes"; + _tRangeUnitGrib1 = TimeRangeUnitGrib1.Minutes30; + break; + + case >=15 and <=253: + tUnit = "reserved"; + _tRangeUnitGrib1 = TimeRangeUnitGrib1.Reserved; + break; + + case 254: // second + tUnit = "second"; + _tRangeUnitGrib1 = TimeRangeUnitGrib1.Second; + break; + + default: + Console.Error.WriteLine("PDS: Time Unit " + timeUnit + " is not yet supported"); + _tRangeUnitGrib1 = TimeRangeUnitGrib1.Missing; + break; + } + + // octet 19 & 20 used to create Forecast time + p1 = raf.ReadByte(); + p2 = raf.ReadByte(); + + // octet 21 (time range indicator) + timeRangeValue = raf.ReadByte(); + // forecast time is always at the end of the range + + switch (timeRangeValue) + { + case 0: + timeRange = "product valid at RT + P1"; + forecastTime = p1; + break; + + case 1: + timeRange = "product valid for RT, P1=0"; + forecastTime = 0; + break; + + case 2: + timeRange = "product valid from (RT + P1) to (RT + P2)"; + forecastTime = p2; + break; + + case 3: + timeRange = "product is an average between (RT + P1) to (RT + P2)"; + forecastTime = p2; + break; + + case 4: + timeRange = "product is an accumulation between (RT + P1) to (RT + P2)"; + forecastTime = p2; + break; + + case 5: + timeRange = "product is the difference (RT + P2) - (RT + P1)"; + forecastTime = p2; + break; + + case 6: + timeRange = "product is an average from (RT - P1) to (RT - P2)"; + forecastTime = -p2; + break; + + case 7: + timeRange = "product is an average from (RT - P1) to (RT + P2)"; + forecastTime = p2; + break; + + case 10: + timeRange = "product valid at RT + P1"; + // p1 really consists of 2 bytes p1 and p2 + forecastTime = p1 = GribNumbers.int2(p1, p2); + p2 = 0; + break; + + case 51: + timeRange = "mean value from RT to (RT + P2)"; + forecastTime = p2; + break; + + default: + Console.Error.WriteLine("PDS: Time Range Indicator " + timeRangeValue + " is not yet supported"); + break; + } + + // octet 22 & 23 + int avgInclude = GribNumbers.int2(raf); + + // octet 24 + int avgMissing = raf.ReadByte(); + + // octet 25 + int century = raf.ReadByte() - 1; + + // octet 26, sub center + subcenter_id = raf.ReadByte(); + + // octets 27-28 (decimal scale factor) + decscale = GribNumbers.int2(raf); + + refTime = new DateTime(century * 100 + year, month, day, hour, minute, 0, DateTimeKind.Utc); + baseTime = refTime; + referenceTime = refTime.ToString(dateFormat); + + + //(century * 100 + year) +"-" + + //month + "-" + day + "T" + hour +":" + minute +":00Z" ); + + + var parameterTable = GribPdsParamTable.GetParameterTable(center_id, subcenter_id, table_version); + parameter = parameterTable.GetParameter(parameterNumber); + //parameter = new Parameter(); + + + if (center_id == 7 && subcenter_id == 2) + { + CustomData = new int[0]; + + // ensemble product + epds = new Grib1Ensemble(raf, parameterNumber); + } + // Special handling of 2D Wave Spectra (single) + else if (table_version == 140 && parameterNumber == 251) + { + CustomData = new int[0]; + + SupportClass.Skip(raf, 12); + int extDef = raf.ReadByte(); // Extension definition + + // Read ECMWF extension for 2D wave spectra single + if (extDef == 13) + { + waveSpectra2DDirFreq = new Grib1WaveSpectra2DDirFreq(raf); + } + } + else + { + // Ignore reserved bytes 29-40 + for (int i = 29; i <= Math.Min(length, 40); i++) + { + raf.ReadByte(); + } + + // Try to read extra bytes + CustomData = new int[Math.Max(length - 40, 0)]; + for (int i = 0; i < CustomData.Length; i++) + { + CustomData[i] = raf.ReadByte(); + } + } + } // end Grib1ProductDefinitionSection + + // --Commented out by Inspection START (11/9/05 10:19 AM): + // /** + // * Get the byte length of this section. + // * + // * @return length in bytes of this section + // */ + // public int getLength() + // { + // return length; + // } + // --Commented out by Inspection STOP (11/9/05 10:19 AM) + + /// Check if GDS exists. + /// + /// + /// true, if GDS exists + /// + public bool gdsExists() + { + return gds_exists; + } + + /// Check if BMS exists. + /// + /// + /// true, if BMS exists + /// + public bool bmsExists() + { + return bms_exists; + } + + /// Name of Identification of center . + /// Center Name as String + /// + public String getCenter_idName() + { + return getCenter_idName(center_id); + } + + private static String getCenter_idName(int center) + { + switch (center) + { + case 0: return "WMO Secretariat"; + + case 1: + case 2: return "Melbourne"; + + case 4: + case 5: return "Moscow"; + + case 7: return "US National Weather Service (NCEP)"; + + case 8: return "US National Weather Service (NWSTG)"; + + case 9: return "US National Weather Service (other)"; + + case 10: return "Cairo (RSMC/RAFC)"; + + case 12: return "Dakar (RSMC/RAFC)"; + + case 14: return "Nairobi (RSMC/RAFC)"; + + case 16: return "Atananarivo (RSMC)"; + + case 18: return "Tunis Casablanca (RSMC)"; + + case 20: return "Las Palmas (RAFC)"; + + case 21: return "Algiers (RSMC)"; + + case 22: return "Lagos (RSMC)"; + + case 24: return "Pretoria (RSMC)"; + + case 25: return "La R?union (RSMC)"; + + case 26: return "Khabarovsk (RSMC)"; + + case 28: return "New Delhi (RSMC/RAFC)"; + + case 30: return "Novosibirsk (RSMC)"; + + case 32: return "Tashkent (RSMC)"; + + case 33: return "Jeddah (RSMC)"; + + case 34: return "Tokyo (RSMC), Japan Meteorological Agency"; + + case 36: return "Bangkok"; + + case 37: return "Ulan Bator"; + + case 38: return "Beijing (RSMC)"; + + case 40: return "Seoul"; + + case 41: return "Buenos Aires (RSMC/RAFC)"; + + case 43: return "Brasilia (RSMC/RAFC)"; + + case 45: return "Santiago"; + + case 46: return "Brazilian Space Agency ? INPE"; + + case 51: return "Miami (RSMC/RAFC)"; + + case 52: return "Miami RSMC, National Hurricane Center"; + + case 53: + case 54: return "Montreal (RSMC)"; + + case 55: return "San Francisco"; + + case 57: return "Air Force Weather Agency"; + + case 58: return "Fleet Numerical Meteorology and Oceanography Center"; + + case 59: return "The NOAA Forecast Systems Laboratory"; + + case 60: return "United States National Centre for Atmospheric Research (NCAR)"; + + case 64: return "Honolulu"; + + case 65: return "Darwin (RSMC)"; + + case 67: return "Melbourne (RSMC)"; + + case 69: return "Wellington (RSMC/RAFC)"; + + case 71: return "Nadi (RSMC)"; + + case 74: return "UK Meteorological Office Bracknell (RSMC)"; + + case 76: return "Moscow (RSMC/RAFC)"; + + case 78: return "Offenbach (RSMC)"; + + case 80: return "Rome (RSMC)"; + + case 82: return "Norrkoping"; + + case 85: return "Toulouse (RSMC)"; + + case 86: return "Helsinki"; + + case 87: return "Belgrade"; + + case 88: return "Oslo"; + + case 89: return "Prague"; + + case 90: return "Episkopi"; + + case 91: return "Ankara"; + + case 92: return "Frankfurt/Main (RAFC)"; + + case 93: return "London (WAFC)"; + + case 94: return "Copenhagen"; + + case 95: return "Rota"; + + case 96: return "Athens"; + + case 97: return "European Space Agency (ESA)"; + + case 98: return "ECMWF, RSMC"; + + case 99: return "De Bilt"; + + case 110: return "Hong-Kong"; + + case 210: return "Frascati (ESA/ESRIN)"; + + case 211: return "Lanion"; + + case 212: return "Lisboa"; + + case 213: return "Reykjavik"; + + case 254: return "EUMETSAT Operation Centre"; + + + default: return "Unknown"; + } + } // end getCenter_idName + + /// SubCenter as String. + /// + /// + /// subCenter + /// + public String getSubCenter_idName(int center) + { + if (center_id == 7) + { + //NWS + switch (center) + { + case 0: return "WMO Secretariat"; + + case 1: return "NCEP Re-Analysis Project"; + + case 2: return "NCEP Ensemble Products"; + + case 3: return "NCEP Central Operations"; + + case 4: return "Environmental Modeling Center"; + + case 5: return "Hydrometeorological Prediction Center"; + + case 6: return "Marine Prediction Center"; + + case 7: return "Climate Prediction Center"; + + case 8: return "Aviation Weather Center"; + + case 9: return "Storm Prediction Center"; + + case 10: return "Tropical Prediction Center"; + + case 11: return "NWS Techniques Development Laboratory"; + + case 12: return "NESDIS Office of Research and Applications"; + + case 13: return "FAA"; + + case 14: return "NWS Meteorological Development Laboratory"; + + case 15: return " The North American Regional Reanalysis (NARR) Project"; + } + } + + return getCenter_idName(center); + } + + /// ProductDefinition name. + /// + /// + /// name of ProductDefinition + /// + public static String getProductDefinitionName(int type) + { + switch (type) + { + case 0: return "Forecast/Uninitialized Analysis/Image Product"; + + case 1: return "Initialized analysis product"; + + case 2: return "Product with a valid time between P1 and P2"; + + case 3: + case 6: + case 7: return "Average"; + + case 4: return "Accumulation"; + + case 5: return "Difference"; + + case 10: return "product valid at reference time P1"; + + case 51: return "Climatological Mean Value"; + + case 113: + case 115: + case 117: return "Average of N forecasts"; + + case 114: + case 116: return "Accumulation of N forecasts"; + + case 118: return "Temporal variance"; + + case 119: + case 125: return "Standard deviation of N forecasts"; + + case 123: return "Average of N uninitialized analyses"; + + case 124: return "Accumulation of N uninitialized analyses"; + + case 128: return "Average of daily forecast accumulations"; + + case 129: return "Average of successive forecast accumulations"; + + case 130: return "Average of daily forecast averages"; + + case 131: return "Average of successive forecast averages"; + + case 132: return "Climatological Average of N analyses"; + + case 133: return "Climatological Average of N forecasts"; + + case 134: return "Climatological Root Mean Square difference between N forecasts and their verifying analyses"; + + case 135: return "Climatological Standard Deviation of N forecasts from the mean of the same N forecasts"; + + case 136: return "Climatological Standard Deviation of N analyses from the mean of the same N analyses"; + } + + return "Unknown"; + } + + static Grib1ProductDefinitionSection() + { + { + dateFormat = new System.Globalization.DateTimeFormatInfo(); + } + } +} + +// end class Grib1ProductDefinitionSection \ No newline at end of file diff --git a/tmp/Grib1/Grib1Record.cs b/tmp/Grib1/Grib1Record.cs new file mode 100644 index 0000000..d7a0cba --- /dev/null +++ b/tmp/Grib1/Grib1Record.cs @@ -0,0 +1,73 @@ +/* + * This file is part of NGrib. + * + * Copyright © 2020 Nicolas Manguй + * + * Copyright 2006-2010 Seaware AB, PO Box 1244, SE-131 28 + * Nacka Strand, Sweden, info@seaware.se. + * + * Copyright 1997-2006 Unidata Program Center/University + * Corporation for Atmospheric Research, P.O. Box 3000, Boulder, CO 80307, + * support@unidata.ucar.edu. + * + * NGrib is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * NGrib is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with NGrib. If not, see . + */ + +namespace NGrib.Grib1; + +/// Grib1Record contains all the sections of a Grib record. +/// Robb Kambic 11/13/03 +/// +public sealed class Grib1Record +{ + /// Get header. + /// header + /// + public System.String Header { get; } + + /// Get Information record. + /// an IS record + /// + public Grib1IndicatorSection IndicatorSection { get; } + + /// Get Product Definition record. + /// a PDS record + /// + public Grib1ProductDefinitionSection ProductDefinitionSection { get; } + + /// Get Grid Definition record. + /// a + /// + public Grib1GridDefinitionSection GridDefinitionSection { get; } + + /// Get offset to bms. + /// long + /// + public long DataOffset { get; } = -1; + + public long RecordOffset { get; } = -1; + + private long endRecordOffset = -1; + + internal Grib1Record(System.String hdr, Grib1IndicatorSection aIndicatorSection, Grib1ProductDefinitionSection aProductDefinitionSection, Grib1GridDefinitionSection aGridDefinitionSection, long offset, long recOffset, long startOfRecordOffset) + { + Header = hdr; + IndicatorSection = aIndicatorSection; + ProductDefinitionSection = aProductDefinitionSection; + GridDefinitionSection = aGridDefinitionSection; + DataOffset = offset; + endRecordOffset = recOffset; + RecordOffset = startOfRecordOffset; + } +} // end Grib1Record \ No newline at end of file diff --git a/tmp/Grib1/Grib1WaveSpectra2DDirFreq.cs b/tmp/Grib1/Grib1WaveSpectra2DDirFreq.cs new file mode 100644 index 0000000..5aab43c --- /dev/null +++ b/tmp/Grib1/Grib1WaveSpectra2DDirFreq.cs @@ -0,0 +1,147 @@ +/* + * This file is part of NGrib. + * + * Copyright 2020 Nicolas Mangu + * + * Copyright 2006-2010 Seaware AB, PO Box 1244, SE-131 28 + * Nacka Strand, Sweden, info@seaware.se. + * + * Copyright 1997-2006 Unidata Program Center/University + * Corporation for Atmospheric Research, P.O. Box 3000, Boulder, CO 80307, + * support@unidata.ucar.edu. + * + * NGrib is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * NGrib is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with NGrib. If not, see . + */ + +namespace NGrib.Grib1; + +public sealed class Grib1WaveSpectra2DDirFreq +{ + private string version; + + public string Version + { + get { return version; } + } + + // one-offset + private int directionNumber; + + public int DirectionNumber + { + get { return directionNumber; } + } + + // one-offset + private int frequencyNumber; + + public int FrequencyNumber + { + get { return frequencyNumber; } + } + + private int numberOfDirections; + + public int NumberOfDirections + { + get { return numberOfDirections; } + } + + private int numberOfFrequencies; + + public int NumberOfFrequencies + { + get { return numberOfFrequencies; } + } + + private int dirScaleFactor; + + public int DirScaleFactor + { + get { return dirScaleFactor; } + } + + private int freqScaleFactor; + + public int FreqScaleFactor + { + get { return freqScaleFactor; } + } + + private double[] directions; + + public double[] Directions + { + get { return directions; } + } + + private double[] frequencies; + + public double[] Frequencies + { + get { return frequencies; } + } + + /// + /// The direction [deg]. + /// + public double Direction + { + get { return directions[directionNumber - 1]; } + } + + /// + /// The frequency [Hz]; + /// + public double Frequency + { + get { return frequencies[frequencyNumber - 1]; } + } + + + internal Grib1WaveSpectra2DDirFreq(System.IO.Stream raf) + { + SupportClass.Skip(raf, 4); + + byte[] ver = GribNumbers.ReadBytes(raf, 4); + System.Text.Encoding enc = System.Text.Encoding.ASCII; + version = enc.GetString(ver); + + SupportClass.Skip(raf, 2); + + directionNumber = raf.ReadByte(); + frequencyNumber = raf.ReadByte(); + numberOfDirections = raf.ReadByte(); + numberOfFrequencies = raf.ReadByte(); + dirScaleFactor = GribNumbers.int4(raf); + freqScaleFactor = GribNumbers.int4(raf); + + SupportClass.Skip(raf, 37); + + directions = new double[numberOfDirections]; + frequencies = new double[numberOfFrequencies]; + + for (int i = 0; i < numberOfDirections; i++) + { + int val = GribNumbers.int4(raf); + directions[i] = (double) val / (double) dirScaleFactor; + } + + for (int i = 0; i < numberOfFrequencies; i++) + { + int val = GribNumbers.int4(raf); + frequencies[i] = (double) val / (double) freqScaleFactor; + } + } +} \ No newline at end of file diff --git a/tmp/Grib1/GribNumbers.cs b/tmp/Grib1/GribNumbers.cs new file mode 100644 index 0000000..e163d83 --- /dev/null +++ b/tmp/Grib1/GribNumbers.cs @@ -0,0 +1,238 @@ +/* + * This file is part of NGrib. + * + * Copyright © 2020 Nicolas Manguй + * + * Copyright 2006-2010 Seaware AB, PO Box 1244, SE-131 28 + * Nacka Strand, Sweden, info@seaware.se. + * + * Copyright 1997-2006 Unidata Program Center/University + * Corporation for Atmospheric Research, P.O. Box 3000, Boulder, CO 80307, + * support@unidata.ucar.edu. + * + * NGrib is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * NGrib is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with NGrib. If not, see . + */ + +namespace NGrib.Grib1; + +/// A class that contains several static methods for converting multiple +/// bytes into one float or integer. +/// +/// +/// Robb Kambic 10/20/04 +/// +/// 2.0 +/// +internal sealed class GribNumbers +{ + /// if missing value is not defined use this value. + public const int UNDEFINED = -9999; + + /// Convert 2 bytes into a signed integer. + /// + /// + /// * + /// + /// integer value + /// + /// IOException + //UPGRADE_TODO: Class 'java.io.RandomAccessFile' was converted to 'System.IO.Stream' which has a different behavior. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1073_javaioRandomAccessFile'" + public static int int2(System.IO.Stream raf) + { + //byte[] bytes = ReadBytes(raf, 2); + //return (int)BitConverter.ToInt16(bytes, 0); + + int a = raf.ReadByte(); + int b = raf.ReadByte(); + return int2(a, b); + } + + public static int int2(int a, int b) + { + return (1 - ((a & 128) >> 6)) * ((a & 127) << 8 | b); + } + + /// Convert 3 bytes into a signed integer. + /// + /// + /// * + /// + /// integer value + /// + /// IOException + public static int int3(System.IO.Stream raf) + { +// byte[] bytes = ReadBytes(raf, 3); +// byte[] fourBytes = new byte[4]; +// bytes.CopyTo(fourBytes, 0); +// fourBytes[3] = 0; +// return BitConverter.ToInt32(fourBytes, 0); + + int a = raf.ReadByte(); + int b = raf.ReadByte(); + int c = raf.ReadByte(); + return (1 - ((a & 128) >> 6)) * ((a & 127) << 16 | b << 8 | c); + } + + + /// Convert 4 bytes into a signed integer. + /// + /// + /// * + /// + /// integer value + /// + /// IOException + public static int int4(System.IO.Stream raf) + { + //byte[] bytes = ReadBytes(raf, 4); + //int i1 = BitConverter.ToInt32(bytes, 0); + + int a = raf.ReadByte(); + int b = raf.ReadByte(); + int c = raf.ReadByte(); + int d = raf.ReadByte(); + + // all bits set to ones + if (a == 0xff && b == 0xff && c == 0xff && d == 0xff) + return UNDEFINED; + + int i2 = (1 - ((a & 128) >> 6)) * ((a & 127) << 24 | b << 16 | c << 8 | d); + return i2; + } + + + /// Convert 2 bytes into an unsigned integer. + /// + /// + /// * + /// + /// integer value + /// + /// IOException + public static int uint2(System.IO.Stream raf) + { + //byte[] bytes = ReadBytes(raf, 2); + //return (uint)BitConverter.ToUInt16(bytes, 0); + + int a = raf.ReadByte(); + int b = raf.ReadByte(); + return a << 8 | b; + } + + /// Convert 3 bytes into an unsigned integer. + /// + /// + /// * + /// + /// integer + /// + /// IOException + public static int uint3(System.IO.Stream raf) + { +// byte[] bytes = ReadBytes(raf, 3); +// byte[] fourBytes = new byte[4]; +// bytes.CopyTo(fourBytes, 0); +// fourBytes[3] = 0; +// return BitConverter.ToUInt32(fourBytes, 0); + + int a = raf.ReadByte(); + int b = raf.ReadByte(); + int c = raf.ReadByte(); + return a << 16 | b << 8 | c; + } + + + /// Convert 4 bytes into a float. + /// + /// + /// FileStream to read from + /// + /// float + /// + /// IOException + public static double double4(System.IO.Stream raf) + { + int a = raf.ReadByte(); + int b = raf.ReadByte(); + int c = raf.ReadByte(); + int d = raf.ReadByte(); + + int sgn, mant, exp; + + mant = b << 16 | c << 8 | d; + if (mant == 0) return 0.0f; + + sgn = -(((a & 128) >> 6) - 1); + exp = (a & 127) - 64; + + return (double) (sgn * Math.Pow(16.0, exp - 6) * mant); + } + + public static float IEEEfloat4(System.IO.Stream raf) + { + byte[] bytes = ReadBytes(raf, 4); + return BitConverter.ToSingle(bytes, 0); + } + + + /// Convert 8 bytes into a signed long. + /// + /// + /// RandomAccessFile + /// + /// + /// long value + /// + /// IOException + //UPGRADE_TODO: Class 'java.io.RandomAccessFile' was converted to 'System.IO.Stream' which has a different behavior. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1073_javaioRandomAccessFile'" + public static long int8(System.IO.Stream raf) + { + int a = raf.ReadByte(); + int b = raf.ReadByte(); + int c = raf.ReadByte(); + int d = raf.ReadByte(); + int e = raf.ReadByte(); + int f = raf.ReadByte(); + int g = raf.ReadByte(); + int h = raf.ReadByte(); + + return (1 - ((a & 128) >> 6)) * ((a & 127) << 56 | b << 48 | c << 40 | d << 32 | e << 24 | f << 16 | g << 8 | h); + } // end int8 + + + public static byte[] ReadBytes(System.IO.Stream raf, int count) + { + byte[] bytes = new byte[count]; + raf.Read(bytes, 0, count); + if (BitConverter.IsLittleEndian) + { + bytes = Swap(bytes); + } + + return bytes; + } + + public static byte[] Swap(byte[] bytes) + { + int nb = bytes.Length; + byte[] swappedBytes = new byte[nb]; + for (int i = 0; i < nb; i++) + { + swappedBytes[i] = bytes[nb - 1 - i]; + } + + return swappedBytes; + } +} // end GribNumbers \ No newline at end of file diff --git a/tmp/Grib1/GribPDSLevel.cs b/tmp/Grib1/GribPDSLevel.cs new file mode 100644 index 0000000..d1dd4be --- /dev/null +++ b/tmp/Grib1/GribPDSLevel.cs @@ -0,0 +1,766 @@ +/* + * This file is part of NGrib. + * + * Copyright 2020 Nicolas Mangu + * + * Copyright 2006-2010 Seaware AB, PO Box 1244, SE-131 28 + * Nacka Strand, Sweden, info@seaware.se. + * + * Copyright 1997-2006 Unidata Program Center/University + * Corporation for Atmospheric Research, P.O. Box 3000, Boulder, CO 80307, + * support@unidata.ucar.edu. + * + * NGrib is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * NGrib is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with NGrib. If not, see . + */ + +/// GribPDSLevel.java 1.0 08/01/2002 +/// +/// Performs operations related to loading level information from Table 3. +/// +/// Capt Richard D. Gonzalez +/// + +namespace NGrib.Grib1; + +/// A class containing static methods which deliver names of +/// levels and units for byte codes from GRIB records. +/// +public sealed class GribPDSLevel +{ + /// Index number from table 3 - can be used for comparison even if the + /// description of the level changes. + /// + /// index + /// + public int Index + { + get { return index; } + } + + /// Name of this level. + /// name as String + /// + public System.String Name + { + get { return name; } + } + + /// gets the 1st value for the level. + /// level value 1 + /// + public float Value1 + { + get { return value1; } + } + + /// gets the 2nd value for the level. + /// level value 2 + /// + public float Value2 + { + get { return value2; } + } + + /// Index number from table 3 - can be used for comparison even if the + /// description of the level changes. + /// + //UPGRADE_NOTE: Final was removed from the declaration of 'index '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'" + private int index; + + /// Name of the vertical coordinate/level. + /// + /// + private System.String name; + + /// Value of PDS octet10 if separate from 11, otherwise value from octet10&11. + private float value1; + + /// Value of PDS octet11. + private float value2; + + /// Constructor. Creates a GribPDSLevel based on octets 10-12 of the PDS. + /// Implements tables 3 and 3a. + /// + /// + /// part 1 of level code index + /// + /// part 2 of level code + /// + /// part 3 of level code + /// + /// + internal GribPDSLevel(int pds10, int pds11, int pds12) + { + int pds1112 = pds11 << 8 | pds12; + index = pds10; + switch (index) + { + case 0: + name = "reserved"; + break; + + case 1: + name = "surface"; + break; + + case 2: + name = "cloud base level"; + break; + + case 3: + name = "cloud top level"; + break; + + case 4: + name = "0 degree isotherm level"; + break; + + case 5: + name = "condensation level"; + break; + + case 6: + name = "maximum wind level"; + break; + + case 7: + name = "tropopause level"; + break; + + case 8: + name = "nominal atmosphere top"; + break; + + case 9: + name = "sea bottom"; + break; + + case 20: + name = "Isothermal level"; + value1 = pds1112; + break; + + case 100: + name = "isobaric"; + value1 = pds1112; + break; + + case 101: + name = "layer between two isobaric levels"; + value1 = pds11 * 10; // convert from kPa to hPa - who uses kPa??? + value2 = pds12 * 10; + break; + + case 102: + name = "mean sea level"; + break; + + case 103: + name = "Altitude above MSL"; + value1 = pds1112; + break; + + case 104: + name = "Layer between two altitudes above MSL"; + value1 = (pds11 * 100); // convert hm to m + value2 = (pds12 * 100); + break; + + case 105: + name = "fixed height above ground"; + value1 = pds1112; + break; + + case 106: + name = "layer between two height levels"; + value1 = (pds11 * 100); // convert hm to m + value2 = (pds12 * 100); + break; + + case 107: + name = "Sigma level"; + value1 = pds1112; + break; + + case 108: + name = "Layer between two sigma layers"; + value1 = pds11; + value2 = pds12; + break; + + case 109: + name = "hybrid level"; + value1 = pds1112; + break; + + case 110: + name = "Layer between two hybrid levels"; + value1 = pds11; + value2 = pds12; + break; + + case 111: + name = "Depth below land surface"; + value1 = pds1112; + break; + + case 112: + name = "Layer between two levels below land surface"; + value1 = pds11; + value2 = pds12; + break; + + case 113: + name = "Isentropic theta level"; + value1 = pds1112; + break; + + case 114: + name = "Layer between two isentropic layers"; + value1 = pds11; + value2 = pds12; + break; + + case 115: + name = "level at specified pressure difference from ground to level"; + value1 = pds1112; + break; + + case 116: + name = "Layer between pressure differences from ground to levels"; + value1 = pds11; + value2 = pds12; + break; + + case 117: + name = "potential vorticity(pv) surface"; + value1 = pds1112; + break; + + case 119: + name = "Eta level"; + value1 = pds1112; + break; + + case 120: + name = "layer between two Eta levels"; + value1 = pds11; + value2 = pds12; + break; + + case 121: + name = "layer between two isobaric surfaces"; + value1 = pds11; + value2 = pds12; + break; + + case 125: + name = "Height above ground (high precision)"; + value1 = pds1112; + break; + + case 126: + name = "isobaric level"; + value1 = pds1112; + break; + + case 128: + name = "layer between two sigma levels"; + value1 = pds11; + value2 = pds12; + break; + + case 141: + name = "layer between two isobaric surfaces"; + value1 = pds11 * 10; // convert from kPa to hPa - who uses kPa??? + value2 = pds12; + break; + + case 160: + name = "Depth below sea level"; + value1 = pds1112; + break; + + case 200: + name = "entire atmosphere layer"; + break; + + case 201: + name = "entire ocean layer"; + break; + + case 204: + name = "Highest tropospheric freezing level"; + break; + + case 206: + name = "Grid scale cloud bottom level"; + break; + + case 207: + name = "Grid scale cloud top level"; + break; + + case 209: + name = "Boundary layer cloud bottom level"; + break; + + case 210: + name = "Boundary layer cloud top level"; + break; + + case 211: + name = "Boundary layer cloud layer"; + break; + + case 212: + name = "Low cloud bottom level"; + break; + + case 213: + name = "Low cloud top level"; + break; + + case 214: + name = "Low Cloud Layer"; + break; + + case 222: + name = "Middle cloud bottom level"; + break; + + case 223: + name = "Middle cloud top level"; + break; + + case 224: + name = "Middle Cloud Layer"; + break; + + case 232: + name = "High cloud bottom level"; + break; + + case 233: + name = "High cloud top level"; + break; + + case 234: + name = "High Cloud Layer"; + break; + + case 235: + name = "Ocean Isotherm Level"; + break; + + case 236: + name = "Layer between two depths below ocean surface"; + value1 = pds11; + value2 = pds12; + break; + + case 237: + name = "Bottom of Ocean Mixed Layer"; + break; + + case 238: + name = "Bottom of Ocean Isothermal Layer"; + break; + + case 242: + name = "Convective cloud bottom level"; + break; + + case 243: + name = "Convective cloud top level"; + break; + + case 244: + name = "Convective cloud layer"; + break; + + case 245: + name = "Lowest level of the wet bulb zero"; + break; + + case 246: + name = "Maximum equivalent potential temperature level"; + break; + + case 247: + name = "Equilibrium level"; + break; + + case 248: + name = "Shallow convective cloud bottom level"; + break; + + case 249: + name = "Shallow convective cloud top level"; + break; + + case 251: + name = "Deep convective cloud bottom level"; + break; + + case 252: + name = "Deep convective cloud top level"; + break; + + default: + name = "undefined level"; + System.Console.Out.WriteLine("GribPDSLevel: Table 3 level " + index + " is not implemented yet"); + break; + } + } // end GribPDSLevel + + /// type of vertical coordinate: Description or short Name + /// derived from ON388 - TABLE 3. + /// + /// + /// + /// level description as String + /// + static public System.String getLevelDescription(int id) + { + switch (id) + { + case 0: return "Reserved"; + + case 1: return "Ground or water surface"; + + case 2: return "Cloud base level"; + + case 3: return "Level of cloud tops"; + + case 4: return "Level of 0o C isotherm"; + + case 5: return "Level of adiabatic condensation lifted from the surface"; + + case 6: return "Maximum wind level"; + + case 7: return "Tropopause"; + + case 8: return "Nominal top of the atmosphere"; + + case 9: return "Sea bottom"; + + case 20: return "Isothermal level"; + + case 100: return "Isobaric surface"; + + case 101: return "Layer between 2 isobaric levels"; + + case 102: return "Mean sea level"; + + case 103: return "Altitude above mean sea level"; + + case 104: return "Layer between 2 altitudes above msl"; + + case 105: return "Specified height level above ground"; + + case 106: return "Layer between 2 specified height level above ground"; + + case 107: return "Sigma level"; + + case 108: return "Layer between 2 sigma levels"; + + case 109: return "Hybrid level"; + + case 110: return "Layer between 2 hybrid levels"; + + case 111: return "Depth below land surface"; + + case 112: return "Layer between 2 depths below land surface"; + + case 113: return "Isentropic theta level"; + + case 114: return "Layer between 2 isentropic levels"; + + case 115: return "Level at specified pressure difference from ground to level"; + + case 116: return "Layer between 2 level at pressure difference from ground to level"; + + case 117: return "Potential vorticity surface"; + + case 119: return "Eta level"; + + case 120: return "Layer between 2 Eta levels"; + + case 121: return "Layer between 2 isobaric levels"; + + case 125: return "Specified height level above ground"; + + case 126: return "Isobaric level"; + + case 128: return "Layer between 2 sigma levels (hi precision)"; + + case 141: return "Layer between 2 isobaric surfaces"; + + case 160: return "Depth below sea level"; + + case 200: return "Entire atmosphere"; + + case 201: return "Entire ocean"; + + case 204: return "Highest tropospheric freezing level"; + + case 206: return "Grid scale cloud bottom level"; + + case 207: return "Grid scale cloud top level"; + + case 209: return "Boundary layer cloud bottom level"; + + case 210: return "Boundary layer cloud top level"; + + case 211: return "Boundary layer cloud layer"; + + case 212: return "Low cloud bottom level"; + + case 213: return "Low cloud top level"; + + case 214: return "Low Cloud Layer"; + + case 222: return "Middle cloud bottom level"; + + case 223: return "Middle cloud top level"; + + case 224: return "Middle Cloud Layer"; + + case 232: return "High cloud bottom level"; + + case 233: return "High cloud top level"; + + case 234: return "High Cloud Layer"; + + case 242: return "Convective cloud bottom level"; + + case 243: return "Convective cloud top level"; + + case 244: return "Convective cloud layer"; + + case 245: return "Lowest level of the wet bulb zero"; + + case 246: return "Maximum equivalent potential temperature level"; + + case 247: return "Equilibrium level"; + + case 248: return "Shallow convective cloud bottom level"; + + case 249: return "Shallow convective cloud top level"; + + case 251: return "Deep convective cloud bottom level"; + + case 252: return "Deep convective cloud top level"; + + case 255: return "Missing"; + + + default: return "Unknown=" + id; + } + } + + /// short name of level. + /// + /// + /// name of level + /// + static public System.String getNameShort(int id) + { + switch (id) + { + case 1: return "surface"; + + case 2: return "cloud_base"; + + case 3: return "cloud_tops"; + + case 4: return "zeroDegC_isotherm"; + + case 5: return "adiabatic_condensation_lifted"; + + case 6: return "maximum_wind"; + + case 7: return "tropopause"; + + case 8: return "atmosphere_top"; + + case 9: return "sea_bottom"; + + case 20: return "isotherm"; + + case 100: return "isobaric"; + + case 101: return "layer_between_two_isobaric"; + + case 102: return "msl"; + + case 103: return "altitude_above_msl"; + + case 104: return "layer_between_two_altitudes_above_msl"; + + case 105: return "height_above_ground"; + + case 106: return "layer_between_two_heights_above_ground"; + + case 107: return "sigma"; + + case 108: return "layer_between_two_sigmas"; + + case 109: return "hybrid"; + + case 110: return "layer_between_two_hybrids"; + + case 111: return "depth_below_surface"; + + case 112: return "layer_between_two_depths_below_surface"; + + case 113: return "isentrope"; + + case 114: return "layer_between_two_isentrope"; + + case 115: return "pressure_difference"; + + case 116: return "layer_between_two_pressure_difference_from_ground"; + + case 117: return "potential_vorticity_surface"; + + case 119: return "eta"; + + case 120: return "layer_between_two_eta"; + + case 121: return "layer_between_two_isobaric_surfaces"; + + case 125: return "height_above_ground"; + + case 126: return "isobaric"; + + case 128: return "layer_between_two_sigmas_hi"; + + case 141: return "layer_between_two_isobaric_surfaces"; + + case 160: return "depth_below_sea"; + + case 200: return "entire_atmosphere"; + + case 201: return "entire_ocean"; + + case 204: return "highest_tropospheric_freezing"; + + case 206: return "grid_scale_cloud bottom"; + + case 207: return "grid_scale_cloud_top"; + + case 209: return "boundary_layer_cloud_bottom"; + + case 210: return "boundary_layer_cloud_top"; + + case 211: return "boundary_layer_cloud_layer"; + + case 212: return "low_cloud_bottom"; + + case 213: return "low_cloud_top"; + + case 214: return "low_cloud_layer"; + + case 222: return "middle_cloud_bottom"; + + case 223: return "middle_cloud_top"; + + case 224: return "middle_cloud_layer"; + + case 232: return "high_cloud_bottom"; + + case 233: return "high_cloud_top"; + + case 234: return "high_cloud_layer"; + + case 242: return "convective_cloud_bottom"; + + case 243: return "convective_cloud_top"; + + case 244: return "convective_cloud_layer"; + + case 245: return "lowest_level_of_wet_bulb_zero"; + + case 246: return "maximum_equivalent_potential_temperature"; + + case 247: return "equilibrium"; + + case 248: return "shallow_convective_cloud_bottom"; + + case 249: return "shallow_convective_cloud_top"; + + case 251: return "deep_convective_cloud_bottom"; + + case 252: return "deep_convective_cloud_top"; + + case 255: return ""; + + + default: return "Unknown" + id; + } + } // end getNameShort + + /// type of vertical coordinate: units + /// derived from ON388 - TABLE 3. + /// + /// units number + /// + /// unit as String + /// + static public System.String getUnits(int id) + { + switch (id) + { + case 20: + case 113: + case 114: + return "K"; + + case 100: + case 101: + case 115: + case 116: + case 121: + case 141: + return "hPa"; + + case 103: + case 104: + case 105: + case 106: + case 160: + return "m"; + + case 107: + case 108: + case 128: + return "sigma"; + + case 111: + case 112: + case 125: + return "cm"; + + case 117: + return "10-6Km2/kgs"; + + case 126: + return "Pa"; + } + + return ""; + } // end getUnits +} \ No newline at end of file diff --git a/tmp/Grib1/GribPdsParamTable.cs b/tmp/Grib1/GribPdsParamTable.cs new file mode 100644 index 0000000..3b4a7e1 --- /dev/null +++ b/tmp/Grib1/GribPdsParamTable.cs @@ -0,0 +1,37 @@ +using NGrib.Grib1.PdsParameterTables; + +namespace NGrib.Grib1; + +public abstract class GribPdsParamTable +{ + private const string Undefined = "undefined"; + + private static readonly IReadOnlyDictionary<(int, int, int), GribPdsParamTable> _table = + new Dictionary<(int, int, int), GribPdsParamTable>() + { + {(98,0,1),new ParameterTable001()}, + {(98,0,2),new ParameterTable002()}, + {(98,0,3),new ParameterTable003()}, + {(98,0,128), new ParameterTable128()}, + {(98,0,210), new ParameterTable210()} + }; + + private static readonly DefaultParameterTable _default = new(0); + + protected abstract int TableNumber { get; } + + public static GribPdsParamTable GetParameterTable(int centerId, int subcenterId, int tableVersion) + { + if (_table.TryGetValue((centerId, subcenterId, tableVersion), out var parameterTable)) + return parameterTable; + return _default; + } + + public abstract Parameter GetParameter(int parameterNumber); + + protected Parameter GetDefaultParameter(int parameterNumber) + { + return new Parameter(TableNumber * 1000 + parameterNumber, parameterNumber.ToString(), + Undefined, Undefined); + } +} \ No newline at end of file diff --git a/tmp/Grib1/Parameter.cs b/tmp/Grib1/Parameter.cs new file mode 100644 index 0000000..b9f60c0 --- /dev/null +++ b/tmp/Grib1/Parameter.cs @@ -0,0 +1,136 @@ +/* + * This file is part of NGrib. + * + * Copyright � 2020 Nicolas Mangu� + * + * Copyright 2006-2010 Seaware AB, PO Box 1244, SE-131 28 + * Nacka Strand, Sweden, info@seaware.se. + * + * Copyright 1997-2006 Unidata Program Center/University + * Corporation for Atmospheric Research, P.O. Box 3000, Boulder, CO 80307, + * support@unidata.ucar.edu. + * + * NGrib is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * NGrib is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with NGrib. If not, see . + */ + +/// Parameter.java +/// Robert Kambic 10/10/03 +/// + +namespace NGrib.Grib1; + +/// Class which represents a parameter from a PDS parameter table. +/// A parameter consists of a discipline( ie Meteorological_products), +/// a Category( ie Temperature ) and a number that refers to a name( ie Temperature), +/// Description( ie Temperature at 2 meters), and Units( ie K ). +/// see Parameters.txt +/// +public sealed class Parameter +{ + //UPGRADE_NOTE: Respective javadoc comments were merged. It should be changed in order to comply with .NET documentation conventions. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1199'" + /// number of parameter. + /// number + /// + /// sets number of parameter. + /// of parameter + /// + public int Number + { + get { return number; } + + set { number = value; } + } + + //UPGRADE_NOTE: Respective javadoc comments were merged. It should be changed in order to comply with .NET documentation conventions. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1199'" + /// name of parameter. + /// name + /// + /// sets name of parameter. + /// of parameter + /// + public System.String Name + { + get { return name; } + + set { name = value; } + } + + //UPGRADE_NOTE: Respective javadoc comments were merged. It should be changed in order to comply with .NET documentation conventions. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1199'" + /// description of parameter. + /// + /// + /// description + /// + /// sets description of parameter. + /// of parameter + /// + public System.String Description + { + get { return description; } + + set { description = value; } + } + + //UPGRADE_NOTE: Respective javadoc comments were merged. It should be changed in order to comply with .NET documentation conventions. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1199'" + /// unit of parameter. + /// unit + /// + /// sets unit of parameter. + /// of parameter + /// + public System.String Unit + { + get { return unit; } + + set { unit = value; } + } + + /// parameter number. + private int number; + + /// name of parameter. + private System.String name; + + /// description of parameter. + private System.String description; + + /// unit of Parameter. + private System.String unit; + + /// constructor. + internal Parameter() + { + number = -1; + name = "undefined"; + description = "undefined"; + unit = "undefined"; + } + + /// constructor. + /// + /// + /// + /// + /// + /// + /// of parameter + /// + internal Parameter(int number, System.String name, System.String description, System.String unit) + { + this.number = number; + this.name = name; + this.description = description; + this.unit = unit; + } +} \ No newline at end of file diff --git a/tmp/Grib1/PdsParameterTables/DefaultParameterTable.cs b/tmp/Grib1/PdsParameterTables/DefaultParameterTable.cs new file mode 100644 index 0000000..b3e64d3 --- /dev/null +++ b/tmp/Grib1/PdsParameterTables/DefaultParameterTable.cs @@ -0,0 +1,15 @@ +namespace NGrib.Grib1.PdsParameterTables; + +public class DefaultParameterTable:GribPdsParamTable +{ + public DefaultParameterTable(int tableNumber) + { + TableNumber = tableNumber; + } + + protected override int TableNumber { get; } + public override Parameter GetParameter(int parameterNumber) + { + return GetDefaultParameter(parameterNumber); + } +} \ No newline at end of file diff --git a/tmp/Grib1/PdsParameterTables/ParameterTable001.cs b/tmp/Grib1/PdsParameterTables/ParameterTable001.cs new file mode 100644 index 0000000..18f51e1 --- /dev/null +++ b/tmp/Grib1/PdsParameterTables/ParameterTable001.cs @@ -0,0 +1,14 @@ +namespace NGrib.Grib1.PdsParameterTables; + +public class ParameterTable001:GribPdsParamTable +{ + protected override int TableNumber => 1; + public override Parameter GetParameter(int parameterNumber) + { + return parameterNumber switch + { + 10 => Parameters.TCO3, + _ => GetDefaultParameter(parameterNumber) + }; + } +} \ No newline at end of file diff --git a/tmp/Grib1/PdsParameterTables/ParameterTable002.cs b/tmp/Grib1/PdsParameterTables/ParameterTable002.cs new file mode 100644 index 0000000..44ee8af --- /dev/null +++ b/tmp/Grib1/PdsParameterTables/ParameterTable002.cs @@ -0,0 +1,15 @@ +namespace NGrib.Grib1.PdsParameterTables; + +public class ParameterTable002:GribPdsParamTable +{ + protected override int TableNumber => 2; + + public override Parameter GetParameter(int parameterNumber) + { + return parameterNumber switch + { + 10 => Parameters.TCO3, + _ => GetDefaultParameter(parameterNumber) + }; + } +} \ No newline at end of file diff --git a/tmp/Grib1/PdsParameterTables/ParameterTable003.cs b/tmp/Grib1/PdsParameterTables/ParameterTable003.cs new file mode 100644 index 0000000..cde780b --- /dev/null +++ b/tmp/Grib1/PdsParameterTables/ParameterTable003.cs @@ -0,0 +1,15 @@ +namespace NGrib.Grib1.PdsParameterTables; + +public class ParameterTable003:GribPdsParamTable +{ + protected override int TableNumber => 3; + + public override Parameter GetParameter(int parameterNumber) + { + return parameterNumber switch + { + 10 => Parameters.TCO3, + _ => GetDefaultParameter(parameterNumber) + }; + } +} \ No newline at end of file diff --git a/tmp/Grib1/PdsParameterTables/ParameterTable128.cs b/tmp/Grib1/PdsParameterTables/ParameterTable128.cs new file mode 100644 index 0000000..07e7540 --- /dev/null +++ b/tmp/Grib1/PdsParameterTables/ParameterTable128.cs @@ -0,0 +1,16 @@ +namespace NGrib.Grib1.PdsParameterTables; + +public class ParameterTable128:GribPdsParamTable +{ + protected override int TableNumber => 128; + + public override Parameter GetParameter(int parameterNumber) + { + return parameterNumber switch + { + 206 => Parameters.GTCO3, + _ => GetDefaultParameter(parameterNumber) + }; + } + +} \ No newline at end of file diff --git a/tmp/Grib1/PdsParameterTables/ParameterTable210.cs b/tmp/Grib1/PdsParameterTables/ParameterTable210.cs new file mode 100644 index 0000000..9ab22fb --- /dev/null +++ b/tmp/Grib1/PdsParameterTables/ParameterTable210.cs @@ -0,0 +1,26 @@ +namespace NGrib.Grib1.PdsParameterTables; + +public class ParameterTable210 : GribPdsParamTable +{ + protected override int TableNumber => 210; + + public override Parameter GetParameter(int parameterNumber) + { + return parameterNumber switch + { + 6=> Parameters.AERMR06, + + 206 => Parameters.GTCO3, + + //73 => Parameters.PM2P5, + + 121 => Parameters.NO2, + + 123 => Parameters.CO, + + 126 => Parameters.TCSO2, + + _ => GetDefaultParameter(parameterNumber) + }; + } +} \ No newline at end of file diff --git a/tmp/Grib1/PdsParameterTables/Parameters.cs b/tmp/Grib1/PdsParameterTables/Parameters.cs new file mode 100644 index 0000000..198a19b --- /dev/null +++ b/tmp/Grib1/PdsParameterTables/Parameters.cs @@ -0,0 +1,47 @@ +namespace NGrib.Grib1.PdsParameterTables; + +public static class Parameters +{ + /// + /// Ozone + /// + public static Parameter GTCO3 { get; }=new Parameter(206, "GTCO3 Total column ozone", + @"(TCO3) This parameter is the total amount of ozone in a column of air extending from the surface of the Earth to the top of the atmosphere. This parameter can also be referred to as total ozone, or vertically integrated ozone. The values are dominated by ozone within the stratosphere. +In the ECMWF Integrated Forecasting System (IFS), there is a simplified representation of ozone chemistry (including representation of the chemistry which has caused the ozone hole). Ozone is also transported around in the atmosphere through the motion of air. See further documentation . +Naturally occurring ozone in the stratosphere helps protect organisms at the surface of the Earth from the harmful effects of ultraviolet (UV) radiation from the Sun. Ozone near the surface, often produced because of pollution, is harmful to organisms. +In the IFS, the units for total ozone are kilograms per square metre, but before 12/06/2001 dobson units were used. Dobson units (DU) are still used extensively for total column ozone. 1 DU = 2.1415E-5 kg m-2", + "kg m^(-2)"); + + public static Parameter TCO3 { get; }=new Parameter(10, "TCO3 Total column ozone", + @"(TCO3) This parameter is the total amount of ozone in a column of air extending from the surface of the Earth to the top of the atmosphere. This parameter can also be referred to as total ozone, or vertically integrated ozone. The values are dominated by ozone within the stratosphere. +In the ECMWF Integrated Forecasting System (IFS), there is a simplified representation of ozone chemistry (including representation of the chemistry which has caused the ozone hole). Ozone is also transported around in the atmosphere through the motion of air. See further documentation . +Naturally occurring ozone in the stratosphere helps protect organisms at the surface of the Earth from the harmful effects of ultraviolet (UV) radiation from the Sun. Ozone near the surface, often produced because of pollution, is harmful to organisms. +In the IFS, the units for total ozone are kilograms per square metre, but before 12/06/2001 dobson units were used. Dobson units (DU) are still used extensively for total column ozone. 1 DU = 2.1415E-5 kg m-2", + "kg m^(-2)"); + + /// + /// Particulate matter d <= 2.5 um + /// + public static Parameter PM2P5 { get; }= new Parameter(210073, "PM2P5 Particulate matter d <= 2.5 um", "pm2p5", "kg m-3"); + + /// + /// Nitrogen dioxide + /// + public static Parameter NO2 { get; } = new(210121, "NO2 Nitrogen dioxide mass mixing ratio", "NO2", "kg kg-1"); + + /// + /// Carbon monoxide + /// + public static Parameter CO { get; } = new(210123, "CO Carbon monoxide mass mixing ratio", "CO", "kg kg-1"); + + /// + /// Total column Sulphur dioxide + /// + public static Parameter TCSO2 { get; } = new(210126, "TCSO2 Total column Sulphur dioxide", "TCSO2", "kg m-2"); + + /// + /// Dust Aerosol (0.9 - 20 um) Mixing Ratio + /// + public static Parameter AERMR06 { get; } = new(210006, "AERMR06 Dust Aerosol (0.9 - 20 um) Mixing Ratio", "AERMR06", "kg kg-1"); + +} \ No newline at end of file diff --git a/tmp/Grib1/PdsParameterTables/TimeRangeUnitGrib1.cs b/tmp/Grib1/PdsParameterTables/TimeRangeUnitGrib1.cs new file mode 100644 index 0000000..7240dd0 --- /dev/null +++ b/tmp/Grib1/PdsParameterTables/TimeRangeUnitGrib1.cs @@ -0,0 +1,23 @@ +using System.ComponentModel; + +namespace NGrib.Grib1.PdsParameterTables; + +public enum TimeRangeUnitGrib1 +{ + [Description("Missing")] Missing = 255, + [Description("Minute")] Minute = 0, + [Description("Hour")] Hour = 1, + [Description("Day")] Day = 2, + [Description("Month")] Month = 3, + [Description("Year")] Year = 4, + [Description("Decade")] Decade = 5, + [Description("Normal")] Normal = 6, + [Description("Century")] Century = 7, + [Description("3 Hours")] Hours3 = 10, + [Description("6 Hours")] Hours6 = 11, + [Description("12 Hours")] Hours12 = 12, + [Description("15 Minutes")] Minutes15 = 13, + [Description("30 Minutes")] Minutes30 = 14, + [Description("Reserved")] Reserved = 253, + [Description("Second")] Second = 254 +} \ No newline at end of file diff --git a/tmp/Grib1/SupportClass.cs b/tmp/Grib1/SupportClass.cs new file mode 100644 index 0000000..4f62d83 --- /dev/null +++ b/tmp/Grib1/SupportClass.cs @@ -0,0 +1,892 @@ +/* + * This file is part of NGrib. + * + * Copyright 2020 Nicolas Mangu + * + * Copyright 2006-2010 Seaware AB, PO Box 1244, SE-131 28 + * Nacka Strand, Sweden, info@seaware.se. + * + * Copyright 1997-2006 Unidata Program Center/University + * Corporation for Atmospheric Research, P.O. Box 3000, Boulder, CO 80307, + * support@unidata.ucar.edu. + * + * NGrib is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * NGrib is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with NGrib. If not, see . + */ + +namespace NGrib.Grib1; + +/// +/// Contains conversion support elements such as classes, interfaces and static methods. +/// +internal class SupportClass +{ + /// + /// Try to skip bytes in the input stream and return the actual number of bytes skipped. + /// + /// Input stream that will be used to skip the bytes + /// Number of bytes to be skipped + /// Actual number of bytes skipped + public static int Skip(System.IO.Stream stream, int skipBytes) + { + long oldPosition = stream.Position; + long result = stream.Seek(skipBytes, System.IO.SeekOrigin.Current) - oldPosition; + return (int) result; + } + + /// + /// Skips a given number of characters into a given Stream. + /// + /// The stream in which the skips are done. + /// The number of caracters to skip. + /// The number of characters skipped. + public static long Skip(System.IO.StreamReader stream, long number) + { + long skippedBytes = 0; + for (long index = 0; index < number; index++) + { + stream.Read(); + skippedBytes++; + } + + return skippedBytes; + } + + /// + /// Skips a given number of characters into a given StringReader. + /// + /// The StringReader in which the skips are done. + /// The number of caracters to skip. + /// The number of characters skipped. + public static long Skip(System.IO.StringReader strReader, long number) + { + long skippedBytes = 0; + for (long index = 0; index < number; index++) + { + strReader.Read(); + skippedBytes++; + } + + return skippedBytes; + } + + + /*******************************/ + /// Reads a number of characters from the current source Stream and writes the data to the target array at the specified index. + /// The source Stream to read from. + /// Contains the array of characteres read from the source Stream. + /// The starting index of the target array. + /// The maximum number of characters to read from the source Stream. + /// The number of characters read. The number will be less than or equal to count depending on the data available in the source Stream. Returns -1 if the end of the stream is reached. + public static Int32 ReadInput(System.IO.Stream sourceStream, sbyte[] target, int start, int count) + { + // Returns 0 bytes if not enough space in target + if (target.Length == 0) + return 0; + + byte[] receiver = new byte[target.Length]; + int bytesRead = sourceStream.Read(receiver, start, count); + + // Returns -1 if EOF + if (bytesRead == 0) + return -1; + + for (int i = start; i < start + bytesRead; i++) + target[i] = (sbyte) receiver[i]; + + return bytesRead; + } + + /// Reads a number of characters from the current source TextReader and writes the data to the target array at the specified index. + /// The source TextReader to read from + /// Contains the array of characteres read from the source TextReader. + /// The starting index of the target array. + /// The maximum number of characters to read from the source TextReader. + /// The number of characters read. The number will be less than or equal to count depending on the data available in the source TextReader. Returns -1 if the end of the stream is reached. + public static Int32 ReadInput(System.IO.TextReader sourceTextReader, sbyte[] target, int start, int count) + { + // Returns 0 bytes if not enough space in target + if (target.Length == 0) return 0; + + char[] charArray = new char[target.Length]; + int bytesRead = sourceTextReader.Read(charArray, start, count); + + // Returns -1 if EOF + if (bytesRead == 0) return -1; + + for (int index = start; index < start + bytesRead; index++) + target[index] = (sbyte) charArray[index]; + + return bytesRead; + } + + /// Converts an array of sbytes to an array of bytes + /// + /// The array of sbytes to be converted + /// The new array of bytes + public static byte[] ToByteArray(sbyte[] sbyteArray) + { + byte[] byteArray = null; + + if (sbyteArray != null) + { + byteArray = new byte[sbyteArray.Length]; + for (int index = 0; index < sbyteArray.Length; index++) + byteArray[index] = (byte) sbyteArray[index]; + } + + return byteArray; + } + + /// + /// Converts a string to an array of bytes + /// + /// The string to be converted + /// The new array of bytes + public static byte[] ToByteArray(String sourceString) + { + return System.Text.Encoding.UTF8.GetBytes(sourceString); + } + + /// + /// Converts a array of object-type instances to a byte-type array. + /// + /// Array to convert. + /// An array of byte type elements. + public static byte[] ToByteArray(Object[] tempObjectArray) + { + byte[] byteArray = null; + if (tempObjectArray != null) + { + byteArray = new byte[tempObjectArray.Length]; + for (int index = 0; index < tempObjectArray.Length; index++) + byteArray[index] = (byte) tempObjectArray[index]; + } + + return byteArray; + } + + /*******************************/ + + /*******************************/ + /// + /// Provides support for DateFormat + /// + public class DateTimeFormatManager + { + static public DateTimeFormatHashTable manager = new DateTimeFormatHashTable(); + + /// + /// Hashtable class to provide functionality for dateformat properties + /// + public class DateTimeFormatHashTable : System.Collections.Hashtable + { + /// + /// Sets the format for datetime. + /// + /// DateTimeFormat instance to set the pattern + /// A string with the pattern format + public void SetDateFormatPattern(System.Globalization.DateTimeFormatInfo format, String newPattern) + { + if (this[format] != null) + ((DateTimeFormatProperties) this[format]).DateFormatPattern = newPattern; + else + { + DateTimeFormatProperties tempProps = new DateTimeFormatProperties(); + tempProps.DateFormatPattern = newPattern; + Add(format, tempProps); + } + } + + /// + /// Gets the current format pattern of the DateTimeFormat instance + /// + /// The DateTimeFormat instance which the value will be obtained + /// The string representing the current datetimeformat pattern + public String GetDateFormatPattern(System.Globalization.DateTimeFormatInfo format) + { + if (this[format] == null) + return "d-MMM-yy"; + else + return ((DateTimeFormatProperties) this[format]).DateFormatPattern; + } + + /// + /// Sets the datetimeformat pattern to the giving format + /// + /// The datetimeformat instance to set + /// The new datetimeformat pattern + public void SetTimeFormatPattern(System.Globalization.DateTimeFormatInfo format, String newPattern) + { + if (this[format] != null) + ((DateTimeFormatProperties) this[format]).TimeFormatPattern = newPattern; + else + { + DateTimeFormatProperties tempProps = new DateTimeFormatProperties(); + tempProps.TimeFormatPattern = newPattern; + Add(format, tempProps); + } + } + + /// + /// Gets the current format pattern of the DateTimeFormat instance + /// + /// The DateTimeFormat instance which the value will be obtained + /// The string representing the current datetimeformat pattern + public String GetTimeFormatPattern(System.Globalization.DateTimeFormatInfo format) + { + if (this[format] == null) + return "h:mm:ss tt"; + else + return ((DateTimeFormatProperties) this[format]).TimeFormatPattern; + } + + /// + /// Internal class to provides the DateFormat and TimeFormat pattern properties on .NET + /// + class DateTimeFormatProperties + { + public String DateFormatPattern = "d-MMM-yy"; + public String TimeFormatPattern = "h:mm:ss tt"; + } + } + } + + /*******************************/ + /// + /// Gets the DateTimeFormat instance and date instance to obtain the date with the format passed + /// + /// The DateTimeFormat to obtain the time and date pattern + /// The date instance used to get the date + /// A string representing the date with the time and date patterns + public static String FormatDateTime(System.Globalization.DateTimeFormatInfo format, DateTime date) + { + String timePattern = DateTimeFormatManager.manager.GetTimeFormatPattern(format); + String datePattern = DateTimeFormatManager.manager.GetDateFormatPattern(format); + return date.ToString(datePattern + " " + timePattern, format); + } + + /*******************************/ + /// + /// Represents a collection ob objects that contains no duplicate elements. + /// + public interface SetSupport : System.Collections.ICollection, System.Collections.IList + { + /// + /// Adds a new element to the Collection if it is not already present. + /// + /// The object to add to the collection. + /// Returns true if the object was added to the collection, otherwise false. + new bool Add(Object obj); + + /// + /// Adds all the elements of the specified collection to the Set. + /// + /// Collection of objects to add. + /// true + bool AddAll(System.Collections.ICollection c); + } + + + /*******************************/ + /// + /// SupportClass for the HashSet class. + /// + [Serializable] + public class HashSetSupport : System.Collections.ArrayList, SetSupport + { + public HashSetSupport() : base() + { + } + + public HashSetSupport(System.Collections.ICollection c) + { + AddAll(c); + } + + public HashSetSupport(int capacity) : base(capacity) + { + } + + /// + /// Adds a new element to the ArrayList if it is not already present. + /// + /// Element to insert to the ArrayList. + /// Returns true if the new element was inserted, false otherwise. + new public virtual bool Add(Object obj) + { + bool inserted; + + if ((inserted = Contains(obj)) == false) + { + base.Add(obj); + } + + return !inserted; + } + + /// + /// Adds all the elements of the specified collection that are not present to the list. + /// + /// Collection where the new elements will be added + /// Returns true if at least one element was added, false otherwise. + public bool AddAll(System.Collections.ICollection c) + { + System.Collections.IEnumerator e = new System.Collections.ArrayList(c).GetEnumerator(); + bool added = false; + + while (e.MoveNext() == true) + { + if (Add(e.Current) == true) + added = true; + } + + return added; + } + + /// + /// Returns a copy of the HashSet instance. + /// + /// Returns a shallow copy of the current HashSet. + public override Object Clone() + { + return MemberwiseClone(); + } + } + + + /*******************************/ + /// + /// This class provides functionality not found in .NET collection-related interfaces. + /// + public class ICollectionSupport + { + /// + /// Adds a new element to the specified collection. + /// + /// Collection where the new element will be added. + /// Object to add. + /// true + public static bool Add(System.Collections.ICollection c, Object obj) + { + bool added = false; + //Reflection. Invoke either the "add" or "Add" method. + System.Reflection.MethodInfo method; + + //Get the "add" method for proprietary classes + method = c.GetType().GetMethod("Add"); + if (method == null) + method = c.GetType().GetMethod("add"); + int index = (int) method.Invoke(c, new Object[] {obj}); + if (index >= 0) + added = true; + + return added; + } + + /// + /// Adds all of the elements of the "c" collection to the "target" collection. + /// + /// Collection where the new elements will be added. + /// Collection whose elements will be added. + /// Returns true if at least one element was added, false otherwise. + public static bool AddAll(System.Collections.ICollection target, System.Collections.ICollection c) + { + System.Collections.IEnumerator e = new System.Collections.ArrayList(c).GetEnumerator(); + bool added = false; + + //Reflection. Invoke "addAll" method for proprietary classes + System.Reflection.MethodInfo method; + + method = target.GetType().GetMethod("addAll"); + + if (method != null) + added = (bool) method.Invoke(target, new Object[] {c}); + else + { + method = target.GetType().GetMethod("Add"); + while (e.MoveNext() == true) + { + bool tempBAdded = (int) method.Invoke(target, new Object[] {e.Current}) >= 0; + added = added ? added : tempBAdded; + } + } + + return added; + } + + /// + /// Removes all the elements from the collection. + /// + /// The collection to remove elements. + public static void Clear(System.Collections.ICollection c) + { + //Reflection. Invoke "Clear" method or "clear" method for proprietary classes + System.Reflection.MethodInfo method; + + method = c.GetType().GetMethod("Clear"); + + if (method == null) + method = c.GetType().GetMethod("clear"); + + method.Invoke(c, new Object[] { }); + } + + /// + /// Determines whether the collection contains the specified element. + /// + /// The collection to check. + /// The object to locate in the collection. + /// true if the element is in the collection. + public static bool Contains(System.Collections.ICollection c, Object obj) + { + bool contains = false; + + //Reflection. Invoke "contains" method for proprietary classes + System.Reflection.MethodInfo method; + + method = c.GetType().GetMethod("Contains"); + + if (method == null) + method = c.GetType().GetMethod("contains"); + + contains = (bool) method.Invoke(c, new Object[] {obj}); + + + return contains; + } + + /// + /// Determines whether the collection contains all the elements in the specified collection. + /// + /// The collection to check. + /// Collection whose elements would be checked for containment. + /// true id the target collection contains all the elements of the specified collection. + public static bool ContainsAll(System.Collections.ICollection target, System.Collections.ICollection c) + { + System.Collections.IEnumerator e = c.GetEnumerator(); + + bool contains = false; + + //Reflection. Invoke "containsAll" method for proprietary classes or "Contains" method for each element in the collection + System.Reflection.MethodInfo method; + + method = target.GetType().GetMethod("containsAll"); + + if (method != null) + contains = (bool) method.Invoke(target, new Object[] {c}); + else + { + method = target.GetType().GetMethod("Contains"); + while (e.MoveNext() == true) + { + if ((contains = (bool) method.Invoke(target, new Object[] {e.Current})) == false) + break; + } + } + + return contains; + } + + /// + /// Removes the specified element from the collection. + /// + /// The collection where the element will be removed. + /// The element to remove from the collection. + public static bool Remove(System.Collections.ICollection c, Object obj) + { + bool changed = false; + + //Reflection. Invoke "remove" method for proprietary classes or "Remove" method + System.Reflection.MethodInfo method; + + method = c.GetType().GetMethod("remove"); + + if (method != null) + method.Invoke(c, new Object[] {obj}); + else + { + method = c.GetType().GetMethod("Contains"); + changed = (bool) method.Invoke(c, new Object[] {obj}); + method = c.GetType().GetMethod("Remove"); + method.Invoke(c, new Object[] {obj}); + } + + return changed; + } + + /// + /// Removes all the elements from the specified collection that are contained in the target collection. + /// + /// Collection where the elements will be removed. + /// Elements to remove from the target collection. + /// true + public static bool RemoveAll(System.Collections.ICollection target, System.Collections.ICollection c) + { + System.Collections.ArrayList al = ToArrayList(c); + System.Collections.IEnumerator e = al.GetEnumerator(); + + //Reflection. Invoke "removeAll" method for proprietary classes or "Remove" for each element in the collection + System.Reflection.MethodInfo method; + + method = target.GetType().GetMethod("removeAll"); + + if (method != null) + method.Invoke(target, new Object[] {al}); + else + { + method = target.GetType().GetMethod("Remove"); + System.Reflection.MethodInfo methodContains = target.GetType().GetMethod("Contains"); + + while (e.MoveNext() == true) + { + while ((bool) methodContains.Invoke(target, new Object[] {e.Current}) == true) + method.Invoke(target, new Object[] {e.Current}); + } + } + + return true; + } + + /// + /// Retains the elements in the target collection that are contained in the specified collection + /// + /// Collection where the elements will be removed. + /// Elements to be retained in the target collection. + /// true + public static bool RetainAll(System.Collections.ICollection target, System.Collections.ICollection c) + { + System.Collections.IEnumerator e = new System.Collections.ArrayList(target).GetEnumerator(); + System.Collections.ArrayList al = new System.Collections.ArrayList(c); + + //Reflection. Invoke "retainAll" method for proprietary classes or "Remove" for each element in the collection + System.Reflection.MethodInfo method; + + method = c.GetType().GetMethod("retainAll"); + + if (method != null) + method.Invoke(target, new Object[] {c}); + else + { + method = c.GetType().GetMethod("Remove"); + + while (e.MoveNext() == true) + { + if (al.Contains(e.Current) == false) + method.Invoke(target, new Object[] {e.Current}); + } + } + + return true; + } + + /// + /// Returns an array containing all the elements of the collection. + /// + /// The array containing all the elements of the collection. + public static Object[] ToArray(System.Collections.ICollection c) + { + int index = 0; + Object[] objects = new Object[c.Count]; + System.Collections.IEnumerator e = c.GetEnumerator(); + + while (e.MoveNext()) + objects[index++] = e.Current; + + return objects; + } + + /// + /// Obtains an array containing all the elements of the collection. + /// + /// The array into which the elements of the collection will be stored. + /// The array containing all the elements of the collection. + public static Object[] ToArray(System.Collections.ICollection c, Object[] objects) + { + int index = 0; + + Type type = objects.GetType().GetElementType(); + Object[] objs = (Object[]) Array.CreateInstance(type, c.Count); + + System.Collections.IEnumerator e = c.GetEnumerator(); + + while (e.MoveNext()) + objs[index++] = e.Current; + + //If objects is smaller than c then do not return the new array in the parameter + if (objects.Length >= c.Count) + objs.CopyTo(objects, 0); + + return objs; + } + + /// + /// Converts an ICollection instance to an ArrayList instance. + /// + /// The ICollection instance to be converted. + /// An ArrayList instance in which its elements are the elements of the ICollection instance. + public static System.Collections.ArrayList ToArrayList(System.Collections.ICollection c) + { + System.Collections.ArrayList tempArrayList = new System.Collections.ArrayList(); + System.Collections.IEnumerator tempEnumerator = c.GetEnumerator(); + while (tempEnumerator.MoveNext()) + tempArrayList.Add(tempEnumerator.Current); + return tempArrayList; + } + } + + + /*******************************/ + /// + /// This method returns the literal value received + /// + /// The literal to return + /// The received value + public static long Identity(long literal) + { + return literal; + } + + /// + /// This method returns the literal value received + /// + /// The literal to return + /// The received value + public static ulong Identity(ulong literal) + { + return literal; + } + + /// + /// This method returns the literal value received + /// + /// The literal to return + /// The received value + public static float Identity(float literal) + { + return literal; + } + + /// + /// This method returns the literal value received + /// + /// The literal to return + /// The received value + public static double Identity(double literal) + { + return literal; + } + + /*******************************/ + /// + /// Writes the exception stack trace to the received stream + /// + /// Exception to obtain information from + /// Output sream used to write to + public static void WriteStackTrace(Exception throwable, System.IO.TextWriter stream) + { + stream.Write(throwable.StackTrace); + stream.Flush(); + } + + /*******************************/ + /// + /// The class performs token processing in strings + /// + public class Tokenizer : System.Collections.IEnumerator + { + /// Position over the string + private long currentPos; + + /// Include demiliters in the results. + private bool includeDelims; + + /// Char representation of the String to tokenize. + private char[] chars; + + //The tokenizer uses the default delimiter set: the space character, the tab character, the newline character, and the carriage-return character and the form-feed character + private string delimiters = " \t\n\r\f"; + + /// + /// Initializes a new class instance with a specified string to process + /// + /// String to tokenize + public Tokenizer(String source) + { + chars = source.ToCharArray(); + } + + /// + /// Initializes a new class instance with a specified string to process + /// and the specified token delimiters to use + /// + /// String to tokenize + /// String containing the delimiters + public Tokenizer(String source, String delimiters) : this(source) + { + this.delimiters = delimiters; + } + + + /// + /// Initializes a new class instance with a specified string to process, the specified token + /// delimiters to use, and whether the delimiters must be included in the results. + /// + /// String to tokenize + /// String containing the delimiters + /// Determines if delimiters are included in the results. + public Tokenizer(String source, String delimiters, bool includeDelims) : this(source, delimiters) + { + this.includeDelims = includeDelims; + } + + + /// + /// Returns the next token from the token list + /// + /// The string value of the token + public String NextToken() + { + return NextToken(delimiters); + } + + /// + /// Returns the next token from the source string, using the provided + /// token delimiters + /// + /// String containing the delimiters to use + /// The string value of the token + public String NextToken(String delimiters) + { + //According to documentation, the usage of the received delimiters should be temporary (only for this call). + //However, it seems it is not true, so the following line is necessary. + this.delimiters = delimiters; + + //at the end + if (currentPos == chars.Length) + throw new ArgumentOutOfRangeException(); + //if over a delimiter and delimiters must be returned + else if ((Array.IndexOf(delimiters.ToCharArray(), chars[currentPos]) != -1) + && includeDelims) + return "" + chars[currentPos++]; + //need to get the token wo delimiters. + else + return nextToken(delimiters.ToCharArray()); + } + + //Returns the nextToken wo delimiters + private String nextToken(char[] delimiters) + { + string token = ""; + long pos = currentPos; + + //skip possible delimiters + while (Array.IndexOf(delimiters, chars[currentPos]) != -1) + //The last one is a delimiter (i.e there is no more tokens) + if (++currentPos == chars.Length) + { + currentPos = pos; + throw new ArgumentOutOfRangeException(); + } + + //getting the token + while (Array.IndexOf(delimiters, chars[currentPos]) == -1) + { + token += chars[currentPos]; + //the last one is not a delimiter + if (++currentPos == chars.Length) + break; + } + + return token; + } + + + /// + /// Determines if there are more tokens to return from the source string + /// + /// True or false, depending if there are more tokens + public bool HasMoreTokens() + { + //keeping the current pos + long pos = currentPos; + + try + { + NextToken(); + } + catch (ArgumentOutOfRangeException) + { + return false; + } + finally + { + currentPos = pos; + } + + return true; + } + + /// + /// Remaining tokens count + /// + public int Count + { + get + { + //keeping the current pos + long pos = currentPos; + int i = 0; + + try + { + while (true) + { + NextToken(); + i++; + } + } + catch (ArgumentOutOfRangeException) + { + currentPos = pos; + return i; + } + } + } + + /// + /// Performs the same action as NextToken. + /// + public Object Current + { + get { return (Object) NextToken(); } + } + + /// + // Performs the same action as HasMoreTokens. + /// + /// True or false, depending if there are more tokens + public bool MoveNext() + { + return HasMoreTokens(); + } + + /// + /// Does nothing. + /// + public void Reset() + { + ; + } + } +} \ No newline at end of file diff --git a/tmp/Grib1Reader.cs b/tmp/Grib1Reader.cs new file mode 100644 index 0000000..ec966d2 --- /dev/null +++ b/tmp/Grib1Reader.cs @@ -0,0 +1,76 @@ +using NGrib.Grib1; + +namespace NGrib; + +public class Grib1Reader : IDisposable +{ + private readonly bool leaveOpen; + private Grib1File _grib1File; + private Grib1Input input; + private Grib1Data data; + + + /// + /// Initializes a new instance of the Grib2Reader class + /// based on the specified file. + /// + /// The GRIB 2 file path. + public Grib1Reader(string filePath) : this(File.OpenRead(filePath)) + { } + + /// + /// Initializes a new instance of the Grib2Reader class + /// based on the specified stream. + /// + /// The GRIB 2 input stream. + /// trueto leave the stream open after the object is disposed; otherwise, false. + public Grib1Reader(Stream input, bool leaveOpen = false) + { + + if (input == null) throw new ArgumentNullException(nameof(input)); + if (!input.CanRead) throw new ArgumentException("The stream must support reading.", nameof(input)); + if (!input.CanSeek) throw new ArgumentException("The stream must support seeking.", nameof(input)); + this.leaveOpen = leaveOpen; + _grib1File = new Grib1File(); + this.input = new Grib1Input(input, _grib1File); + data = new Grib1Data(input, _grib1File); + } + + /// + /// Enumerates the records in the underlying stream. + /// + /// The records in the GRIB11 stream. + public IEnumerable ReadRecords() => input.ScanRecords(); + + + /// + /// Read the data set floating point values. + /// + /// The record to read. + /// Indicates whether the Bit-map section was used by the GRIB file producer. + /// The data set point values. + public double[] ReadRecordRawData(Grib1Record record, bool hasBitmapSection = false) => + data.getData(record.DataOffset, record.ProductDefinitionSection.DecimalScale, false); + + /// + /// Read the records grid value. + /// + /// The record to read. + /// Indicates whether the Bit-map section was used by the GRIB file producer. + /// The record grid points and the corresponding values. + public IEnumerable> ReadRecordValues(Grib1Record record, bool hasBitmapSection = false) + { + var rawData = ReadRecordRawData(record, hasBitmapSection); + + return record.GridDefinitionSection.EnumerateGridPoints() + .Zip(rawData, (c, v) => new KeyValuePair(c, v)); + } + + public void Dispose() + { + if (!leaveOpen) + { + input.InputStream.Close(); + } + } +} \ No newline at end of file diff --git a/tmp/Grib2/CodeTables/0_0_Discipline.cs b/tmp/Grib2/CodeTables/0_0_Discipline.cs new file mode 100644 index 0000000..8c68655 --- /dev/null +++ b/tmp/Grib2/CodeTables/0_0_Discipline.cs @@ -0,0 +1,33 @@ +/* + * This file is part of NGrib. + * + * Copyright © 2020 Nicolas Mangué + * + * NGrib is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * NGrib is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with NGrib. If not, see . + */ + +namespace NGrib.Grib2.CodeTables; + +/// +/// Discipline of processed data in the GRIB message. +/// +public enum Discipline +{ + MeteorologicalProducts = 0, + HydrologicalProducts = 1, + LandSurfaceProducts = 2, + SpaceProducts = 3, + OceanographicProducts = 10, + Missing = 255, +} \ No newline at end of file diff --git a/tmp/Grib2/CodeTables/1_2_ReferenceTimeSignificance.cs b/tmp/Grib2/CodeTables/1_2_ReferenceTimeSignificance.cs new file mode 100644 index 0000000..a4f4f2b --- /dev/null +++ b/tmp/Grib2/CodeTables/1_2_ReferenceTimeSignificance.cs @@ -0,0 +1,51 @@ +/* + * This file is part of NGrib. + * + * Copyright © 2020 Nicolas Mangué + * + * NGrib is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * NGrib is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with NGrib. If not, see . + */ + +namespace NGrib.Grib2.CodeTables; + +/// +/// Code Table 1.2: Significance of Reference Time +/// +public enum ReferenceTimeSignificance +{ + /// + /// Analysis. + /// + Analysis = 0, + + /// + /// Start of forecast. + /// + ForecastStart = 1, + + /// + /// Verifying time of forecast. + /// + ForecastVerifyingTime = 2, + + /// + /// Observation time. + /// + ObservationTime = 3, + + /// + /// Missing. + /// + Missing = 255 +} \ No newline at end of file diff --git a/tmp/Grib2/CodeTables/1_3_ProductStatus.cs b/tmp/Grib2/CodeTables/1_3_ProductStatus.cs new file mode 100644 index 0000000..e8aa7b7 --- /dev/null +++ b/tmp/Grib2/CodeTables/1_3_ProductStatus.cs @@ -0,0 +1,51 @@ +/* + * This file is part of NGrib. + * + * Copyright © 2020 Nicolas Mangué + * + * NGrib is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * NGrib is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with NGrib. If not, see . + */ + +namespace NGrib.Grib2.CodeTables; + +/// +/// Code Table 1.3: Production status of data +/// +public enum ProductStatus +{ + /// + /// Operational products + /// + OperationalProducts = 0, + + /// + /// Operational test products + /// + OperationalTestProducts = 1, + + /// + /// Research products + /// + ResearchProducts = 2, + + /// + /// Re-analysis products + /// + ReanalysisProducts = 3, + + /// + /// Missing + /// + Missing = 255 +} \ No newline at end of file diff --git a/tmp/Grib2/CodeTables/1_4_ProductType.cs b/tmp/Grib2/CodeTables/1_4_ProductType.cs new file mode 100644 index 0000000..ea1418e --- /dev/null +++ b/tmp/Grib2/CodeTables/1_4_ProductType.cs @@ -0,0 +1,71 @@ +/* + * This file is part of NGrib. + * + * Copyright © 2020 Nicolas Mangué + * + * NGrib is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * NGrib is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with NGrib. If not, see . + */ + +namespace NGrib.Grib2.CodeTables; + +/// +/// Code Table 1.4: Type of data +/// +public enum ProductType +{ + /// + /// Analysis products + /// + AnalysisProducts = 0, + + /// + /// Forecast products + /// + ForecastProducts = 1, + + /// + /// Analysis and forecast products + /// + AnalysisAndForecastProducts = 2, + + /// + /// Control forecast products + /// + ControlForecastProducts = 3, + + /// + /// Perturbed forecast products + /// + PerturbedForecastProducts = 4, + + /// + /// Control and perturbed forecast products + /// + ControlAndPerturbedForecastProducts = 5, + + /// + /// Processed satellite observations + /// + ProcessedSatelliteObservations = 6, + + /// + /// Processed radar observations + /// + ProcessedRadarObservations = 7, + + /// + /// Missing + /// + Missing = 255 +} \ No newline at end of file diff --git a/tmp/Grib2/CodeTables/3_2_EarthShape.cs b/tmp/Grib2/CodeTables/3_2_EarthShape.cs new file mode 100644 index 0000000..7604a42 --- /dev/null +++ b/tmp/Grib2/CodeTables/3_2_EarthShape.cs @@ -0,0 +1,62 @@ +/* + * This file is part of NGrib. + * + * Copyright © 2020 Nicolas Mangué + * + * NGrib is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * NGrib is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with NGrib. If not, see . + */ + +namespace NGrib.Grib2.CodeTables; + +/// +/// Code Table 3.2: Shape of the Earth +/// +public enum EarthShape +{ + /// + /// Earth assumed spherical with radius = 6,367,470.0 m. + /// + DefaultSpherical, + + /// + /// Earth assumed spherical with radius specified by data producer. + /// + CustomSpherical, + + /// + /// Earth assumed oblate spheroid with size as determined by IAU in 1965 (major axis = 6,378,160.0 m, minor axis = 6,356,775.0 m, f = 1/297.0). + /// + Iau1965OblateSpheroid, + + /// + /// Earth assumed oblate spheroid with major and minor axes specified by data producer. + /// + CustomOblateSpheroid, + + /// + /// Earth assumed oblate spheroid as defined in IAG-GRS80 model (major axis = 6,378,137.0 m, minor axis = 6,356,752.314 m, f = 1/298.257222101). + /// + IagGr80OblateSpheroid, + + /// + /// Earth assumed represented by WGS84 (as used by ICAO since 1998). + /// + Wgs84, + + /// + /// Earth model assumed spherical with radius 6,371,200.0 m, + /// but the horizontal datum of the resulting Latitude/Longitude field is the WGS84 reference frame. + /// + Wgs84Spherical +} \ No newline at end of file diff --git a/tmp/Grib2/CodeTables/3_3_ResolutionAndComponent.cs b/tmp/Grib2/CodeTables/3_3_ResolutionAndComponent.cs new file mode 100644 index 0000000..966cee1 --- /dev/null +++ b/tmp/Grib2/CodeTables/3_3_ResolutionAndComponent.cs @@ -0,0 +1,28 @@ +/* + * This file is part of NGrib. + * + * Copyright © 2020 Nicolas Mangué + * + * NGrib is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * NGrib is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with NGrib. If not, see . + */ + +namespace NGrib.Grib2.CodeTables; + +[Flags] +public enum ResolutionAndComponent +{ + IDirectionIncrementGiven = 32, + JDirectionIncrementGiven = 16, + RelativeDefinedGrid = 8 +} \ No newline at end of file diff --git a/tmp/Grib2/CodeTables/3_4_ScanningMode.cs b/tmp/Grib2/CodeTables/3_4_ScanningMode.cs new file mode 100644 index 0000000..05a491c --- /dev/null +++ b/tmp/Grib2/CodeTables/3_4_ScanningMode.cs @@ -0,0 +1,34 @@ +/* + * This file is part of NGrib. + * + * Copyright © 2020 Nicolas Mangué + * + * NGrib is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * NGrib is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with NGrib. If not, see . + */ + +namespace NGrib.Grib2.CodeTables; + +[Flags] +public enum ScanningMode +{ + ScanIReverse = 128, + ScanJPositive = 64, + AdjacentPointsInJConsecutive = 32, + AdjacentRowsScanInOppositeDirection = 16, + DxOffOdd = 8, + DxOffEven = 4, + DyOff = 2, + ReducedGrid = 1, + Default = 0 +} \ No newline at end of file diff --git a/tmp/Grib2/CodeTables/4_1_ParameterCategory.cs b/tmp/Grib2/CodeTables/4_1_ParameterCategory.cs new file mode 100644 index 0000000..b30ca9c --- /dev/null +++ b/tmp/Grib2/CodeTables/4_1_ParameterCategory.cs @@ -0,0 +1,226 @@ +/* + * This file is part of NGrib. + * + * Copyright © 2020 Nicolas Mangué + * + * NGrib is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * NGrib is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with NGrib. If not, see . + */ + +using System.Collections.Immutable; + +namespace NGrib.Grib2.CodeTables; + +/// +/// Represents a category parameters by product discipline. +/// +public struct ParameterCategory +{ + /// + /// Product discipline. + /// + public Discipline Discipline { get; } + + /// + /// Parameter category code. + /// + public int Code { get; } + + /// + /// Parameter category description. + /// + public string Description { get; } + + private ParameterCategory(Discipline discipline, int code, string description) + { + Discipline = discipline; + Code = code; + Description = description; + } + + ///Temperature + public static ParameterCategory Temperature { get; } = new ParameterCategory(Discipline.MeteorologicalProducts, 0, "Temperature"); + + ///Moisture + public static ParameterCategory Moisture { get; } = new ParameterCategory(Discipline.MeteorologicalProducts, 1, "Moisture"); + + ///Momentum + public static ParameterCategory Momentum { get; } = new ParameterCategory(Discipline.MeteorologicalProducts, 2, "Momentum"); + + ///Mass + public static ParameterCategory Mass { get; } = new ParameterCategory(Discipline.MeteorologicalProducts, 3, "Mass"); + + ///Short-wave Radiation + public static ParameterCategory ShortWaveRadiation { get; } = + new ParameterCategory(Discipline.MeteorologicalProducts, 4, "Short-wave Radiation"); + + ///Long-wave Radiation + public static ParameterCategory LongWaveRadiation { get; } = + new ParameterCategory(Discipline.MeteorologicalProducts, 5, "Long-wave Radiation"); + + ///Cloud + public static ParameterCategory Cloud { get; } = new ParameterCategory(Discipline.MeteorologicalProducts, 6, "Cloud"); + + ///Thermodynamic Stability indices + public static ParameterCategory ThermodynamicStabilityIndices { get; } = new ParameterCategory(Discipline.MeteorologicalProducts, + 7, "Thermodynamic Stability indices"); + + ///Kinematic Stability indices + public static ParameterCategory KinematicStabilityIndices { get; } = + new ParameterCategory(Discipline.MeteorologicalProducts, 8, "Kinematic Stability indices"); + + ///Temperature Probabilities + public static ParameterCategory TemperatureProbabilities { get; } = + new ParameterCategory(Discipline.MeteorologicalProducts, 9, "Temperature Probabilities"); + + ///Moisture Probabilities + public static ParameterCategory MoistureProbabilities { get; } = + new ParameterCategory(Discipline.MeteorologicalProducts, 10, "Moisture Probabilities"); + + ///Momentum Probabilities + public static ParameterCategory MomentumProbabilities { get; } = + new ParameterCategory(Discipline.MeteorologicalProducts, 11, "Momentum Probabilities"); + + ///Mass Probabilities + public static ParameterCategory MassProbabilities { get; } = + new ParameterCategory(Discipline.MeteorologicalProducts, 12, "Mass Probabilities"); + + ///Aerosols + public static ParameterCategory Aerosols { get; } = new ParameterCategory(Discipline.MeteorologicalProducts, 13, "Aerosols"); + + ///Trace gases (e.g., ozone, CO2) + public static ParameterCategory TraceGases { get; } = + new ParameterCategory(Discipline.MeteorologicalProducts, 14, "Trace gases (e.g., ozone, CO2)"); + + ///Radar + public static ParameterCategory Radar { get; } = new ParameterCategory(Discipline.MeteorologicalProducts, 15, "Radar"); + + ///Forecast Radar Imagery + public static ParameterCategory ForecastRadarImagery { get; } = + new ParameterCategory(Discipline.MeteorologicalProducts, 16, "Forecast Radar Imagery"); + + ///Electro-dynamics + public static ParameterCategory Electrodynamics { get; } = + new ParameterCategory(Discipline.MeteorologicalProducts, 17, "Electro-dynamics"); + + ///Nuclear/radiology + public static ParameterCategory NuclearRadiology { get; } = + new ParameterCategory(Discipline.MeteorologicalProducts, 18, "Nuclear/radiology"); + ///Physical atmospheric properties + public static ParameterCategory PhysicalAtmosphericProperties { get; } = new ParameterCategory(Discipline.MeteorologicalProducts, + 19, "Physical atmospheric properties"); + + /// Atmospheric chemical Constituents + public static ParameterCategory AtmosphericChemicalConstituents { get; } = + new ParameterCategory(Discipline.MeteorologicalProducts, 20, "Atmospheric chemical Constituents"); + + ///CCITT IA5 string + public static ParameterCategory CcittIa5String { get; } = + new ParameterCategory(Discipline.MeteorologicalProducts, 190, "CCITT IA5 string"); + + ///Miscellaneous + public static ParameterCategory Miscellaneous { get; } = + new ParameterCategory(Discipline.MeteorologicalProducts, 191, "Miscellaneous"); + + + ///Hydrology basic products + public static ParameterCategory HydrologyBasicProducts { get; } = + new ParameterCategory(Discipline.HydrologicalProducts, 0, "Hydrology basic products"); + + ///Hydrology probabilities + public static ParameterCategory HydrologyProbabilities { get; } = + new ParameterCategory(Discipline.HydrologicalProducts, 1, "Hydrology probabilities"); + + + ///Vegetation/Biomass + public static ParameterCategory VegetationBiomass { get; } = + new ParameterCategory(Discipline.LandSurfaceProducts, 0, "Vegetation/Biomass"); + + ///Agri-/aquacultural Special Products + public static ParameterCategory AgriAquaCulturalSpecialProducts { get; } = new ParameterCategory(Discipline.LandSurfaceProducts, + 1, "Agri-/aquacultural Special Products"); + + ///Transportation-related Products + public static ParameterCategory TransportationRelatedProducts { get; } = + new ParameterCategory(Discipline.LandSurfaceProducts, 2, "Transportation-related Products"); + + ///Soil Products + public static ParameterCategory SoilProducts { get; } = new ParameterCategory(Discipline.LandSurfaceProducts, 3, "Soil Products"); + + + ///Image format products + public static ParameterCategory ImageFormatProducts { get; } = + new ParameterCategory(Discipline.SpaceProducts, 0, "Image format products"); + + ///Quantitative products + public static ParameterCategory QuantitativeProducts { get; } = + new ParameterCategory(Discipline.SpaceProducts, 1, "Quantitative products"); + + + ///Waves + public static ParameterCategory Waves { get; } = new ParameterCategory(Discipline.OceanographicProducts, 0, "Waves"); + + ///Currents + public static ParameterCategory Currents { get; } = new ParameterCategory(Discipline.OceanographicProducts, 1, "Currents"); + + ///Ice + public static ParameterCategory Ice { get; } = new ParameterCategory(Discipline.OceanographicProducts, 2, "Ice"); + + ///Surface Properties + public static ParameterCategory SurfaceProperties { get; } = + new ParameterCategory(Discipline.OceanographicProducts, 3, "Surface Properties"); + + ///Sub-surface Properties + public static ParameterCategory SubSurfaceProperties { get; } = + new ParameterCategory(Discipline.OceanographicProducts, 4, "Sub-surface Properties"); + + public static IReadOnlyDictionary> CategoriesByDiscipline { get; } = + ImmutableList.Empty + .Add(Temperature) + .Add(Moisture) + .Add(Momentum) + .Add(Mass) + .Add(ShortWaveRadiation) + .Add(LongWaveRadiation) + .Add(Cloud) + .Add(ThermodynamicStabilityIndices) + .Add(KinematicStabilityIndices) + .Add(TemperatureProbabilities) + .Add(MoistureProbabilities) + .Add(MomentumProbabilities) + .Add(MassProbabilities) + .Add(Aerosols) + .Add(TraceGases) + .Add(Radar) + .Add(ForecastRadarImagery) + .Add(Electrodynamics) + .Add(NuclearRadiology) + .Add(PhysicalAtmosphericProperties) + .Add(CcittIa5String) + .Add(Miscellaneous) + .Add(HydrologyBasicProducts) + .Add(HydrologyProbabilities) + .Add(VegetationBiomass) + .Add(AgriAquaCulturalSpecialProducts) + .Add(TransportationRelatedProducts) + .Add(SoilProducts) + .Add(ImageFormatProducts) + .Add(QuantitativeProducts) + .Add(Waves) + .Add(Currents) + .Add(Ice) + .Add(SurfaceProperties) + .Add(SubSurfaceProperties) + .GroupBy(c => c.Discipline) + .ToDictionary(g => g.Key, g => (IReadOnlyCollection) g.ToImmutableList()); +} \ No newline at end of file diff --git a/tmp/Grib2/CodeTables/4_2_Parameter.cs b/tmp/Grib2/CodeTables/4_2_Parameter.cs new file mode 100644 index 0000000..d44f131 --- /dev/null +++ b/tmp/Grib2/CodeTables/4_2_Parameter.cs @@ -0,0 +1,2014 @@ +/* + * This file is part of NGrib. + * + * Copyright © 2020 Nicolas Mangué + * + * NGrib is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * NGrib is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with NGrib. If not, see . + */ + +using System.Collections.Immutable; + +namespace NGrib.Grib2.CodeTables; + +/// +/// Represents a parameter. +/// +public readonly struct Parameter +{ + /// + /// Parameter category. + /// + public ParameterCategory Category { get; } + + /// + /// Parameter number. + /// + public int Code { get; } + + /// + /// Parameter name. + /// + public string Name { get; } + + /// + /// Units. + /// + public string Unit { get; } + + private Parameter(ParameterCategory category, int code, string name, string unit) + { + Category = category; + Code = code; + Name = name; + Unit = unit; + } + + public static Parameter? Get(Discipline d, int parameterCategory, int parameterNumber) + { + if (ParameterCategory.CategoriesByDiscipline.TryGetValue(d, out var categories)) + { + var category = categories.Where(c => c.Code == parameterCategory).ToArray(); + if (category.Any() && ParametersByCategory.TryGetValue(category[0], out var parameters)) + { + var parameter = parameters.Where(p => p.Code == parameterNumber).ToArray(); + if (parameter.Any()) + { + return parameter[0]; + } + } + } + + return null; + } + + #region Product Discipline 0: Meteorological products, Parameter Category 0: Temperature + + ///Temperature (K) + public static Parameter Temperature { get; } = new Parameter(ParameterCategory.Temperature, 0, "Temperature", "K"); + + ///Virtual temperature (K) + public static Parameter VirtualTemperature { get; } = + new Parameter(ParameterCategory.Temperature, 1, "Virtual temperature", "K"); + + ///Potential temperature (K) + public static Parameter PotentialTemperature { get; } = + new Parameter(ParameterCategory.Temperature, 2, "Potential temperature", "K"); + + ///Pseudo-adiabatic potential temperature or equivalent potential temperature (K) + public static Parameter PseudoAdiabaticPotentialTemperatureOrEquivalentPotentialTemperature { get; } = + new Parameter(ParameterCategory.Temperature, 3, + "Pseudo-adiabatic potential temperature or equivalent potential temperature", "K"); + + ///Maximum temperature (K) + public static Parameter MaximumTemperature { get; } = + new Parameter(ParameterCategory.Temperature, 4, "Maximum temperature", "K"); + + ///Minimum temperature (K) + public static Parameter MinimumTemperature { get; } = + new Parameter(ParameterCategory.Temperature, 5, "Minimum temperature", "K"); + + ///Dew point temperature (K) + public static Parameter DewPointTemperature { get; } = + new Parameter(ParameterCategory.Temperature, 6, "Dew point temperature", "K"); + + ///Dew point depression (or deficit) (K) + public static Parameter DewPointDepression { get; } = + new Parameter(ParameterCategory.Temperature, 7, "Dew point depression (or deficit)", "K"); + + ///Lapse rate (K m-1) + public static Parameter LapseRate { get; } = new Parameter(ParameterCategory.Temperature, 8, "Lapse rate", "K m-1"); + + ///Temperature anomaly (K) + public static Parameter TemperatureAnomaly { get; } = + new Parameter(ParameterCategory.Temperature, 9, "Temperature anomaly", "K"); + + ///Latent heat net flux (W m-2) + public static Parameter LatentHeatNetFlux { get; } = + new Parameter(ParameterCategory.Temperature, 10, "Latent heat net flux", "W m-2"); + + ///Sensible heat net flux (W m-2) + public static Parameter SensibleHeatNetFlux { get; } = + new Parameter(ParameterCategory.Temperature, 11, "Sensible heat net flux", "W m-2"); + + ///Heat index (K) + public static Parameter HeatIndex { get; } = new Parameter(ParameterCategory.Temperature, 12, "Heat index", "K"); + + ///Wind chill factor (K) + public static Parameter WindChillFactor { get; } = + new Parameter(ParameterCategory.Temperature, 13, "Wind chill factor", "K"); + + ///Minimum dew point depression (K) + public static Parameter MinimumDewPointDepression { get; } = + new Parameter(ParameterCategory.Temperature, 14, "Minimum dew point depression", "K"); + + ///Virtual potential temperature (K) + public static Parameter VirtualPotentialTemperature { get; } = + new Parameter(ParameterCategory.Temperature, 15, "Virtual potential temperature", "K"); + + ///Snow Phase Change Heat Flux (W m-2) + public static Parameter SnowPhaseChangeHeatFlux { get; } = + new Parameter(ParameterCategory.Temperature, 16, "Snow Phase Change Heat Flux", "W m-2"); + + ///Skin Temperature (K) + public static Parameter SkinTemperature { get; } = + new Parameter(ParameterCategory.Temperature, 17, "Skin Temperature", "K"); + + ///Snow Temperature (top of snow) (K) + public static Parameter SnowTemperature { get; } = + new Parameter(ParameterCategory.Temperature, 18, "Snow Temperature (top of snow)", "K"); + + ///Turbulent Transfer Coefficient for Heat (Numeric) + public static Parameter TurbulentTransferCoefficientForHeat { get; } = + new Parameter(ParameterCategory.Temperature, 19, "Turbulent Transfer Coefficient for Heat", "Numeric"); + + ///Turbulent Diffusion Coefficient for Heat (m2s-1) + public static Parameter TurbulentDiffusionCoefficientForHeat { get; } = + new Parameter(ParameterCategory.Temperature, 20, "Turbulent Diffusion Coefficient for Heat", "m2s-1"); + + ///Apparent Temperature (K) + public static Parameter ApparentTemperature { get; } = + new Parameter(ParameterCategory.Temperature, 21, "Apparent Temperature ", "K"); + + ///Temperature Tendency due to Short-Wave Radiation (K s-1) + public static Parameter TemperatureTendencyDueToShortWaveRadiation { get; } = + new Parameter(ParameterCategory.Temperature, 22, "Temperature Tendency due to Short-Wave Radiation", "K s-1"); + + ///Temperature Tendency due to Long-Wave Radiation (K s-1) + public static Parameter TemperatureTendencyDueToLongWaveRadiation { get; } = + new Parameter(ParameterCategory.Temperature, 23, "Temperature Tendency due to Long-Wave Radiation", "K s-1"); + + ///Temperature Tendency due to Short-Wave Radiation,Clear Sky (K s-1) + public static Parameter TemperatureTendencyDueToShortWaveRadiationClearSky { get; } = + new Parameter(ParameterCategory.Temperature, 24, "Temperature Tendency due to Short-Wave Radiation,Clear Sky", "K s-1"); + + ///Temperature Tendency due to Long-Wave Radiation,Clear Sky (K s-1) + public static Parameter TemperatureTendencyDueToLongWaveRadiationClearSky { get; } = + new Parameter(ParameterCategory.Temperature, 25, "Temperature Tendency due to Long-Wave Radiation,Clear Sky", "K s-1"); + + ///Temperature Tendency due to parameterizations (K s-1) + public static Parameter TemperatureTendencyDueToParameterizations { get; } = + new Parameter(ParameterCategory.Temperature, 26, "Temperature Tendency due to parameterizations", "K s-1"); + + ///Wet Bulb Temperature (K) + public static Parameter WetBulbTemperature { get; } = + new Parameter(ParameterCategory.Temperature, 27, "Wet Bulb Temperature", "K"); + + ///Unbalanced Component of Temperature (K) + public static Parameter UnbalancedComponentOfTemperature { get; } = + new Parameter(ParameterCategory.Temperature, 28, "Unbalanced Component of Temperature", "K"); + + ///Temperature Advection (K s-1) + public static Parameter TemperatureAdvection { get; } = + new Parameter(ParameterCategory.Temperature, 29, "Temperature Advection", "K s-1"); + + #endregion + + #region Product Discipline 0: Meteorological products, Parameter Category 1: Moisture + + ///Specific humidity (kg kg-1) + public static Parameter SpecificHumidity { get; } = + new Parameter(ParameterCategory.Moisture, 0, "Specific humidity", "kg kg-1"); + + ///Relative humidity (%) + public static Parameter RelativeHumidity { get; } = new Parameter(ParameterCategory.Moisture, 1, "Relative humidity", "%"); + + ///Humidity mixing ratio (kg kg-1) + public static Parameter HumidityMixingRatio { get; } = + new Parameter(ParameterCategory.Moisture, 2, "Humidity mixing ratio", "kg kg-1"); + + ///Precipitable water (kg m-2) + public static Parameter PrecipitableWater { get; } = + new Parameter(ParameterCategory.Moisture, 3, "Precipitable water", "kg m-2"); + + ///Vapor pressure (Pa) + public static Parameter VaporPressure { get; } = new Parameter(ParameterCategory.Moisture, 4, "Vapor pressure", "Pa"); + + ///Saturation deficit (Pa) + public static Parameter SaturationDeficit { get; } = + new Parameter(ParameterCategory.Moisture, 5, "Saturation deficit", "Pa"); + + ///Evaporation (kg m-2) + public static Parameter Evaporation { get; } = new Parameter(ParameterCategory.Moisture, 6, "Evaporation", "kg m-2"); + + ///Precipitation rate (kg m-2 s-1) + public static Parameter PrecipitationRate { get; } = + new Parameter(ParameterCategory.Moisture, 7, "Precipitation rate", "kg m-2 s-1"); + + ///Total precipitation (kg m-2) + public static Parameter TotalPrecipitation { get; } = + new Parameter(ParameterCategory.Moisture, 8, "Total precipitation", "kg m-2"); + + ///Large scale precipitation (non-convective) (kg m-2) + public static Parameter LargeScalePrecipitationNonConvective { get; } = new Parameter(ParameterCategory.Moisture, 9, + "Large scale precipitation (non-convective)", "kg m-2"); + + ///Convective precipitation (kg m-2) + public static Parameter ConvectivePrecipitation { get; } = + new Parameter(ParameterCategory.Moisture, 10, "Convective precipitation", "kg m-2"); + + ///Snow depth (m) + public static Parameter SnowDepth { get; } = new Parameter(ParameterCategory.Moisture, 11, "Snow depth", "m"); + + ///Snowfall rate water equivalent (kg m-2 s-1) + public static Parameter SnowfallRateWaterEquivalent { get; } = + new Parameter(ParameterCategory.Moisture, 12, "Snowfall rate water equivalent", "kg m-2 s-1"); + + ///Water equivalent of accumulated snow depth (kg m-2) + public static Parameter WaterEquivalentOfAccumulatedSnowDepth { get; } = new Parameter(ParameterCategory.Moisture, 13, + "Water equivalent of accumulated snow depth", "kg m-2"); + + ///Convective snow (kg m-2) + public static Parameter ConvectiveSnow { get; } = + new Parameter(ParameterCategory.Moisture, 14, "Convective snow", "kg m-2"); + + ///Large scale snow (kg m-2) + public static Parameter LargeScaleSnow { get; } = + new Parameter(ParameterCategory.Moisture, 15, "Large scale snow", "kg m-2"); + + ///Snow melt (kg m-2) + public static Parameter SnowMelt { get; } = new Parameter(ParameterCategory.Moisture, 16, "Snow melt", "kg m-2"); + + ///Snow age (day) + public static Parameter SnowAge { get; } = new Parameter(ParameterCategory.Moisture, 17, "Snow age", "day"); + + ///Absolute humidity (kg m-3) + public static Parameter AbsoluteHumidity { get; } = + new Parameter(ParameterCategory.Moisture, 18, "Absolute humidity", "kg m-3"); + + ///Precipitation type (Code table (4.201)) + public static Parameter PrecipitationType { get; } = + new Parameter(ParameterCategory.Moisture, 19, "Precipitation type", "Code table (4.201)"); + + ///Integrated liquid water (kg m-2) + public static Parameter IntegratedLiquidWater { get; } = + new Parameter(ParameterCategory.Moisture, 20, "Integrated liquid water", "kg m-2"); + + ///Condensate (kg kg-1) + public static Parameter Condensate { get; } = new Parameter(ParameterCategory.Moisture, 21, "Condensate", "kg kg-1"); + + ///Cloud mixing ratio (kg kg-1) + public static Parameter CloudMixingRatio { get; } = + new Parameter(ParameterCategory.Moisture, 22, "Cloud mixing ratio", "kg kg-1"); + + ///Ice water mixing ratio (kg kg-1) + public static Parameter IceWaterMixingRatio { get; } = + new Parameter(ParameterCategory.Moisture, 23, "Ice water mixing ratio", "kg kg-1"); + + ///Rain mixing ratio (kg kg-1) + public static Parameter RainMixingRatio { get; } = + new Parameter(ParameterCategory.Moisture, 24, "Rain mixing ratio", "kg kg-1"); + + ///Snow mixing ratio (kg kg-1) + public static Parameter SnowMixingRatio { get; } = + new Parameter(ParameterCategory.Moisture, 25, "Snow mixing ratio", "kg kg-1"); + + ///Horizontal moisture convergence (kg kg-1 s-1) + public static Parameter HorizontalMoistureConvergence { get; } = new Parameter(ParameterCategory.Moisture, 26, + "Horizontal moisture convergence", "kg kg-1 s-1"); + + ///Maximum relative humidity (%) + public static Parameter MaximumRelativeHumidity { get; } = + new Parameter(ParameterCategory.Moisture, 27, "Maximum relative humidity", "%"); + + ///Maximum absolute humidity (kg m-3) + public static Parameter MaximumAbsoluteHumidity { get; } = + new Parameter(ParameterCategory.Moisture, 28, "Maximum absolute humidity", "kg m-3"); + + ///Total snowfall (m) + public static Parameter TotalSnowfall { get; } = new Parameter(ParameterCategory.Moisture, 29, "Total snowfall", "m"); + + ///Precipitable water category (Code table (4.202)) + public static Parameter PrecipitableWaterCategory { get; } = new Parameter(ParameterCategory.Moisture, 30, + "Precipitable water category", "Code table (4.202)"); + + ///Hail (m) + public static Parameter Hail { get; } = new Parameter(ParameterCategory.Moisture, 31, "Hail", "m"); + + ///Graupel (snow pellets) (kg kg-1) + public static Parameter Graupel { get; } = + new Parameter(ParameterCategory.Moisture, 32, "Graupel (snow pellets)", "kg kg-1"); + + ///Categorical Rain (Code table 4.222) + public static Parameter CategoricalRain { get; } = + new Parameter(ParameterCategory.Moisture, 33, "Categorical Rain", ""); + + ///Categorical Freezing Rain (Code table 4.222) + public static Parameter CategoricalFreezingRain { get; } = + new Parameter(ParameterCategory.Moisture, 34, "Categorical Freezing Rain", ""); + + ///Categorical Ice Pellets (Code table 4.222) + public static Parameter CategoricalIcePellets { get; } = + new Parameter(ParameterCategory.Moisture, 35, "Categorical Ice Pellets", ""); + + ///Categorical Snow (Code table 4.222) + public static Parameter CategoricalSnow { get; } = + new Parameter(ParameterCategory.Moisture, 36, "Categorical Snow", ""); + + ///Convective Precipitation Rate (kg m-2 s-1) + public static Parameter ConvectivePrecipitationRate { get; } = + new Parameter(ParameterCategory.Moisture, 37, "Convective Precipitation Rate", "kg m-2 s-1"); + + ///Horizontal Moisture Divergence (kg kg-1 s-1) + public static Parameter HorizontalMoistureDivergence { get; } = + new Parameter(ParameterCategory.Moisture, 38, "Horizontal Moisture Divergence", "kg kg-1 s-1"); + + ///Percent frozen precipitation (%) + public static Parameter PercentFrozenPrecipitation { get; } = + new Parameter(ParameterCategory.Moisture, 39, "Percent frozen precipitation", "%"); + + ///Potential Evaporation (kg m-2) + public static Parameter PotentialEvaporation { get; } = + new Parameter(ParameterCategory.Moisture, 40, "Potential Evaporation", "kg m-2"); + + ///Potential Evaporation Rate (W m-2) + public static Parameter PotentialEvaporationRate { get; } = + new Parameter(ParameterCategory.Moisture, 41, "Potential Evaporation Rate", "W m-2"); + + ///Snow Cover (%) + public static Parameter SnowCover { get; } = + new Parameter(ParameterCategory.Moisture, 42, "Snow Cover", "%"); + + ///Rain Fraction of Total Cloud Water (Proportion) + public static Parameter RainFractionOfTotalCloudWater { get; } = + new Parameter(ParameterCategory.Moisture, 43, "Rain Fraction of Total Cloud Water", "Proportion"); + + ///Rime Factor (Numeric) + public static Parameter RimeFactor { get; } = + new Parameter(ParameterCategory.Moisture, 44, "Rime Factor", "Numeric"); + + ///Total Column Integrated Rain (kg m-2) + public static Parameter TotalColumnIntegratedRain { get; } = + new Parameter(ParameterCategory.Moisture, 45, "Total Column Integrated Rain", "kg m-2"); + + ///Total Column Integrated Snow (kg m-2) + public static Parameter TotalColumnIntegratedSnow { get; } = + new Parameter(ParameterCategory.Moisture, 46, "Total Column Integrated Snow", "kg m-2"); + + ///Large Scale Water Precipitation (Non-Convective) (kg m-2) + public static Parameter LargeScaleWaterPrecipitation { get; } = + new Parameter(ParameterCategory.Moisture, 47, "Large Scale Water Precipitation (Non-Convective) ", "kg m-2"); + + ///Convective Water Precipitation (kg m-2) + public static Parameter ConvectiveWaterPrecipitation { get; } = + new Parameter(ParameterCategory.Moisture, 48, "Convective Water Precipitation ", "kg m-2"); + + ///Total Water Precipitation (kg m-2) + public static Parameter TotalWaterPrecipitation { get; } = + new Parameter(ParameterCategory.Moisture, 49, "Total Water Precipitation ", "kg m-2"); + + ///Total Snow Precipitation (kg m-2) + public static Parameter TotalSnowPrecipitation { get; } = + new Parameter(ParameterCategory.Moisture, 50, "Total Snow Precipitation ", "kg m-2"); + + ///Total Column Water(Vertically integrated total water (vapour+cloud water/ice) (kg m-2) + public static Parameter TotalColumnWater { get; } = + new Parameter(ParameterCategory.Moisture, 51, "Total Column Water(Vertically integrated total water (vapour+cloud water/ice)", "kg m-2"); + + ///Total Precipitation Rate (kg m-2 s-1) + public static Parameter TotalPrecipitationRate { get; } = + new Parameter(ParameterCategory.Moisture, 52, "Total Precipitation Rate ", "kg m-2 s-1"); + + ///Total Snowfall Rate Water Equivalent (kg m-2 s-1) + public static Parameter TotalSnowfallRateWaterEquivalent { get; } = + new Parameter(ParameterCategory.Moisture, 53, "Total Snowfall Rate Water Equivalent ", "kg m-2 s-1"); + + ///Large Scale Precipitation Rate (kg m-2 s-1) + public static Parameter LargeScalePrecipitationRate { get; } = + new Parameter(ParameterCategory.Moisture, 54, "Large Scale Precipitation Rate", "kg m-2 s-1"); + + ///Convective Snowfall Rate Water Equivalent (kg m-2 s-1) + public static Parameter ConvectiveSnowfallRateWaterEquivalent { get; } = + new Parameter(ParameterCategory.Moisture, 55, "Convective Snowfall Rate Water Equivalent", "kg m-2 s-1"); + + ///Large Scale Snowfall Rate Water Equivalent (kg m-2 s-1) + public static Parameter LargeScaleSnowfallRateWaterEquivalent { get; } = + new Parameter(ParameterCategory.Moisture, 56, "Large Scale Snowfall Rate Water Equivalent", "kg m-2 s-1"); + + ///Total Snowfall Rate (m s-1) + public static Parameter TotalSnowfallRate { get; } = + new Parameter(ParameterCategory.Moisture, 57, "Total Snowfall Rate", "m s-1"); + + ///Convective Snowfall Rate (m s-1) + public static Parameter ConvectiveSnowfallRate { get; } = + new Parameter(ParameterCategory.Moisture, 58, "Convective Snowfall Rate", "m s-1"); + + ///Large Scale Snowfall Rate (m s-1) + public static Parameter LargeScaleSnowfallRate { get; } = + new Parameter(ParameterCategory.Moisture, 59, "Large Scale Snowfall Rate", "m s-1"); + + ///Snow Depth Water Equivalent (kg m-2) + public static Parameter SnowDepthWaterEquivalent { get; } = + new Parameter(ParameterCategory.Moisture, 60, "Snow Depth Water Equivalent", "kg m-2"); + + ///Snow Density (kg m-3) + public static Parameter SnowDensity { get; } = + new Parameter(ParameterCategory.Moisture, 61, "Snow Density", "kg m-3"); + + ///Snow Evaporation (kg m-2) + public static Parameter SnowEvaporation { get; } = + new Parameter(ParameterCategory.Moisture, 62, "Snow Evaporation", "kg m-2"); + + ///Total Column Integrated Water Vapour (kg m-2) + public static Parameter TotalColumnIntegratedWaterVapour { get; } = + new Parameter(ParameterCategory.Moisture, 64, "Total Column Integrated Water Vapour", "kg m-2"); + + ///Rain Precipitation Rate (kg m-2 s-1) + public static Parameter RainPrecipitationRate { get; } = + new Parameter(ParameterCategory.Moisture, 65, "Rain Precipitation Rate", "kg m-2 s-1"); + + ///Snow Precipitation Rate (kg m-2 s-1) + public static Parameter SnowPrecipitationRate { get; } = + new Parameter(ParameterCategory.Moisture, 66, "Snow Precipitation Rate", "kg m-2 s-1"); + + ///Freezing Rain Precipitation Rate (kg m-2 s-1) + public static Parameter FreezingRainPrecipitationRate { get; } = + new Parameter(ParameterCategory.Moisture, 67, "Freezing Rain Precipitation Rate", "kg m-2 s-1"); + + ///Ice Pellets Precipitation Rate (kg m-2 s-1) + public static Parameter IcePelletsPrecipitationRate { get; } = + new Parameter(ParameterCategory.Moisture, 68, "Ice Pellets Precipitation Rate", "kg m-2 s-1"); + + ///Total Column Integrate Cloud Water (kg m-2) + public static Parameter TotalColumnIntegrateCloudWater { get; } = + new Parameter(ParameterCategory.Moisture, 69, "Total Column Integrate Cloud Water", "kg m-2"); + + ///Total Column Integrate Cloud Ice (kg m-2) + public static Parameter TotalColumnIntegrateCloudIce { get; } = + new Parameter(ParameterCategory.Moisture, 70, "Total Column Integrate Cloud Ice", "kg m-2"); + + ///Hail Mixing Ratio (kg kg-1) + public static Parameter HailMixingRatio { get; } = + new Parameter(ParameterCategory.Moisture, 71, "Hail Mixing Ratio", "kg kg-1"); + + ///Total Column Integrate Hail (kg m-2) + public static Parameter TotalColumnIntegrateHail { get; } = + new Parameter(ParameterCategory.Moisture, 72, "Total Column Integrate Hail", "kg m-2"); + + ///Hail Prepitation Rate (kg m-2 s-1) + public static Parameter HailPrepitationRate { get; } = + new Parameter(ParameterCategory.Moisture, 73, "Hail Prepitation Rate", "kg m-2 s-1"); + + ///Total Column Integrate Graupel (kg m-2) + public static Parameter TotalColumnIntegrateGraupel { get; } = + new Parameter(ParameterCategory.Moisture, 74, "Total Column Integrate Graupel", "kg m-2"); + + ///Graupel (Snow Pellets) Prepitation Rate (kg m-2 s-1) + public static Parameter GraupelPrecipitationRate { get; } = + new Parameter(ParameterCategory.Moisture, 75, "Graupel (Snow Pellets) Prepitation Rate", "kg m-2 s-1"); + + ///Convective Rain Rate (kg m-2 s-1) + public static Parameter ConvectiveRainRate { get; } = + new Parameter(ParameterCategory.Moisture, 76, "Convective Rain Rate", "kg m-2 s-1"); + + ///Large Scale Rain Rate (kg m-2 s-1) + public static Parameter LargeScaleRainRate { get; } = + new Parameter(ParameterCategory.Moisture, 77, "Large Scale Rain Rate", "kg m-2 s-1"); + + ///Total Column Integrate Water (Allcomponents including precipitation) (kg m-2) + public static Parameter TotalColumnIntegrateWater { get; } = + new Parameter(ParameterCategory.Moisture, 78, "Total Column Integrate Water (Allcomponents including precipitation)", "kg m-2"); + + ///Evaporation Rate (kg m-2 s-1) + public static Parameter EvaporationRate { get; } = + new Parameter(ParameterCategory.Moisture, 79, "Evaporation Rate", "kg m-2 s-1"); + + ///Total Condensate (kg kg-1) + public static Parameter TotalCondensate { get; } = + new Parameter(ParameterCategory.Moisture, 80, "Total Condensate", "kg kg-1"); + + ///Total Column-Integrate Condensate (kg m-2) + public static Parameter TotalColumnIntegrateCondensate { get; } = + new Parameter(ParameterCategory.Moisture, 81, "Total Column-Integrate Condensate", "kg m-2"); + + ///Cloud Ice Mixing Ratio (kg kg-1) + public static Parameter CloudIceMixingRatio { get; } = + new Parameter(ParameterCategory.Moisture, 82, "Cloud Ice Mixing Ratio", "kg kg-1"); + + ///Specific Cloud Liquid Water Content (kg kg-1) + public static Parameter SpecificCloudLiquidWaterContent { get; } = + new Parameter(ParameterCategory.Moisture, 83, "Specific Cloud Liquid Water Content", "kg kg-1"); + + ///Specific Cloud Ice Water Content (kg kg-1) + public static Parameter SpecificCloudIceWaterContent { get; } = + new Parameter(ParameterCategory.Moisture, 84, "Specific Cloud Ice Water Content", "kg kg-1"); + + ///Specific Rain Water Content (kg kg-1) + public static Parameter SpecificRainWaterContent { get; } = + new Parameter(ParameterCategory.Moisture, 85, "Specific Rain Water Content", "kg kg-1"); + + ///Specific Snow Water Content (kg kg-1) + public static Parameter SpecificSnowWaterContent { get; } = + new Parameter(ParameterCategory.Moisture, 86, "Specific Snow Water Content", "kg kg-1"); + + ///Stratiform Precipitation Rate (kg m-2 s-1) + public static Parameter StratiformPrecipitationRate { get; } = + new Parameter(ParameterCategory.Moisture, 87, "Stratiform Precipitation Rate", "kg m-2 s-1"); + + ///Categorical Convective Precipitation (Code table 4.222) + public static Parameter CategoricalConvectivePrecipitation { get; } = + new Parameter(ParameterCategory.Moisture, 88, "Categorical Convective Precipitation", ""); + + ///Total Kinematic Moisture Flux (kg kg-1 m s-1) + public static Parameter TotalKinematicMoistureFlux { get; } = + new Parameter(ParameterCategory.Moisture, 90, "Total Kinematic Moisture Flux", "kg kg-1 m s-1"); + + ///U-component (zonal) Kinematic Moisture Flux (kg kg-1 m s-1) + public static Parameter Ucomponent { get; } = + new Parameter(ParameterCategory.Moisture, 91, "U-component (zonal) Kinematic Moisture Flux", "kg kg-1 m s-1"); + + ///V-component (meridional) Kinematic Moisture Flux (kg kg-1 m s-1) + public static Parameter Vcomponent { get; } = + new Parameter(ParameterCategory.Moisture, 92, "V-component (meridional) Kinematic Moisture Flux", "kg kg-1 m s-1"); + + ///Relative Humidity With Respect to Water (%) + public static Parameter RelativeHumidityWithRespectToWater { get; } = + new Parameter(ParameterCategory.Moisture, 93, "Relative Humidity With Respect to Water", "%"); + + ///Relative Humidity With Respect to Ice (%) + public static Parameter RelativeHumidityWithRespectToIce { get; } = + new Parameter(ParameterCategory.Moisture, 94, "Relative Humidity With Respect to Ice", "%"); + + ///Freezing or Frozen Precipitation Rate (kg m-2 s-1) + public static Parameter FreezingOrFrozenPrecipitationRate { get; } = + new Parameter(ParameterCategory.Moisture, 95, "Freezing or Frozen Precipitation Rate", "kg m-2 s-1"); + + ///Mass Density of Rain (kg m-3) + public static Parameter MassDensityOfRain { get; } = + new Parameter(ParameterCategory.Moisture, 96, "Mass Density of Rain", "kg m-3"); + + ///Mass Density of Snow (kg m-3) + public static Parameter MassDensityOfSnow { get; } = + new Parameter(ParameterCategory.Moisture, 97, "Mass Density of Snow", "kg m-3"); + + ///Mass Density of Graupel (kg m-3) + public static Parameter MassDensityOfGraupel { get; } = + new Parameter(ParameterCategory.Moisture, 98, "Mass Density of Graupel", "kg m-3"); + + ///Mass Density of Hail (kg m-3) + public static Parameter MassDensityOfHail { get; } = + new Parameter(ParameterCategory.Moisture, 99, "Mass Density of Hail", "kg m-3"); + + ///Specific Number Concentration of Rain (kg-1) + public static Parameter SpecificNumberConcentrationOfRain { get; } = + new Parameter(ParameterCategory.Moisture, 100, "Specific Number Concentration of Rain", "kg-1"); + + ///Specific Number Concentration of Snow (kg-1) + public static Parameter SpecificNumberConcentrationOfSnow { get; } = + new Parameter(ParameterCategory.Moisture, 101, "Specific Number Concentration of Snow", "kg-1"); + + ///Specific Number Concentration of Graupel (kg-1) + public static Parameter SpecificNumberConcentrationOfGraupel { get; } = + new Parameter(ParameterCategory.Moisture, 102, "Specific Number Concentration of Graupel", "kg-1"); + + ///Specific Number Concentration of Hail (kg-1) + public static Parameter SpecificNumberConcentrationOfHail { get; } = + new Parameter(ParameterCategory.Moisture, 103, "Specific Number Concentration of Hail", "kg-1"); + + ///Number Density of Rain (m-3) + public static Parameter NumberDensityOfRain { get; } = + new Parameter(ParameterCategory.Moisture, 104, "Number Density of Rain", "m-3"); + + ///Number Density of Snow (m-3) + public static Parameter NumberDensityOfSnow { get; } = + new Parameter(ParameterCategory.Moisture, 105, "Number Density of Snow", "m-3"); + + ///Number Density of Graupel (m-3) + public static Parameter NumberDensityOfGraupel { get; } = + new Parameter(ParameterCategory.Moisture, 106, "Number Density of Graupel", "m-3"); + + ///Number Density of Hail (m-3) + public static Parameter NumberDensityOfHail { get; } = + new Parameter(ParameterCategory.Moisture, 107, "Number Density of Hail", "m-3"); + + ///Specific Humidity Tendency due to Parameterizations (kg kg-1 s-1) + public static Parameter SpecificHumidityTendencyDueToParameterizations { get; } = + new Parameter(ParameterCategory.Moisture, 108, "Specific Humidity Tendency due to Parameterizations", "kg kg-1 s-1"); + + ///Mass Density of Liquid Water Coating on Hail Expressed as Mass of Liquid Water per Unit Volume of Air (kg m-3) + public static Parameter MassDensityOfLiquidWaterCoatingOnHail { get; } = + new Parameter(ParameterCategory.Moisture, 109, "Mass Density of Liquid Water Coating on Hail Expressed as Mass of Liquid Water per Unit Volume of Air", "kg m-3"); + + ///Specific Mass of Liquid Water Coating on HailExpressed as Mass of Liquid Water per Unit Mass of Moist Air (kg kg-1) + public static Parameter SpecificMassOfLiquidWaterCoatingOnHail { get; } = + new Parameter(ParameterCategory.Moisture, 110, "Specific Mass of Liquid Water Coating on HailExpressed as Mass of Liquid Water per Unit Mass of Moist Air", "kg kg-1"); + + ///Mass Mixing Ratio of Liquid Water Coating on Hail Expressed as Mass of Liquid Water per Unit Mass of Dry Air (kg kg-1) + public static Parameter MassMixingRatioOfLiquidWaterCoatingOnHail { get; } = + new Parameter(ParameterCategory.Moisture, 111, "Mass Mixing Ratio of Liquid Water Coating on Hail Expressed as Mass of Liquid Water per Unit Mass of Dry Air", "kg kg-1"); + + ///Mass Density of Liquid Water Coating on GraupelExpressed as Mass of Liquid Water per Unit Volume of Air (kg m-3) + public static Parameter MassDensityOfLiquidWaterCoatingOnGraupel { get; } = + new Parameter(ParameterCategory.Moisture, 112, "Mass Density of Liquid Water Coating on GraupelExpressed as Mass of Liquid Water per Unit Volume of Air", "kg m-3"); + + ///Specific Mass of Liquid Water Coating on Graupel Expressed as Mass of Liquid Water per Unit Mass of Moist Air (kg kg-1) + public static Parameter SpecificMassOfLiquidWaterCoatingOnGraupel { get; } = + new Parameter(ParameterCategory.Moisture, 113, "Specific Mass of Liquid Water Coating on Graupel Expressed as Mass of Liquid Water per Unit Mass of Moist Air", "kg kg-1"); + + ///Mass Mixing Ratio of Liquid Water Coating on Graupel Expressed as Mass of Liquid Water per Unit Mass of Dry Air (kg kg-1) + public static Parameter MassMixingRatioOfLiquidWaterCoatingOnGraupel { get; } = + new Parameter(ParameterCategory.Moisture, 114, "Mass Mixing Ratio of Liquid Water Coating on Graupel Expressed as Mass of Liquid Water per Unit Mass of Dry Air", "kg kg-1"); + + ///Mass Density of Liquid Water Coating on Snow Expressed as Mass of Liquid Water per Unit Volume of Air (kg m-3) + public static Parameter MassDensityOfLiquidWaterCoatingOnSnow { get; } = + new Parameter(ParameterCategory.Moisture, 115, "Mass Density of Liquid Water Coating on Snow Expressed as Mass of Liquid Water per Unit Volume of Air", "kg m-3"); + + ///Specific Mass of Liquid Water Coating on Snow Expressed as Mass of Liquid Water per Unit Mass of Moist Air (kg kg-1) + public static Parameter SpecificMassOfLiquidWaterCoatingOnSnow { get; } = + new Parameter(ParameterCategory.Moisture, 116, "Specific Mass of Liquid Water Coating on Snow Expressed as Mass of Liquid Water per Unit Mass of Moist Air", "kg kg-1"); + + ///Mass Mixing Ratio of Liquid Water Coating on Snow Expressed as Mass of Liquid Water per Unit Mass of Dry Air (kg kg-1) + public static Parameter MassMixingRatioOfLiquidWaterCoatingOnSnow { get; } = + new Parameter(ParameterCategory.Moisture, 117, "Mass Mixing Ratio of Liquid Water Coating on Snow Expressed as Mass of Liquid Water per Unit Mass of Dry Air", "kg kg-1"); + + ///Unbalanced Component of Specific Humidity (kg kg-1) + public static Parameter UnbalancedComponentOfSpecificHumidity { get; } = + new Parameter(ParameterCategory.Moisture, 118, "Unbalanced Component of Specific Humidity", "kg kg-1"); + + ///Unbalanced Component of Specific Cloud Liquid Water content (kg kg-1) + public static Parameter UnbalancedComponentOfSpecificCloudLiquidWaterContent { get; } = + new Parameter(ParameterCategory.Moisture, 119, "Unbalanced Component of Specific Cloud Liquid Water content", "kg kg-1"); + + ///Unbalanced Component of Specific Cloud Ice Water content (kg kg-1) + public static Parameter UnbalancedComponentOfSpecificCloudIceWaterContent { get; } = + new Parameter(ParameterCategory.Moisture, 120, "Unbalanced Component of Specific Cloud Ice Water content", "kg kg-1"); + + ///Fraction of Snow Cover (Proportion) + public static Parameter FractionOfSnowCover { get; } = + new Parameter(ParameterCategory.Moisture, 121, "Fraction of Snow Cover", "Proportion"); + + #endregion + + #region Product Discipline 0: Meteorological products, Parameter Category 2: Momentum + + ///Wind direction (from which blowing) (deg true) + public static Parameter WindDirection { get; } = + new Parameter(ParameterCategory.Momentum, 0, "Wind direction (from which blowing)", "deg true"); + + ///Wind speed (m s-1) + public static Parameter WindSpeed { get; } = new Parameter(ParameterCategory.Momentum, 1, "Wind speed", "m s-1"); + + ///u-component of wind (m s-1) + public static Parameter UComponentOfWind { get; } = + new Parameter(ParameterCategory.Momentum, 2, "u-component of wind", "m s-1"); + + ///v-component of wind (m s-1) + public static Parameter VComponentOfWind { get; } = + new Parameter(ParameterCategory.Momentum, 3, "v-component of wind", "m s-1"); + + ///Stream function (m2 s-1) + public static Parameter StreamFunction { get; } = + new Parameter(ParameterCategory.Momentum, 4, "Stream function", "m2 s-1"); + + ///Velocity potential (m2 s-1) + public static Parameter VelocityPotential { get; } = + new Parameter(ParameterCategory.Momentum, 5, "Velocity potential", "m2 s-1"); + + ///Montgomery stream function (m2 s-2) + public static Parameter MontgomeryStreamFunction { get; } = + new Parameter(ParameterCategory.Momentum, 6, "Montgomery stream function", "m2 s-2"); + + ///Sigma coordinate vertical velocity (s-1) + public static Parameter SigmaCoordinateVerticalVelocity { get; } = + new Parameter(ParameterCategory.Momentum, 7, "Sigma coordinate vertical velocity", "s-1"); + + ///Vertical velocity (pressure) (Pa s-1) + public static Parameter VerticalVelocityPressure { get; } = + new Parameter(ParameterCategory.Momentum, 8, "Vertical velocity (pressure)", "Pa s-1"); + + ///Vertical velocity (geometric) (m s-1) + public static Parameter VerticalVelocityGeometric { get; } = + new Parameter(ParameterCategory.Momentum, 9, "Vertical velocity (geometric)", "m s-1"); + + ///Absolute vorticity (s-1) + public static Parameter AbsoluteVorticity { get; } = + new Parameter(ParameterCategory.Momentum, 10, "Absolute vorticity", "s-1"); + + ///Absolute divergence (s-1) + public static Parameter AbsoluteDivergence { get; } = + new Parameter(ParameterCategory.Momentum, 11, "Absolute divergence", "s-1"); + + ///Relative vorticity (s-1) + public static Parameter RelativeVorticity { get; } = + new Parameter(ParameterCategory.Momentum, 12, "Relative vorticity", "s-1"); + + ///Relative divergence (s-1) + public static Parameter RelativeDivergence { get; } = + new Parameter(ParameterCategory.Momentum, 13, "Relative divergence", "s-1"); + + ///Potential vorticity (K m2 kg-1 s-1) + public static Parameter PotentialVorticity { get; } = + new Parameter(ParameterCategory.Momentum, 14, "Potential vorticity", "K m2 kg-1 s-1"); + + ///Vertical u-component shear (s-1) + public static Parameter VerticalUComponentShear { get; } = + new Parameter(ParameterCategory.Momentum, 15, "Vertical u-component shear", "s-1"); + + ///Vertical v-component shear (s-1) + public static Parameter VerticalVComponentShear { get; } = + new Parameter(ParameterCategory.Momentum, 16, "Vertical v-component shear", "s-1"); + + ///Momentum flux, u component (s-1) + public static Parameter MomentumFluxUComponent { get; } = + new Parameter(ParameterCategory.Momentum, 17, "Momentum flux, u component", "s-1"); + + ///Momentum flux, v component (s-1) + public static Parameter MomentumFluxVComponent { get; } = + new Parameter(ParameterCategory.Momentum, 18, "Momentum flux, v component", "s-1"); + + ///Wind mixing energy (J) + public static Parameter WindMixingEnergy { get; } = + new Parameter(ParameterCategory.Momentum, 19, "Wind mixing energy", "J"); + + ///Boundary layer dissipation (W m-2) + public static Parameter BoundaryLayerDissipation { get; } = + new Parameter(ParameterCategory.Momentum, 20, "Boundary layer dissipation", "W m-2"); + + ///Maximum wind speed (m s-1) + public static Parameter MaximumWindSpeed { get; } = + new Parameter(ParameterCategory.Momentum, 21, "Maximum wind speed", "m s-1"); + + ///Wind speed (gust) (m s-1) + public static Parameter WindSpeedGust { get; } = + new Parameter(ParameterCategory.Momentum, 22, "Wind speed (gust)", "m s-1"); + + ///u-component of wind (gust) (m s-1) + public static Parameter UComponentOfWindGust { get; } = + new Parameter(ParameterCategory.Momentum, 23, "u-component of wind (gust)", "m s-1"); + + ///v-component of wind (gust) (m s-1) + public static Parameter VComponentOfWindGust { get; } = + new Parameter(ParameterCategory.Momentum, 24, "v-component of wind (gust)", "m s-1"); + + #endregion + + #region Product Discipline 0: Meteorological products, Parameter Category 3: Mass + + ///Pressure (Pa) + public static Parameter Pressure { get; } = new Parameter(ParameterCategory.Mass, 0, "Pressure", "Pa"); + + ///Pressure reduced to MSL (Pa) + public static Parameter PressureReducedToMsl { get; } = + new Parameter(ParameterCategory.Mass, 1, "Pressure reduced to MSL", "Pa"); + + ///Pressure tendency (Pa s-1) + public static Parameter PressureTendency { get; } = + new Parameter(ParameterCategory.Mass, 2, "Pressure tendency", "Pa s-1"); + + ///ICAO Standard Atmosphere Reference Height (m) + public static Parameter IcaoStandardAtmosphereReferenceHeight { get; } = + new Parameter(ParameterCategory.Mass, 3, "ICAO Standard Atmosphere Reference Height", "m"); + + ///Geopotential (m2 s-2) + public static Parameter Geopotential { get; } = new Parameter(ParameterCategory.Mass, 4, "Geopotential", "m2 s-2"); + + ///Geopotential height (gpm) + public static Parameter GeopotentialHeight { get; } = + new Parameter(ParameterCategory.Mass, 5, "Geopotential height", "gpm"); + + ///Geometric height (m) + public static Parameter GeometricHeight { get; } = new Parameter(ParameterCategory.Mass, 6, "Geometric height", "m"); + + ///Standard deviation of height (m) + public static Parameter StandardDeviationOfHeight { get; } = + new Parameter(ParameterCategory.Mass, 7, "Standard deviation of height", "m"); + + ///Pressure anomaly (Pa) + public static Parameter PressureAnomaly { get; } = new Parameter(ParameterCategory.Mass, 8, "Pressure anomaly", "Pa"); + + ///Geopotential height anomaly (gpm) + public static Parameter GeopotentialHeightAnomaly { get; } = + new Parameter(ParameterCategory.Mass, 9, "Geopotential height anomaly", "gpm"); + + ///Density (kg m-3) + public static Parameter Density { get; } = new Parameter(ParameterCategory.Mass, 10, "Density", "kg m-3"); + + ///Altimeter setting (Pa) + public static Parameter AltimeterSetting { get; } = new Parameter(ParameterCategory.Mass, 11, "Altimeter setting", "Pa"); + + ///Thickness (m) + public static Parameter Thickness { get; } = new Parameter(ParameterCategory.Mass, 12, "Thickness", "m"); + + ///Pressure altitude (m) + public static Parameter PressureAltitude { get; } = new Parameter(ParameterCategory.Mass, 13, "Pressure altitude", "m"); + + ///Density altitude (m) + public static Parameter DensityAltitude { get; } = new Parameter(ParameterCategory.Mass, 14, "Density altitude", "m"); + + #endregion + + #region Product Discipline 0: Meteorological products, Parameter Category 4: Short-wave Radiation + + ///Net short-wave radiation flux (surface) (W m-2) + public static Parameter NetShortWaveRadiationFluxSurface { get; } = new Parameter(ParameterCategory.ShortWaveRadiation, 0, + "Net short-wave radiation flux (surface)", "W m-2"); + + ///Net short-wave radiation flux (top of atmosphere) (W m-2) + public static Parameter NetShortWaveRadiationFlux { get; } = new Parameter(ParameterCategory.ShortWaveRadiation, 1, + "Net short-wave radiation flux (top of atmosphere)", "W m-2"); + + ///Short wave radiation flux (W m-2) + public static Parameter ShortWaveRadiationFlux { get; } = + new Parameter(ParameterCategory.ShortWaveRadiation, 2, "Short wave radiation flux", "W m-2"); + + ///Global radiation flux (W m-2) + public static Parameter GlobalRadiationFlux { get; } = + new Parameter(ParameterCategory.ShortWaveRadiation, 3, "Global radiation flux", "W m-2"); + + ///Brightness temperature (K) + public static Parameter BrightnessTemperature { get; } = + new Parameter(ParameterCategory.ShortWaveRadiation, 4, "Brightness temperature", "K"); + + ///Radiance (with respect to wave number) (W m-1 sr-1) + public static Parameter RadianceWaveNumber { get; } = new Parameter(ParameterCategory.ShortWaveRadiation, 5, + "Radiance (with respect to wave number)", "W m-1 sr-1"); + + ///Radiance (with respect to wave length) (W m-3 sr-1) + public static Parameter RadianceWaveLength { get; } = new Parameter(ParameterCategory.ShortWaveRadiation, 6, + "Radiance (with respect to wave length)", "W m-3 sr-1"); + + #endregion + + #region Product Discipline 0: Meteorological products, Parameter Category 5: Long-wave Radiation + + ///Net long wave radiation flux (surface) (W m-2) + public static Parameter NetLongWaveRadiationFluxSurface { get; } = new Parameter(ParameterCategory.LongWaveRadiation, 0, + "Net long wave radiation flux (surface)", "W m-2"); + + ///Net long wave radiation flux (top of atmosphere) (W m-2) + public static Parameter NetLongWaveRadiationFlux { get; } = new Parameter(ParameterCategory.LongWaveRadiation, 1, + "Net long wave radiation flux (top of atmosphere)", "W m-2"); + + ///Long wave radiation flux (W m-2) + public static Parameter LongWaveRadiationFlux { get; } = + new Parameter(ParameterCategory.LongWaveRadiation, 2, "Long wave radiation flux", "W m-2"); + + #endregion + + #region Product Discipline 0: Meteorological products, Parameter Category 6: Cloud + + ///Cloud Ice (kg m-2) + public static Parameter CloudIce { get; } = new Parameter(ParameterCategory.Cloud, 0, "Cloud Ice", "kg m-2"); + + ///Total cloud cover (%) + public static Parameter TotalCloudCover { get; } = new Parameter(ParameterCategory.Cloud, 1, "Total cloud cover", "%"); + + ///Convective cloud cover (%) + public static Parameter ConvectiveCloudCover { get; } = + new Parameter(ParameterCategory.Cloud, 2, "Convective cloud cover", "%"); + + ///Low cloud cover (%) + public static Parameter LowCloudCover { get; } = new Parameter(ParameterCategory.Cloud, 3, "Low cloud cover", "%"); + + ///Medium cloud cover (%) + public static Parameter MediumCloudCover { get; } = new Parameter(ParameterCategory.Cloud, 4, "Medium cloud cover", "%"); + + ///High cloud cover (%) + public static Parameter HighCloudCover { get; } = new Parameter(ParameterCategory.Cloud, 5, "High cloud cover", "%"); + + ///Cloud water (kg m-2) + public static Parameter CloudWater { get; } = new Parameter(ParameterCategory.Cloud, 6, "Cloud water", "kg m-2"); + + ///Cloud amount (%) + public static Parameter CloudAmount { get; } = new Parameter(ParameterCategory.Cloud, 7, "Cloud amount", "%"); + + ///Cloud type (Code table (4.203)) + public static Parameter CloudType { get; } = new Parameter(ParameterCategory.Cloud, 8, "Cloud type", "Code table (4.203)"); + + ///Thunderstorm maximum tops (m) + public static Parameter ThunderstormMaximumTops { get; } = + new Parameter(ParameterCategory.Cloud, 9, "Thunderstorm maximum tops", "m"); + + ///Thunderstorm coverage (Code table (4.204)) + public static Parameter ThunderstormCoverage { get; } = + new Parameter(ParameterCategory.Cloud, 10, "Thunderstorm coverage", "Code table (4.204)"); + + ///Cloud base (m) + public static Parameter CloudBase { get; } = new Parameter(ParameterCategory.Cloud, 11, "Cloud base", "m"); + + ///Cloud top (m) + public static Parameter CloudTop { get; } = new Parameter(ParameterCategory.Cloud, 12, "Cloud top", "m"); + + ///Ceiling (m) + public static Parameter Ceiling { get; } = new Parameter(ParameterCategory.Cloud, 13, "Ceiling", "m"); + + #endregion + + #region Product Discipline 0: Meteorological products, Parameter Category 7: Thermodynamic Stability Indices + + ///Parcel lifted index (to 500 hPa) (K) + public static Parameter ParcelLiftedIndex { get; } = new Parameter(ParameterCategory.ThermodynamicStabilityIndices, 0, + "Parcel lifted index (to 500 hPa)", "K"); + + ///Best lifted index (to 500 hPa) (K) + public static Parameter BestLiftedIndex { get; } = new Parameter(ParameterCategory.ThermodynamicStabilityIndices, 1, + "Best lifted index (to 500 hPa)", "K"); + + ///K index (K) + public static Parameter KIndex { get; } = + new Parameter(ParameterCategory.ThermodynamicStabilityIndices, 2, "K index", "K"); + + ///KO index (K) + public static Parameter KoIndex { get; } = + new Parameter(ParameterCategory.ThermodynamicStabilityIndices, 3, "KO index", "K"); + + ///Total totals index (K) + public static Parameter TotalTotalsIndex { get; } = + new Parameter(ParameterCategory.ThermodynamicStabilityIndices, 4, "Total totals index", "K"); + + ///Sweat index (numeric) + public static Parameter SweatIndex { get; } = + new Parameter(ParameterCategory.ThermodynamicStabilityIndices, 5, "Sweat index", "numeric"); + + ///Convective available potential energy (J kg-1) + public static Parameter ConvectiveAvailablePotentialEnergy { get; } = new Parameter( + ParameterCategory.ThermodynamicStabilityIndices, 6, "Convective available potential energy", "J kg-1"); + + ///Convective inhibition (J kg-1) + public static Parameter ConvectiveInhibition { get; } = new Parameter(ParameterCategory.ThermodynamicStabilityIndices, 7, + "Convective inhibition", "J kg-1"); + + ///Storm relative helicity (J kg-1) + public static Parameter StormRelativeHelicity { get; } = new Parameter(ParameterCategory.ThermodynamicStabilityIndices, 8, + "Storm relative helicity", "J kg-1"); + + ///Energy helicity index (numeric) + public static Parameter EnergyHelicityIndex { get; } = new Parameter(ParameterCategory.ThermodynamicStabilityIndices, 9, + "Energy helicity index", "numeric"); + + #endregion + + #region Product Discipline 0: Meteorological products, Parameter Category 13: Aerosols + + ///Aerosol type (Code table (4.205)) + public static Parameter AerosolType { get; } = + new Parameter(ParameterCategory.Aerosols, 0, "Aerosol type", "Code table (4.205)"); + + #endregion + + #region Product Discipline 0: Meteorological products, Parameter Category 14: Trace Gases + + ///Total ozone (Dobson) + public static Parameter TotalOzone { get; } = new Parameter(ParameterCategory.TraceGases, 0, "Total ozone", "Dobson"); + + #endregion + + #region Product Discipline 0 - Meteorological products, Parameter Category 15: Radar + + ///Base spectrum width (m s-1) + public static Parameter BaseSpectrumWidth { get; } = + new Parameter(ParameterCategory.Radar, 0, "Base spectrum width", "m s-1"); + + ///Base reflectivity (dB) + public static Parameter BaseReflectivity { get; } = new Parameter(ParameterCategory.Radar, 1, "Base reflectivity", "dB"); + + ///Base radial velocity (m s-1) + public static Parameter BaseRadialVelocity { get; } = + new Parameter(ParameterCategory.Radar, 2, "Base radial velocity", "m s-1"); + + ///Vertically-integrated liquid (kg m-1) + public static Parameter VerticallyIntegratedLiquid { get; } = + new Parameter(ParameterCategory.Radar, 3, "Vertically-integrated liquid", "kg m-1"); + + ///Layer-maximum base reflectivity (dB) + public static Parameter LayerMaximumBaseReflectivity { get; } = + new Parameter(ParameterCategory.Radar, 4, "Layer-maximum base reflectivity", "dB"); + + ///Precipitation (kg m-2) + public static Parameter Precipitation { get; } = new Parameter(ParameterCategory.Radar, 5, "Precipitation", "kg m-2"); + + ///Radar spectra (1) (-) + public static Parameter RadarSpectra1 { get; } = new Parameter(ParameterCategory.Radar, 6, "Radar spectra (1)", "-"); + + ///Radar spectra (2) (-) + public static Parameter RadarSpectra2 { get; } = new Parameter(ParameterCategory.Radar, 7, "Radar spectra (2)", "-"); + + ///Radar spectra (3) (-) + public static Parameter RadarSpectra3 { get; } = new Parameter(ParameterCategory.Radar, 8, "Radar spectra (3)", "-"); + + #endregion + + #region Product Discipline 0: Meteorological products, Parameter Category 18: Nuclear/radiology + + ///Air concentration of Caesium 137 (Bq m-3) + public static Parameter AirConcentrationOfCaesium137 { get; } = new Parameter(ParameterCategory.NuclearRadiology, 0, + "Air concentration of Caesium 137", "Bq m-3"); + + ///Air concentration of Iodine 131 (Bq m-3) + public static Parameter AirConcentrationOfIodine131 { get; } = new Parameter(ParameterCategory.NuclearRadiology, 1, + "Air concentration of Iodine 131", "Bq m-3"); + + ///Air concentration of radioactive pollutant (Bq m-3) + public static Parameter AirConcentrationOfRadioactivePollutant { get; } = new Parameter(ParameterCategory.NuclearRadiology, + 2, "Air concentration of radioactive pollutant", "Bq m-3"); + + ///Ground deposition of Caesium 137 (Bq m-2) + public static Parameter GroundDepositionOfCaesium137 { get; } = new Parameter(ParameterCategory.NuclearRadiology, 3, + "Ground deposition of Caesium 137", "Bq m-2"); + + ///Ground deposition of Iodine 131 (Bq m-2) + public static Parameter GroundDepositionOfIodine131 { get; } = new Parameter(ParameterCategory.NuclearRadiology, 4, + "Ground deposition of Iodine 131", "Bq m-2"); + + ///Ground deposition of radioactive pollutant (Bq m-2) + public static Parameter GroundDepositionOfRadioactivePollutant { get; } = new Parameter(ParameterCategory.NuclearRadiology, + 5, "Ground deposition of radioactive pollutant", "Bq m-2"); + + ///Time-integrated air concentration of caesium pollutant (Bq s m-3) + public static Parameter TimeIntegratedAirConcentrationOfCaesiumPollutant { get; } = new Parameter( + ParameterCategory.NuclearRadiology, 6, "Time-integrated air concentration of caesium pollutant", "Bq s m-3"); + + ///Time-integrated air concentration of iodine pollutant (Bq s m-3) + public static Parameter TimeIntegratedAirConcentrationOfIodinePollutant { get; } = new Parameter( + ParameterCategory.NuclearRadiology, 7, "Time-integrated air concentration of iodine pollutant", "Bq s m-3"); + + ///Time-integrated air concentration of radioactive pollutant (Bq s m-3) + public static Parameter TimeIntegratedAirConcentrationOfRadioactivePollutant { get; } = new Parameter( + ParameterCategory.NuclearRadiology, 8, "Time-integrated air concentration of radioactive pollutant", "Bq s m-3"); + + #endregion + + #region Product Discipline 0: Meteorological products, Parameter Category 19: Physical atmospheric properties + + ///Visibility (m) + public static Parameter Visibility { get; } = + new Parameter(ParameterCategory.PhysicalAtmosphericProperties, 0, "Visibility", "m"); + + ///Albedo (%) + public static Parameter Albedo { get; } = new Parameter(ParameterCategory.PhysicalAtmosphericProperties, 1, "Albedo", "%"); + + ///Thunderstorm probability (%) + public static Parameter ThunderstormProbability { get; } = new Parameter(ParameterCategory.PhysicalAtmosphericProperties, + 2, "Thunderstorm probability", "%"); + + ///mixed layer depth (m) + public static Parameter MixedLayerDepth { get; } = + new Parameter(ParameterCategory.PhysicalAtmosphericProperties, 3, "mixed layer depth", "m"); + + ///Volcanic ash (Code table (4.206)) + public static Parameter VolcanicAsh { get; } = new Parameter(ParameterCategory.PhysicalAtmosphericProperties, 4, + "Volcanic ash", "Code table (4.206)"); + + ///Icing top (m) + public static Parameter IcingTop { get; } = + new Parameter(ParameterCategory.PhysicalAtmosphericProperties, 5, "Icing top", "m"); + + ///Icing base (m) + public static Parameter IcingBase { get; } = + new Parameter(ParameterCategory.PhysicalAtmosphericProperties, 6, "Icing base", "m"); + + ///Icing (Code table (4.207)) + public static Parameter Icing { get; } = + new Parameter(ParameterCategory.PhysicalAtmosphericProperties, 7, "Icing", "Code table (4.207)"); + + ///Turbulence top (m) + public static Parameter TurbulenceTop { get; } = + new Parameter(ParameterCategory.PhysicalAtmosphericProperties, 8, "Turbulence top", "m"); + + ///Turbulence base (m) + public static Parameter TurbulenceBase { get; } = + new Parameter(ParameterCategory.PhysicalAtmosphericProperties, 9, "Turbulence base", "m"); + + ///Turbulence (Code table (4.208)) + public static Parameter Turbulence { get; } = new Parameter(ParameterCategory.PhysicalAtmosphericProperties, 10, + "Turbulence", "Code table (4.208)"); + + ///Turbulent kinetic energy (J kg-1) + public static Parameter TurbulentKineticEnergy { get; } = new Parameter(ParameterCategory.PhysicalAtmosphericProperties, + 11, "Turbulent kinetic energy", "J kg-1"); + + ///Planetary boundary layer regime (Code table (4.209)) + public static Parameter PlanetaryBoundaryLayerRegime { get; } = new Parameter( + ParameterCategory.PhysicalAtmosphericProperties, 12, "Planetary boundary layer regime", "Code table (4.209)"); + + ///Contrail intensity (Code table (4.210)) + public static Parameter ContrailIntensity { get; } = new Parameter(ParameterCategory.PhysicalAtmosphericProperties, 13, + "Contrail intensity", "Code table (4.210)"); + + ///Contrail engine type (Code table (4.211)) + public static Parameter ContrailEngineType { get; } = new Parameter(ParameterCategory.PhysicalAtmosphericProperties, 14, + "Contrail engine type", "Code table (4.211)"); + + ///Contrail top (m) + public static Parameter ContrailTop { get; } = + new Parameter(ParameterCategory.PhysicalAtmosphericProperties, 15, "Contrail top", "m"); + + ///Contrail (base) + public static Parameter Contrail { get; } = + new Parameter(ParameterCategory.PhysicalAtmosphericProperties, 16, "Contrail", "base"); + + #endregion + + #region Product Discipline 0: Meteorological products, ParameterCategory 20: Atmospheric chemical Constituents + + public static Parameter MassDensityConcentration { get; } = new( + ParameterCategory.AtmosphericChemicalConstituents, 0, "Mass Density (Concentration)", "kg m-3"); + + public static Parameter ColumnIntegratedMassDensitySeeNote1 { get; } = new( + ParameterCategory.AtmosphericChemicalConstituents, 1, "Column-Integrated Mass Density (See Note 1)", + "kg m-2"); + + public static Parameter MassMixingRatioMassFractionInAir { get; } = new( + ParameterCategory.AtmosphericChemicalConstituents, 2, "Mass Mixing Ratio (Mass Fraction in Air)", + "kg kg-1"); + + public static Parameter AtmosphereEmissionMassFlux { get; } = new( + ParameterCategory.AtmosphericChemicalConstituents, 3, "Atmosphere Emission Mass Flux", "kg m-2s-1"); + + public static Parameter AtmosphereNetProductionMassFlux { get; } = new( + ParameterCategory.AtmosphericChemicalConstituents, 4, "Atmosphere Net Production Mass Flux", "kg m-2s-1"); + + public static Parameter AtmosphereNetProductionAndEmisionMassFlux { get; } = new( + ParameterCategory.AtmosphericChemicalConstituents, 5, "Atmosphere Net Production And Emision Mass Flux", + "kg m-2s-1"); + + public static Parameter SurfaceDryDepositionMassFlux { get; } = new( + ParameterCategory.AtmosphericChemicalConstituents, 6, "Surface Dry Deposition Mass Flux", "kg m-2s-1"); + + public static Parameter SurfaceWetDepositionMassFlux { get; } = new( + ParameterCategory.AtmosphericChemicalConstituents, 7, "Surface Wet Deposition Mass Flux", "kg m-2s-1"); + + public static Parameter AtmosphereReEmissionMassFlux { get; } = new( + ParameterCategory.AtmosphericChemicalConstituents, 8, "Atmosphere Re-Emission Mass Flux", "kg m-2s-1"); + + public static Parameter WetDepositionByLargeScalePrecipitationMassFlux { get; } = new( + ParameterCategory.AtmosphericChemicalConstituents, 9, + "Wet Deposition by Large-Scale Precipitation Mass Flux", "kg m-2s-1"); + + public static Parameter WetDepositionByConvectivePrecipitationMassFlux { get; } = new( + ParameterCategory.AtmosphericChemicalConstituents, 10, + "Wet Deposition by Convective Precipitation Mass Flux", "kg m-2s-1"); + + public static Parameter SedimentationMassFlux { get; } = + new(ParameterCategory.AtmosphericChemicalConstituents, 11, "Sedimentation Mass Flux", "kg m-2s-1"); + + public static Parameter DryDepositionMassFlux { get; } = + new(ParameterCategory.AtmosphericChemicalConstituents, 12, "Dry Deposition Mass Flux", "kg m-2s-1"); + + public static Parameter TransferFromHydrophobicToHydrophilic { get; } = new( + ParameterCategory.AtmosphericChemicalConstituents, 13, "Transfer From Hydrophobic to Hydrophilic", + "kg kg-1s-1"); + + public static Parameter TransferFromSo2SulphurDioxideToSo4Sulphate { get; } = new( + ParameterCategory.AtmosphericChemicalConstituents, 14, + "Transfer From SO2 (Sulphur Dioxide) to SO4 (Sulphate)", "kg kg-1s-1"); + + public static Parameter DryDepositionVelocity { get; } = + new(ParameterCategory.AtmosphericChemicalConstituents, 15, "Dry deposition velocity", "m s-1"); + + public static Parameter MassMixingRatioWithRespectToDryAir { get; } = new( + ParameterCategory.AtmosphericChemicalConstituents, 16, "Mass mixing ratio with respect to dry air", + "kg kg-1"); + + public static Parameter MassMixingRatioWithRespectToWetAir { get; } = new( + ParameterCategory.AtmosphericChemicalConstituents, 17, "Mass mixing ratio with respect to wet air", + "kg kg-1"); + + public static Parameter AmountInAtmosphere { get; } = new(ParameterCategory.AtmosphericChemicalConstituents, + 50, "Amount in Atmosphere", "mol"); + + public static Parameter ConcentrationInAir { get; } = new(ParameterCategory.AtmosphericChemicalConstituents, + 51, "Concentration In Air", "mol m-3"); + + public static Parameter VolumeMixingRatioFractionInAir { get; } = new( + ParameterCategory.AtmosphericChemicalConstituents, 52, "Volume Mixing Ratio (Fraction in Air)", + "mol mol-1"); + + public static Parameter ChemicalGrossProductionRateOfConcentration { get; } = new( + ParameterCategory.AtmosphericChemicalConstituents, 53, "Chemical Gross Production Rate of Concentration", + "mol m-3s-1"); + + public static Parameter ChemicalGrossDestructionRateOfConcentration { get; } = new( + ParameterCategory.AtmosphericChemicalConstituents, 54, "Chemical Gross Destruction Rate of Concentration", + "mol m-3s-1"); + + public static Parameter SurfaceFlux { get; } = new(ParameterCategory.AtmosphericChemicalConstituents, 55, + "Surface Flux", "mol m-2s-1"); + + public static Parameter ChangesOfAmountInAtmosphereSeeNote1 { get; } = new( + ParameterCategory.AtmosphericChemicalConstituents, 56, "Changes Of Amount in Atmosphere (See Note 1)", + "mol s-1"); + + public static Parameter TotalYearlyAverageBurdenOfTheAtmosphere { get; } = new( + ParameterCategory.AtmosphericChemicalConstituents, 57, "Total Yearly Average Burden of The Atmosphere>", + "mol"); + + public static Parameter TotalYearlyAverageAtmosphericLossSeeNote1 { get; } = new( + ParameterCategory.AtmosphericChemicalConstituents, 58, "Total Yearly Average Atmospheric Loss (See Note 1)", + "mol s-1"); + + public static Parameter AerosolNumberConcentrationSeeNote2 { get; } = new( + ParameterCategory.AtmosphericChemicalConstituents, 59, "Aerosol Number Concentration (See Note 2)", "m-3"); + + public static Parameter AerosolSpecificNumberConcentrationSeeNote2 { get; } = new( + ParameterCategory.AtmosphericChemicalConstituents, 60, "Aerosol Specific Number Concentration (See Note 2)", + "kg-1"); + + public static Parameter MaximumOfMassDensitySeeNote1 { get; } = new( + ParameterCategory.AtmosphericChemicalConstituents, 61, "Maximum of Mass Density (See Note 1)", "kg m-3"); + + public static Parameter HeightOfMassDensity { get; } = new(ParameterCategory.AtmosphericChemicalConstituents, + 62, "Height of Mass Density", "m"); + + public static Parameter ColumnAveragedMassDensityInLayer { get; } = new( + ParameterCategory.AtmosphericChemicalConstituents, 63, "Column-Averaged Mass Density in Layer", "kg m-3"); + + public static Parameter MoleFractionWithRespectToDryAir { get; } = new( + ParameterCategory.AtmosphericChemicalConstituents, 64, "Mole fraction with respect to dry air", + "mol mol-1"); + + public static Parameter MoleFractionWithRespectToWetAir { get; } = new( + ParameterCategory.AtmosphericChemicalConstituents, 65, "Mole fraction with respect to wet air", + "mol mol-1"); + + public static Parameter ColumnintegratedIncloudScavengingRateByPrecipitation { get; } = new( + ParameterCategory.AtmosphericChemicalConstituents, 66, + "Column-integrated in-cloud scavenging rate by precipitation", "kg m-2 s-1"); + + public static Parameter ColumnintegratedBelowcloudScavengingRateByPrecipitation { get; } = new( + ParameterCategory.AtmosphericChemicalConstituents, 67, + "Column-integrated below-cloud scavenging rate by precipitation", "kg m-2 s-1"); + + public static Parameter ColumnintegratedReleaseRateFromEvaporatingPrecipitation { get; } = new( + ParameterCategory.AtmosphericChemicalConstituents, 68, + "Column-integrated release rate from evaporating precipitation", "kg m-2 s-1"); + + public static Parameter ColumnintegratedIncloudScavengingRateByLargescalePrecipitation { get; } = new( + ParameterCategory.AtmosphericChemicalConstituents, 69, + "Column-integrated in-cloud scavenging rate by large-scale precipitation", "kg m-2 s-1"); + + public static Parameter ColumnintegratedBelowcloudScavengingRateByLargescalePrecipitation { get; } = new( + ParameterCategory.AtmosphericChemicalConstituents, 70, + "Column-integrated below-cloud scavenging rate by large-scale precipitation", "kg m-2 s-1"); + + public static Parameter ColumnintegratedReleaseRateFromEvaporatingLargescalePrecipitation { get; } = new( + ParameterCategory.AtmosphericChemicalConstituents, 71, + "Column-integrated release rate from evaporating large-scale precipitation", "kg m-2 s-1"); + + public static Parameter ColumnintegratedIncloudScavengingRateByConvectivePrecipitation { get; } = new( + ParameterCategory.AtmosphericChemicalConstituents, 72, + "Column-integrated in-cloud scavenging rate by convective precipitation", "kg m-2 s-1"); + + public static Parameter ColumnintegratedBelowcloudScavengingRateByConvectivePrecipitation { get; } = new( + ParameterCategory.AtmosphericChemicalConstituents, 73, + "Column-integrated below-cloud scavenging rate by convective precipitation", "kg m-2 s-1"); + + public static Parameter ColumnintegratedReleaseRateFromEvaporatingConvectivePrecipitation { get; } = new( + ParameterCategory.AtmosphericChemicalConstituents, 74, + "Column-integrated release rate from evaporating convective precipitation", "kg m-2 s-1"); + + public static Parameter WildfireFlux { get; } = new(ParameterCategory.AtmosphericChemicalConstituents, 75, + "Wildfire flux", "kg m-2 s-1"); + + public static Parameter EmissionRate { get; } = new(ParameterCategory.AtmosphericChemicalConstituents, 76, + "Emission Rate", "kg kg-1 s-1"); + + public static Parameter SurfaceEmissionFlux { get; } = new(ParameterCategory.AtmosphericChemicalConstituents, + 77, "Surface Emission flux", "kg m-2 s-1"); + + public static Parameter SurfaceAreaDensityAerosol { get; } = new( + ParameterCategory.AtmosphericChemicalConstituents, 100, "Surface Area Density (Aerosol)", "m-1"); + + public static Parameter VerticalVisualRange { get; } = new(ParameterCategory.AtmosphericChemicalConstituents, + 101, "Vertical Visual Range", "m"); + + public static Parameter AerosolOpticalThickness { get; } = new( + ParameterCategory.AtmosphericChemicalConstituents, 102, "Aerosol Optical Thickness", "Numeric"); + + public static Parameter SingleScatteringAlbedo { get; } = + new(ParameterCategory.AtmosphericChemicalConstituents, 103, "Single Scattering Albedo", "Numeric"); + + public static Parameter AsymmetryFactor { get; } = new(ParameterCategory.AtmosphericChemicalConstituents, 104, + "Asymmetry Factor", "Numeric"); + + public static Parameter AerosolExtinctionCoefficient { get; } = new( + ParameterCategory.AtmosphericChemicalConstituents, 105, "Aerosol Extinction Coefficient", "m-1"); + + public static Parameter AerosolAbsorptionCoefficient { get; } = new( + ParameterCategory.AtmosphericChemicalConstituents, 106, "Aerosol Absorption Coefficient", "m-1"); + + public static Parameter AerosolLidarBackscatterFromSatellite { get; } = new( + ParameterCategory.AtmosphericChemicalConstituents, 107, "Aerosol Lidar Backscatter from Satellite", + "m-1sr-1"); + + public static Parameter AerosolLidarBackscatterFromTheGround { get; } = new( + ParameterCategory.AtmosphericChemicalConstituents, 108, "Aerosol Lidar Backscatter from the Ground", + "m-1sr-1"); + + public static Parameter AerosolLidarExtinctionFromSatellite { get; } = new( + ParameterCategory.AtmosphericChemicalConstituents, 109, "Aerosol Lidar Extinction from Satellite", "m-1"); + + public static Parameter AerosolLidarExtinctionFromTheGround { get; } = new( + ParameterCategory.AtmosphericChemicalConstituents, 110, "Aerosol Lidar Extinction from the Ground", "m-1"); + + public static Parameter AngstromExponent { get; } = new(ParameterCategory.AtmosphericChemicalConstituents, 111, + "Angstrom Exponent", "Numeric"); + + public static Parameter ScatteringAerosolOpticalThickness { get; } = new( + ParameterCategory.AtmosphericChemicalConstituents, 112, "Scattering Aerosol Optical Thickness", "Numeric"); + + #endregion + + #region Product Discipline 0: Meteorological products, Parameter Category 253: ASCII character string + + ///Arbitrary text string CCITTIA5 + public static Parameter ArbitraryTextStringCcittia5 { get; } = + new Parameter(ParameterCategory.CcittIa5String, 0, "Arbitrary text string CCITTIA5", ""); + + #endregion + + #region Product Discipline 1: Hydrologic products, Parameter Category 0: Hydrology basic products + + ///Flash flood guidance (Encoded as an accumulation over a floating subinterval of time between the reference time and valid time) (kg m-2) + public static Parameter FlashFloodGuidance { get; } = new Parameter(ParameterCategory.HydrologyBasicProducts, 0, + "Flash flood guidance (Encoded as an accumulation over a floating subinterval of time between the reference time and valid time)", + "kg m-2"); + + ///Flash flood runoff (Encoded as an accumulation over a floating subinterval of time) (kg m-2) + public static Parameter FlashFloodRunoff { get; } = new Parameter(ParameterCategory.HydrologyBasicProducts, 1, + "Flash flood runoff (Encoded as an accumulation over a floating subinterval of time)", "kg m-2"); + + ///Remotely sensed snow cover (code table 4.215) + public static Parameter RemotelySensedSnowCover { get; } = new Parameter(ParameterCategory.HydrologyBasicProducts, 2, + "Remotely sensed snow cover (code table 4.215)", ""); + + ///Elevation of snow covered terrain (code table 4.216) + public static Parameter ElevationOfSnowCoveredTerrain { get; } = new Parameter(ParameterCategory.HydrologyBasicProducts, 3, + "Elevation of snow covered terrain (code table 4.216)", ""); + + ///Snow water equivalent percent of normal (%) + public static Parameter SnowWaterEquivalentPercentOfNormal { get; } = + new Parameter(ParameterCategory.HydrologyBasicProducts, 4, "Snow water equivalent percent of normal", "%"); + + #endregion + + #region Product Discipline 1: Hydrologic products, Parameter Category 1: Hydrology probabilities + + ///Conditional percent precipitation amount fractile for an overall period (kg m-2(Encoded as an accumulation).) + public static Parameter ConditionalPercentPrecipitationAmountFractileForAnOverallPeriod { get; } = new Parameter( + ParameterCategory.HydrologyProbabilities, 0, "Conditional percent precipitation amount fractile for an overall period", + "kg m-2(Encoded as an accumulation)."); + + ///Percent precipitation in a sub-period of an overall period (Encoded as per cent accumulation over the sub-period) (%) + public static Parameter PercentPrecipitationInASubPeriodOfAnOverallPeriod { get; } = new Parameter( + ParameterCategory.HydrologyProbabilities, 1, + "Percent precipitation in a sub-period of an overall period (Encoded as per cent accumulation over the sub-period)", + "%"); + + ///Probability of 0.01 inch of precipitation (POP) (%) + public static Parameter ProbabilityOf001InchOfPrecipitationPop { get; } = + new Parameter(ParameterCategory.HydrologyProbabilities, 2, "Probability of 0.01 inch of precipitation (POP)", "%"); + + #endregion + + #region Product Discipline 2: Land surface products, Parameter Category 0: Vegetation/Biomass + + ///Land cover (1=land, 2=sea) (Proportion) + public static Parameter LandCover { get; } = + new Parameter(ParameterCategory.VegetationBiomass, 0, "Land cover (1=land, 2=sea)", "Proportion"); + + ///Surface roughness (m) + public static Parameter SurfaceRoughness { get; } = + new Parameter(ParameterCategory.VegetationBiomass, 1, "Surface roughness", "m"); + + ///Soil temperature + public static Parameter SoilTemperature { get; } = + new Parameter(ParameterCategory.VegetationBiomass, 2, "Soil temperature", ""); + + ///Soil moisture content (kg m-2) + public static Parameter SoilMoistureContent { get; } = + new Parameter(ParameterCategory.VegetationBiomass, 3, "Soil moisture content", "kg m-2"); + + ///Vegetation (%) + public static Parameter Vegetation { get; } = new Parameter(ParameterCategory.VegetationBiomass, 4, "Vegetation", "%"); + + ///Water runoff (kg m-2) + public static Parameter WaterRunoff { get; } = + new Parameter(ParameterCategory.VegetationBiomass, 5, "Water runoff", "kg m-2"); + + ///Evapotranspiration (kg-2 s-1) + public static Parameter Evapotranspiration { get; } = + new Parameter(ParameterCategory.VegetationBiomass, 6, "Evapotranspiration", "kg-2 s-1"); + + ///Model terrain height (m) + public static Parameter ModelTerrainHeight { get; } = + new Parameter(ParameterCategory.VegetationBiomass, 7, "Model terrain height", "m"); + + ///Land use (Code table (4.212)) + public static Parameter LandUse { get; } = + new Parameter(ParameterCategory.VegetationBiomass, 8, "Land use", "Code table (4.212)"); + + #endregion + + #region Product Discipline 2: Land surface products, Parameter Category 3: Soil Products + + ///Soil type (Code table (4.213)) + public static Parameter SoilType { get; } = + new Parameter(ParameterCategory.SoilProducts, 0, "Soil type", "Code table (4.213)"); + + ///Upper layer soil temperature (K) + public static Parameter UpperLayerSoilTemperature { get; } = + new Parameter(ParameterCategory.SoilProducts, 1, "Upper layer soil temperature", "K"); + + ///Upper layer soil moisture (kg m-3) + public static Parameter UpperLayerSoilMoisture { get; } = + new Parameter(ParameterCategory.SoilProducts, 2, "Upper layer soil moisture", "kg m-3"); + + ///Lower layer soil moisture (kg m-3) + public static Parameter LowerLayerSoilMoisture { get; } = + new Parameter(ParameterCategory.SoilProducts, 3, "Lower layer soil moisture", "kg m-3"); + + ///Bottom layer soil temperature (K) + public static Parameter BottomLayerSoilTemperature { get; } = + new Parameter(ParameterCategory.SoilProducts, 4, "Bottom layer soil temperature", "K"); + + #endregion + + #region Product Discipline 3: Space products, Parameter Category 0: Image format products + + ///Scaled radiance (numeric) + public static Parameter ScaledRadiance { get; } = + new Parameter(ParameterCategory.ImageFormatProducts, 0, "Scaled radiance", "numeric"); + + ///Scaled albedo (numeric) + public static Parameter ScaledAlbedo { get; } = + new Parameter(ParameterCategory.ImageFormatProducts, 1, "Scaled albedo", "numeric"); + + ///Scaled brightness temperature (numeric) + public static Parameter ScaledBrightnessTemperature { get; } = new Parameter(ParameterCategory.ImageFormatProducts, 2, + "Scaled brightness temperature", "numeric"); + + ///Scaled precipitable water (numeric) + public static Parameter ScaledPrecipitableWater { get; } = + new Parameter(ParameterCategory.ImageFormatProducts, 3, "Scaled precipitable water", "numeric"); + + ///Scaled lifted index (numeric) + public static Parameter ScaledLiftedIndex { get; } = + new Parameter(ParameterCategory.ImageFormatProducts, 4, "Scaled lifted index", "numeric"); + + ///Scaled cloud top pressure (numeric) + public static Parameter ScaledCloudTopPressure { get; } = + new Parameter(ParameterCategory.ImageFormatProducts, 5, "Scaled cloud top pressure", "numeric"); + + ///Scaled skin temperature (numeric) + public static Parameter ScaledSkinTemperature { get; } = + new Parameter(ParameterCategory.ImageFormatProducts, 6, "Scaled skin temperature", "numeric"); + + ///Cloud mask (Code table 4.217) + public static Parameter CloudMask { get; } = + new Parameter(ParameterCategory.ImageFormatProducts, 7, "Cloud mask", "Code table 4.217"); + + #endregion + + #region Product Discipline 3: Space products, Parameter Category 1: Quantitative products + + ///Estimated precipitation (kg m-2) + public static Parameter EstimatedPrecipitation { get; } = + new Parameter(ParameterCategory.QuantitativeProducts, 0, "Estimated precipitation", "kg m-2"); + + #endregion + + #region Product Discipline 10: Oceanographic products, Parameter Category 0: Waves + + ///Wave spectra (1) (-) + public static Parameter WaveSpectra1 { get; } = new Parameter(ParameterCategory.Waves, 0, "Wave spectra (1)", "-"); + + ///Wave spectra (2) (-) + public static Parameter WaveSpectra2 { get; } = new Parameter(ParameterCategory.Waves, 1, "Wave spectra (2)", "-"); + + ///Wave spectra (3) (-) + public static Parameter WaveSpectra3 { get; } = new Parameter(ParameterCategory.Waves, 2, "Wave spectra (3)", "-"); + + ///Significant height of combined wind waves and swell (m) + public static Parameter SignificantHeightOfCombinedWindWavesAndSwell { get; } = new Parameter(ParameterCategory.Waves, 3, + "Significant height of combined wind waves and swell", "m"); + + ///Direction of wind waves (Degree true) + public static Parameter DirectionOfWindWaves { get; } = + new Parameter(ParameterCategory.Waves, 4, "Direction of wind waves", "Degree true"); + + ///Significant height of wind waves (m) + public static Parameter SignificantHeightOfWindWaves { get; } = + new Parameter(ParameterCategory.Waves, 5, "Significant height of wind waves", "m"); + + ///Mean period of wind waves (s) + public static Parameter MeanPeriodOfWindWaves { get; } = + new Parameter(ParameterCategory.Waves, 6, "Mean period of wind waves", "s"); + + ///Direction of swell waves (Degree true) + public static Parameter DirectionOfSwellWaves { get; } = + new Parameter(ParameterCategory.Waves, 7, "Direction of swell waves", "Degree true"); + + ///Significant height of swell waves (m) + public static Parameter SignificantHeightOfSwellWaves { get; } = + new Parameter(ParameterCategory.Waves, 8, "Significant height of swell waves", "m"); + + ///Mean period of swell waves (s) + public static Parameter MeanPeriodOfSwellWaves { get; } = + new Parameter(ParameterCategory.Waves, 9, "Mean period of swell waves", "s"); + + ///Primary wave direction (Degree true) + public static Parameter PrimaryWaveDirection { get; } = + new Parameter(ParameterCategory.Waves, 10, "Primary wave direction", "Degree true"); + + ///Primary wave mean period (s) + public static Parameter PrimaryWaveMeanPeriod { get; } = + new Parameter(ParameterCategory.Waves, 11, "Primary wave mean period", "s"); + + ///Secondary wave direction (Degree true) + public static Parameter SecondaryWaveDirection { get; } = + new Parameter(ParameterCategory.Waves, 12, "Secondary wave direction", "Degree true"); + + ///Secondary wave mean period (s) + public static Parameter SecondaryWaveMeanPeriod { get; } = + new Parameter(ParameterCategory.Waves, 13, "Secondary wave mean period", "s"); + + #endregion + + #region Product Discipline 10: Oceanographic products, Parameter Category 1: Currents + + ///Current direction (Degree true) + public static Parameter CurrentDirection { get; } = + new Parameter(ParameterCategory.Currents, 0, "Current direction", "Degree true"); + + ///Current speed (m s-1) + public static Parameter CurrentSpeed { get; } = new Parameter(ParameterCategory.Currents, 1, "Current speed", "m s-1"); + + ///u-component of current (m s-1) + public static Parameter UComponentOfCurrent { get; } = + new Parameter(ParameterCategory.Currents, 2, "u-component of current", "m s-1"); + + ///v-component of current (m s-1) + public static Parameter VComponentOfCurrent { get; } = + new Parameter(ParameterCategory.Currents, 3, "v-component of current", "m s-1"); + + #endregion + + #region Product Discipline 10: Oceanographic products, Parameter Category 2: Ice + + ///Ice cover (Proportion) + public static Parameter IceCover { get; } = new Parameter(ParameterCategory.Ice, 0, "Ice cover", "Proportion"); + + ///Ice thickness (m) + public static Parameter IceThickness { get; } = new Parameter(ParameterCategory.Ice, 1, "Ice thickness", "m"); + + ///Direction of ice drift (Degree true) + public static Parameter DirectionOfIceDrift { get; } = + new Parameter(ParameterCategory.Ice, 2, "Direction of ice drift", "Degree true"); + + ///Speed of ice drift (m s-1) + public static Parameter SpeedOfIceDrift { get; } = new Parameter(ParameterCategory.Ice, 3, "Speed of ice drift", "m s-1"); + + ///u-component of ice drift (m s-1) + public static Parameter UComponentOfIceDrift { get; } = + new Parameter(ParameterCategory.Ice, 4, "u-component of ice drift", "m s-1"); + + ///v-component of ice drift (m s-1) + public static Parameter VComponentOfIceDrift { get; } = + new Parameter(ParameterCategory.Ice, 5, "v-component of ice drift", "m s-1"); + + ///Ice growth rate (m s-1) + public static Parameter IceGrowthRate { get; } = new Parameter(ParameterCategory.Ice, 6, "Ice growth rate", "m s-1"); + + ///Ice divergence (s-1) + public static Parameter IceDivergence { get; } = new Parameter(ParameterCategory.Ice, 7, "Ice divergence", "s-1"); + + #endregion + + #region Product Discipline 10: Oceanographic products, Parameter Category 3: Surface Properties + + ///Water temperature (K) + public static Parameter WaterTemperature { get; } = + new Parameter(ParameterCategory.SurfaceProperties, 0, "Water temperature", "K"); + + ///Deviation of sea level from mean (m) + public static Parameter DeviationOfSeaLevelFromMean { get; } = + new Parameter(ParameterCategory.SurfaceProperties, 1, "Deviation of sea level from mean", "m"); + + #endregion + + #region Product Discipline 10: Oceanographic products, Parameter Category 4: Sub-surface Properties + + ///Main thermocline depth (m) + public static Parameter MainThermoclineDepth { get; } = + new Parameter(ParameterCategory.SubSurfaceProperties, 0, "Main thermocline depth", "m"); + + ///Main thermocline anomaly (m) + public static Parameter MainThermoclineAnomaly { get; } = + new Parameter(ParameterCategory.SubSurfaceProperties, 1, "Main thermocline anomaly", "m"); + + ///Transient thermocline depth (m) + public static Parameter TransientThermoclineDepth { get; } = + new Parameter(ParameterCategory.SubSurfaceProperties, 2, "Transient thermocline depth", "m"); + + ///Salinity (kg kg-1) + public static Parameter Salinity { get; } = + new Parameter(ParameterCategory.SubSurfaceProperties, 3, "Salinity", "kg kg-1"); + + #endregion + + public static IReadOnlyDictionary> ParametersByCategory { get; } = + ImmutableList.Empty + .Add(Temperature) + .Add(VirtualTemperature) + .Add(PotentialTemperature) + .Add(PseudoAdiabaticPotentialTemperatureOrEquivalentPotentialTemperature) + .Add(MaximumTemperature) + .Add(MinimumTemperature) + .Add(DewPointTemperature) + .Add(DewPointDepression) + .Add(LapseRate) + .Add(TemperatureAnomaly) + .Add(LatentHeatNetFlux) + .Add(SensibleHeatNetFlux) + .Add(HeatIndex) + .Add(WindChillFactor) + .Add(MinimumDewPointDepression) + .Add(VirtualPotentialTemperature) + .Add(SnowPhaseChangeHeatFlux) + .Add(SkinTemperature) + .Add(SnowTemperature) + .Add(TurbulentTransferCoefficientForHeat) + .Add(TurbulentDiffusionCoefficientForHeat) + .Add(ApparentTemperature) + .Add(TemperatureTendencyDueToShortWaveRadiation) + .Add(TemperatureTendencyDueToLongWaveRadiation) + .Add(TemperatureTendencyDueToShortWaveRadiationClearSky) + .Add(TemperatureTendencyDueToLongWaveRadiationClearSky) + .Add(TemperatureTendencyDueToParameterizations) + .Add(WetBulbTemperature) + .Add(UnbalancedComponentOfTemperature) + .Add(TemperatureAdvection) + .Add(SpecificHumidity) + .Add(RelativeHumidity) + .Add(HumidityMixingRatio) + .Add(PrecipitableWater) + .Add(VaporPressure) + .Add(SaturationDeficit) + .Add(Evaporation) + .Add(PrecipitationRate) + .Add(TotalPrecipitation) + .Add(LargeScalePrecipitationNonConvective) + .Add(ConvectivePrecipitation) + .Add(SnowDepth) + .Add(SnowfallRateWaterEquivalent) + .Add(WaterEquivalentOfAccumulatedSnowDepth) + .Add(ConvectiveSnow) + .Add(LargeScaleSnow) + .Add(SnowMelt) + .Add(SnowAge) + .Add(AbsoluteHumidity) + .Add(PrecipitationType) + .Add(IntegratedLiquidWater) + .Add(Condensate) + .Add(CloudMixingRatio) + .Add(IceWaterMixingRatio) + .Add(RainMixingRatio) + .Add(SnowMixingRatio) + .Add(HorizontalMoistureConvergence) + .Add(MaximumRelativeHumidity) + .Add(MaximumAbsoluteHumidity) + .Add(TotalSnowfall) + .Add(PrecipitableWaterCategory) + .Add(Hail) + .Add(Graupel) + .Add(CategoricalRain) + .Add(CategoricalFreezingRain) + .Add(CategoricalIcePellets) + .Add(CategoricalSnow) + .Add(ConvectivePrecipitationRate) + .Add(HorizontalMoistureDivergence) + .Add(PercentFrozenPrecipitation) + .Add(PotentialEvaporation) + .Add(PotentialEvaporationRate) + .Add(SnowCover) + .Add(RainFractionOfTotalCloudWater) + .Add(RimeFactor) + .Add(TotalColumnIntegratedRain) + .Add(TotalColumnIntegratedSnow) + .Add(LargeScaleWaterPrecipitation) + .Add(ConvectiveWaterPrecipitation) + .Add(TotalWaterPrecipitation) + .Add(TotalSnowPrecipitation) + .Add(TotalColumnWater) + .Add(TotalPrecipitationRate) + .Add(TotalSnowfallRateWaterEquivalent) + .Add(LargeScalePrecipitationRate) + .Add(ConvectiveSnowfallRateWaterEquivalent) + .Add(LargeScaleSnowfallRateWaterEquivalent) + .Add(TotalSnowfallRate) + .Add(ConvectiveSnowfallRate) + .Add(LargeScaleSnowfallRate) + .Add(SnowDepthWaterEquivalent) + .Add(SnowDensity) + .Add(SnowEvaporation) + .Add(TotalColumnIntegratedWaterVapour) + .Add(RainPrecipitationRate) + .Add(SnowPrecipitationRate) + .Add(FreezingRainPrecipitationRate) + .Add(IcePelletsPrecipitationRate) + .Add(TotalColumnIntegrateCloudWater) + .Add(TotalColumnIntegrateCloudIce) + .Add(HailMixingRatio) + .Add(TotalColumnIntegrateHail) + .Add(HailPrepitationRate) + .Add(TotalColumnIntegrateGraupel) + .Add(GraupelPrecipitationRate) + .Add(ConvectiveRainRate) + .Add(LargeScaleRainRate) + .Add(TotalColumnIntegrateWater) + .Add(EvaporationRate) + .Add(TotalCondensate) + .Add(TotalColumnIntegrateCondensate) + .Add(CloudIceMixingRatio) + .Add(SpecificCloudLiquidWaterContent) + .Add(SpecificCloudIceWaterContent) + .Add(SpecificRainWaterContent) + .Add(SpecificSnowWaterContent) + .Add(StratiformPrecipitationRate) + .Add(CategoricalConvectivePrecipitation) + .Add(TotalKinematicMoistureFlux) + .Add(Ucomponent) + .Add(Vcomponent) + .Add(RelativeHumidityWithRespectToWater) + .Add(RelativeHumidityWithRespectToIce) + .Add(FreezingOrFrozenPrecipitationRate) + .Add(MassDensityOfRain) + .Add(MassDensityOfSnow) + .Add(MassDensityOfGraupel) + .Add(MassDensityOfHail) + .Add(SpecificNumberConcentrationOfRain) + .Add(SpecificNumberConcentrationOfSnow) + .Add(SpecificNumberConcentrationOfGraupel) + .Add(SpecificNumberConcentrationOfHail) + .Add(NumberDensityOfRain) + .Add(NumberDensityOfSnow) + .Add(NumberDensityOfGraupel) + .Add(NumberDensityOfHail) + .Add(SpecificHumidityTendencyDueToParameterizations) + .Add(MassDensityOfLiquidWaterCoatingOnHail) + .Add(SpecificMassOfLiquidWaterCoatingOnHail) + .Add(MassMixingRatioOfLiquidWaterCoatingOnHail) + .Add(MassDensityOfLiquidWaterCoatingOnGraupel) + .Add(SpecificMassOfLiquidWaterCoatingOnGraupel) + .Add(MassMixingRatioOfLiquidWaterCoatingOnGraupel) + .Add(MassDensityOfLiquidWaterCoatingOnSnow) + .Add(SpecificMassOfLiquidWaterCoatingOnSnow) + .Add(MassMixingRatioOfLiquidWaterCoatingOnSnow) + .Add(UnbalancedComponentOfSpecificHumidity) + .Add(UnbalancedComponentOfSpecificCloudLiquidWaterContent) + .Add(UnbalancedComponentOfSpecificCloudIceWaterContent) + .Add(FractionOfSnowCover) + .Add(WindDirection) + .Add(WindSpeed) + .Add(UComponentOfWind) + .Add(VComponentOfWind) + .Add(StreamFunction) + .Add(VelocityPotential) + .Add(MontgomeryStreamFunction) + .Add(SigmaCoordinateVerticalVelocity) + .Add(VerticalVelocityPressure) + .Add(VerticalVelocityGeometric) + .Add(AbsoluteVorticity) + .Add(AbsoluteDivergence) + .Add(RelativeVorticity) + .Add(RelativeDivergence) + .Add(PotentialVorticity) + .Add(VerticalUComponentShear) + .Add(VerticalVComponentShear) + .Add(MomentumFluxUComponent) + .Add(MomentumFluxVComponent) + .Add(WindMixingEnergy) + .Add(BoundaryLayerDissipation) + .Add(MaximumWindSpeed) + .Add(WindSpeedGust) + .Add(UComponentOfWindGust) + .Add(VComponentOfWindGust) + .Add(Pressure) + .Add(PressureReducedToMsl) + .Add(PressureTendency) + .Add(IcaoStandardAtmosphereReferenceHeight) + .Add(Geopotential) + .Add(GeopotentialHeight) + .Add(GeometricHeight) + .Add(StandardDeviationOfHeight) + .Add(PressureAnomaly) + .Add(GeopotentialHeightAnomaly) + .Add(Density) + .Add(AltimeterSetting) + .Add(Thickness) + .Add(PressureAltitude) + .Add(DensityAltitude) + .Add(NetShortWaveRadiationFluxSurface) + .Add(NetShortWaveRadiationFlux) + .Add(ShortWaveRadiationFlux) + .Add(GlobalRadiationFlux) + .Add(BrightnessTemperature) + .Add(RadianceWaveNumber) + .Add(RadianceWaveLength) + .Add(NetLongWaveRadiationFluxSurface) + .Add(NetLongWaveRadiationFlux) + .Add(LongWaveRadiationFlux) + .Add(CloudIce) + .Add(TotalCloudCover) + .Add(ConvectiveCloudCover) + .Add(LowCloudCover) + .Add(MediumCloudCover) + .Add(HighCloudCover) + .Add(CloudWater) + .Add(CloudAmount) + .Add(CloudType) + .Add(ThunderstormMaximumTops) + .Add(ThunderstormCoverage) + .Add(CloudBase) + .Add(CloudTop) + .Add(Ceiling) + .Add(ParcelLiftedIndex) + .Add(BestLiftedIndex) + .Add(KIndex) + .Add(KoIndex) + .Add(TotalTotalsIndex) + .Add(SweatIndex) + .Add(ConvectiveAvailablePotentialEnergy) + .Add(ConvectiveInhibition) + .Add(StormRelativeHelicity) + .Add(EnergyHelicityIndex) + .Add(AerosolType) + .Add(TotalOzone) + .Add(BaseSpectrumWidth) + .Add(BaseReflectivity) + .Add(BaseRadialVelocity) + .Add(VerticallyIntegratedLiquid) + .Add(LayerMaximumBaseReflectivity) + .Add(Precipitation) + .Add(RadarSpectra1) + .Add(RadarSpectra2) + .Add(RadarSpectra3) + .Add(AirConcentrationOfCaesium137) + .Add(AirConcentrationOfIodine131) + .Add(AirConcentrationOfRadioactivePollutant) + .Add(GroundDepositionOfCaesium137) + .Add(GroundDepositionOfIodine131) + .Add(GroundDepositionOfRadioactivePollutant) + .Add(TimeIntegratedAirConcentrationOfCaesiumPollutant) + .Add(TimeIntegratedAirConcentrationOfIodinePollutant) + .Add(TimeIntegratedAirConcentrationOfRadioactivePollutant) + .Add(Visibility) + .Add(Albedo) + .Add(ThunderstormProbability) + .Add(MixedLayerDepth) + .Add(VolcanicAsh) + .Add(IcingTop) + .Add(IcingBase) + .Add(Icing) + .Add(TurbulenceTop) + .Add(TurbulenceBase) + .Add(Turbulence) + .Add(TurbulentKineticEnergy) + .Add(PlanetaryBoundaryLayerRegime) + .Add(ContrailIntensity) + .Add(ContrailEngineType) + .Add(ContrailTop) + .Add(Contrail) + .Add(MassDensityConcentration) + .Add(ColumnIntegratedMassDensitySeeNote1) + .Add(MassMixingRatioMassFractionInAir) + .Add(AtmosphereEmissionMassFlux) + .Add(AtmosphereNetProductionMassFlux) + .Add(AtmosphereNetProductionAndEmisionMassFlux) + .Add(SurfaceDryDepositionMassFlux) + .Add(SurfaceWetDepositionMassFlux) + .Add(AtmosphereReEmissionMassFlux) + .Add(WetDepositionByLargeScalePrecipitationMassFlux) + .Add(WetDepositionByConvectivePrecipitationMassFlux) + .Add(TransferFromHydrophobicToHydrophilic) + .Add(TransferFromSo2SulphurDioxideToSo4Sulphate) + .Add(MassMixingRatioWithRespectToDryAir) + .Add(MassMixingRatioWithRespectToWetAir) + .Add(VolumeMixingRatioFractionInAir) + .Add(ChemicalGrossProductionRateOfConcentration) + .Add(ChemicalGrossDestructionRateOfConcentration) + .Add(ChangesOfAmountInAtmosphereSeeNote1) + .Add(TotalYearlyAverageBurdenOfTheAtmosphere) + .Add(TotalYearlyAverageAtmosphericLossSeeNote1) + .Add(AerosolNumberConcentrationSeeNote2) + .Add(AerosolSpecificNumberConcentrationSeeNote2) + .Add(MaximumOfMassDensitySeeNote1) + .Add(ColumnAveragedMassDensityInLayer) + .Add(MoleFractionWithRespectToDryAir) + .Add(MoleFractionWithRespectToWetAir) + .Add(ColumnintegratedIncloudScavengingRateByPrecipitation) + .Add(ColumnintegratedBelowcloudScavengingRateByPrecipitation) + .Add(ColumnintegratedReleaseRateFromEvaporatingPrecipitation) + .Add(ColumnintegratedIncloudScavengingRateByLargescalePrecipitation) + .Add(ColumnintegratedBelowcloudScavengingRateByLargescalePrecipitation) + .Add(ColumnintegratedReleaseRateFromEvaporatingLargescalePrecipitation) + .Add(ColumnintegratedIncloudScavengingRateByConvectivePrecipitation) + .Add(ColumnintegratedBelowcloudScavengingRateByConvectivePrecipitation) + .Add(ColumnintegratedReleaseRateFromEvaporatingConvectivePrecipitation) + .Add(SurfaceAreaDensityAerosol) + .Add(AerosolOpticalThickness) + .Add(AerosolExtinctionCoefficient) + .Add(AerosolAbsorptionCoefficient) + .Add(AerosolLidarBackscatterFromSatellite) + .Add(AerosolLidarBackscatterFromTheGround) + .Add(AerosolLidarExtinctionFromSatellite) + .Add(AerosolLidarExtinctionFromTheGround) + .Add(ScatteringAerosolOpticalThickness) + .Add(ArbitraryTextStringCcittia5) + .Add(FlashFloodGuidance) + .Add(FlashFloodRunoff) + .Add(RemotelySensedSnowCover) + .Add(ElevationOfSnowCoveredTerrain) + .Add(SnowWaterEquivalentPercentOfNormal) + .Add(ConditionalPercentPrecipitationAmountFractileForAnOverallPeriod) + .Add(PercentPrecipitationInASubPeriodOfAnOverallPeriod) + .Add(ProbabilityOf001InchOfPrecipitationPop) + .Add(LandCover) + .Add(SurfaceRoughness) + .Add(SoilTemperature) + .Add(SoilMoistureContent) + .Add(Vegetation) + .Add(WaterRunoff) + .Add(Evapotranspiration) + .Add(ModelTerrainHeight) + .Add(LandUse) + .Add(SoilType) + .Add(UpperLayerSoilTemperature) + .Add(UpperLayerSoilMoisture) + .Add(LowerLayerSoilMoisture) + .Add(BottomLayerSoilTemperature) + .Add(ScaledRadiance) + .Add(ScaledAlbedo) + .Add(ScaledBrightnessTemperature) + .Add(ScaledPrecipitableWater) + .Add(ScaledLiftedIndex) + .Add(ScaledCloudTopPressure) + .Add(ScaledSkinTemperature) + .Add(CloudMask) + .Add(EstimatedPrecipitation) + .Add(WaveSpectra1) + .Add(WaveSpectra2) + .Add(WaveSpectra3) + .Add(SignificantHeightOfCombinedWindWavesAndSwell) + .Add(DirectionOfWindWaves) + .Add(SignificantHeightOfWindWaves) + .Add(MeanPeriodOfWindWaves) + .Add(DirectionOfSwellWaves) + .Add(SignificantHeightOfSwellWaves) + .Add(MeanPeriodOfSwellWaves) + .Add(PrimaryWaveDirection) + .Add(PrimaryWaveMeanPeriod) + .Add(SecondaryWaveDirection) + .Add(SecondaryWaveMeanPeriod) + .Add(CurrentDirection) + .Add(CurrentSpeed) + .Add(UComponentOfCurrent) + .Add(VComponentOfCurrent) + .Add(IceCover) + .Add(IceThickness) + .Add(DirectionOfIceDrift) + .Add(SpeedOfIceDrift) + .Add(UComponentOfIceDrift) + .Add(VComponentOfIceDrift) + .Add(IceGrowthRate) + .Add(IceDivergence) + .Add(WaterTemperature) + .Add(DeviationOfSeaLevelFromMean) + .Add(MainThermoclineDepth) + .Add(MainThermoclineAnomaly) + .Add(TransientThermoclineDepth) + .Add(Salinity) + .GroupBy(c => c.Category) + .ToDictionary(g => g.Key, g => (IReadOnlyCollection) g.ToImmutableList()); +} \ No newline at end of file diff --git a/tmp/Grib2/CodeTables/4_2_ParameterNumber.cs b/tmp/Grib2/CodeTables/4_2_ParameterNumber.cs new file mode 100644 index 0000000..ee01b1f --- /dev/null +++ b/tmp/Grib2/CodeTables/4_2_ParameterNumber.cs @@ -0,0 +1,905 @@ +/* + * This file is part of NGrib. + * + * Copyright © 2020 Nicolas Mangué + * + * NGrib is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * NGrib is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with NGrib. If not, see . + */ + +using System.ComponentModel; + +namespace NGrib.Grib2.CodeTables; + +/// +/// Code Table 4.2: Parameter number by product discipline and parameter category +/// +public enum ParameterNumber +{ + #region Product Discipline 0: Meteorological products, Parameter Category 0: Temperature + + ///Temperature (K) + [Description("Temperature")] Temperature = 0, + + ///Virtual temperature (K) + [Description("Virtual temperature")] VirtualTemperature = 1, + + ///Potential temperature (K) + [Description("Potential temperature")] PotentialTemperature = 2, + + ///Pseudo-adiabatic potential temperature or equivalent potential temperature (K) + [Description("Pseudo-adiabatic potential temperature or equivalent potential temperature")] + PseudoAdiabaticPotentialTemperatureOrEquivalentPotentialTemperature = 3, + + ///Maximum temperature (K) + [Description("Maximum temperature")] MaximumTemperature = 4, + + ///Minimum temperature (K) + [Description("Minimum temperature")] MinimumTemperature = 5, + + ///Dew point temperature (K) + [Description("Dew point temperature")] DewPointTemperature = 6, + + ///Dew point depression (or deficit) (K) + [Description("Dew point depression (or deficit)")] + DewPointDepression = 7, + + ///Lapse rate (K m-1) + [Description("Lapse rate")] LapseRate = 8, + + ///Temperature anomaly (K) + [Description("Temperature anomaly")] TemperatureAnomaly = 9, + + ///Latent heat net flux (W m-2) + [Description("Latent heat net flux")] LatentHeatNetFlux = 10, + + ///Sensible heat net flux (W m-2) + [Description("Sensible heat net flux")] + SensibleHeatNetFlux = 11, + + ///Heat index (K) + [Description("Heat index")] HeatIndex = 12, + + ///Wind chill factor (K) + [Description("Wind chill factor")] WindChillFactor = 13, + + ///Minimum dew point depression (K) + [Description("Minimum dew point depression")] + MinimumDewPointDepression = 14, + + ///Virtual potential temperature (K) + [Description("Virtual potential temperature")] + VirtualPotentialTemperature = 15, + + #endregion + + #region Product Discipline 0: Meteorological products, Parameter Category 1: Moisture + + ///Specific humidity (kg kg-1) + [Description("Specific humidity")] SpecificHumidity = 0, + + ///Relative humidity (%) + [Description("Relative humidity")] RelativeHumidity = 1, + + ///Humidity mixing ratio (kg kg-1) + [Description("Humidity mixing ratio")] HumidityMixingRatio = 2, + + ///Precipitable water (kg m-2) + [Description("Precipitable water")] PrecipitableWater = 3, + + ///Vapor pressure (Pa) + [Description("Vapor pressure")] VaporPressure = 4, + + ///Saturation deficit (Pa) + [Description("Saturation deficit")] SaturationDeficit = 5, + + ///Evaporation (kg m-2) + [Description("Evaporation")] Evaporation = 6, + + ///Precipitation rate (kg m-2 s-1) + [Description("Precipitation rate")] PrecipitationRate = 7, + + ///Total precipitation (kg m-2) + [Description("Total precipitation")] TotalPrecipitation = 8, + + ///Large scale precipitation (non-convective) (kg m-2) + [Description("Large scale precipitation (non-convective)")] + LargeScalePrecipitationNonconvective = 9, + + ///Convective precipitation (kg m-2) + [Description("Convective precipitation")] + ConvectivePrecipitation = 10, + + ///Snow depth (m) + [Description("Snow depth")] SnowDepth = 11, + + ///Snowfall rate water equivalent (kg m-2 s-1) + [Description("Snowfall rate water equivalent")] + SnowfallRateWaterEquivalent = 12, + + ///Water equivalent of accumulated snow depth (kg m-2) + [Description("Water equivalent of accumulated snow depth")] + WaterEquivalentOfAccumulatedSnowDepth = 13, + + ///Convective snow (kg m-2) + [Description("Convective snow")] ConvectiveSnow = 14, + + ///Large scale snow (kg m-2) + [Description("Large scale snow")] LargeScaleSnow = 15, + + ///Snow melt (kg m-2) + [Description("Snow melt")] SnowMelt = 16, + + ///Snow age (day) + [Description("Snow age")] SnowAge = 17, + + ///Absolute humidity (kg m-3) + [Description("Absolute humidity")] AbsoluteHumidity = 18, + + ///Precipitation type (Code table (4.201)) + [Description("Precipitation type")] PrecipitationType = 19, + + ///Integrated liquid water (kg m-2) + [Description("Integrated liquid water")] + IntegratedLiquidWater = 20, + + ///Condensate (kg kg-1) + [Description("Condensate")] Condensate = 21, + + ///Cloud mixing ratio (kg kg-1) + [Description("Cloud mixing ratio")] CloudMixingRatio = 22, + + ///Ice water mixing ratio (kg kg-1) + [Description("Ice water mixing ratio")] + IceWaterMixingRatio = 23, + + ///Rain mixing ratio (kg kg-1) + [Description("Rain mixing ratio")] RainMixingRatio = 24, + + ///Snow mixing ratio (kg kg-1) + [Description("Snow mixing ratio")] SnowMixingRatio = 25, + + ///Horizontal moisture convergence (kg kg-1 s-1) + [Description("Horizontal moisture convergence")] + HorizontalMoistureConvergence = 26, + + ///Maximum relative humidity (%) + [Description("Maximum relative humidity")] + MaximumRelativeHumidity = 27, + + ///Maximum absolute humidity (kg m-3) + [Description("Maximum absolute humidity")] + MaximumAbsoluteHumidity = 28, + + ///Total snowfall (m) + [Description("Total snowfall")] TotalSnowfall = 29, + + ///Precipitable water category (Code table (4.202)) + [Description("Precipitable water category")] + PrecipitableWaterCategory = 30, + + ///Hail (m) + [Description("Hail")] Hail = 31, + + ///Graupel (snow pellets) (kg kg-1) + [Description("Graupel (snow pellets)")] + Graupel = 32, + + #endregion + + #region Product Discipline 0: Meteorological products, Parameter Category 2: Momentum + + ///Wind direction (from which blowing) (deg true) + [Description("Wind direction (from which blowing)")] + WindDirection = 0, + + ///Wind speed (m s-1) + [Description("Wind speed")] WindSpeed = 1, + + ///u-component of wind (m s-1) + [Description("u-component of wind")] UComponentOfWind = 2, + + ///v-component of wind (m s-1) + [Description("v-component of wind")] VComponentOfWind = 3, + + ///Stream function (m2 s-1) + [Description("Stream function")] StreamFunction = 4, + + ///Velocity potential (m2 s-1) + [Description("Velocity potential")] VelocityPotential = 5, + + ///Montgomery stream function (m2 s-2) + [Description("Montgomery stream function")] + MontgomeryStreamFunction = 6, + + ///Sigma coordinate vertical velocity (s-1) + [Description("Sigma coordinate vertical velocity")] + SigmaCoordinateVerticalVelocity = 7, + + ///Vertical velocity (pressure) (Pa s-1) + [Description("Vertical velocity (pressure)")] + VerticalVelocityPressure = 8, + + ///Vertical velocity (geometric) (m s-1) + [Description("Vertical velocity (geometric)")] + VerticalVelocityGeometric = 9, + + ///Absolute vorticity (s-1) + [Description("Absolute vorticity")] AbsoluteVorticity = 10, + + ///Absolute divergence (s-1) + [Description("Absolute divergence")] AbsoluteDivergence = 11, + + ///Relative vorticity (s-1) + [Description("Relative vorticity")] RelativeVorticity = 12, + + ///Relative divergence (s-1) + [Description("Relative divergence")] RelativeDivergence = 13, + + ///Potential vorticity (K m2 kg-1 s-1) + [Description("Potential vorticity")] PotentialVorticity = 14, + + ///Vertical u-component shear (s-1) + [Description("Vertical u-component shear")] + VerticalUComponentShear = 15, + + ///Vertical v-component shear (s-1) + [Description("Vertical v-component shear")] + VerticalVComponentShear = 16, + + ///Momentum flux, u component (s-1) + [Description("Momentum flux, u component")] + MomentumFluxUComponent = 17, + + ///Momentum flux, v component (s-1) + [Description("Momentum flux, v component")] + MomentumFluxVComponent = 18, + + ///Wind mixing energy (J) + [Description("Wind mixing energy")] WindMixingEnergy = 19, + + ///Boundary layer dissipation (W m-2) + [Description("Boundary layer dissipation")] + BoundaryLayerDissipation = 20, + + ///Maximum wind speed (m s-1) + [Description("Maximum wind speed")] MaximumWindSpeed = 21, + + ///Wind speed (gust) (m s-1) + [Description("Wind speed (gust)")] WindSpeedGust = 22, + + ///u-component of wind (gust) (m s-1) + [Description("u-component of wind (gust)")] + UComponentOfWindGust = 23, + + ///v-component of wind (gust) (m s-1) + [Description("v-component of wind (gust)")] + VComponentOfWindGust = 24, + + #endregion + + #region Product Discipline 0: Meteorological products, Parameter Category 3: Mass + + ///Pressure (Pa) + [Description("Pressure")] Pressure = 0, + + ///Pressure reduced to MSL (Pa) + [Description("Pressure reduced to MSL")] + PressureReducedToMsl = 1, + + ///Pressure tendency (Pa s-1) + [Description("Pressure tendency")] PressureTendency = 2, + + ///ICAO Standard Atmosphere Reference Height (m) + [Description("ICAO Standard Atmosphere Reference Height")] + IcaoStandardAtmosphereReferenceHeight = 3, + + ///Geopotential (m2 s-2) + [Description("Geopotential")] Geopotential = 4, + + ///Geopotential height (gpm) + [Description("Geopotential height")] GeopotentialHeight = 5, + + ///Geometric height (m) + [Description("Geometric height")] GeometricHeight = 6, + + ///Standard deviation of height (m) + [Description("Standard deviation of height")] + StandardDeviationOfHeight = 7, + + ///Pressure anomaly (Pa) + [Description("Pressure anomaly")] PressureAnomaly = 8, + + ///Geopotential height anomaly (gpm) + [Description("Geopotential height anomaly")] + GeopotentialHeightAnomaly = 9, + + ///Density (kg m-3) + [Description("Density")] Density = 10, + + ///Altimeter setting (Pa) + [Description("Altimeter setting")] AltimeterSetting = 11, + + ///Thickness (m) + [Description("Thickness")] Thickness = 12, + + ///Pressure altitude (m) + [Description("Pressure altitude")] PressureAltitude = 13, + + ///Density altitude (m) + [Description("Density altitude")] DensityAltitude = 14, + + #endregion + + #region Product Discipline 0: Meteorological products, Parameter Category 4: Short-wave Radiation + + ///Net short-wave radiation flux (surface) (W m-2) + [Description("Net short-wave radiation flux (surface)")] + NetShortWaveRadiationFluxSurface = 0, + + ///Net short-wave radiation flux (top of atmosphere) (W m-2) + [Description("Net short-wave radiation flux (top of atmosphere)")] + NetShortWaveRadiationFlux = 1, + + ///Short wave radiation flux (W m-2) + [Description("Short wave radiation flux")] + ShortWaveRadiationFlux = 2, + + ///Global radiation flux (W m-2) + [Description("Global radiation flux")] GlobalRadiationFlux = 3, + + ///Brightness temperature (K) + [Description("Brightness temperature")] + BrightnessTemperature = 4, + + ///Radiance (with respect to wave number) (W m-1 sr-1) + [Description("Radiance (with respect to wave number)")] + RadianceWaveNumber = 5, + + ///Radiance (with respect to wave length) (W m-3 sr-1) + [Description("Radiance (with respect to wave length)")] + RadianceWaveLength = 6, + + #endregion + + #region Product Discipline 0: Meteorological products, Parameter Category 5: Long-wave Radiation + + ///Net long wave radiation flux (surface) (W m-2) + [Description("Net long wave radiation flux (surface)")] + NetLongWaveRadiationFluxSurface = 0, + + ///Net long wave radiation flux (top of atmosphere) (W m-2) + [Description("Net long wave radiation flux (top of atmosphere)")] + NetLongWaveRadiationFluxTopOfAtmosphere = 1, + + ///Long wave radiation flux (W m-2) + [Description("Long wave radiation flux")] + LongWaveRadiationFlux = 2, + + #endregion + + #region Product Discipline 0: Meteorological products, Parameter Category 6: Cloud + + ///Cloud Ice (kg m-2) + [Description("Cloud Ice")] CloudIce = 0, + + ///Total cloud cover (%) + [Description("Total cloud cover")] TotalCloudCover = 1, + + ///Convective cloud cover (%) + [Description("Convective cloud cover")] + ConvectiveCloudCover = 2, + + ///Low cloud cover (%) + [Description("Low cloud cover")] LowCloudCover = 3, + + ///Medium cloud cover (%) + [Description("Medium cloud cover")] MediumCloudCover = 4, + + ///High cloud cover (%) + [Description("High cloud cover")] HighCloudCover = 5, + + ///Cloud water (kg m-2) + [Description("Cloud water")] CloudWater = 6, + + ///Cloud amount (%) + [Description("Cloud amount")] CloudAmount = 7, + + ///Cloud type (Code table (4.203)) + [Description("Cloud type")] CloudType = 8, + + ///Thunderstorm maximum tops (m) + [Description("Thunderstorm maximum tops")] + ThunderstormMaximumTops = 9, + + ///Thunderstorm coverage (Code table (4.204)) + [Description("Thunderstorm coverage")] ThunderstormCoverage = 10, + + ///Cloud base (m) + [Description("Cloud base")] CloudBase = 11, + + ///Cloud top (m) + [Description("Cloud top")] CloudTop = 12, + + ///Ceiling (m) + [Description("Ceiling")] Ceiling = 13, + + #endregion + + #region Product Discipline 0: Meteorological products, Parameter Category 7: Thermodynamic Stability Indices + + ///Parcel lifted index (to 500 hPa) (K) + [Description("Parcel lifted index (to 500 hPa)")] + ParcelLiftedIndex = 0, + + ///Best lifted index (to 500 hPa) (K) + [Description("Best lifted index (to 500 hPa)")] + BestLiftedIndex = 1, + + ///K index (K) + [Description("K index")] KIndex = 2, + + ///KO index (K) + [Description("KO index")] KoIndex = 3, + + ///Total totals index (K) + [Description("Total totals index")] TotalTotalsIndex = 4, + + ///Sweat index (numeric) + [Description("Sweat index")] SweatIndex = 5, + + ///Convective available potential energy (J kg-1) + [Description("Convective available potential energy")] + ConvectiveAvailablePotentialEnergy = 6, + + ///Convective inhibition (J kg-1) + [Description("Convective inhibition")] ConvectiveInhibition = 7, + + ///Storm relative helicity (J kg-1) + [Description("Storm relative helicity")] + StormRelativeHelicity = 8, + + ///Energy helicity index (numeric) + [Description("Energy helicity index")] EnergyHelicityIndex = 9, + + #endregion + + #region Product Discipline 0: Meteorological products, Parameter Category 13: Aerosols + + ///Aerosol type (Code table (4.205)) + [Description("Aerosol type")] AerosolType = 0, + + #endregion + + #region Product Discipline 0: Meteorological products, Parameter Category 14: Trace Gases + + ///Total ozone (Dobson) + [Description("Total ozone")] TotalOzone = 0, + + #endregion + + #region Product Discipline 0 - Meteorological products, Parameter Category 15: Radar + + ///Base spectrum width (m s-1) + [Description("Base spectrum width")] BaseSpectrumWidth = 0, + + ///Base reflectivity (dB) + [Description("Base reflectivity")] BaseReflectivity = 1, + + ///Base radial velocity (m s-1) + [Description("Base radial velocity")] BaseRadialVelocity = 2, + + ///Vertically-integrated liquid (kg m-1) + [Description("Vertically-integrated liquid")] + VerticallyIntegratedLiquid = 3, + + ///Layer-maximum base reflectivity (dB) + [Description("Layer-maximum base reflectivity")] + LayerMaximumBaseReflectivity = 4, + + ///Precipitation (kg m-2) + [Description("Precipitation")] Precipitation = 5, + + ///Radar spectra (1) (-) + [Description("Radar spectra (1)")] RadarSpectra1 = 6, + + ///Radar spectra (2) (-) + [Description("Radar spectra (2)")] RadarSpectra2 = 7, + + ///Radar spectra (3) (-) + [Description("Radar spectra (3)")] RadarSpectra3 = 8, + + #endregion + + #region Product Discipline 0: Meteorological products, Parameter Category 18: Nuclear/radiology + + ///Air concentration of Caesium 137 (Bq m-3) + [Description("Air concentration of Caesium 137")] + AirConcentrationOfCaesium137 = 0, + + ///Air concentration of Iodine 131 (Bq m-3) + [Description("Air concentration of Iodine 131")] + AirConcentrationOfIodine131 = 1, + + ///Air concentration of radioactive pollutant (Bq m-3) + [Description("Air concentration of radioactive pollutant")] + AirConcentrationOfRadioactivePollutant = 2, + + ///Ground deposition of Caesium 137 (Bq m-2) + [Description("Ground deposition of Caesium 137")] + GroundDepositionOfCaesium137 = 3, + + ///Ground deposition of Iodine 131 (Bq m-2) + [Description("Ground deposition of Iodine 131")] + GroundDepositionOfIodine131 = 4, + + ///Ground deposition of radioactive pollutant (Bq m-2) + [Description("Ground deposition of radioactive pollutant")] + GroundDepositionOfRadioactivePollutant = 5, + + ///Time-integrated air concentration of caesium pollutant (Bq s m-3) + [Description("Time-integrated air concentration of caesium pollutant")] + TimeIntegratedAirConcentrationOfCaesiumPollutant = 6, + + ///Time-integrated air concentration of iodine pollutant (Bq s m-3) + [Description("Time-integrated air concentration of iodine pollutant")] + TimeIntegratedAirConcentrationOfIodinePollutant = 7, + + ///Time-integrated air concentration of radioactive pollutant (Bq s m-3) + [Description("Time-integrated air concentration of radioactive pollutant")] + TimeIntegratedAirConcentrationOfRadioactivePollutant = 8, + + #endregion + + #region Product Discipline 0: Meteorological products, Parameter Category 19: Physical atmospheric properties + + ///Visibility (m) + [Description("Visibility")] Visibility = 0, + + ///Albedo (%) + [Description("Albedo")] Albedo = 1, + + ///Thunderstorm probability (%) + [Description("Thunderstorm probability")] + ThunderstormProbability = 2, + + ///mixed layer depth (m) + [Description("mixed layer depth")] MixedLayerDepth = 3, + + ///Volcanic ash (Code table (4.206)) + [Description("Volcanic ash")] VolcanicAsh = 4, + + ///Icing top (m) + [Description("Icing top")] IcingTop = 5, + + ///Icing base (m) + [Description("Icing base")] IcingBase = 6, + + ///Icing (Code table (4.207)) + [Description("Icing")] Icing = 7, + + ///Turbulence top (m) + [Description("Turbulence top")] TurbulenceTop = 8, + + ///Turbulence base (m) + [Description("Turbulence base")] TurbulenceBase = 9, + + ///Turbulence (Code table (4.208)) + [Description("Turbulence")] Turbulence = 10, + + ///Turbulent kinetic energy (J kg-1) + [Description("Turbulent kinetic energy")] + TurbulentKineticEnergy = 11, + + ///Planetary boundary layer regime (Code table (4.209)) + [Description("Planetary boundary layer regime")] + PlanetaryBoundaryLayerRegime = 12, + + ///Contrail intensity (Code table (4.210)) + [Description("Contrail intensity")] ContrailIntensity = 13, + + ///Contrail engine type (Code table (4.211)) + [Description("Contrail engine type")] ContrailEngineType = 14, + + ///Contrail top (m) + [Description("Contrail top")] ContrailTop = 15, + + ///Contrail (base) + [Description("Contrail")] Contrail = 16, + + #endregion + + #region Product Discipline 0: Meteorological products, Parameter Category 253: ASCII character string + + ///Arbitrary text string CCITTIA5 + [Description("Arbitrary text string CCITTIA5")] + ArbitraryTextStringCcittia5 = 0, + + #endregion + + #region Product Discipline 1: Hydrologic products, Parameter Category 0: Hydrology basic products + + ///Flash flood guidance (Encoded as an accumulation over a floating subinterval of time between the reference time and valid time) (kg m-2) + [Description( + "Flash flood guidance (Encoded as an accumulation over a floating subinterval of time between the reference time and valid time)")] + FlashFloodGuidance = 0, + + ///Flash flood runoff (Encoded as an accumulation over a floating subinterval of time) (kg m-2) + [Description("Flash flood runoff (Encoded as an accumulation over a floating subinterval of time)")] + FlashFloodRunoff = 1, + + ///Remotely sensed snow cover (code table 4.215) + [Description("Remotely sensed snow cover (code table 4.215)")] + RemotelySensedSnowCover = 2, + + ///Elevation of snow covered terrain (code table 4.216) + [Description("Elevation of snow covered terrain (code table 4.216)")] + ElevationOfSnowCoveredTerrain = 3, + + ///Snow water equivalent percent of normal (%) + [Description("Snow water equivalent percent of normal")] + SnowWaterEquivalentPercentOfNormal = 4, + + #endregion + + #region Product Discipline 1: Hydrologic products, Parameter Category 1: Hydrology probabilities + + ///Conditional percent precipitation amount fractile for an overall period (kg m-2(Encoded as an accumulation).) + [Description("Conditional percent precipitation amount fractile for an overall period")] + ConditionalPercentPrecipitationAmountFractileForAnOverallPeriod = 0, + + ///Percent precipitation in a sub-period of an overall period (Encoded as per cent accumulation over the sub-period) (%) + [Description( + "Percent precipitation in a sub-period of an overall period (Encoded as per cent accumulation over the sub-period)")] + PercentPrecipitationInASubPeriodOfAnOverallPeriod = 1, + + ///Probability of 0.01 inch of precipitation (POP) (%) + [Description("Probability of 0.01 inch of precipitation (POP)")] + ProbabilityOf001InchOfPrecipitationPop = 2, + + #endregion + + #region Product Discipline 2: Land surface products, Parameter Category 0: Vegetation/Biomass + + ///Land cover (1=land, 2=sea) (Proportion) + [Description("Land cover (1=land, 2=sea)")] + LandCover = 0, + + ///Surface roughness (m) + [Description("Surface roughness")] SurfaceRoughness = 1, + + ///Soil temperature + [Description("Soil temperature")] SoilTemperature = 2, + + ///Soil moisture content (kg m-2) + [Description("Soil moisture content")] SoilMoistureContent = 3, + + ///Vegetation (%) + [Description("Vegetation")] Vegetation = 4, + + ///Water runoff (kg m-2) + [Description("Water runoff")] WaterRunoff = 5, + + ///Evapotranspiration (kg-2 s-1) + [Description("Evapotranspiration")] Evapotranspiration = 6, + + ///Model terrain height (m) + [Description("Model terrain height")] ModelTerrainHeight = 7, + + ///Land use (Code table (4.212)) + [Description("Land use")] LandUse = 8, + + #endregion + + #region Product Discipline 2: Land surface products, Parameter Category 3: Soil Products + + ///Soil type (Code table (4.213)) + [Description("Soil type")] SoilType = 0, + + ///Upper layer soil temperature (K) + [Description("Upper layer soil temperature")] + UpperLayerSoilTemperature = 1, + + ///Upper layer soil moisture (kg m-3) + [Description("Upper layer soil moisture")] + UpperLayerSoilMoisture = 2, + + ///Lower layer soil moisture (kg m-3) + [Description("Lower layer soil moisture")] + LowerLayerSoilMoisture = 3, + + ///Bottom layer soil temperature (K) + [Description("Bottom layer soil temperature")] + BottomLayerSoilTemperature = 4, + + #endregion + + #region Product Discipline 3: Space products, Parameter Category 0: Image format products + + ///Scaled radiance (numeric) + [Description("Scaled radiance")] ScaledRadiance = 0, + + ///Scaled albedo (numeric) + [Description("Scaled albedo")] ScaledAlbedo = 1, + + ///Scaled brightness temperature (numeric) + [Description("Scaled brightness temperature")] + ScaledBrightnessTemperature = 2, + + ///Scaled precipitable water (numeric) + [Description("Scaled precipitable water")] + ScaledPrecipitableWater = 3, + + ///Scaled lifted index (numeric) + [Description("Scaled lifted index")] ScaledLiftedIndex = 4, + + ///Scaled cloud top pressure (numeric) + [Description("Scaled cloud top pressure")] + ScaledCloudTopPressure = 5, + + ///Scaled skin temperature (numeric) + [Description("Scaled skin temperature")] + ScaledSkinTemperature = 6, + + ///Cloud mask (Code table 4.217) + [Description("Cloud mask")] CloudMask = 7, + + #endregion + + #region Product Discipline 3: Space products, Parameter Category 1: Quantitative products + + ///Estimated precipitation (kg m-2) + [Description("Estimated precipitation")] + EstimatedPrecipitation = 0, + + #endregion + + #region Product Discipline 10: Oceanographic products, Parameter Category 0: Waves + + ///Wave spectra (1) (-) + [Description("Wave spectra (1)")] WaveSpectra1 = 0, + + ///Wave spectra (2) (-) + [Description("Wave spectra (2)")] WaveSpectra2 = 1, + + ///Wave spectra (3) (-) + [Description("Wave spectra (3)")] WaveSpectra3 = 2, + + ///Significant height of combined wind waves and swell (m) + [Description("Significant height of combined wind waves and swell")] + SignificantHeightOfCombinedWindWavesAndSwell = 3, + + ///Direction of wind waves (Degree true) + [Description("Direction of wind waves")] + DirectionOfWindWaves = 4, + + ///Significant height of wind waves (m) + [Description("Significant height of wind waves")] + SignificantHeightOfWindWaves = 5, + + ///Mean period of wind waves (s) + [Description("Mean period of wind waves")] + MeanPeriodOfWindWaves = 6, + + ///Direction of swell waves (Degree true) + [Description("Direction of swell waves")] + DirectionOfSwellWaves = 7, + + ///Significant height of swell waves (m) + [Description("Significant height of swell waves")] + SignificantHeightOfSwellWaves = 8, + + ///Mean period of swell waves (s) + [Description("Mean period of swell waves")] + MeanPeriodOfSwellWaves = 9, + + ///Primary wave direction (Degree true) + [Description("Primary wave direction")] + PrimaryWaveDirection = 10, + + ///Primary wave mean period (s) + [Description("Primary wave mean period")] + PrimaryWaveMeanPeriod = 11, + + ///Secondary wave direction (Degree true) + [Description("Secondary wave direction")] + SecondaryWaveDirection = 12, + + ///Secondary wave mean period (s) + [Description("Secondary wave mean period")] + SecondaryWaveMeanPeriod = 13, + + #endregion + + #region Product Discipline 10: Oceanographic products, Parameter Category 1: Currents + + ///Current direction (Degree true) + [Description("Current direction")] CurrentDirection = 0, + + ///Current speed (m s-1) + [Description("Current speed")] CurrentSpeed = 1, + + ///u-component of current (m s-1) + [Description("u-component of current")] + UComponentOfCurrent = 2, + + ///v-component of current (m s-1) + [Description("v-component of current")] + VComponentOfCurrent = 3, + + #endregion + + #region Product Discipline 10: Oceanographic products, Parameter Category 2: Ice + + ///Ice cover (Proportion) + [Description("Ice cover")] IceCover = 0, + + ///Ice thickness (m) + [Description("Ice thickness")] IceThickness = 1, + + ///Direction of ice drift (Degree true) + [Description("Direction of ice drift")] + DirectionOfIceDrift = 2, + + ///Speed of ice drift (m s-1) + [Description("Speed of ice drift")] SpeedOfIceDrift = 3, + + ///u-component of ice drift (m s-1) + [Description("u-component of ice drift")] + UComponentOfIceDrift = 4, + + ///v-component of ice drift (m s-1) + [Description("v-component of ice drift")] + VComponentOfIceDrift = 5, + + ///Ice growth rate (m s-1) + [Description("Ice growth rate")] IceGrowthRate = 6, + + ///Ice divergence (s-1) + [Description("Ice divergence")] IceDivergence = 7, + + #endregion + + #region Product Discipline 10: Oceanographic products, Parameter Category 3: Surface Properties + + ///Water temperature (K) + [Description("Water temperature")] WaterTemperature = 0, + + ///Deviation of sea level from mean (m) + [Description("Deviation of sea level from mean")] + DeviationOfSeaLevelFromMean = 1, + + #endregion + + #region Product Discipline 10: Oceanographic products, Parameter Category 4: Sub-surface Properties + + ///Main thermocline depth (m) + [Description("Main thermocline depth")] + MainThermoclineDepth = 0, + + ///Main thermocline anomaly (m) + [Description("Main thermocline anomaly")] + MainThermoclineAnomaly = 1, + + ///Transient thermocline depth (m) + [Description("Transient thermocline depth")] + TransientThermoclineDepth = 2, + + ///Salinity (kg kg-1) + [Description("Salinity")] Salinity = 3, + + #endregion + + ///Missing + [Description("Missing")] Missing = 255, +} \ No newline at end of file diff --git a/tmp/Grib2/CodeTables/4_3_GeneratingProcessType.cs b/tmp/Grib2/CodeTables/4_3_GeneratingProcessType.cs new file mode 100644 index 0000000..6cc0828 --- /dev/null +++ b/tmp/Grib2/CodeTables/4_3_GeneratingProcessType.cs @@ -0,0 +1,59 @@ +/* + * This file is part of NGrib. + * + * Copyright © 2020 Nicolas Mangué + * + * NGrib is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * NGrib is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with NGrib. If not, see . + */ + +using System.ComponentModel; + +namespace NGrib.Grib2.CodeTables; + +/// +/// Code table 4.3: Type of generating process +/// +public enum GeneratingProcessType +{ + ///Analysis + [Description("Analysis")] Analysis = 0, + + ///Initialization + [Description("Initialization")] Initialization = 1, + + ///Forecast + [Description("Forecast")] Forecast = 2, + + ///Bias corrected forecast + [Description("Bias corrected forecast")] + BiasCorrectedForecast = 3, + + ///Ensemble forecast + [Description("Ensemble forecast")] EnsembleForecast = 4, + + ///Probability forecast + [Description("Probability forecast")] ProbabilityForecast = 5, + + ///Forecast error + [Description("Forecast error")] ForecastError = 6, + + ///Analysis error + [Description("Analysis error")] AnalysisError = 7, + + ///Observation + [Description("Observation")] Observation = 8, + + ///Missing + [Description("Missing")] Missing = 255, +} \ No newline at end of file diff --git a/tmp/Grib2/CodeTables/4_4_TimeRangeUnit.cs b/tmp/Grib2/CodeTables/4_4_TimeRangeUnit.cs new file mode 100644 index 0000000..92cfea2 --- /dev/null +++ b/tmp/Grib2/CodeTables/4_4_TimeRangeUnit.cs @@ -0,0 +1,67 @@ +/* + * This file is part of NGrib. + * + * Copyright © 2020 Nicolas Mangué + * + * NGrib is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * NGrib is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with NGrib. If not, see . + */ + +using System.ComponentModel; + +namespace NGrib.Grib2.CodeTables; + +/// +/// Code Table 4.4: Indicator of unit of time range +/// +public enum TimeRangeUnitGrib2 +{ + ///Minute + [Description("Minute")] Minute = 0, + + ///Hour + [Description("Hour")] Hour = 1, + + ///Day + [Description("Day")] Day = 2, + + ///Month + [Description("Month")] Month = 3, + + ///Year + [Description("Year")] Year = 4, + + ///Decade (10 years) + [Description("Decade (10 years)")] Decade = 5, + + ///Normal (30 years) + [Description("Normal (30 years)")] Normal = 6, + + ///Century (100 years) + [Description("Century (100 years)")] Century = 7, + + ///3 hours + [Description("3 hours")] Hours3 = 10, + + ///6 hours + [Description("6 hours")] Hours6 = 11, + + ///12 hours + [Description("12 hours")] Hours12 = 12, + + ///Second + [Description("Second")] Second = 13, + + ///Missing + [Description("Missing")] Missing = 255, +} \ No newline at end of file diff --git a/tmp/Grib2/CodeTables/4_5_FixedSurfaceType.cs b/tmp/Grib2/CodeTables/4_5_FixedSurfaceType.cs new file mode 100644 index 0000000..2bb458d --- /dev/null +++ b/tmp/Grib2/CodeTables/4_5_FixedSurfaceType.cs @@ -0,0 +1,110 @@ +/* + * This file is part of NGrib. + * + * Copyright © 2020 Nicolas Mangué + * + * NGrib is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * NGrib is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with NGrib. If not, see . + */ + +using System.ComponentModel; + +namespace NGrib.Grib2.CodeTables; + +/// +/// Code table 4.5: Fixed surface types and units +/// +public enum FixedSurfaceType +{ + ///Ground or water surface + [Description("Ground or water surface")] + GroundOrWaterSurface = 1, + + ///Cloud base level + [Description("Cloud base level")] CloudBaseLevel = 2, + + ///Level of cloud tops + [Description("Level of cloud tops")] LevelOfCloudTops = 3, + + ///Level of 0°C isotherm + [Description("Level of 0°C isotherm")] LevelOf0CIsotherm = 4, + + ///Level of adiabatic condensation lifted from the surface + [Description("Level of adiabatic condensation lifted from the surface")] + LevelOfAdiabaticCondensationLiftedFromTheSurface = 5, + + ///Maximum wind level + [Description("Maximum wind level")] MaximumWindLevel = 6, + + ///Tropopause + [Description("Tropopause")] Tropopause = 7, + + ///Nominal top of the atmosphere + [Description("Nominal top of the atmosphere")] + NominalTopOfTheAtmosphere = 8, + + ///Sea bottom + [Description("Sea bottom")] SeaBottom = 9, + + ///Isothermal level (K) + [Description("Isothermal level")] IsothermalLevel = 20, + + ///Isobaric surface (Pa) + [Description("Isobaric surface")] IsobaricSurface = 100, + + ///Mean sea level + [Description("Mean sea level")] MeanSeaLevel = 101, + + ///Specific altitude above mean sea level (m) + [Description("Specific altitude above mean sea level")] + SpecificAltitudeAboveMeanSeaLevel = 102, + + ///Specified height level above ground (m) + [Description("Specified height level above ground")] + SpecifiedHeightLevelAboveGround = 103, + + ///Sigma level (sigma value) + [Description("Sigma level")] SigmaLevel = 104, + + ///Hybrid level + [Description("Hybrid level")] HybridLevel = 105, + + ///Depth below land surface (m) + [Description("Depth below land surface")] + DepthBelowLandSurface = 106, + + ///Isentropic (theta) level (K) + [Description("Isentropic (theta) level")] + IsentropicLevel = 107, + + ///Level at specified pressure difference from ground to level (Pa) + [Description("Level at specified pressure difference from ground to level")] + LevelAtSpecifiedPressureDifferenceFromGroundToLevel = 108, + + ///Potential vorticity surface (K m2 kg-1 s-1) + [Description("Potential vorticity surface")] + PotentialVorticitySurface = 109, + + ///Eta* level + [Description("Eta* level")] EtaLevel = 111, + + ///Mixed layer depth (m) + [Description("Mixed layer depth")] MixedLayerDepth = 117, + + ///Depth below sea level (m) + [Description("Depth below sea level")] + DepthBelowSeaLevel = 160, + + ///Missing + [Description("Missing ")] Missing = 255, +} \ No newline at end of file diff --git a/tmp/Grib2/CodeTables/4_6_EnsembleForecastType.cs b/tmp/Grib2/CodeTables/4_6_EnsembleForecastType.cs new file mode 100644 index 0000000..56daeac --- /dev/null +++ b/tmp/Grib2/CodeTables/4_6_EnsembleForecastType.cs @@ -0,0 +1,37 @@ +namespace NGrib.Grib2.CodeTables; + +/// +/// Code table 4.6 - Type of ensemble forecast +/// +public enum EnsembleForecastType +{ + /// + /// Unperturbed high-resolution control forecast + /// + UnperturbedHighResolutionControlForecast = 0, + + /// + /// Unperturbed low-resolution control forecast + /// + UnperturbedLowResolutionControlForecast = 1, + + /// + /// Negatively perturbed forecast + /// + NegativelyPerturbedForecast = 2, + + /// + /// Positively perturbed forecast + /// + PositivelyPerturbedForecast = 3, + + /// + /// Multi-model forecast + /// + MultiModelForecast = 4, + + /// + /// Missing + /// + Missing = 255, +} \ No newline at end of file diff --git a/tmp/Grib2/CodeTables/5_1_OriginalFieldValuesType.cs b/tmp/Grib2/CodeTables/5_1_OriginalFieldValuesType.cs new file mode 100644 index 0000000..6cf245e --- /dev/null +++ b/tmp/Grib2/CodeTables/5_1_OriginalFieldValuesType.cs @@ -0,0 +1,41 @@ +/* + * This file is part of NGrib. + * + * Copyright © 2020 Nicolas Mangué + * + * NGrib is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * NGrib is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with NGrib. If not, see . + */ + +namespace NGrib.Grib2.CodeTables; + +/// +/// Code Table 5.1: Type of original field values +/// +public enum OriginalFieldValuesType +{ + /// + /// Floating point + /// + FloatingPoint, + + /// + /// Integer + /// + Integer, + + /// + /// Missing + /// + Missing = 255 +} \ No newline at end of file diff --git a/tmp/Grib2/CodeTables/5_4_GroupSplittingMethod.cs b/tmp/Grib2/CodeTables/5_4_GroupSplittingMethod.cs new file mode 100644 index 0000000..24cc874 --- /dev/null +++ b/tmp/Grib2/CodeTables/5_4_GroupSplittingMethod.cs @@ -0,0 +1,41 @@ +/* + * This file is part of NGrib. + * + * Copyright © 2020 Nicolas Mangué + * + * NGrib is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * NGrib is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with NGrib. If not, see . + */ + +namespace NGrib.Grib2.CodeTables; + +/// +/// Code Table 5.4: Group Splitting Method +/// +public enum GroupSplittingMethod +{ + /// + /// Row by row splitting + /// + RowByRow, + + /// + /// General group splitting + /// + GeneralGroup, + + /// + /// Missing + /// + Missing, +} \ No newline at end of file diff --git a/tmp/Grib2/CodeTables/5_5_ComplexPackingMissingValueManagement.cs b/tmp/Grib2/CodeTables/5_5_ComplexPackingMissingValueManagement.cs new file mode 100644 index 0000000..34f815b --- /dev/null +++ b/tmp/Grib2/CodeTables/5_5_ComplexPackingMissingValueManagement.cs @@ -0,0 +1,46 @@ +/* + * This file is part of NGrib. + * + * Copyright © 2020 Nicolas Mangué + * + * NGrib is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * NGrib is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with NGrib. If not, see . + */ + +namespace NGrib.Grib2.CodeTables; + +/// +/// Code Table 5.5: Missing Value Management for Complex Packing +/// +public enum ComplexPackingMissingValueManagement +{ + /// + /// No explicit missing values included within data values. + /// + None, + + /// + /// Primary missing values included within data values. + /// + Primary, + + /// + /// Primary and secondary missing values included within data values. + /// + PrimaryAndSecondary, + + /// + /// Missing. + /// + Missing +} \ No newline at end of file diff --git a/tmp/Grib2/CodeTables/5_6_SpatialDifferencingOrder.cs b/tmp/Grib2/CodeTables/5_6_SpatialDifferencingOrder.cs new file mode 100644 index 0000000..c7adcfe --- /dev/null +++ b/tmp/Grib2/CodeTables/5_6_SpatialDifferencingOrder.cs @@ -0,0 +1,41 @@ +/* + * This file is part of NGrib. + * + * Copyright © 2020 Nicolas Mangué + * + * NGrib is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * NGrib is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with NGrib. If not, see . + */ + +namespace NGrib.Grib2.CodeTables; + +/// +/// Code Table 5.6: Order of Spatial Differencing +/// +public enum SpatialDifferencingOrder +{ + /// + /// First-order spatial differencing. + /// + FirstOrder = 1, + + /// + /// Second-order spatial differencing. + /// + SecondOrder = 2, + + /// + /// Missing. + /// + Missing = 255, +} \ No newline at end of file diff --git a/tmp/Grib2/CodeTables/C_1_Center.cs b/tmp/Grib2/CodeTables/C_1_Center.cs new file mode 100644 index 0000000..7be72da --- /dev/null +++ b/tmp/Grib2/CodeTables/C_1_Center.cs @@ -0,0 +1,983 @@ +/* + * This file is part of NGrib. + * + * Copyright © 2020 Nicolas Mangué + * + * NGrib is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * NGrib is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with NGrib. If not, see . + */ + +using System.Diagnostics.CodeAnalysis; + +namespace NGrib.Grib2.CodeTables; + +[SuppressMessage("ReSharper", "IdentifierTypo")] +[SuppressMessage("ReSharper", "CommentTypo")] +[SuppressMessage("ReSharper", "StringLiteralTypo")] +public readonly struct Center +{ + public int Id { get; } + public string Name { get; } + + private Center(int id, string name = null) + { + Id = id; + Name = name; + } + + public bool Equals(Center other) => Id == other.Id; + + public override bool Equals(object obj) => obj is Center other && Equals(other); + + public override int GetHashCode() => Id.GetHashCode(); + + public static Center GetCenterById(int centerId) + { + var centers = AllCenters.Where(c => c.Id == centerId).ToArray(); + return centers.Any() ? centers[0] : new Center(centerId); + } + + ///WMO Secretariat (0) + public static Center WmoSecretariat { get; } = new Center(0, "WMO Secretariat"); + + ///Melbourne (1) + public static Center Melbourne { get; } = new Center(1, "Melbourne"); + + ///Melbourne (2) + public static Center Melbourne2 { get; } = new Center(2, "Melbourne"); + + ///Melbourne (3) + public static Center Melbourne3 { get; } = new Center(3, "Melbourne"); + + ///Moscow (4) + public static Center Moscow { get; } = new Center(4, "Moscow"); + + ///Moscow (5) + public static Center Moscow5 { get; } = new Center(5, "Moscow"); + + ///Moscow (6) + public static Center Moscow6 { get; } = new Center(6, "Moscow"); + + ///US National Weather Service, National Centers for Environmental Prediction (NCEP) (7) + public static Center UsNcep { get; } = new Center(7, + "US National Weather Service, National Centers for Environmental Prediction (NCEP)"); + + ///US National Weather Service Telecommunications Gateway (NWSTG) (8) + public static Center UsNwstg { get; } = + new Center(8, "US National Weather Service Telecommunications Gateway (NWSTG)"); + + ///US National Weather Service - Other (9) + public static Center UsNwsOther { get; } = new Center(9, "US National Weather Service - Other"); + + ///Cairo (RSMC) (10) + public static Center Cairo { get; } = new Center(10, "Cairo (RSMC)"); + + ///Cairo (RSMC) (11) + public static Center CairoReserved { get; } = new Center(11, "Cairo (RSMC)"); + + ///Dakar (RSMC) (12) + public static Center Dakar { get; } = new Center(12, "Dakar (RSMC)"); + + ///Dakar (RSMC) (13) + public static Center DakarReserved { get; } = new Center(13, "Dakar (RSMC)"); + + ///Nairobi (RSMC) (14) + public static Center Nairobi { get; } = new Center(14, "Nairobi (RSMC)"); + + ///Nairobi (RSMC) (15) + public static Center NairobiReserved { get; } = new Center(15, "Nairobi (RSMC)"); + + ///Casablanca (RSMC) (16) + public static Center Casablanca { get; } = new Center(16, "Casablanca (RSMC)"); + + ///Tunis (RSMC) (17) + public static Center Tunis { get; } = new Center(17, "Tunis (RSMC)"); + + ///Tunis-Casablanca (RSMC) (18) + public static Center TunisCasablanca { get; } = new Center(18, "Tunis-Casablanca (RSMC)"); + + ///Tunis-Casablanca (RSMC) (19) + public static Center TunisCasablancaReserved { get; } = new Center(19, "Tunis-Casablanca (RSMC)"); + + ///Las Palmas (20) + public static Center LasPalmas { get; } = new Center(20, "Las Palmas"); + + ///Algiers (RSMC) (21) + public static Center Algiers { get; } = new Center(21, "Algiers (RSMC)"); + + ///ACMAD (22) + public static Center Acmad { get; } = new Center(22, "ACMAD"); + + ///Mozambique (NMC) (23) + public static Center Mozambique { get; } = new Center(23, "Mozambique (NMC)"); + + ///Pretoria (RSMC) (24) + public static Center Pretoria { get; } = new Center(24, "Pretoria (RSMC)"); + + ///La Réunion (RSMC) (25) + public static Center LaReunion { get; } = new Center(25, "La Réunion (RSMC)"); + + ///Khabarovsk (RSMC) (26) + public static Center Khabarovsk { get; } = new Center(26, "Khabarovsk (RSMC)"); + + ///Khabarovsk (RSMC) (27) + public static Center KhabarovskReserved { get; } = new Center(27, "Khabarovsk (RSMC)"); + + ///New Delhi (RSMC) (28) + public static Center NewDelhi { get; } = new Center(28, "New Delhi (RSMC)"); + + ///New Delhi (RSMC) (29) + public static Center NewDelhiReserved { get; } = new Center(29, "New Delhi (RSMC)"); + + ///Novosibirsk (RSMC) (30) + public static Center Novosibirsk { get; } = new Center(30, "Novosibirsk (RSMC)"); + + ///Novosibirsk (RSMC) (31) + public static Center NovosibirskReserved { get; } = new Center(31, "Novosibirsk (RSMC)"); + + ///Tashkent (RSMC) (32) + public static Center Tashkent { get; } = new Center(32, "Tashkent (RSMC)"); + + ///Jeddah (RSMC) (33) + public static Center Jeddah { get; } = new Center(33, "Jeddah (RSMC)"); + + ///Tokyo (RSMC), Japan Meteorological Agency (34) + public static Center Tokyo { get; } = new Center(34, "Tokyo (RSMC), Japan Meteorological Agency"); + + ///Tokyo (RSMC), Japan Meteorological Agency (35) + public static Center TokyoReserved { get; } = new Center(35, "Tokyo (RSMC), Japan Meteorological Agency"); + + ///Bangkok (36) + public static Center Bangkok { get; } = new Center(36, "Bangkok"); + + ///Ulaanbaatar (37) + public static Center Ulaanbaatar { get; } = new Center(37, "Ulaanbaatar"); + + ///Beijing (RSMC) (38) + public static Center Beijing { get; } = new Center(38, "Beijing (RSMC)"); + + ///Beijing (RSMC) (39) + public static Center BeijingReserved { get; } = new Center(39, "Beijing (RSMC)"); + + ///Seoul (40) + public static Center Seoul { get; } = new Center(40, "Seoul"); + + ///Buenos Aires (RSMC) (41) + public static Center BuenosAires { get; } = new Center(41, "Buenos Aires (RSMC)"); + + ///Buenos Aires (RSMC) (42) + public static Center BuenosAiresReserved { get; } = new Center(42, "Buenos Aires (RSMC)"); + + ///Brasilia (RSMC) (43) + public static Center Brasilia { get; } = new Center(43, "Brasilia (RSMC)"); + + ///Brasilia (RSMC) (44) + public static Center BrasiliaReserved { get; } = new Center(44, "Brasilia (RSMC)"); + + ///Santiago (45) + public static Center Santiago { get; } = new Center(45, "Santiago"); + + ///Brazilian Space Agency ­ - INPE (46) + public static Center BrazilianSpaceAgencyInpe { get; } = new Center(46, "Brazilian Space Agency ­ - INPE"); + + ///Colombia (NMC) (47) + public static Center Colombia { get; } = new Center(47, "Colombia (NMC)"); + + ///Ecuador (NMC) (48) + public static Center Ecuador { get; } = new Center(48, "Ecuador (NMC)"); + + ///Peru (NMC) (49) + public static Center Peru { get; } = new Center(49, "Peru (NMC)"); + + ///Venezuela (Bolivarian Republic of) (NMC) (50) + public static Center Venezuela { get; } = new Center(50, "Venezuela (Bolivarian Republic of) (NMC)"); + + ///Miami (RSMC) (51) + public static Center Miami { get; } = new Center(51, "Miami (RSMC)"); + + ///Miami (RSMC), National Hurricane Center (52) + public static Center MiamiNhc { get; } = new Center(52, "Miami (RSMC), National Hurricane Center"); + + ///Montreal (RSMC) (53) + public static Center Montreal { get; } = new Center(53, "Montreal (RSMC)"); + + ///Montreal (RSMC) (54) + public static Center MontrealReserved { get; } = new Center(54, "Montreal (RSMC)"); + + ///San Francisco (55) + public static Center SanFrancisco { get; } = new Center(55, "San Francisco"); + + ///ARINC Center (56) + public static Center ArincCenter { get; } = new Center(56, "ARINC Center"); + + ///U.S. Air Force - Air Force Global Weather Central (57) + public static Center UsAfGwc { get; } = new Center(57, "U.S. Air Force - Air Force Global Weather Central"); + + ///Fleet Numerical Meteorology and Oceanography Center, Monterey, CA, USA (58) + public static Center CaFnmoc { get; } = + new Center(58, "Fleet Numerical Meteorology and Oceanography Center, Monterey, CA, USA"); + + ///The NOAA Forecast Systems Laboratory, Boulder, CO, USA (59) + public static Center UsNoaaForecastSystemsLaboratory { get; } = + new Center(59, "The NOAA Forecast Systems Laboratory, Boulder, CO, USA"); + + ///United States National Center for Atmospheric Research (NCAR) (60) + public static Center UsNcar { get; } = + new Center(60, "United States National Center for Atmospheric Research (NCAR)"); + + ///Service ARGOS - Landover (61) + public static Center ArgosLandover { get; } = new Center(61, "Service ARGOS - Landover"); + + ///U.S. Naval Oceanographic Office (62) + public static Center UsNoo { get; } = new Center(62, "U.S. Naval Oceanographic Office"); + + ///International Research Institute for Climate and Society (IRI ) (63) + public static Center Iri { get; } = + new Center(63, "International Research Institute for Climate and Society (IRI )"); + + ///Honolulu (RSMC) (64) + public static Center Honolulu { get; } = new Center(64, "Honolulu (RSMC)"); + + ///Darwin (RSMC) (65) + public static Center Darwin { get; } = new Center(65, "Darwin (RSMC)"); + + ///Darwin (RSMC) (66) + public static Center DarwinReserved { get; } = new Center(66, "Darwin (RSMC)"); + + ///Melbourne (RSMC) (67) + public static Center Melbourne67 { get; } = new Center(67, "Melbourne (RSMC)"); + + ///Wellington (RSMC) (69) + public static Center Wellington { get; } = new Center(69, "Wellington (RSMC)"); + + ///Wellington (RSMC) (70) + public static Center WellingtonReserved { get; } = new Center(70, "Wellington (RSMC)"); + + ///Nadi (RSMC) (71) + public static Center Nadi { get; } = new Center(71, "Nadi (RSMC)"); + + ///Singapore (72) + public static Center Singapore { get; } = new Center(72, "Singapore"); + + ///Malaysia (NMC) (73) + public static Center Malaysia { get; } = new Center(73, "Malaysia (NMC)"); + + ///UK Meteorological Office - ­ Exeter (RSMC) (74) + public static Center UkMeteorologicalOffice { get; } = new Center(74, "UK Meteorological Office - ­ Exeter (RSMC)"); + + ///UK Meteorological Office - ­ Exeter (RSMC) (75) + public static Center UkMeteorologicalOfficeReserved { get; } = + new Center(75, "UK Meteorological Office - ­ Exeter (RSMC)"); + + ///Moscow (RSMC) (76) + public static Center Moscow76 { get; } = new Center(76, "Moscow (RSMC)"); + + ///Offenbach (RSMC) (78) + public static Center Offenbach { get; } = new Center(78, "Offenbach (RSMC)"); + + ///Offenbach (RSMC) (79) + public static Center OffenbachReserved { get; } = new Center(79, "Offenbach (RSMC)"); + + ///Rome (RSMC) (80) + public static Center Rome { get; } = new Center(80, "Rome (RSMC)"); + + ///Rome (RSMC) (81) + public static Center RomeReserved { get; } = new Center(81, "Rome (RSMC)"); + + ///Norrköping (82) + public static Center Norrkoping { get; } = new Center(82, "Norrköping"); + + ///Norrköping (83) + public static Center NorrkopingReserved { get; } = new Center(83, "Norrköping"); + + ///Toulouse (RSMC) (84) + public static Center Toulouse { get; } = new Center(84, "Toulouse (RSMC)"); + + ///Toulouse (RSMC) (85) + public static Center Toulouse85 { get; } = new Center(85, "Toulouse (RSMC)"); + + ///Helsinki (86) + public static Center Helsinki { get; } = new Center(86, "Helsinki"); + + ///Belgrade (87) + public static Center Belgrade { get; } = new Center(87, "Belgrade"); + + ///Oslo (88) + public static Center Oslo { get; } = new Center(88, "Oslo"); + + ///Prague (89) + public static Center Prague { get; } = new Center(89, "Prague"); + + ///Episkopi (90) + public static Center Episkopi { get; } = new Center(90, "Episkopi"); + + ///Ankara (91) + public static Center Ankara { get; } = new Center(91, "Ankara"); + + ///Frankfurt/Main (92) + public static Center FrankfurtMain { get; } = new Center(92, "Frankfurt/Main"); + + ///London (WAFC) (93) + public static Center London { get; } = new Center(93, "London (WAFC)"); + + ///Copenhagen (94) + public static Center Copenhagen { get; } = new Center(94, "Copenhagen"); + + ///Rota (95) + public static Center Rota { get; } = new Center(95, "Rota"); + + ///Athens (96) + public static Center Athens { get; } = new Center(96, "Athens"); + + ///European Space Agency (ESA) (97) + public static Center Esa { get; } = new Center(97, "European Space Agency (ESA)"); + + ///European Center for Medium Range Weather Forecasts (ECMWF) (RSMC) (98) + public static Center Ecmwf { get; } = + new Center(98, "European Center for Medium Range Weather Forecasts (ECMWF) (RSMC)"); + + ///De Bilt (99) + public static Center DeBilt { get; } = new Center(99, "De Bilt"); + + ///Brazzaville (100) + public static Center Brazzaville { get; } = new Center(100, "Brazzaville"); + + ///Abidjan (101) + public static Center Abidjan { get; } = new Center(101, "Abidjan"); + + ///Libya (NMC) (102) + public static Center Libya { get; } = new Center(102, "Libya (NMC)"); + + ///Madagascar (NMC) (103) + public static Center Madagascar { get; } = new Center(103, "Madagascar (NMC)"); + + ///Mauritius (NMC) (104) + public static Center Mauritius { get; } = new Center(104, "Mauritius (NMC)"); + + ///Niger (NMC) (105) + public static Center Niger { get; } = new Center(105, "Niger (NMC)"); + + ///Seychelles (NMC) (106) + public static Center Seychelles { get; } = new Center(106, "Seychelles (NMC)"); + + ///Uganda (NMC) (107) + public static Center Uganda { get; } = new Center(107, "Uganda (NMC)"); + + ///United Republic of Tanzania (NMC) (108) + public static Center Tanzania { get; } = new Center(108, "United Republic of Tanzania (NMC)"); + + ///Zimbabwe (NMC) (109) + public static Center Zimbabwe { get; } = new Center(109, "Zimbabwe (NMC)"); + + ///Hong-Kong, China (110) + public static Center HongKong { get; } = new Center(110, "Hong-Kong, China"); + + ///Afghanistan (NMC) (111) + public static Center Afghanistan { get; } = new Center(111, "Afghanistan (NMC)"); + + ///Bahrain (NMC) (112) + public static Center Bahrain { get; } = new Center(112, "Bahrain (NMC)"); + + ///Bangladesh (NMC) (113) + public static Center Bangladesh { get; } = new Center(113, "Bangladesh (NMC)"); + + ///Bhutan (NMC) (114) + public static Center Bhutan { get; } = new Center(114, "Bhutan (NMC)"); + + ///Cambodia (NMC) (115) + public static Center Cambodia { get; } = new Center(115, "Cambodia (NMC)"); + + ///Democratic People's Republic of Korea (NMC) (116) + public static Center DprKorea { get; } = new Center(116, "Democratic People's Republic of Korea (NMC)"); + + ///Islamic Republic of Iran (NMC) (117) + public static Center Iran { get; } = new Center(117, "Islamic Republic of Iran (NMC)"); + + ///Iraq (NMC) (118) + public static Center Iraq { get; } = new Center(118, "Iraq (NMC)"); + + ///Kazakhstan (NMC) (119) + public static Center Kazakhstan { get; } = new Center(119, "Kazakhstan (NMC)"); + + ///Kuwait (NMC) (120) + public static Center Kuwait { get; } = new Center(120, "Kuwait (NMC)"); + + ///Kyrgyzstan (NMC) (121) + public static Center Kyrgyzstan { get; } = new Center(121, "Kyrgyzstan (NMC)"); + + ///Lao People's Democratic Republic (NMC) (122) + public static Center Laos { get; } = new Center(122, "Lao People's Democratic Republic (NMC)"); + + ///Macao, China (123) + public static Center Macao { get; } = new Center(123, "Macao, China"); + + ///Maldives (NMC) (124) + public static Center Maldives { get; } = new Center(124, "Maldives (NMC)"); + + ///Myanmar (NMC) (125) + public static Center Myanmar { get; } = new Center(125, "Myanmar (NMC)"); + + ///Nepal (NMC) (126) + public static Center Nepal { get; } = new Center(126, "Nepal (NMC)"); + + ///Oman (NMC) (127) + public static Center Oman { get; } = new Center(127, "Oman (NMC)"); + + ///Pakistan (NMC) (128) + public static Center Pakistan { get; } = new Center(128, "Pakistan (NMC)"); + + ///Qatar (NMC) (129) + public static Center Qatar { get; } = new Center(129, "Qatar (NMC)"); + + ///Yemen (NMC) (130) + public static Center Yemen { get; } = new Center(130, "Yemen (NMC)"); + + ///Sri Lanka, (NMC) (131) + public static Center SriLanka { get; } = new Center(131, "Sri Lanka, (NMC)"); + + ///Tajikistan (NMC) (132) + public static Center Tajikistan { get; } = new Center(132, "Tajikistan (NMC)"); + + ///Turkmenistan (NMC) (133) + public static Center Turkmenistan { get; } = new Center(133, "Turkmenistan (NMC)"); + + ///United Arab Emirates (NMC) (134) + public static Center Emirates { get; } = new Center(134, "United Arab Emirates (NMC)"); + + ///Uzbekistan, (NMC) (135) + public static Center Uzbekistan { get; } = new Center(135, "Uzbekistan, (NMC)"); + + ///Viet Nam (NMC) (136) + public static Center Vietnam { get; } = new Center(136, "Viet Nam (NMC)"); + + ///Bolivia (Plurinational State of) (NMC) (140) + public static Center Bolivia { get; } = new Center(140, "Bolivia (Plurinational State of) (NMC)"); + + ///Guyana (NMC) (141) + public static Center Guyana { get; } = new Center(141, "Guyana (NMC)"); + + ///Paraguay (NMC) (142) + public static Center Paraguay { get; } = new Center(142, "Paraguay (NMC)"); + + ///Suriname (NMC) (143) + public static Center Suriname { get; } = new Center(143, "Suriname (NMC)"); + + ///Uruguay (NMC) (144) + public static Center Uruguay { get; } = new Center(144, "Uruguay (NMC)"); + + ///French Guyana (145) + public static Center FrenchGuyana { get; } = new Center(145, "French Guyana"); + + ///Brazilian Navy Hydrographic Center (146) + public static Center BrNhc { get; } = new Center(146, "Brazilian Navy Hydrographic Center"); + + ///National Commission on Space Activities  (CONAE) - Argentina (147) + public static Center ArConaz { get; } = + new Center(147, "National Commission on Space Activities  (CONAE) - Argentina"); + + ///Antigua and Barbuda (NMC) (150) + public static Center AntiguaBarbuda { get; } = new Center(150, "Antigua and Barbuda (NMC)"); + + ///Bahamas (NMC) (151) + public static Center Bahamas { get; } = new Center(151, "Bahamas (NMC)"); + + ///Barbados (NMC) (152) + public static Center Barbados { get; } = new Center(152, "Barbados (NMC)"); + + ///Belize (NMC) (153) + public static Center Belize { get; } = new Center(153, "Belize (NMC)"); + + ///British Caribbean Territories Center (154) + public static Center Caribbean { get; } = new Center(154, "British Caribbean Territories Center"); + + ///San José (155) + public static Center SanJose { get; } = new Center(155, "San José"); + + ///Cuba (NMC) (156) + public static Center Cuba { get; } = new Center(156, "Cuba (NMC)"); + + ///Dominica (NMC) (157) + public static Center Dominica { get; } = new Center(157, "Dominica (NMC)"); + + ///Dominican Republic (NMC) (158) + public static Center DominicanRepublic { get; } = new Center(158, "Dominican Republic (NMC)"); + + ///El Salvador (NMC) (159) + public static Center ElSalvador { get; } = new Center(159, "El Salvador (NMC)"); + + ///US NOAA/NESDIS  (160) + public static Center UsNoaaNesdis { get; } = new Center(160, "US NOAA/NESDIS "); + + ///US NOAA Office of Oceanic and Atmospheric Research (161) + public static Center UsNoaaOar { get; } = new Center(161, "US NOAA Office of Oceanic and Atmospheric Research"); + + ///Guatemala (NMC) (162) + public static Center Guatemala { get; } = new Center(162, "Guatemala (NMC)"); + + ///Haiti (NMC) (163) + public static Center Haiti { get; } = new Center(163, "Haiti (NMC)"); + + ///Honduras (NMC) (164) + public static Center Honduras { get; } = new Center(164, "Honduras (NMC)"); + + ///Jamaica (NMC) (165) + public static Center Jamaica { get; } = new Center(165, "Jamaica (NMC)"); + + ///Mexico City (166) + public static Center MexicoCity { get; } = new Center(166, "Mexico City"); + + ///Curaçao and Sint Maarten (NMC) (167) + public static Center CuracaoSintMaarten { get; } = new Center(167, "Curaçao and Sint Maarten (NMC)"); + + ///Nicaragua (NMC) (168) + public static Center Nicaragua { get; } = new Center(168, "Nicaragua (NMC)"); + + ///Panama (NMC) (169) + public static Center Panama { get; } = new Center(169, "Panama (NMC)"); + + ///Saint Lucia (NMC) (170) + public static Center SaintLucia { get; } = new Center(170, "Saint Lucia (NMC)"); + + ///Trinidad and Tobago (NMC) (171) + public static Center TrinidadTobago { get; } = new Center(171, "Trinidad and Tobago (NMC)"); + + ///French Departments in RA IV (172) + public static Center FrenchDepartments { get; } = new Center(172, "French Departments in RA IV"); + + ///US National Aeronautics and Space Administration (NASA) (173) + public static Center UsNasa { get; } = new Center(173, "US National Aeronautics and Space Administration (NASA)"); + + ///Integrated System Data Management/Marine Environmental Data Service (ISDM/MEDS) - Canada (174) + public static Center CaIsdmMeds { get; } = new Center(174, + "Integrated System Data Management/Marine Environmental Data Service (ISDM/MEDS) - Canada"); + + ///University Corporation for Atmospheric Research (UCAR) - United States (175) + public static Center UsUcar { get; } = + new Center(175, "University Corporation for Atmospheric Research (UCAR) - United States"); + + ///Cooperative Institute for Meteorological Satellite Studies (CIMSS) - United States (176) + public static Center UsCimss { get; } = new Center(176, + "Cooperative Institute for Meteorological Satellite Studies (CIMSS) - United States"); + + ///NOAA National Ocean Service - United States (177) + public static Center UsNoaaNos { get; } = new Center(177, "NOAA National Ocean Service - United States"); + + ///Cook Islands (NMC) (190) + public static Center CookIslands { get; } = new Center(190, "Cook Islands (NMC)"); + + ///French Polynesia (NMC) (191) + public static Center FrenchPolynesia { get; } = new Center(191, "French Polynesia (NMC)"); + + ///Tonga (NMC) (192) + public static Center Tonga { get; } = new Center(192, "Tonga (NMC)"); + + ///Vanuatu (NMC) (193) + public static Center Vanuatu { get; } = new Center(193, "Vanuatu (NMC)"); + + ///Brunei Darussalam (NMC) (194) + public static Center BruneiDarussalam { get; } = new Center(194, "Brunei Darussalam (NMC)"); + + ///Indonesia (NMC) (195) + public static Center Indonesia { get; } = new Center(195, "Indonesia (NMC)"); + + ///Kiribati (NMC) (196) + public static Center Kiribati { get; } = new Center(196, "Kiribati (NMC)"); + + ///Federated States of Micronesia (NMC) (197) + public static Center Micronesia { get; } = new Center(197, "Federated States of Micronesia (NMC)"); + + ///New Caledonia (NMC) (198) + public static Center NewCaledonia { get; } = new Center(198, "New Caledonia (NMC)"); + + ///Niue (199) + public static Center Niue { get; } = new Center(199, "Niue"); + + ///Papua New Guinea (NMC) (200) + public static Center PapuaNewGuinea { get; } = new Center(200, "Papua New Guinea (NMC)"); + + ///Philippines (NMC) (201) + public static Center Philippines { get; } = new Center(201, "Philippines (NMC)"); + + ///Samoa (NMC) (202) + public static Center Samoa { get; } = new Center(202, "Samoa (NMC)"); + + ///Solomon Islands (NMC) (203) + public static Center SolomonIslands { get; } = new Center(203, "Solomon Islands (NMC)"); + + ///National Institute of Water and Atmospheric Research (NIWA - New Zealand) (204) + public static Center NzNiwa { get; } = + new Center(204, "National Institute of Water and Atmospheric Research (NIWA - New Zealand)"); + + ///Frascati (ESA/ESRIN) (210) + public static Center Frascati { get; } = new Center(210, "Frascati (ESA/ESRIN)"); + + ///Lanion (211) + public static Center Lanion { get; } = new Center(211, "Lanion"); + + ///Lisboa (212) + public static Center Lisboa { get; } = new Center(212, "Lisboa"); + + ///Reykjavik (213) + public static Center Reykjavik { get; } = new Center(213, "Reykjavik"); + + ///Madrid (214) + public static Center Madrid { get; } = new Center(214, "Madrid"); + + ///Zürich (215) + public static Center Zurich { get; } = new Center(215, "Zürich"); + + ///Service ARGOS - Toulouse (216) + public static Center ToulouseArgos { get; } = new Center(216, "Service ARGOS - Toulouse"); + + ///Bratislava (217) + public static Center Bratislava { get; } = new Center(217, "Bratislava"); + + ///Budapest (218) + public static Center Budapest { get; } = new Center(218, "Budapest"); + + ///Ljubljana (219) + public static Center Ljubljana { get; } = new Center(219, "Ljubljana"); + + ///Warsaw (220) + public static Center Warsaw { get; } = new Center(220, "Warsaw"); + + ///Zagreb (221) + public static Center Zagreb { get; } = new Center(221, "Zagreb"); + + ///Albania (NMC) (222) + public static Center Albania { get; } = new Center(222, "Albania (NMC)"); + + ///Armenia (NMC) (223) + public static Center Armenia { get; } = new Center(223, "Armenia (NMC)"); + + ///Austria (NMC) (224) + public static Center Austria { get; } = new Center(224, "Austria (NMC)"); + + ///Azerbaijan (NMC) (225) + public static Center Azerbaijan { get; } = new Center(225, "Azerbaijan (NMC)"); + + ///Belarus (NMC) (226) + public static Center Belarus { get; } = new Center(226, "Belarus (NMC)"); + + ///Belgium (NMC) (227) + public static Center Belgium { get; } = new Center(227, "Belgium (NMC)"); + + ///Bosnia and Herzegovina (NMC) (228) + public static Center BosniaHerzegovina { get; } = new Center(228, "Bosnia and Herzegovina (NMC)"); + + ///Bulgaria (NMC) (229) + public static Center Bulgaria { get; } = new Center(229, "Bulgaria (NMC)"); + + ///Cyprus (NMC) (230) + public static Center Cyprus { get; } = new Center(230, "Cyprus (NMC)"); + + ///Estonia (NMC) (231) + public static Center Estonia { get; } = new Center(231, "Estonia (NMC)"); + + ///Georgia (NMC) (232) + public static Center Georgia { get; } = new Center(232, "Georgia (NMC)"); + + ///Dublin (233) + public static Center Dublin { get; } = new Center(233, "Dublin"); + + ///Israel (NMC) (234) + public static Center Israel { get; } = new Center(234, "Israel (NMC)"); + + ///Jordan (NMC) (235) + public static Center Jordan { get; } = new Center(235, "Jordan (NMC)"); + + ///Latvia (NMC) (236) + public static Center Latvia { get; } = new Center(236, "Latvia (NMC)"); + + ///Lebanon (NMC) (237) + public static Center Lebanon { get; } = new Center(237, "Lebanon (NMC)"); + + ///Lithuania (NMC) (238) + public static Center Lithuania { get; } = new Center(238, "Lithuania (NMC)"); + + ///Luxembourg (239) + public static Center Luxembourg { get; } = new Center(239, "Luxembourg"); + + ///Malta (NMC) (240) + public static Center Malta { get; } = new Center(240, "Malta (NMC)"); + + ///Monaco (241) + public static Center Monaco { get; } = new Center(241, "Monaco"); + + ///Romania (NMC) (242) + public static Center Romania { get; } = new Center(242, "Romania (NMC)"); + + ///Syrian Arab Republic (NMC) (243) + public static Center Syria { get; } = new Center(243, "Syrian Arab Republic (NMC)"); + + ///The former Yugoslav Republic of Macedonia (NMC) (244) + public static Center NorthMacedonia { get; } = new Center(244, "The former Yugoslav Republic of Macedonia (NMC)"); + + ///Ukraine (NMC) (245) + public static Center Ukraine { get; } = new Center(245, "Ukraine (NMC)"); + + ///Republic of Moldova (NMC) (246) + public static Center Moldova { get; } = new Center(246, "Republic of Moldova (NMC)"); + + ///Operational Programme for the Exchange of weather RAdar information (OPERA) - EUMETNET (247) + public static Center EumetnetOpera { get; } = new Center(247, + "Operational Programme for the Exchange of weather RAdar information (OPERA) - EUMETNET"); + + ///Montenegro (NMC) (248) + public static Center Montenegro { get; } = new Center(248, "Montenegro (NMC)"); + + ///COnsortium for Small scale MOdelling (COSMO) (250) + public static Center Cosmo { get; } = new Center(250, "COnsortium for Small scale MOdelling (COSMO)"); + + ///Meteorological Cooperation on Operational NWP (MetCoOp) (251) + public static Center MetCoOp { get; } = new Center(251, "Meteorological Cooperation on Operational NWP (MetCoOp)"); + + ///Max Planck Institute for Meteorology (MPI-M) (252) + public static Center MpiM { get; } = new Center(252, "Max Planck Institute for Meteorology (MPI-M)"); + + ///EUMETSAT Operation Center (254) + public static Center Eumetsat { get; } = new Center(254, "EUMETSAT Operation Center"); + + public static IReadOnlyCollection
AllCenters = new List
+ { + WmoSecretariat, + Melbourne, + Melbourne2, + Melbourne3, + Moscow, + Moscow5, + Moscow6, + UsNcep, + UsNwstg, + UsNwsOther, + Cairo, + CairoReserved, + Dakar, + DakarReserved, + Nairobi, + NairobiReserved, + Casablanca, + Tunis, + TunisCasablanca, + TunisCasablancaReserved, + LasPalmas, + Algiers, + Acmad, + Mozambique, + Pretoria, + LaReunion, + Khabarovsk, + KhabarovskReserved, + NewDelhi, + NewDelhiReserved, + Novosibirsk, + NovosibirskReserved, + Tashkent, + Jeddah, + Tokyo, + TokyoReserved, + Bangkok, + Ulaanbaatar, + Beijing, + BeijingReserved, + Seoul, + BuenosAires, + BuenosAiresReserved, + Brasilia, + BrasiliaReserved, + Santiago, + BrazilianSpaceAgencyInpe, + Colombia, + Ecuador, + Peru, + Venezuela, + Miami, + MiamiNhc, + Montreal, + MontrealReserved, + SanFrancisco, + ArincCenter, + UsAfGwc, + CaFnmoc, + UsNoaaForecastSystemsLaboratory, + UsNcar, + ArgosLandover, + UsNoo, + Iri, + Honolulu, + Darwin, + DarwinReserved, + Melbourne67, + Wellington, + WellingtonReserved, + Nadi, + Singapore, + Malaysia, + UkMeteorologicalOffice, + UkMeteorologicalOfficeReserved, + Moscow76, + Offenbach, + OffenbachReserved, + Rome, + RomeReserved, + Norrkoping, + NorrkopingReserved, + Toulouse, + Toulouse85, + Helsinki, + Belgrade, + Oslo, + Prague, + Episkopi, + Ankara, + FrankfurtMain, + London, + Copenhagen, + Rota, + Athens, + Esa, + Ecmwf, + DeBilt, + Brazzaville, + Abidjan, + Libya, + Madagascar, + Mauritius, + Niger, + Seychelles, + Uganda, + Tanzania, + Zimbabwe, + HongKong, + Afghanistan, + Bahrain, + Bangladesh, + Bhutan, + Cambodia, + DprKorea, + Iran, + Iraq, + Kazakhstan, + Kuwait, + Kyrgyzstan, + Laos, + Macao, + Maldives, + Myanmar, + Nepal, + Oman, + Pakistan, + Qatar, + Yemen, + SriLanka, + Tajikistan, + Turkmenistan, + Emirates, + Uzbekistan, + Vietnam, + Bolivia, + Guyana, + Paraguay, + Suriname, + Uruguay, + FrenchGuyana, + BrNhc, + ArConaz, + AntiguaBarbuda, + Bahamas, + Barbados, + Belize, + Caribbean, + SanJose, + Cuba, + Dominica, + DominicanRepublic, + ElSalvador, + UsNoaaNesdis, + UsNoaaOar, + Guatemala, + Haiti, + Honduras, + Jamaica, + MexicoCity, + CuracaoSintMaarten, + Nicaragua, + Panama, + SaintLucia, + TrinidadTobago, + FrenchDepartments, + UsNasa, + CaIsdmMeds, + UsUcar, + UsCimss, + UsNoaaNos, + CookIslands, + FrenchPolynesia, + Tonga, + Vanuatu, + BruneiDarussalam, + Indonesia, + Kiribati, + Micronesia, + NewCaledonia, + Niue, + PapuaNewGuinea, + Philippines, + Samoa, + SolomonIslands, + NzNiwa, + Frascati, + Lanion, + Lisboa, + Reykjavik, + Madrid, + Zurich, + ToulouseArgos, + Bratislava, + Budapest, + Ljubljana, + Warsaw, + Zagreb, + Albania, + Armenia, + Austria, + Azerbaijan, + Belarus, + Belgium, + BosniaHerzegovina, + Bulgaria, + Cyprus, + Estonia, + Georgia, + Dublin, + Israel, + Jordan, + Latvia, + Lebanon, + Lithuania, + Luxembourg, + Malta, + Monaco, + Romania, + Syria, + NorthMacedonia, + Ukraine, + Moldova, + EumetnetOpera, + Montenegro, + Cosmo, + MetCoOp, + MpiM, + Eumetsat, + }; +} \ No newline at end of file diff --git a/tmp/Grib2/Dataset.cs b/tmp/Grib2/Dataset.cs new file mode 100644 index 0000000..7e82e6c --- /dev/null +++ b/tmp/Grib2/Dataset.cs @@ -0,0 +1,121 @@ +/* + * This file is part of NGrib. + * + * Copyright © 2020 Nicolas Mangué + * + * Copyright 2006-2010 Seaware AB, PO Box 1244, SE-131 28 + * Nacka Strand, Sweden, info@seaware.se. + * + * Copyright 1997-2006 Unidata Program Center/University + * Corporation for Atmospheric Research, P.O. Box 3000, Boulder, CO 80307, + * support@unidata.ucar.edu. + * + * NGrib is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * NGrib is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with NGrib. If not, see . + */ + +using NGrib.Grib2.CodeTables; +using NGrib.Grib2.Sections; + +namespace NGrib.Grib2; + +/// +/// Represents a data set in a GRIB2 message. +/// +public sealed class DataSet +{ + /// + /// Message in which the data set is provided. + /// + public Message Message { get; } + + /// + /// Local Use Section. + /// + /// null if not used. + public LocalUseSection LocalUseSection { get; } + + /// + /// Grid Definition Section. + /// + public GridDefinitionSection GridDefinitionSection { get; } + + /// + /// Product Definition Section. + /// + public ProductDefinitionSection ProductDefinitionSection { get; } + + /// + /// Bitmap Section. + /// + public BitmapSection BitmapSection { get; } + + /// + /// Data Representation Section. + /// + public DataRepresentationSection DataRepresentationSection { get; } + + /// + /// Data Section. + /// + public DataSection DataSection { get; } + + /// + /// Parameter defined in the Product Definition Section. + /// + public Parameter? Parameter => ProductDefinitionSection.ProductDefinition?.Parameter; + + internal DataSet( + Message message, + LocalUseSection localUseSection, + GridDefinitionSection gridDefinitionSection, + ProductDefinitionSection productDefinitionSection, + DataRepresentationSection dataRepresentationSection, + BitmapSection bitmapSection, + DataSection dataSection) + { + Message = message; + GridDefinitionSection = gridDefinitionSection; + ProductDefinitionSection = productDefinitionSection; + DataRepresentationSection = dataRepresentationSection; + BitmapSection = bitmapSection; + DataSection = dataSection; + LocalUseSection = localUseSection; + } + + internal IEnumerable> GetData(BufferedBinaryReader reader) + { + return GridDefinitionSection.GridDefinition.EnumerateGridPoints() + .Zip(GetRawData(reader), (p, v) => new KeyValuePair(p, v)); + } + + internal IEnumerable GetRawData(BufferedBinaryReader reader) + { + if (DataRepresentationSection.DataRepresentation == null) + { + throw new NotSupportedException($"Data Representation Template {DataRepresentationSection.TemplateNumber} is not supported."); + } + + var bitmap = BitmapSection.GetBitmap(reader); + + using var valuesEnumerator = DataRepresentationSection.DataRepresentation + .EnumerateDataValues(reader, DataSection, DataRepresentationSection.DataPointsNumber) + .GetEnumerator(); + + foreach (var isValueDefined in bitmap) + { + var v = isValueDefined && valuesEnumerator.MoveNext() ? valuesEnumerator.Current : (double?)null; + yield return v; + } + } +} \ No newline at end of file diff --git a/tmp/Grib2/Grib2File.cs b/tmp/Grib2/Grib2File.cs new file mode 100644 index 0000000..3639184 --- /dev/null +++ b/tmp/Grib2/Grib2File.cs @@ -0,0 +1,59 @@ +using NGrib.Grib2.Sections; + +namespace NGrib.Grib2; + +public class Grib2File +{ + public Message ReadGrib2Message(BufferedBinaryReader reader, out long currentPosition) + { + var indicatorSection = IndicatorSection.BuildFrom(reader); + var identificationSection = IdentificationSection.BuildFrom(reader); + + var message = new Message(indicatorSection, identificationSection); + + LocalUseSection localUseSection = null; + do + { + if (reader.PeekSection().Is(SectionCode.LocalUseSection)) + { + localUseSection = LocalUseSection.BuildFrom(reader); + } + + while (reader.PeekSection().Is(SectionCode.GridDefinitionSection)) + { + var gridDefinitionSection = GridDefinitionSection.BuildFrom(reader); + + while (reader.PeekSection().Is(SectionCode.ProductDefinitionSection)) + { + var productDefinitionSection = ProductDefinitionSection.BuildFrom(reader, indicatorSection.Discipline); + var dataRepresentationSection = DataRepresentationSection.BuildFrom(reader); + + var bitmapSection = BitmapSection.BuildFrom(reader, dataRepresentationSection.DataPointsNumber); + + var dataSection = DataSection.BuildFrom(reader); + + message.AddDataset( + localUseSection, + gridDefinitionSection, + productDefinitionSection, + dataRepresentationSection, + bitmapSection, + dataSection); + } + } + } while (!reader.PeekSection().Is(SectionCode.EndSection)); + + EndSection.BuildFrom(reader); + + // Saves and restore the current position + // to avoid losing track of the current message + // if a data set read happens during the enumeration + currentPosition = reader.Position; + return message; + } + + public IEnumerable>> GetData(BufferedBinaryReader reader, Message message) + { + return message.DataSets.Select(x => x.GetData(reader)); + } +} \ No newline at end of file diff --git a/tmp/Grib2/Message.cs b/tmp/Grib2/Message.cs new file mode 100644 index 0000000..46b31cc --- /dev/null +++ b/tmp/Grib2/Message.cs @@ -0,0 +1,79 @@ +/* + * This file is part of NGrib. + * + * Copyright © 2020 Nicolas Mangué + * + * Copyright 2006-2010 Seaware AB, PO Box 1244, SE-131 28 + * Nacka Strand, Sweden, info@seaware.se. + * + * Copyright 1997-2006 Unidata Program Center/University + * Corporation for Atmospheric Research, P.O. Box 3000, Boulder, CO 80307, + * support@unidata.ucar.edu. + * + * NGrib is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * NGrib is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with NGrib. If not, see . + */ + +using NGrib.Grib2.Sections; + +namespace NGrib.Grib2; + +/// +/// Represents a GRIB2 message. +/// +public sealed class Message +{ + /// + /// Indicator Section. + /// + public IndicatorSection IndicatorSection { get; } + + /// + /// Identification Section. + /// + public IdentificationSection IdentificationSection { get; } + + /// + /// Data sets in the message. + /// + public IReadOnlyCollection DataSets => dataSets; + + private readonly List dataSets; + + internal Message(IndicatorSection indicatorSection, IdentificationSection identificationSection) + { + IndicatorSection = indicatorSection ?? throw new ArgumentNullException(nameof(indicatorSection)); + IdentificationSection = identificationSection ?? throw new ArgumentNullException(nameof(identificationSection)); + dataSets = new List(); + } + + internal void AddDataset( + LocalUseSection lus, + GridDefinitionSection gds, + ProductDefinitionSection pds, + DataRepresentationSection drs, + BitmapSection bs, + DataSection ds) + { + var record = new DataSet( + this, + lus, + gds, + pds, + drs, + bs, + ds); + + dataSets.Add(record); + } +} \ No newline at end of file diff --git a/tmp/Grib2/Sections/0_IndicatorSection.cs b/tmp/Grib2/Sections/0_IndicatorSection.cs new file mode 100644 index 0000000..ff5df8c --- /dev/null +++ b/tmp/Grib2/Sections/0_IndicatorSection.cs @@ -0,0 +1,96 @@ +/* + * This file is part of NGrib. + * + * Copyright © 2020 Nicolas Mangué + * + * Copyright 2006-2010 Seaware AB, PO Box 1244, SE-131 28 + * Nacka Strand, Sweden, info@seaware.se. + * + * Copyright 1997-2006 Unidata Program Center/University + * Corporation for Atmospheric Research, P.O. Box 3000, Boulder, CO 80307, + * support@unidata.ucar.edu. + * + * NGrib is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * NGrib is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with NGrib. If not, see . + */ + +using System.Numerics; +using NGrib.Grib2.CodeTables; + +namespace NGrib.Grib2.Sections; + +/// +/// Section 0 - Indicator Section +/// +public sealed class IndicatorSection +{ + private const int INDICATOR_SECTION_LENGTH = 16; + + /// + /// Length of section in octets. + /// + public long Length { get; } + + /// + /// Number of section. + /// + public int Section { get; } + + /// + /// Discipline from the GRIB Code Table 0.0. + /// + public Discipline Discipline { get; } + + /// + /// GRIB Edition Number. + /// + public int GribEdition { get; } + + /// + /// Total length of GRIB message in octets (including Section 0). + /// + public BigInteger TotalLength { get; } + + private IndicatorSection(int disciplineCode, int gribEdition, BigInteger totalLength) + { + Length = INDICATOR_SECTION_LENGTH; + Section = (int) SectionCode.IndicatorSection; + Discipline = (Discipline)disciplineCode; + + GribEdition = gribEdition; + TotalLength = totalLength; + } + + internal static IndicatorSection BuildFrom(BufferedBinaryReader reader) + { + var fileStart = reader.Read(Constants.GribFileStart.Length); + if (!Constants.GribFileStart.SequenceEqual(fileStart)) + { + throw new BadGribFormatException("Invalid file start."); + } + + // Ignore the 2 reserved bytes + reader.Skip(2); + + var disciplineNumber = reader.ReadUInt8(); + var gribEdition = reader.ReadUInt8(); + if (gribEdition != 2) + { + throw new NotSupportedException($"Only GRIB edition 2 is supported. GRIB edition {gribEdition} is not yet supported"); + } + + var totalLength = reader.ReadUInt64(); + + return new IndicatorSection(disciplineNumber, 2, totalLength); + } +} \ No newline at end of file diff --git a/tmp/Grib2/Sections/1_IdentificationSection.cs b/tmp/Grib2/Sections/1_IdentificationSection.cs new file mode 100644 index 0000000..ea9270b --- /dev/null +++ b/tmp/Grib2/Sections/1_IdentificationSection.cs @@ -0,0 +1,150 @@ +/* + * This file is part of NGrib. + * + * Copyright © 2020 Nicolas Mangué + * + * Copyright 2006-2010 Seaware AB, PO Box 1244, SE-131 28 + * Nacka Strand, Sweden, info@seaware.se. + * + * Copyright 1997-2006 Unidata Program Center/University + * Corporation for Atmospheric Research, P.O. Box 3000, Boulder, CO 80307, + * support@unidata.ucar.edu. + * + * NGrib is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * NGrib is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with NGrib. If not, see . + */ + +using NGrib.Grib2.CodeTables; + +namespace NGrib.Grib2.Sections; + +/// +/// Section 1 - Identification Section +/// +public sealed record IdentificationSection +{ + /// + /// Length of section in octets. + /// + public long Length { get; } + + /// + /// Number of section. + /// + public int Section { get; } + + /// + /// Identification of originating/generating center. + /// + public int CenterCode { get; } + + /// + /// Originating/generating center. + /// + public Center Center { get; } + + /// + /// Identification of originating/generating sub-centre (allocated by originating/generating Centre) + /// + public int SubCenterCode { get; } + + /// + /// GRIB Master Tables Version Number. + /// + public int MasterTableVersion { get; } + + /// + /// Version number of GRIB Local Tables used to augment Master Tables. + /// + public int LocalTableVersion { get; } + + /// + /// Significance of Reference Time. + /// + public ReferenceTimeSignificance ReferenceTimeSignificance { get; } + + /// + /// Reference time of data. + /// + public DateTime ReferenceTime { get; } + + /// + /// Production status of processed data in this GRIB message. + /// + public ProductStatus ProductStatus { get; } + + /// + /// Type of processed data in this GRIB message. + /// + public ProductType ProductType { get; } + + private IdentificationSection(long length, int section, int centerCode, int subCenterCode, int masterTableVersion, int localTableVersion, int referenceTimeSignificanceCode, DateTime referenceTime, int productStatusCode, int productTypeCode) + { + Length = length; + Section = section; + CenterCode = centerCode; + Center = Center.GetCenterById(CenterCode); + SubCenterCode = subCenterCode; + MasterTableVersion = masterTableVersion; + LocalTableVersion = localTableVersion; + ReferenceTimeSignificance = (ReferenceTimeSignificance)referenceTimeSignificanceCode; + ReferenceTime = referenceTime; + ProductStatus = (ProductStatus)productStatusCode; + ProductType = (ProductType)productTypeCode; + } + + internal static IdentificationSection BuildFrom(BufferedBinaryReader reader) + { + // section 1 octet 1-4 (length of section) + var length = reader.ReadUInt32(); + + var section = reader.ReadUInt8(); + if (section != (int) SectionCode.IdentificationSection) + { + return null; + } + + // Center octet 6-7 + var centerCode = reader.ReadUInt16(); + + // Center octet 8-9 + var subCenterCode = reader.ReadUInt16(); + + // Parameter master table octet 10 + var masterTableVersion = reader.ReadUInt8(); + + // Parameter local table octet 11 + var localTableVersion = reader.ReadUInt8(); + + // significanceOfRT octet 12 + var significanceOfRt = reader.ReadUInt8(); + + // octets 13-19 (base time of forecast) + var refTime = reader.ReadDateTime(); + + var productStatusCode = reader.ReadUInt8(); + + var productTypeCode = reader.ReadUInt8(); + return new IdentificationSection( + length, + section, + centerCode, + subCenterCode, + masterTableVersion, + localTableVersion, + significanceOfRt, + refTime, + productStatusCode, + productTypeCode); + } +} \ No newline at end of file diff --git a/tmp/Grib2/Sections/2_LocalUseSection.cs b/tmp/Grib2/Sections/2_LocalUseSection.cs new file mode 100644 index 0000000..9fd09e7 --- /dev/null +++ b/tmp/Grib2/Sections/2_LocalUseSection.cs @@ -0,0 +1,71 @@ +/* + * This file is part of NGrib. + * + * Copyright © 2020 Nicolas Mangué + * + * Copyright 2006-2010 Seaware AB, PO Box 1244, SE-131 28 + * Nacka Strand, Sweden, info@seaware.se. + * + * Copyright 1997-2006 Unidata Program Center/University + * Corporation for Atmospheric Research, P.O. Box 3000, Boulder, CO 80307, + * support@unidata.ucar.edu. + * + * NGrib is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * NGrib is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with NGrib. If not, see . + */ + +namespace NGrib.Grib2.Sections; + +/// +/// Section 2 - Local Use Section +/// +public sealed class LocalUseSection +{ + /// + /// Length of section in octets. + /// + public long Length { get; } + + /// + /// Number of section. + /// + public int Section { get; } + + /// + /// Position at which the local use data begins. + /// + internal long ContentOffset { get; } + + private LocalUseSection(long length, int section, long contentOffset) + { + Length = length; + Section = section; + ContentOffset = contentOffset; + } + + internal static LocalUseSection BuildFrom(BufferedBinaryReader reader) + { + // octets 1-4 (Length of GDS) + var length = reader.ReadUInt32(); + + var section = reader.ReadUInt8(); + if (section != (int) SectionCode.LocalUseSection) + { + return null; + } + + var contentOffset = reader.Position; + reader.Skip((int) length - 5); + return new LocalUseSection(length, section, contentOffset); + } +} \ No newline at end of file diff --git a/tmp/Grib2/Sections/3_GridDefinitionSection.cs b/tmp/Grib2/Sections/3_GridDefinitionSection.cs new file mode 100644 index 0000000..76d9021 --- /dev/null +++ b/tmp/Grib2/Sections/3_GridDefinitionSection.cs @@ -0,0 +1,151 @@ +/* + * This file is part of NGrib. + * + * Copyright © 2020 Nicolas Mangué + * + * Copyright 2006-2010 Seaware AB, PO Box 1244, SE-131 28 + * Nacka Strand, Sweden, info@seaware.se. + * + * Copyright 1997-2006 Unidata Program Center/University + * Corporation for Atmospheric Research, P.O. Box 3000, Boulder, CO 80307, + * support@unidata.ucar.edu. + * + * NGrib is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * NGrib is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with NGrib. If not, see . + */ + +using NGrib.Grib2.Templates; +using NGrib.Grib2.Templates.GridDefinitions; + +namespace NGrib.Grib2.Sections; + +/// +/// Section 3 - Grid Definition Section +/// +public sealed class GridDefinitionSection +{ + /// + /// Length of section in octets. + /// + public long Length { get; } + + /// + /// Number of section. + /// + public int Section { get; } + + /// + /// Source of grid definition. + /// + public int Source { get; } + + /// + /// Number of data points. + /// + public long DataPointsNumber { get; } + + /// + /// Number of octets for optional list of numbers defining number of points. + /// + public int OptionalListNumberLength { get; } + + /// + /// Interpretation of list of numbers defining number of points. + /// + public int OptionalListInterpretationCode { get; } + + /// + /// Grid Definition Template Number + /// + public int TemplateNumber { get; } + + /// + /// Grid Definition Template + /// + public GridDefinition GridDefinition { get; } + + private GridDefinitionSection( + long length, + int section, + int source, + long dataPointsNumber, + int oLon, + int ioLon, + int templateNumber, + GridDefinition gridDefinition) + { + TemplateNumber = templateNumber; + Length = length; + Section = section; + Source = source; + DataPointsNumber = dataPointsNumber; + OptionalListNumberLength = oLon; + OptionalListInterpretationCode = ioLon; + GridDefinition = gridDefinition; + } + + internal static GridDefinitionSection BuildFrom(BufferedBinaryReader reader) + { + var currentPosition = reader.Position; + var length = reader.ReadUInt32(); + + var section = reader.ReadUInt8(); // This is section 3 + + if (section != (int) SectionCode.GridDefinitionSection) + { + throw new UnexpectedGribSectionException(SectionCode.GridDefinitionSection, section); + } + + var source = reader.ReadUInt8(); + + var numberPoints = reader.ReadUInt32(); + + var olLength = reader.ReadUInt8(); + + var olInterpretation = reader.ReadUInt8(); + + var templateNumber = reader.ReadUInt16(); + + var gridDefinition = GridDefinitionFactories.Build(reader, templateNumber); + + // Prevent from over-reading the stream + reader.Seek(currentPosition + length, SeekOrigin.Begin); + + return new GridDefinitionSection(length, section, source, numberPoints, olLength, olInterpretation, + templateNumber, gridDefinition); + } + + private static readonly TemplateFactory GridDefinitionFactories = + new TemplateFactory + { + {0, r => new LatLonGridDefinition(r)}, + {1, r => new RotatedLatLonGridDefinition(r)}, + {2, r => new StretchedLatLonGridDefinition(r)}, + {3, r => new StretchedRotatedLatLonGridDefinition(r)}, + {10, r => new MercatorGridDefinition(r)}, + {20, r => new PolarStereographicProjectionGridDefinition(r)}, + {30, r => new LambertConformalGridDefinition(r)}, + {31, r => new AlbersEqualAreaGridDefinition(r)}, + {40, r => new GaussianLatLonGridDefinition(r)}, + {41, r => new RotatedGaussianLatLonGridDefinition(r)}, + {42, r => new StretchedGaussianLatLonGridDefinition(r)}, + {43, r => new StretchedRotatedGaussianLatLonGridDefinition(r)}, + {50, r => new SphericalHarmonicCoefficientsGridDefinition(r)}, + {51, r => new RotatedSphericalHarmonicCoefficientsGridDefinition(r)}, + {52, r => new StretchedSphericalHarmonicCoefficientsGridDefinition(r)}, + {53, r => new StretchedRotatedSphericalHarmonicCoefficientsGridDefinition(r)}, + {90, r => new SpaceViewPerspectiveOrOrthographicGridDefinition(r)}, + {100, r => new TriangularGridBasedOnAnIcosahedronGridDefinition(r)}, + {110, r => new EquatorialAzimuthalEquidistantProjectionGridDefinition(r)} + }; +} \ No newline at end of file diff --git a/tmp/Grib2/Sections/4_ProductDefinitionSection.cs b/tmp/Grib2/Sections/4_ProductDefinitionSection.cs new file mode 100644 index 0000000..7d6cf9b --- /dev/null +++ b/tmp/Grib2/Sections/4_ProductDefinitionSection.cs @@ -0,0 +1,115 @@ +/* + * This file is part of NGrib. + * + * Copyright © 2020 Nicolas Mangué + * + * Copyright 2006-2010 Seaware AB, PO Box 1244, SE-131 28 + * Nacka Strand, Sweden, info@seaware.se. + * + * Copyright 1997-2006 Unidata Program Center/University + * Corporation for Atmospheric Research, P.O. Box 3000, Boulder, CO 80307, + * support@unidata.ucar.edu. + * + * NGrib is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * NGrib is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with NGrib. If not, see . + */ + +using NGrib.Grib2.CodeTables; +using NGrib.Grib2.Templates; +using NGrib.Grib2.Templates.ProductDefinitions; + +namespace NGrib.Grib2.Sections; + +/// +/// Section 4 - Product Definition Section +/// +public sealed class ProductDefinitionSection +{ + /// + /// Length of section in octets. + /// + public long Length { get; } + + /// + /// Number of section. + /// + public int Section { get; } + + /// + /// Number of coordinates values after Template. + /// + public int CoordinatesAfterTemplateNumber { get; } + + /// + /// Product Definition Template Number + /// + public int ProductDefinitionTemplateNumber { get; } + + /// + /// Product Definition Template. + /// + public ProductDefinition ProductDefinition { get; } + + private ProductDefinitionSection( + long length, + int section, + int coordinatesAfterTemplateNumber, + int productDefinitionTemplateNumber, + ProductDefinition productDefinition) + { + CoordinatesAfterTemplateNumber = coordinatesAfterTemplateNumber; + ProductDefinitionTemplateNumber = productDefinitionTemplateNumber; + ProductDefinition = productDefinition; + Length = length; + Section = section; + } + + internal static ProductDefinitionSection BuildFrom(BufferedBinaryReader reader, Discipline discipline) + { + var currentPosition = reader.Position; + + // octets 1-4 (Length of PDS) + var length = reader.ReadUInt32(); + + // octet 5 + var section = reader.ReadUInt8(); + + // octet 6-7 + var coordinates = reader.ReadUInt16(); + + // octet 8-9 + var productDefinitionTemplateNumber = reader.ReadUInt16(); + + var productDefinition = ProductDefinitionFactories.Build(reader, productDefinitionTemplateNumber, discipline); + + // Prevent from over-reading the stream + reader.Seek(currentPosition + length, SeekOrigin.Begin); + + return new ProductDefinitionSection(length, section, coordinates, productDefinitionTemplateNumber, + productDefinition); + } + + public bool TryGet(TemplateContent content, out T value) => ProductDefinition.TryGet(content, out value); + + private static readonly TemplateFactory ProductDefinitionFactories = + new TemplateFactory + { + {0, (r, args) => new ProductDefinition0000(r, (Discipline) args[0])}, + {1, (r, args) => new ProductDefinition0001(r, (Discipline) args[0])}, + {2, (r, args) => new ProductDefinition0002(r, (Discipline) args[0])}, + {8, (r, args) => new ProductDefinition0008(r, (Discipline) args[0])}, + {11, (r, args) => new ProductDefinition0011(r, (Discipline) args[0])}, + {12, (r, args) => new ProductDefinition0012(r, (Discipline) args[0])}, + {40, (r, args) => new ProductDefinition0040(r, (Discipline) args[0])} + }; +} \ No newline at end of file diff --git a/tmp/Grib2/Sections/5_DataRepresentationSection.cs b/tmp/Grib2/Sections/5_DataRepresentationSection.cs new file mode 100644 index 0000000..3bb18dc --- /dev/null +++ b/tmp/Grib2/Sections/5_DataRepresentationSection.cs @@ -0,0 +1,115 @@ +/* + * This file is part of NGrib. + * + * Copyright © 2020 Nicolas Mangué + * + * Copyright 2006-2010 Seaware AB, PO Box 1244, SE-131 28 + * Nacka Strand, Sweden, info@seaware.se. + * + * Copyright 1997-2006 Unidata Program Center/University + * Corporation for Atmospheric Research, P.O. Box 3000, Boulder, CO 80307, + * support@unidata.ucar.edu. + * + * NGrib is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * NGrib is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with NGrib. If not, see . + */ + +using NGrib.Grib2.Templates; +using NGrib.Grib2.Templates.DataRepresentations; + +namespace NGrib.Grib2.Sections; + +/// +/// Section 5 - Data Representation Section +/// +public sealed class DataRepresentationSection +{ + /// + /// Length of section in octets. + /// + public long Length { get; } + + /// + /// Number of section. + /// + public int Section { get; } + + /// + /// Number of data points where one or more values are specified in Section 7 + /// when a bit map is present, total number of data points when a bit map is absent. + /// + public long DataPointsNumber { get; } + + /// + /// Data Representation Template Number. + /// + public int TemplateNumber { get; } + + /// + /// Data Representation Template. + /// + public DataRepresentation DataRepresentation { get; } + + private DataRepresentationSection( + long length, + int section, + long dataPointsNumber, + int templateNumber, + DataRepresentation dataRepresentation) + { + Section = section; + Length = length; + DataPointsNumber = dataPointsNumber; + TemplateNumber = templateNumber; + DataRepresentation = dataRepresentation; + } + + internal static DataRepresentationSection BuildFrom(BufferedBinaryReader reader) + { + var sectionStartPosition = reader.Position; + + // octets 1-4 (Length of DRS) + var length = reader.ReadUInt32(); + + var section = reader.ReadUInt8(); + if (section != (int) SectionCode.DataRepresentationSection) + { + throw new UnexpectedGribSectionException( + SectionCode.DataRepresentationSection, + section + ); + } + + var dataPoints = reader.ReadUInt32(); + + var dataTemplateNumber = reader.ReadUInt16(); + + var dataRepresentation = DataRepresentationFactory.Build(reader, dataTemplateNumber); + + // Prevent from over-reading the stream + reader.Seek(sectionStartPosition + length, SeekOrigin.Begin); + + return new DataRepresentationSection(length, section, dataPoints, dataTemplateNumber, dataRepresentation); + } + + private static readonly TemplateFactory DataRepresentationFactory = + new TemplateFactory + { + { 0, r => new GridPointDataSimplePacking(r) }, + { 2, r => new GridPointDataComplexPacking(r) }, + { 3, r => new GridPointDataComplexPackingAndSpatialDifferencing(r) }, + { 40, r => new GridPointDataJpeg2000CodeStream(r) }, + { 40000, r => new GridPointDataJpeg2000CodeStream(r) }, + { 50002, r => new GridPointDataEcmwfSecondOrderPacking(r) }, + }; +} \ No newline at end of file diff --git a/tmp/Grib2/Sections/6_BitmapSection.cs b/tmp/Grib2/Sections/6_BitmapSection.cs new file mode 100644 index 0000000..44a8378 --- /dev/null +++ b/tmp/Grib2/Sections/6_BitmapSection.cs @@ -0,0 +1,164 @@ +/* + * This file is part of NGrib. + * + * Copyright © 2020 Nicolas Mangué + * + * Copyright 2006-2010 Seaware AB, PO Box 1244, SE-131 28 + * Nacka Strand, Sweden, info@seaware.se. + * + * Copyright 1997-2006 Unidata Program Center/University + * Corporation for Atmospheric Research, P.O. Box 3000, Boulder, CO 80307, + * support@unidata.ucar.edu. + * + * NGrib is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * NGrib is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with NGrib. If not, see . + */ + +using System.Collections; + +namespace NGrib.Grib2.Sections; + +/// +/// Section 6 - Bitmap Section +/// +public sealed class BitmapSection +{ + /// + /// Length of section in octets. + /// + public long Length { get; } + + /// + /// Number of section. + /// + public int Section { get; } + + /// + /// Bit-map indicator code. + /// + public int BitMapIndicatorCode { get; } + + /// + /// Position of the bitmap start. + /// + public long BitmapOffset { get; } + + /// + /// Number of data points. + /// + /// + /// As defined in the Grid Definition Section when there is no bitmap. + /// + private readonly long dataPointsNumber; + + private BitmapSection(long length, int section, int bitmapIndicatorCode, long dataPointsNumber, long bitmapOffset) + { + BitmapOffset = bitmapOffset; + Length = length; + Section = section; + BitMapIndicatorCode = bitmapIndicatorCode; + this.dataPointsNumber = bitmapIndicatorCode == 0 ? (length - 6) * 8 : dataPointsNumber; + } + + internal static BitmapSection BuildFrom(BufferedBinaryReader raf, long dataPointsNumber) + { + var length = raf.ReadUInt32(); + + var section = raf.ReadUInt8(); + if (section != (int) SectionCode.BitmapSection) + { + throw new UnexpectedGribSectionException( + SectionCode.BitmapSection, + section + ); + } + + var bitmapIndicator = raf.ReadUInt8(); + var bitmapOffset = raf.Position; + + // Skip through the bitmap data + // There is no need to load it now + raf.Skip((int) length - 6); + + return new BitmapSection(length, section, bitmapIndicator, dataPointsNumber, bitmapOffset); + } + + internal IEnumerable GetBitmap(BufferedBinaryReader reader) + { + if (BitMapIndicatorCode == 0) + { + reader.Seek(BitmapOffset, SeekOrigin.Begin); + + var bitmap = new BitArray((int)dataPointsNumber, true); + + void TrySet(int i, bool value) + { + if (i < bitmap.Length) + { + bitmap[i] = value; + } + } + + // create new bit map, octet 4 contains number of unused bits at the end + var i = 0; + while (i < bitmap.Length) + { + var bitmapByte = (Bitmask)reader.ReadByte(); + + TrySet(i++, bitmapByte.HasFlag(Bitmask.Bit1)); + TrySet(i++, bitmapByte.HasFlag(Bitmask.Bit2)); + TrySet(i++, bitmapByte.HasFlag(Bitmask.Bit3)); + TrySet(i++, bitmapByte.HasFlag(Bitmask.Bit4)); + TrySet(i++, bitmapByte.HasFlag(Bitmask.Bit5)); + TrySet(i++, bitmapByte.HasFlag(Bitmask.Bit6)); + TrySet(i++, bitmapByte.HasFlag(Bitmask.Bit7)); + TrySet(i++, bitmapByte.HasFlag(Bitmask.Bit8)); + } + + IEnumerable EnumerateBitArray() + { + foreach (bool item in bitmap) + { + yield return item; + } + } + + return EnumerateBitArray(); + } + else + { + IEnumerable EnumerateTrue() + { + for (int i = 0; i < dataPointsNumber; i++) + { + yield return true; + } + } + + return EnumerateTrue(); + } + } + + [Flags] + private enum Bitmask : byte + { + Bit1 = 1 << 7, + Bit2 = 1 << 6, + Bit3 = 1 << 5, + Bit4 = 1 << 4, + Bit5 = 1 << 3, + Bit6 = 1 << 2, + Bit7 = 1 << 1, + Bit8 = 1, + } +} \ No newline at end of file diff --git a/tmp/Grib2/Sections/7_DataSection.cs b/tmp/Grib2/Sections/7_DataSection.cs new file mode 100644 index 0000000..abebad8 --- /dev/null +++ b/tmp/Grib2/Sections/7_DataSection.cs @@ -0,0 +1,84 @@ +/* + * This file is part of NGrib. + * + * Copyright © 2020 Nicolas Mangué + * + * Copyright 2006-2010 Seaware AB, PO Box 1244, SE-131 28 + * Nacka Strand, Sweden, info@seaware.se. + * + * Copyright 1997-2006 Unidata Program Center/University + * Corporation for Atmospheric Research, P.O. Box 3000, Boulder, CO 80307, + * support@unidata.ucar.edu. + * + * NGrib is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * NGrib is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with NGrib. If not, see . + */ + +namespace NGrib.Grib2.Sections; + +/// +/// Section 6 - Data Section +/// +public sealed class DataSection +{ + /// + /// Length of section in octets. + /// + public long Length { get; } + + /// + /// Number of section. + /// + public int Section { get; } + + /// + /// Position of the data start. + /// + public long DataOffset { get; } + + /// + /// Data part length. + /// + public long DataLength { get; } + + private DataSection(long length, int section, long dataOffset, long dataLength) + { + DataOffset = dataOffset; + Length = length; + Section = section; + DataLength = dataLength; + } + + internal static DataSection BuildFrom(BufferedBinaryReader reader) + { + // octets 1-4 (Length of DS) + var length = reader.ReadUInt32(); + + // octet 5 section 7 + var section = reader.ReadUInt8(); + if (section != (int) SectionCode.DataSection) + { + throw new UnexpectedGribSectionException( + SectionCode.DataSection, + section + ); + } + + var dataOffset = reader.Position; + + var dataLength = length - 5; + reader.Skip((int) dataLength); + + return new DataSection(length, section, dataOffset, dataLength); + } +} \ No newline at end of file diff --git a/tmp/Grib2/Sections/8_EndSection.cs b/tmp/Grib2/Sections/8_EndSection.cs new file mode 100644 index 0000000..aba08c1 --- /dev/null +++ b/tmp/Grib2/Sections/8_EndSection.cs @@ -0,0 +1,63 @@ +/* + * This file is part of NGrib. + * + * Copyright © 2020 Nicolas Mangué + * + * Copyright 2006-2010 Seaware AB, PO Box 1244, SE-131 28 + * Nacka Strand, Sweden, info@seaware.se. + * + * Copyright 1997-2006 Unidata Program Center/University + * Corporation for Atmospheric Research, P.O. Box 3000, Boulder, CO 80307, + * support@unidata.ucar.edu. + * + * NGrib is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * NGrib is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with NGrib. If not, see . + */ + +namespace NGrib.Grib2.Sections; + +/// +/// Section 8 - End Section +/// +public sealed class EndSection +{ + /// + /// Length of section in octets. + /// + public long Length { get; } + + /// + /// Number of section. + /// + public int Section { get; } + + private EndSection(long length, int section) + { + Length = length; + Section = section; + } + + internal static EndSection BuildFrom(BufferedBinaryReader reader) + { + var sectionInfos = reader.ReadSectionInfo(); + if (!sectionInfos.Is(SectionCode.EndSection)) + { + throw new UnexpectedGribSectionException( + SectionCode.DataSection, + sectionInfos.SectionCode + ); + } + + return new EndSection(sectionInfos.Length, sectionInfos.SectionCode); + } +} \ No newline at end of file diff --git a/tmp/Grib2/Sections/SectionCode.cs b/tmp/Grib2/Sections/SectionCode.cs new file mode 100644 index 0000000..20d81ad --- /dev/null +++ b/tmp/Grib2/Sections/SectionCode.cs @@ -0,0 +1,71 @@ +/* + * This file is part of NGrib. + * + * Copyright © 2020 Nicolas Mangué + * + * NGrib is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * NGrib is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with NGrib. If not, see . + */ + +namespace NGrib.Grib2.Sections; + +/// +/// Section Codes. +/// +public enum SectionCode +{ + /// + /// Indicator Section Code. + /// + IndicatorSection, + + /// + /// Identification Section Code. + /// + IdentificationSection, + + /// + /// Local Use Section Code. + /// + LocalUseSection, + + /// + /// Grid Definition Section Code. + /// + GridDefinitionSection, + + /// + /// Product Definition Section Code. + /// + ProductDefinitionSection, + + /// + /// Data Representation Section Code. + /// + DataRepresentationSection, + + /// + /// Bitmap Section Code. + /// + BitmapSection, + + /// + /// Data Section Code. + /// + DataSection, + + /// + /// End Section Code. + /// + EndSection +} \ No newline at end of file diff --git a/tmp/Grib2/Sections/SectionInfo.cs b/tmp/Grib2/Sections/SectionInfo.cs new file mode 100644 index 0000000..1b1ec51 --- /dev/null +++ b/tmp/Grib2/Sections/SectionInfo.cs @@ -0,0 +1,63 @@ +/* + * This file is part of NGrib. + * + * Copyright © 2020 Nicolas Mangué + * + * NGrib is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * NGrib is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with NGrib. If not, see . + */ + +namespace NGrib.Grib2.Sections; + +/// +/// Represents basic section information. +/// +public readonly struct SectionInfo +{ + /// + /// Length of section in octets. + /// + public long Length { get; } + + /// + /// Number of section. + /// + public int SectionCode { get; } + + /// + /// Initialize a new instance. + /// + /// Section length. + /// Section code. + public SectionInfo(long length, int sectionCode) + { + Length = length; + SectionCode = sectionCode; + } + + /// + /// Initialize a new instance. + /// + /// Section length. + /// Section code. + public SectionInfo(long length, SectionCode sectionCode) : this(length, (int) sectionCode) + { + } + + /// + /// Indicates whether this instance section code is equal to a specified section code. + /// + /// A section code. + /// true if this instance section is the same as the parameter, false otherwise. + public bool Is(SectionCode sectionCode) => SectionCode == (int) sectionCode; +} \ No newline at end of file diff --git a/tmp/Grib2/Templates/DataRepresentations/0000_GridPointDataSimplePacking.cs b/tmp/Grib2/Templates/DataRepresentations/0000_GridPointDataSimplePacking.cs new file mode 100644 index 0000000..7eb67a9 --- /dev/null +++ b/tmp/Grib2/Templates/DataRepresentations/0000_GridPointDataSimplePacking.cs @@ -0,0 +1,111 @@ +/* + * This file is part of NGrib. + * + * Copyright © 2020 Nicolas Mangué + * + * Copyright 2006-2010 Seaware AB, PO Box 1244, SE-131 28 + * Nacka Strand, Sweden, info@seaware.se. + * + * Copyright 1997-2006 Unidata Program Center/University + * Corporation for Atmospheric Research, P.O. Box 3000, Boulder, CO 80307, + * support@unidata.ucar.edu. + * + * NGrib is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * NGrib is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with NGrib. If not, see . + */ + +using NGrib.Grib2.CodeTables; +using NGrib.Grib2.Sections; + +namespace NGrib.Grib2.Templates.DataRepresentations; + +/// +/// Data Representation Template 5.0: Grid point data - simple packing +/// +public class GridPointDataSimplePacking : DataRepresentation +{ + /// + /// Reference value (R) . + /// + public double ReferenceValue { get; } + + /// + /// Binary scale factor (E). + /// + public int BinaryScaleFactor { get; } + + /// + /// Decimal scale factor (D). + /// + public int DecimalScaleFactor { get; } + + /// + /// Number of bits used for each packed value for simple packing, or for each group reference value for complex packing or spatial differencing. + /// + public int NumberOfBits { get; } + + /// + /// Type of original field values. + /// + public OriginalFieldValuesType OriginalFieldValuesType { get; } + + internal GridPointDataSimplePacking(BufferedBinaryReader reader) + { + ReferenceValue = reader.ReadSingle(); + BinaryScaleFactor = reader.ReadInt16(); + DecimalScaleFactor = reader.ReadInt16(); + NumberOfBits = reader.ReadUInt8(); + + OriginalFieldValuesType = (OriginalFieldValuesType) reader.ReadUInt8(); + } + + private protected override IEnumerable DoEnumerateDataValues(BufferedBinaryReader reader, DataSection dataSection, long dataPointsNumber) + { + IEnumerable ReadPackedValues() + { + reader.NextUIntN(); + for (var i = 0; i < dataPointsNumber; i++) + { + yield return reader.ReadUIntN(NumberOfBits); + } + } + + return Unpack(ReadPackedValues()); + + } + + protected IEnumerable Unpack(IEnumerable packedValues) + { + var d = DecimalScaleFactor; + + var dd = Math.Pow(10, d); + + var r = ReferenceValue; + + var e = BinaryScaleFactor; + + var ee = Math.Pow(2.0, e); + + // Y * 10**D = R + (X1 + X2) * 2**E + // E = binary scale factor + // D = decimal scale factor + // R = reference value + // X1 = 0 + // X2 = scaled encoded value + foreach(var item in packedValues) + { + // (R + ( X1 + X2) * EE)/DD ; + yield return ((r + item * ee) / dd); + } + } +} \ No newline at end of file diff --git a/tmp/Grib2/Templates/DataRepresentations/0002_GridPointDataComplexPacking.cs b/tmp/Grib2/Templates/DataRepresentations/0002_GridPointDataComplexPacking.cs new file mode 100644 index 0000000..580f2ed --- /dev/null +++ b/tmp/Grib2/Templates/DataRepresentations/0002_GridPointDataComplexPacking.cs @@ -0,0 +1,266 @@ +/* + * This file is part of NGrib. + * + * Copyright © 2020 Nicolas Mangué + * + * Copyright 2006-2010 Seaware AB, PO Box 1244, SE-131 28 + * Nacka Strand, Sweden, info@seaware.se. + * + * Copyright 1997-2006 Unidata Program Center/University + * Corporation for Atmospheric Research, P.O. Box 3000, Boulder, CO 80307, + * support@unidata.ucar.edu. + * + * NGrib is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * NGrib is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with NGrib. If not, see . + */ + +using NGrib.Grib2.CodeTables; +using NGrib.Grib2.Sections; + +namespace NGrib.Grib2.Templates.DataRepresentations; + +/// +/// Data Representation Template 5.2: Grid point data - complex packing +/// +public class GridPointDataComplexPacking : GridPointDataSimplePacking +{ + /// + /// Group splitting method used. + /// + public GroupSplittingMethod GroupSplittingMethod { get; } + + /// + /// Group splitting method used. + /// + public ComplexPackingMissingValueManagement MissingValueManagement { get; } + + /// + /// Primary missing value substitute. + /// + public float PrimaryMissingValue { get; } + + /// + /// Secondary missing value substitute. + /// + public float SecondaryMissingValue { get; } + + /// + /// Number of groups of data values into which field is split (NG). + /// + public long NumberOfGroups { get; } + + /// + /// Reference for group widths. + /// + public int ReferenceGroupWidths { get; } + + /// + /// Number of bits used for the group widths. + /// + public int BitsGroupWidths { get; } + + /// + /// Reference for group lengths. + /// + public long ReferenceGroupLength { get; } + + /// + /// Length increment for the group lengths. + /// + public int LengthIncrement { get; } + + /// + /// True length of last group. + /// + public long LastGroupLength { get; } + + /// + /// Number of bits used for the scaled group lengths. + /// + /// + /// After subtraction of the reference value given in octets 38-41 and division by the length increment given in octet 42. + /// + public int BitsScaledGroupLength { get; } + + internal GridPointDataComplexPacking(BufferedBinaryReader reader) : base(reader) + { + GroupSplittingMethod = (GroupSplittingMethod) reader.ReadUInt8(); + + MissingValueManagement = (ComplexPackingMissingValueManagement) reader.ReadUInt8(); + + PrimaryMissingValue = reader.ReadSingle(); + SecondaryMissingValue = reader.ReadSingle(); + NumberOfGroups = reader.ReadUInt32(); + + ReferenceGroupWidths = reader.ReadUInt8(); + + BitsGroupWidths = reader.ReadUInt8(); + // according to documentation subtract referenceGroupWidths + BitsGroupWidths = BitsGroupWidths - ReferenceGroupWidths; + + ReferenceGroupLength = reader.ReadUInt32(); + + LengthIncrement = reader.ReadUInt8(); + + LastGroupLength = reader.ReadUInt32(); + + BitsScaledGroupLength = reader.ReadUInt8(); + } + + private protected override IEnumerable DoEnumerateDataValues(BufferedBinaryReader reader, DataSection dataSection, long dataPointsNumber) + { + var mvm = MissingValueManagement; + + var pmv = PrimaryMissingValue; + + var ng = (int) NumberOfGroups; + + // 6-xx Get reference values for groups (X1's) + var x1 = new int[ng]; + var nbBits = NumberOfBits; + + for (var i = 0; i < ng; i++) + { + x1[i] = reader.ReadUIntN(nbBits); + } + + // [xx + 1 ]-yy Get number of bits used to encode each group + var nb = new int[ng]; + nbBits = BitsGroupWidths; + + reader.NextUIntN(); + for (var i = 0; i < ng; i++) + { + nb[i] = reader.ReadUIntN(nbBits); + } + + // [yy +1 ]-zz Get the scaled group lengths using formula + // Ln = ref + Kn * len_inc, where n = 1-NG, + // ref = referenceGroupLength, and len_inc = lengthIncrement + + var l = new int[ng]; + var rgLength = (int) ReferenceGroupLength; + + var lenInc = LengthIncrement; + + nbBits = BitsScaledGroupLength; + + reader.NextUIntN(); + for (var i = 0; i < ng; i++) + { + // NG + l[i] = rgLength + reader.ReadUIntN(nbBits) * lenInc; + } + + // [zz +1 ]-nn get X2 values and calculate the results Y using formula + // Y * 10**D = R + (X1 + X2) * 2**E + + var d = DecimalScaleFactor; + + var dd = Math.Pow(10, d); + + var r = ReferenceValue; + + var e = BinaryScaleFactor; + + var ee = Math.Pow(2.0, e); + + // used to check missing values when X2 is packed with all 1's + var bitsmv1 = new int[31]; + for (var i = 0; i < 31; i++) + { + bitsmv1[i] = (int) Math.Pow(2, i) - 1; + } + + int x2; + reader.NextUIntN(); + for (var i = 0; i < ng - 1; i++) + { + for (var j = 0; j < l[i]; j++) + { + if (nb[i] == 0) + { + if (mvm == 0) + { + // X2 = 0 + yield return (float) ((r + x1[i] * ee) / dd); + } + else if (mvm == ComplexPackingMissingValueManagement.Primary) + { + yield return pmv; + } + } + else + { + x2 = reader.ReadUIntN(nb[i]); + if (mvm == 0) + { + yield return (float) ((r + (x1[i] + x2) * ee) / dd); + } + else if (mvm == ComplexPackingMissingValueManagement.Primary) + { + // X2 is also set to missing value is all bits set to 1's + if (x2 == bitsmv1[nb[i]]) + { + yield return pmv; + } + else + { + yield return (float) ((r + (x1[i] + x2) * ee) / dd); + } + } + } + } // end for j + } // end for i + + // process last group + var last = (int) LastGroupLength; + + for (var j = 0; j < last; j++) + { + // last group + if (nb[ng - 1] == 0) + { + if (mvm == 0) + { + // X2 = 0 + yield return (float) ((r + x1[ng - 1] * ee) / dd); + } + else if (mvm == ComplexPackingMissingValueManagement.Primary) + { + yield return pmv; + } + } + else + { + x2 = reader.ReadUIntN(nb[ng - 1]); + if (mvm == 0) + { + yield return (float) ((r + (x1[ng - 1] + x2) * ee) / dd); + } + else if (mvm == ComplexPackingMissingValueManagement.Primary) + { + // X2 is also set to missing value is all bits set to 1's + if (x2 == bitsmv1[nb[ng - 1]]) + { + yield return pmv; + } + else + { + yield return (float) ((r + (x1[ng - 1] + x2) * ee) / dd); + } + } + } + } // end for j + } +} \ No newline at end of file diff --git a/tmp/Grib2/Templates/DataRepresentations/0003_GridPointDataComplexPackingAndSpatialDifferencing.cs b/tmp/Grib2/Templates/DataRepresentations/0003_GridPointDataComplexPackingAndSpatialDifferencing.cs new file mode 100644 index 0000000..6d2d2e4 --- /dev/null +++ b/tmp/Grib2/Templates/DataRepresentations/0003_GridPointDataComplexPackingAndSpatialDifferencing.cs @@ -0,0 +1,420 @@ +/* + * This file is part of NGrib. + * + * Copyright © 2020 Nicolas Mangué + * + * Copyright 2006-2010 Seaware AB, PO Box 1244, SE-131 28 + * Nacka Strand, Sweden, info@seaware.se. + * + * Copyright 1997-2006 Unidata Program Center/University + * Corporation for Atmospheric Research, P.O. Box 3000, Boulder, CO 80307, + * support@unidata.ucar.edu. + * + * NGrib is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * NGrib is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with NGrib. If not, see . + */ + +using NGrib.Grib2.CodeTables; +using NGrib.Grib2.Sections; + +namespace NGrib.Grib2.Templates.DataRepresentations; + +/// +/// Data Representation Template 5.3: Grid point data - complex packing and spatial differencing +/// +public class GridPointDataComplexPackingAndSpatialDifferencing : GridPointDataComplexPacking +{ + /// + /// Order of spatial differencing. + /// + public SpatialDifferencingOrder OrderSpatial { get; } + + /// + /// Number of octets required in the Data Section to specify extra + /// descriptors needed for spatial differencing. + /// + public int ExtraDescriptorsLength { get; } + + internal GridPointDataComplexPackingAndSpatialDifferencing(BufferedBinaryReader reader) : base(reader) + { + OrderSpatial = (SpatialDifferencingOrder) reader.ReadUInt8(); + ExtraDescriptorsLength = reader.ReadUInt8(); + } + + private protected override IEnumerable DoEnumerateDataValues(BufferedBinaryReader reader, DataSection dataSection, long dataPointsNumber) + { + var mvm = MissingValueManagement; + + double pmv = PrimaryMissingValue; + + int ng = (int) NumberOfGroups; + + int g1 = 0, gMin = 0, h1 = 0, h2 = 0, hMin = 0; + // [6-ww] 1st values of undifferenced scaled values and minimums + var os = OrderSpatial; + int ds = ExtraDescriptorsLength; + + reader.NextUIntN(); + int sign; + // ds is number of bytes, convert to bits -1 for sign bit + ds = ds * 8 - 1; + if (os == SpatialDifferencingOrder.FirstOrder) + { + // first order spatial differencing g1 and gMin + sign = reader.ReadUIntN(1); + g1 = reader.ReadUIntN(ds); + if (sign == 1) + { + g1 *= (-1); + } + + sign = reader.ReadUIntN(1); + gMin = reader.ReadUIntN(ds); + if (sign == 1) + { + gMin *= (-1); + } + } + else if (os == SpatialDifferencingOrder.SecondOrder) + { + //second order spatial differencing h1, h2, hMin + sign = reader.ReadUIntN(1); + h1 = reader.ReadUIntN(ds); + if (sign == 1) + { + h1 *= (-1); + } + + sign = reader.ReadUIntN(1); + h2 = reader.ReadUIntN(ds); + if (sign == 1) + { + h2 *= (-1); + } + + sign = reader.ReadUIntN(1); + hMin = reader.ReadUIntN(ds); + if (sign == 1) + { + hMin *= (-1); + } + } + else + { + throw new BadGribFormatException("DS Error"); + } + + // [ww +1]-xx Get reference values for groups (X1's) + int[] x1 = new int[ng]; + int nbBits = NumberOfBits; + + reader.NextUIntN(); + for (int i = 0; i < ng; i++) + { + x1[i] = reader.ReadUIntN(nbBits); + } + + // [xx +1 ]-yy Get number of bits used to encode each group + int[] nb = new int[ng]; + nbBits = BitsGroupWidths; + + reader.NextUIntN(); + for (int i = 0; i < ng; i++) + { + nb[i] = reader.ReadUIntN(nbBits); + } + + // [yy +1 ]-zz Get the scaled group lengths using formula + // Ln = ref + Kn * len_inc, where n = 1-NG, + // ref = referenceGroupLength, and len_inc = lengthIncrement + + int[] l = new int[ng]; + int countL = 0; + int rgLength = (int) ReferenceGroupLength; + + int lenInc = LengthIncrement; + + nbBits = BitsScaledGroupLength; + + reader.NextUIntN(); + for (int i = 0; i < ng; i++) + { + // NG + l[i] = rgLength + reader.ReadUIntN(nbBits) * lenInc; + + countL += l[i]; + } + + // [zz +1 ]-nn get X2 values and add X1[ i ] + X2 + + var data = new double[countL]; + + //gds.getNumberPoints() ); + // used to check missing values when X2 is packed with all 1's + int[] bitsmv1 = new int[31]; + //int bitsmv2[] = new int[ 31 ]; didn't code cuz number larger the # of bits + for (int i = 0; i < 31; i++) + { + bitsmv1[i] = (int) Math.Pow(2, i) - 1; + } + + var count = 0; + int x2; + reader.NextUIntN(); + for (int i = 0; i < ng - 1; i++) + { + for (int j = 0; j < l[i]; j++) + { + if (nb[i] == 0) + { + if (mvm == 0) + { + // X2 = 0 + data[count++] = x1[i]; + } + else if (mvm == ComplexPackingMissingValueManagement.Primary) + { + data[count++] = pmv; + } + } + else + { + x2 = reader.ReadUIntN(nb[i]); + + if (mvm == 0) + { + data[count++] = x1[i] + x2; + } + else if (mvm == ComplexPackingMissingValueManagement.Primary) + { + // X2 is also set to missing value is all bits set to 1's + if (x2 == bitsmv1[nb[i]]) + { + data[count++] = pmv; + } + else + { + data[count++] = x1[i] + x2; + } + } + } + } // end for j + } // end for i + + // process last group + int last = (int) LastGroupLength; + + for (int j = 0; j < last; j++) + { + // last group + if (nb[ng - 1] == 0) + { + if (mvm == 0) + { + // X2 = 0 + data[count++] = x1[ng - 1]; + } + else if (mvm == ComplexPackingMissingValueManagement.Primary) + { + data[count++] = pmv; + } + } + else + { + x2 = reader.ReadUIntN(nb[ng - 1]); + if (mvm == 0) + { + data[count++] = x1[ng - 1] + x2; + } + else if (mvm == ComplexPackingMissingValueManagement.Primary) + { + // X2 is also set to missing value is all bits set to 1's + if (x2 == bitsmv1[nb[ng - 1]]) + { + data[count++] = pmv; + } + else + { + data[count++] = x1[ng - 1] + x2; + } + } + } + } // end for j + + if (os == SpatialDifferencingOrder.FirstOrder) + { + // g1 and gMin this coding is a sort of guess, no doc + double sum = 0; + if (mvm == 0) + { + // no missing values + for (int i = 1; i < data.Length; i++) + { + data[i] += gMin; // add minimum back + } + + data[0] = g1; + for (int i = 1; i < data.Length; i++) + { + sum += data[i]; + data[i] = data[i - 1] + sum; + } + } + else + { + // contains missing values + double lastOne = pmv; + // add the minimum back and set g1 + int idx = 0; + for (int i = 0; i < data.Length; i++) + { + if (data[i] != pmv) + { + if (idx == 0) + { + // set g1 + data[i] = g1; + lastOne = data[i]; + idx = i + 1; + } + else + { + data[i] += gMin; + } + } + } + + if (lastOne == pmv) + { + throw new BadGribFormatException("DS bad spatial differencing data"); + } + + for (int i = idx; i < data.Length; i++) + { + if (data[i] != pmv) + { + sum += data[i]; + data[i] = lastOne + sum; + lastOne = data[i]; + } + } + } + } + else if (os == SpatialDifferencingOrder.SecondOrder) + { + //h1, h2, hMin + double hDiff = h2 - h1; + double sum = 0; + if (mvm == 0) + { + // no missing values + for (int i = 2; i < data.Length; i++) + { + data[i] += hMin; // add minimum back + } + + data[0] = h1; + data[1] = h2; + sum = hDiff; + for (int i = 2; i < data.Length; i++) + { + sum += data[i]; + data[i] = data[i - 1] + sum; + } + } + else + { + // contains missing values + int idx = 0; + double lastOne = pmv; + // add the minimum back and set h1 and h2 + for (int i = 0; i < data.Length; i++) + { + if (data[i] != pmv) + { + if (idx == 0) + { + // set h1 + data[i] = h1; + sum = 0; + lastOne = data[i]; + idx++; + } + else if (idx == 1) + { + // set h2 + data[i] = h1 + hDiff; + sum = hDiff; + lastOne = data[i]; + idx = i + 1; + } + else + { + data[i] += hMin; + } + } + } + + if (lastOne == pmv) + { + throw new BadGribFormatException("DS bad spatial differencing data"); + } + + for (int i = idx; i < data.Length; i++) + { + if (data[i] != pmv) + { + sum += data[i]; + + data[i] = lastOne + sum; + lastOne = data[i]; + } + } + } + } // end h1, h2, hMin + + // formula used to create values, Y * 10**D = R + (X1 + X2) * 2**E + + var d = DecimalScaleFactor; + + var dd = Math.Pow(10, d); + + var r = ReferenceValue; + + var e = BinaryScaleFactor; + + var ee = Math.Pow(2.0, e); + + if (mvm == 0) + { + // no missing values + for (int i = 0; i < data.Length; i++) + { + data[i] = ((r + data[i] * ee) / dd); + } + } + else + { + // missing value == 1 + for (int i = 0; i < data.Length; i++) + { + if (data[i] != pmv) + { + data[i] = ((r + data[i] * ee) / dd); + } + } + } + + return data; + } +} \ No newline at end of file diff --git a/tmp/Grib2/Templates/DataRepresentations/0040_GridPointDataJpeg2000CodeStream.cs b/tmp/Grib2/Templates/DataRepresentations/0040_GridPointDataJpeg2000CodeStream.cs new file mode 100644 index 0000000..6f3c70b --- /dev/null +++ b/tmp/Grib2/Templates/DataRepresentations/0040_GridPointDataJpeg2000CodeStream.cs @@ -0,0 +1,65 @@ +/* + * This file is part of NGrib. + * + * Copyright © 2020 Nicolas Mangué + * + * Copyright 2006-2010 Seaware AB, PO Box 1244, SE-131 28 + * Nacka Strand, Sweden, info@seaware.se. + * + * Copyright 1997-2006 Unidata Program Center/University + * Corporation for Atmospheric Research, P.O. Box 3000, Boulder, CO 80307, + * support@unidata.ucar.edu. + * + * NGrib is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * NGrib is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with NGrib. If not, see . + */ + +using CSJ2K; +using NGrib.Grib2.Sections; + +namespace NGrib.Grib2.Templates.DataRepresentations; + +public class GridPointDataJpeg2000CodeStream : GridPointDataSimplePacking +{ + /// Type compression method used (see Code Table 5.40000). + /// CompressionMethod + /// + public int CompressionMethod { get; } + + /// Compression ratio used . + /// CompressionRatio + /// + public int CompressionRatio { get; } + + internal GridPointDataJpeg2000CodeStream(BufferedBinaryReader reader) : base(reader) + { + CompressionMethod = reader.ReadUInt8(); + + CompressionRatio = reader.ReadUInt8(); + } + + private protected override IEnumerable DoEnumerateDataValues(BufferedBinaryReader reader, DataSection dataSection, long dataPointsNumber) + { + var data = reader.Read((int) dataSection.DataLength); + var img = J2kImage.FromBytes(data); + + if (img.NumberOfComponents <= 0) + { + return new double[0]; + } + + var values = img.GetComponent(0); + + return Unpack(values); + } +} \ No newline at end of file diff --git a/tmp/Grib2/Templates/DataRepresentations/50002_GridPointDataEcmwfSecondOrderPacking.cs b/tmp/Grib2/Templates/DataRepresentations/50002_GridPointDataEcmwfSecondOrderPacking.cs new file mode 100644 index 0000000..9c2a4d5 --- /dev/null +++ b/tmp/Grib2/Templates/DataRepresentations/50002_GridPointDataEcmwfSecondOrderPacking.cs @@ -0,0 +1,245 @@ +/* + * This file is part of NGrib. + * + * Copyright © 2020 Nicolas Mangué + * + * Copyright 2006-2010 Seaware AB, PO Box 1244, SE-131 28 + * Nacka Strand, Sweden, info@seaware.se. + * + * Copyright 1997-2006 Unidata Program Center/University + * Corporation for Atmospheric Research, P.O. Box 3000, Boulder, CO 80307, + * support@unidata.ucar.edu. + * + * NGrib is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * NGrib is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with NGrib. If not, see . + */ + +using NGrib.Grib2.Sections; +using System.Collections.Immutable; + +namespace NGrib.Grib2.Templates.DataRepresentations; + +/// +/// Data Representation Template 5.0: Grid point data - second order packing +/// +/// +/// https://apps.ecmwf.int/codes/grib/format/grib2/templates/5/50002 +/// +public class GridPointDataEcmwfSecondOrderPacking : DataRepresentation +{ + /// + /// Reference value (R) . + /// + public float ReferenceValue { get; } + + /// + /// Binary scale factor (E). + /// + public int BinaryScaleFactor { get; } + + /// + /// Decimal scale factor (D). + /// + public int DecimalScaleFactor { get; } + + /// + /// Number of bits used for each packed value. + /// + public int NumberOfBits { get; } + + /// + /// Width of first order values + /// + public int WidthOfFirstOrderValues { get; } + + /// + /// Number of groups + /// + public long P1 { get; } + + /// + /// Number of second order packed values + /// + public long P2 { get; } + + /// + /// Width of widths + /// + public int WidthOfWidths { get; } + + /// + /// Width of lengths + /// + public int WidthOfLengths { get; } + + /// + /// Ordering flags (Flag table 5.50002) + /// + public int SecondOrderFlags { get; } + + /// + /// Order of spatial differencing + /// + public int OrderOfSpd { get; } + + /// + /// Width of spatial differencing + /// + public int WidthOfSpd { get; } + + /// + /// SPD + /// + public IReadOnlyList Spd { get; } + + internal GridPointDataEcmwfSecondOrderPacking(BufferedBinaryReader reader) + { + ReferenceValue = reader.ReadSingle(); + BinaryScaleFactor = reader.ReadInt16(); + DecimalScaleFactor = reader.ReadInt16(); + NumberOfBits = reader.ReadUInt8(); + + WidthOfFirstOrderValues = reader.ReadUInt8(); + P1 = reader.ReadUInt32(); + P2 = reader.ReadUInt32(); + WidthOfWidths = reader.ReadUInt8(); + WidthOfLengths = reader.ReadUInt8(); + SecondOrderFlags = reader.ReadUInt8(); + OrderOfSpd = reader.ReadUInt8(); + WidthOfSpd = reader.ReadUInt8(); + var spdA = new int [OrderOfSpd + 1]; + + reader.NextUIntN(); + for (var i = 0; i < OrderOfSpd; i++) + { + spdA[i] = reader.ReadUIntN(WidthOfSpd); + } + + spdA[OrderOfSpd] = reader.ReadIntN(WidthOfSpd); + Spd = spdA.ToImmutableList(); + } + + private protected override IEnumerable DoEnumerateDataValues(BufferedBinaryReader reader, DataSection dataSection, long dataPointsNumber) + { + // Implementation based on NetCDF-Java + // https://github.com/Unidata/netcdf-java/blob/v5.4.2/grib/src/main/java/ucar/nc2/grib/grib2/Grib2DataReader.java#L972 + reader.NextUIntN(); + var groupWidth = new int[P1]; + for (var i = 0; i < P1; i++) + { + groupWidth[i] = reader.ReadUIntN(WidthOfWidths); + } + + reader.NextUIntN(); + var groupLength = new int[P1]; + for (var i = 0; i < P1; i++) + { + groupLength[i] = reader.ReadUIntN(WidthOfLengths); + } + + reader.NextUIntN(); + var firstOrderValues = new int[P1]; + for (var i = 0; i < P1; i++) + { + firstOrderValues[i] = reader.ReadUIntN(WidthOfFirstOrderValues); + } + + var bias = 0; + if (OrderOfSpd > 0) + { + bias = Spd[OrderOfSpd]; + } + + reader.NextUIntN(); + var cnt = OrderOfSpd; + var data = new int[dataPointsNumber]; + for (var i = 0; i < P1; i++) + { + if (groupWidth[i] > 0) + { + for (var j = 0; j < groupLength[i]; j++) + { + data[cnt] = reader.ReadUIntN(groupWidth[i]); + data[cnt] += firstOrderValues[i]; + cnt++; + } + } + else + { + for (var j = 0; j < groupLength[i]; j++) + { + data[cnt] = firstOrderValues[i]; + cnt++; + } + } + } + + for (var i = 0; i < OrderOfSpd; i++) + { + data[i] = Spd[i]; + } + + int y, z, w; + switch (OrderOfSpd) + { + case 1: + y = data[0]; + for (var i = 1; i < dataPointsNumber; i++) + { + y += data[i] + bias; + data[i] = y; + } + + break; + case 2: + y = data[1] - data[0]; + z = data[1]; + for (var i = 2; i < dataPointsNumber; i++) + { + y += data[i] + bias; + z += y; + data[i] = z; + } + + break; + case 3: + y = data[2] - data[1]; + z = y - (data[1] - data[0]); + w = data[2]; + for (var i = 3; i < dataPointsNumber; i++) + { + z += data[i] + bias; + y += z; + w += y; + data[i] = w; + } + + break; + } + + var d = DecimalScaleFactor; + + var dd = Math.Pow(10, -d); + + var r = ReferenceValue; + + var e = BinaryScaleFactor; + + var ee = Math.Pow(2.0, e); + + for (var i = 0; i < dataPointsNumber; i++) + { + yield return (float)((data[i] * ee + r) * dd); + } + } +} \ No newline at end of file diff --git a/tmp/Grib2/Templates/DataRepresentations/DataRepresentation.cs b/tmp/Grib2/Templates/DataRepresentations/DataRepresentation.cs new file mode 100644 index 0000000..3213f2b --- /dev/null +++ b/tmp/Grib2/Templates/DataRepresentations/DataRepresentation.cs @@ -0,0 +1,33 @@ +/* + * This file is part of NGrib. + * + * Copyright © 2020 Nicolas Mangué + * + * NGrib is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * NGrib is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with NGrib. If not, see . + */ + +using NGrib.Grib2.Sections; + +namespace NGrib.Grib2.Templates.DataRepresentations; + +public abstract class DataRepresentation +{ + internal IEnumerable EnumerateDataValues(BufferedBinaryReader reader, DataSection dataSection, long dataPointsNumber) + { + reader.Seek(dataSection.DataOffset, SeekOrigin.Begin); + return DoEnumerateDataValues(reader, dataSection, dataPointsNumber); + } + + private protected abstract IEnumerable DoEnumerateDataValues(BufferedBinaryReader reader, DataSection dataSection, long dataPointsNumber); +} \ No newline at end of file diff --git a/tmp/Grib2/Templates/GridDefinitions/0000_LatLonGridDefinition.cs b/tmp/Grib2/Templates/GridDefinitions/0000_LatLonGridDefinition.cs new file mode 100644 index 0000000..a3d2cac --- /dev/null +++ b/tmp/Grib2/Templates/GridDefinitions/0000_LatLonGridDefinition.cs @@ -0,0 +1,143 @@ +/* + * This file is part of NGrib. + * + * Copyright © 2020 Nicolas Mangué + * + * Copyright 2006-2010 Seaware AB, PO Box 1244, SE-131 28 + * Nacka Strand, Sweden, info@seaware.se. + * + * Copyright 1997-2006 Unidata Program Center/University + * Corporation for Atmospheric Research, P.O. Box 3000, Boulder, CO 80307, + * support@unidata.ucar.edu. + * + * NGrib is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * NGrib is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with NGrib. If not, see . + */ + +using System.Diagnostics; +using NGrib.Grib2.CodeTables; + +namespace NGrib.Grib2.Templates.GridDefinitions; + +public class LatLonGridDefinition : XyEarthGridDefinition +{ + /// + /// Basic angle of the initial production domain. + /// + public long Angle { get; } + + /// + /// Subdivisions of basic angle used to define extreme longitudes and latitudes, and direction increments. + /// + public long SubdivisionsAngle { get; } + + /// + /// Latitude of first grid point. + /// + public double La1 { get; } + + /// + /// Longitude of first grid point. + /// + public double Lo1 { get; } + + /// + /// Resolution and component flags value. + /// + public ResolutionAndComponent ResolutionAndComponent { get; } + + /// + /// Latitude of last grid point. + /// + public double La2 { get; } + + /// + /// Longitude of last grid point. + /// + public double Lo2 { get; } + + /// + /// X-direction increment. + /// + public double Dx { get; } + + /// + /// Y-direction increment. + /// + public double Dy { get; } + + /// + /// Scanning mode. + /// + public int ScanMode { get; } + + internal LatLonGridDefinition(BufferedBinaryReader reader) : base(reader) + { + Angle = reader.ReadUInt32(); + SubdivisionsAngle = reader.ReadUInt32(); + double ratio; + if (Angle == 0) + { + ratio = 1e-6; + } + else + { + ratio = Angle / (double) SubdivisionsAngle; + } + + La1 = reader.ReadInt32() * ratio; + Lo1 = reader.ReadInt32() * ratio; + ResolutionAndComponent = (ResolutionAndComponent) reader.ReadUInt8(); + La2 = reader.ReadInt32() * ratio; + Lo2 = reader.ReadInt32() * ratio; + Dx = reader.ReadInt32() * ratio; + Dy = reader.ReadInt32() * ratio; + ScanMode = reader.ReadUInt8(); + } + + public override IEnumerable EnumerateGridPoints() + { + var scanningMode = (ScanningMode) ScanMode; + var resolution = ResolutionAndComponent; + + if (resolution != (ResolutionAndComponent.JDirectionIncrementGiven | ResolutionAndComponent.IDirectionIncrementGiven) || + (scanningMode & ~(ScanningMode.ScanJPositive | ScanningMode.ScanIReverse)) != ScanningMode.Default) + { + throw new NotImplementedException(); + } + + var firstGridPoint = new Coordinate(La1, Lo1); + var lastGridPoint = new Coordinate(La2, Lo2); + + var xStep = Dx * (scanningMode.HasFlag(ScanningMode.ScanIReverse) ? -1 : 1); + var yStep = Dy * (scanningMode.HasFlag(ScanningMode.ScanJPositive) ? 1 : -1); + var currentGridPoint = firstGridPoint; + + // Adjacent points in x direction are consecutive + var latitudeOffset = 0d; + for (var y = 0; y < Ny; y++) + { + var longitudeOffset = 0d; + for (var x = 0; x < Nx; x++) + { + currentGridPoint = firstGridPoint.Add(latitudeOffset, longitudeOffset); + yield return currentGridPoint; + + longitudeOffset += xStep; + } + latitudeOffset += yStep; + } + + Debug.Assert(lastGridPoint.Equals(currentGridPoint)); + } +} \ No newline at end of file diff --git a/tmp/Grib2/Templates/GridDefinitions/0001_RotatedLatLon.cs b/tmp/Grib2/Templates/GridDefinitions/0001_RotatedLatLon.cs new file mode 100644 index 0000000..df4da9c --- /dev/null +++ b/tmp/Grib2/Templates/GridDefinitions/0001_RotatedLatLon.cs @@ -0,0 +1,55 @@ +/* + * This file is part of NGrib. + * + * Copyright © 2020 Nicolas Mangué + * + * Copyright 2006-2010 Seaware AB, PO Box 1244, SE-131 28 + * Nacka Strand, Sweden, info@seaware.se. + * + * Copyright 1997-2006 Unidata Program Center/University + * Corporation for Atmospheric Research, P.O. Box 3000, Boulder, CO 80307, + * support@unidata.ucar.edu. + * + * NGrib is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * NGrib is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with NGrib. If not, see . + */ + +namespace NGrib.Grib2.Templates.GridDefinitions; + +public class RotatedLatLonGridDefinition : LatLonGridDefinition +{ + /// . + /// SpLat as a float + /// + /// + public float SpLat { get; } + + /// . + /// SpLon as a float + /// + /// + public float SpLon { get; } + + /// . + /// Rotationangle as a float + /// + /// + public float Rotationangle { get; } + + internal RotatedLatLonGridDefinition(BufferedBinaryReader reader) : base(reader) + { + SpLat = reader.ReadInt32() * 1e-6f; + SpLon = reader.ReadUInt32() * 1e-6f; + Rotationangle = reader.ReadSingle(); + } +} \ No newline at end of file diff --git a/tmp/Grib2/Templates/GridDefinitions/0002_StretchedLatLonGridDefinition.cs b/tmp/Grib2/Templates/GridDefinitions/0002_StretchedLatLonGridDefinition.cs new file mode 100644 index 0000000..dbbba37 --- /dev/null +++ b/tmp/Grib2/Templates/GridDefinitions/0002_StretchedLatLonGridDefinition.cs @@ -0,0 +1,56 @@ +/* + * This file is part of NGrib. + * + * Copyright © 2020 Nicolas Mangué + * + * Copyright 2006-2010 Seaware AB, PO Box 1244, SE-131 28 + * Nacka Strand, Sweden, info@seaware.se. + * + * Copyright 1997-2006 Unidata Program Center/University + * Corporation for Atmospheric Research, P.O. Box 3000, Boulder, CO 80307, + * support@unidata.ucar.edu. + * + * NGrib is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * NGrib is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with NGrib. If not, see . + */ + +namespace NGrib.Grib2.Templates.GridDefinitions; + +public class StretchedLatLonGridDefinition : LatLonGridDefinition +{ + /// . + /// PoleLat as a float + /// + /// + public float PoleLat { get; } + + /// . + /// PoleLon as a float + /// + /// + public float PoleLon { get; } + + /// . + /// Factor as a float + /// + /// + public float Factor { get; } + + internal StretchedLatLonGridDefinition(BufferedBinaryReader reader) : base(reader) + { + //Stretched Latitude/longitude + PoleLat = reader.ReadInt32() * 1e-6f; + PoleLon = reader.ReadUInt32() * 1e-6f; + Factor = reader.ReadUInt32(); + } +} \ No newline at end of file diff --git a/tmp/Grib2/Templates/GridDefinitions/0003_StretchedRotatedLatLonGridDefinition.cs b/tmp/Grib2/Templates/GridDefinitions/0003_StretchedRotatedLatLonGridDefinition.cs new file mode 100644 index 0000000..18c2b62 --- /dev/null +++ b/tmp/Grib2/Templates/GridDefinitions/0003_StretchedRotatedLatLonGridDefinition.cs @@ -0,0 +1,57 @@ +/* + * This file is part of NGrib. + * + * Copyright © 2020 Nicolas Mangué + * + * Copyright 2006-2010 Seaware AB, PO Box 1244, SE-131 28 + * Nacka Strand, Sweden, info@seaware.se. + * + * Copyright 1997-2006 Unidata Program Center/University + * Corporation for Atmospheric Research, P.O. Box 3000, Boulder, CO 80307, + * support@unidata.ucar.edu. + * + * NGrib is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * NGrib is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with NGrib. If not, see . + */ + +namespace NGrib.Grib2.Templates.GridDefinitions; + +public class StretchedRotatedLatLonGridDefinition : RotatedLatLonGridDefinition +{ + /// . + /// PoleLat as a float + /// + /// + public float PoleLat { get; } + + /// . + /// PoleLon as a float + /// + /// + public float PoleLon { get; } + + /// . + /// Factor as a float + /// + /// + public float Factor { get; } + + internal StretchedRotatedLatLonGridDefinition(BufferedBinaryReader reader) : base(reader) + { + //Stretched and Rotated + // Latitude/longitude + PoleLat = reader.ReadInt32() * 1e-6f; + PoleLon = reader.ReadUInt32() * 1e-6f; + Factor = reader.ReadUInt32(); + } +} \ No newline at end of file diff --git a/tmp/Grib2/Templates/GridDefinitions/0010_MercatorGridDefinition.cs b/tmp/Grib2/Templates/GridDefinitions/0010_MercatorGridDefinition.cs new file mode 100644 index 0000000..5ff31c8 --- /dev/null +++ b/tmp/Grib2/Templates/GridDefinitions/0010_MercatorGridDefinition.cs @@ -0,0 +1,88 @@ +/* + * This file is part of NGrib. + * + * Copyright © 2020 Nicolas Mangué + * + * Copyright 2006-2010 Seaware AB, PO Box 1244, SE-131 28 + * Nacka Strand, Sweden, info@seaware.se. + * + * Copyright 1997-2006 Unidata Program Center/University + * Corporation for Atmospheric Research, P.O. Box 3000, Boulder, CO 80307, + * support@unidata.ucar.edu. + * + * NGrib is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * NGrib is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with NGrib. If not, see . + */ + +namespace NGrib.Grib2.Templates.GridDefinitions; + +public class MercatorGridDefinition : GridPointEarthGridDefinition +{ + /// . + /// Lad as a float + /// + /// + public double Lad { get; } + + /// . + /// La2 as a float + /// + /// + public double La2 { get; } + + /// . + /// Lo2 as a float + /// + /// + public double Lo2 { get; } + + /// Get scan mode. + /// + /// + /// scan mode + /// + public int ScanMode { get; } + + /// . + /// Angle as a int + /// + /// + public long Angle { get; } + + /// Get x-increment/distance between two grid points. + /// + /// + /// x-increment + /// + public double Dx { get; } + + /// Get y-increment/distance between two grid points. + /// + /// + /// y-increment + /// + public double Dy { get; } + + internal MercatorGridDefinition(BufferedBinaryReader reader) : base(reader) + { + Lad = reader.ReadInt32() * 1e-6; + La2 = reader.ReadInt32() * 1e-6; + Lo2 = reader.ReadUInt32() * 1e-6; + ScanMode = reader.ReadUInt8(); + Angle = reader.ReadUInt32(); + Dx = reader.ReadUInt32() * 1e-3; + Dy = reader.ReadUInt32() * 1e-3; + } + + public override IEnumerable EnumerateGridPoints() => throw new NotImplementedException(); +} \ No newline at end of file diff --git a/tmp/Grib2/Templates/GridDefinitions/0020_PolarStereographicProjectionGridDefinition.cs b/tmp/Grib2/Templates/GridDefinitions/0020_PolarStereographicProjectionGridDefinition.cs new file mode 100644 index 0000000..ad5324b --- /dev/null +++ b/tmp/Grib2/Templates/GridDefinitions/0020_PolarStereographicProjectionGridDefinition.cs @@ -0,0 +1,81 @@ +/* + * This file is part of NGrib. + * + * Copyright © 2020 Nicolas Mangué + * + * Copyright 2006-2010 Seaware AB, PO Box 1244, SE-131 28 + * Nacka Strand, Sweden, info@seaware.se. + * + * Copyright 1997-2006 Unidata Program Center/University + * Corporation for Atmospheric Research, P.O. Box 3000, Boulder, CO 80307, + * support@unidata.ucar.edu. + * + * NGrib is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * NGrib is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with NGrib. If not, see . + */ + +namespace NGrib.Grib2.Templates.GridDefinitions; + +public class PolarStereographicProjectionGridDefinition : GridPointEarthGridDefinition +{ + /// . + /// Lad as a float + /// + /// + public double Lad { get; } + + /// . + /// Lov as a float + /// + /// + public double Lov { get; } + + /// Get x-increment/distance between two grid points. + /// + /// + /// x-increment + /// + public double Dx { get; } + + /// Get y-increment/distance between two grid points. + /// + /// + /// y-increment + /// + public double Dy { get; } + + /// . + /// ProjectionCenter as a int + /// + /// + public int ProjectionCenter { get; } + + /// Get scan mode. + /// + /// + /// scan mode + /// + public int ScanMode { get; } + + internal PolarStereographicProjectionGridDefinition(BufferedBinaryReader reader) : base(reader) + { + Lad = reader.ReadInt32() * 1e-6; + Lov = reader.ReadUInt32() * 1e-6; + Dx = reader.ReadUInt32() * 1e-3; + Dy = reader.ReadUInt32() * 1e-3; + ProjectionCenter = reader.ReadUInt8(); + ScanMode = reader.ReadUInt8(); + } + + public override IEnumerable EnumerateGridPoints() => throw new NotImplementedException(); +} \ No newline at end of file diff --git a/tmp/Grib2/Templates/GridDefinitions/0030_LambertConformalGridDefinition.cs b/tmp/Grib2/Templates/GridDefinitions/0030_LambertConformalGridDefinition.cs new file mode 100644 index 0000000..308cf4d --- /dev/null +++ b/tmp/Grib2/Templates/GridDefinitions/0030_LambertConformalGridDefinition.cs @@ -0,0 +1,63 @@ +/* + * This file is part of NGrib. + * + * Copyright © 2020 Nicolas Mangué + * + * Copyright 2006-2010 Seaware AB, PO Box 1244, SE-131 28 + * Nacka Strand, Sweden, info@seaware.se. + * + * Copyright 1997-2006 Unidata Program Center/University + * Corporation for Atmospheric Research, P.O. Box 3000, Boulder, CO 80307, + * support@unidata.ucar.edu. + * + * NGrib is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * NGrib is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with NGrib. If not, see . + */ + +namespace NGrib.Grib2.Templates.GridDefinitions; + +public class LambertConformalGridDefinition : PolarStereographicProjectionGridDefinition +{ + /// . + /// Latin1 as a float + /// + /// + public float Latin1 { get; } + + /// . + /// Latin2 as a float + /// + /// + public float Latin2 { get; } + + /// . + /// SpLat as a float + /// + /// + public float SpLat { get; } + + /// . + /// SpLon as a float + /// + /// + public float SpLon { get; } + + internal LambertConformalGridDefinition(BufferedBinaryReader reader) : base(reader) + { + Latin1 = reader.ReadUInt32() * 1e-6f; + Latin2 = reader.ReadUInt32() * 1e-6f; + + SpLat = reader.ReadInt32() * 1e-6f; + SpLon = reader.ReadUInt32() * 1e-6f; + } +} \ No newline at end of file diff --git a/tmp/Grib2/Templates/GridDefinitions/0031_AlbersEqualAreaGridDefinition.cs b/tmp/Grib2/Templates/GridDefinitions/0031_AlbersEqualAreaGridDefinition.cs new file mode 100644 index 0000000..78ae9dd --- /dev/null +++ b/tmp/Grib2/Templates/GridDefinitions/0031_AlbersEqualAreaGridDefinition.cs @@ -0,0 +1,34 @@ +/* + * This file is part of NGrib. + * + * Copyright © 2020 Nicolas Mangué + * + * Copyright 2006-2010 Seaware AB, PO Box 1244, SE-131 28 + * Nacka Strand, Sweden, info@seaware.se. + * + * Copyright 1997-2006 Unidata Program Center/University + * Corporation for Atmospheric Research, P.O. Box 3000, Boulder, CO 80307, + * support@unidata.ucar.edu. + * + * NGrib is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * NGrib is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with NGrib. If not, see . + */ + +namespace NGrib.Grib2.Templates.GridDefinitions; + +public class AlbersEqualAreaGridDefinition : LambertConformalGridDefinition +{ + internal AlbersEqualAreaGridDefinition(BufferedBinaryReader reader) : base(reader) + { + } +} \ No newline at end of file diff --git a/tmp/Grib2/Templates/GridDefinitions/0040_GaussianLatLonGridDefinition.cs b/tmp/Grib2/Templates/GridDefinitions/0040_GaussianLatLonGridDefinition.cs new file mode 100644 index 0000000..bf1a5b4 --- /dev/null +++ b/tmp/Grib2/Templates/GridDefinitions/0040_GaussianLatLonGridDefinition.cs @@ -0,0 +1,273 @@ +/* + * This file is part of NGrib. + * + * Copyright © 2020 Nicolas Mangué + * + * Copyright 2006-2010 Seaware AB, PO Box 1244, SE-131 28 + * Nacka Strand, Sweden, info@seaware.se. + * + * Copyright 1997-2006 Unidata Program Center/University + * Corporation for Atmospheric Research, P.O. Box 3000, Boulder, CO 80307, + * support@unidata.ucar.edu. + * + * NGrib is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * NGrib is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with NGrib. If not, see . + * + * Edited by reagafonov@yandex.ru + * Adopted from GribApi.Xp + */ + +using System.Data; +using NGrib.Helpers; + +namespace NGrib.Grib2.Templates.GridDefinitions; + +public class GaussianLatLonGridDefinition : XyEarthGridDefinition +{ + private const long Maxiter = 1000; + + private const double MPi = Math.PI; + + private static readonly double[] GaussValues; + protected double Ratio { get; } + + /// . + /// Angle as a int + /// + /// + public long Angle { get; } + + /// . + /// Subdivisionsangle as a int + /// + /// + public long Subdivisionsangle { get; } + + /// . + /// La1 as a double + /// + /// + public double La1 { get; } + + /// . + /// Lo1 as a double + /// + /// + public double Lo1 { get; } + + /// . + /// Resolution as a int + /// + /// + public int Resolution { get; } + + /// . + /// La2 as a double + /// + /// + public double La2 { get; } + + /// . + /// Lo2 as a double + /// + /// + public double Lo2 { get; } + + /// Get x-increment/distance between two grid points. + /// + /// + /// x-increment + /// + public double Dx { get; } + + /// Number of latitudes in full grid. + /// + /// + /// + /// + public long N { get; } + + /// Get scan mode. + /// + /// + /// scan mode + /// + public ScanMode ScanMode { get; } + + public IEnumerable Latitudes { get; } + + static GaussianLatLonGridDefinition() + { + GaussValues = new[] + { + 2.4048255577E0, 5.5200781103E0, + 8.6537279129E0, 11.7915344391E0, 14.9309177086E0, + 18.0710639679E0, 21.2116366299E0, 24.3524715308E0, + 27.4934791320E0, 30.6346064684E0, 33.7758202136E0, + 36.9170983537E0, 40.0584257646E0, 43.1997917132E0, + 46.3411883717E0, 49.4826098974E0, 52.6240518411E0, + 55.7655107550E0, 58.9069839261E0, 62.0484691902E0, + 65.1899648002E0, 68.3314693299E0, 71.4729816036E0, + 74.6145006437E0, 77.7560256304E0, 80.8975558711E0, + 84.0390907769E0, 87.1806298436E0, 90.3221726372E0, + 93.4637187819E0, 96.6052679510E0, 99.7468198587E0, + 102.8883742542E0, 106.0299309165E0, 109.1714896498E0, + 112.3130502805E0, 115.4546126537E0, 118.5961766309E0, + 121.7377420880E0, 124.8793089132E0, 128.0208770059E0, + 131.1624462752E0, 134.3040166383E0, 137.4455880203E0, + 140.5871603528E0, 143.7287335737E0, 146.8703076258E0, + 150.0118824570E0, 153.1534580192E0, 156.2950342685E0 + }; + } + + + static void gauss_first_guess(long trunc, ref double[] vals) + { + long i, numVals; + + numVals = GaussValues.Length; + for (i = 0; i < trunc; i++) + { + if (i < numVals) + vals[i] = GaussValues[i]; + else + vals[i] = vals[i - 1] + MPi; + } + } + + internal GaussianLatLonGridDefinition(BufferedBinaryReader reader) : base(reader) + { + Angle = reader.ReadUInt32(); + Subdivisionsangle = reader.ReadUInt32(); + if (Angle == 0) + { + Ratio = 1e-6; + } + else + { + Ratio = (double)Angle / Subdivisionsangle; + } + + La1 = reader.ReadInt32() * Ratio; + Lo1 = reader.ReadInt32() * Ratio; + Resolution = reader.ReadUInt8(); + La2 = reader.ReadUInt32() * Ratio; + Lo2 = reader.ReadUInt32() * Ratio; + Dx = reader.ReadUInt32() * Ratio; + N = reader.ReadUInt32(); + + ScanMode = new ScanMode(reader.ReadUInt8()); + + var latitudes = new double[2 * N]; + grib_get_gaussian_latitudes(N, ref latitudes); + + var minLat = Math.Min(La1, La2); + + Latitudes = latitudes.OrderBy(x => x).SkipWhile(x => minLat > x).Take((int) Ny); + + if (minLat > La1) + Latitudes = Latitudes.Reverse(); + + Latitudes = Latitudes.ToList(); + } + + private void grib_get_gaussian_latitudes(long trunc, ref double[] lats) + { + long jlat; + long iter; + long legi; + double convval; + double root; + double legfonc = 0; + double mem1, mem2, conv; + double denom; + double precision = 1.0E-14; + long nlat = trunc * 2; + + var rad2deg = 180.0d / MPi; + + convval = (1.0d - ((2.0d / MPi) * (2.0d / MPi)) * 0.25d); + + gauss_first_guess(trunc, ref lats); + denom = Math.Sqrt(((nlat + 0.5d) * (nlat + 0.5d)) + convval); + + for (jlat = 0; jlat < trunc; jlat++) + { + /* First approximation for root */ + root = Math.Cos(lats[jlat] / denom); + + /* Perform loop of Newton iterations */ + iter = 0; + conv = 1; + + while (Math.Abs(conv) >= precision) + { + mem2 = 1.0; + mem1 = root; + + /* Compute Legendre polynomial */ + for (legi = 0; legi < nlat; legi++) + { + legfonc = ((2.0 * (legi + 1) - 1.0) * root * mem1 - legi * mem2) / (legi + 1); + mem2 = mem1; + mem1 = legfonc; + } + + /* Perform Newton iteration */ + conv = legfonc / ((nlat * (mem2 - root * legfonc)) / (1.0d - (root * root))); + root -= conv; + + /* Routine fails if no convergence after MAXITER iterations */ + if (iter++ > Maxiter) + { + throw new DataException("Non converge"); + } + } + + /* Set North and South values using symmetry */ + lats[jlat] = Math.Asin(root) * rad2deg; + lats[nlat - 1 - jlat] = -lats[jlat]; + } + + if (nlat != (trunc * 2)) + lats[trunc + 1] = 0.0; + } + + public override IEnumerable EnumerateGridPoints() + { + if (ScanMode.RowsZigzag || ScanMode.IsYDirectionOffset + || ScanMode.IsXDirectionEvenOffset || ScanMode.RowsNxNyPoints + || ScanMode.IsXDirectionOddRowsOffset + || ScanMode.IsXIncrement + || ScanMode.IsYIncrement + || ScanMode.IsNortherly + || Lo2<=Lo1) + throw new NotImplementedException(); + + var dx = (Lo2 - Lo1) / (Nx - 1); + return GetXConsecutiveCoordinates(dx); + } + + private IEnumerable GetXConsecutiveCoordinates(double dx) + { + foreach (var lat in Latitudes) + { + for (var x = 0; x < Nx; x++) + { + var lon = Lo1 + x * dx; + var coordinate = new Coordinate(lat, lon); + yield return coordinate; + } + } + } +} \ No newline at end of file diff --git a/tmp/Grib2/Templates/GridDefinitions/0041_RotatedGaussianLatLonGridDefinition.cs b/tmp/Grib2/Templates/GridDefinitions/0041_RotatedGaussianLatLonGridDefinition.cs new file mode 100644 index 0000000..e07fa75 --- /dev/null +++ b/tmp/Grib2/Templates/GridDefinitions/0041_RotatedGaussianLatLonGridDefinition.cs @@ -0,0 +1,55 @@ +/* + * This file is part of NGrib. + * + * Copyright © 2020 Nicolas Mangué + * + * Copyright 2006-2010 Seaware AB, PO Box 1244, SE-131 28 + * Nacka Strand, Sweden, info@seaware.se. + * + * Copyright 1997-2006 Unidata Program Center/University + * Corporation for Atmospheric Research, P.O. Box 3000, Boulder, CO 80307, + * support@unidata.ucar.edu. + * + * NGrib is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * NGrib is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with NGrib. If not, see . + */ + +namespace NGrib.Grib2.Templates.GridDefinitions; + +public class RotatedGaussianLatLonGridDefinition : GaussianLatLonGridDefinition +{ + /// . + /// SpLat as a float + /// + /// + public double SpLat { get; } + + /// . + /// SpLon as a float + /// + /// + public double SpLon { get; } + + /// . + /// Rotationangle as a float + /// + /// + public long Rotationangle { get; } + + internal RotatedGaussianLatLonGridDefinition(BufferedBinaryReader reader) : base(reader) + { + SpLat = reader.ReadInt32() * Ratio; + SpLon = reader.ReadUInt32() * Ratio; + Rotationangle = reader.ReadUInt32(); + } +} \ No newline at end of file diff --git a/tmp/Grib2/Templates/GridDefinitions/0042_StretchedGaussianLatLonGridDefinition.cs b/tmp/Grib2/Templates/GridDefinitions/0042_StretchedGaussianLatLonGridDefinition.cs new file mode 100644 index 0000000..abb919b --- /dev/null +++ b/tmp/Grib2/Templates/GridDefinitions/0042_StretchedGaussianLatLonGridDefinition.cs @@ -0,0 +1,55 @@ +/* + * This file is part of NGrib. + * + * Copyright © 2020 Nicolas Mangué + * + * Copyright 2006-2010 Seaware AB, PO Box 1244, SE-131 28 + * Nacka Strand, Sweden, info@seaware.se. + * + * Copyright 1997-2006 Unidata Program Center/University + * Corporation for Atmospheric Research, P.O. Box 3000, Boulder, CO 80307, + * support@unidata.ucar.edu. + * + * NGrib is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * NGrib is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with NGrib. If not, see . + */ + +namespace NGrib.Grib2.Templates.GridDefinitions; + +public class StretchedGaussianLatLonGridDefinition : GaussianLatLonGridDefinition +{ + /// . + /// PoleLat as a float + /// + /// + public double PoleLat { get; } + + /// . + /// PoleLon as a float + /// + /// + public double PoleLon { get; } + + /// . + /// Factor as a float + /// + /// + public long Factor { get; } + + internal StretchedGaussianLatLonGridDefinition(BufferedBinaryReader reader) : base(reader) + { + PoleLat = reader.ReadInt32() * Ratio; + PoleLon = reader.ReadUInt32() * Ratio; + Factor = reader.ReadUInt32(); + } +} \ No newline at end of file diff --git a/tmp/Grib2/Templates/GridDefinitions/0043_StretchedRotatedGaussianLatLonGridDefinition.cs b/tmp/Grib2/Templates/GridDefinitions/0043_StretchedRotatedGaussianLatLonGridDefinition.cs new file mode 100644 index 0000000..0daa88d --- /dev/null +++ b/tmp/Grib2/Templates/GridDefinitions/0043_StretchedRotatedGaussianLatLonGridDefinition.cs @@ -0,0 +1,55 @@ +/* + * This file is part of NGrib. + * + * Copyright © 2020 Nicolas Mangué + * + * Copyright 2006-2010 Seaware AB, PO Box 1244, SE-131 28 + * Nacka Strand, Sweden, info@seaware.se. + * + * Copyright 1997-2006 Unidata Program Center/University + * Corporation for Atmospheric Research, P.O. Box 3000, Boulder, CO 80307, + * support@unidata.ucar.edu. + * + * NGrib is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * NGrib is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with NGrib. If not, see . + */ + +namespace NGrib.Grib2.Templates.GridDefinitions; + +public class StretchedRotatedGaussianLatLonGridDefinition : RotatedGaussianLatLonGridDefinition +{ + /// . + /// PoleLat as a float + /// + /// + public double PoleLat { get; } + + /// . + /// PoleLon as a float + /// + /// + public double PoleLon { get; } + + /// . + /// Factor as a float + /// + /// + public long Factor { get; } + + internal StretchedRotatedGaussianLatLonGridDefinition(BufferedBinaryReader reader) : base(reader) + { + PoleLat = reader.ReadInt32() * Ratio; + PoleLon = reader.ReadUInt32() * Ratio; + Factor = reader.ReadUInt32(); + } +} \ No newline at end of file diff --git a/tmp/Grib2/Templates/GridDefinitions/0050_SphericalHarmonicCoefficientsGridDefinition.cs b/tmp/Grib2/Templates/GridDefinitions/0050_SphericalHarmonicCoefficientsGridDefinition.cs new file mode 100644 index 0000000..1405ad4 --- /dev/null +++ b/tmp/Grib2/Templates/GridDefinitions/0050_SphericalHarmonicCoefficientsGridDefinition.cs @@ -0,0 +1,71 @@ +/* + * This file is part of NGrib. + * + * Copyright © 2020 Nicolas Mangué + * + * Copyright 2006-2010 Seaware AB, PO Box 1244, SE-131 28 + * Nacka Strand, Sweden, info@seaware.se. + * + * Copyright 1997-2006 Unidata Program Center/University + * Corporation for Atmospheric Research, P.O. Box 3000, Boulder, CO 80307, + * support@unidata.ucar.edu. + * + * NGrib is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * NGrib is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with NGrib. If not, see . + */ + +namespace NGrib.Grib2.Templates.GridDefinitions; + +public class SphericalHarmonicCoefficientsGridDefinition : GridDefinition +{ + /// . + /// J as a float + /// + /// + public float J { get; } + + /// . + /// K as a float + /// + /// + public float K { get; } + + /// . + /// M as a float + /// + /// + public float M { get; } + + /// . + /// Method as a int + /// + /// + public int Method { get; } + + /// . + /// Mode as a int + /// + /// + public int Mode { get; } + + internal SphericalHarmonicCoefficientsGridDefinition(BufferedBinaryReader reader) : base(reader) + { + J = reader.ReadSingle(); + K = reader.ReadSingle(); + M = reader.ReadSingle(); + Method = reader.ReadUInt8(); + Mode = reader.ReadUInt8(); + } + + public override IEnumerable EnumerateGridPoints() => throw new NotImplementedException(); +} \ No newline at end of file diff --git a/tmp/Grib2/Templates/GridDefinitions/0051_RotatedSphericalHarmonicCoefficientsGridDefinition.cs b/tmp/Grib2/Templates/GridDefinitions/0051_RotatedSphericalHarmonicCoefficientsGridDefinition.cs new file mode 100644 index 0000000..2acd016 --- /dev/null +++ b/tmp/Grib2/Templates/GridDefinitions/0051_RotatedSphericalHarmonicCoefficientsGridDefinition.cs @@ -0,0 +1,55 @@ +/* + * This file is part of NGrib. + * + * Copyright © 2020 Nicolas Mangué + * + * Copyright 2006-2010 Seaware AB, PO Box 1244, SE-131 28 + * Nacka Strand, Sweden, info@seaware.se. + * + * Copyright 1997-2006 Unidata Program Center/University + * Corporation for Atmospheric Research, P.O. Box 3000, Boulder, CO 80307, + * support@unidata.ucar.edu. + * + * NGrib is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * NGrib is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with NGrib. If not, see . + */ + +namespace NGrib.Grib2.Templates.GridDefinitions; + +public class RotatedSphericalHarmonicCoefficientsGridDefinition : SphericalHarmonicCoefficientsGridDefinition +{ + /// . + /// SpLat as a float + /// + /// + public float SpLat { get; } + + /// . + /// SpLon as a float + /// + /// + public float SpLon { get; } + + /// . + /// Rotationangle as a float + /// + /// + public long Rotationangle { get; } + + internal RotatedSphericalHarmonicCoefficientsGridDefinition(BufferedBinaryReader reader) : base(reader) + { + SpLat = reader.ReadInt32() * 1e-6f; + SpLon = reader.ReadUInt32() * 1e-6f; + Rotationangle = reader.ReadUInt32(); + } +} \ No newline at end of file diff --git a/tmp/Grib2/Templates/GridDefinitions/0052_StretchedSphericalHarmonicCoefficientsGridDefinition.cs b/tmp/Grib2/Templates/GridDefinitions/0052_StretchedSphericalHarmonicCoefficientsGridDefinition.cs new file mode 100644 index 0000000..8ae28ab --- /dev/null +++ b/tmp/Grib2/Templates/GridDefinitions/0052_StretchedSphericalHarmonicCoefficientsGridDefinition.cs @@ -0,0 +1,55 @@ +/* + * This file is part of NGrib. + * + * Copyright © 2020 Nicolas Mangué + * + * Copyright 2006-2010 Seaware AB, PO Box 1244, SE-131 28 + * Nacka Strand, Sweden, info@seaware.se. + * + * Copyright 1997-2006 Unidata Program Center/University + * Corporation for Atmospheric Research, P.O. Box 3000, Boulder, CO 80307, + * support@unidata.ucar.edu. + * + * NGrib is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * NGrib is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with NGrib. If not, see . + */ + +namespace NGrib.Grib2.Templates.GridDefinitions; + +public class StretchedSphericalHarmonicCoefficientsGridDefinition : SphericalHarmonicCoefficientsGridDefinition +{ + /// . + /// PoleLat as a float + /// + /// + public float PoleLat { get; } + + /// . + /// PoleLon as a float + /// + /// + public float PoleLon { get; } + + /// . + /// Factor as a float + /// + /// + public float Factor { get; } + + internal StretchedSphericalHarmonicCoefficientsGridDefinition(BufferedBinaryReader reader) : base(reader) + { + PoleLat = reader.ReadInt32() * 1e-6f; + PoleLon = reader.ReadUInt32() * 1e-6f; + Factor = reader.ReadSingle(); + } +} \ No newline at end of file diff --git a/tmp/Grib2/Templates/GridDefinitions/0053_StretchedRotatedSphericalHarmonicCoefficientsGridDefinition.cs b/tmp/Grib2/Templates/GridDefinitions/0053_StretchedRotatedSphericalHarmonicCoefficientsGridDefinition.cs new file mode 100644 index 0000000..bb5eefb --- /dev/null +++ b/tmp/Grib2/Templates/GridDefinitions/0053_StretchedRotatedSphericalHarmonicCoefficientsGridDefinition.cs @@ -0,0 +1,55 @@ +/* + * This file is part of NGrib. + * + * Copyright © 2020 Nicolas Mangué + * + * Copyright 2006-2010 Seaware AB, PO Box 1244, SE-131 28 + * Nacka Strand, Sweden, info@seaware.se. + * + * Copyright 1997-2006 Unidata Program Center/University + * Corporation for Atmospheric Research, P.O. Box 3000, Boulder, CO 80307, + * support@unidata.ucar.edu. + * + * NGrib is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * NGrib is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with NGrib. If not, see . + */ + +namespace NGrib.Grib2.Templates.GridDefinitions; + +public class StretchedRotatedSphericalHarmonicCoefficientsGridDefinition : RotatedSphericalHarmonicCoefficientsGridDefinition +{ + /// . + /// PoleLat as a float + /// + /// + public float PoleLat { get; } + + /// . + /// PoleLon as a float + /// + /// + public float PoleLon { get; } + + /// . + /// Factor as a float + /// + /// + public float Factor { get; } + + internal StretchedRotatedSphericalHarmonicCoefficientsGridDefinition(BufferedBinaryReader reader) : base(reader) + { + PoleLat = reader.ReadInt32() * 1e-6f; + PoleLon = reader.ReadUInt32() * 1e-6f; + Factor = reader.ReadSingle(); + } +} \ No newline at end of file diff --git a/tmp/Grib2/Templates/GridDefinitions/0090_SpaceViewPerspectiveOrOrthographicGridDefinition.cs b/tmp/Grib2/Templates/GridDefinitions/0090_SpaceViewPerspectiveOrOrthographicGridDefinition.cs new file mode 100644 index 0000000..65ae4a5 --- /dev/null +++ b/tmp/Grib2/Templates/GridDefinitions/0090_SpaceViewPerspectiveOrOrthographicGridDefinition.cs @@ -0,0 +1,100 @@ +/* + * This file is part of NGrib. + * + * Copyright © 2020 Nicolas Mangué + * + * Copyright 2006-2010 Seaware AB, PO Box 1244, SE-131 28 + * Nacka Strand, Sweden, info@seaware.se. + * + * Copyright 1997-2006 Unidata Program Center/University + * Corporation for Atmospheric Research, P.O. Box 3000, Boulder, CO 80307, + * support@unidata.ucar.edu. + * + * NGrib is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * NGrib is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with NGrib. If not, see . + */ + +namespace NGrib.Grib2.Templates.GridDefinitions; + +public class SpaceViewPerspectiveOrOrthographicGridDefinition : XyEarthGridDefinition +{ + public long Lap { get; } + public long Lop { get; } + public long Xo { get; } + public long Yo { get; } + public long Altitude { get; } + + /// . + /// Resolution as a int + /// + /// + public int Resolution { get; } + + /// Get x-increment/distance between two grid points. + /// + /// + /// x-increment + /// + public float Dx { get; } + + /// Get y-increment/distance between two grid points. + /// + /// + /// y-increment + /// + public float Dy { get; } + + /// Get scan mode. + /// + /// + /// scan mode + /// + public int ScanMode { get; } + + + /// . + /// Xp as a float + /// + /// + public float Xp { get; } + + /// . + /// Yp as a float + /// + /// + public float Yp { get; } + + /// . + /// Angle as a int + /// + /// + public long Angle { get; } + + internal SpaceViewPerspectiveOrOrthographicGridDefinition(BufferedBinaryReader reader) : base(reader) + { + Lap = reader.ReadInt32(); + Lop = reader.ReadUInt32(); + Resolution = reader.ReadUInt8(); + Dx = reader.ReadUInt32(); + Dy = reader.ReadUInt32(); + Xp = reader.ReadUInt32() * 1e-3f; + Yp = reader.ReadUInt32() * 1e-3f; + ScanMode = reader.ReadUInt8(); + Angle = reader.ReadUInt32(); + Altitude = reader.ReadUInt32() * 1_000_000; + Xo = reader.ReadUInt32(); + Yo = reader.ReadUInt32(); + } + + public override IEnumerable EnumerateGridPoints() => throw new NotImplementedException(); +} \ No newline at end of file diff --git a/tmp/Grib2/Templates/GridDefinitions/0100_TriangularGridBasedOnAnIcosahedronGridDefinition.cs b/tmp/Grib2/Templates/GridDefinitions/0100_TriangularGridBasedOnAnIcosahedronGridDefinition.cs new file mode 100644 index 0000000..f0cc308 --- /dev/null +++ b/tmp/Grib2/Templates/GridDefinitions/0100_TriangularGridBasedOnAnIcosahedronGridDefinition.cs @@ -0,0 +1,110 @@ +/* + * This file is part of NGrib. + * + * Copyright © 2020 Nicolas Mangué + * + * Copyright 2006-2010 Seaware AB, PO Box 1244, SE-131 28 + * Nacka Strand, Sweden, info@seaware.se. + * + * Copyright 1997-2006 Unidata Program Center/University + * Corporation for Atmospheric Research, P.O. Box 3000, Boulder, CO 80307, + * support@unidata.ucar.edu. + * + * NGrib is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * NGrib is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with NGrib. If not, see . + */ + +namespace NGrib.Grib2.Templates.GridDefinitions; + +public class TriangularGridBasedOnAnIcosahedronGridDefinition : GridDefinition +{ + /// . + /// N2 as a int + /// + /// + public int N2 { get; } + + /// . + /// N3 as a int + /// + /// + public int N3 { get; } + + /// . + /// Ni as a int + /// + /// + public int Ni { get; } + + /// . + /// Nd as a int + /// + /// + public int Nd { get; } + + /// . + /// PoleLat as a float + /// + /// + public float PoleLat { get; } + + /// . + /// PoleLon as a float + /// + /// + public float PoleLon { get; } + + public long Lonofcenter { get; } + + /// . + /// Position as a int + /// + /// + public int Position { get; } + + /// . + /// Order as a int + /// + /// + public int Order { get; } + + /// Get scan mode. + /// + /// + /// scan mode + /// + public int ScanMode { get; } + + /// . + /// N as a int + /// + /// + public long N { get; } + + internal TriangularGridBasedOnAnIcosahedronGridDefinition(BufferedBinaryReader reader) : base(reader) + { + N2 = reader.ReadUInt8(); + N3 = reader.ReadUInt8(); + Ni = reader.ReadUInt16(); + Nd = reader.ReadUInt8(); + PoleLat = reader.ReadInt32() * 1e-6f; + PoleLon = reader.ReadUInt32() * 1e-6f; + Lonofcenter = reader.ReadUInt32(); + Position = reader.ReadUInt8(); + Order = reader.ReadUInt8(); + ScanMode = reader.ReadUInt8(); + N = reader.ReadUInt32(); + } + + public override IEnumerable EnumerateGridPoints() => throw new NotImplementedException(); +} \ No newline at end of file diff --git a/tmp/Grib2/Templates/GridDefinitions/0110_EquatorialAzimuthalEquidistantProjectionGridDefinition.cs b/tmp/Grib2/Templates/GridDefinitions/0110_EquatorialAzimuthalEquidistantProjectionGridDefinition.cs new file mode 100644 index 0000000..371ff9c --- /dev/null +++ b/tmp/Grib2/Templates/GridDefinitions/0110_EquatorialAzimuthalEquidistantProjectionGridDefinition.cs @@ -0,0 +1,67 @@ +/* + * This file is part of NGrib. + * + * Copyright © 2020 Nicolas Mangué + * + * Copyright 2006-2010 Seaware AB, PO Box 1244, SE-131 28 + * Nacka Strand, Sweden, info@seaware.se. + * + * Copyright 1997-2006 Unidata Program Center/University + * Corporation for Atmospheric Research, P.O. Box 3000, Boulder, CO 80307, + * support@unidata.ucar.edu. + * + * NGrib is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * NGrib is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with NGrib. If not, see . + */ + +namespace NGrib.Grib2.Templates.GridDefinitions; + +public class EquatorialAzimuthalEquidistantProjectionGridDefinition : GridPointEarthGridDefinition +{ + /// Get x-increment/distance between two grid points. + /// + /// + /// x-increment + /// + public float Dx { get; } + + /// Get y-increment/distance between two grid points. + /// + /// + /// y-increment + /// + public float Dy { get; } + + /// Get scan mode. + /// + /// + /// scan mode + /// + public int ScanMode { get; } + + /// . + /// ProjectionCenter as a int + /// + /// + public int ProjectionCenter { get; } + + internal EquatorialAzimuthalEquidistantProjectionGridDefinition(BufferedBinaryReader reader) : base(reader) + { + Dx = reader.ReadUInt32() * 1e-3f; + Dy = reader.ReadUInt32() * 1e-3f; + ProjectionCenter = reader.ReadUInt8(); + ScanMode = reader.ReadUInt8(); + } + + public override IEnumerable EnumerateGridPoints() => throw new NotImplementedException(); +} \ No newline at end of file diff --git a/tmp/Grib2/Templates/GridDefinitions/Earth.cs b/tmp/Grib2/Templates/GridDefinitions/Earth.cs new file mode 100644 index 0000000..69bd201 --- /dev/null +++ b/tmp/Grib2/Templates/GridDefinitions/Earth.cs @@ -0,0 +1,67 @@ +/* + * This file is part of NGrib. + * + * Copyright © 2020 Nicolas Mangué + * + * NGrib is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * NGrib is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with NGrib. If not, see . + */ + +using NGrib.Grib2.CodeTables; + +namespace NGrib.Grib2.Templates.GridDefinitions; + +public abstract class Earth +{ + public EarthShape Shape { get; } + + protected Earth(int shapeCode) + { + Shape = shapeCode.As() ?? throw new ArgumentException("Unknown shape code.", nameof(shapeCode)); + } +} + +public class SphericalEarth : Earth +{ + /// . + /// EarthRadius as a float + /// + /// + public double Radius { get; } + + public SphericalEarth(int shapeCode, double radius) : base(shapeCode) + { + Radius = radius; + } +} + +public class OblateSpheroidEarth : Earth +{ + /// . + /// MajorAxis as a float + /// + /// + public double MajorAxis { get; } + + /// . + /// MinorAxis as a float + /// + /// + public double MinorAxis { get; } + + public OblateSpheroidEarth(int shapeCode, double majorAxis, double minorAxis) : base(shapeCode) + { + MajorAxis = majorAxis; + MinorAxis = minorAxis; + } +} \ No newline at end of file diff --git a/tmp/Grib2/Templates/GridDefinitions/EarthGridDefinition.cs b/tmp/Grib2/Templates/GridDefinitions/EarthGridDefinition.cs new file mode 100644 index 0000000..2d94346 --- /dev/null +++ b/tmp/Grib2/Templates/GridDefinitions/EarthGridDefinition.cs @@ -0,0 +1,105 @@ +/* + * This file is part of NGrib. + * + * Copyright © 2020 Nicolas Mangué + * + * Copyright 2006-2010 Seaware AB, PO Box 1244, SE-131 28 + * Nacka Strand, Sweden, info@seaware.se. + * + * Copyright 1997-2006 Unidata Program Center/University + * Corporation for Atmospheric Research, P.O. Box 3000, Boulder, CO 80307, + * support@unidata.ucar.edu. + * + * NGrib is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * NGrib is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with NGrib. If not, see . + */ + +namespace NGrib.Grib2.Templates.GridDefinitions; + +public abstract class EarthGridDefinition : GridDefinition +{ + /// + /// Shape of the earth code. + /// + public int EarthShapeCode { get; } + + /// + /// Radius of spherical earth. + /// + public double? EarthRadius { get; } + + /// + /// Major axis of oblate spheroid earth. + /// + public double? EarthMajorAxis { get; } + + /// + /// Minor axis of oblate spheroid earth. + /// + public double? EarthMinorAxis { get; } + + /// + /// Computed Earth shape (with default values). + /// + public Earth EarthShape { get; } + + private protected EarthGridDefinition(BufferedBinaryReader reader) : base(reader) + { + EarthShapeCode = reader.ReadUInt8(); + + EarthRadius = reader.ReadScaledValue(); + EarthMajorAxis = reader.ReadScaledValue(); + EarthMinorAxis = reader.ReadScaledValue(); + + EarthShape = ComputeEarthShape(); + } + + private Earth ComputeEarthShape() + { + Earth earthShape; + + switch (EarthShapeCode) + { + case (int) CodeTables.EarthShape.DefaultSpherical: + earthShape = new SphericalEarth(EarthShapeCode, 6367470); + break; + case (int) CodeTables.EarthShape.CustomSpherical: + earthShape = new SphericalEarth(EarthShapeCode, EarthRadius ?? throw new BadGribFormatException("Missing Earth radius value.")); + break; + case (int) CodeTables.EarthShape.Iau1965OblateSpheroid: + earthShape = new OblateSpheroidEarth(EarthShapeCode, 6378160.0f, 6356775.0f); + break; + case (int) CodeTables.EarthShape.CustomOblateSpheroid: + earthShape = new OblateSpheroidEarth(EarthShapeCode, + EarthMajorAxis ?? throw new BadGribFormatException("Missing Earth major axis value."), + EarthMinorAxis ?? throw new BadGribFormatException("Missing Earth minor axis value.") + ); + break; + case (int) CodeTables.EarthShape.IagGr80OblateSpheroid: + earthShape = new OblateSpheroidEarth(EarthShapeCode, + 6378137.0f, + 6356752.314f); + break; + case (int) CodeTables.EarthShape.Wgs84: + earthShape = new OblateSpheroidEarth(EarthShapeCode, 6_378_137.0f, 6_356_752.314245179497563967f); + break; + case (int) CodeTables.EarthShape.Wgs84Spherical: + earthShape = new SphericalEarth(EarthShapeCode, 6371229); + break; + default: + return null; + } + + return earthShape; + } +} \ No newline at end of file diff --git a/tmp/Grib2/Templates/GridDefinitions/GridDefinition.cs b/tmp/Grib2/Templates/GridDefinitions/GridDefinition.cs new file mode 100644 index 0000000..b1eb372 --- /dev/null +++ b/tmp/Grib2/Templates/GridDefinitions/GridDefinition.cs @@ -0,0 +1,47 @@ +/* + * This file is part of NGrib. + * + * Copyright © 2020 Nicolas Mangué + * + * NGrib is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * NGrib is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with NGrib. If not, see . + */ + +namespace NGrib.Grib2.Templates.GridDefinitions; + +/// +/// Represents a GRIB2 Grid Definition +/// +public abstract class GridDefinition +{ + /// + /// Grid Definition Offset. + /// + public long Offset { get; } + + private protected GridDefinition(BufferedBinaryReader reader) + { + Offset = reader.Position; + } + + /// + /// Enumerated the point coordinates within the current grid. + /// + /// + /// The points are returned in the order defined by the grid (i.e. scanning mode). + /// + /// + /// Grid points coordinates. + /// + public abstract IEnumerable EnumerateGridPoints(); +} \ No newline at end of file diff --git a/tmp/Grib2/Templates/GridDefinitions/GridPointEarthGridDefinition.cs b/tmp/Grib2/Templates/GridDefinitions/GridPointEarthGridDefinition.cs new file mode 100644 index 0000000..92358a9 --- /dev/null +++ b/tmp/Grib2/Templates/GridDefinitions/GridPointEarthGridDefinition.cs @@ -0,0 +1,49 @@ +/* + * This file is part of NGrib. + * + * Copyright © 2020 Nicolas Mangué + * + * NGrib is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * NGrib is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with NGrib. If not, see . + */ + +namespace NGrib.Grib2.Templates.GridDefinitions; + +public abstract class GridPointEarthGridDefinition : XyEarthGridDefinition +{ + /// . + /// La1 as a float + /// + /// + public double La1 { get; } + + /// . + /// Lo1 as a float + /// + /// + public double Lo1 { get; } + + /// . + /// Resolution as a int + /// + /// + public int Resolution { get; } + + + private protected GridPointEarthGridDefinition(BufferedBinaryReader reader) : base(reader) + { + La1 = reader.ReadInt32() * 1e-6; + Lo1 = reader.ReadUInt32() * 1e-6; + Resolution = reader.ReadUInt8(); + } +} \ No newline at end of file diff --git a/tmp/Grib2/Templates/GridDefinitions/XyEarthGridDefinition.cs b/tmp/Grib2/Templates/GridDefinitions/XyEarthGridDefinition.cs new file mode 100644 index 0000000..0c0a19e --- /dev/null +++ b/tmp/Grib2/Templates/GridDefinitions/XyEarthGridDefinition.cs @@ -0,0 +1,39 @@ +/* + * This file is part of NGrib. + * + * Copyright © 2020 Nicolas Mangué + * + * NGrib is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * NGrib is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with NGrib. If not, see . + */ + +namespace NGrib.Grib2.Templates.GridDefinitions; + +public abstract class XyEarthGridDefinition : EarthGridDefinition +{ + /// + /// Number of points along x-axis or a parallel. + /// + public long Nx { get; } + + /// + /// Number of points along y-axis or a meridian. + /// + public long Ny { get; } + + private protected XyEarthGridDefinition(BufferedBinaryReader reader) : base(reader) + { + Nx = reader.ReadUInt32(); + Ny = reader.ReadUInt32(); + } +} \ No newline at end of file diff --git a/tmp/Grib2/Templates/ProductDefinitions/ChemicalOrPhysicalConsistent.cs b/tmp/Grib2/Templates/ProductDefinitions/ChemicalOrPhysicalConsistent.cs new file mode 100644 index 0000000..3a4102e --- /dev/null +++ b/tmp/Grib2/Templates/ProductDefinitions/ChemicalOrPhysicalConsistent.cs @@ -0,0 +1,252 @@ +namespace NGrib.Grib2.Templates.ProductDefinitions; + +public enum ChemicalOrPhysicalConsistent : ushort +{ + Ozone = 0, + + WaterVapour, + + Methane, + + CarbonDioxide, + + CarbonMonoxide, + + NitrogenDioxide, + + NitrousOxide, + + Formaldehyde, + + SulphurDioxide, + + Ammonia, + + Ammonium, + + NitrogenMonoxide, + + AtomicOxygen, + + NitrateRadical, + + HydroperoxylRadical, + + DinitrogenPentoxide, + + NitrousAcid, + + NitricAcid, + + PeroxynitricAcid, + + HydrogenPeroxide, + + MolecularHydrogen, + + AtomicNitrogen, + + Sulphate, + + Radon, + + ElementalMercury, + + DivalentMercury, + + AtomicChlorine, + + ChlorineMonoxide, + + DichlorinePeroxide, + + HypochlorousAcid, + + ChlorineNitrate, + + ChlorineDioxide, + + AtomicBromide, + + BromineMonoxide, + + BromineChloride, + + HydrogenBromide, + + HypobromousAcid, + + BromineNitrate, + + Oxygen, + + HydroxylRadical = 10000, + + MethylPeroxyRadical, + + MethylHydroperoxide, + + Methanol = 10004, + + FormicAcid, + + HydrogenCyanide, + + AcetoNitrile, + + Ethane, + + EtheneEthylene, + + EthyneAcetylene, + + Ethanol, + + AceticAcid, + + PeroxyacetylNitrate, + + Propane, + + Propene, + + Butanes, + + Isoprene, + + AlphaPinene, + + BetaPinene, + + Limonene, + + Benzene, + + Toluene, + + Xylene, + + DimethylSulphide = 10500, + + HydrogenChloride = 20000, + + Cfc11, + + Cfc12, + + Cfc113, + + Cfc113A, + + Cfc114, + + Cfc115, + + Hcfc22, + + Hcfc141B, + + Hcfc142B, + + Halon1202, + + Halon1211, + + Halon1301, + + Halon2402, + + MethylChlorideHcc40, + + CarbonTetrachlorideHcc10, + + Hcc140A, + + MethylBromideHbc40B1, + + HexachlorocyclohexaneHch, + + AlphaHexachlorocyclohexane, + + HexachlorobiphenylPcb153, + + /// + /// Tracer, defined by originating centre + /// + RadioactivePollutant = 30000, + + /// + /// OH+HO2 + /// + HOxRadical, + + /// + /// HO2+RO2 + /// + TotalInorganicAndOrganicPeroxyRadicals, + + PassiveOzone, + + NOxExpressedAsNitrogen, + + AllNitrogenOxidesNOyExpressedAsNitrogen, + + TotalInorganicChlorine, + + TotalInorganicBromine, + + /// + ///Total Inorganic Chlorine Except HCl, ClONO2: ClOx + /// + TotalInorganicChlorineExceptHClClOno2ClOx, + + /// + /// Total Inorganic Bromine Except Hbr, BrONO2:BrOx + /// + TotalInorganicBromineExceptHbrBrOno2BrOx, + + LumpedAlkanes, + + LumpedAlkenes, + + LumpedAromaticCoumpounds, + + LumpedTerpenes, + + NonMethaneVolatileOrganicCompoundsExpressedAsCarbon, + + AnthropogenicNonMethaneVolatileOrganicCompoundsExpressedAsCarbon, + + BiogenicNonMethaneVolatileOrganicCompoundsExpressedAsCarbon, + + LumpedOxygenatedHydrocarbons, + + TotalAerosol = 62000, + + DustDry, + + WaterInAmbient, + + AmmoniumDry, + + NitrateDry, + + NitricAcidTrihydrate, + + SulphateDry, + + MercuryDry, + + SeaSaltDry, + + BlackCarbonDry, + + ParticulateOrganicMatterDry, + + PrimaryParticulateOrganicMatterDry, + + SecondaryParticulateOrganicMatterDry, + + Missing = 65535 +} + diff --git a/tmp/Grib2/Templates/ProductDefinitions/ProductDefinition.cs b/tmp/Grib2/Templates/ProductDefinitions/ProductDefinition.cs new file mode 100644 index 0000000..50cb9c0 --- /dev/null +++ b/tmp/Grib2/Templates/ProductDefinitions/ProductDefinition.cs @@ -0,0 +1,81 @@ +/* + * This file is part of NGrib. + * + * Copyright © 2020 Nicolas Mangué + * + * NGrib is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * NGrib is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with NGrib. If not, see . + */ + +using NGrib.Grib2.CodeTables; + +namespace NGrib.Grib2.Templates.ProductDefinitions; + +/// +/// Represents a GRIB2 Product Definition. +/// +public abstract class ProductDefinition : Template +{ + /// + /// Start position on the product definition. + /// + public long Offset { get; } + + /// + /// Parameter category. + /// + public int ParameterCategory { get; } + + /// + /// Parameter number. + /// + public int ParameterNumber { get; } + + /// + /// Parameter informations. + /// + /// + /// null if a unknown discipline/category/number is used. + /// + public Parameter? Parameter { get; } + + /// + /// Type of generating process. + /// + public GeneratingProcessType GeneratingProcessType { get; set; } + + private protected ProductDefinition(BufferedBinaryReader reader, Discipline discipline) + { + Offset = reader.Position; + ParameterCategory = reader.ReadUInt8(); + RegisterContent(ProductDefinitionContent.ParameterCategory, () => ParameterCategory); + + ParameterNumber = reader.ReadUInt8(); + RegisterContent(ProductDefinitionContent.ParameterNumber, () => ParameterNumber); + + Parameter = CodeTables.Parameter.Get(discipline, ParameterCategory, ParameterNumber); + if (Parameter.HasValue) + { + RegisterContent(ProductDefinitionContent.Parameter, () => Parameter.Value); + } + + InitGeneratingProcessType(reader); + } + + //Todo: сделать красивее + protected virtual void InitGeneratingProcessType(BufferedBinaryReader reader) + { + GeneratingProcessType = (GeneratingProcessType) reader.ReadUInt8(); + RegisterContent(ProductDefinitionContent.GeneratingProcessType, () => GeneratingProcessType); + } +} \ No newline at end of file diff --git a/tmp/Grib2/Templates/ProductDefinitions/ProductDefinition0000.cs b/tmp/Grib2/Templates/ProductDefinitions/ProductDefinition0000.cs new file mode 100644 index 0000000..31d6009 --- /dev/null +++ b/tmp/Grib2/Templates/ProductDefinitions/ProductDefinition0000.cs @@ -0,0 +1,113 @@ +/* + * This file is part of NGrib. + * + * Copyright © 2020 Nicolas Mangué + * + * NGrib is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * NGrib is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with NGrib. If not, see . + */ + +using NGrib.Grib2.CodeTables; + +namespace NGrib.Grib2.Templates.ProductDefinitions; + +/// +/// Product Definition Template 4.0: Analysis or forecast at a horizontal level or in a horizontal layer at a point in time +/// +public class ProductDefinition0000 : WithBackgroundProductDefinition +{ + /// + /// Analysis or forecast generating processes identifier. + /// + public int GeneratingProcessIdentifier { get; } + + /// + /// Hours of observational data cutoff after reference time. + /// + public int HoursAfter { get; } + + /// + /// Minutes of observational data cutoff after reference time. + /// + public int MinutesAfter { get; } + + /// + /// Timespan of observational data cutoff after reference time. + /// + public TimeSpan ObservationalDataCutoff { get; } + + /// + /// Indicator of unit of time range. + /// + public TimeRangeUnitGrib2 TimeRangeUnitGrib2 { get; } + + /// + /// Forecast time in units defined by indicator of unit of time range. + /// + public int ForecastTime { get; } + + /// + /// Type of first fixed surface. + /// + public FixedSurfaceType FirstFixedSurfaceType { get; } + + /// + /// Value of first fixed surface. + /// + public double? FirstFixedSurfaceValue { get; } + + /// + /// Type of second fixed surface. + /// + public FixedSurfaceType SecondFixedSurfaceType { get; } + + /// + /// Value of second fixed surface. + /// + public double? SecondFixedSurfaceValue { get; } + + internal ProductDefinition0000(BufferedBinaryReader reader, Discipline discipline) : base( + reader, discipline) + { + GeneratingProcessIdentifier = reader.ReadUInt8(); + HoursAfter = reader.ReadUInt16(); + MinutesAfter = reader.ReadUInt8(); + ObservationalDataCutoff = TimeSpan.FromHours(HoursAfter) + TimeSpan.FromMinutes(MinutesAfter); + TimeRangeUnitGrib2 = (TimeRangeUnitGrib2) reader.ReadUInt8(); + ForecastTime = reader.ReadInt32(); + + FirstFixedSurfaceType = (FixedSurfaceType) reader.ReadUInt8(); + FirstFixedSurfaceValue = reader.ReadScaledValue(); + + SecondFixedSurfaceType = (FixedSurfaceType) reader.ReadUInt8(); + SecondFixedSurfaceValue = reader.ReadScaledValue(); + + RegisterContent(ProductDefinitionContent.GeneratingProcessId, () => GeneratingProcessIdentifier); + RegisterContent(ProductDefinitionContent.ObservationalDataCutoff, () => ObservationalDataCutoff); + var forecastTime = CalculateTimeRangeFrom(TimeRangeUnitGrib2, ForecastTime); + if (forecastTime.HasValue) { + RegisterContent(ProductDefinitionContent.ForecastTime, () => forecastTime.Value); + } + + RegisterContent(ProductDefinitionContent.FirstFixedSurfaceType, () => FirstFixedSurfaceType); + if (FirstFixedSurfaceValue.HasValue) + { + RegisterContent(ProductDefinitionContent.FirstFixedSurfaceValue, () => FirstFixedSurfaceValue.Value); + } + RegisterContent(ProductDefinitionContent.SecondFixedSurfaceType, () => SecondFixedSurfaceType); + if (SecondFixedSurfaceValue.HasValue) + { + RegisterContent(ProductDefinitionContent.SecondFixedSurfaceValue, () => SecondFixedSurfaceValue.Value); + } + } +} \ No newline at end of file diff --git a/tmp/Grib2/Templates/ProductDefinitions/ProductDefinition0001.cs b/tmp/Grib2/Templates/ProductDefinitions/ProductDefinition0001.cs new file mode 100644 index 0000000..174b69a --- /dev/null +++ b/tmp/Grib2/Templates/ProductDefinitions/ProductDefinition0001.cs @@ -0,0 +1,54 @@ +/* + * This file is part of NGrib. + * + * Copyright © 2020 Nicolas Mangué + * + * NGrib is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * NGrib is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with NGrib. If not, see . + */ + +using NGrib.Grib2.CodeTables; + +namespace NGrib.Grib2.Templates.ProductDefinitions; + +/// +/// Product Definition Template 4.1: Individual ensemble forecast, control and perturbed, at ahorizontal level or in a horizontal layer at a point in time. +/// +public class ProductDefinition0001 : ProductDefinition0000 +{ + /// + /// Type of ensemble forecast (see Code table 4.6). + /// + public EnsembleForecastType EnsembleForecastType { get; } + + /// + /// Perturbation number. + /// + public int PerturbationNumber { get; } + + /// + /// Number of forecasts in ensemble + /// + public int EnsembleForecastsNumber { get; } + + internal ProductDefinition0001(BufferedBinaryReader reader, Discipline discipline) : base(reader, discipline) + { + EnsembleForecastType = (EnsembleForecastType) reader.ReadByte(); + PerturbationNumber = reader.ReadByte(); + EnsembleForecastsNumber = reader.ReadByte(); + + RegisterContent(ProductDefinitionContent.EnsembleForecastType, () => EnsembleForecastType); + RegisterContent(ProductDefinitionContent.PerturbationNumber, () => PerturbationNumber); + RegisterContent(ProductDefinitionContent.EnsembleForecastsNumber, () => EnsembleForecastsNumber); + } +} \ No newline at end of file diff --git a/tmp/Grib2/Templates/ProductDefinitions/ProductDefinition0002.cs b/tmp/Grib2/Templates/ProductDefinitions/ProductDefinition0002.cs new file mode 100644 index 0000000..cfbf7e0 --- /dev/null +++ b/tmp/Grib2/Templates/ProductDefinitions/ProductDefinition0002.cs @@ -0,0 +1,48 @@ +/* + * This file is part of NGrib. + * + * Copyright © 2020 Nicolas Mangué + * + * NGrib is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * NGrib is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with NGrib. If not, see . + */ + +using NGrib.Grib2.CodeTables; + +namespace NGrib.Grib2.Templates.ProductDefinitions; + +/// +/// Product Definition Template 4.2: Derived forecast based on all ensemble members at a horizontal level +/// or in a horizontal layer at a point in time. +/// +public class ProductDefinition0002 : ProductDefinition0000 +{ + /// + /// Derived forecast (see Code Table 4.7) + /// + public int DerivedForecast { get; } + + /// + /// Number of forecasts in ensemble + /// + public int EnsembleForecastsNumber { get; } + + internal ProductDefinition0002(BufferedBinaryReader reader, Discipline discipline) : base(reader, discipline) + { + DerivedForecast = reader.ReadByte(); + EnsembleForecastsNumber = reader.ReadByte(); + + RegisterContent(ProductDefinitionContent.DerivedForecast, () => DerivedForecast); + RegisterContent(ProductDefinitionContent.EnsembleForecastsNumber, () => EnsembleForecastsNumber); + } +} \ No newline at end of file diff --git a/tmp/Grib2/Templates/ProductDefinitions/ProductDefinition0008.cs b/tmp/Grib2/Templates/ProductDefinitions/ProductDefinition0008.cs new file mode 100644 index 0000000..1585d74 --- /dev/null +++ b/tmp/Grib2/Templates/ProductDefinitions/ProductDefinition0008.cs @@ -0,0 +1,119 @@ +/* + * This file is part of NGrib. + * + * Copyright © 2020 Nicolas Mangué + * + * NGrib is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * NGrib is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with NGrib. If not, see . + */ + +using NGrib.Grib2.CodeTables; + +namespace NGrib.Grib2.Templates.ProductDefinitions; + +/// +/// Product Definition Template 4.8: Average, accumulation, and/or extreme values +/// or other statistically processed values at a horizontal level or in a horizontal +/// layer in a continuous or non-continuous time interval +/// +public class ProductDefinition0008 : ProductDefinition0000 +{ + /// + /// Time of end of overall time interval. + /// + public DateTime OverallTimeIntervalEnd { get; } + + /// + /// Number of time range specifications describing the time intervals used to calculate the statistically processed field. + /// + public int TimeRangeNumber { get; } + + /// + /// Total number of data values missing in statistical process. + /// + public long MissingDataValuesTotalNumber { get; } + + /// + /// Statistical process used to calculate the processed field from the field at each time increment during the time range. + /// + public int StatisticalProcess { get; } + + /// + /// Type of time increment between successive fields used in the statistical processing. + /// + public long StatisticalProcessingTimeIncrementType { get; } + + /// + /// Indicator of unit of time for time range over which statistical processing is done. + /// + public TimeRangeUnitGrib2 StatisticalProcessingTimeRangeUnitGrib2 { get; } + + /// + /// Length of the time range over which statistical processing is done, in units defined by StatisticalProcessingTimeRangeUnit. + /// + public long StatisticalProcessingTimeRangeLength { get; } + + /// + /// Indicator of unit of time for the increment between the successive fields used. + /// + public TimeRangeUnitGrib2 SuccessiveFieldsIncrementRangeUnitGrib2 { get; } + + /// + /// Time increment between successive fields, in units defined by SuccessiveFieldsIncrementUnit. + /// + public long SuccessiveFieldsTimeIncrement { get; } + + internal ProductDefinition0008( + BufferedBinaryReader reader, + Discipline discipline) : base(reader, discipline) + { + OverallTimeIntervalEnd = reader.ReadDateTime(); + RegisterContent(ProductDefinitionContent.OverallTimeIntervalEnd, () => OverallTimeIntervalEnd); + + // 42 + TimeRangeNumber = reader.ReadUInt8(); + + // 43-46 + MissingDataValuesTotalNumber = reader.ReadUInt32(); + + //47 + StatisticalProcess = reader.ReadUInt8(); + + //48 + StatisticalProcessingTimeIncrementType = reader.ReadUInt8(); + + //49 + StatisticalProcessingTimeRangeUnitGrib2 = (TimeRangeUnitGrib2) reader.ReadUInt8(); + + //50-53 + StatisticalProcessingTimeRangeLength = reader.ReadUInt32(); + + var timeRange = CalculateTimeRangeFrom(StatisticalProcessingTimeRangeUnitGrib2, StatisticalProcessingTimeRangeLength); + if (timeRange.HasValue) + { + RegisterContent(ProductDefinitionContent.StatisticalProcessingTimeRange, () => timeRange.Value); + } + + //54 + SuccessiveFieldsIncrementRangeUnitGrib2 = (TimeRangeUnitGrib2) reader.ReadUInt8(); + + //55-58 + SuccessiveFieldsTimeIncrement = reader.ReadUInt32(); + + var successiveFieldsTimeIncrement = CalculateTimeRangeFrom(SuccessiveFieldsIncrementRangeUnitGrib2, SuccessiveFieldsTimeIncrement); + if (successiveFieldsTimeIncrement.HasValue) + { + RegisterContent(ProductDefinitionContent.StatisticalProcessingTimeRange, () => successiveFieldsTimeIncrement.Value); + } + } +} \ No newline at end of file diff --git a/tmp/Grib2/Templates/ProductDefinitions/ProductDefinition0011.cs b/tmp/Grib2/Templates/ProductDefinitions/ProductDefinition0011.cs new file mode 100644 index 0000000..a14a352 --- /dev/null +++ b/tmp/Grib2/Templates/ProductDefinitions/ProductDefinition0011.cs @@ -0,0 +1,116 @@ +/* + * This file is part of NGrib. + * + * Copyright © 2020 Nicolas Mangué + * + * NGrib is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * NGrib is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with NGrib. If not, see . + */ + +using NGrib.Grib2.CodeTables; + +namespace NGrib.Grib2.Templates.ProductDefinitions; + +/// +/// Product definition template 4.11 – Individual ensemble forecast, control and perturbed, +/// at ahorizontal level or in a horizontal layer in a continuous or non-continuous time interval. +/// +public class ProductDefinition0011 : ProductDefinition0001 +{ + /// + /// Time of end of overall time interval + /// + public DateTime OverallTimeIntervalEnd { get; } + + /// + /// Number of time range specifications describing the time intervals used to calculate the statistically processed field. + /// + public int TimeRangeNumber { get; } + + /// + /// Total number of data values missing in statistical process. + /// + public long MissingDataValuesTotalNumber { get; } + + /// + /// Statistical process used to calculate the processed field from the field at each time increment during the time range. + /// + public int StatisticalProcess { get; } + + /// + /// Type of time increment between successive fields used in the statistical processing. + /// + public long StatisticalProcessingTimeIncrementType { get; } + + /// + /// Indicator of unit of time for time range over which statistical processing is done. + /// + public TimeRangeUnitGrib2 StatisticalProcessingTimeRangeUnitGrib2 { get; } + + /// + /// Length of the time range over which statistical processing is done, in units defined by StatisticalProcessingTimeRangeUnit. + /// + public long StatisticalProcessingTimeRangeLength { get; } + + /// + /// Indicator of unit of time for the increment between the successive fields used. + /// + public TimeRangeUnitGrib2 SuccessiveFieldsIncrementRangeUnitGrib2 { get; } + + /// + /// Time increment between successive fields, in units defined by SuccessiveFieldsIncrementUnit. + /// + public long SuccessiveFieldsTimeIncrement { get; } + + internal ProductDefinition0011(BufferedBinaryReader reader, Discipline discipline) : base(reader, discipline) + { + OverallTimeIntervalEnd = reader.ReadDateTime(); + RegisterContent(ProductDefinitionContent.OverallTimeIntervalEnd, () => OverallTimeIntervalEnd); + + // 42 + TimeRangeNumber = reader.ReadUInt8(); + + // 43-46 + MissingDataValuesTotalNumber = reader.ReadUInt32(); + + //47 + StatisticalProcess = reader.ReadUInt8(); + + //48 + StatisticalProcessingTimeIncrementType = reader.ReadUInt8(); + + //49 + StatisticalProcessingTimeRangeUnitGrib2 = (TimeRangeUnitGrib2)reader.ReadUInt8(); + + //50-53 + StatisticalProcessingTimeRangeLength = reader.ReadUInt32(); + + var timeRange = CalculateTimeRangeFrom(StatisticalProcessingTimeRangeUnitGrib2, StatisticalProcessingTimeRangeLength); + if (timeRange.HasValue) + { + RegisterContent(ProductDefinitionContent.StatisticalProcessingTimeRange, () => timeRange.Value); + } + + //54 + SuccessiveFieldsIncrementRangeUnitGrib2 = (TimeRangeUnitGrib2)reader.ReadUInt8(); + + //55-58 + SuccessiveFieldsTimeIncrement = reader.ReadUInt32(); + + var successiveFieldsTimeIncrement = CalculateTimeRangeFrom(SuccessiveFieldsIncrementRangeUnitGrib2, SuccessiveFieldsTimeIncrement); + if (successiveFieldsTimeIncrement.HasValue) + { + RegisterContent(ProductDefinitionContent.StatisticalProcessingTimeRange, () => successiveFieldsTimeIncrement.Value); + } + } +} \ No newline at end of file diff --git a/tmp/Grib2/Templates/ProductDefinitions/ProductDefinition0012.cs b/tmp/Grib2/Templates/ProductDefinitions/ProductDefinition0012.cs new file mode 100644 index 0000000..41e54ba --- /dev/null +++ b/tmp/Grib2/Templates/ProductDefinitions/ProductDefinition0012.cs @@ -0,0 +1,116 @@ +/* + * This file is part of NGrib. + * + * Copyright © 2020 Nicolas Mangué + * + * NGrib is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * NGrib is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with NGrib. If not, see . + */ + +using NGrib.Grib2.CodeTables; + +namespace NGrib.Grib2.Templates.ProductDefinitions; + +/// +/// Product definition template 4.12: Derived forecasts based on all ensemble members at a horizontal level +/// or in a horizontal layer in a continuous or non-continuous time interval. +/// +public class ProductDefinition0012 : ProductDefinition0002 +{ + /// + /// Time of end of overall time interval + /// + public DateTime OverallTimeIntervalEnd { get; } + + /// + /// Number of time range specifications describing the time intervals used to calculate the statistically processed field. + /// + public int TimeRangeNumber { get; } + + /// + /// Total number of data values missing in statistical process. + /// + public long MissingDataValuesTotalNumber { get; } + + /// + /// Statistical process used to calculate the processed field from the field at each time increment during the time range. + /// + public int StatisticalProcess { get; } + + /// + /// Type of time increment between successive fields used in the statistical processing. + /// + public long StatisticalProcessingTimeIncrementType { get; } + + /// + /// Indicator of unit of time for time range over which statistical processing is done. + /// + public TimeRangeUnitGrib2 StatisticalProcessingTimeRangeUnitGrib2 { get; } + + /// + /// Length of the time range over which statistical processing is done, in units defined by StatisticalProcessingTimeRangeUnit. + /// + public long StatisticalProcessingTimeRangeLength { get; } + + /// + /// Indicator of unit of time for the increment between the successive fields used. + /// + public TimeRangeUnitGrib2 SuccessiveFieldsIncrementRangeUnitGrib2 { get; } + + /// + /// Time increment between successive fields, in units defined by SuccessiveFieldsIncrementUnit. + /// + public long SuccessiveFieldsTimeIncrement { get; } + + internal ProductDefinition0012(BufferedBinaryReader reader, Discipline discipline) : base(reader, discipline) + { + OverallTimeIntervalEnd = reader.ReadDateTime(); + RegisterContent(ProductDefinitionContent.OverallTimeIntervalEnd, () => OverallTimeIntervalEnd); + + // 42 + TimeRangeNumber = reader.ReadUInt8(); + + // 43-46 + MissingDataValuesTotalNumber = reader.ReadUInt32(); + + //47 + StatisticalProcess = reader.ReadUInt8(); + + //48 + StatisticalProcessingTimeIncrementType = reader.ReadUInt8(); + + //49 + StatisticalProcessingTimeRangeUnitGrib2 = (TimeRangeUnitGrib2)reader.ReadUInt8(); + + //50-53 + StatisticalProcessingTimeRangeLength = reader.ReadUInt32(); + + var timeRange = CalculateTimeRangeFrom(StatisticalProcessingTimeRangeUnitGrib2, StatisticalProcessingTimeRangeLength); + if (timeRange.HasValue) + { + RegisterContent(ProductDefinitionContent.StatisticalProcessingTimeRange, () => timeRange.Value); + } + + //54 + SuccessiveFieldsIncrementRangeUnitGrib2 = (TimeRangeUnitGrib2)reader.ReadUInt8(); + + //55-58 + SuccessiveFieldsTimeIncrement = reader.ReadUInt32(); + + var successiveFieldsTimeIncrement = CalculateTimeRangeFrom(SuccessiveFieldsIncrementRangeUnitGrib2, SuccessiveFieldsTimeIncrement); + if (successiveFieldsTimeIncrement.HasValue) + { + RegisterContent(ProductDefinitionContent.StatisticalProcessingTimeRange, () => successiveFieldsTimeIncrement.Value); + } + } +} \ No newline at end of file diff --git a/tmp/Grib2/Templates/ProductDefinitions/ProductDefinition0040.cs b/tmp/Grib2/Templates/ProductDefinitions/ProductDefinition0040.cs new file mode 100644 index 0000000..c924ac6 --- /dev/null +++ b/tmp/Grib2/Templates/ProductDefinitions/ProductDefinition0040.cs @@ -0,0 +1,20 @@ +using NGrib.Grib2.CodeTables; + +namespace NGrib.Grib2.Templates.ProductDefinitions; + +public class ProductDefinition0040:ProductDefinition0000 +{ + public ChemicalOrPhysicalConsistent ChemicalOrPhysicalConsistent { get; set; } + + protected override void InitGeneratingProcessType(BufferedBinaryReader reader) + { + ChemicalOrPhysicalConsistent = (ChemicalOrPhysicalConsistent)reader.ReadUInt16(); + RegisterContent(ProductDefinitionContent.ChemicalOrPhysicalConsistent, ()=>ChemicalOrPhysicalConsistent); + + base.InitGeneratingProcessType(reader); + } + + internal ProductDefinition0040(BufferedBinaryReader reader, Discipline discipline) : base(reader, discipline) + { + } +} \ No newline at end of file diff --git a/tmp/Grib2/Templates/ProductDefinitions/ProductDefinitionContent.cs b/tmp/Grib2/Templates/ProductDefinitions/ProductDefinitionContent.cs new file mode 100644 index 0000000..a3cf7fe --- /dev/null +++ b/tmp/Grib2/Templates/ProductDefinitions/ProductDefinitionContent.cs @@ -0,0 +1,135 @@ +/* + * This file is part of NGrib. + * + * Copyright © 2020 Nicolas Mangué + * + * NGrib is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * NGrib is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with NGrib. If not, see . + */ + +using NGrib.Grib2.CodeTables; + +namespace NGrib.Grib2.Templates.ProductDefinitions; + +/// +/// Catalog of the product definition contents. +/// +public static class ProductDefinitionContent +{ + /// + /// Parameter category (see Code Table 4.1). + /// + public static TemplateContent ParameterCategory { get; } = new TemplateContent(); + + /// + /// Parameter number (see Code Table 4.2). + /// + public static TemplateContent ParameterNumber { get; } = new TemplateContent(); + + /// + /// Parameter. + /// + public static TemplateContent Parameter { get; } = new TemplateContent(); + + /// + /// Type of generating process (see Code Table 4.3). + /// + public static TemplateContent GeneratingProcessType { get; } = + new TemplateContent(); + + /// + /// Background generating process identifier (defined by originating centre). + /// + public static TemplateContent BackgroundGeneratingProcessId { get; } = new TemplateContent(); + + /// + /// Analysis or forecast generating processes identifier (defined by originating centre). + /// + public static TemplateContent GeneratingProcessId { get; } = new TemplateContent(); + + /// + /// Time span of observational data cutoff after reference time. + /// + public static TemplateContent ObservationalDataCutoff { get; } = new TemplateContent(); + + /// + /// Forecast time. + /// + public static TemplateContent ForecastTime { get; } = new TemplateContent(); + + /// + /// Type of first fixed surface (see Code Table 4.5). + /// + public static TemplateContent FirstFixedSurfaceType { get; } = + new TemplateContent(); + + /// + /// Value of first fixed surface. + /// + public static TemplateContent FirstFixedSurfaceValue { get; } = new TemplateContent(); + + /// + /// Type of second fixed surface (see Code Table 4.5). + /// + public static TemplateContent SecondFixedSurfaceType { get; } = + new TemplateContent(); + + /// + /// Value of second fixed surface. + /// + public static TemplateContent SecondFixedSurfaceValue { get; } = new TemplateContent(); + + /// + /// Type of ensemble forecast (see Code Table 4.6). + /// + public static TemplateContent EnsembleForecastType { get; } = + new TemplateContent(); + + /// + /// Perturbation number. + /// + public static TemplateContent PerturbationNumber { get; } = new TemplateContent(); + + /// + /// Number of forecasts in ensemble. + /// + public static TemplateContent EnsembleForecastsNumber { get; } = new TemplateContent(); + + /// + /// Derived forecast (see Code Table 4.7). + /// + public static TemplateContent DerivedForecast { get; } = new TemplateContent(); + + /// + /// Datetime of end of overall time interval. + /// + public static TemplateContent OverallTimeIntervalEnd { get; } = new TemplateContent(); + + /// + /// Time range over which statistical processing is done. + /// + public static TemplateContent StatisticalProcessingTimeRange { get; } = + new TemplateContent(); + + /// + /// Time increment between successive fields. + /// + public static TemplateContent SuccessiveFieldsTimeIncrement { get; } = + new TemplateContent(); + + /// + /// Atmospheric Chemical Constituent Type + /// + public static TemplateContent ChemicalOrPhysicalConsistent { get; } + = new TemplateContent(); +} \ No newline at end of file diff --git a/tmp/Grib2/Templates/ProductDefinitions/WithBackgroundProductDefinition.cs b/tmp/Grib2/Templates/ProductDefinitions/WithBackgroundProductDefinition.cs new file mode 100644 index 0000000..e3402d7 --- /dev/null +++ b/tmp/Grib2/Templates/ProductDefinitions/WithBackgroundProductDefinition.cs @@ -0,0 +1,36 @@ +/* + * This file is part of NGrib. + * + * Copyright © 2020 Nicolas Mangué + * + * NGrib is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * NGrib is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with NGrib. If not, see . + */ + +using NGrib.Grib2.CodeTables; + +namespace NGrib.Grib2.Templates.ProductDefinitions; + +public class WithBackgroundProductDefinition : ProductDefinition +{ + /// + /// Background generating process identifier. + /// + public int BackgroundGeneratingProcessIdentifier { get; } + + internal WithBackgroundProductDefinition(BufferedBinaryReader reader, Discipline discipline) : base(reader, + discipline) + { + BackgroundGeneratingProcessIdentifier = reader.ReadUInt8(); + } +} \ No newline at end of file diff --git a/tmp/Grib2/Templates/Template.cs b/tmp/Grib2/Templates/Template.cs new file mode 100644 index 0000000..91a5d77 --- /dev/null +++ b/tmp/Grib2/Templates/Template.cs @@ -0,0 +1,75 @@ +/* + * This file is part of NGrib. + * + * Copyright © 2020 Nicolas Mangué + * + * NGrib is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * NGrib is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with NGrib. If not, see . + */ + +using NGrib.Grib2.CodeTables; + +namespace NGrib.Grib2.Templates; + +public abstract class Template +{ + private readonly Dictionary> _accessors = new Dictionary>(); + + protected Template() + { + } + + protected void RegisterContent(TemplateContent content, Func accesor) + { + _accessors[content] = () => accesor(); + } + + public bool TryGet(TemplateContent content, out T result) + { + if (_accessors.TryGetValue(content, out var methodInfo)) + { + result = (T) methodInfo.Invoke(); + return true; + } + + result = default; + return false; + } + + protected TimeSpan? CalculateTimeRangeFrom(TimeRangeUnitGrib2 rangeUnitGrib2, long value) + { + switch(rangeUnitGrib2) + { + case TimeRangeUnitGrib2.Minute: + return TimeSpan.FromMinutes(value); + case TimeRangeUnitGrib2.Hour: + return TimeSpan.FromHours(value); + case TimeRangeUnitGrib2.Day: + return TimeSpan.FromDays(value); + case TimeRangeUnitGrib2.Month: + return TimeSpan.FromDays(value); + case TimeRangeUnitGrib2.Hours3: + return TimeSpan.FromHours(value*3); + case TimeRangeUnitGrib2.Hours6: + return TimeSpan.FromDays(value*6); + case TimeRangeUnitGrib2.Hours12: + return TimeSpan.FromDays(value*12); + case TimeRangeUnitGrib2.Second: + return TimeSpan.FromSeconds(value); + default: + // The other TimeRangeUnit (i.e. Month) can't be + // converted to a TimeSpan without some convention. + return null; + } + } +} \ No newline at end of file diff --git a/tmp/Grib2/Templates/TemplateContent.cs b/tmp/Grib2/Templates/TemplateContent.cs new file mode 100644 index 0000000..8043127 --- /dev/null +++ b/tmp/Grib2/Templates/TemplateContent.cs @@ -0,0 +1,36 @@ +/* + * This file is part of NGrib. + * + * Copyright © 2020 Nicolas Mangué + * + * NGrib is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * NGrib is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with NGrib. If not, see . + */ + +namespace NGrib.Grib2.Templates; + +public abstract class TemplateContent +{ + protected TemplateContent() + { + } +} + +#pragma warning disable S2326 // Unused type parameters should be removed +public class TemplateContent : TemplateContent +#pragma warning restore S2326 // Unused type parameters should be removed +{ + internal TemplateContent() : base() + { + } +} \ No newline at end of file diff --git a/tmp/Grib2/Templates/TemplateFactory.cs b/tmp/Grib2/Templates/TemplateFactory.cs new file mode 100644 index 0000000..b68c196 --- /dev/null +++ b/tmp/Grib2/Templates/TemplateFactory.cs @@ -0,0 +1,69 @@ +/* + * This file is part of NGrib. + * + * Copyright © 2020 Nicolas Mangué + * + * NGrib is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * NGrib is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with NGrib. If not, see . + */ + +using System.Collections; + +namespace NGrib.Grib2.Templates; + +internal class TemplateFactory : IEnumerable>> +{ + /// + /// Methods available to build T from a templateNumber. + /// + /// + /// We use Stack instead of List (or even Dictionary) to provide an easy way to override or extend + /// the default factories. + /// + private readonly Dictionary> factories; + + public TemplateFactory() + { + factories = new Dictionary>(); + } + + /// + /// Add a new factory method. + /// + internal void Add(int templateNumber, Func factoryMethod) + { + if (factoryMethod == null) throw new ArgumentNullException(nameof(factoryMethod)); + + factories[templateNumber] = (reader, objects) => factoryMethod(reader); + } + + /// + /// Add a new factory method. + /// + internal void Add(int templateNumber, Func factoryMethod) + { + factories[templateNumber] = factoryMethod ?? throw new ArgumentNullException(nameof(factoryMethod)); + } + + internal T Build(BufferedBinaryReader reader, int templateNumber, params object[] args) + { + return factories.TryGetValue(templateNumber, out var factory) + ? factory(reader, args) + : default; + } + + public IEnumerator>> GetEnumerator() => + factories.GetEnumerator(); + + IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); +} \ No newline at end of file diff --git a/tmp/Grib2Reader.cs b/tmp/Grib2Reader.cs new file mode 100644 index 0000000..20f5558 --- /dev/null +++ b/tmp/Grib2Reader.cs @@ -0,0 +1,107 @@ +/* + * This file is part of NGrib. + * + * Copyright © 2020 Nicolas Mangué + * + * Copyright 2006-2010 Seaware AB, PO Box 1244, SE-131 28 + * Nacka Strand, Sweden, info@seaware.se. + * + * Copyright 1997-2006 Unidata Program Center/University + * Corporation for Atmospheric Research, P.O. Box 3000, Boulder, CO 80307, + * support@unidata.ucar.edu. + * + * NGrib is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * NGrib is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with NGrib. If not, see . + */ + +using NGrib.Grib2; +using NGrib.Grib2.Sections; + +namespace NGrib; + +/// +/// Reads GRIB 2 data format. +/// +public class Grib2Reader : IDisposable +{ + private readonly BufferedBinaryReader reader; + private readonly Grib2File _grib2File = new(); + + /// + /// Initializes a new instance of the Grib2Reader class + /// based on the specified file. + /// + /// The GRIB 2 file path. + public Grib2Reader(string filePath, int bufferSize = 4096) : this(File.OpenRead(filePath), false, bufferSize) + { } + + /// + /// Initializes a new instance of the Grib2Reader class + /// based on the specified stream. + /// + /// The GRIB 2 input stream. + /// trueto leave the stream open after the object is disposed; otherwise, false. + public Grib2Reader(Stream input, bool leaveOpen = false, int bufferSize = 4096) + { + if (input == null) throw new ArgumentNullException(nameof(input)); + if (!input.CanRead) throw new ArgumentException("The stream must support reading.", nameof(input)); + if (!input.CanSeek) throw new ArgumentException("The stream must support seeking.", nameof(input)); + + reader = new BufferedBinaryReader(input, leaveOpen, bufferSize); + } + + /// + /// Enumerates the messages in the underlying stream. + /// + /// The messages in the GRIB 2 stream. + public IEnumerable ReadMessages() + { + reader.Seek(0, SeekOrigin.Begin); + + do + { + var message = _grib2File.ReadGrib2Message(reader, out var currentPosition); + yield return message; + reader.Seek(currentPosition, SeekOrigin.Begin); + + } while (!reader.HasReachedStreamEnd && reader.PeekSection().Is(SectionCode.IndicatorSection)); + } + + /// + /// Enumerates every data sets for each messages in the underlying GRIB 2 stream. + /// + /// Enumeration of every data sets in the underlying GRIB 2 stream. + public IEnumerable ReadAllDataSets() => ReadMessages().SelectMany(m => m.DataSets); + + /// + /// Read the data set floating point values. + /// + /// The data set to read. + /// The data set point values. + public IEnumerable ReadDataSetRawData(DataSet dataSet) => dataSet.GetRawData(reader); + + /// + /// Read the data set grid value. + /// + /// The data set to read. + /// The data set grid points and the corresponding values. + public IEnumerable> ReadDataSetValues(DataSet dataSet) => dataSet.GetData(reader); + + /// + /// Releases the resources used by the . + /// + public void Dispose() + { + reader?.Dispose(); + } +} \ No newline at end of file diff --git a/tmp/GribReader.cs b/tmp/GribReader.cs new file mode 100644 index 0000000..cdd43ab --- /dev/null +++ b/tmp/GribReader.cs @@ -0,0 +1,38 @@ +using NGrib.Common; + +namespace NGrib; + +public class GribReader:IDisposable +{ + private readonly Stream _stream; + private readonly bool _leaveOpen; + private readonly CommonGribFile _common = new(); + public GribReader(Stream stream, bool leaveOpen = false) + { + _stream = stream; + _leaveOpen = leaveOpen; + } + + public IEnumerable GetMessages() + { + var position = _stream.Position; + + while(true) + { + var message = _common.GetMessage(_stream); + if (message ==null) + break; + var positionInner = _stream.Position; + yield return message; + _stream.Seek(positionInner, SeekOrigin.Begin); + }; + + _stream.Position = position; + } + + public void Dispose() + { + if (!_leaveOpen) + _stream?.Dispose(); + } +} \ No newline at end of file diff --git a/tmp/Helpers/ScanMode.cs b/tmp/Helpers/ScanMode.cs new file mode 100644 index 0000000..0c50171 --- /dev/null +++ b/tmp/Helpers/ScanMode.cs @@ -0,0 +1,28 @@ +namespace NGrib.Helpers; +/// +/// Adopted from JGribX +/// +public class ScanMode +{ + public bool IsXIncrement { get; set; } + + public bool IsYIncrement { get; set; } + + public bool IsNortherly { get; set; } + + public bool RowsZigzag { get; set; } + + public bool IsXDirectionEvenOffset { get; set; } + + public bool IsXDirectionOddRowsOffset { get; set; } + + public bool IsYDirectionOffset { get; set; } + + public bool RowsNxNyPoints { get; set; } + public ScanMode(int formatCode) + { + IsXIncrement = formatCode.GetBit(3); + IsYIncrement = formatCode.GetBit(4); + IsNortherly = formatCode.GetBit(5); + } +} \ No newline at end of file diff --git a/tmp/NGrib.csproj b/tmp/NGrib.csproj new file mode 100644 index 0000000..70e3ea9 --- /dev/null +++ b/tmp/NGrib.csproj @@ -0,0 +1,39 @@ + + + + net6.0 + latest + true + 0.8.0 + Nicolas Mangué + + NGrib is a .NET Standard library to read GRIB (GRid in Binary) files. GRIB is a gridded data standard from WMO (World Meteorological Organisation) and is used by many meteorological organisation. + Copyright ©2021 + LGPL-3.0-or-later + https://github.com/nmangue/NGrib + https://github.com/nmangue/NGrib.git + git + Add support for Data Representation Template 5.50002 + 0.8.0.0 + 0.8.0.0 + + + + true + snupkg + disable + enable + + + + + + + + + + + + + + diff --git a/tmp/Properties/AssemblyInfo.cs b/tmp/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..77a72a5 --- /dev/null +++ b/tmp/Properties/AssemblyInfo.cs @@ -0,0 +1,3 @@ +using System.Runtime.CompilerServices; + +[assembly: InternalsVisibleTo("NGrib.Tests")] \ No newline at end of file diff --git a/tmp/UnexpectedGribSectionException.cs b/tmp/UnexpectedGribSectionException.cs new file mode 100644 index 0000000..02035c4 --- /dev/null +++ b/tmp/UnexpectedGribSectionException.cs @@ -0,0 +1,39 @@ +/* + * This file is part of NGrib. + * + * Copyright 2020 Nicolas Mangu + * + * NGrib is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * NGrib is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with NGrib. If not, see . + */ + +using NGrib.Grib2.Sections; + +namespace NGrib; + +/// +/// The exception that is thrown when the read section number is not +/// the expected one. +/// +public class UnexpectedGribSectionException : BadGribFormatException +{ + /// + /// Initializes a new instance of the class. + /// + /// The expected section code. + /// The section code actually read. + public UnexpectedGribSectionException(SectionCode expectedSectionCode, int readSectionCode) + : base($"Expected section {expectedSectionCode} but found {readSectionCode}") + { + } +} \ No newline at end of file