chore: praise be the clippy gods
This commit is contained in:
parent
fe4a47d6cc
commit
e4dcb48878
9 changed files with 55 additions and 90 deletions
|
@ -1,6 +1,3 @@
|
|||
use std::{env, fs};
|
||||
use std::hint::black_box;
|
||||
use std::time::Instant;
|
||||
use criterion::{criterion_group, criterion_main, BenchmarkId, Criterion};
|
||||
use wxbox_ar2::parse;
|
||||
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
#![warn(clippy::all)]
|
||||
|
||||
use nexrad_data::volume::File;
|
||||
use nexrad_decode::messages::MessageContents;
|
||||
use nexrad_decode::messages::digital_radar_data::{GenericDataBlock, RadialStatus};
|
||||
|
@ -46,7 +48,6 @@ pub struct MomentData {
|
|||
|
||||
impl MomentData {
|
||||
/// Values from this data moment corresponding to gates in the radial.
|
||||
|
||||
pub fn values(&self) -> Vec<MomentValue> {
|
||||
let copied_values = self.values.iter().copied();
|
||||
|
||||
|
@ -67,9 +68,7 @@ impl MomentData {
|
|||
}
|
||||
|
||||
/// The data moment value for a product in a radial's gate. The value may be a floating-point number
|
||||
|
||||
/// or a special case such as "below threshold" or "range folded".
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq)]
|
||||
|
||||
pub enum MomentValue {
|
||||
|
@ -89,7 +88,7 @@ pub fn parse(input: Vec<u8>) -> nexrad_data::result::Result<Scan> {
|
|||
let mut vcp: Option<u16> = None;
|
||||
let mut radials = vec![];
|
||||
|
||||
let mut radial_chunks: Vec<nexrad_data::result::Result<(Vec<Radial>, Option<u16>)>> = file.records()
|
||||
let radial_chunks: Vec<nexrad_data::result::Result<(Vec<Radial>, Option<u16>)>> = file.records()
|
||||
.par_iter_mut()
|
||||
.map(|record| {
|
||||
let mut vcp = None;
|
||||
|
@ -145,23 +144,23 @@ fn into_radial(
|
|||
radial_status: message.header.radial_status(),
|
||||
elevation_number: message.header.elevation_number,
|
||||
elevation_number_degrees: message.header.elevation_angle,
|
||||
reflectivity: message.reflectivity_data_block.map(|u| into_moment_data(u)),
|
||||
velocity: message.velocity_data_block.map(|u| into_moment_data(u)),
|
||||
reflectivity: message.reflectivity_data_block.map(into_moment_data),
|
||||
velocity: message.velocity_data_block.map(into_moment_data),
|
||||
spectrum_width: message
|
||||
.spectrum_width_data_block
|
||||
.map(|u| into_moment_data(u)),
|
||||
.map(into_moment_data),
|
||||
differential_reflectivity: message
|
||||
.differential_reflectivity_data_block
|
||||
.map(|u| into_moment_data(u)),
|
||||
.map(into_moment_data),
|
||||
differential_phase: message
|
||||
.differential_phase_data_block
|
||||
.map(|u| into_moment_data(u)),
|
||||
.map(into_moment_data),
|
||||
correlation_coefficient: message
|
||||
.correlation_coefficient_data_block
|
||||
.map(|u| into_moment_data(u)),
|
||||
.map(into_moment_data),
|
||||
specific_differential_phase: message
|
||||
.specific_diff_phase_data_block
|
||||
.map(|u| into_moment_data(u)),
|
||||
.map(into_moment_data),
|
||||
})
|
||||
}
|
||||
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
use std::{env, fs};
|
||||
use std::fs::File;
|
||||
use std::time::Instant;
|
||||
use wxbox_ar2::parse;
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
use serde::{Deserialize, Deserializer};
|
||||
use std::collections::HashMap;
|
||||
use std::sync::{LazyLock, OnceLock};
|
||||
use std::sync::LazyLock;
|
||||
|
||||
#[derive(Deserialize, Debug)]
|
||||
pub struct Wsr88dSite {
|
||||
|
@ -30,7 +30,7 @@ where
|
|||
{
|
||||
let s: String = Deserialize::deserialize(deserializer)?;
|
||||
|
||||
let elevation = s.split(" ").nth(0).unwrap();
|
||||
let elevation = s.split(" ").next().unwrap();
|
||||
Ok(elevation.parse().unwrap())
|
||||
}
|
||||
|
||||
|
|
|
@ -1,7 +1,4 @@
|
|||
|
||||
use std::{env, fs};
|
||||
use std::hint::black_box;
|
||||
use std::time::Instant;
|
||||
use criterion::{criterion_group, criterion_main, BenchmarkId, Criterion};
|
||||
use wxbox_grib2::GribMessage;
|
||||
|
||||
|
|
|
@ -2,28 +2,24 @@ use crate::AppState;
|
|||
use crate::error::AppError;
|
||||
use crate::tiles::{DataId, TileId};
|
||||
use anyhow::{anyhow, bail};
|
||||
use axum::Json;
|
||||
use axum::extract::{Path, State};
|
||||
use axum::http::{StatusCode, header};
|
||||
use axum::http::header;
|
||||
use axum::response::IntoResponse;
|
||||
use flate2::read::GzDecoder;
|
||||
use image::codecs::png::PngEncoder;
|
||||
use image::{Rgba, RgbaImage};
|
||||
use moka::future::Cache;
|
||||
use rayon::iter::IntoParallelIterator;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::collections::HashMap;
|
||||
use std::f64::consts::PI;
|
||||
use std::fmt::Debug;
|
||||
use std::io;
|
||||
use std::io::{Cursor, ErrorKind};
|
||||
use std::num::TryFromIntError;
|
||||
use std::sync::Arc;
|
||||
use axum::Json;
|
||||
use tokio::io::AsyncReadExt;
|
||||
use tracing::{debug, info_span};
|
||||
use tracing::info_span;
|
||||
use wxbox_grib2::GribMessage;
|
||||
use wxbox_grib2::wgs84::LatLong;
|
||||
use wxbox_pal::{ColorPalette, Palette};
|
||||
use wxbox_pal::ColorPalette;
|
||||
|
||||
use rayon::iter::ParallelIterator;
|
||||
use wxbox_common::{Grib2DataSource, GribMessageTimeMetadata, GribTileMetadata};
|
||||
|
@ -35,13 +31,11 @@ pub type Grib2DataConfig = HashMap<String, Grib2DataSource>;
|
|||
|
||||
#[tracing::instrument(level = "info")]
|
||||
pub async fn grib2_metadata(
|
||||
Path((source)): Path<(String)>,
|
||||
Path(source): Path<String>,
|
||||
State(state): State<AppState>,
|
||||
) -> Result<Json<wxbox_common::GribTileMetadata>, AppError> {
|
||||
// is this even a valid data source?
|
||||
let data_id = DataId {
|
||||
source,
|
||||
};
|
||||
let data_id = DataId { source };
|
||||
let Some(ds) = state.config.data.grib2.get(&data_id.source) else {
|
||||
return Err(anyhow!("invalid/unknown grib2 state").into());
|
||||
};
|
||||
|
@ -185,10 +179,7 @@ async fn render_to_png(
|
|||
|
||||
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]));
|
||||
|
||||
color
|
||||
colorize(nearest_value, &data_source).unwrap_or(Rgba::from([0, 0, 0, 0]))
|
||||
})
|
||||
.collect::<Vec<_>>()
|
||||
})
|
||||
|
|
|
@ -2,25 +2,22 @@ mod config;
|
|||
mod error;
|
||||
mod grib2;
|
||||
mod nexrad;
|
||||
mod tiles;
|
||||
mod nexrad_list_response;
|
||||
mod tiles;
|
||||
|
||||
use crate::config::Config;
|
||||
use crate::grib2::{Grib2DataCache, Grib2TileCache, grib2_handler, grib2_metadata};
|
||||
use crate::nexrad::{NexradDataCache, NexradTileCache, nexrad_handler};
|
||||
use crate::tiles::{DataId, TileId};
|
||||
use axum::Router;
|
||||
use axum::http::Method;
|
||||
use axum::routing::get;
|
||||
use moka::future::Cache;
|
||||
use std::env::args;
|
||||
use std::fmt::{Debug, Formatter};
|
||||
use std::sync::Arc;
|
||||
use axum::http::Method;
|
||||
use tower_http::cors::{Any, CorsLayer};
|
||||
use tracing_subscriber::EnvFilter;
|
||||
use tracing_subscriber::fmt::format::FmtSpan;
|
||||
use tracing_subscriber::util::SubscriberInitExt;
|
||||
use wxbox_grib2::GribMessage;
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct AppState {
|
||||
|
|
|
@ -1,11 +1,12 @@
|
|||
use crate::AppState;
|
||||
use crate::error::AppError;
|
||||
use crate::nexrad_list_response::ListBucketResult;
|
||||
use crate::tiles::{DataId, TileId};
|
||||
use anyhow::{anyhow, bail};
|
||||
use axum::extract::{Path, State};
|
||||
use axum::http::{StatusCode, header};
|
||||
use axum::http::header;
|
||||
use axum::response::IntoResponse;
|
||||
use flate2::read::GzDecoder;
|
||||
use chrono::{Datelike, Utc};
|
||||
use geographiclib::Geodesic;
|
||||
use image::codecs::png::PngEncoder;
|
||||
use image::{Rgba, RgbaImage};
|
||||
|
@ -16,19 +17,13 @@ use serde::{Deserialize, Serialize};
|
|||
use std::collections::HashMap;
|
||||
use std::f64::consts::PI;
|
||||
use std::fmt::Debug;
|
||||
use std::{fs, io};
|
||||
use std::io::{Cursor, ErrorKind};
|
||||
use std::num::TryFromIntError;
|
||||
use std::io;
|
||||
use std::io::ErrorKind;
|
||||
use std::sync::Arc;
|
||||
use chrono::{Datelike, Utc};
|
||||
use tokio::io::AsyncReadExt;
|
||||
use tracing::{debug, info_span};
|
||||
use wxbox_ar2::sites::wsr88d::{SITES, Wsr88dSite};
|
||||
use wxbox_ar2::{MomentValue, Radial, Scan, Sweep, parse};
|
||||
use wxbox_grib2::GribMessage;
|
||||
use wxbox_grib2::wgs84::LatLong;
|
||||
use wxbox_pal::{ColorPalette, Palette};
|
||||
use crate::nexrad_list_response::ListBucketResult;
|
||||
use wxbox_pal::ColorPalette;
|
||||
|
||||
pub type NexradDataCache = Cache<DataId, Arc<wxbox_ar2::Scan>>;
|
||||
pub type NexradTileCache = Cache<TileId, Arc<Vec<u8>>>;
|
||||
|
@ -92,8 +87,14 @@ pub async fn nexrad_handler(
|
|||
|
||||
// we know we need to build the tile, so let's do that now
|
||||
// it also returns it, so we can conveniently return it right now
|
||||
let pixel_data =
|
||||
render_to_png(state.nexrad_tile_cache.clone(), data, tile_id, &site, ds.clone()).await?;
|
||||
let pixel_data = render_to_png(
|
||||
state.nexrad_tile_cache.clone(),
|
||||
data,
|
||||
tile_id,
|
||||
&site,
|
||||
ds.clone(),
|
||||
)
|
||||
.await?;
|
||||
|
||||
Ok((
|
||||
[(header::CONTENT_TYPE, "image/png")],
|
||||
|
@ -104,23 +105,24 @@ pub async fn nexrad_handler(
|
|||
async fn load_nexrad_data(
|
||||
cache: NexradDataCache,
|
||||
data_id: DataId,
|
||||
data_source: NexradDataSource,
|
||||
_data_source: NexradDataSource,
|
||||
site: &str,
|
||||
) -> anyhow::Result<Arc<Scan>> {
|
||||
let _load_span = info_span!("load_nexrad_data");
|
||||
|
||||
let mut searchdate = Utc::now();
|
||||
|
||||
|
||||
let client = reqwest::Client::new();
|
||||
let mut url;
|
||||
let url;
|
||||
let mut days_went_back = 0;
|
||||
|
||||
'outer: loop {
|
||||
let year = searchdate.year();
|
||||
let month = searchdate.month();
|
||||
let day = searchdate.day();
|
||||
let listing_url = format!("https://noaa-nexrad-level2.s3.amazonaws.com/?list-type=2&delimiter=/&prefix={year}/{month:02}/{day:02}/{site}/");
|
||||
let listing_url = format!(
|
||||
"https://noaa-nexrad-level2.s3.amazonaws.com/?list-type=2&delimiter=/&prefix={year}/{month:02}/{day:02}/{site}/"
|
||||
);
|
||||
debug!("downloading listing from {}", listing_url);
|
||||
let r = client.get(listing_url).send().await?;
|
||||
if !r.status().is_success() {
|
||||
|
@ -135,18 +137,20 @@ async fn load_nexrad_data(
|
|||
// fake. continue
|
||||
continue;
|
||||
} else {
|
||||
debug!("nexrad: found l2 file for {} date {}", site, file.LastModified);
|
||||
debug!(
|
||||
"nexrad: found l2 file for {} date {}",
|
||||
site, file.LastModified
|
||||
);
|
||||
url = format!("https://noaa-nexrad-level2.s3.amazonaws.com/{}", file.Key);
|
||||
break 'outer;
|
||||
}
|
||||
}
|
||||
}
|
||||
searchdate -= chrono::Duration::days(1);
|
||||
days_went_back += 1;
|
||||
if days_went_back > 7 {
|
||||
bail!("no recent radar data");
|
||||
}
|
||||
|
||||
searchdate -= chrono::Duration::days(1);
|
||||
days_went_back += 1;
|
||||
if days_went_back > 7 {
|
||||
bail!("no recent radar data");
|
||||
}
|
||||
}
|
||||
|
||||
let client = reqwest::Client::new();
|
||||
|
@ -169,15 +173,6 @@ async fn load_nexrad_data(
|
|||
const TWO_PI: f64 = PI * 2.0;
|
||||
const HALF_PI: f64 = PI / 2.0;
|
||||
|
||||
const A: f64 = 6_378.1370; // km
|
||||
const B: f64 = 6_356.7523; // km
|
||||
|
||||
fn radius_at_latitude(phi: f64) -> f64 {
|
||||
let top = (A.powi(2) * phi.cos()).powi(2) + (B.powi(2) * phi.sin()).powi(2);
|
||||
let bottom = (A * phi.cos()).powi(2) + (B * phi.sin()).powi(2);
|
||||
(top / bottom).sqrt()
|
||||
}
|
||||
|
||||
fn calculate_inverse(
|
||||
tile_x_times_tilesize: f64,
|
||||
tile_y_times_tilesize: f64,
|
||||
|
@ -241,7 +236,7 @@ async fn render_to_png(
|
|||
let tile_x_times_tilesize = tile_id.x as f64 * tile_id.size as f64;
|
||||
let tile_y_times_tilesize = tile_id.y as f64 * tile_id.size as f64;
|
||||
|
||||
let first_sweep = data.sweeps.get(0).unwrap();
|
||||
let first_sweep = data.sweeps.first().unwrap();
|
||||
let g = Geodesic::wgs84();
|
||||
|
||||
let radar = SITES.sites.get(site).unwrap();
|
||||
|
@ -284,7 +279,7 @@ async fn render_to_png(
|
|||
|
||||
let data = &reflectivity.values;
|
||||
|
||||
if gate > data.len() || gate < 0 {
|
||||
if gate > data.len() {
|
||||
return colorize(None, &data_source).unwrap_or(Rgba::from([0, 0, 0, 0]));
|
||||
}
|
||||
|
||||
|
@ -296,7 +291,7 @@ async fn render_to_png(
|
|||
),
|
||||
});
|
||||
|
||||
return colorize(color, &data_source).unwrap_or(Rgba::from([0, 0, 0, 0]));
|
||||
colorize(color, &data_source).unwrap_or(Rgba::from([0, 0, 0, 0]))
|
||||
})
|
||||
.collect::<Vec<_>>()
|
||||
})
|
||||
|
@ -338,12 +333,7 @@ fn colorize(
|
|||
Some(MomentValue::RangeFolded) => Rgba([119, 0, 125, 255]),
|
||||
Some(MomentValue::Value(value)) => {
|
||||
let color = wxbox_pal::parser::parse(&data_source.palette)?.colorize(value as f64);
|
||||
Rgba([
|
||||
color.red,
|
||||
color.green,
|
||||
color.blue,
|
||||
color.alpha,
|
||||
])
|
||||
Rgba([color.red, color.green, color.blue, color.alpha])
|
||||
}
|
||||
None => Rgba([0, 0, 0, 30]),
|
||||
})
|
||||
|
|
|
@ -3,16 +3,11 @@ use serde::Deserialize;
|
|||
#[derive(Deserialize, Debug)]
|
||||
#[allow(non_snake_case)] // xml
|
||||
pub struct ListBucketResult {
|
||||
pub Name: String,
|
||||
pub Prefix: String,
|
||||
pub KeyCount: usize,
|
||||
pub MaxKeys: usize,
|
||||
|
||||
pub Contents: Option<Vec<ListBucketResultContents>>,
|
||||
}
|
||||
#[derive(Deserialize, Debug)]
|
||||
#[allow(non_snake_case)] // xml
|
||||
pub struct ListBucketResultContents {
|
||||
pub Key: String,
|
||||
pub LastModified: String
|
||||
}
|
||||
pub LastModified: String,
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue