# Get started with ambre

    library(ambre)
    set.seed(2024)

    library(dplyr)
    library(purrr)

## What ambre does, and for whom

If you plan to irrigate crops with treated wastewater (water reuse, or REUT), you need to know whether the water is safe. `ambre` answers that question with QMRA – Quantitative Microbial Risk Assessment – estimating the health risk of a programme for the reuse of treated wastewater for exposed populations: field workers, local residents and consumers of the products.

The benchmark is the World Health Organization target of no more than 1e-6 DALY per person per year (one micro disability-adjusted life-year). `ambre` follows the multi-barrier idea: pathogens are cut down not only by the wastewater-treatment plant but also by on-field practices (drip instead of sprinklers, buffer distances, washing, peeling…), all modelled from one shared log-reduction database. This article is the guided tour; the other vignettes go deeper on each piece.

## Installation and the bundled example data

`ambre` lives on the INRAE forge. Install it once with `remotes`:

    remotes::install_git(
      "https://forge.inrae.fr/reversaal/reut/ambre-package.git"
    )

You do not need your own data to follow along. The package ships four example input files – ready-made Excel scenarios – that every function in this tour reads through `system.file()`:

    list.files(system.file(package = "ambre"), pattern = "\\.xlsx$")
    #> [1] "input_1culture_2pop.xlsx"
    #> [2] "input_cas_apprentissage_complet.xlsx"

They grow in size from a single crop and population (`input_1culture_1pop.xlsx`) to a full learning case of 35 exposed populations (`input_cas_apprentissage_complet.xlsx`). We will use the two-row file `input_1culture_2pop.xlsx` throughout.

## The `scenario` object

Everything in `ambre` revolves around one table, the scenario. You build it from an Excel file with `create_scenario()`:

    scenario <- create_scenario(
      system.file("input_1culture_2pop.xlsx", package = "ambre")
    )
    dim(scenario)
    #> [1]  2 24

Each row is one combination of crop x exposed population x exposure path. The example has two rows, so two situations to assess. Let’s look at the columns that matter most:

    dplyr::glimpse(
      scenario[, c("CropName", "PopulationName", "PathName",
                   "CropID", "PopulationID", "PathID", "config")]
    )
    #> Rows: 2
    #> Columns: 7
    #> $ CropName       <chr> "Tomato", "Corn seed"
    #> $ PopulationName <chr> "Irrigation staff", "Maintenance staff"
    #> $ PathName       <chr> "Ingestion of water droplets during maintenance of the …
    #> $ CropID         <dbl> 6, 1
    #> $ PopulationID   <dbl> 1, 2
    #> $ PathID         <dbl> 1, 4
    #> $ config         <list> [[<spec_tbl_df[3 x 10]>], [<spec_tbl_df[38 x 13]>], [[<…

The human-readable names you typed in Excel (`CropName`, `PopulationName`, `PathName`) are each resolved to an integer key – `CropID`, `PopulationID`, `PathID` – that `ambre` uses to look values up in its internal database.

The last column, `config`, is the interesting one: it is a list-column holding, on every row, a full private copy of the bundled `config_ambre` database. As the QMRA pipeline runs, each step writes its results back into that per-row config, so a scenario carries both its inputs and its growing outputs in a single object. You rarely touch `config` by hand – the run functions below do it for you.

## Your first run

The fastest way to a result is `run_qmra_treatment()`. Give it a scenario file and one or more pathogens; it runs the whole workflow – simulate inflow concentration and exposure volume to calculate the initial dose, simulate log-reduction from the treatment scheme to calculate the final dose of exposure, calculate infection and illness probability, and DALYs – and returns a set of figures.

The function prints a running commentary as it works, so we send that noise to nowhere with `results = "hide"` and look at the pictures afterwards:

    library(dplyr)
    scenario <- create_scenario(system.file("input_1culture_2pop.xlsx", package = "ambre"))
    regulation_reduction <- config_ambre$regulation$regulation_value |> filter(Country == "France") |>
                              select(-c(Concentration, Country, RegulationID))
    regulation_concentration <- config_ambre$regulation$regulation_value |> filter(Country == "France") |>
                              select(-c(Country, RegulationID, Reduction))
    plots <- run_qmra_initial_situation(scenario = scenario,
                         pathogen = c("Campylobacter jejuni", "Norovirus"),
                         regulationLog = regulation_reduction,
                         regulationConcentration = regulation_concentration)

What comes back is a named list of five `ggplot` objects:

    names(plots)
    #> [1] "logreduction"               "dalys"
    #> [3] "regul_matrix_log"           "regul_matrix_concentration"

These five steps trace the journey of raw water through to its effects on health. (This run takes into account only treatment-type barriers; to also include agricultural practice-type barriers, see `run_qmra_barrier()` and the comparative vignette below.)

## Reading the four figures

Print each element to see it. Here is what each one tells you.

Log-reduction – how many log10 units each barrier in the train removes according to pathogen group simulated (Bacteria, Viruses, Protozoa); a taller box means a more effective barrier.

    plots$logreduction
    #> $Bacteria

    #>
    #> $Viruses

DALYs – the disability-adjusted life-years lost per person per year, on a log scale. The red line marks the objective: boxes sitting below it meet the tolerable-risk goal, boxes crossing above it do not. The default value of 1e-6 DALY corresponds to the WHO target.

    plots$dalys
    #> $`Campylobacter jejuni`

    #>
    #> $Norovirus

Each plot is a boxplot for a reason: `ambre` is a Monte-Carlo engine that repeats the calculation many times, so a result is a range of plausible values, not a single number. Reading that spread is the subject of its own vignette.

Regulation matrix

The outcome of an exposure scenario can be assessed in terms of regulatory compliance with regard to: - Log‑reduction (the decrease in pathogen concentration expressed in log10 units: regulation_matrix_log()

    plots$regul_matrix_log

Crop name | Target water class | Bacteria | Viruses
--- | --- | --- | ---
Tomato | B | 12 | 8
Corn seed | D | 12 | 8

- Residual concentration of the contaminant in the effluent: regulation_matrix_concentration()

    plots$regul_matrix_concentration

Crop name | Target water class | Campylobacter jejuni | Norovirus
--- | --- | --- | ---
Corn seed | D | 0 | 100
Tomato | B | 0 | 100

The background color indicates whether the reduction results are sufficient in relation to the regulations (green: complies with or falls below regulatory requirements; red: fails to meet regulatory requirements)

## Other figures

Other figures can be generated :

Inflow pathogen concentration

The `plot_inflow()` function generates a violin plot showing the distribution of pathogen inflow concentrations simulated in a scenario. Each violin represents the variability of the inflow concentration for one pathogen, while colors distinguish pathogen groups.

    scenario_with_inflow <- inflow_concentration(scenario = scenario,
     pathogenName = c("Campylobacter jejuni", "Norovirus"))
    #> Simulated pathogen: Campylobacter jejuni
    #> Create 1000 random distribution(s): uniform (n: 60, min: 100.000000, max: 5000.000000)
    #> Simulated pathogen: Norovirus
    #> Create 1000 random distribution(s): uniform (n: 60, min: 0.000000, max: 1000000.000000)
    #> Providing inflow events ... ok. (0.00 secs)
    #> Providing inflow paras ... ok. (0.00 secs)
    #> Simulated pathogen: Campylobacter jejuni
    #> Create 1000 random distribution(s): uniform (n: 48, min: 100.000000, max: 5000.000000)
    #> Simulated pathogen: Norovirus
    #> Create 1000 random distribution(s): uniform (n: 48, min: 0.000000, max: 1000000.000000)
    #> Providing inflow events ... ok. (0.00 secs)
    #> Providing inflow paras ... ok. (0.00 secs)
    plot_inflow(scenario_with_inflow)

A violin plot combines the features of a boxplot and a kernel density plot to visualize the distribution of simulated values.

- The height of each violin represents the range of simulated inflow concentrations for a given pathogen.
- The width of the violin at a given y-value is proportional to the density of simulations at that concentration:
  - wider sections indicate that many simulations produced similar inflow concentrations;
  - narrower sections indicate that fewer simulations fall within that range.
- The shape of the violin can reveal important characteristics of the distribution, such as skewness, multimodality, or the presence of multiple concentration regimes.
- Colors identify the pathogen group (Bacteria, Viruses, or Protozoa), allowing comparisons both within and between groups.

Because the y-axis is displayed on a log₁₀ scale, equal vertical distances correspond to multiplicative (rather than additive) differences in concentration. This scaling is particularly useful for microbial concentrations, which often span several orders of magnitude.

When interpreting the figure, wider violins indicate a higher probability of observing concentrations within a given range, while taller violins indicate a broader overall variability in simulated inflow concentrations.

Volume of exposure

The `plot_volumes()` function generates boxplots of the exposure volumes simulated for each combination of exposed population and exposure pathway. The plots are faceted by crop, making it possible to compare exposure volumes across crops, populations, and transmission pathways.

    scenario_volume <-
      scenario_with_inflow |>
      mutate(
        volume = map(
          .x = config,
          .f = ~ simulate_exposure(config = .x)
        )
      )
    #> Simulated exposure: volume per event
    #> Distribution set from 'triangle' to 'uniform' because 'min' equals 'max'
    #> Create 1000 random distribution(s): uniform (n: 60, min: 0.001000, max: 0.001000)
    #> Simulated exposure: volume per event
    #> Distribution set from 'triangle' to 'uniform' because 'min' equals 'max'
    #> Create 1000 random distribution(s): uniform (n: 48, min: 0.001000, max: 0.001000)

    plot_volumes(scenario_volume)

Each boxplot summarizes the distribution of simulated exposure volumes:

- the horizontal line inside the box represents the median exposure volume;
- the box spans the interquartile range (IQR), containing the middle 50% of simulated values;
- the whiskers extend to the most extreme observations within 1.5 × IQR from the box;
- observations beyond the whiskers are displayed as outliers;
- if a boxplot appears as a single horizontal line, all simulated values are identical. In this case, the minimum, first quartile, median, third quartile, and maximum are equal, indicating that no variability was observed in the simulated exposure volume.

Comparing boxplots allows users to assess differences in the typical exposure volume, the variability of simulated events, and the presence of extreme values among populations, crops, and exposure pathways.

Probability of infection

The `plot_infection_probability()` function generates boxplots of the simulated annual probability of infection for each pathogen. Separate plots are produced for each pathogen, allowing comparisons of infection probabilities across exposed populations and crops.

    scenario_dose_ini <- initial_dose_calculation(scenario_volume)

    scenario_scheme <- update_treatment_scheme(scenario_dose_ini)

    scenario_with_logreduc_and_co <- scenario_scheme |>
      mutate( log_reduction = map(config, simulate_treatment))
    #> Create 1000 random distribution(s): uniform (n: 60, min: 1.000000, max: 2.000000)
    #> Create 1000 random distribution(s): uniform (n: 60, min: 1.000000, max: 2.000000)
    #> Create 1000 random distribution(s): uniform (n: 60, min: 1.000000, max: 3.000000)
    #> Create 1000 random distribution(s): uniform (n: 60, min: 1.000000, max: 2.000000)
    #> Create 1000 random distribution(s): uniform (n: 60, min: 5.000000, max: 7.000000)
    #> Create 1000 random distribution(s): uniform (n: 60, min: 2.000000, max: 4.000000)
    #> Simulated treatment: Q.1 - Activated Sludge for Bacteria
    #> Simulated treatment: Q.1 - Activated Sludge for Viruses
    #> Simulated treatment: Q.2 - Maturation Pond for Bacteria
    #> Simulated treatment: Q.2 - Maturation Pond for Viruses
    #> Simulated treatment: Q.6 - Chlorination for Bacteria
    #> Simulated treatment: Q.6 - Chlorination for Viruses
    #> Simulated treatment: Q.1 - Activated Sludge for Bacteria
    #> Simulated treatment: Q.1 - Activated Sludge for Viruses
    #> Simulated treatment: Q.2 - Maturation Pond for Bacteria
    #> Simulated treatment: Q.2 - Maturation Pond for Viruses
    #> Simulated treatment: Q.6 - Chlorination for Bacteria
    #> Simulated treatment: Q.6 - Chlorination for Viruses
    #> Create 1000 random distribution(s): uniform (n: 48, min: 1.000000, max: 2.000000)
    #> Create 1000 random distribution(s): uniform (n: 48, min: 1.000000, max: 2.000000)
    #> Create 1000 random distribution(s): uniform (n: 48, min: 1.000000, max: 3.000000)
    #> Create 1000 random distribution(s): uniform (n: 48, min: 1.000000, max: 2.000000)
    #> Create 1000 random distribution(s): uniform (n: 48, min: 5.000000, max: 7.000000)
    #> Create 1000 random distribution(s): uniform (n: 48, min: 2.000000, max: 4.000000)
    #> Simulated treatment: Q.1 - Activated Sludge for Bacteria
    #> Simulated treatment: Q.1 - Activated Sludge for Viruses
    #> Simulated treatment: Q.2 - Maturation Pond for Bacteria
    #> Simulated treatment: Q.2 - Maturation Pond for Viruses
    #> Simulated treatment: Q.6 - Chlorination for Bacteria
    #> Simulated treatment: Q.6 - Chlorination for Viruses
    #> Simulated treatment: Q.1 - Activated Sludge for Bacteria
    #> Simulated treatment: Q.1 - Activated Sludge for Viruses
    #> Simulated treatment: Q.2 - Maturation Pond for Bacteria
    #> Simulated treatment: Q.2 - Maturation Pond for Viruses
    #> Simulated treatment: Q.6 - Chlorination for Bacteria
    #> Simulated treatment: Q.6 - Chlorination for Viruses

    scenario_final_dose_and_co_test <- final_dose_calculation(scenario_with_logreduc_and_co)

    scenario_inf_proba_and_co <- infection_probability_calculation(scenario_final_dose_and_co_test)

    scenario_illness_proba_and_co <- illness_probability_calculation(scenario_inf_proba_and_co)

    scenario_dalys_and_co <- dalys_calculation(scenario_illness_proba_and_co)

    scenario_risk_total_and_co <-get_risk_total(scenario_dalys_and_co)

    plot_infection_probability(scenario_risk_total_and_co)
    #> $`Campylobacter jejuni`

    #>
    #> $Norovirus

Each boxplot summarizes the distribution of simulated annual infection probabilities. Comparing boxplots allows users to identify differences in both the magnitude and the variability of annual infection probabilities among exposed populations and crops for each pathogen simulated.

## Where to go next

You now have the mental map. From here, pick the thread you need – open any of these articles with `vignette()`, or browse them on the package website:

- `vignette("b-treatment-vs-multibarrier", package = "ambre")` – treatment plant only versus adding on-field barriers, side by side.
- `vignette("c-input-file", package = "ambre")` – how to write your own Excel scenario, and the allowed crops, populations, paths and barriers.
- `vignette("d-interpreting-risk", package = "ambre")` – reading results against the WHO 1e-6 DALY target and the EU 2020/741 framing.
- `vignette("g-monte-carlo-engine", package = "ambre")` – why every result is a range, and how the repeat x event simulation works.
- `vignette("e-economic-analysis", package = "ambre")` – putting a cost on a reuse scenario alongside its risk.
- `vignette("h-config-ambre", package = "ambre")` – a tour of the bundled `config_ambre` database that powers every calculation.
- `vignette("f-what-if-exposure", package = "ambre")` – calibrating exposure volume and frequency to test “what if” questions.