Files
dwd_cloud_cover_rs/README.md
2026-03-03 23:26:05 +01:00

98 lines
3.3 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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 (048) |
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) |
| 12 % | Very light blue |
| 25 % | Light blue |
| 510 % | Medium blue |
| 1020 % | Blue |
| 2050 % | Dark blue |
| 50100 % | 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`.