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 } }