wxbox/crates/interchange/src/ar2.rs
core 32244daafe
Some checks are pending
Verify Latest Dependencies / Verify Latest Dependencies (push) Waiting to run
build and test / wxbox - latest (push) Waiting to run
mostly functional v2 rendering
2025-05-30 23:38:29 -04:00

120 lines
5.7 KiB
Rust

use ordered_float::OrderedFloat;
use crate::cif::cif_container::MessageType;
use crate::{AsCif, cif};
use nexrad_decode::messages::digital_radar_data::RadialStatus;
use wxbox_ar2::{MomentData, Radial, Scan};
pub struct Ar2AsCifParams {
pub requested_elevation: u8,
pub requested_product: String,
}
impl AsCif for Scan {
type Params = Ar2AsCifParams;
fn as_cif(&self, params: &Self::Params) -> cif::CifContainer {
let mut digital_radar_data = cif::digital_radar_data::DigitalRadarData::default();
digital_radar_data.elevation_number = params.requested_elevation as i32;
digital_radar_data.vcp_number = self.coverage_pattern_number as i32;
// find the elevation
let mut maybe_elevation = self
.sweeps
.iter()
.find(|u| u.elevation_number == params.requested_elevation);
if let Some(elevation) = maybe_elevation {
// parse out the radials
let mut radials_we_can_use: Vec<(&Radial, &MomentData)> = vec![];
let mut elevation = elevation.clone();
elevation.radials.sort_by_key(|u| OrderedFloat(u.azimuth_angle_degrees));
for radial in &elevation.radials {
match params.requested_product.as_str() {
"REF" if radial.reflectivity.is_some() => {
radials_we_can_use.push((&radial, &radial.reflectivity.as_ref().unwrap()));
}
"VEL" if radial.velocity.is_some() => {
radials_we_can_use.push((&radial, &radial.velocity.as_ref().unwrap()));
}
"SW" if radial.spectrum_width.is_some() => {
radials_we_can_use
.push((&radial, &radial.spectrum_width.as_ref().unwrap()));
}
"ZDR" if radial.differential_reflectivity.is_some() => {
radials_we_can_use
.push((&radial, &radial.differential_reflectivity.as_ref().unwrap()));
}
"PHI" if radial.differential_phase.is_some() => {
radials_we_can_use
.push((&radial, &radial.differential_phase.as_ref().unwrap()));
}
"RHO" if radial.correlation_coefficient.is_some() => {
radials_we_can_use
.push((&radial, &radial.correlation_coefficient.as_ref().unwrap()));
}
"CFP" if radial.specific_differential_phase.is_some() => {
radials_we_can_use.push((
&radial,
&radial.specific_differential_phase.as_ref().unwrap(),
));
}
_ => {}
}
}
digital_radar_data.radials = radials_we_can_use
.iter()
.map(|u| {
let mut radial = cif::digital_radar_data::Radial::default();
radial.elevation_number = u.0.elevation_number as i32;
radial.azimuth_angle_degrees = u.0.azimuth_angle_degrees;
radial.azimuth_number = u.0.azimuth_number as i32;
radial.azimuth_spacing_degrees = u.0.azimuth_spacing_degrees;
radial.collection_timestamp = u.0.collection_timestamp as u64;
radial.elevation_degrees = u.0.elevation_number_degrees;
radial.radial_status = match u.0.radial_status {
RadialStatus::ElevationStart => {
cif::digital_radar_data::RadialStatus::ElevationStart
}
RadialStatus::IntermediateRadialData => {
cif::digital_radar_data::RadialStatus::IntermediateRadialData
}
RadialStatus::ElevationEnd => {
cif::digital_radar_data::RadialStatus::ElevationEnd
}
RadialStatus::VolumeScanStart => {
cif::digital_radar_data::RadialStatus::VolumeScanStart
}
RadialStatus::VolumeScanEnd => {
cif::digital_radar_data::RadialStatus::VolumeScanEnd
}
RadialStatus::ElevationStartVCPFinal => {
cif::digital_radar_data::RadialStatus::ElevationStartVcpFinal
}
}
.into();
let mut moment_meta = cif::digital_radar_data::MomentaryMeta::default();
moment_meta.product_name = params.requested_product.clone();
let mut moment_data = cif::digital_radar_data::MomentaryData::default();
moment_data.offset = u.1.offset;
moment_data.sample_interval = u.1.sample_interval as i32;
moment_data.scale = u.1.scale;
moment_data.start_range = u.1.start_range as i32;
moment_data.data = u.1.values.iter().map(|u| *u as i32).collect();
let mut moment_product = cif::digital_radar_data::MomentaryProduct::default();
moment_product.product_metadata = Some(moment_meta);
moment_product.data = Some(moment_data);
radial.product = Some(moment_product);
radial
})
.collect()
}
let mut container = cif::CifContainer::default();
container.message_type = Some(MessageType::DigitalRadarData(digital_radar_data));
container
}
}