gistools/readers/grib2/sections/_5/
templates.rs

1use crate::{
2    parsers::Reader,
3    readers::{
4        Grib2Table5_1, Grib2Table5_4, Grib2Table5_5, Grib2Table5_6, Grib2Table5_7, Grib2Table5_40,
5    },
6};
7
8/// Returns a template generator for the given template number
9#[derive(Debug, Clone, PartialEq)]
10pub enum Grib2Template5 {
11    /// Data Representation Template 5.0 - Grid point data - simple packing
12    Grib2Template50(Grib2Template50),
13    /// Data Representation Template 5.2 – Complex packing (no spatial differencing).
14    Grib2Template52(Grib2Template52),
15    /// Data Representation Template 5.3 – Complex packing and spatial differencing.
16    Grib2Template53(Grib2Template53),
17    /// Data Representation Template 5.40
18    Grib2Template540(Grib2Template540),
19    /// Data Representation Template 5.50 - Spectral data - simple packing
20    Grib2Template550(Grib2Template550),
21    /// Data Representation Template 5.51 - Spectral data - complex packing
22    Grib2Template551(Grib2Template551),
23}
24impl Grib2Template5 {
25    /// Creates a new instance of Grib2Template50
26    ///
27    /// ## Parameters
28    /// - `template`: Template number
29    ///
30    /// ## Returns
31    /// Template generator
32    pub fn new<T: Reader>(section: &T, template: u8) -> Self {
33        match template {
34            0 => Grib2Template5::Grib2Template50(Grib2Template50::new(section)),
35            2 => Grib2Template5::Grib2Template52(Grib2Template52::new(section)),
36            3 => Grib2Template5::Grib2Template53(Grib2Template53::new(section)),
37            40 => Grib2Template5::Grib2Template540(Grib2Template540::new(section)),
38            50 => Grib2Template5::Grib2Template550(Grib2Template550::new(section)),
39            51 => Grib2Template5::Grib2Template551(Grib2Template551::new(section)),
40            _ => panic!("Template 5.{template} not defined"),
41        }
42    }
43    /// Get the simple packing template
44    pub fn get_simple_packing_template(&self) -> Option<&Grib2Template50> {
45        match self {
46            Grib2Template5::Grib2Template50(template) => Some(template),
47            _ => None,
48        }
49    }
50}
51
52/// # Data Representation Template 5.0 - Grid point data - simple packing
53///
54/// [Read more...](https://www.nco.ncep.noaa.gov/pmb/docs/grib2/grib2_doc/grib2_temp5-0.shtml)
55///
56/// ## Notes
57/// - Negative values of E or D shall be represented according to Regulation [92.1.5](https://codes.ecmwf.int/grib/format/grib2/regulations/).
58///
59/// ## Returns
60/// Description of how to decode simple unpacked data
61#[derive(Debug, Clone, PartialEq)]
62pub struct Grib2Template50 {
63    /// Reference value (R) (IEEE 32-bit floating-point value)
64    pub reference_value: f32,
65    /// Binary scale factor (E)
66    pub binary_scale_factor: i32,
67    /// Decimal scale factor (D)
68    pub decimal_scale_factor: i32,
69    /// Number of bits used for each packed value for simple packing, or for each group reference value for complex packing or spatial differencing
70    pub number_of_bits: u8,
71    /// Type of original field values (see Code [Table 5.1](https://www.nco.ncep.noaa.gov/pmb/docs/grib2/grib2_doc/grib2_table5-1.shtml))
72    pub original_type: Grib2Table5_1,
73}
74impl Grib2Template50 {
75    /// Creates a new instance of Grib2Template50
76    pub fn new<T: Reader>(section: &T) -> Self {
77        let original_type = section.uint8(Some(20));
78        let mut binary_scale_factor = (section.uint16_be(Some(15)) & 0x7fff) as i32;
79        if section.uint16_be(Some(15)) >> 15 > 0 {
80            binary_scale_factor *= -1;
81        }
82        let mut decimal_scale_factor = (section.uint16_be(Some(17)) & 0x7fff) as i32;
83        if section.uint16_be(Some(17)) >> 15 > 0 {
84            decimal_scale_factor *= -1;
85        }
86
87        Self {
88            reference_value: section.f32_be(Some(11)),
89            binary_scale_factor,
90            decimal_scale_factor,
91            number_of_bits: section.uint8(Some(19)),
92            original_type: original_type.into(),
93        }
94    }
95}
96
97/// # Data Representation Template 5.2 – Complex packing (no spatial differencing).
98///
99/// Reads and parses the metadata fields defined by GRIB2 Template 5.2.
100/// For most templates, details of the packing process are described in Regulation 92.9.4.
101///
102/// See also:
103/// - [Template 5.2 documentation](https://www.nco.ncep.noaa.gov/pmb/docs/grib2/grib2_doc/grib2_temp5-2.shtml)
104/// - [Data template 7.2 for complementary info](https://www.nco.ncep.noaa.gov/pmb/docs/grib2/grib2_doc/grib2_temp7-2.shtml)
105#[derive(Debug, Clone, PartialEq)]
106pub struct Grib2Template52 {
107    /// Reference value (R) (IEEE 32-bit floating-point). Octets 12–15 in the GRIB2 documentation.
108    pub reference_value: f32,
109    /// Binary scale factor (E). Octets 16–17.
110    pub binary_scale_factor: i32,
111    /// Decimal scale factor (D). Octets 18–19.
112    pub decimal_scale_factor: i32,
113    /// Number of bits per packed value for simple packing, or per group reference for
114    /// complex packing. Octet 20 in the documentation.
115    pub number_of_bits: u8,
116    /// Type of original field values. See Code Table 5.1. Octet 21.
117    pub original_type: Grib2Table5_1,
118
119    // Fields specific to complex packing (no spatial differencing):
120    /// Group splitting method used. See Code Table 5.4. Octet 22.
121    pub group_splitting_method: Grib2Table5_4,
122    /// Missing value management. See Code Table 5.5. Octet 23.
123    pub missing_value_management: Grib2Table5_5,
124    /// Primary missing value substitute. Octets 24–27.
125    pub primary_missing_value_substitute: u32,
126    /// Secondary missing value substitute. Octets 28–31.
127    pub secondary_missing_value_substitute: u32,
128    /// Number of groups of data values (NG). Octets 32–35.
129    pub number_of_groups: u32,
130    /// Reference for group widths. Octet 36.
131    /// The group width is the number of bits used for every value in a group.
132    pub reference_for_group_widths: u8,
133    /// Number of bits used for the group widths (after subtracting the reference value). Octet 37.
134    pub group_widths_bits: u8,
135    /// Reference for group lengths. Octets 38–41.
136    /// The group length (L) is the number of values in a group.
137    pub reference_for_group_lengths: u32,
138    /// Length increment for group lengths. Octet 42.
139    /// Used in the formula: Lₙ = ref + Kₙ × len_inc.
140    pub group_length_factor: u8,
141    /// True length of the last group. Octets 43–46.
142    /// A special-case group length if the sequence doesn’t fit the formula.
143    pub true_length_of_last_group: u32,
144    /// Number of bits used for scaled group lengths (after subtracting ref
145    /// and dividing by the length increment). Octet 47.
146    pub n_bits_group_length: u8,
147}
148impl Grib2Template52 {
149    /// Creates a new instance of Grib2Template52
150    ///
151    /// ## Parameters
152    /// - `section`: Binary reader providing access to the section data.
153    ///
154    /// ## Returns
155    /// Object containing the fields of Template 5.2.
156    pub fn new<T: Reader>(section: &T) -> Self {
157        // Binary and decimal scale factors can be negative.
158        // They are stored with the sign bit in the high-order bit (bit 15).
159        let original_type_code = section.uint8(Some(20));
160
161        let mut binary_scale_factor = (section.uint16_be(Some(15)) & 0x7fff) as i32;
162        if section.uint16_be(Some(15)) >> 15 > 0 {
163            binary_scale_factor *= -1;
164        }
165        let mut decimal_scale_factor = (section.uint16_be(Some(17)) & 0x7fff) as i32;
166        if section.uint16_be(Some(17)) >> 15 > 0 {
167            decimal_scale_factor *= -1;
168        }
169        // Fields unique to 5.2 (similar to 5.3, but no spatial differencing):
170        let group_splitting_method_code = section.uint8(Some(21)); // Octet 22
171        let missing_value_management_code = section.uint8(Some(22)); // Octet 23
172        let primary_missing_value_substitute = section.uint32_be(Some(23)); // Octets 24–27
173        let secondary_missing_value_substitute = section.uint32_be(Some(27)); // Octets 28–31
174        let number_of_groups = section.uint32_be(Some(31)); // Octets 32–35
175        let reference_for_group_widths = section.uint8(Some(35)); // Octet 36
176        let group_widths_bits = section.uint8(Some(36)); // Octet 37
177        let reference_for_group_lengths = section.uint32_be(Some(37)); // Octets 38–41
178        let group_length_factor = section.uint8(Some(41)); // Octet 42
179        let true_length_of_last_group = section.uint32_be(Some(42)); // Octets 43–46
180        let n_bits_group_length = section.uint8(Some(46)); // Octet 47
181
182        Self {
183            reference_value: section.f32_be(Some(11)),
184            binary_scale_factor,
185            decimal_scale_factor,
186            number_of_bits: section.uint8(Some(19)),
187            original_type: original_type_code.into(),
188            group_splitting_method: group_splitting_method_code.into(),
189            missing_value_management: missing_value_management_code.into(),
190            primary_missing_value_substitute,
191            secondary_missing_value_substitute,
192            number_of_groups,
193            reference_for_group_widths,
194            group_widths_bits,
195            reference_for_group_lengths,
196            group_length_factor,
197            true_length_of_last_group,
198            n_bits_group_length,
199        }
200    }
201}
202
203/// # Data Representation Template 5.3 – Complex packing and spatial differencing.
204///
205/// Reads and parses the metadata fields defined by GRIB2 Template 5.3.
206/// For most templates, details of the packing process are described in Regulation 92.9.4.
207///
208/// See also:
209/// - [GRIB2 Template 5.3 documentation](https://www.nco.ncep.noaa.gov/pmb/docs/grib2/grib2_doc/grib2_temp5-3.shtml)
210/// - [Data template 7.3 and associated notes](https://www.nco.ncep.noaa.gov/pmb/docs/grib2/grib2_doc/grib2_temp7-3.shtml)
211/// - Spatial differencing (Regulation 92.9.4).
212#[derive(Debug, Clone, PartialEq)]
213pub struct Grib2Template53 {
214    /// Reference value (R) (IEEE 32-bit floating-point).
215    /// Octets 12–15 in the GRIB2 documentation.
216    pub reference_value: f32,
217    /// Binary scale factor (E). Octets 16–17.
218    pub binary_scale_factor: i32,
219    /// Decimal scale factor (D). Octets 18–19.
220    pub decimal_scale_factor: i32,
221    /// Number of bits per packed value for simple packing,
222    /// or per group reference for complex packing.
223    /// Octet 20 in the documentation.
224    pub number_of_bits: u8,
225    /// Type of original field values. See Code Table 5.1. Octet 21.
226    pub original_type: Grib2Table5_1,
227
228    // Fields specific to complex packing and spatial differencing:
229    /// Group splitting method used. See Code Table 5.4. Octet 22.
230    pub group_splitting_method: Grib2Table5_4,
231    /// Missing value management. See Code Table 5.5. Octet 23.
232    pub missing_value_management: Grib2Table5_5,
233    /// Primary missing value substitute. Octets 24–27.
234    pub primary_missing_value_substitute: u32,
235    /// Secondary missing value substitute. Octets 28–31.
236    pub secondary_missing_value_substitute: u32,
237    /// Number of groups of data values (NG). Octets 32–35.
238    pub number_of_groups: u32,
239    /// Reference for group widths. Octet 36.
240    /// The group width is the number of bits used for every value in a group.
241    pub reference_for_group_widths: u8,
242    /// Number of bits used for the group widths (after subtracting the reference value).
243    /// Octet 37.
244    pub group_widths_bits: u8,
245    /// Reference for group lengths. Octets 38–41.
246    /// The group length (L) is the number of values in a group.
247    pub reference_for_group_lengths: u32,
248    /// Length increment for group lengths. Octet 42.
249    /// Used in the formula: Lₙ = ref + Kₙ × len_inc.
250    pub group_length_factor: u8,
251    /// True length of the last group. Octets 43–46.
252    /// A special-case group length if the sequence doesn’t fit the formula.
253    pub true_length_of_last_group: u32,
254    /// Number of bits used for scaled group lengths (after subtracting ref
255    /// and dividing by the length increment). Octet 47.
256    pub n_bits_group_length: u8,
257    /// Order of spatial difference. See Code Table 5.6. Octet 48.
258    pub order_of_spatial_difference: Grib2Table5_6,
259    /// Number of extra descriptor octets needed for spatial differencing
260    /// (octets 6–ww in data template 7.3). Octet 49.
261    pub extra_descriptor_octets: u8,
262}
263impl Grib2Template53 {
264    /// Create a new instance of Grib2Template53
265    ///
266    /// ## Parameters
267    /// - `section`: Binary reader providing access to the section data
268    ///
269    /// ## Returns
270    /// Object containing the fields of Template 5.3
271    pub fn new<T: Reader>(section: &T) -> Self {
272        // Binary and decimal scale factors can be negative.
273        // They are stored with the sign bit in the high-order bit (bit 15).
274        let original_type_code = section.uint8(Some(20));
275        let mut binary_scale_factor = (section.uint16_be(Some(15)) & 0x7fff) as i32;
276        if section.uint16_be(Some(15)) >> 15 > 0 {
277            binary_scale_factor *= -1;
278        }
279        let mut decimal_scale_factor = (section.uint16_be(Some(17)) & 0x7fff) as i32;
280        if section.uint16_be(Some(17)) >> 15 > 0 {
281            decimal_scale_factor *= -1;
282        }
283        // New fields introduced by Template 5.3
284        let group_splitting_method_code = section.uint8(Some(21));
285        let missing_value_management_code = section.uint8(Some(22));
286        let primary_missing_value_substitute = section.uint32_be(Some(23));
287        let secondary_missing_value_substitute = section.uint32_be(Some(27));
288        let number_of_groups = section.uint32_be(Some(31));
289        let reference_for_group_widths = section.uint8(Some(35));
290        let group_widths_bits = section.uint8(Some(36));
291        let reference_for_group_lengths = section.uint32_be(Some(37));
292        let group_length_factor = section.uint8(Some(41));
293        let true_length_of_last_group = section.uint32_be(Some(42));
294        let n_bits_group_length = section.uint8(Some(46));
295        let order_of_spatial_difference_code = section.uint8(Some(47));
296        let extra_descriptor_octets = section.uint8(Some(48));
297
298        Self {
299            reference_value: section.f32_be(Some(11)),
300            binary_scale_factor,
301            decimal_scale_factor,
302            number_of_bits: section.uint8(Some(19)),
303            original_type: original_type_code.into(),
304            group_splitting_method: group_splitting_method_code.into(),
305            missing_value_management: missing_value_management_code.into(),
306            primary_missing_value_substitute,
307            secondary_missing_value_substitute,
308            number_of_groups,
309            reference_for_group_widths,
310            group_widths_bits,
311            reference_for_group_lengths,
312            group_length_factor,
313            true_length_of_last_group,
314            n_bits_group_length,
315            order_of_spatial_difference: order_of_spatial_difference_code.into(),
316            extra_descriptor_octets,
317        }
318    }
319}
320
321/// Data Representation Template 5.40
322///  
323/// [Read more...](https://www.nco.ncep.noaa.gov/pmb/docs/grib2/grib2_doc/grib2_temp5-40.shtml)
324#[derive(Debug, Clone, PartialEq)]
325pub struct Grib2Template540 {
326    /// Reference value (R) (IEEE 32-bit floating-point value) */
327    pub reference_value: f32,
328    /// Binary scale factor (E) */
329    pub binary_scale_factor: i16,
330    /// Decimal scale factor (D) */
331    pub decimal_scale_factor: i16,
332    /// Number of bits used for each packed value for simple packing, or for each group reference value for complex packing or spatial differencing */
333    pub number_of_bits: u8,
334    /// Type of original field values (see Code [Table 5.1](https://www.nco.ncep.noaa.gov/pmb/docs/grib2/grib2_doc/grib2_table5-1.shtml)) */
335    pub original_type: Grib2Table5_1,
336    /// Type of Compression used. (see [Code Table 5.40](https://www.nco.ncep.noaa.gov/pmb/docs/grib2/grib2_doc/grib2_table5-40.shtml)) */
337    pub compression_type: Grib2Table5_40,
338    /// Target compression ratio, M:1 (with respect to the bit-depth specified in octet 20),
339    /// when octet 22 indicates Lossy Compression. Otherwise, set to missing.
340    pub compression_ratio: u8,
341}
342impl Grib2Template540 {
343    /// Create a new instance of Grib2Template540
344    ///
345    /// ## Parameters
346    /// - `section`: The raw section data to parse
347    ///
348    /// ## Returns
349    /// Parsed Data Representation Information
350    pub fn new<T: Reader>(section: &T) -> Self {
351        let original_type_code = section.uint8(Some(20));
352        let compression_type = section.uint8(Some(21));
353        Self {
354            reference_value: section.f32_be(Some(11)),
355            binary_scale_factor: section.int16_be(Some(15)),
356            decimal_scale_factor: section.int16_be(Some(17)),
357            number_of_bits: section.uint8(Some(19)),
358            original_type: original_type_code.into(),
359            compression_type: compression_type.into(),
360            compression_ratio: section.uint8(Some(22)),
361        }
362    }
363}
364// export function grib2Template540(section: Reader) {
365// }
366
367/// # Data Representation Template 5.50 - Spectral data - simple packing
368///
369/// [Read more...](https://www.nco.ncep.noaa.gov/pmb/docs/grib2/grib2_doc/grib2_temp5-50.shtml)
370///
371/// ## Notes
372/// - Removal of the real part of (0.0) coefficient from packed data is intended to reduce the
373///   variability of the coefficients, in order to improve packing accuracy.
374/// - For some spectral representations, the (0.0) coefficient represents the mean value of the
375///   parameter represented.
376/// - Negative values of E or D shall be represented according to Regulation [92.1.5](https://codes.ecmwf.int/grib/format/grib2/regulations/).
377///
378/// ## Returns
379/// Description of how to decode simple unpacked data
380#[derive(Debug, Clone, PartialEq)]
381pub struct Grib2Template550 {
382    /// Reference value (R) (IEEE 32-bit floating-point value)
383    pub reference_value: f32,
384    /// Binary scale factor (E)
385    pub binary_scale_factor: i32,
386    /// Decimal scale factor (D)
387    pub decimal_scale_factor: i32,
388    /// Number of bits used for each packed value for simple packing, or for each group reference value for complex packing or spatial differencing
389    pub number_of_bits: u8,
390    /// Type of original field values (see Code [Table 5.1](https://www.nco.ncep.noaa.gov/pmb/docs/grib2/grib2_doc/grib2_table5-1.shtml))
391    pub real_part_coefficient_type: f32,
392}
393impl Grib2Template550 {
394    /// Create a new instance of Grib2Template540
395    pub fn new<T: Reader>(section: &T) -> Self {
396        let mut binary_scale_factor = (section.uint16_be(Some(15)) & 0x7fff) as i32;
397        if section.uint16_be(Some(15)) >> 15 > 0 {
398            binary_scale_factor *= -1;
399        }
400        let mut decimal_scale_factor = (section.uint16_be(Some(17)) & 0x7fff) as i32;
401        if section.uint16_be(Some(17)) >> 15 > 0 {
402            decimal_scale_factor *= -1;
403        }
404
405        Self {
406            reference_value: section.f32_be(Some(11)),
407            binary_scale_factor,
408            decimal_scale_factor,
409            number_of_bits: section.uint8(Some(19)),
410            real_part_coefficient_type: section.f32_be(Some(20)),
411        }
412    }
413}
414
415/// # Data Representation Template 5.51 - Spectral data - complex packing
416///
417/// [Read more...](https://www.nco.ncep.noaa.gov/pmb/docs/grib2/grib2_doc/grib2_temp5-51.shtml)
418///
419/// ## Notes
420/// - The unpacked subset is a set of values defined in the same way as the full set of values
421///   (on a spectrum limited to j_s, k_s and m_s ), but on which scaling and packing are not applied.
422///   Associated values are stored in octets 6 onwards of section 7.
423/// - The remaining coefficients are multiplied by `(n x (n+1))p` , scaled and packed. The operator
424///   associated with this multiplication is derived from the Laplacian operator on the sphere.
425/// - The retrieval formula for a coefficient of wave number n is then: `Y = (R+X x 2e ) x 10-d x (n x(n+1))-p`
426///   where X is the packed scaled value associated with the coefficient.
427///
428/// ## Returns
429/// Description of how to decode simple unpacked data
430#[derive(Debug, Clone, PartialEq)]
431pub struct Grib2Template551 {
432    /// Reference value (R) (IEEE 32-bit floating-point value)
433    pub reference_value: f32,
434    /// Binary scale factor (E)
435    pub binary_scale_factor: i32,
436    /// Decimal scale factor (D)
437    pub decimal_scale_factor: i32,
438    /// Number of bits used for each packed value for simple packing, or for each group reference value for complex packing or spatial differencing
439    pub number_of_bits: u8,
440    /// P ― Laplacian scaling factor (expressed in 10^-6 units)
441    pub p: f32,
442    /// j_s ― pentagonal resolution parameter of the unpacked subset (see Note1)
443    pub j_s: i16,
444    /// k_s ― pentagonal resolution parameter of the unpacked subset (see Note1)
445    pub k_s: i16,
446    /// m_s ― pentagonal resolution parameter of the unpacked subset (see Note1)
447    pub m_s: i16,
448    /// t_s ― total number of values in the unpacked subset (see Note1)
449    pub t_s: i32,
450    /// Precision of the unpacked subset (see Code Table 5.7)
451    pub precision: Grib2Table5_7,
452}
453impl Grib2Template551 {
454    /// Create a new instance of Grib2Template540
455    pub fn new<T: Reader>(section: &T) -> Self {
456        let mut binary_scale_factor = (section.uint16_be(Some(15)) & 0x7fff) as i32;
457        if section.uint16_be(Some(15)) >> 15 > 0 {
458            binary_scale_factor *= -1;
459        }
460        let mut decimal_scale_factor = (section.uint16_be(Some(17)) & 0x7fff) as i32;
461        if section.uint16_be(Some(17)) >> 15 > 0 {
462            decimal_scale_factor *= -1;
463        }
464        let precision_code = section.uint8(Some(34));
465
466        Self {
467            reference_value: section.f32_be(Some(11)),
468            binary_scale_factor,
469            decimal_scale_factor,
470            number_of_bits: section.uint8(Some(19)),
471            p: section.f32_be(Some(20)),
472            j_s: section.int16_be(Some(24)),
473            k_s: section.int16_be(Some(26)),
474            m_s: section.int16_be(Some(28)),
475            t_s: section.int32_be(Some(30)),
476            precision: precision_code.into(),
477        }
478    }
479}