grib/
cookbook.rs

1//! A cookbook of examples for GRIB2 data handling.
2//!
3//! # Table of contents
4//!
5//! 1. [Comparison of various GRIB2 data library/tool operations][cmp]
6//!     * [Listing all submessages inside][cmp-listing]
7//!     * [Finding submessages inside that match some condition][cmp-finding]
8//!     * [Extracting values with location info from a submessage][cmp-decoding]
9//!
10//! [cmp]: #comparison-of-various-grib2-data-librarytool-operations
11//! [cmp-listing]: #listing-all-submessages-inside
12//! [cmp-finding]: #finding-submessages-inside-that-match-some-condition
13//! [cmp-decoding]: #extracting-values-with-location-info-from-a-submessage
14//!
15//! # Comparison of various GRIB2 data library/tool operations
16//!
17//! This section provides example code of data operations using some GRIB
18//! processing libraries and tools.
19//!
20//! ## Listing all submessages inside
21//!
22//! GRIB tools from ecCodes:
23//!
24//! ```shell
25//! $ grib_ls datafile.grib
26//! ```
27//!
28//! wgrib2:
29//!
30//! ```shell
31//! $ wgrib2 datafile.grib
32//! ```
33//!
34//! pygrib:
35//!
36//! ```python
37//! import pygrib
38//!
39//! path = "testdata/icon_global_icosahedral_single-level_2021112018_000_TOT_PREC.grib2"
40//! grib = pygrib.open(path)
41//! for submessage in grib:
42//!     print(submessage)
43//! ```
44//!
45//! grib-rs:
46//!
47//! ```rust
48//! use std::{fs::File, io::BufReader, path::Path};
49//!
50//! use grib::codetables::{CodeTable4_2, Lookup};
51//!
52//! fn list_submessages<P>(path: P)
53//! where
54//!     P: AsRef<Path>,
55//! {
56//!     let f = File::open(path).unwrap();
57//!     let f = BufReader::new(f);
58//!
59//!     let grib2 = grib::from_reader(f).unwrap();
60//!
61//!     for (_index, submessage) in grib2.iter() {
62//!         let discipline = submessage.indicator().discipline;
63//!         let category = submessage.prod_def().parameter_category().unwrap();
64//!         let parameter = submessage.prod_def().parameter_number().unwrap();
65//!         let parameter = CodeTable4_2::new(discipline, category).lookup(usize::from(parameter));
66//!
67//!         let forecast_time = submessage.prod_def().forecast_time().unwrap();
68//!
69//!         let (first, _second) = submessage.prod_def().fixed_surfaces().unwrap();
70//!         let elevation_level = first.value();
71//!
72//!         println!(
73//!             "{:<31} {:>14} {:>17}",
74//!             parameter.to_string(),
75//!             forecast_time.to_string(),
76//!             elevation_level
77//!         );
78//!     }
79//! }
80//!
81//! fn main() {
82//!     let path = "testdata/icon_global_icosahedral_single-level_2021112018_000_TOT_PREC.grib2";
83//!     list_submessages(&path);
84//! }
85//! ```
86//!
87//! gribber:
88//!
89//! ```shell
90//! $ gribber list datafile.grib
91//! ```
92//!
93//! ## Finding submessages inside that match some condition
94//!
95//! GRIB tools from ecCodes:
96//!
97//! ```shell
98//! $ grib_ls -w forecastTime=0,level=850,shortName=u datafile.grib
99//! ```
100//!
101//! wgrib2:
102//!
103//! ```shell
104//! $ wgrib2 datafile.grib -match ':3 hour fcst:'
105//! ```
106//!
107//! pygrib:
108//!
109//! ```python
110//! import pygrib
111//!
112//! path = "testdata/icon_global_icosahedral_single-level_2021112018_000_TOT_PREC.grib2"
113//! grib = pygrib.open(path)
114//! for submessage in grib.select(forecastTime=3):
115//!     print(submessage)
116//! ```
117//!
118//! grib-rs:
119//!
120//! ```rust
121//! use std::{fs::File, io::BufReader, path::Path};
122//!
123//! use grib::{codetables::grib2::*, ForecastTime, Name};
124//!
125//! fn find_submessages<P>(path: P, forecast_time_hours: u32)
126//! where
127//!     P: AsRef<Path>,
128//! {
129//!     let f = File::open(path).unwrap();
130//!     let f = BufReader::new(f);
131//!
132//!     let grib2 = grib::from_reader(f).unwrap();
133//!
134//!     for (index, submessage) in grib2.iter() {
135//!         let ft = submessage.prod_def().forecast_time();
136//!         match ft {
137//!             Some(ForecastTime {
138//!                 unit: Name(Table4_4::Hour),
139//!                 value: hours,
140//!             }) => {
141//!                 if hours == forecast_time_hours {
142//!                     println!("{}.{}: {}", index.0, index.1, hours);
143//!                 }
144//!             }
145//!             _ => {}
146//!         }
147//!     }
148//! }
149//!
150//! fn main() {
151//!     let path = "testdata/icon_global_icosahedral_single-level_2021112018_000_TOT_PREC.grib2";
152//!     find_submessages(&path, 3);
153//! }
154//! ```
155//!
156//! gribber:
157//!
158//! ```shell
159//! $ gribber list datafile.grib | grep '3 Hour'
160//! ```
161//!
162//! (gribber's API for finding submessages is still in the conceptual stage and
163//! is not yet available.)
164//!
165//! ## Extracting values with location info from a submessage
166//!
167//! GRIB tools from ecCodes:
168//!
169//! ```shell
170//! $ grib_get_data -w forecastTime=0,count=1 datafile.grib
171//! ```
172//!
173//! wgrib2 (creating a flat binary file of values):
174//!
175//! ```shell
176//! $ wgrib2 -d 1.1 -order we:ns -no_header -bin output.bin datafile.grib
177//! ```
178//!
179//! pygrib:
180//!
181//! ```python
182//! import pygrib
183//!
184//! path = "datafile.grib"
185//! grib = pygrib.open(path)
186//! submessage = grib.message(1)
187//! lats, lons = submessage.latlons()
188//! values = submessage.values
189//! print((lats, lons, values))
190//! ```
191//!
192//! grib-rs:
193//!
194//! ```rust
195//! use std::{
196//!     fs::File,
197//!     io::{BufReader, Read, Write},
198//!     path::Path,
199//! };
200//!
201//! use grib::codetables::{grib2::*, *};
202//!
203//! fn decode_layer<P>(path: P, message_index: (usize, usize))
204//! where
205//!     P: AsRef<Path>,
206//! {
207//!     let f = File::open(path).unwrap();
208//!     let f = BufReader::new(f);
209//!
210//!     let grib2 = grib::from_reader(f).unwrap();
211//!     let (_index, submessage) = grib2
212//!         .iter()
213//!         .find(|(index, _)| *index == message_index)
214//!         .ok_or("no such index")
215//!         .unwrap();
216//!
217//!     let latlons = submessage.latlons().unwrap();
218//!     let decoder = grib::Grib2SubmessageDecoder::from(submessage).unwrap();
219//!     let values = decoder.dispatch().unwrap();
220//!
221//!     for ((lat, lon), value) in latlons.zip(values) {
222//!         println!("{lat} {lon} {value}");
223//!     }
224//! }
225//!
226//! fn main() {
227//!     let path = "testdata/gdas.t12z.pgrb2.0p25.f000.0-10.xz";
228//!
229//!     let mut buf = Vec::new();
230//!     let mut out = tempfile::NamedTempFile::new().unwrap();
231//!
232//!     let f = File::open(path).unwrap();
233//!     let f = BufReader::new(f);
234//!     let mut f = xz2::bufread::XzDecoder::new(f);
235//!     f.read_to_end(&mut buf).unwrap();
236//!     out.write_all(&buf).unwrap();
237//!
238//!     decode_layer(&out.path(), (0, 0));
239//! }
240//! ```
241//!
242//! gribber (showing values along with lat/lon info):
243//!
244//! ```shell
245//! $ gribber decode datafile.grib 0.0
246//! ```
247//!
248//! gribber (creating a flat binary file of values):
249//!
250//! ```shell
251//! $ gribber decode -b output.bin datafile.grib 0.0
252//! ```