pub fn summarize_file(path: &Path) -> Result<FileSummary, String>Expand description
Summarize a GRIB file into FileSummary / MessageSummary for diagnostics.
Examples found in repository?
examples/extract_param.rs (line 28)
13fn main() -> Result<(), Box<dyn Error>> {
14 let args: Vec<_> = env::args_os().skip(1).collect();
15 if args.len() < 4 {
16 eprintln!("usage: extract_param <file.grib2> <param> <lon> <lat>");
17 eprintln!("example: extract_param data.grib2 msl 113.363 22.962");
18 return Ok(());
19 }
20
21 let file_s = args[0].to_string_lossy().to_string();
22 let path = Path::new(&file_s);
23 let param = args[1].to_string_lossy().to_string();
24 let lon: f64 = args[2].to_string_lossy().parse()?;
25 let lat: f64 = args[3].to_string_lossy().parse()?;
26
27 println!("Summarizing file: {}", path.display());
28 let fs = summarize_file(path)?;
29 for m in fs.messages.iter().take(10) {
30 println!("msg {}: key='{}' repr={:?} payload_len={} decode_ok={}", m.message_index, m.key, m.repr_template, m.payload_len, m.decode_ok);
31 }
32
33 println!("\nFinding candidates for param '{}':", param);
34 let candidates = find_candidates_for_param(path, ¶m)?;
35
36 // Read grid early so fallback paths can use it
37 let grid = read_first_grib2_latlon_grid(path)?;
38
39 if candidates.is_empty() {
40 println!("No candidates found for '{}'. Trying filename prefix fallback...", param);
41 // Try filename prefix fallback using the ParamAlias file_prefixes
42 let alias = rust_grib_decoder::param_alias::ParamAlias::for_param(¶m);
43 if let Some(fname) = path.file_name().and_then(|s| s.to_str()) {
44 for prefix in alias.file_prefixes.iter() {
45 if fname.starts_with(prefix) {
46 println!("Filename '{}' starts with prefix '{}', attempting message 0 decode", fname, prefix);
47 // Try to decode message 0 using template42 Section5 params if present
48 let params_vec = read_grib2_section5_template42_params_by_message(path)?;
49 if let Some(Some(params)) = params_vec.get(0) {
50 if let Ok(values) = decode_template42_try_message_payload(path, 0, grid.ni, grid.nj, params) {
51 let val = interp_value(&values, grid.ni, grid.nj, grid.lon1_deg, grid.lat1_deg, grid.di_deg, grid.dj_deg, lon, lat);
52 println!("Decoded {} samples from message 0 — interpolated value at {}x{} = {}", values.len(), lon, lat, val);
53 return Ok(());
54 } else {
55 eprintln!("template42 rust-aec decode failed for message 0");
56 }
57 }
58 #[cfg(feature = "grib-support")]
59 {
60 use grib::{from_reader, Grib2SubmessageDecoder};
61 use std::fs::File;
62 use std::io::BufReader;
63 let f = File::open(path)?;
64 let r = BufReader::new(f);
65 let grib2 = from_reader(r)?;
66 for ((midx, _sidx), sub) in grib2.iter() {
67 if midx == 0 {
68 let (w, h) = sub.grid_shape()?;
69 let decoder = Grib2SubmessageDecoder::from(sub)?;
70 match decoder.dispatch() {
71 Ok(decoded) => {
72 let vals: Vec<f32> = decoded.collect();
73 let val = interp_value(&vals, w, h, grid.lon1_deg, grid.lat1_deg, grid.di_deg, grid.dj_deg, lon, lat);
74 println!("grib crate decoded {} samples (msg 0) — interpolated value = {}", vals.len(), val);
75 return Ok(());
76 }
77 Err(e) => eprintln!("grib crate decode error (msg 0): {}", e),
78 }
79 }
80 }
81 }
82 }
83 }
84 }
85
86 println!("No decode succeeded using filename prefix fallback.");
87 return Ok(());
88 }
89
90 for (idx, reason, key, ft) in candidates.iter().take(3) {
91 println!("candidate: msg={} reason={:?} key='{}' ft={:?}", idx, reason, key, ft);
92 }
93
94 // Choose the first candidate and attempt to decode it
95 let (msg_idx, _, key, _ft) = &candidates[0];
96 println!("\nAttempting to decode candidate msg {} ('{}')", msg_idx, key);
97
98 let grid = read_first_grib2_latlon_grid(path)?;
99 println!("Grid: {}x{} lon1={} lat1={} di={} dj={}", grid.ni, grid.nj, grid.lon1_deg, grid.lat1_deg, grid.di_deg, grid.dj_deg);
100
101 // Try template-42 rust-aec decode using Section5 params if available
102 let params_vec = read_grib2_section5_template42_params_by_message(path)?;
103 if let Some(Some(params)) = params_vec.get(*msg_idx) {
104 println!("Found template42 params for msg {} — trying rust-aec decode", msg_idx);
105 match decode_template42_try_message_payload(path, *msg_idx, grid.ni, grid.nj, params) {
106 Ok(values) => {
107 let val = interp_value(&values, grid.ni, grid.nj, grid.lon1_deg, grid.lat1_deg, grid.di_deg, grid.dj_deg, lon, lat);
108 println!("Decoded {} samples — interpolated value at {}x{} = {}", values.len(), lon, lat, val);
109 return Ok(());
110 }
111 Err(e) => eprintln!("rust-aec decode failed: {}", e),
112 }
113 }
114
115 #[cfg(feature = "grib-support")]
116 {
117 println!("Attempting to decode using `grib` crate for msg {}", msg_idx);
118 use std::fs::File;
119 use std::io::BufReader;
120 let f = File::open(path)?;
121 let r = BufReader::new(f);
122 let grib2 = from_reader(r)?;
123 for ((midx, _sidx), sub) in grib2.iter() {
124 if midx == *msg_idx {
125 let (w, h) = sub.grid_shape()?;
126 let decoder = Grib2SubmessageDecoder::from(sub)?;
127 match decoder.dispatch() {
128 Ok(decoded) => {
129 let vals: Vec<f32> = decoded.collect();
130 let val = interp_value(&vals, w, h, grid.lon1_deg, grid.lat1_deg, grid.di_deg, grid.dj_deg, lon, lat);
131 println!("grib crate decoded {} samples — interpolated value = {}", vals.len(), val);
132 return Ok(());
133 }
134 Err(e) => eprintln!("grib crate decode error: {}", e),
135 }
136 }
137 }
138 }
139
140 println!("Could not decode the selected message (no template42 params and grib-support not enabled or decoding failed).");
141 Ok(())
142}