Fitting temperature- and moisture-based models to infection data using R


In many processes of the disease cycle, such as infection - one of the most critical components for disease forecasting - the interaction between temperature and the duration of moisture determine the amount of succesful infection sites and resulting disease severity. This post shows how to fit, in R language, a form of the Analytis Beta model to infection data as a function of temperature and an asymptotic regression model to infection as a function of moisture duration.

Emerson Del Ponte


Studies on the relationship between environmental variables and disease in the field are fundamental to develop empirical (statistical) disease prediction models (Del Ponte et al. 2006). On the other hand, relationships studied in the controlled environment (laboratory or greenhouse) provide a basis to develop fundamental models or sub-models that describe specific processes such as sporulation, dispersal, infection and incubation (Magarey et al. 2005; Krause and Massie 1975). These submodels can be further incorporated into mechanistic models that mimic advance of the disease cycle (Rossi et al. 2008), or directly into predictive systems where the infection submodel is the most critical information for disease occurrence (MacHardy 1989). The infection models are based on regression equations of various forms (Magarey et al. 2005; Biggs 1988; De Wolf and Isard 2007; Dalla Pria et al. 2006).

Here, we will fit a Beta generalized model (Hau and Kranz 1990) to data on the response to temperature and an asymptotic regression model to data on the response to wetness duration. The integration of the two models can be used to develop contour or surface-response plots.

Data source

We will use a subset of the data obtained from a study conducted under controlled conditions that aimed to assess the influence of temperature and leaf wetness duration on infection and subsequent symptom development of citrus canker in sweet orange (Dalla Pria et al. 2006).

The data used here is only for severity on the cultivar Hamlin. The mean value was extracted from Figures 1 and 2 (see below). The left plot is for the response to temperature and the right plot is for the response wetness duration. The response is severity of infection.

The data was extracted using the R package digitize as shown here on this tweet.

Modelling the effect of temperature

Let’s enter the data manually. Where \(t\) is the temperature and \(y\) is the severity on leaves.

temp <- tibble::tribble(
  ~t, ~y,
12.0, 0.00,
15.0, 0.1,
20.0, 0.5,
25.0, 1.2,
30.0, 1.5,
35.0, 1.2,
40.0, 0.1

Fit the Beta generalized model (Hau and Kranz 1990). The model can be written as:

\[ y = a*((t - b )^d)*((c - t)^e) \]

where \(b\) and \(c\) represent minimum and maximum temperatures, respectively, for the development of the disease, \(a\), \(d\) and \(e\) are parameters to be estimated, \(t\) is the temperature and \(y\) is disease severity. We need the {minpack.lm} library to avoid parameterization issues.

fit_temp <- nlsLM(
  y ~ a * ((t - b) ^ d) * ((c - t) ^ e),
  start = list(
    a = 0,
    b = 10,
    c = 40,
    d = 1.5,
    e = 1
  algorithm = "port",
  data = temp

Formula: y ~ a * ((t - b)^d) * ((c - t)^e)

   Estimate Std. Error t value Pr(>|t|)    
a  0.001303   0.006295   0.207    0.855    
b 11.999999   4.875414   2.461    0.133    
c 40.137236   0.346763 115.748 7.46e-05 ***
d  1.760101   1.193017   1.475    0.278    
e  0.830868   0.445213   1.866    0.203    
Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1

Residual standard error: 0.1121 on 2 degrees of freedom

Algorithm "port", convergence message: Relative error between `par' and the solution is at most `ptol'.
modelr::rsquare(fit_temp, temp)
[1] 0.9898275

Store the model parameters in objects.

          a           b           c           d           e 
 0.00130259 11.99999931 40.13723602  1.76010097  0.83086798 
a <- fit_temp$m$getAllPars()[1]
b <- fit_temp$m$getAllPars()[2]
c <- fit_temp$m$getAllPars()[3]
d <- fit_temp$m$getAllPars()[4]
e <- fit_temp$m$getAllPars()[5]

Create a data frame for predictions at each temperature unit from 10 to 45 degree Celsius.

t <- seq(10, 45, 0.1)
y <- a * ((t - b) ^ d) * ((c - t) ^ e)
dat <- data.frame(t, y)

Plot the observed and predicted data using {ggplot2} package.

dat |>
  ggplot(aes(t, y)) +
  geom_line() +
  geom_point(data = temp, aes(t, y)) +
  theme_classic(base_size = 16) +
  labs(x = "Temperature", y = "Severity")

Modelling the effect of wetness duration

Again, we enter the data manually. The \(x\) is wetness duration in hours and \(y\) is severity.

wet <- tibble::tribble(~ x, ~ y,
                       0 ,  0,
                       4 ,  0.50,
                       8 ,  0.81,
                       12,  1.50,
                       16,  1.26,
                       20,  2.10,
                       24,  1.45)

Now we fit a three-parameter asymptotic regression model. These models describe a limited growth, where y approaches an horizontal asymptote as x tends to infinity. This equation is also known as Monomolecular Growth, Mitscherlich law or von Bertalanffy law. See this tutorial for comprehensive information about fitting several non-linear regression models in R.

The model can be written as

\[ y = c1 + (d1-c1)*(1-exp(-x/e1)) \]

where \(c\) is the lower limit (at \(x = 0\)), the parameter d is the upper limit and the parameter and \(e\) (greater than 0) is determining the steepness of the increase as \(x\).

We will solve the model again using the nlsLM function. We should provide initial values for the three parameters.

fit_wet <- nlsLM(y ~ c1 + (d1 - c1) * (1 - exp(-x / e1)),
                 start = list(c1 = 0.5,
                              d1 = 3,
                              e1 = 1),
                 data = wet)


Formula: y ~ c1 + (d1 - c1) * (1 - exp(-x/e1))

   Estimate Std. Error t value Pr(>|t|)  
c1 -0.04898    0.31182  -0.157   0.8828  
d1  2.00746    0.70594   2.844   0.0467 *
e1 11.63694    9.33183   1.247   0.2804  
Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1

Residual standard error: 0.3296 on 4 degrees of freedom

Number of iterations to convergence: 7 
Achieved convergence tolerance: 1.49e-08
modelr::rsquare(fit_wet, wet)
[1] 0.8532282

Store the value of the parameters in the respective object.

HW <- seq(0, 24, 0.1)
c1 <-  fit_wet$m$getAllPars()[1]
d1 <- fit_wet$m$getAllPars()[2]
e1 <- fit_wet$m$getAllPars()[3]
y <-  (c1 + (d1 - c1) * (1 - exp(-HW / e1)))
dat2 <- data.frame(HW, y)

Now we can plot the results and the original data.

dat2 |>
  ggplot(aes(HW, y)) +
  geom_line() +
  geom_point(data = wet, aes(x, y)) +
  theme_classic(base_size = 16) +
  labs(x = "Wetness duration", y = "Severity")

Integrate the models

Integrate the two equations to create a contour plot. We need a data frame for the interaction between \(t\) and hours of wetness. Then, we obtain the disease value for each combination of \(t\) and \(HW\).

t <- rep(1:40, 40)
HW <- rep(1:40, each = 40)
dis <-
  (a * (t - b) ^ d) * ((c - t) ^ e) * (c1 + (d1 - c1) * (1 - exp(-HW / e1)))
validation <- data.frame(t, HW, dis)

Now the contour plot can be visualized using {ggplot2} and {geomtextpath} packages.

ggplot(validation, aes(t, HW, z = dis)) +
  geom_contour_filled(bins = 8, alpha = 0.7) +
  geom_textcontour(bins = 8,
                   size = 2.5,
                   padding = unit(0.05, "in")) +
  theme_light() +
  theme(legend.position = "right") +
  ylim(0, 40) +
  labs(y = "Wetness duration (hours)",
       fill = "Severity",
       x = "Temperature (Celcius)")

That’s it. Feel free to reach me in case of questions!

Biggs, A. R. 1988. Influence of temperature and wetness duration on infection of peach and sweet cherry fruits byMonilinia fructicola. Phytopathology. 78:1352 Available at:
Dalla Pria, M., Christiano, R. C. S., Furtado, E. L., Amorim, L., and Bergamin Filho, A. 2006. Effect of temperature and leaf wetness duration on infection of sweet oranges by Asiatic citrus canker. Plant Pathology. 55:657–663 Available at:
De Wolf, E. D., and Isard, S. A. 2007. Disease Cycle Approach to Plant Disease Prediction. Annual Review of Phytopathology. 45:203–220 Available at:
Del Ponte, E. M., Godoy, C. V., Li, X., and Yang, X. B. 2006. Predicting Severity of Asian Soybean Rust Epidemics with Empirical Rainfall Models. Phytopathology®. 96:797–803 Available at:
Hau, B., and Kranz, J. 1990. Mathematics and statistics for analyses in epidemiology. In Springer Berlin Heidelberg, p. 12–52. Available at:
Krause, R. A., and Massie, L. B. 1975. Predictive Systems: Modern Approaches to Disease Control. Annual Review of Phytopathology. 13:31–47 Available at:
MacHardy, W. E. 1989. A revision of mills’s criteria for predicting apple scab infection periods. Phytopathology. 79:304 Available at:
Magarey, R. D., Sutton, T. B., and Thayer, C. L. 2005. A Simple Generic Infection Model for Foliar Fungal Plant Pathogens. Phytopathology®. 95:92–100 Available at:
Rossi, V., Caffi, T., Giosuè, S., and Bugiani, R. 2008. A mechanistic model simulating primary infections of downy mildew in grapevine. Ecological Modelling. 212:480–491 Available at:



If you see mistakes or want to suggest changes, please create an issue on the source repository.


Text and figures are licensed under Creative Commons Attribution CC BY 4.0. Source code is available at, unless otherwise noted. The figures that have been reused from other sources don't fall under this license and can be recognized by a note in their caption: "Figure from ...".