| Crates.io | ecmwf-opendata |
| lib.rs | ecmwf-opendata |
| version | 0.1.4 |
| created_at | 2025-12-26 11:20:26.519133+00 |
| updated_at | 2025-12-29 14:43:12.413708+00 |
| description | Rust client for ECMWF Open Data (MARS-like requests, URL resolution, and downloads including .index range selection). |
| homepage | |
| repository | https://github.com/hkwk/ecmwf-opendata |
| max_upload_size | |
| id | 2005594 |
| size | 155,877 |
Rust client for ECMWF Open Data.
API documentation (docs.rs): https://docs.rs/ecmwf-opendata
This crate is a Rust re-implementation of the core functionality of the upstream Python project ecmwf-opendata:
.index sidecar using HTTP Range requestsChinese documentation: see README.zh-CN.md.
cargo add ecmwf-opendata
Client(...) optionsPython:
client = Client(
source="ecmwf",
model="ifs",
resol="0p25",
preserve_request_order=False,
infer_stream_keyword=True,
)
Rust:
use ecmwf_opendata::{Client, ClientOptions};
let opts = ClientOptions {
source: "ecmwf".to_string(),
model: "ifs".to_string(),
resol: "0p25".to_string(),
preserve_request_order: false,
infer_stream_keyword: true,
..ClientOptions::default()
};
let client = Client::new(opts)?;
# Ok::<(), ecmwf_opendata::Error>(())
source can be a known mirror ("ecmwf", "aws", "azure", "google") or a custom base URL ("https://...").
use ecmwf_opendata::{Client, ClientOptions, Request};
let client = Client::new(ClientOptions::default())?;
let req = Request::new()
.r#type("fc")
.param("msl")
.step(240)
.target("data.grib2");
let result = client.retrieve_request(req)?;
println!("Downloaded {} bytes", result.size_bytes);
# Ok::<(), ecmwf_opendata::Error>(())
retrieve_pairs: strongest “kwargs/dict” feeluse ecmwf_opendata::{Client, ClientOptions};
let client = Client::new(ClientOptions::default())?;
let result = client.retrieve_pairs([
("type", "fc".into()),
("param", "msl".into()),
("step", 240.into()),
("target", "data.grib2".into()),
])?;
println!("{}", result.datetime);
# Ok::<(), ecmwf_opendata::Error>(())
client.retrieve(time=..., ...)use ecmwf_opendata::{Client, ClientOptions, retrieve};
let client = Client::new(ClientOptions::default())?;
let steps: Vec<i32> = (12..=360).step_by(12).collect();
let result = retrieve!(
client,
time = 0,
stream = "enfo",
type = "ep",
step = steps,
levelist = 850,
param = [
"ptsa_gt_1stdev",
"ptsa_gt_1p5stdev",
"ptsa_gt_2stdev",
"ptsa_lt_1stdev",
"ptsa_lt_1p5stdev",
"ptsa_lt_2stdev",
],
target = "data.grib2",
)?;
println!("{}", result.datetime);
# Ok::<(), ecmwf_opendata::Error>(())
If your UI stores values as strings, build a request with Request::from_str_pairs.
use ecmwf_opendata::{Client, ClientOptions, Request};
let client = Client::new(ClientOptions::default())?;
// Example: values come from text fields
let req = Request::from_str_pairs([
("time", "0"),
("stream", "enfo"),
("type", "ep"),
("step", "12,24,36"),
("levelist", "850"),
("param", "tpg1,tpg5,10fgg10"),
("target", "data.grib2"),
]);
let result = client.retrieve_request(req)?;
println!("{}", result.datetime);
# Ok::<(), ecmwf_opendata::Error>(())
This repository also includes a small CLI example (as a Cargo example target).
cargo run --example cli -- retrieve data.grib2
cargo run --example cli -- download data.grib2
A convenience example that mirrors a typical operational script: it spawns threads to download several meteorological variables for grouped forecast step ranges and writes files named
<variable>_<YYYYmmddHH>_<start>-<end>.grib2 under <main_dir>/realtimeforecast/<YYYYmmddHH>/.
Usage:
cargo run --example realtime_forecast -- <main_dir> [<YYYYmmddHH>]
<YYYYmmddHH> is omitted the example picks the nearest 00/12 UTC cycle automatically.10u/srf, 10v/srf, 2t/srf, msl/srf, tp/srf, gh/pl, u/pl, v/pl.Notes:
Client using ClientOptions (see the source in examples/realtime_forecast.rs); edit the source or other fields there to change behavior (e.g. source = "ecmwf" | "aws" | "azure" | "google").latest() probing depends on endpoint availability. If it fails, specify date/time explicitly.