Visualizing outputs and data

Output structure

PlantSimEngine's run! functions return for each timestep the state of the variables that were requested using the tracked_outputs kwarg (or the state of every variable if this kwarg was left unspecified). Multi-scale simulations also indicate which organ and MTG node these state variables are related to.

Here's an example indicating how to plot output data using CairoMakie, a package used for plotting.

# ] add PlantSimEngine, DataFrames, CSV
using PlantSimEngine, PlantMeteo, DataFrames, CSV

# Include the model definition from the examples folder:
using PlantSimEngine.Examples

# Import the example meteorological data:
meteo_day = CSV.read(joinpath(pkgdir(PlantSimEngine), "examples/meteo_day.csv"), DataFrame, header=18)

# Define the list of models for coupling:
models = ModelList(
    ToyLAIModel(),
    Beer(0.6),
    status=(TT_cu=cumsum(meteo_day[:, :TT]),),  # Pass the cumulated degree-days as input to `ToyLAIModel`, this could also be done using another model
)

# Run the simulation:
sim_outputs = run!(models, meteo_day)
TimeStepTable{Status{(:TT_cu, :LAI, :aPPFD)...}(365 x 3):
╭─────┬──────────┬────────────┬───────────╮
 Row     TT_cu         LAI      aPPFD 
       Float64     Float64    Float64 
├─────┼──────────┼────────────┼───────────┤
   1       0.0  0.00554988  0.0476221 
   2       0.0  0.00554988  0.0260688 
   3       0.0  0.00554988  0.0377774 
   4       0.0  0.00554988  0.0468871 
   5       0.0  0.00554988  0.0545266 
   6       0.0  0.00554988  0.0567055 
   7       0.0  0.00554988  0.0521376 
   8       0.0  0.00554988  0.0563642 
   9       0.0  0.00554988  0.0349947 
  10       0.0  0.00554988  0.0168016 
  11       0.0  0.00554988  0.0606171 
  12       0.0  0.00554988  0.0486197 
  13    0.5625  0.00557831  0.0357278 
  14  0.945833  0.00559777  0.0519777 
  15  0.979167  0.00559946  0.0564167 

╰─────┴──────────┴────────────┴───────────╯
                           350 rows omitted

The output data is displayed as a by default as a TimeStepTable. It is also possible to filter which variables are kept via the optional tracked_outputs keyword argument.

Plotting outputs

Using CairoMakie, one can plot out selected variables :

Note

You will need to add CairoMakie to your environment through Pkg mode first.

# Plot the results:
using CairoMakie

fig = Figure(resolution=(800, 600))
ax = Axis(fig[1, 1], ylabel="LAI (m² m⁻²)")
lines!(ax, sim_outputs[:TT_cu], sim_outputs[:LAI], color=:mediumseagreen)

ax2 = Axis(fig[2, 1], xlabel="Cumulated growing degree days since sowing (°C)", ylabel="aPPFD (mol m⁻² d⁻¹)")
lines!(ax2, sim_outputs[:TT_cu], sim_outputs[:aPPFD], color=:firebrick1)

fig
Example block output

TimeStepTables and DataFrames

The output data is usually stored in a TimeStepTable structure defined in PlantMeteo.jl, which is a fast DataFrame-like structure with each time step being a Status. It can be also be any Tables.jl structure, such as a regular DataFrame. Weather data is also usually stored in a TimeStepTable but with each time step being an Atmosphere.

Another simple way to get the results is to transform the outputs into a DataFrame. Which is very easy because the TimeStepTable implements the Tables.jl interface:

using DataFrames
sim_outputs_df = PlantSimEngine.convert_outputs(sim_outputs, DataFrame)
sim_outputs_df[[1, 2, 3, 363, 364, 365], :]
6×3 DataFrame
RowTT_cuLAIaPPFD
Float64Float64Float64
10.00.005549880.0476221
20.00.005549880.0260688
30.00.005549880.0377774
42189.270.00.0
52192.90.00.0
62193.820.00.0

It is also possible to create DataFrames from specific variables:

df = DataFrame(aPPFD=sim_outputs[:aPPFD][1], LAI=sim_outputs.LAI[1], Ri_PAR_f=meteo.Ri_PAR_f[1])

Which can also be useful for Parameter fitting .