Skip to main content

nexrad_model/data/
product.rs

1use crate::data::{CFPMomentData, MomentData, Radial};
2
3#[cfg(feature = "serde")]
4use serde::{Deserialize, Serialize};
5
6/// Identifies a radar data product (moment type).
7///
8/// Each product corresponds to a different type of moment data captured by the radar.
9/// This enum is shared across the entire crate ecosystem — it identifies which moment
10/// field to extract from a radial, which processing algorithm to apply, or which color
11/// scale to use for rendering.
12#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
13#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
14pub enum Product {
15    /// Base reflectivity (dBZ). Measures the intensity of precipitation.
16    Reflectivity,
17    /// Radial velocity (m/s). Measures motion toward or away from the radar.
18    Velocity,
19    /// Spectrum width (m/s). Measures turbulence within the radar beam.
20    SpectrumWidth,
21    /// Differential reflectivity (dB). Compares horizontal and vertical reflectivity.
22    DifferentialReflectivity,
23    /// Differential phase (degrees). Phase difference between polarizations.
24    DifferentialPhase,
25    /// Correlation coefficient. Correlation between polarizations (0-1).
26    CorrelationCoefficient,
27    /// Clutter filter power (CFP). Difference between clutter-filtered and unfiltered reflectivity.
28    ClutterFilterPower,
29}
30
31impl Product {
32    /// Returns the moment data for this product from a radial, if present.
33    ///
34    /// For all products except [`Product::ClutterFilterPower`], this returns the standard
35    /// [`MomentData`]. For CFP, use [`cfp_moment_data`](Self::cfp_moment_data) instead.
36    pub fn moment_data<'a>(&self, radial: &'a Radial) -> Option<&'a MomentData> {
37        match self {
38            Product::Reflectivity => radial.reflectivity(),
39            Product::Velocity => radial.velocity(),
40            Product::SpectrumWidth => radial.spectrum_width(),
41            Product::DifferentialReflectivity => radial.differential_reflectivity(),
42            Product::DifferentialPhase => radial.differential_phase(),
43            Product::CorrelationCoefficient => radial.correlation_coefficient(),
44            Product::ClutterFilterPower => None,
45        }
46    }
47
48    /// Returns the CFP moment data from a radial, if this product is
49    /// [`Product::ClutterFilterPower`] and the data is present.
50    pub fn cfp_moment_data<'a>(&self, radial: &'a Radial) -> Option<&'a CFPMomentData> {
51        match self {
52            Product::ClutterFilterPower => radial.clutter_filter_power(),
53            _ => None,
54        }
55    }
56
57    /// Returns the typical value range `(min, max)` for this product.
58    ///
59    /// These ranges cover the expected data values for each product type and are
60    /// used for color mapping and normalization.
61    pub fn value_range(&self) -> (f32, f32) {
62        match self {
63            Product::Reflectivity => (-32.0, 95.0),
64            Product::Velocity => (-64.0, 64.0),
65            Product::SpectrumWidth => (0.0, 30.0),
66            Product::DifferentialReflectivity => (-2.0, 6.0),
67            Product::DifferentialPhase => (0.0, 360.0),
68            Product::CorrelationCoefficient => (0.0, 1.0),
69            Product::ClutterFilterPower => (-20.0, 20.0),
70        }
71    }
72
73    /// Returns the standard unit string for this product.
74    pub fn unit(&self) -> &'static str {
75        match self {
76            Product::Reflectivity => "dBZ",
77            Product::Velocity => "m/s",
78            Product::SpectrumWidth => "m/s",
79            Product::DifferentialReflectivity => "dB",
80            Product::DifferentialPhase => "°",
81            Product::CorrelationCoefficient => "",
82            Product::ClutterFilterPower => "dB",
83        }
84    }
85
86    /// Returns a human-readable label for this product.
87    pub fn label(&self) -> &'static str {
88        match self {
89            Product::Reflectivity => "Reflectivity",
90            Product::Velocity => "Velocity",
91            Product::SpectrumWidth => "Spectrum Width",
92            Product::DifferentialReflectivity => "Differential Reflectivity",
93            Product::DifferentialPhase => "Differential Phase",
94            Product::CorrelationCoefficient => "Correlation Coefficient",
95            Product::ClutterFilterPower => "Clutter Filter Power",
96        }
97    }
98}