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//! ```