formatting
Some checks are pending
Verify Latest Dependencies / Verify Latest Dependencies (push) Waiting to run
build and test / wxbox - latest (push) Waiting to run

This commit is contained in:
core 2025-04-05 22:06:56 -04:00
parent 913ec262bd
commit 23571406ea
Signed by: core
GPG key ID: FDBF740DADDCEECF
10 changed files with 152 additions and 105 deletions

View file

@ -1,8 +1,8 @@
use std::fmt::Debug;
use nexrad_data::volume::File; use nexrad_data::volume::File;
use nexrad_decode::messages::digital_radar_data::{GenericDataBlock, RadialStatus};
use nexrad_decode::messages::MessageContents; use nexrad_decode::messages::MessageContents;
use nexrad_decode::messages::digital_radar_data::{GenericDataBlock, RadialStatus};
use nexrad_decode::result::Error; use nexrad_decode::result::Error;
use std::fmt::Debug;
pub mod sites; pub mod sites;
@ -39,7 +39,7 @@ pub struct MomentData {
pub offset: f32, pub offset: f32,
pub values: Vec<u8>, pub values: Vec<u8>,
pub start_range: u16, pub start_range: u16,
pub sample_interval: u16 pub sample_interval: u16,
} }
impl MomentData { impl MomentData {
@ -97,8 +97,7 @@ pub fn parse(input: Vec<u8>) -> nexrad_data::result::Result<Scan> {
if let MessageContents::DigitalRadarData(radar_data_message) = contents { if let MessageContents::DigitalRadarData(radar_data_message) = contents {
if vcp.is_none() { if vcp.is_none() {
if let Some(volume_block) = &radar_data_message.volume_data_block { if let Some(volume_block) = &radar_data_message.volume_data_block {
vcp = vcp = Some(volume_block.volume_coverage_pattern_number);
Some(volume_block.volume_coverage_pattern_number);
} }
} }
radials.push(into_radial(*radar_data_message)?); radials.push(into_radial(*radar_data_message)?);
@ -112,9 +111,15 @@ pub fn parse(input: Vec<u8>) -> nexrad_data::result::Result<Scan> {
}) })
} }
fn into_radial(message: nexrad_decode::messages::digital_radar_data::Message) -> nexrad_data::result::Result<Radial> { fn into_radial(
message: nexrad_decode::messages::digital_radar_data::Message,
) -> nexrad_data::result::Result<Radial> {
Ok(Radial { Ok(Radial {
collection_timestamp: message.header.date_time().ok_or(Error::MessageMissingDateError)?.timestamp_millis(), collection_timestamp: message
.header
.date_time()
.ok_or(Error::MessageMissingDateError)?
.timestamp_millis(),
azimuth_number: message.header.azimuth_number, azimuth_number: message.header.azimuth_number,
azimuth_angle_degrees: message.header.azimuth_angle, azimuth_angle_degrees: message.header.azimuth_angle,
azimuth_spacing_degrees: message.header.azimuth_resolution_spacing as f32 * 0.5, azimuth_spacing_degrees: message.header.azimuth_resolution_spacing as f32 * 0.5,
@ -123,11 +128,21 @@ fn into_radial(message: nexrad_decode::messages::digital_radar_data::Message) ->
elevation_number_degrees: message.header.elevation_angle, elevation_number_degrees: message.header.elevation_angle,
reflectivity: message.reflectivity_data_block.map(|u| into_moment_data(u)), reflectivity: message.reflectivity_data_block.map(|u| into_moment_data(u)),
velocity: message.velocity_data_block.map(|u| into_moment_data(u)), velocity: message.velocity_data_block.map(|u| into_moment_data(u)),
spectrum_width: message.spectrum_width_data_block.map(|u| into_moment_data(u)), spectrum_width: message
differential_reflectivity: message.differential_reflectivity_data_block.map(|u| into_moment_data(u)), .spectrum_width_data_block
differential_phase: message.differential_phase_data_block.map(|u| into_moment_data(u)), .map(|u| into_moment_data(u)),
correlation_coefficient: message.correlation_coefficient_data_block.map(|u| into_moment_data(u)), differential_reflectivity: message
specific_differential_phase: message.specific_diff_phase_data_block.map(|u| into_moment_data(u)), .differential_reflectivity_data_block
.map(|u| into_moment_data(u)),
differential_phase: message
.differential_phase_data_block
.map(|u| into_moment_data(u)),
correlation_coefficient: message
.correlation_coefficient_data_block
.map(|u| into_moment_data(u)),
specific_differential_phase: message
.specific_diff_phase_data_block
.map(|u| into_moment_data(u)),
}) })
} }
@ -137,58 +152,41 @@ fn into_moment_data(block: GenericDataBlock) -> MomentData {
offset: block.header.offset, offset: block.header.offset,
values: block.encoded_data, values: block.encoded_data,
start_range: block.header.data_moment_range, start_range: block.header.data_moment_range,
sample_interval: block.header.data_moment_range_sample_interval sample_interval: block.header.data_moment_range_sample_interval,
} }
} }
impl Sweep { impl Sweep {
pub fn new(elevation_number: u8, radials: Vec<Radial>) -> Self { pub fn new(elevation_number: u8, radials: Vec<Radial>) -> Self {
Self { Self {
elevation_number, elevation_number,
radials, radials,
} }
} }
pub fn from_radials(radials: Vec<Radial>) -> Vec<Self> { pub fn from_radials(radials: Vec<Radial>) -> Vec<Self> {
let mut sweeps = Vec::new(); let mut sweeps = Vec::new();
let mut sweep_elevation_number = None; let mut sweep_elevation_number = None;
let mut sweep_radials = Vec::new(); let mut sweep_radials = Vec::new();
for radial in radials { for radial in radials {
if let Some(elevation_number) = sweep_elevation_number { if let Some(elevation_number) = sweep_elevation_number {
if elevation_number != radial.elevation_number { if elevation_number != radial.elevation_number {
sweeps.push(Sweep::new(elevation_number, sweep_radials)); sweeps.push(Sweep::new(elevation_number, sweep_radials));
sweep_radials = Vec::new(); sweep_radials = Vec::new();
} }
} }
sweep_elevation_number = Some(radial.elevation_number); sweep_elevation_number = Some(radial.elevation_number);
sweep_radials.push(radial); sweep_radials.push(radial);
} }
sweeps sweeps
} }
} }
pub const DATA_BYTES: &[u8] = include_bytes!("../KCRP20170825_235733_V06"); pub const DATA_BYTES: &[u8] = include_bytes!("../KCRP20170825_235733_V06");

View file

@ -4,5 +4,16 @@ use wxbox_ar2::parse;
fn main() { fn main() {
let f = fs::read("KCRP20170825_235733_V06").unwrap(); let f = fs::read("KCRP20170825_235733_V06").unwrap();
let f = parse(f).unwrap(); let f = parse(f).unwrap();
println!("{:?}", f.sweeps.get(0).unwrap().radials.get(0).unwrap().reflectivity.as_ref().unwrap()); println!(
"{:?}",
f.sweeps
.get(0)
.unwrap()
.radials
.get(0)
.unwrap()
.reflectivity
.as_ref()
.unwrap()
);
} }

View file

@ -83,8 +83,10 @@ mod tests {
let radar = SITES.sites.get("KCRP").unwrap(); let radar = SITES.sites.get("KCRP").unwrap();
let radar_theta = radar.long; let radar_theta = radar.long;
let radar_phi = radar.lat; let radar_phi = radar.lat;
let radar_r = ((A.powi(2) * radar_phi.cos()).powi(2) + (B.powi(2) * radar_phi.sin()).powi(2) let radar_r = ((A.powi(2) * radar_phi.cos()).powi(2)
/ (A * radar_phi.cos()).powi(2) + (B * radar_phi.sin()).powi(2)).sqrt(); + (B.powi(2) * radar_phi.sin()).powi(2) / (A * radar_phi.cos()).powi(2)
+ (B * radar_phi.sin()).powi(2))
.sqrt();
let radar_x = radar_r * radar_theta.cos() * radar_phi.sin(); let radar_x = radar_r * radar_theta.cos() * radar_phi.sin();
let radar_y = radar_r * radar_theta.sin() * radar_phi.sin(); let radar_y = radar_r * radar_theta.sin() * radar_phi.sin();
@ -94,7 +96,6 @@ mod tests {
let measurement_phi = radar_phi; let measurement_phi = radar_phi;
let measurement_r = radar_r; let measurement_r = radar_r;
let measurement_x = measurement_r * measurement_theta.cos() * measurement_phi.sin(); let measurement_x = measurement_r * measurement_theta.cos() * measurement_phi.sin();
let measurement_y = measurement_r * measurement_theta.sin() * measurement_phi.sin(); let measurement_y = measurement_r * measurement_theta.sin() * measurement_phi.sin();
let measurement_z = measurement_r * measurement_theta.cos(); let measurement_z = measurement_r * measurement_theta.cos();
@ -103,7 +104,8 @@ mod tests {
let radar_local_y = measurement_y - radar_y; let radar_local_y = measurement_y - radar_y;
let radar_local_z = measurement_z - radar_z; let radar_local_z = measurement_z - radar_z;
let radar_local_r = (radar_local_x.powi(2) + radar_local_y.powi(2) + radar_local_z.powi(2)).sqrt(); let radar_local_r =
(radar_local_x.powi(2) + radar_local_y.powi(2) + radar_local_z.powi(2)).sqrt();
let radar_local_theta = (radar_local_y / radar_local_x).atan(); let radar_local_theta = (radar_local_y / radar_local_x).atan();
let radar_local_phi = (radar_local_z / radar_local_r).acos(); let radar_local_phi = (radar_local_z / radar_local_r).acos();

View file

@ -93,19 +93,18 @@ pub static NOAA_MRMS_MERGED_RHOHV_3KM_CONUS: LazyLock<LayerSource> =
tile_size: 512, tile_size: 512,
max_zoom: 19, max_zoom: 19,
}); });
pub static ROC_KCRP_TEST: LazyLock<LayerSource> = pub static ROC_KCRP_TEST: LazyLock<LayerSource> = LazyLock::new(|| LayerSource {
LazyLock::new(|| LayerSource { source_id: 0x0EFAF68CB6E30B8E,
source_id: 0x0EFAF68CB6E30B8E, tile_url: format!(
tile_url: format!( "{}/nexrad/kcrp_ref_test/{{z}}/{{x}}/{{y}}@2x.png",
"{}/nexrad/kcrp_ref_test/{{z}}/{{x}}/{{y}}@2x.png", env!("TILER_BASE_URL")
env!("TILER_BASE_URL") ),
), display_name: "KCRP SSR Test".into(),
display_name: "KCRP SSR Test".into(), short_name: "KCRP SSR TEST (KCRP)".into(),
short_name: "KCRP SSR TEST (KCRP)".into(), type_hint: LayerTypeHint::RadarData,
type_hint: LayerTypeHint::RadarData, location: "KCRP".into(),
location: "KCRP".into(), source: "NOAA / ROC".into(),
source: "NOAA / ROC".into(), source_link: "https://roc.noaa.gov".into(),
source_link: "https://roc.noaa.gov".into(), tile_size: 512,
tile_size: 512, max_zoom: 19,
max_zoom: 19, });
});

View file

@ -62,7 +62,7 @@ impl LayerManager {
&*NOAA_MRMS_MERGED_CREF_QC_GUAM, // Guam &*NOAA_MRMS_MERGED_CREF_QC_GUAM, // Guam
// -- NOAA MRMS - Merged RhoHV (Differential Reflectivity) @ 3km // -- NOAA MRMS - Merged RhoHV (Differential Reflectivity) @ 3km
&*NOAA_MRMS_MERGED_RHOHV_3KM_CONUS, &*NOAA_MRMS_MERGED_RHOHV_3KM_CONUS,
&*ROC_KCRP_TEST &*ROC_KCRP_TEST,
]; ];
for layer in layers { for layer in layers {

View file

@ -2,13 +2,13 @@ pub mod error;
pub mod wgs84; pub mod wgs84;
use crate::error::GribError; use crate::error::GribError;
use wxbox_nommer::NomReader;
use crate::wgs84::LatLong; use crate::wgs84::LatLong;
use crate::LatLongVectorRelativity::{EasterlyAndNortherly, IncreasingXY}; use crate::LatLongVectorRelativity::{EasterlyAndNortherly, IncreasingXY};
use image::{DynamicImage, ImageFormat, ImageReader}; use image::{DynamicImage, ImageFormat, ImageReader};
use std::fmt::{Debug, Formatter}; use std::fmt::{Debug, Formatter};
use std::io::{Cursor, Read}; use std::io::{Cursor, Read};
use tracing::warn; use tracing::warn;
use wxbox_nommer::NomReader;
pub const INDICATOR: u32 = u32::from_be_bytes(*b"GRIB"); pub const INDICATOR: u32 = u32::from_be_bytes(*b"GRIB");
pub const EDITION: u8 = 2; pub const EDITION: u8 = 2;

View file

@ -1,6 +1,6 @@
use crate::grib2::Grib2DataConfig; use crate::grib2::Grib2DataConfig;
use serde::{Deserialize, Serialize};
use crate::nexrad::NexradDataConfig; use crate::nexrad::NexradDataConfig;
use serde::{Deserialize, Serialize};
#[derive(Serialize, Deserialize)] #[derive(Serialize, Deserialize)]
pub struct Config { pub struct Config {

View file

@ -9,6 +9,7 @@ use flate2::read::GzDecoder;
use image::codecs::png::PngEncoder; use image::codecs::png::PngEncoder;
use image::{Rgba, RgbaImage}; use image::{Rgba, RgbaImage};
use moka::future::Cache; use moka::future::Cache;
use rayon::iter::IntoParallelIterator;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use std::collections::HashMap; use std::collections::HashMap;
use std::f64::consts::PI; use std::f64::consts::PI;
@ -17,7 +18,6 @@ use std::io;
use std::io::{Cursor, ErrorKind}; use std::io::{Cursor, ErrorKind};
use std::num::TryFromIntError; use std::num::TryFromIntError;
use std::sync::Arc; use std::sync::Arc;
use rayon::iter::IntoParallelIterator;
use tokio::io::AsyncReadExt; use tokio::io::AsyncReadExt;
use tracing::{debug, info_span}; use tracing::{debug, info_span};
use wxbox_grib2::GribMessage; use wxbox_grib2::GribMessage;
@ -146,21 +146,29 @@ async fn render_to_png(
let tile_y_times_tilesize = tile_id.y as f64 * tile_id.size as f64; let tile_y_times_tilesize = tile_id.y as f64 * tile_id.size as f64;
let generate_pixels_span = info_span!("generate_pixels"); let generate_pixels_span = info_span!("generate_pixels");
let pixels = (0..tile_id.size).into_par_iter().map(|x| { let pixels = (0..tile_id.size)
(0..tile_id.size).into_par_iter().map(|y| { .into_par_iter()
let x_cartesian = (tile_x_times_tilesize + x as f64) / n; .map(|x| {
let y_cartesian = (tile_y_times_tilesize + y as f64) / n; (0..tile_id.size)
.into_par_iter()
.map(|y| {
let x_cartesian = (tile_x_times_tilesize + x as f64) / n;
let y_cartesian = (tile_y_times_tilesize + y as f64) / n;
let long = (TWO_PI * x_cartesian - PI).to_degrees(); let long = (TWO_PI * x_cartesian - PI).to_degrees();
let lat = ((PI - TWO_PI * y_cartesian).exp().atan() * 2.0_f64 - HALF_PI).to_degrees(); let lat =
((PI - TWO_PI * y_cartesian).exp().atan() * 2.0_f64 - HALF_PI).to_degrees();
let nearest_value = data.value_for(LatLong { lat, long }).map(|u| u as f64); let nearest_value = data.value_for(LatLong { lat, long }).map(|u| u as f64);
let color = colorize(nearest_value, &data_source).unwrap_or(Rgba::from([0,0,0,0])); let color =
colorize(nearest_value, &data_source).unwrap_or(Rgba::from([0, 0, 0, 0]));
color color
}).collect::<Vec<_>>() })
}).collect::<Vec<_>>(); .collect::<Vec<_>>()
})
.collect::<Vec<_>>();
drop(generate_pixels_span); drop(generate_pixels_span);
let put_pixels_span = info_span!("put_pixels"); let put_pixels_span = info_span!("put_pixels");

View file

@ -1,11 +1,12 @@
mod config; mod config;
mod error; mod error;
mod grib2; mod grib2;
mod tiles;
mod nexrad; mod nexrad;
mod tiles;
use crate::config::Config; use crate::config::Config;
use crate::grib2::{Grib2DataCache, Grib2TileCache, grib2_handler}; use crate::grib2::{Grib2DataCache, Grib2TileCache, grib2_handler};
use crate::nexrad::{NexradDataCache, NexradTileCache, nexrad_handler};
use crate::tiles::{DataId, TileId}; use crate::tiles::{DataId, TileId};
use axum::Router; use axum::Router;
use axum::routing::get; use axum::routing::get;
@ -16,7 +17,6 @@ use std::sync::Arc;
use tracing_subscriber::fmt::format::FmtSpan; use tracing_subscriber::fmt::format::FmtSpan;
use tracing_subscriber::util::SubscriberInitExt; use tracing_subscriber::util::SubscriberInitExt;
use wxbox_grib2::GribMessage; use wxbox_grib2::GribMessage;
use crate::nexrad::{nexrad_handler, NexradDataCache, NexradTileCache};
#[derive(Clone)] #[derive(Clone)]
pub struct AppState { pub struct AppState {

View file

@ -6,9 +6,12 @@ use axum::extract::{Path, State};
use axum::http::{StatusCode, header}; use axum::http::{StatusCode, header};
use axum::response::IntoResponse; use axum::response::IntoResponse;
use flate2::read::GzDecoder; use flate2::read::GzDecoder;
use geographiclib::Geodesic;
use image::codecs::png::PngEncoder; use image::codecs::png::PngEncoder;
use image::{Rgba, RgbaImage}; use image::{Rgba, RgbaImage};
use moka::future::Cache; use moka::future::Cache;
use rayon::iter::IntoParallelIterator;
use rayon::iter::ParallelIterator;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use std::collections::HashMap; use std::collections::HashMap;
use std::f64::consts::PI; use std::f64::consts::PI;
@ -17,14 +20,11 @@ use std::io;
use std::io::{Cursor, ErrorKind}; use std::io::{Cursor, ErrorKind};
use std::num::TryFromIntError; use std::num::TryFromIntError;
use std::sync::Arc; use std::sync::Arc;
use geographiclib::Geodesic;
use rayon::iter::IntoParallelIterator;
use tokio::io::AsyncReadExt; use tokio::io::AsyncReadExt;
use tracing::{debug, info_span}; use tracing::{debug, info_span};
use wxbox_ar2::{parse, MomentValue, Scan, DATA_BYTES, Radial, Sweep};
use wxbox_ar2::sites::wsr88d::{SITES, Wsr88dSite}; use wxbox_ar2::sites::wsr88d::{SITES, Wsr88dSite};
use wxbox_ar2::{DATA_BYTES, MomentValue, Radial, Scan, Sweep, parse};
use wxbox_grib2::GribMessage; use wxbox_grib2::GribMessage;
use rayon::iter::ParallelIterator;
use wxbox_grib2::wgs84::LatLong; use wxbox_grib2::wgs84::LatLong;
use wxbox_pal::{ColorPalette, Palette}; use wxbox_pal::{ColorPalette, Palette};
@ -126,7 +126,15 @@ fn radius_at_latitude(phi: f64) -> f64 {
(top / bottom).sqrt() (top / bottom).sqrt()
} }
fn calculate_inverse(tile_x_times_tilesize: f64, tile_y_times_tilesize: f64, x: usize, y: usize, g: &Geodesic, radar: &Wsr88dSite, n: f64) -> (f64, f64) { fn calculate_inverse(
tile_x_times_tilesize: f64,
tile_y_times_tilesize: f64,
x: usize,
y: usize,
g: &Geodesic,
radar: &Wsr88dSite,
n: f64,
) -> (f64, f64) {
let x_cartesian = (tile_x_times_tilesize + x as f64) / n; let x_cartesian = (tile_x_times_tilesize + x as f64) / n;
let y_cartesian = (tile_y_times_tilesize + y as f64) / n; let y_cartesian = (tile_y_times_tilesize + y as f64) / n;
@ -145,7 +153,9 @@ fn locate_radial(azimuth: f64, sweep: &Sweep) -> Option<&Radial> {
for radial in &sweep.radials { for radial in &sweep.radials {
let this_dist = (radial.azimuth_angle_degrees as f64 - azimuth).abs(); let this_dist = (radial.azimuth_angle_degrees as f64 - azimuth).abs();
if this_dist.abs() > radial.azimuth_spacing_degrees as f64 { continue; } if this_dist.abs() > radial.azimuth_spacing_degrees as f64 {
continue;
}
if let Some(previous_best) = closest_radial { if let Some(previous_best) = closest_radial {
let curr_dist = (previous_best.azimuth_angle_degrees as f64 - azimuth).abs(); let curr_dist = (previous_best.azimuth_angle_degrees as f64 - azimuth).abs();
@ -156,8 +166,6 @@ fn locate_radial(azimuth: f64, sweep: &Sweep) -> Option<&Radial> {
} else { } else {
closest_radial = Some(radial); closest_radial = Some(radial);
} }
} }
closest_radial closest_radial
@ -189,39 +197,58 @@ async fn render_to_png(
drop(prep_span); drop(prep_span);
let generate_pixels_span = info_span!("generate_pixels"); let generate_pixels_span = info_span!("generate_pixels");
let pixels = (0..tile_id.size).into_par_iter().map(|x| { let pixels = (0..tile_id.size)
(0..tile_id.size).into_par_iter().map(|y| { .into_par_iter()
let (d_m, azimuth) = calculate_inverse(tile_x_times_tilesize, tile_y_times_tilesize, x, y, &g, radar, n); .map(|x| {
let Some(radial) = locate_radial(azimuth, first_sweep) else { return colorize(None, &data_source).unwrap_or(Rgba::from([0,0,0,0])) }; (0..tile_id.size)
.into_par_iter()
.map(|y| {
let (d_m, azimuth) = calculate_inverse(
tile_x_times_tilesize,
tile_y_times_tilesize,
x,
y,
&g,
radar,
n,
);
let Some(radial) = locate_radial(azimuth, first_sweep) else {
return colorize(None, &data_source).unwrap_or(Rgba::from([0, 0, 0, 0]));
};
let reflectivity = radial.reflectivity.as_ref().unwrap(); let reflectivity = radial.reflectivity.as_ref().unwrap();
let distance_km = d_m / 1000.0; let distance_km = d_m / 1000.0;
let first_gate_distance = reflectivity.start_range as f64 / 1000.0; // stored in meters let first_gate_distance = reflectivity.start_range as f64 / 1000.0; // stored in meters
let gate_spacing = reflectivity.sample_interval as f64 / 1000.0; // also stored in meters let gate_spacing = reflectivity.sample_interval as f64 / 1000.0; // also stored in meters
if distance_km < first_gate_distance { if distance_km < first_gate_distance {
return colorize(None, &data_source).unwrap_or(Rgba::from([0,0,0,0])) return colorize(None, &data_source).unwrap_or(Rgba::from([0, 0, 0, 0]));
} }
let gate = ((distance_km - first_gate_distance) / gate_spacing).round() as usize; let gate =
((distance_km - first_gate_distance) / gate_spacing).round() as usize;
let data = &reflectivity.values; let data = &reflectivity.values;
if gate > data.len() || gate < 0 { if gate > data.len() || gate < 0 {
return colorize(None, &data_source).unwrap_or(Rgba::from([0,0,0,0])); return colorize(None, &data_source).unwrap_or(Rgba::from([0, 0, 0, 0]));
} }
let color = data.get(gate).map(|raw_value| match raw_value { let color = data.get(gate).map(|raw_value| match raw_value {
0 => MomentValue::BelowThreshold, 0 => MomentValue::BelowThreshold,
1 => MomentValue::RangeFolded, 1 => MomentValue::RangeFolded,
_ => MomentValue::Value((*raw_value as f32 - reflectivity.offset) / reflectivity.scale), _ => MomentValue::Value(
}); (*raw_value as f32 - reflectivity.offset) / reflectivity.scale,
),
});
return colorize(color, &data_source).unwrap_or(Rgba::from([0,0,0,0])); return colorize(color, &data_source).unwrap_or(Rgba::from([0, 0, 0, 0]));
}).collect::<Vec<_>>() })
}).collect::<Vec<_>>(); .collect::<Vec<_>>()
})
.collect::<Vec<_>>();
drop(generate_pixels_span); drop(generate_pixels_span);
let put_pixels_span = info_span!("put_pixels"); let put_pixels_span = info_span!("put_pixels");
@ -242,7 +269,6 @@ async fn render_to_png(
let output = Arc::new(result); let output = Arc::new(result);
drop(encode_span); drop(encode_span);
drop(span); drop(span);
@ -251,7 +277,10 @@ async fn render_to_png(
Ok(output) Ok(output)
} }
fn colorize(value: Option<MomentValue>, data_source: &NexradDataSource) -> anyhow::Result<Rgba<u8>> { fn colorize(
value: Option<MomentValue>,
data_source: &NexradDataSource,
) -> anyhow::Result<Rgba<u8>> {
Ok(match value { Ok(match value {
Some(MomentValue::BelowThreshold) => Rgba([0, 0, 0, 0]), Some(MomentValue::BelowThreshold) => Rgba([0, 0, 0, 0]),
Some(MomentValue::RangeFolded) => Rgba([119, 0, 125, 255]), Some(MomentValue::RangeFolded) => Rgba([119, 0, 125, 255]),