Author: Kaique S. Alves
Date: 2026-04-12

# Working with the PowderyMildew dataset

#### Kaique S. Alves

#### 2026-04-12

    library(epifitter)
    library(dplyr)
    library(ggplot2)
    library(cowplot)
    theme_set(cowplot::theme_half_open(font_size = 12))
    data("PowderyMildew")

## Overview

`PowderyMildew` is an experimental dataset included in `epifitter`. It contains disease progress curves for powdery mildew in organic tomato under different irrigation systems and soil moisture levels.

The data are derived from the study by Lage, Marouelli, and Cafe-Filho (2019) on powdery mildew management under different irrigation configurations in organic tomato.

The dataset is especially useful for demonstrating workflows with:

- a real epidemic dataset rather than simulated curves;
- repeated observations over time within experimental blocks;
- treatment comparisons using summary measures and fitted models.

## Load the data

Use the usual `data()` interface for packaged datasets.

    data("PowderyMildew")
    knitr::kable(head(PowderyMildew, 12), digits = 4)

irrigation_type | moisture | block | time | sev
--- | --- | --- | --- | ---
Drip | High moisture | 1 | 0 | 0.011
Drip | High moisture | 2 | 0 | 0.011
Drip | High moisture | 3 | 0 | 0.011
Drip | High moisture | 1 | 7 | 0.034
Drip | High moisture | 2 | 7 | 0.040
Drip | High moisture | 3 | 7 | 0.036
Drip | High moisture | 1 | 14 | 0.114
Drip | High moisture | 2 | 14 | 0.109
Drip | High moisture | 3 | 14 | 0.097
Drip | High moisture | 1 | 21 | 0.126
Drip | High moisture | 2 | 21 | 0.120
Drip | High moisture | 3 | 21 | 0.103

The dataset contains five variables:

- `irrigation_type` for the irrigation system;
- `moisture` for the soil moisture regime;
- `block` for the experimental block;
- `time` for the assessment date;
- `sev` for disease severity on a proportional scale.

## Inspect the experimental structure

    PowderyMildew %>%
      distinct(irrigation_type, moisture, block) %>%
      arrange(irrigation_type, moisture, block) %>%
      knitr::kable()

| irrigation_type | moisture | block
--- | --- | --- | ---
1 | Drip | High moisture | 1
2 | Drip | High moisture | 2
3 | Drip | High moisture | 3
91 | Furrow | Moderate moisture | 1
92 | Furrow | Moderate moisture | 2
93 | Furrow | Moderate moisture | 3
31 | MS | High moisture | 1
32 | MS | High moisture | 2
33 | MS | High moisture | 3
61 | MS | Moderate moisture | 1
62 | MS | Moderate moisture | 2
63 | MS | Moderate moisture | 3
121 | MS above canopy | High moisture | 1
122 | MS above canopy | High moisture | 2
123 | MS above canopy | High moisture | 3
151 | MS above canopy | Moderate moisture | 1
152 | MS above canopy | Moderate moisture | 2
153 | MS above canopy | Moderate moisture | 3
181 | Overhead | High moisture | 1
182 | Overhead | High moisture | 2
183 | Overhead | High moisture | 3
211 | Overhead | Moderate moisture | 1
212 | Overhead | Moderate moisture | 2
213 | Overhead | Moderate moisture | 3

This is a repeated-measures dataset: each block was assessed across several time points within each irrigation-by-moisture combination.

## Visualize treatment means over time

A useful first step is to summarize replicated blocks within each treatment and visualize the mean disease progress curve.

    pm_summary <- PowderyMildew %>%
      group_by(irrigation_type, moisture, time) %>%
      summarise(
        mean_sev = mean(sev),
        .groups = "drop"
      )

    knitr::kable(head(pm_summary, 12), digits = 4)

irrigation_type | moisture | time | mean_sev
--- | --- | --- | ---
Drip | High moisture | 0 | 0.0110
Drip | High moisture | 7 | 0.0367
Drip | High moisture | 14 | 0.1067
Drip | High moisture | 21 | 0.1163
Drip | High moisture | 28 | 0.1527
Drip | High moisture | 35 | 0.1810
Drip | High moisture | 42 | 0.3237
Drip | High moisture | 49 | 0.3543
Drip | High moisture | 56 | 0.4190
Drip | High moisture | 63 | 0.4340
Furrow | Moderate moisture | 0 | 0.0100
Furrow | Moderate moisture | 7 | 0.0373

    ggplot(pm_summary, aes(time, mean_sev, color = irrigation_type)) +
      geom_point(size = 1.8) +
      geom_line(linewidth = 0.9) +
      facet_wrap(~ moisture) +
      labs(
        title = "Mean powdery mildew progress by treatment",
        x = "Time",
        y = "Mean severity",
        color = "Irrigation"
      )

## Calculate AUDPC and AUDPS per experimental unit

Because `block` identifies repeated experimental units, a common analysis is to calculate one summary value per block within each treatment.

    pm_area <- PowderyMildew %>%
      group_by(irrigation_type, moisture, block) %>%
      summarise(
        audpc = AUDPC(time = time, y = sev, aggregate = "none"),
        audps = AUDPS(time = time, y = sev, aggregate = "none"),
        .groups = "drop"
      )

    knitr::kable(pm_area, digits = 4)

irrigation_type | moisture | block | audpc | audps
--- | --- | --- | --- | ---
Drip | High moisture | 1 | 13.1530 | 14.7105
Drip | High moisture | 2 | 13.8040 | 15.3615
Drip | High moisture | 3 | 13.3700 | 14.9275
Furrow | Moderate moisture | 1 | 13.7270 | 15.3615
Furrow | Moderate moisture | 2 | 14.1645 | 15.7990
Furrow | Moderate moisture | 3 | 13.8670 | 15.4210
MS | High moisture | 1 | 8.3020 | 9.6005
MS | High moisture | 2 | 9.3625 | 10.6260
MS | High moisture | 3 | 8.3755 | 9.5620
MS | Moderate moisture | 1 | 10.7205 | 12.1905
MS | Moderate moisture | 2 | 11.3330 | 12.7645
MS | Moderate moisture | 3 | 11.6970 | 13.1285
MS above canopy | High moisture | 1 | 3.8395 | 4.3225
MS above canopy | High moisture | 2 | 4.2245 | 4.7775
MS above canopy | High moisture | 3 | 4.1930 | 4.7740
MS above canopy | Moderate moisture | 1 | 4.6935 | 5.2535
MS above canopy | Moderate moisture | 2 | 5.2010 | 5.8940
MS above canopy | Moderate moisture | 3 | 5.0365 | 5.6455
Overhead | High moisture | 1 | 3.5770 | 3.9865
Overhead | High moisture | 2 | 3.5665 | 3.9795
Overhead | High moisture | 3 | 3.9725 | 4.4940
Overhead | Moderate moisture | 1 | 3.9935 | 4.4695
Overhead | Moderate moisture | 2 | 3.7065 | 4.1825
Overhead | Moderate moisture | 3 | 3.8360 | 4.2910

This differs from pooling all rows together. If all blocks are passed at once, `AUDPC()` and `AUDPS()` assume that you want one treatment-level summary curve and aggregate repeated observations at each time point before calculating the area.

To compare treatments visually, it is often useful to plot one point per block on top of a boxplot.

    pm_area_long <- pm_area %>%
      tidyr::pivot_longer(
        cols = c(audpc, audps),
        names_to = "summary_measure",
        values_to = "value"
      )

    facet_aud <- if (requireNamespace("lemon", quietly = TRUE)) {
      lemon::facet_rep_grid(summary_measure ~ moisture, scales = "free_y")
    } else {
      ggplot2::facet_grid(summary_measure ~ moisture, scales = "free_y")
    }

    ggplot(
      pm_area_long,
      aes(irrigation_type, value, fill = irrigation_type)
    ) +
      geom_boxplot(
        width = 0.65,
        outlier.shape = NA,
        alpha = 0.28,
        linewidth = 0.6
      ) +
      geom_jitter(
        aes(color = irrigation_type),
        width = 0.12,
        height = 0,
        size = 2.4,
        alpha = 0.85
      ) +
      facet_aud +
      labs(
        title = "Area-under-the-curve summaries by treatment",
        x = "Irrigation treatment",
        y = "Summary value",
        color = "Irrigation"
      ) +
      cowplot::theme_half_open(font_size = 12) +
      background_grid(major = "y", minor = "none") +
      theme(
        legend.position = "none",
        axis.text.x = element_text(angle = 20, hjust = 1),
        strip.background = element_rect(fill = "#e7f1f3", color = NA),
        strip.text = element_text(face = "bold")
      )

## Fit a model to one observed curve

To work with a single disease progress curve, first filter one treatment-by-block combination.

    single_curve <- PowderyMildew %>%
      filter(
        irrigation_type == "Drip",
        moisture == "High moisture",
        block == 1
      )

    knitr::kable(single_curve, digits = 4)

| irrigation_type | moisture | block | time | sev
--- | --- | --- | --- | --- | ---
1 | Drip | High moisture | 1 | 0 | 0.011
4 | Drip | High moisture | 1 | 7 | 0.034
7 | Drip | High moisture | 1 | 14 | 0.114
10 | Drip | High moisture | 1 | 21 | 0.126
13 | Drip | High moisture | 1 | 28 | 0.160
16 | Drip | High moisture | 1 | 35 | 0.183
19 | Drip | High moisture | 1 | 42 | 0.297
22 | Drip | High moisture | 1 | 49 | 0.331
25 | Drip | High moisture | 1 | 56 | 0.389
28 | Drip | High moisture | 1 | 63 | 0.434

    ggplot(single_curve, aes(time, sev)) +
      geom_point(size = 2, color = "#15616d") +
      geom_line(linewidth = 0.9, color = "#15616d") +
      labs(
        title = "Single observed disease progress curve",
        subtitle = "Drip irrigation, high moisture, block 1",
        x = "Time",
        y = "Severity"
      )

Now fit the candidate models to that curve.

    single_fit <- fit_lin(time = single_curve$time, y = single_curve$sev)
    knitr::kable(single_fit$stats_all, digits = 4)

best_model | model | r | r_se | r_ci_lwr | r_ci_upr | v0 | v0_se | r_squared | RSE | CCC | y0 | y0_ci_lwr | y0_ci_upr
--- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | ---
1 | Gompertz | 0.0253 | 0.0018 | 0.0212 | 0.0293 | -1.3374 | 0.0659 | 0.9625 | 0.1120 | 0.9809 | 0.0222 | 0.0119 | 0.0379
2 | Monomolecular | 0.0089 | 0.0006 | 0.0074 | 0.0104 | -0.0319 | 0.0240 | 0.9603 | 0.0408 | 0.9797 | -0.0324 | -0.0912 | 0.0232
3 | Logistic | 0.0593 | 0.0076 | 0.0418 | 0.0768 | -3.5948 | 0.2833 | 0.8844 | 0.4819 | 0.9386 | 0.0267 | 0.0141 | 0.0501
4 | Exponential | 0.0504 | 0.0078 | 0.0323 | 0.0685 | -3.5629 | 0.2932 | 0.8374 | 0.4989 | 0.9115 | 0.0284 | 0.0144 | 0.0558

    plot_fit(single_fit, point_size = 2, line_size = 0.9)

## Fit models to many observed curves at once

`fit_multi()` is useful when each treatment-by-block combination should be fitted separately.

    pm_multi_fit <- fit_multi(
      time_col = "time",
      intensity_col = "sev",
      data = PowderyMildew,
      strata_cols = c("irrigation_type", "moisture", "block")
    )

    knitr::kable(head(pm_multi_fit$Parameters, 12), digits = 4)

irrigation_type | moisture | block | best_model | model | r | r_se | r_ci_lwr | r_ci_upr | v0 | v0_se | r_squared | RSE | CCC | y0 | y0_ci_lwr | y0_ci_upr
--- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | ---
Drip | High moisture | 1 | 1 | Gompertz | 0.0253 | 0.0018 | 0.0212 | 0.0293 | -1.3374 | 0.0659 | 0.9625 | 0.1120 | 0.9809 | 0.0222 | 0.0119 | 0.0379
Drip | High moisture | 1 | 2 | Monomolecular | 0.0089 | 0.0006 | 0.0074 | 0.0104 | -0.0319 | 0.0240 | 0.9603 | 0.0408 | 0.9797 | -0.0324 | -0.0912 | 0.0232
Drip | High moisture | 1 | 3 | Logistic | 0.0593 | 0.0076 | 0.0418 | 0.0768 | -3.5948 | 0.2833 | 0.8844 | 0.4819 | 0.9386 | 0.0267 | 0.0141 | 0.0501
Drip | High moisture | 1 | 4 | Exponential | 0.0504 | 0.0078 | 0.0323 | 0.0685 | -3.5629 | 0.2932 | 0.8374 | 0.4989 | 0.9115 | 0.0284 | 0.0144 | 0.0558
Drip | High moisture | 2 | 1 | Gompertz | 0.0269 | 0.0019 | 0.0225 | 0.0314 | -1.3544 | 0.0718 | 0.9609 | 0.1221 | 0.9801 | 0.0208 | 0.0103 | 0.0375
Drip | High moisture | 2 | 2 | Monomolecular | 0.0100 | 0.0010 | 0.0078 | 0.0122 | -0.0456 | 0.0360 | 0.9313 | 0.0612 | 0.9645 | -0.0466 | -0.1372 | 0.0367
Drip | High moisture | 2 | 3 | Logistic | 0.0615 | 0.0073 | 0.0447 | 0.0784 | -3.6037 | 0.2729 | 0.8987 | 0.4643 | 0.9466 | 0.0265 | 0.0143 | 0.0486
Drip | High moisture | 2 | 4 | Exponential | 0.0515 | 0.0075 | 0.0341 | 0.0689 | -3.5582 | 0.2819 | 0.8535 | 0.4795 | 0.9209 | 0.0285 | 0.0149 | 0.0546
Drip | High moisture | 3 | 1 | Gompertz | 0.0268 | 0.0019 | 0.0225 | 0.0311 | -1.3806 | 0.0696 | 0.9628 | 0.1184 | 0.9811 | 0.0187 | 0.0094 | 0.0338
Drip | High moisture | 3 | 2 | Monomolecular | 0.0097 | 0.0009 | 0.0076 | 0.0118 | -0.0473 | 0.0339 | 0.9347 | 0.0576 | 0.9663 | -0.0484 | -0.1336 | 0.0303
Drip | High moisture | 3 | 3 | Logistic | 0.0621 | 0.0069 | 0.0461 | 0.0781 | -3.6884 | 0.2591 | 0.9093 | 0.4409 | 0.9525 | 0.0244 | 0.0136 | 0.0435
Drip | High moisture | 3 | 4 | Exponential | 0.0524 | 0.0072 | 0.0359 | 0.0689 | -3.6411 | 0.2672 | 0.8703 | 0.4546 | 0.9307 | 0.0262 | 0.0142 | 0.0486

This output keeps the original stratification variables, which makes it easier to compare fitted parameters among irrigation systems, moisture regimes, and blocks.

## Practical guidance

- Use `data("PowderyMildew")` to load the bundled dataset.
- Use grouped summaries by `block` when you want one AUDPC or AUDPS value per experimental unit.
- Use grouped means over time when the goal is a treatment-level visualization.
- Use `fit_lin()` for a quick model ranking on one observed curve.
- Use `fit_multi()` when you want to fit many treatment-block curves in a single workflow.

## Data source

The `PowderyMildew` dataset included in `epifitter` comes from:

Lage, D. A. C., Marouelli, W. A., and Cafe-Filho, A. C. (2019). Management of powdery mildew and behaviour of late blight under different irrigation configurations in organic tomato. Crop Protection, 125, 104886.