API
Index
PlantMeteo.ATMOSPHERE_COMPUTEDPlantMeteo.ATMOSPHERE_NONSTANDARD_NAMESPlantMeteo.DEFAULT_OPENMETEO_HOURLYPlantMeteo.OPENMETEO_MODELSPlantMeteo.AbstractAPIPlantMeteo.AbstractAtmospherePlantMeteo.AbstractSamplingWindowPlantMeteo.AbstractTimeReducerPlantMeteo.AtmospherePlantMeteo.CalendarWindowPlantMeteo.ConstantsPlantMeteo.DurationSumReducerPlantMeteo.DurationSumReducerPlantMeteo.DurationSumReducerPlantMeteo.FirstReducerPlantMeteo.FirstReducerPlantMeteo.LastReducerPlantMeteo.LastReducerPlantMeteo.MaxReducerPlantMeteo.MaxReducerPlantMeteo.MeanReducerPlantMeteo.MeanReducerPlantMeteo.MeanWeightedPlantMeteo.MeanWeightedPlantMeteo.MeteoTransformPlantMeteo.MinReducerPlantMeteo.MinReducerPlantMeteo.OpenMeteoPlantMeteo.OpenMeteoUnitsPlantMeteo.PreparedWeatherPlantMeteo.RadiationEnergyPlantMeteo.RadiationEnergyPlantMeteo.RadiationEnergyPlantMeteo.RollingWindowPlantMeteo.SumReducerPlantMeteo.SumReducerPlantMeteo.TimeStepTableBase.getpropertyBase.setindex!PlantMeteo.WeatherPlantMeteo._build_calendar_window_cachePlantMeteo._default_radiation_flux_varsPlantMeteo._duration_period_from_secondsPlantMeteo._duration_secondsPlantMeteo._expected_period_secondsPlantMeteo._normalize_reducerPlantMeteo._normalize_single_transformPlantMeteo._period_keyPlantMeteo._reduce_valuesPlantMeteo._sample_weather_uncachedPlantMeteo._transform_signaturePlantMeteo._week_start_datePlantMeteo._window_boundsPlantMeteo._window_indicesPlantMeteo.add_transformations!PlantMeteo.air_densityPlantMeteo.atmosphere_emissivityPlantMeteo.check_day_completePlantMeteo.check_non_overlapping_timestepsPlantMeteo.compute_datePlantMeteo.compute_durationPlantMeteo.default_sampling_transformsPlantMeteo.default_transformationPlantMeteo.duration_secondsPlantMeteo.e_satPlantMeteo.e_sat_slopePlantMeteo.fetch_openmeteoPlantMeteo.format_openmeteo!PlantMeteo.get_forecastPlantMeteo.get_index_rawPlantMeteo.get_weatherPlantMeteo.latent_heat_vaporizationPlantMeteo.materialize_weatherPlantMeteo.new_namesPlantMeteo.next_rowPlantMeteo.next_valuePlantMeteo.normalize_sampling_transformsPlantMeteo.parse_hourPlantMeteo.positive_duration_secondsPlantMeteo.prepare_weatherPlantMeteo.prepare_weather_samplerPlantMeteo.prev_rowPlantMeteo.prev_valuePlantMeteo.psychrometer_constantPlantMeteo.read_weatherPlantMeteo.rh_from_ePlantMeteo.rh_from_vpdPlantMeteo.row_datetime_intervalPlantMeteo.row_structPlantMeteo.sample_weatherPlantMeteo.select_overlapping_timestepsPlantMeteo.select_weatherPlantMeteo.standardize_columns!PlantMeteo.sum_durationPlantMeteo.timesteps_durationsPlantMeteo.to_dailyPlantMeteo.vapor_pressurePlantMeteo.vpdPlantMeteo.vpd_from_ePlantMeteo.write_weatherPlantMeteo.write_weather_
API documentation
PlantMeteo.ATMOSPHERE_COMPUTED — Constant
ATMOSPHERE_SELECTList of variables that are by default removed from the table when using write_weather on a TimeStepTable{Atmosphere}.
PlantMeteo.ATMOSPHERE_NONSTANDARD_NAMES — Constant
ATMOSPHERE_NONSTANDARD_NAMESList of variables that are by default renamed when using write_weather on a TimeStepTable{Atmosphere}, to be compatible with standard file systems (CSV, databases...).
Cₐ=>Caeₛ=>esρ=>rhoλ=>lambdaγ=>gammaε=>epsilonΔ=>Delta
The reverse procedure is done when reading a file with read_weather.
See also
PlantMeteo.DEFAULT_OPENMETEO_HOURLY — Constant
DEFAULT_OPENMETEO_HOURLYDefault variables downloaded for an Open-Meteo forecast. See here for more.
PlantMeteo.OPENMETEO_MODELS — Constant
OPENMETEO_MODELSPossible models for the forecast. See here for more details.
PlantMeteo.AbstractAPI — Type
AbstractAPIAn abstract type for APIs. This is used to define the API to use for the weather forecast. You can get all available APIs using subtype(AbstractAPI).
PlantMeteo.AbstractAtmosphere — Type
Abstract atmospheric conditions type. The suptypes of AbstractAtmosphere should describe the atmospheric conditions for one time-step only, see e.g. Atmosphere
PlantMeteo.AbstractSamplingWindow — Type
AbstractSamplingWindowAbstract supertype for weather window selectors used by sample_weather.
PlantMeteo.AbstractTimeReducer — Type
AbstractTimeReducerAbstract supertype for reducers used by MeteoTransform.
Reducer implementations are expected to be callable with either:
(vals)(vals, durations)
See MeanWeighted, SumReducer, and RadiationEnergy.
PlantMeteo.Atmosphere — Type
Atmosphere structure to hold all values related to the meteorology / atmosphere.
Arguments
date<:AbstractDateTime = Dates.now(): the date of the record.duration<:Period = Dates.Second(1.0): the duration of the time-step in Dates.Period.T(°C): air temperatureWind(m s-1): wind speedRh(0-1): relative humidity (can be computed usingrh_from_vpd)P = DEFAULTS.P(kPa): air pressure. The default value is at 1 atm, i.e. the mean sea-level
atmospheric pressure on Earth.
Precipitations = DEFAULTS.Precipitations(mm): precipitations from atmosphere (i.e. rain, snow, hail, etc.)Cₐ = DEFAULTS.Cₐ(ppm): air CO₂ concentrationcheck = true: whether to check the validity of the input values.e = vapor_pressure(T,Rh)(kPa): vapor pressureeₛ = e_sat(T)(kPa): saturated vapor pressureVPD = eₛ - e(kPa): vapor pressure deficitρ = air_density(T, P, constants.Rd, constants.K₀)(kg m-3): air densityλ = latent_heat_vaporization(T, constants.λ₀)(J kg-1): latent heat of vaporizationγ = psychrometer_constant(P, λ, constants.Cₚ, constants.ε)(kPa K−1): psychrometer "constant"ε = atmosphere_emissivity(T,e,constants.K₀)(0-1): atmosphere emissivityΔ = e_sat_slope(meteo.T)(0-1): slope of the saturation vapor pressure at air temperatureclearness::A = Inf(0-1): Sky clearnessRi_SW_f::A = Inf(W m-2): Incoming short wave radiation fluxRi_PAR_f::A = Inf(W m-2): Incoming PAR fluxRi_NIR_f::A = Inf(W m-2): Incoming NIR fluxRi_TIR_f::A = Inf(W m-2): Incoming TIR fluxRi_custom_f::A = Inf(W m-2): Incoming radiation flux for a custom waveband
Notes
The structure can be built using only T, Rh, Wind and P. All other variables are optional and either let at their default value or automatically computed using the functions given in Arguments.
Examples
Atmosphere(T = 20.0, Wind = 1.0, P = 101.3, Rh = 0.65)PlantMeteo.CalendarWindow — Type
CalendarWindow(period; anchor=:current_period, week_start=1, completeness=:allow_partial)Calendar-based window selector used by sample_weather.
Arguments
period::Symbol: grouping period.:day: group by civil day.:week: group by civil week (start controlled byweek_start).:month: group by calendar month.
anchor::Symbol: which period is sampled at weather stepi.:current_period: sample from the period containingweather[i].date.:previous_complete_period: sample from the period immediately before the current one.
week_start::Int: week start day in1:7(1=Monday,7=Sunday). Used only whenperiod == :week.completeness::Symbol: behavior when selected period is missing/incomplete.:allow_partial: accept partial periods; if no previous period exists, fallback to[step].:strict: require a valid complete selected period (default); otherwise throw an error.
Notes
CalendarWindowrequiresdate::DateTimein source weather rows.- Completeness is checked from summed
durationagainst expected civil period duration.
Errors
Throws if any argument is outside the allowed set.
PlantMeteo.Constants — Type
Physical constants
The definition and default values are:
K₀ = -273.15: absolute zero (°C)R = 8.314: universal gas constant ($J\ mol^{-1}\ K^{-1}$).Rd = 287.0586: gas constant of dry air ($J\ kg^{-1}\ K^{-1}$).Dₕ₀ = 21.5e-6: molecular diffusivity for heat at base temperature, applied in the integrated form of the Fick’s Law of diffusion ($m^2\ s^{-1}$). See eq. 3.10 from Monteith and Unsworth (2013).Cₚ = 1013.0: Specific heat of air at constant pressure ($J\ K^{-1}\ kg^{-1}$), also known as efficiency of impaction of particles. See Allen et al. (1998), or Monteith and Unsworth (2013). NB: bigleaf R package uses 1004.834 intead.ε = 0.622: ratio of molecular weights of water vapor and air. See Monteith and Unsworth (2013).λ₀ = 2.501: latent heat of vaporization for water at 0 degree ($J\ kg^{-1}$).σ = 5.670373e-08Stefan-Boltzmann constant in ($W\ m^{-2}\ K^{-4}$).Gbₕ_to_Gbₕ₂ₒ = 1.075: conversion coefficient from conductance to heat to conductance to water vapor.Gsc_to_Gsw = 1.57: conversion coefficient from stomatal conductance to CO₂ to conductance to water vapor.Gbc_to_Gbₕ = 1.32: conversion coefficient from boundary layer conductance to CO₂ to heat.Mₕ₂ₒ = 18.0e-3(kg mol-1): Molar mass for water.J_to_umol = 4.57: Conversion factor from radiation in Joules m-2 s-1 (or W m-2) to μmol m-2 s-1.PAR_fraction = 0.48: Fraction of shortwave radiation that is photosynthetically active radiation (PAR).
References
Allen, Richard G., Luis S. Pereira, Dirk Raes, et Martin J Fao Smith. 1998. « Crop evapotranspiration-Guidelines for computing crop water requirements-FAO Irrigation and drainage paper 56 » 300 (9): D05109.
Monteith, John, et Mike Unsworth. 2013. Principles of environmental physics: plants, animals, and the atmosphere. Academic Press.
PlantMeteo.DurationSumReducer — Type
DurationSumReducer()Integrate values over durations (seconds) with no unit conversion. Returns sum(values .* durations).
PlantMeteo.DurationSumReducer — Method
DurationSumReducer()(vals, durations)Integrate values over durations without applying any extra scaling factor. Durations are interpreted as seconds when given as Real, or converted to seconds when given as Dates.TimePeriod.
PlantMeteo.DurationSumReducer — Method
DurationSumReducer()(vals)Erroring fallback for duration-free reductions.
PlantMeteo.FirstReducer — Type
FirstReducer()Reducer returning first value in the window.
PlantMeteo.FirstReducer — Method
(FirstReducer())(vals)
(FirstReducer())(vals, durations)Return first sampled value.
Arguments
vals::AbstractVector: values to reduce.durations::AbstractVector{<:Real}: optional durations (ignored).
PlantMeteo.LastReducer — Type
LastReducer()Reducer returning last value in the window.
PlantMeteo.LastReducer — Method
(LastReducer())(vals)
(LastReducer())(vals, durations)Return last sampled value.
Arguments
vals::AbstractVector: values to reduce.durations::AbstractVector{<:Real}: optional durations (ignored).
PlantMeteo.MaxReducer — Type
MaxReducer()Maximum reducer.
PlantMeteo.MaxReducer — Method
(MaxReducer())(vals)
(MaxReducer())(vals, durations)Compute maximum of sampled values.
Arguments
vals::AbstractVector{<:Real}: values to reduce.durations::AbstractVector{<:Real}: optional durations (ignored).
PlantMeteo.MeanReducer — Type
MeanReducer()Arithmetic mean reducer.
PlantMeteo.MeanReducer — Method
(MeanReducer())(vals)
(MeanReducer())(vals, durations)Compute arithmetic mean of sampled values.
Arguments
vals::AbstractVector{<:Real}: values to reduce.durations::AbstractVector{<:Real}: optional durations (ignored).
PlantMeteo.MeanWeighted — Type
MeanWeighted()Duration-weighted mean reducer. When durations are not provided, falls back to a plain mean.
PlantMeteo.MeanWeighted — Method
(MeanWeighted())(vals, durations)Compute duration-weighted mean.
Arguments
vals::AbstractVector{<:Real}: values to reduce.durations::AbstractVector{<:Real}: per-value durations.
Returns
Weighted mean, or nothing when the total duration is zero.
PlantMeteo.MeteoTransform — Type
MeteoTransform(target; source=target, reducer=MeanWeighted())Build a transform rule consumed by sample_weather.
Arguments
target::Symbol: output variable name in sampled weather.source::Symbol: input variable name read from source rows.reducer: reducer instance used on windowed values.
PlantMeteo.MinReducer — Type
MinReducer()Minimum reducer.
PlantMeteo.MinReducer — Method
(MinReducer())(vals)
(MinReducer())(vals, durations)Compute minimum of sampled values.
Arguments
vals::AbstractVector{<:Real}: values to reduce.durations::AbstractVector{<:Real}: optional durations (ignored).
PlantMeteo.OpenMeteo — Type
OpenMeteo()
OpenMeteo(
vars=PlantMeteo.DEFAULT_OPENMETEO_HOURLY,
forecast_server="https://api.open-meteo.com/v1/forecast",
historical_server="https://archive-api.open-meteo.com/v1/era5",
units=OpenMeteoUnits(),
timezone="UTC",
models=["auto"]
)A type that defines the open-meteo.com API. No need of an API key as it is free. Please keep in mind that the API is distributed under the AGPL license, that it is not free for commercial use, and that you should use it responsibly.
Notes
The API wrapper provided by PlantMeteo is only working for the hourly data as daily data is missing some variables. The API wrapper is also not working for the "soil" variables as they are not consistant between forecast and historical data.
See also
Arguments
vars: the variables needed, see here.forecast_server: the server to use for the forecast, see
here. Default to https://api.open-meteo.com/v1/forecast.
historical_server: the server to use for the historical data, see
here. Default to https://archive-api.open-meteo.com/v1/era5.
start_archive::Dates.Day: the first day on which we have to get data from the historical archive instead of the forecast server,
data is at 25km resolution in the archive. Default to -150 days.
units::OpenMeteoUnits: the units used for the variables, seeOpenMeteoUnits.timezone: the timezone used for the data, see the list here.
Default to "UTC". This parameter is not checked, so be careful when using it.
models: the models to use for the forecast. Default to"["best_match"]". SeeOPENMETEO_MODELSfor more details.
Troubleshooting
If you get an error when calling the API, try to decrease the value of start_archive to e.g.. 100 days before today (-Dates.Day(100)).
Details
The default variables are: "temperature2m", "relativehumidity2m", "precipitation", "surfacepressure", "windspeed10m", "shortwaveradiation", "directradiation", "diffuse_radiation".
Note that we don't download: "soiltemperature0cm", "soiltemperature6cm", "soiltemperature18cm", "soiltemperature54cm", "soilmoisture01cm", "soilmoisture13cm", "soilmoisture39cm", "soilmoisture927cm" and "soilmoisture27_81cm" by default as they are not consistant between forecast and hystorical data.
Sources
- Open-Meteo.com, under Attribution
4.0 International (CC BY 4.0).
- Copernicus Climate Change Service information 2022 (Hersbach et al., 2018).
Hersbach, H., Bell, B., Berrisford, P., Biavati, G., Horányi, A., Muñoz Sabater, J., Nicolas, J., Peubey, C., Radu, R., Rozum, I., Schepers, D., Simmons, A., Soci, C., Dee, D., Thépaut, J-N. (2018): ERA5 hourly data on single levels from 1959 to present. Copernicus Climate Change Service (C3S) Climate Data Store (CDS). (Updated daily), 10.24381/cds.adbb2d47
PlantMeteo.OpenMeteoUnits — Type
OpenMeteoUnits(temperature_unit, windspeed_unit, precipitation_unit)
OpenMeteoUnits(;temperature_unit="celsius", windspeed_unit="ms", precipitation_unit="mm")A type that defines the units used for the variabels when calling the open-meteo.com API.
Arguments
temperature_unit: the temperature unit, can be "celsius" or "fahrenheit". Default to "celsius".windspeed_unit: the windspeed unit, can be "ms", "kmh", "mph", or "kn". Default to "ms".precipitation_unit: the precipitation unit, can be "mm" or "inch". Default to "mm".
Examples
julia> units = OpenMeteoUnits("celsius", "ms", "mm")
OpenMeteoUnits("celsius", "ms", "mm")PlantMeteo.PreparedWeather — Type
PreparedWeather(weather; transforms=default_sampling_transforms(), lazy=true)Build a sampler container used by sample_weather.
Arguments
weather: source weather table (TimeStepTable{Atmosphere}or compatible rows).transforms: transform specification accepted bynormalize_sampling_transforms.lazy::Bool: enable memoization cache for repeated sampling queries.
PlantMeteo.RadiationEnergy — Type
RadiationEnergy()Integrate flux values (W m-2) over durations (seconds) into MJ m-2.
PlantMeteo.RadiationEnergy — Method
RadiationEnergy()(vals, durations)Integrate flux values over durations into energy in MJ m-2.
Arguments
vals::AbstractVector{<:Real}: flux values in W m-2.durations::AbstractVector{<:Real}: durations in seconds or inDates.TimePeriod(e.g.Dates.Day,Dates.Minute...).
PlantMeteo.RadiationEnergy — Method
(RadiationEnergy())(vals)Erroring fallback for duration-free reductions.
Use (RadiationEnergy())(vals, durations) in weather sampling contexts.
PlantMeteo.RollingWindow — Type
RollingWindow(dt=1.0)Trailing window selector for sample_weather.
Arguments
dt::Real: trailing window length in source weather timesteps.
Notes
RollingWindow()is equivalent toRollingWindow(1.0)(identity window).
PlantMeteo.SumReducer — Type
SumReducer()Sum reducer.
PlantMeteo.SumReducer — Method
(SumReducer())(vals)
(SumReducer())(vals, durations)Compute sum of sampled values.
Arguments
vals::AbstractVector{<:Real}: values to reduce.durations::AbstractVector{<:Real}: optional durations (ignored).
PlantMeteo.TimeStepTable — Type
TimeStepTable(vars)TimeStepTable stores variables values for each time step, e.g. weather variables. It implements the Tables.jl interface, so it can be used with any package that uses Tables.jl (like DataFrames.jl).
You can extend TimeStepTable to store your own variables by defining a new type for the storage of the variables. You can look at the Atmosphere type for an example implementation, or the Status type from PlantSimEngine.jl.
Examples
data = TimeStepTable(
[
Atmosphere(T = 20.0, Wind = 1.0, P = 101.3, Rh = 0.65),
Atmosphere(T = 23.0, Wind = 1.5, P = 101.3, Rh = 0.60),
Atmosphere(T = 25.0, Wind = 3.0, P = 101.3, Rh = 0.55)
]
)
# We can convert it into a DataFrame:
using DataFrames
df = DataFrame(data)
# We can also create a TimeStepTable from a DataFrame:
TimeStepTable(df)
# Note that by default it will use NamedTuple to store the variables
# for high performance. If you want to use a different type, you can
# specify it as a type parameter (if you want *e.g.* mutability or pre-computations):
TimeStepTable{Atmosphere}(df)
# Or if you use PlantSimEngine: TimeStepTable{Status}(df)
# Indexing examples:
data[:T] # full column by Symbol
data["T"] # full column by String
data[1] # one row
data[1:2] # row subset as TimeStepTable
data[1, :] # one row (matrix-like syntax)
data[1, :T] # one cell by row + Symbol column
data[1, "T"] # one cell by row + String column
data[1:2, :T] # vector slice from one column
data[1:2, "T"]Base.getproperty — Method
Tables.getcolumn(row::TimeStepRow, nm::Symbol)
Tables.getcolumn(row::TimeStepRow, nm::Int)Get the value of a variable in a TimeStepRow object.
Base.setindex! — Method
setindex!(row::TimeStepRow, nm::Symbol)
setindex!(row::TimeStepRow, i::Int)Set the value of a variable in a TimeStepRow object.
PlantMeteo.Weather — Method
Weather(data[, metadata])Defines the weather, i.e. the local conditions of the Atmosphere for one or more time-steps. Each time-step is described using the Atmosphere structure, and the resulting structure is a TimeStepTable.
The simplest way to instantiate a Weather is to use a DataFrame as input.
The DataFrame should be formated such as each row is an observation for a given time-step and each column is a variable. The column names should match exactly the variables names of the Atmosphere structure:
See also
- the
Atmospherestructure - the
read_weatherfunction to read Archimed-formatted meteorology data.
Examples
Example of weather data defined by hand (cumbersome):
w = Weather(
[
Atmosphere(T = 20.0, Wind = 1.0, P = 101.3, Rh = 0.65),
Atmosphere(T = 23.0, Wind = 1.5, P = 101.3, Rh = 0.60),
Atmosphere(T = 25.0, Wind = 3.0, P = 101.3, Rh = 0.55)
],
(
site = "Test site",
important_metadata = "this is important and will be attached to our weather data"
)
)Weather is a TimeStepTable{Atmosphere}, so we can convert it into a DataFrame:
using DataFrames
df = DataFrame(w)And then back into Weather to make a TimeStepTable{Atmosphere}:
Weather(df, (site = "My site",))Of course it works with any DataFrame that has at least the required variables listed in Atmosphere.
PlantMeteo._build_calendar_window_cache — Method
_build_calendar_window_cache(prepared, window)Precompute per-step indices and completeness flags for CalendarWindow sampling.
Arguments
prepared::PreparedWeather: source weather container.window::CalendarWindow: calendar window settings.
Returns
Named tuple with:
indices_by_step::Vector{Vector{Int}}complete_by_step::Vector{Bool}
PlantMeteo._default_radiation_flux_vars — Method
_default_radiation_flux_vars()Return default radiation source variable names used by default_sampling_transforms.
PlantMeteo._duration_period_from_seconds — Method
_duration_period_from_seconds(sec)Convert seconds to a Dates.Millisecond period used in sampled outputs.
Arguments
sec::Float64: duration in seconds.
PlantMeteo._duration_seconds — Method
_duration_seconds(d)Convert a duration-like value to seconds.
Arguments
d: aDates.Period, a real value already in seconds, or another value.
Returns
Float64 seconds. Unknown types fall back to 1.0.
PlantMeteo._expected_period_seconds — Method
_expected_period_seconds(period_key, window)Return expected duration in seconds for a complete calendar period.
Arguments
period_key::Dates.Date: canonical period key from_period_key.window::CalendarWindow: window configuration.
PlantMeteo._normalize_reducer — Method
_normalize_reducer(reducer)Normalize user reducer definitions into a callable reducer object.
Arguments
reducer: reducer instance/type or callable.
Returns
- Reducer instance when input is a reducer type.
- Reducer/callable unchanged when already instantiated.
PlantMeteo._normalize_single_transform — Method
_normalize_single_transform(target, rule)Normalize one transform specification entry into a MeteoTransform.
Arguments
target::Symbol: output variable name.rule: reducer-like value or named tuple with optionalsourceandreducer.
PlantMeteo._period_key — Method
_period_key(dt, window)Map a DateTime to the canonical period key used by CalendarWindow.
Arguments
dt::Dates.DateTime: timestamp to classify.window::CalendarWindow: window configuration (day/week/month).
PlantMeteo._reduce_values — Method
_reduce_values(vals, durations, reducer)Apply one reducer to sampled values and optional durations.
Arguments
vals::AbstractVector: sampled source values for one transform.durations::AbstractVector{<:Real}: per-value durations in seconds.reducer: normalized reducer instance or callable.
Returns
Reduced value, or nothing when reduction is not possible (for example non-real values with real-only reducers).
PlantMeteo._sample_weather_uncached — Method
_sample_weather_uncached(prepared, step, window, transforms)Compute one sampled weather row without using/setting cache.
Arguments
prepared::PreparedWeather: source weather container.step::Int: index of the current source weather row.window::AbstractSamplingWindow: window selection strategy.transforms::AbstractVector{MeteoTransform}: normalized transform rules.
Returns
Atmosphere sampled at step.
PlantMeteo._transform_signature — Method
_transform_signature(transforms)Compute a deterministic hash signature for transform rules used in cache keys.
Arguments
transforms::AbstractVector{MeteoTransform}: normalized transform rules.
PlantMeteo._week_start_date — Method
_week_start_date(d, week_start)Return the civil week start date containing d.
Arguments
d::Dates.Date: date to classify.week_start::Int: week start day in1:7(1=Monday,7=Sunday).
PlantMeteo._window_bounds — Method
_window_bounds(step, window)Compute inclusive trailing bounds (start, stop) for a RollingWindow.
Arguments
step::Int: current weather index.window::RollingWindow: rolling window configuration.
PlantMeteo._window_indices — Method
_window_indices(prepared, step, window)Return source weather indices selected for one sampling query.
Arguments
prepared::PreparedWeather: source weather container.step::Int: current weather index.window::AbstractSamplingWindow: window selection strategy.
PlantMeteo.add_transformations! — Method
add_transformations!(df, trans, vars, fun; error_missing=false)Add the fun transformations to the trans vector for the variables vars found in the df DataFrame.
Arguments
df: the DataFrametrans: the vector of transformations (will be modified in-place)vars: the variables to transform (can be a symbol, a vector of symbols or a pairs :var => :new_var)fun: the function to apply to the variableserror_missing=true: iftrue, the function returns an error if the variable is not found. Iffalse,
the variable is not added to trans.
PlantMeteo.air_density — Method
air_density(Tₐ, P; check=true)
air_density(Tₐ, P, Rd, K₀; check=true)ρ, the air density (kg m-3).
Arguments
Tₐ(Celsius degree): air temperatureP(kPa): air pressureRd(J kg-1 K-1): gas constant of dry air (see Foken p. 245, or R bigleaf package).K₀(Celsius degree): temperature in Celsius degree at 0 Kelvincheck(Bool): check if P is in the 85-110 kPa earth range
Note
Rd and K₀ are Taken from Constants if not provided.
References
Foken, T, 2008: Micrometeorology. Springer, Berlin, Germany.
PlantMeteo.atmosphere_emissivity — Method
atmosphere_emissivity(Tₐ,eₐ)Emissivity of the atmoshpere at a given temperature and vapor pressure.
Arguments
Tₐ(°C): air temperatureeₐ(kPa): air vapor pressureK₀(°C): absolute zero
Examples
Tₐ = 20.0
VPD = 1.5
atmosphere_emissivity(Tₐ, vapor_pressure(Tₐ,VPD))References
Leuning, R., F. M. Kelliher, DGG de Pury, et E.-D. SCHULZE. 1995. Leaf nitrogen, photosynthesis, conductance and transpiration: scaling from leaves to canopies ». Plant, Cell & Environment 18 (10): 1183‑1200.
PlantMeteo.check_day_complete — Method
check_day_complete(df)Check that the weather table df has full days (24h) of data by summing their durations.
df must be a Tables.jl compatible table with a date and duration column. The date column must be a Dates.DateTime column, and the duration column must be a Dates.Period or Dates.CompoundPeriod column.
PlantMeteo.check_non_overlapping_timesteps — Method
check_non_overlapping_timesteps(rows; kwargs...)Validate that each timestep starts at or after the previous timestep end. Throws an error on the first overlap.
PlantMeteo.compute_date — Function
compute_date(data, date_format, hour_format; forward_fill_date=false)Compute the date column depending on several cases:
- If it is already in data and is a
DateTime, does nothing. - If it is a
String, tries and parse it using a user-inputDateFormat - If it is a
Date, return it as is, or try to make it aDateTimeif there's a column named
hour_start
Arguments
data: anyTables.jlcompatible table, such as aDataFramedate_format: aDateFormatto parse thedatecolumn if it is aStringhour_format: aDateFormatto parse thehour_startcolumn if it is aStringforward_fill_date: whentrue, missing dates are filled with the previous non-missing date
PlantMeteo.compute_duration — Function
compute_duration(data, hour_format, duration)Compute the duration column depending on several cases:
- If it is already in the data, use the
durationfunction to parse it into aDate.Period. - If it is not, but there's a column named
hour_endand another one either calledhour_start
or date, compute the duration from the period between hour_start (or date) and hour_end.
Arguments
data: anyTables.jlcompatible table, such as aDataFramehour_format: aDateFormatto parse thehour_startandhour_endcolumns if they areStrings.duration: a function to parse thedurationcolumn. UsuallyDates.DayorDates.Minute.
PlantMeteo.default_sampling_transforms — Method
default_sampling_transforms(; radiation_mode=:both)Default weather sampling rules.
radiation_mode controls how radiation targets are emitted:
:flux_mean: duration-weighted mean flux (same units as source):energy_sum: integrated quantity in MJ m-2 over the sampling window:both: keepRi_*_fas weighted-mean flux and also emitRi_*_qquantities
Arguments
radiation_mode::Symbol: one of:flux_mean,:energy_sum,:both.
Returns
Vector{MeteoTransform} used by PreparedWeather and sample_weather.
PlantMeteo.default_transformation — Method
default_transformation(df)Return the default transformations to apply to the df DataFrame for the to_daily function. If the variable is not available, the transformation is not applied.
The default transformations are:
:date => (x -> unique(Dates.Date.(x))) => :date: the date is transformed into aDateobject:duration => sum => :duration: the duration is summed:T => minimum => :Tmin: we use the minimum temperature for Tmin:T => maximum => :Tmax: and the maximum temperature for Tmax:T => mean => :T: and the average daily temperature (!= than average of Tmin and Tmax):Precipitations => sum => :Precipitations: the precipitations are summed:Rh => mean => :Rh: the relative humidity is averaged:Wind, :P, :Rh, :Cₐ, :e, :eₛ, :VPD, :ρ, :λ, :γ, :ε, :Δ, :clearnessare
all averaged
[:Ri_SW_f, :duration] => ((x, y) -> sum(x .* Dates.toms.(y)) * 1.0e-9) => :Ri_SW_f: the irradiance is integrated, so its unit changes from W m⁻² to MJ m⁻² d⁻¹- All other irradiance variables are also integrated (see the code for details)
PlantMeteo.duration_seconds — Method
duration_seconds(x; field_name="duration", allow_nan=true)Convert a duration-like value into seconds.
Accepted values are:
- numeric values (already in seconds),
Dates.Period,Dates.Time,Dates.DateTime,- strings formatted as
HH:MM[:SS], - strings parseable as numbers.
When parsing fails, the function returns NaN if allow_nan=true, otherwise it throws.
PlantMeteo.e_sat — Method
e_sat(T)Saturated water vapour pressure (es, in kPa) at given temperature T (°C). See Jones (1992) p. 110 for the equation.
PlantMeteo.e_sat_slope — Method
e_sat_slope(T)Slope of the vapor pressure saturation curve at a given temperature T (°C).
PlantMeteo.fetch_openmeteo — Method
fetch_openmeteo(url, lat, lon, start_date, end_date, params::OpenMeteo)Fetches the weather forecast from OpenMeteo.com and returns a tuple of:
- a vector of
Atmosphere - a
NamedTupleof metadata (e.g.elevation,timezone,units...)
PlantMeteo.format_openmeteo! — Method
format_openmeteo(data)Format the JSON file returned by the Open-Meteo API into a vector of Atmosphere. The function also updates some units in data.
PlantMeteo.get_forecast — Method
get_forecast(params::OpenMeteo, lat, lon, period; verbose=true)A function that returns the weather forecast from OpenMeteo.com
Arguments
lat: Latitude of the locationlon: Longitude of the locationperiod::Union{StepRange{Date, Day}, Vector{Dates.Date}}: Period of the forecastverbose: Iftrue, print more information in case of errors or warnings.kwargs: Additional keyword arguments passed toget_forecast(not used in this method).
Examples
using PlantMeteo, Dates
lat = 48.8566
lon = 2.3522
period = [Dates.today(), Dates.today()+Dates.Day(3)]
params = OpenMeteo()
get_forecast(params, lat, lon, period)PlantMeteo.get_index_raw — Method
Get row from TimeStepTable in its raw format, e.g. as a NamedTuple or Atmosphere of values.
PlantMeteo.get_weather — Method
get_weather(lat, lon, period::Union{StepRange{Date, Day}, Vector{Dates.Date}}; api::DataType=OpenMeteo, sink=TimeStepTable, kwargs...)Returns the weather forecast for a given location and time using a weather API.
Arguments
lat::Float64: Latitude of the location in degreeslon::Float64: Longitude of the location in degreesperiod::Union{StepRange{Date, Day}, Vector{Dates.Date}}: Period of the forecastapi::DataType=OpenMeteo: API to use for the forecast.sink::DataType=TimeStepTable: Type of the output. Default isTimeStepTable, but it
can be any type that implements the Tables.jl interface, such as DataFrames.
kwargs...: Additional keyword arguments that are passed to the API
Details
We can get all available APIs using subtype(AbstractAPI). Please keep in mind that the default OpenMeteo API is not free for commercial use, and that you should use it responsibly.
Examples
using PlantMeteo, Dates
# Forecast for today and tomorrow:
period = [today(), today()+Dates.Day(1)]
w = get_weather(48.8566, 2.3522, period)PlantMeteo.latent_heat_vaporization — Method
latent_heat_vaporization(Tₐ,λ₀)
latent_heat_vaporization(Tₐ)λ, the latent heat of vaporization for water (J kg-1).
Arguments
Tₐ(°C): air temperatureλ₀: latent heat of vaporization for water at 0 degree Celsius. Taken fromConstants().λ₀
if not provided (see Constants).
PlantMeteo.materialize_weather — Method
materialize_weather(prepared; windows, transforms=nothing)Precompute sampled weather tables for a set of sampling windows. Returns Dict{AbstractSamplingWindow,TimeStepTable{Atmosphere}}.
Arguments
prepared::PreparedWeather: sampler state containing source weather.windows: iterable collection ofAbstractSamplingWindow.transforms: optional transform override applied to all windows.
PlantMeteo.new_names — Method
new_names(args)Get the new names of the columns after the transformation provided by the user.
PlantMeteo.next_row — Function
next_row(row::TimeStepRow, i=1)Return the next row in the table.
PlantMeteo.next_value — Function
next_value(row::TimeStepRow, var, next_index=1; default=nothing)Return the value of var in the next row in the table, or default if there is no next row.
PlantMeteo.normalize_sampling_transforms — Method
normalize_sampling_transforms(transforms)Normalize user-provided weather transform definitions into Vector{MeteoTransform}.
Accepted inputs are:
Vector{MeteoTransform}(copied as-is)NamedTuplewhere each key is the target variable and each value is either:- a reducer (
AbstractTimeReducerinstance/type, or callable), or - a named tuple with optional
sourceandreducerfields
- a reducer (
AbstractVectorcontaining onlyMeteoTransformentries
This is the canonical parser used by PreparedWeather and sample_weather to validate and materialize transform rules.
Arguments
transforms: user transform specification (named tuple or vector forms).
Returns
Vector{MeteoTransform}.
PlantMeteo.parse_hour — Function
parse_hour(h, hour_format=Dates.DateFormat("HH:MM:SS"))Parse an hour that can be of several formats:
Time: return it as isString: try to parse it using the user-inputDateFormatDateTime: transform it into aTime
Arguments
h: hour to parsehour_format::DateFormat: user-input format to parse the hours
Examples
julia> using PlantMeteo, Dates;As a string:
julia> PlantMeteo.parse_hour("12:00:00")
12:00:00As a Time:
julia> PlantMeteo.parse_hour(Dates.Time(12, 0, 0))
12:00:00As a DateTime:
julia> PlantMeteo.parse_hour(Dates.DateTime(2020, 1, 1, 12, 0, 0))
12:00:00PlantMeteo.positive_duration_seconds — Method
positive_duration_seconds(x; field_name="duration")Convert a duration-like value to seconds and ensure it is finite and strictly positive.
PlantMeteo.prepare_weather — Method
prepare_weather(
w;
vars=setdiff(propertynames(w), ATMOSPHERE_COMPUTED),
duration=Dates.Minute
)Prepare the weather data for writing to a file. The function returns a DataFrame with the selected variables and the duration formated.
Arguments
w: aTables.jlinterfaced table, such as aTimeStepTable{Atmosphere}or aDataFramevars: a vector of variables to write (as symbols). By default, all variables are written except the ones that
can be recomputed (see ATMOSPHERE_COMPUTED). If nothing is given, all variables are written.
duration: the unit for formating the duration of the time steps. By default, it isDates.Minute
Examples
using PlantMeteo, Dates
file = joinpath(dirname(dirname(pathof(PlantMeteo))),"test","data","meteo.csv")
w = read_weather(
file,
:temperature => :T,
:relativeHumidity => (x -> x ./100) => :Rh,
:wind => :Wind,
:atmosphereCO2_ppm => :Cₐ,
date_format = DateFormat("yyyy/mm/dd")
)
df = prepare_weather(w)PlantMeteo.prepare_weather_sampler — Method
prepare_weather_sampler(weather; transforms=default_sampling_transforms(), lazy=true)Build the PreparedWeather container holding a fine-step weather table and lazy sampling cache.
Arguments
weather: source weather table.transforms: transform specification accepted bynormalize_sampling_transforms.lazy::Bool: enable/disable sampling cache.
PlantMeteo.prev_row — Function
prev_row(row::TimeStepRow, i=1)Return the previous row in the table, or default if there is no previous row.
PlantMeteo.prev_value — Function
prev_value(row::TimeStepRow, var, prev_index=1; default=nothing)Return the value of var in the previous row in the table, or default if there is no previous row.
PlantMeteo.psychrometer_constant — Method
psychrometer_constant(P, λ, Cₚ, ε; check=true)
psychrometer_constant(P, λ; check=true)γ, the psychrometer constant, also called psychrometric constant (kPa K−1). See Monteith and Unsworth (2013), p. 222.
Arguments
P(kPa): air pressureλ($J\ kg^{-1}$): latent heat of vaporization for water (seelatent_heat_vaporization)Cₚ(J kg-1 K-1): specific heat of air at constant pressure ($J\ K^{-1}\ kg^{-1}$)ε(Celsius degree): temperature in Celsius degree at 0 Kelvincheck(Bool): check if P is in the 85-110 kPa earth range
Note
Cₚ, ε and λ₀ are taken from Constants if not provided.
Tₐ = 20.0
λ = latent_heat_vaporization(Tₐ, λ₀)
psychrometer_constant(100.0, λ)References
Monteith, John L., et Mike H. Unsworth. 2013. « Chapter 13 - Steady-State Heat Balance: (i) Water Surfaces, Soil, and Vegetation ». In Principles of Environmental Physics (Fourth Edition), edited by John L. Monteith et Mike H. Unsworth, 217‑47. Boston: Academic Press.
PlantMeteo.read_weather — Method
read_weather(
file[,args...];
date_format = DateFormat("yyyy-mm-ddTHH:MM:SS.s"),
date_formats = nothing,
hour_format = DateFormat("HH:MM:SS"),
duration = nothing,
forward_fill_date = false,
)Read a meteo file. The meteo file is a CSV, and optionnaly with metadata in a header formatted as a commented YAML. The column names and units should match exactly the fields of Atmosphere, or the user should provide their transformation as arguments (args) with the DataFrames.jl form, i.e.:
:var_name => (x -> x .+ 1) => :new_name: the variable:var_nameis transformed by the functionx -> x .+ 1and renamed to:new_name:var_name => :new_name: the variable:var_nameis renamed to:new_name:var_name: the variable:var_nameis kept as is
Note
The variables found in the file will be used as is if not transformed, and not recomputed from the other variables. Please check that all variables have the same units as in the Atmosphere structure.
Arguments
file::String: path to a meteo fileargs...: A list of arguments to transform the table. See above to see the possible forms.date_format = DateFormat("yyyy-mm-ddTHH:MM:SS.s"): the format for theDateTimecolumnsdate_formats = nothing: optional fallback date formats tried afterdate_formathour_format = DateFormat("HH:MM:SS"): the format for theTimecolumns (e.g.hour_start)duration: a function to parse thedurationcolumn if present in the file. UsuallyDates.DayorDates.Minute.
If the column is absent, the duration will be computed using the hour_format and the hour_start and hour_end columns along with the date column.
forward_fill_date = false: iftrue, missing dates are replaced by the previous parsed date.
Examples
using PlantMeteo, Dates
file = joinpath(dirname(dirname(pathof(PlantMeteo))),"test","data","meteo.csv")
meteo = read_weather(
file,
:temperature => :T,
:relativeHumidity => (x -> x ./100) => :Rh,
:wind => :Wind,
:atmosphereCO2_ppm => :Cₐ,
date_format = DateFormat("yyyy/mm/dd")
)PlantMeteo.rh_from_e — Method
rh_from_e(VPD,eₛ)Conversion between e (kPa) and rh (0-1).
Examples
rh_from_e(1.5,25.0)PlantMeteo.rh_from_vpd — Method
rh_from_vpd(VPD,eₛ)Conversion between VPD and rh.
Examples
eₛ = e_sat(Tₐ)
rh_from_vpd(1.5,eₛ)PlantMeteo.row_datetime_interval — Method
row_datetime_interval(
row;
index=0,
date_cols=(:date,),
start_cols=(:hour_start, :hour),
end_cols=(:hour_end,),
duration_cols=(:step_duration, :duration),
default_date=Date(2000, 1, 1),
default_duration_seconds=1.0,
allow_end_rollover=false,
)Return (start_dt, end_dt) for one timestep row.
start_dt is built from date_cols + start_cols. end_dt is taken from end_cols, or derived from duration_cols, or from default_duration_seconds when no explicit end is available.
PlantMeteo.row_struct — Method
row_struct(ts::TimeStepRow)Get TimeStepRow in its raw format, e.g. the NamedTuple that stores the values, or the Atmosphere of values (or Status for PlantSimEngine.jl).
PlantMeteo.sample_weather — Method
sample_weather(prepared, step; window=RollingWindow(1.0), transforms=nothing)Sample one aggregated weather row at step from a PreparedWeather sampler.
Arguments
prepared::PreparedWeather: output ofprepare_weather_sampler, holding source weather and optional cache.step::Int: 1-based index in the original fine-step weather table.
Keyword arguments
window::AbstractSamplingWindow: selection strategy used before reduction. The defaultRollingWindow(1.0)behaves as an identity window.transforms: optional transform override for this call. Ifnothing, usesprepared.transforms; otherwise accepted bynormalize_sampling_transforms(e.g.NamedTupleorVector{MeteoTransform}).
Returns
An Atmosphere instance built from reduced variables over the selected window. When prepared.lazy == true, results are memoized by (step, window, transforms) and reused on repeated calls.
PlantMeteo.select_overlapping_timesteps — Method
select_overlapping_timesteps(rows, start_dt, end_dt; closed=true, kwargs...)Return rows whose timestep interval overlaps [start_dt, end_dt] (closed=true) or (start_dt, end_dt) (closed=false).
PlantMeteo.select_weather — Function
select_weather(w, vars=setdiff(propertynames(w), ATMOSPHERE_COMPUTED))Select the variables to write in the weather data. The function returns a DataFrame with the selected variables.
Arguments
w: aTables.jlinterfaced table, such as aTimeStepTable{Atmosphere}or aDataFramevars: a vector of variables to write (as symbols). By default, all variables are written except the ones that
can be recomputed (see ATMOSPHERE_COMPUTED). If nothing is given, all variables are written.
Examples
using PlantMeteo, Dates
file = joinpath(dirname(dirname(pathof(PlantMeteo))),"test","data","meteo.csv")
w = read_weather(
file,
:temperature => :T,
:relativeHumidity => (x -> x ./100) => :Rh,
:wind => :Wind,
:atmosphereCO2_ppm => :Cₐ,
date_format = DateFormat("yyyy/mm/dd")
)
df = select_weather(w)PlantMeteo.standardize_columns! — Method
standardize_columns!(::ToFileColumns, df)
standardize_columns!(::ToPlantMeteoColumns, df)Standardize the column names of a DataFrame built upon Atmospheres to be compatible with standard file systems (CSV, databases...).
Arguments
df: aDataFramebuilt uponAtmospheres
Examples
using PlantMeteo, Dates, DataFrames
file = joinpath(dirname(dirname(pathof(PlantMeteo))),"test","data","meteo.csv")
df = read_weather(
file,
:temperature => :T,
:relativeHumidity => (x -> x ./100) => :Rh,
:wind => :Wind,
:atmosphereCO2_ppm => :Cₐ,
date_format = DateFormat("yyyy/mm/dd")
) |> DataFrame
df = standardize_columns!(ToFileColumns(), df)PlantMeteo.sum_duration — Method
sum_duration(x::T) where {T<:AbstractVector{<:Dates.Period}}
sum_duration(x::T) where {T<:AbstractVector{<:Dates.CompoundPeriod}}Sum the durations in x and return a Dates.Day object.
PlantMeteo.timesteps_durations — Method
timesteps_durations(datetime::Dates.DateTime; verbose=true)Duration in sensible units (e.g. 1 hour, or 1 day), computed as the duration between a step and the previous step. The first one is unknown, so we force it as the same as all (if unique), or the second one (if not) with a warning.
The function returns a Dates.CompoundPeriod because it helps finding a sensible default from a milliseconds period (e.g. 1 Hour or 1 Day).
Arguments
datetime::Vector{Dates.DateTime}: Vector of datesverbose::Bool=true: Iftrue, print a warning if the duration is not
constant between the time steps.
Examples
julia> timesteps_durations([Dates.DateTime(2019, 1, 1, 0), Dates.DateTime(2019, 1, 1, 1)])
2-element Vector{Dates.CompoundPeriod}:
1 hour
1 hourPlantMeteo.to_daily — Method
to_daily(df, args...)
to_daily(t::T, args...) where {T<:TimeStepTable{<:Atmosphere}}Transform a DataFrame object or TimeStepTable{<:Atmosphere} with sub-daily time steps (e.g. 1h) to a daily time-step table.
Arguments
t: aTimeStepTable{<:Atmosphere}with sub-daily time steps (e.g. 1h)args: a list of transformations to apply to the data, formates as forDataFrames.jl
Notes
Default transformations are applied to the data, and can be overriden by the user. The default transformations are:
:date => (x -> unique(Dates.Date.(x))) => :date: the date is transformed into aDateobject:duration => sum => :duration: the duration is summed:T => minimum => :Tmin: we use the minimum temperature for Tmin:T => maximum => :Tmax: and the maximum temperature for Tmax:Precipitations => sum => :Precipitations: the precipitations are summed:Rh => mean => :Rh: the relative humidity is averaged:Wind, :P, :Rh, :Cₐ, :e, :eₛ, :VPD, :ρ, :λ, :γ, :ε, :Δ, :clearnessare
all averaged
[:Ri_SW_f, :duration] => ((x, y) -> sum(x .* Dates.toms.(y)) * 1.0e-9) => :Ri_SW_f: the irradiance is integrated, so its unit changes from W m⁻² to MJ m⁻² d⁻¹- All other irradiance variables are also integrated (see the code for details)
Note that the default transformations can be overriden by the user, and that the default transformations are only applied if the variable is available.
Examples
using PlantMeteo, Dates
# Forecast for today and tomorrow:
period = [today(), today()+Dates.Day(1)]
w = get_weather(48.8566, 2.3522, period)
# Convert to daily:
w_daily = to_daily(w, :T => mean => :Tmean)PlantMeteo.vapor_pressure — Method
vapor_pressure(Tₐ, Rh; check=true)Vapor pressure (kPa) at given temperature (°C) and relative hunidity (0-1).
Arguments
Tₐ(Celsius degree): air temperatureRh(0-1): relative humiditycheck(Bool): if true, check thatRhis between 0 and 1
Examples
vapor_pressure(25.0, 0.4)PlantMeteo.vpd — Method
vpd(Rh,Tₐ)Compute vapor pressure deficit (kPa) from the air relative humidity (0-1) and temperature (°C).
The computation simply uses vpd = eₛ - e.
Examples
vpd(0.4,25.0)PlantMeteo.vpd_from_e — Method
vpd_from_e(e,Tₐ)Compute vapor pressure deficit (kPa) from the air vapor pressure (kPa) and temperature (°C).
The computation simply uses vpd = eₛ - e.
Examples
vpd_from_e(1.5,25.0)PlantMeteo.write_weather — Method
write_weather(
file, w;
vars=setdiff(propertynames(w), ATMOSPHERE_COMPUTED),
duration=Dates.Minute
)Write the weather data to a file.
Arguments
file: aStringrepresenting the path to the file to writew: aTimeStepTable{Atmosphere}vars: a vector of variables to write (as symbols). By default, all variables are written except the ones that
can be recomputed (see ATMOSPHERE_COMPUTED). If nothing is given, all variables are written.
duration: the unit for formating the duration of the time steps. By default, it isDates.Minute.
Examples
using PlantMeteo, Dates
file = joinpath(dirname(dirname(pathof(PlantMeteo))),"test","data","meteo.csv")
w = read_weather(
file,
:temperature => :T,
:relativeHumidity => (x -> x ./100) => :Rh,
:wind => :Wind,
:atmosphereCO2_ppm => :Cₐ,
date_format = DateFormat("yyyy/mm/dd")
)
write_weather("meteo.csv", w)PlantMeteo.write_weather_ — Method
write_weather_(file, w)Write the weather data to a file with a special-commented yaml header for the metadata.