Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
c8b4bc1
Add initial fns from pressure testing report
pratikunterwegs Mar 12, 2026
db03465
Move pressure testing plotting
pratikunterwegs Mar 12, 2026
50f6b0d
Clean up funs and add constants
pratikunterwegs Mar 12, 2026
13d6244
Clean up fns and add constants
pratikunterwegs Mar 13, 2026
8aa8494
Rename files
pratikunterwegs Mar 13, 2026
de1eda6
Add checks and docs for pressure testing fns
pratikunterwegs Apr 20, 2026
46d3d97
Add pkg constants
pratikunterwegs Apr 20, 2026
63e5871
Add pkg helpers
pratikunterwegs Apr 20, 2026
ffff840
WIP separate plot prep from plot code
pratikunterwegs Apr 20, 2026
d0237fb
WIP add docs and pkg infra
pratikunterwegs Apr 21, 2026
4a52fbb
Reorganise docs
pratikunterwegs Apr 21, 2026
bba30c5
WIP plotting and prep fns impact diagnostics
pratikunterwegs Apr 21, 2026
a455c5a
Add constants
pratikunterwegs Apr 21, 2026
beb2a07
Update plot prep and plot fns
pratikunterwegs Apr 21, 2026
0424f17
Fixes from initial test run
pratikunterwegs Apr 22, 2026
386be9b
Update infra, bump to v0.0.4
pratikunterwegs Apr 22, 2026
43753fb
Rename fn file, fix arg name
pratikunterwegs Apr 22, 2026
14f1829
Adding pine countries to constants for impact plotting key countries
zegibney Apr 29, 2026
0d446cd
Adding plotting functions from rapid-model-run-impact report which pl…
zegibney Apr 29, 2026
fce44b8
Fix for enabling package checks
zegibney Jun 1, 2026
291e905
Adding more meaningful checks and assertions
zegibney Jun 1, 2026
8a1be98
Defining example data and fvps dataframes
zegibney Jun 1, 2026
876048a
Adding impact plots to pkgdown documentation
zegibney Jun 1, 2026
a87d836
Merge branch 'develop' into develop_zoe
zegibney Jul 3, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/R-CMD-check.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ on:
push:
branches: [main, master]
pull_request:
branches: [main, master]
branches: [*]

name: R-CMD-check

Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/lint-changed-files.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
on:
workflow_dispatch:
pull_request:
branches: [main, master]
branches: [*]
paths:
- '**.R'
- '**.Rmd'
Expand Down
8 changes: 8 additions & 0 deletions R/constants.R
Original file line number Diff line number Diff line change
Expand Up @@ -215,3 +215,11 @@ DEF_TOUCHSTONE_OLD_OLD <- "202110"
#'
#' @export
COLOUR_VIMC <- "#008080"

#' @name constants
#'
#' @examples
#' pine
#'
#' @export
pine <- c("PAK", "IND", "NGA", "ETH")
274 changes: 274 additions & 0 deletions R/fn_plotting_impact.R

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Overall comment on these fns - since they prepare data before plotting it, I would separate the preparation steps from the plotting steps, and have paired functions prep_plot_X() and plot_X(), which is the pattern we've adopted in {vimcheck}. In a report, these would/should be pipe-able, data %>% prep_plot_X() %>% plot_X(),

Original file line number Diff line number Diff line change
@@ -0,0 +1,274 @@
#' Plot central impact estimates by cohort and year.
#'
#' Produces faceted plots of central impact estimates for priority countries,
#' stratified either by birth cohort or by year of vaccination.
#' Impact metrics include cases, deaths, DALYs, and YLLs.
#'
#' @param data A tibble containing impact estimates.
#' @param burden_type Burden metric used to evaluate impact. burden_type can be: cases, deaths, dalys, yll.
#' @param title Title of the plot to be rendered
#' @param view Charactar scalar. The way impact is assigned, either by birth cohort ("cohort") or by year of vaccination ("year").
#'
#' @return ggplot object showing central impact estimates
#'
#' @examples
#'
#' # Create example data
#' impact_data <- tibble::tibble(
#' country = c("A", "A", "B", "B"),
#' year = c(2020, 2021, 2020, 2021),
#' birth_cohort = c(2000, 2001, 2000, 2001),
#' burden_outcome = c("deaths", "cases", "deaths", "cases"),
#' impact = c(15, 5, 14, 8),
#' short_name = c("short1", "short2", "short3", "short4")
#' )
#' plot_impact(
#' data = impact_data,
#' burden_type = "cases",
#' title = "Cases averted",
#' view = "year"
#' )
Comment thread
zegibney marked this conversation as resolved.
#'
#' @export
plot_impact <- function(
data,
burden_type = c("cases", "deaths", "dalys", "yll"),
title,
view = c("cohort", "year")
){
checkmate::assert_tibble(data, min.rows = 1L, min.cols = 1L)
Comment thread
zegibney marked this conversation as resolved.

required_cols <- c("country", "burden_outcome", "impact", "short_name")

checkmate::assert_names(
names(data),
must.include = required_cols
)

checkmate::assert_character(title, len = 1)

burden_type <- rlang::arg_match(burden_type)
view <- rlang::arg_match(view)

Impact <- dplyr::filter(data,
.data$country %in% pine,
.data$burden_outcome == burden_type,
.data$impact != 0)

if(nrow(Impact) > 0){
# ---- Cohort view ----
if(view == "cohort"){

checkmate::assert_names(names(data), must.include = "birth_cohort")

Impact <- Impact %>% dplyr::rename(Impact, cohort = .data$birth_cohort)

cols_to_select <- c("country", "cohort", "impact", "short_name")

Impact <- dplyr::select(Impact, all_of(cols_to_select))

p <- ggplot(
Impact,
aes(
x = .data$cohort,
y = .data$impact,
ymin = .data$impact,
ymax = .data$impact,
fill = as.character(.data$short_name)
)
) +
ggplot::geom_ribbon(alpha = 0.3) +
ggplot::geom_line(aes(colour = .data$short_name), size = 0.5)+
ggplot::geom_point(aes(colour = .data$short_name), size = 0.5)+
theme_vimc() + #TODO: to check where the theme definition is saved as may not be right for this plot

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The theme is in R/fn_plotting_helpers.R - you could either modify the default theme or build off it if you want this figure to look different.

facet_wrap(country~., scales = "free_y") +
labs(
x = "Birth cohort",
y = paste(burden_type, "averted"),
title = title
) +
theme(
legend.position="bottom",
legend.key.size= unit(0.5, 'cm'),
legend.key.width = unit(0.3, 'cm')
)

} else { # ---- Year (non-cohort) view ----
cols_to_select <- c("country", "year", "impact", "short_name")

checkmate::assert_names(names(data), must.include = "year")

Impact <- dplyr::select(Impact, all_of(cols_to_select))

p <- ggplot (
Impact,
aes(
x = .data$year,
y = .data$impact,
ymin = .data$impact,
ymax = .data$impact,
fill = .data$short_name
)
) +
ggplot::geom_ribbon(alpha = 0.3)+
ggplot::geom_line(aes(colour = .data$short_name), size = 0.5)+
ggplot::geom_point(aes(colour = .data$short_name), size = 0.5)+
theme_vimc() + #TODO: same note as above re theme definition
facet_wrap(country~., scales = "free_y")+
labs(
x = "Year",
y = paste(burden_type, "averted"),
title = title
) +
theme(
legend.position="bottom",
legend.key.size= unit(0.5, 'cm'),
legend.key.width = unit(0.3, 'cm')
)
}
} else {
p <- "No estimates in the data." #TODO: both here and in the below plot returning p may be an issue? Can you think of a better way?
}
Comment on lines +129 to +131

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This could be handled in a plotting preparation function that errors if there is no PINE data? That way the plotting fn always returns a plot.

return(p)

}

#' Plot coverage and fully vaccinated persons (FVPs)
#'
#' Generates plots of routine vaccine coverage and fully vaccinated
#' persons (FVPs) over time for selected countries.
#'
#' @param fvps A tibble showing the number of fvps (fully vaccinated persons)
#' by country, year and scenario/activity type.
#'
#' @return A named list with two ggplot objects:
#' \describe{
#' \item{coverage}{A plot of routine vaccine coverage over time.}
#' \item{fvps}{A plot of fully vaccinated persons over time.}
#' }
#' @examples
#'
#' # Create example data
#' fvps <- tibble::tibble(
#' country = c("AGO", "AGO", "BEN", "BEN"),
#' year = c(2020, 2021, 2020, 2021),
#' activity_type = c("routine", "campaign", "routine", "campaign"),
#' scenario_type = c("default", "default", "default", "default"),
#' vaccine = c("measles", "measles", "measles", "measles"),
#' coverage_adjusted = c(0.8, 0.85, 0.4, 0.7),
#' fvps = c(1000000, 1200000, 800000, 900000)
#' )

#' plots <- plot_coverage_fvps(fvps)
Comment thread
zegibney marked this conversation as resolved.
#' plots$coverage
#' plots$fvps
#'
#' @export
plot_coverage_fvps <- function(fvps){
checkmate::assert_tibble(fvps, min.rows = 1L, min.cols = 1L)
Comment on lines +167 to +168

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pretty much the same general suggestions as for the preceding fn.


required_cols <- c(
"country",
"activity_type",
"scenario_type",
"vaccine",
"coverage_adjusted",
"year",
"fvps"
)

checkmate::assert_names(
names(fvps),
must.include = required_cols
)


fvps <- dplyr::filter(fvps, .data$country %in% pine)

cov <- dplyr::filter(fvps, .data$activity_type == "routine")

cov <- dplyr::mutate(cov,
vaccine_delivery = paste(.data$scenario_type, .data$vaccine, sep = "_"),
coverage_adjusted = round(.data$coverage_adjusted*100, 2)
)

cols_to_select <- c("country", "vaccine_delivery", "year", "coverage_adjusted")

cov <- dplyr::select(cov, all_of(cols_to_select))

cov <- dplyr::rename(cov, coverage = .data$coverage_adjusted)

fvps <- dplyr::mutate(fvps,
vaccine_delivery = paste(.data$scenario_type, .data$activity_type, sep = "_")
)
cols_to_select <- c("country", "vaccine_delivery", "year", "fvps")

fvps <- dplyr::select(fvps, all_of(cols_to_select))

fvps <- dplyr::group_by(fvps,
.data$country,
.data$vaccine_delivery,
.data$year)

fvps <- dplyr::summarise(fvps,
fvps = round(sum(.data$fvps)/1e6, 2),
.groups = "drop"
)
if(nrow(cov) > 0){
p <- ggplot(
cov,
aes(
x = .data$year,
y = .data$coverage,
ymin = 0,
ymax = 1,
fill = .data$vaccine_delivery)
) +
ggplot::geom_line(aes(colour = .data$vaccine_delivery), size = 0.5) +
theme_vimc() + #TODO: same note as above
facet_wrap(country~., scales = "free_y")+
labs(
x = "Year",
y = "Coverage (%)",
title = "Routine vaccine coverage"
) +
theme(
legend.position="bottom",
legend.key.size= unit(0.5, 'cm'),
legend.key.width = unit(0.3, 'cm')
)

} else {
p <- "There is no routine coverage in the database."
}


q <- ggplot(
fvps,
aes(
x = .data$year,
y = .data$fvps,
ymin = .data$fvps,
ymax = .data$fvps, #TODO: min/max both here and above seem to be the same so may be irrelevant to define
fill = .data$vaccine_delivery
)
) +
geom_point(aes(colour = .data$vaccine_delivery), size = 0.5) +
theme_vimc()+ #TODO: same note above on theme
facet_wrap(country~., scales = "free_y") +
labs(
x = "Year",
y = "FVPs (in millions)",
title = "FVPs"
) +
theme(
legend.position="bottom",
legend.key.size = unit(0.5, 'cm'),
legend.key.width = unit(0.3, 'cm')
)

return(list(
coverage = p,
fvps = q
))
}
29 changes: 29 additions & 0 deletions man/plot_coverage_fvps.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

35 changes: 35 additions & 0 deletions man/plot_impact.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading