Initial commit
This commit is contained in:
97
README.md
Normal file
97
README.md
Normal file
@@ -0,0 +1,97 @@
|
||||
# cloud_cover
|
||||
|
||||
Downloads total cloud cover (CLCT) predictions from the [DWD open-data
|
||||
server](https://opendata.dwd.de/weather/nwp/icon-d2/grib/) and renders
|
||||
one PNG map per forecast hour, centred on the Brandenburg / Berlin area.
|
||||
|
||||
This is a Rust port of `../cloud_cover_prediction.py`. The output format
|
||||
differs: instead of using PyNGL's contour renderer the Rust version does a
|
||||
direct point-by-point orthographic projection of the ICON-D2 grid onto a
|
||||
bitmap, which avoids every system-library dependency (no CDO, no PyNIO, no
|
||||
PyNGL, no libssl, no libbz2 — the binary is fully self-contained).
|
||||
|
||||
## Usage
|
||||
|
||||
```
|
||||
cloud_cover <ISO_TIMESTAMP> <HOURS>
|
||||
```
|
||||
|
||||
| Argument | Description |
|
||||
|---|---|
|
||||
| `ISO_TIMESTAMP` | Model run time in ISO 8601, e.g. `2026-03-03T18:00:00Z` |
|
||||
| `HOURS` | Number of forecast steps to render (0–48) |
|
||||
|
||||
The timestamp must correspond to an ICON-D2 model run, which is issued
|
||||
every 3 hours starting at 00 UTC (00, 03, 06, 09, 12, 15, 18, 21).
|
||||
|
||||
### Example
|
||||
|
||||
```sh
|
||||
cargo run --release -- "2026-03-03T18:00:00Z" 12
|
||||
```
|
||||
|
||||
Output PNGs are written to `cache/<date>_<hour>UTC/clct_000001.png` …
|
||||
`clct_NNNNNN.png`. Downloaded GRIB2 files are cached in the same directory
|
||||
so that re-running the same timestamp skips the network requests.
|
||||
|
||||
## How it works
|
||||
|
||||
1. **Download** — `reqwest` fetches the bzip2-compressed GRIB2 files from
|
||||
the DWD server. Two coordinate files (`clat`, `clon`) give the latitude
|
||||
and longitude of every point on the ICON-D2 icosahedral grid (~542 000
|
||||
points for Germany). One `clct` file per forecast step contains the
|
||||
total cloud cover percentage at each point.
|
||||
|
||||
2. **Decompress** — `bzip2` decompresses the files in-memory.
|
||||
|
||||
3. **Parse** — A minimal built-in GRIB2 decoder extracts the data values.
|
||||
Only simple packing (data representation template 0) is supported, which
|
||||
is what DWD uses. Grid points that are flagged as absent by the section-6
|
||||
bitmap are set to `NaN` and skipped during rendering.
|
||||
|
||||
4. **Project & render** — Each grid point is projected onto the image plane
|
||||
using an orthographic projection centred on Falkensee (52.56 °N,
|
||||
13.08 °E). Points are painted as 2 × 2 pixel squares, colour-coded by
|
||||
cloud cover percentage. City markers and labels are drawn on top, and a
|
||||
colour-scale legend is shown on the right. `plotters` writes the final
|
||||
PNG.
|
||||
|
||||
## Cloud cover colour scale
|
||||
|
||||
| Cloud cover | Colour |
|
||||
|---|---|
|
||||
| < 1 % | Land background (clear) |
|
||||
| 1–2 % | Very light blue |
|
||||
| 2–5 % | Light blue |
|
||||
| 5–10 % | Medium blue |
|
||||
| 10–20 % | Blue |
|
||||
| 20–50 % | Dark blue |
|
||||
| 50–100 % | Very dark blue |
|
||||
|
||||
## Marked locations
|
||||
|
||||
Falkensee · Pausin · Nauen · Hennigsdorf · Ketzin/Brückenkopf · Potsdam ·
|
||||
Berlin (Mitte)
|
||||
|
||||
## Dependencies
|
||||
|
||||
All dependencies are pure Rust or vendored C code compiled into the binary.
|
||||
No system shared libraries are required at runtime beyond libc.
|
||||
|
||||
| Crate | Role |
|
||||
|---|---|
|
||||
| `reqwest` (rustls-tls) | HTTP client with pure-Rust TLS |
|
||||
| `bzip2` | bzip2 decompression (vendors libbzip2) |
|
||||
| `plotters` + `plotters-bitmap` | PNG rendering with built-in bitmap font |
|
||||
| `clap` | CLI argument parsing |
|
||||
| `chrono` | Date/time handling |
|
||||
| `anyhow` | Error propagation |
|
||||
|
||||
## Building
|
||||
|
||||
```sh
|
||||
cd cloud_cover_rs
|
||||
cargo build --release
|
||||
```
|
||||
|
||||
The compiled binary ends up at `target/release/cloud_cover`.
|
||||
Reference in New Issue
Block a user