Core Concepts

The package is easiest to understand if you keep three objects in mind:

  • Atmosphere: one timestep of atmospheric conditions
  • Weather: a convenient constructor for weather tables made of Atmosphere rows
  • TimeStepTable: 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
)

row
Atmosphere(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, clearness = Inf, Ri_SW_f = 620.0, Ri_PAR_f = Inf, Ri_NIR_f = Inf, Ri_TIR_f = Inf, Ri_custom_f = Inf)

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.

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 22):
date duration T Wind P Rh Precipitations Cₐ e eₛ VPD ρ λ γ ε Δ clearness Ri_SW_f Ri_PAR_f Ri_NIR_f Ri_TIR_f Ri_custom_f
DateTime Hour Float64 Float64 Float64 Float64 Float64 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 Inf 620.0 Inf Inf Inf Inf
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 Inf 580.0 Inf Inf Inf Inf
Metadata: `Dict("source" => "synthetic", "site" => "demo")`

Weather is usually the easiest way to say "this is a weather table made of atmospheric rows".

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.0
weather[2, :T]
25.0
metadatakeys(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.

Variables And Units

PlantMeteo expects canonical variable names and units in Atmosphere rows. For example:

  • T: air temperature in degrees Celsius
  • Rh: relative humidity in 0-1 units
  • Wind: wind speed in m s-1
  • P: air pressure in kPa
  • Ri_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.

What Comes Next