Output reference
Hourly grid
icon-uv run writes a compressed NetCDF dataset on native ICON cell centres.
The main dimensions are time and cell; latitude, longitude and model altitude
are cell coordinates. Original cell IDs and the grid UUID are preserved.
For polygon rendering, obtain triangle vertices from the source ICON grid.
NetCDF uses lossless compression and chunked storage, preserving each input variable's dtype. Computed grid diagnostics use float32; float64 atmospheric inputs and coordinates retain their precision and quality flags remain integers. Writing a file does not introduce a separate float64-to-float32 conversion. Scientific UVI values are not rounded to display integers.
| Variable | Units | Meaning |
|---|---|---|
uvi |
1 | Hourly mean all-sky UV Index on an open horizontal surface |
clear_sky_uvi |
1 | UV Index with the same atmosphere and surface but no cloud |
erythemal_direct |
W/m² | Direct erythemal irradiance on a horizontal surface |
erythemal_diffuse |
W/m² | Diffuse erythemal irradiance |
uvi_sample_max |
1 | Largest reconstructed solar-sample UVI within the hour |
effective_cloud_tau550 |
1 | Inferred cloud optical thickness at 550 nm |
cloud_scale |
1 | Scalar extension of the table response where needed |
quality_flag |
bit mask | Calculation conditions listed below |
uvi = 40 * (erythemal_direct + erythemal_diffuse). Direct irradiance here is
horizontal, rather than direct-normal irradiance. The sample maximum and the
hourly mean describe different temporal quantities.
time is the UTC interval midpoint; time_bounds(time, bounds) supplies the
hour's two endpoints. The dataset retains the hourly shortwave forcing, pressure,
ozone, aerosol optical depth and surface state needed to recompute point and
daily products. Attributes record source cycles, input hashes, radiation-table
identity, calculation settings and package version.
Quality flags
Flags are combined by bitwise OR. For example, flag & 64 tests for low-sun
samples; several conditions can apply to the same value.
| Bit | Meaning |
|---|---|
| 1 | Shortwave exceeds the calculated clear-sky response; a scalar extension is used |
| 2 | Shortwave falls below the minimum cloud-table response; a scalar extension is used |
| 4 | Weak or absent solar signal; cloud inversion carries little information |
| 8 | Nonmonotonic cloud response; the earliest bracketing branch is selected |
| 16 | Atmospheric-column adjustment for a point's elevation |
| 32 | Approximate terrain screening applied |
| 64 | A daylight sample has solar zenith angle above 78° |
| 128 | Missing required ICON input; affected UV values are NaN |
These flags describe calculation conditions. Missing driver variables, invalid units and
out-of-range table inputs raise errors; missing input samples remain NaN. Use icon_uv.check_grid to check saved
fields and reconstruct their shortwave forcing:
uv run --no-sync python -m icon_uv.check_grid \
--grid work/uv.nc --output work/grid_check.json
Point forecasts
compute_points(grid, locations.points) returns hourly data indexed by
time, poi, with a member axis for ensembles. The location API
defines point matching, default ICON-derived albedo and optional site overrides.
Output retains target and source coordinates/elevations, source cell ID/distance,
treatment, effective UV albedo and supplied horizon.
Pressure is adjusted to target elevation using an 8434 m scale height. The source cell supplies cloud state, ozone and aerosol. The radiation table must match the source grid's table identity. Inherited albedo retains time/member variation; explicit fixed albedo is recorded with the point's effective surface state.
uvi and clear_sky_uvi describe ambient horizontal UV. With a supplied horizon,
terrain_screened_uvi blocks direct sunlight below the horizon and scales diffuse
irradiance by the isotropic sky-view factor, mean(cos(horizon)²). Without a
horizon, the screened field is unavailable (NaN). Terrain reflection and
anisotropic diffuse radiation are omitted. Elevation adjustment retains the
source cloud column and does not infer whether a summit lies above clouds.
The Davos example
is the supplied site example: 72 horizon samples at 5° azimuth spacing, extracted
from swisstopo terrain profiles
on 5 September 2026 using a 20 km radius and 401 samples per ray. Horizon angles
are rounded to 0.01°; point altitude is 1588.2 m. UV albedo 0.05 is an explicit
assumption. This is terrain-derived example geometry, not a surveyed instrument
installation or measured albedo. load_locations accepts this point catalog
for both hourly and daily calculations.
Daily JSON
See daily products for the catalog format, aggregation,
statuses and schema. Daily values are reconstructed rolling peaks; taking the
maximum of uvi would instead produce a maximum of clock-hour means.
Comparing observations
icon_uv.products.compare_observations(forecast, observations) returns matched
bias, MAE and RMSE. Both inputs need uvi(time, poi) in units 1, unique named
coordinates and identical hourly time_bounds. Observation data also need
boolean qc_good(time, poi). The caller supplies the instrument-specific unit,
time-support and quality-control adaptation. Comparisons use shared times and
points, excluding missing values and observations with qc_good=False.
Ensemble dimensions
With the default ensemble download, member-dependent ICON and UV fields have
(member, time, cell) dimensions; POI forecasts have (member, time, poi).
member identifies CTRL 0 and perturbed members 1–20. Native coordinates, time_bounds(time, bounds), and interpolated CAMS
ozone_du(time, cell) / aod550(time, cell) are shared across members. Attributes record the expected member
IDs and the minimum coverage fraction. Missing samples remain NaN with quality
flag 128; daily reductions require 90% complete member products by default.
For hourly point or grid summaries, reduce the computed UV values across
member and mask insufficient coverage, for example
points.uvi.median("member").where(points.uvi.count("member") >= 19) for the
default 21-member request. Adapt the count if you change the coverage threshold. For a daily
UV Index product, use daily export: it
computes member daily peaks before reduction. Averaging atmospheric inputs first
would lose cloud uncertainty and alter the nonlinear UV calculation.
Download with fetch-icon --control to retain the original single-member
(time, cell) / (time, poi) layout. Existing CTRL files remain supported.