Core Concepts
The package is easiest to understand if you keep three objects in mind:
Atmosphere: one timestep of atmospheric conditionsWeather: a convenient constructor for weather tables made ofAtmosphererowsTimeStepTable: the underlying table abstraction used across the package
Atmosphere: One Timestep
using PlantMeteo
using Dates
row = Atmosphere(
date = DateTime(2025, 7, 1, 12),
duration = Hour(1),
T = 24.0,
Wind = 1.8,
Rh = 0.58,
P = 101.3,
Ri_SW_f = 620.0
)
rowAtmosphere(date = DateTime("2025-07-01T12:00:00"), duration = Hour(1), T = 24.0, Wind = 1.8, P = 101.3, Rh = 0.58, Precipitations = 0.0, Cₐ = 400.0, e = 1.7373682725833977, eₛ = 2.9954625389368927, VPD = 1.258094266353495, ρ = 1.1875807472771054, λ = 2.44424e6, γ = 0.06749702930430417, ε = 0.5946170191650276, Δ = 0.18041050771926415, Ri_SW_f = 620.0)An Atmosphere row stores one weather timestep. Some variables are mandatory (T, Wind, Rh), while others are optional or can be computed from those core inputs.
Construction is strict by default. Invalid wind, humidity, or pressure throws an error before dependent variables are computed. check=false skips these checks but does not clamp wind, divide humidity by 100, convert pressure, or otherwise change the supplied values. Physical zero remains valid for calm wind, dry air, darkness, and zero incoming radiation.
Optional clearness and Ri_*_f forcing is structural. If a keyword is omitted, the property is absent; if the source explicitly contains a missing value, pass missing and the property remains present. PlantMeteo does not use Inf to mean "not supplied".
Weather: A Convenient Weather Constructor
weather = Weather(
[
row,
Atmosphere(
date = DateTime(2025, 7, 1, 13),
duration = Hour(1),
T = 25.0,
Wind = 2.0,
Rh = 0.55,
P = 101.3,
Ri_SW_f = 580.0
),
],
(site = "demo", source = "synthetic")
)
weather| TimeStepTable{Atmosphere{(:date, :duration,...}(2 x 17): | |||||||||||||||||
| date | duration | T | Wind | P | Rh | Precipitations | Cₐ | e | eₛ | VPD | ρ | λ | γ | ε | Δ | Ri_SW_f | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| DateTime | Hour | Float64 | Float64 | Float64 | Float64 | Float64 | Float64 | Float64 | Float64 | Float64 | Float64 | Float64 | Float64 | Float64 | Float64 | Float64 | |
| 1 | 2025-07-01T12:00:00 | 1 hour | 24.0 | 1.8 | 101.3 | 0.58 | 0.0 | 400.0 | 1.73737 | 2.99546 | 1.25809 | 1.18758 | 2.44424e6 | 0.067497 | 0.594617 | 0.180411 | 620.0 |
| 2 | 2025-07-01T13:00:00 | 1 hour | 25.0 | 2.0 | 101.3 | 0.55 | 0.0 | 400.0 | 1.74911 | 3.1802 | 1.43109 | 1.1836 | 2.44188e6 | 0.0675624 | 0.594904 | 0.190095 | 580.0 |
Weather is usually the easiest way to say "this is a weather table made of atmospheric rows". If an optional forcing exists on only some input rows, Weather keeps one stable union schema and inserts missing in the other rows. A forcing omitted from every row remains structurally absent from the whole table.
TimeStepTable: The Shared Table Abstraction
Weather is built on top of TimeStepTable, which exposes row access, column access, metadata, and the Tables.jl interface.
weather[1]╭──── TimeStepRow ─────────────────────────────────────────────────────────────╮
│ Step 1: date=2025-07-01T12:00:00, duration=1 hour, T=24.0, Wind=1.8, │
│ P=101.3, Rh=0.58, Precipitations=0.0, Cₐ=400.0, e=1.7373682725833977, │
│ eₛ=2.9954625389368927 ... │
╰──────────────────────────────────────────────────────────────────────────────╯weather[:T]2-element Vector{Float64}:
24.0
25.0weather[2, :T]25.0metadatakeys(weather)("site", "source")This is what makes the rest of the package coherent: whether the data came from an API, a CSV file, or a synthetic example, you work with the same table abstraction afterward.
Metadata
Metadata is attached to the table, not to each row:
metadata(weather)Dict{String, String} with 2 entries:
"source" => "synthetic"
"site" => "demo"This is useful for keeping site information, provenance, or source notes attached to the weather series. PlantMeteo preserves metadata values from imported files without interpreting them. Column transformations apply only to table columns: they never parse or rename metadata values. Downstream code may interpret a metadata key only when that behavior is part of its documented API; otherwise the value remains source provenance.
Variables And Units
PlantMeteo expects canonical variable names and units in Atmosphere rows. For example:
T: air temperature in degrees CelsiusRh: relative humidity in 0-1 unitsWind: wind speed in m s-1P: air pressure in kPaRi_SW_f: incoming short-wave radiation flux in W m-2
This is why read_weather matters: local files rarely arrive with these exact names and units. Declare non-canonical humidity and pressure units with input_units, or call normalize_weather_import directly. Conversion is never guessed from the magnitude of a value. Imported tables append a YAML-safe provenance record that lists the conversions applied without discarding earlier import history.
What Comes Next
- Use Getting Weather Data to build a
Weathertable from an API or a local file. - Use Daily Aggregation when you want one row per day.
- Use Weather Sampling when you want model-aligned windows instead of fixed daily rows.