Quickstart

This quickstart starts with the most common pain point: getting usable weather from coordinates and dates. The examples below use PlantMeteo.DemoAPI(), a built-in offline backend for tests and documentation, so the code stays reproducible. It is not a real weather provider. For actual downloads, use the built-in OpenMeteo backend (which is the default).

1. Download Weather Into A Typed Table

We can use get_weather to download weather for a location and period:

using PlantMeteo
using Dates
using Statistics

period = Date(2025, 7, 1):Day(1):Date(2025, 7, 2)
weather = get_weather(48.8566, 2.3522, period; api = PlantMeteo.DemoAPI())
weather[1:4]
TimeStepTable{Atmosphere{(:date, :duration,...}(4 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-01T00:00:00 1 hour 20.0 1.3 101.3 0.65 0.0 415.0 1.52555 2.347 0.821448 1.20379 2.4537e6 0.0672368 0.584806 0.145734 0.0
2 2025-07-01T01:00:00 1 hour 21.2941 1.29659 101.3 0.611177 0.0 415.0 1.5535 2.54181 0.988315 1.19849 2.45064e6 0.0673208 0.585956 0.156273 0.0
3 2025-07-01T02:00:00 1 hour 22.5 1.2866 101.3 0.575 0.0 415.0 1.57317 2.73596 1.16278 1.19361 2.44779e6 0.0673992 0.586667 0.166668 0.0
4 2025-07-01T03:00:00 1 hour 23.5355 1.27071 101.3 0.543934 0.0 415.0 1.58443 2.9129 1.32847 1.18944 2.44534e6 0.0674667 0.586972 0.176056 0.0
Metadata: `Dict{String, Any}("latitude" => 48.8566, "source" => "demo-api", "longitude" => 2.3522)`

get_weather returns a Weather-like TimeStepTable that you can inspect row-wise or column-wise.

2. Inspect The Variables You Will Feed To The Model

TimeStepTable is a custom table type that is optimized for weather sampling. It has a row-oriented design, so it is efficient to access rows of weather data for sampling. Each row corresponds to a timestep in the original data, and the columns correspond to the variables at that timestep.

We can inspect the variables in the table by indexing rows like a vector, e.g. weather[1] is the first row, which is a TimeStepRow struct with fields for each variable:

weather[1]
╭──── TimeStepRow ─────────────────────────────────────────────────────────────╮
  Step 1: date=2025-07-01T00:00:00, duration=1 hour, T=20.0, Wind=1.3,        
  P=101.3, Rh=0.65, Precipitations=0.0, Cₐ=415.0, e=1.5255470730405223,       
  eₛ=2.3469954969854188 ...                                                   
╰──────────────────────────────────────────────────────────────────────────────╯

You can then inspect the variables in that row by field access, e.g. weather[1].date is the date at the first timestep:

weather[1].date
2025-07-01T00:00:00

Similarly, you can access any variable in that row:

weather[1].T
20.0

You can also use a column-oriented design to access variables across all rows like a DataFrame, e.g.:

weather[1:3, :T]
3-element Vector{Float64}:
 20.0
 21.294095225512603
 22.5

The table also has metadata keys that describe the site and the source of the data:

metadatakeys(weather)
("latitude", "longitude", "source")

3. Aggregate To One Row Per Day

You can use to_daily when you want to aggregate infra-day data into a standard daily weather table with one row per civil day.

daily = to_daily(weather)
TimeStepTable{Atmosphere{(:date, :duration,...}(2 x 21):
date duration T Wind P Rh Precipitations Cₐ e eₛ VPD ρ λ γ ε Δ Ri_SW_f year dayofyear Tmin Tmax
Date Day Float64 Float64 Float64 Float64 Float64 Float64 Float64 Float64 Float64 Float64 Float64 Float64 Float64 Float64 Float64 Int64 Int64 Float64 Float64
1 2025-07-01 1 day 20.0 1.2 101.3 0.65 1.2 415.0 1.50274 2.39642 0.893674 1.20396 2.4537e6 0.0672376 0.583441 0.148012 17.7741 2025 182 15.0 25.0
2 2025-07-02 1 day 20.8 1.2 101.3 0.65 1.2 415.0 1.57876 2.51709 0.938332 1.20068 2.45181e6 0.0672895 0.587345 0.154521 17.7741 2025 183 15.8 25.8
Metadata: `Dict{String, Any}("latitude" => 48.8566, "source" => "demo-api", "longitude" => 2.3522)`
length(daily)
2
daily[1]
╭──── TimeStepRow ─────────────────────────────────────────────────────────────╮
  Step 1: date=2025-07-01, duration=1 day, T=19.999999999999996, Wind=1.2,    
  P=101.30000000000003, Rh=0.6500000000000001, Precipitations=1.20000000000   
  00002, Cₐ=415.0, e=1.5027425702003174, eₛ=2.3964165011914402 ...            
╰──────────────────────────────────────────────────────────────────────────────╯

4. Sample Weather For A Model Time Window

We can use sample_weather to sample weather for a model time window. This is useful when you have a model that runs on a different time step than the original data, or when you want to apply a custom reducer over a rolling window.

Let's say we have a model that runs on 24-hour time steps, and we want to sample weather for each 24-hour window. We can use sample_weather with a RollingWindow to do this:

prepared = prepare_weather_sampler(weather)
window = RollingWindow(24.0)
sampled = sample_weather(prepared, 24; window = window)
Atmosphere(date = DateTime("2025-07-01T23:00:00"), duration = Millisecond(86400000), T = 20.0, Wind = 1.1999999999999997, P = 101.3, Rh = 0.6500000000000001, Precipitations = 1.2000000000000002, Cₐ = 415.0, e = 1.502742570200317, eₛ = 2.396416501191441, VPD = 0.8936739309911232, ρ = 1.203960293363366, λ = 2.453700000000001e6, γ = 0.0672375819269494, ε = 0.5834413910269151, Δ = 0.1480115968281549, Ri_SW_f = 205.71834055297288, Rhmax = 0.8, Rhmin = 0.5, Ri_SW_q = 17.774064623776855, Tmax = 25.0, Tmin = 15.0)

The underlying data structure of sampled is the same as weather, but the values are now the result of applying the reducer (by default, mean) over each 24-hour window. Each row in sampled corresponds to a 24-hour window in the original data, and the variables are the aggregated values for that window. You can inspect the variables in sampled just like before, e.g. sampled[1] is the first sampled row, and sampled[1].T is the mean temperature over the first 24-hour window:

sampled
Atmosphere(date = DateTime("2025-07-01T23:00:00"), duration = Millisecond(86400000), T = 20.0, Wind = 1.1999999999999997, P = 101.3, Rh = 0.6500000000000001, Precipitations = 1.2000000000000002, Cₐ = 415.0, e = 1.502742570200317, eₛ = 2.396416501191441, VPD = 0.8936739309911232, ρ = 1.203960293363366, λ = 2.453700000000001e6, γ = 0.0672375819269494, ε = 0.5834413910269151, Δ = 0.1480115968281549, Ri_SW_f = 205.71834055297288, Rhmax = 0.8, Rhmin = 0.5, Ri_SW_q = 17.774064623776855, Tmax = 25.0, Tmin = 15.0)

This sampled row is the aggregation of the previous 24 hourly timesteps:

mean(weather[i].T for i in 1:24)
20.0

5. Switch To The Real Open-Meteo Backend

The runnable examples above stay offline on purpose. In real use, replace PlantMeteo.DemoAPI() with OpenMeteo() (which is the default):

using PlantMeteo, Dates

period = Date(2025, 7, 1):Day(1):Date(2025, 7, 3)
weather = get_weather(48.8566, 2.3522, period; api=OpenMeteo())

Next Steps