Skip to main content

nexrad_decode/messages/volume_coverage_pattern/
header.rs

1use serde::Deserialize;
2use std::fmt::Debug;
3
4use crate::messages::primitive_aliases::{Code1, Code2, Integer1, Integer2, Integer4};
5use crate::messages::volume_coverage_pattern::definitions::*;
6
7#[cfg(feature = "uom")]
8use uom::si::{f64::Velocity, velocity::meter_per_second};
9
10/// The volume coverage pattern header block
11#[derive(Clone, PartialEq, Deserialize)]
12pub struct Header {
13    /// Total message size in halfwords, including the header and all elevation blocks
14    pub message_size: Integer2,
15
16    /// Pattern type is always 2
17    pub pattern_type: Code2,
18
19    /// Volume Coverage Pattern Number
20    pub pattern_number: Integer2,
21
22    /// Number of elevation cuts in the complete volume scan
23    pub number_of_elevation_cuts: Integer2,
24
25    /// Volume Coverage Pattern Version Number
26    pub version: Integer1,
27
28    /// Clutter map groups are not currently implemented
29    pub clutter_map_group_number: Integer1,
30
31    /// Doppler velocity resolution.
32    /// 2 -> 0.5
33    /// 4 -> 1.0
34    pub doppler_velocity_resolution: Code1,
35
36    /// Pulse width values.
37    /// 2 -> Short
38    /// 4 -> Long
39    pub pulse_width: Code1,
40
41    /// Reserved
42    pub reserved_1: Integer4,
43
44    /// VCP sequencing values.
45    /// Bits 0-4: Number of Elevations
46    /// Bits 5-6: Maximum SAILS Cuts
47    /// Bit  13:  Sequence Active
48    /// Bit  14:  Truncated VCP
49    pub vcp_sequencing: Code2,
50
51    /// VCP supplemental data.
52    /// Bit  0:     SAILS VCP
53    /// Bits 1-3:   Number SAILS Cuts
54    /// Bit  4:     MRLE VCP
55    /// Bits 5-7:   Number MRLE Cuts
56    /// Bits 8-10:  Spare
57    /// Bit  11:    MPDA VCP
58    /// Bit  12:    BASE TILT VCP
59    /// Bits 13-15: Number of BASE TILTS
60    pub vcp_supplemental_data: Code2,
61
62    /// Reserved
63    pub reserved_2: Integer2,
64}
65
66impl Header {
67    /// The pattern type of the volume coverage pattern
68    pub fn pattern_type(&self) -> PatternType {
69        match self.pattern_type {
70            2 => PatternType::Constant,
71            _ => PatternType::Unknown,
72        }
73    }
74
75    /// The doppler velocity resolution of this coverage pattern
76    #[cfg(feature = "uom")]
77    pub fn doppler_velocity_resolution(&self) -> Option<Velocity> {
78        match self.doppler_velocity_resolution {
79            2 => Some(Velocity::new::<meter_per_second>(0.5)),
80            4 => Some(Velocity::new::<meter_per_second>(1.0)),
81            _ => None,
82        }
83    }
84
85    /// The doppler velocity resolution of this coverage pattern in m/s
86    pub fn doppler_velocity_resolution_meters_per_second(&self) -> Option<f64> {
87        match self.doppler_velocity_resolution {
88            2 => Some(0.5),
89            4 => Some(1.0),
90            _ => None,
91        }
92    }
93
94    /// The pulse width for this VCP
95    pub fn pulse_width(&self) -> PulseWidth {
96        match self.pulse_width {
97            2 => PulseWidth::Short,
98            4 => PulseWidth::Long,
99            _ => PulseWidth::Unknown,
100        }
101    }
102
103    /// The number of elevations in the VCP
104    pub fn vcp_sequencing_number_of_elevations(&self) -> u8 {
105        (self.vcp_sequencing & 0x001F) as u8
106    }
107
108    /// The maximum number of SAILS cuts allowed in this VCP
109    pub fn vcp_sequencing_maximum_sails_cuts(&self) -> u8 {
110        ((self.vcp_sequencing & 0x0060) >> 5) as u8
111    }
112
113    /// Whether this VCP is a part of an active VCP sequence
114    pub fn vcp_sequencing_sequence_active(&self) -> bool {
115        ((self.vcp_sequencing & 0x2000) >> 13) == 1
116    }
117
118    /// Whether this VCP is truncated
119    pub fn vcp_sequencing_truncated_vcp(&self) -> bool {
120        ((self.vcp_sequencing & 0x4000) >> 14) == 1
121    }
122
123    /// Whether this VCP uses SAILS cuts
124    pub fn vcp_supplemental_data_sails_vcp(&self) -> bool {
125        (self.vcp_supplemental_data & 0x0001) == 1
126    }
127
128    /// The number of SAILS cuts used by this VCP
129    pub fn vcp_supplemental_data_number_sails_cuts(&self) -> u8 {
130        ((self.vcp_supplemental_data & 0x000E) >> 1) as u8
131    }
132
133    /// Whether this VCP uses MRLE cuts
134    pub fn vcp_supplemental_data_mrle_vcp(&self) -> bool {
135        ((self.vcp_supplemental_data & 0x0010) >> 4) == 1
136    }
137
138    /// The number of MRLE cuts used by this VCP
139    pub fn vcp_supplemental_data_number_mrle_cuts(&self) -> u8 {
140        ((self.vcp_supplemental_data & 0x00E0) >> 5) as u8
141    }
142
143    /// Whether this VCP is a Multi-PRF Dealiasing Algorithm (MPDA) VCP
144    pub fn vcp_supplemental_data_mpda_vcp(&self) -> bool {
145        ((self.vcp_supplemental_data & 0x0800) >> 11) == 1
146    }
147
148    /// Whether this VCP contains BASE TILTS
149    pub fn vcp_supplemental_data_base_tilt_vcp(&self) -> bool {
150        ((self.vcp_supplemental_data & 0x1000) >> 12) == 1
151    }
152
153    /// The number of BASE TILTS in this VCP
154    pub fn vcp_supplemental_data_base_tilts(&self) -> u8 {
155        ((self.vcp_supplemental_data & 0xE000) >> 13) as u8
156    }
157}
158
159impl Debug for Header {
160    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
161        let mut debug = f.debug_struct("Header");
162
163        debug.field("message_size", &self.message_size);
164        debug.field("pattern_type", &self.pattern_type());
165        debug.field("pattern_number", &self.pattern_number);
166        debug.field("number_of_elevation_cuts", &self.number_of_elevation_cuts);
167        debug.field("version", &self.version);
168        debug.field("clutter_map_group_number", &self.clutter_map_group_number);
169
170        #[cfg(feature = "uom")]
171        debug.field(
172            "doppler_velocity_resolution",
173            &self.doppler_velocity_resolution(),
174        );
175        #[cfg(not(feature = "uom"))]
176        debug.field(
177            "doppler_velocity_resolution",
178            &self.doppler_velocity_resolution_meters_per_second(),
179        );
180
181        debug.field("pulse_width", &self.pulse_width());
182        debug.field("reserved_1", &self.reserved_1);
183        debug.field("vcp_sequencing_raw", &self.vcp_sequencing);
184        debug.field(
185            "vcp_sequencing_number_of_elevations",
186            &self.vcp_sequencing_number_of_elevations(),
187        );
188        debug.field(
189            "vcp_sequencing_maximum_sails_cuts",
190            &self.vcp_sequencing_maximum_sails_cuts(),
191        );
192        debug.field(
193            "vcp_sequencing_sequence_active",
194            &self.vcp_sequencing_sequence_active(),
195        );
196        debug.field(
197            "vcp_sequencing_truncated_vcp",
198            &self.vcp_sequencing_truncated_vcp(),
199        );
200        debug.field("vcp_supplemental_data_raw", &self.vcp_supplemental_data);
201        debug.field(
202            "vcp_supplemental_data_sails_vcp",
203            &self.vcp_supplemental_data_sails_vcp(),
204        );
205        debug.field(
206            "vcp_supplemental_data_number_sails_cuts",
207            &self.vcp_supplemental_data_number_sails_cuts(),
208        );
209        debug.field(
210            "vcp_supplemental_data_mrle_vcp",
211            &self.vcp_supplemental_data_mrle_vcp(),
212        );
213        debug.field(
214            "vcp_supplemental_data_number_mrle_cuts",
215            &self.vcp_supplemental_data_number_mrle_cuts(),
216        );
217        debug.field(
218            "vcp_supplemental_data_mpda_vcp",
219            &self.vcp_supplemental_data_mpda_vcp(),
220        );
221        debug.field(
222            "vcp_supplemental_data_base_tilt_vcp",
223            &self.vcp_supplemental_data_base_tilt_vcp(),
224        );
225        debug.field(
226            "vcp_supplemental_data_base_tilts",
227            &self.vcp_supplemental_data_base_tilts(),
228        );
229        debug.field("reserved_2", &self.reserved_2);
230
231        debug.finish()
232    }
233}