126 lines
4.3 KiB
Rust
126 lines
4.3 KiB
Rust
use clap::Parser;
|
|
use log::{debug, info, LevelFilter};
|
|
use std::collections::HashMap;
|
|
use std::fs::File;
|
|
use std::io::{Read, Write};
|
|
|
|
#[derive(Parser)]
|
|
#[command(author, version, about, long_about = None)]
|
|
struct Cli {
|
|
/// Path to the Archive II file to process
|
|
#[arg(required = true)]
|
|
file_path: String,
|
|
|
|
/// Path to save the output CSV file (defaults to 'elevation_angles.csv')
|
|
#[arg(default_value = "elevation_angles.csv")]
|
|
output_path: String,
|
|
}
|
|
|
|
#[tokio::main]
|
|
async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
|
// Initialize logging
|
|
env_logger::Builder::from_env(env_logger::Env::default().default_filter_or("info"))
|
|
.filter_module("reqwest::connect", LevelFilter::Info)
|
|
.init();
|
|
|
|
// Parse command line arguments
|
|
let cli = Cli::parse();
|
|
let file_path = &cli.file_path;
|
|
let output_path = &cli.output_path;
|
|
|
|
info!("Processing file: {}", file_path);
|
|
|
|
// Read the file
|
|
let mut file =
|
|
File::open(file_path).unwrap_or_else(|_| panic!("Failed to open file: {}", file_path));
|
|
let mut buffer = Vec::new();
|
|
file.read_to_end(&mut buffer)?;
|
|
|
|
// Parse the Archive II file
|
|
let volume_file = nexrad_data::volume::File::new(buffer);
|
|
|
|
// Create a HashMap to store elevation angles by elevation and azimuth numbers
|
|
// Key: (elevation_number, azimuth_number), Value: elevation_angle
|
|
let mut elevation_angles: HashMap<(u8, u16), f32> = HashMap::new();
|
|
|
|
// Maximum elevation number and azimuth number for CSV dimensions
|
|
let mut max_elevation_num = 0;
|
|
let mut max_azimuth_num = 0;
|
|
|
|
// Process all records in the file
|
|
for mut record in volume_file.records() {
|
|
debug!("Processing record...");
|
|
if record.compressed() {
|
|
debug!("Decompressing LDM record...");
|
|
record = record.decompress().expect("Failed to decompress record");
|
|
}
|
|
|
|
// Extract messages from the record
|
|
let messages = record.messages()?;
|
|
|
|
// Process each message to extract elevation angles
|
|
for message in messages {
|
|
// Check if the message is a Digital Radar Data message
|
|
if let nexrad_decode::messages::MessageContents::DigitalRadarData(digital_data) =
|
|
message.contents()
|
|
{
|
|
// Access header information where the elevation data is stored
|
|
let header = &digital_data.header;
|
|
|
|
let elevation_num = header.elevation_number;
|
|
let azimuth_num = header.azimuth_number;
|
|
let elevation_angle = header.elevation_angle;
|
|
|
|
// Update max values for dimensions
|
|
if elevation_num > max_elevation_num {
|
|
max_elevation_num = elevation_num;
|
|
}
|
|
if azimuth_num > max_azimuth_num {
|
|
max_azimuth_num = azimuth_num;
|
|
}
|
|
|
|
// Store elevation angle information
|
|
elevation_angles.insert((elevation_num, azimuth_num), elevation_angle);
|
|
debug!(
|
|
"Elevation: {}, Azimuth Number: {}, Elevation Angle: {}",
|
|
elevation_num, azimuth_num, elevation_angle
|
|
);
|
|
}
|
|
}
|
|
}
|
|
|
|
info!(
|
|
"Found elevation angles for {} elevation-azimuth combinations",
|
|
elevation_angles.len()
|
|
);
|
|
info!("Maximum elevation number: {}", max_elevation_num);
|
|
info!("Maximum azimuth number: {}", max_azimuth_num);
|
|
|
|
// Create and write the CSV file
|
|
let mut output_file = File::create(output_path)?;
|
|
|
|
// Write header with elevation numbers
|
|
write!(output_file, "azimuth_num")?;
|
|
for elev in 1..=max_elevation_num {
|
|
write!(output_file, ",elev_{}", elev)?;
|
|
}
|
|
writeln!(output_file)?;
|
|
|
|
// Write rows for each azimuth number
|
|
for azimuth_num in 1..=max_azimuth_num {
|
|
write!(output_file, "{}", azimuth_num)?;
|
|
|
|
// For each elevation in this azimuth number, write the elevation angle
|
|
for elev_num in 1..=max_elevation_num {
|
|
match elevation_angles.get(&(elev_num, azimuth_num)) {
|
|
Some(angle) => write!(output_file, ",{:.2}", angle)?,
|
|
None => write!(output_file, ",")?, // Empty value if no data for this combination
|
|
}
|
|
}
|
|
writeln!(output_file)?;
|
|
}
|
|
|
|
info!("CSV file created successfully: {}", output_path);
|
|
|
|
Ok(())
|
|
}
|