Three-parameter logistic model fitted to cumulative leaf number per plant as a function of accumulated GDD, with ANOVA on parameters and all derivative-based critical points.
Overview
Leaf number (leaves plant⁻¹) follows a sigmoidal accumulation pattern driven by thermal time. The logistic model uses a higher asymptote (β₁ ≈ 150 leaves) and a shallower steepness (β₃ ≈ 0.005) relative to leaf area and plant height, reflecting slower saturation kinetics of leaf appearance.
Critical points from the first and second derivatives are computed at the block level and subjected to two-factor ANOVA, consistent with the approach used for leaf area and plant height.
\[
y = \frac{\beta_1}{1 + e^{\;\beta_3(\beta_2 - x)}}
\]
Inflection point (GDD at maximum leaf appearance rate)
β₃
Steepness coefficient (leaf appearance rate)
Required packages
Show code
library(rio) # Data importlibrary(tidyverse) # Data wrangling and visualisationlibrary(metan) # mean_by(), doo()library(broom) # tidy() – NLS summary as data framelibrary(AgroR) # FAT2DBC() – two-factor ANOVA in RCBDlibrary(patchwork) # Combine ggplot panelslibrary(hydroGOF) # gof() – goodness-of-fit metricslibrary(gt) # Professional tables
Load data
Show code
# Import the pre-computed plot-mean dataset.# Each row = one season × cultivar × block × date mean (already averaged across plants).df_model <-import("../df_model_cresc_medias.xlsx")
Fit logistic models – leaf number
Show code
# Response variable: 'n' (number of leaves per plant)formula_nf <- n_mean ~ b1 / (1+exp((b3 * (b2 - gda))))# Starting values:# b1 = 150 → higher asymptote than leaf area (more leaves)# b2 = 400 → inflection around 400 GDD# b3 = 0.005 → shallower sigmoid (slower saturation of leaf count)start_nf <-list(b1 =150, b2 =400, b3 =0.005)# Increase maxiter: the default 50 iterations is often insufficient for# flat curves with small b3 values.mod_nf <- df_model |>filter(data !="04/11") |>group_by(epoca, cultivar, bloco) |>doo(~nls(formula_nf,data = .,start = start_nf,control =list(maxiter =500)))
Goodness of fit
Show code
# Helper function: extract R² and AIC from a single NLS model objectget_gof <-function(model) { aic <-AIC(model) bic <-BIC(model) fit <- model$m$fitted() res <- model$m$resid() obs <- fit + res g <- hydroGOF::gof(sim = fit, obs = obs, digits =4) r2 <- g["R2", ] rmse <- g["RMSE", ] mae <- g["MAE", ] d <- g["d", ]data.frame(aic = aic, bic = bic, r2 = r2, rmse = rmse, mae = mae, d = d)}gof_nf <- mod_nf |>mutate(map_dfr(.x = data, .f =~get_gof(.))) |>select(-data) |>mutate(variable ="leaf_number")# Display goodness of fit table with gtgof_nf |>gt() |>tab_header(title ="Supplementary Table S7",subtitle ="Goodness-of-fit metrics for Leaf Number logistic models (per block)" ) |>fmt_number(columns =where(is.numeric), decimals =4)
Supplementary Table S7
Goodness-of-fit metrics for Leaf Number logistic models (per block)
epoca
bloco
cultivar
aic
bic
r2
rmse
mae
d
variable
E1
B1
D
93.4669
95.4065
0.9478
8.5180
7.2684
0.9866
leaf_number
E1
B2
D
110.3749
112.3146
0.8012
17.2306
12.5903
0.9434
leaf_number
E1
B3
D
104.4329
106.3725
0.8700
13.4516
9.9129
0.9638
leaf_number
E1
B1
M
95.0313
96.9710
0.9374
9.0917
7.2052
0.9839
leaf_number
E1
B2
M
96.9291
98.8688
0.9479
9.8399
8.3223
0.9865
leaf_number
E1
B3
M
105.9092
107.8488
0.8256
14.3050
11.5220
0.9509
leaf_number
E2
B1
D
76.8690
78.0793
0.9293
7.5724
4.6942
0.9814
leaf_number
E2
B2
D
92.3730
93.5833
0.7167
16.4399
11.5470
0.9155
leaf_number
E2
B3
D
79.2999
80.5103
0.9137
8.5511
6.9266
0.9772
leaf_number
E2
B1
M
82.5137
83.7241
0.9058
10.0417
8.3373
0.9750
leaf_number
E2
B2
M
88.9461
90.1564
0.8313
13.8511
9.0146
0.9534
leaf_number
E2
B3
M
71.3668
72.5771
0.9656
5.7512
4.8502
0.9913
leaf_number
Show code
saveRDS(gof_nf, "../results/gof_nf.rds")
Extract estimated parameters and compute critical points
Show code
# broom::tidy() converts each NLS object into a tidy data frame;# pivot_wider() places b1, b2, b3 as separate columns.parameters_nf <- mod_nf |>mutate(data =map(data, ~.x |>tidy())) |>unnest(data) |>select(epoca, cultivar, bloco, term, estimate) |>pivot_wider(names_from = term,values_from = estimate)
Logistic curves fitted to cumulative leaf number per plant as a function of accumulated GDD, faceted by sowing season. Points = treatment means. The semi-transparent point (04/11) was excluded from fitting.
First (left) and second (right) derivatives of the fitted logistic curves for leaf number. Points mark the inflection (●), maximum acceleration (▲), and maximum deceleration (▽) thresholds per cultivar × season combination.