---
title: "Epidemiological maps"
output:
  rmarkdown::html_vignette:
    toc: true
    toc_depth: 2
vignette: >
  %\VignetteIndexEntry{Epidemiological maps}
  %\VignetteEngine{knitr::rmarkdown}
  %\VignetteEncoding{UTF-8}
---

## Introduction

Epidemiological maps are powerful tools for visualizing the geographic distribution of disease cases, helping identify spatial clusters, regional patterns, and areas of concern. The `epi_map()` function creates choropleth maps using spatial boundary data, allowing you to overlay epidemiological data on geographic regions. The function supports both static (ggplot2) and interactive (leaflet) maps with extensive customization options.

## Prerequisites

```{r setup, include=FALSE}
knitr::opts_chunk$set(
  echo = TRUE,
  eval = TRUE,
  fig.width = 8,
  fig.height = 6,
  warning = FALSE,
  message = FALSE
)
```

```{r load-libraries, eval=TRUE, echo=TRUE}
library(epiviz)
library(dplyr)
library(sf)
```

## Example 1: Static map with un-merged shapefile

Local authority maps provide detailed spatial resolution for outbreak investigation and local surveillance. This example shows Staph aureus detections by London local authorities using an un-merged shapefile approach.

### Prepare the data

```{r prepare-london-data, eval=TRUE, echo=TRUE}
# Aggregate detections by local authority for London (as used in tests)
london_detections <- epiviz::lab_data %>%
  filter(
    region == "London",
    organism_species_name == "STAPHYLOCOCCUS AUREUS"
  ) %>%
  group_by(local_authority_name) %>%
  summarise(detections = n(), .groups = "drop")
```

### Create the static map with un-merged shapefile

```{r static-london-map, fig.cap="Static choropleth of Staphylococcus aureus detections across London local authorities.", fig.alt="Choropleth map shading London local authority districts by the number of Staphylococcus aureus detections."}
epi_map(
  dynamic = FALSE,  # Create static map
  params = list(
    df = london_detections,
    value_col = "detections",           # Variable containing values to map
    data_areacode = "local_authority_name",  # Variable containing area names
    inc_shp = FALSE,                    # Use un-merged shapefile approach
    shp_name = epiviz::London_LA_boundaries_2023,  # Spatial boundary data
    shp_areacode = "LAD23NM",          # Variable in boundary data matching area names
    fill_palette = "Blues",            # Color palette
    fill_opacity = 1.0,                # Opacity of filled areas
    break_intervals = NULL,            # Use automatic breaks
    break_labels = NULL,               # Use automatic labels
    force_cat = TRUE,                  # Force categorical breaks
    n_breaks = NULL,                   # Use default number of breaks
    labels = NULL,                     # No custom labels
    map_title = "Staphylococcus Aureus detections in London Local Authority Districts",
    map_title_size = 13,
    map_title_colour = "black",
    map_footer = "",
    map_footer_size = 12,
    map_footer_colour = "black",
    area_labels = TRUE,                # Show area labels
    area_labels_topn = NULL,           # Show all areas
    legend_title = "Number of \nDetections",
    legend_pos = "right",
    map_zoom = data.frame(LONG = c(-0.12776), LAT = c(51.50735), zoom = c(8.7)),  # London center
    border_shape_name = NULL,          # No border shapefile
    border_code_col = NULL,
    border_areaname = NULL
  )
)
```

**Interpretation**: This map reveals the spatial distribution of Staph aureus detections across London local authorities, highlighting areas with higher case counts that may require targeted public health interventions.

## Example 2: Static map with pre-merged shapefile

When you have already merged your data with spatial boundaries, you can use the pre-merged approach for more control over the mapping process.

### Prepare the pre-merged data

```{r prepare-merged-map-data, eval=TRUE, echo=TRUE}
# Aggregate detections by region
regional_detections <- epiviz::lab_data %>%
  filter(organism_species_name == "KLEBSIELLA PNEUMONIAE") %>%
  group_by(region) %>%
  summarise(detections = n(), .groups = "drop") %>%
  mutate(map_labels = paste0(region, ": \n", detections))  # Create custom labels

# Get the shapefile
shape <- epiviz::PHEC_boundaries_2016

# Merge data with shapefile
merged_data <- left_join(x = shape, y = regional_detections,
                        by = c("phec16nm" = "region"))
```

### Create the static map with pre-merged data

```{r static-merged-map, fig.cap="Static choropleth of Klebsiella pneumoniae detections across UK public health regions.", fig.alt="Choropleth map of UK public health regions coloured by Klebsiella pneumoniae detections with categorical legend."}
epi_map(
  dynamic = FALSE,  # Create static map
  params = list(
    df = merged_data,                  # Pre-merged data
    value_col = "detections",
    data_areacode = "phec16nm",        # Area code in merged data
    inc_shp = TRUE,                    # Use pre-merged approach
    shp_name = NULL,                   # No separate shapefile needed
    shp_areacode = NULL,               # No separate shapefile needed
    fill_palette = "YlOrRd",          # Yellow to red palette
    fill_opacity = 0.7,                # Semi-transparent fill
    break_intervals = c(0, 500, 1000, 1500, 2000, 2500),  # Custom break intervals
    break_labels = c("0-499", "500-999", "1000-1499", "1500-1999", "2000-2499", "2500+"),  # Custom labels
    force_cat = TRUE,                  # Force categorical breaks
    n_breaks = NULL,
    labels = "map_labels",             # Use custom labels
    map_title = "Number of Klebsiella Pneumoniae detections \nin UK public health regions",
    map_title_size = 12,
    map_title_colour = "orangered",
    map_footer = "Map represents simulated test data only.",
    map_footer_size = 10,
    map_footer_colour = "black",
    area_labels = FALSE,               # Don't show area labels (using custom labels)
    area_labels_topn = NULL,
    legend_title = "Number of \nDetections",
    legend_pos = "topright",
    map_zoom = NULL,                   # Use default zoom
    border_shape_name = NULL,
    border_code_col = NULL,
    border_areaname = NULL
  )
)
```

**Interpretation**: This map shows the regional distribution of Klebsiella pneumoniae detections across UK public health regions, with custom break intervals and labels for better interpretation.

## Example 3: Static map with border shapefile

Border shapefiles allow you to add additional geographic context, such as country boundaries or administrative regions.

### Create the map with border shapefile

```{r static-border-map, fig.cap="Static choropleth with UK country border overlays.", fig.alt="Choropleth map of UK public health regions coloured by detections with outlines for Wales, Northern Ireland, and Scotland."}
# Use the same regional data
regional_detections <- epiviz::lab_data %>%
  filter(organism_species_name == "KLEBSIELLA PNEUMONIAE") %>%
  group_by(region) %>%
  summarise(detections = n(), .groups = "drop") %>%
  mutate(map_labels = paste0(region, ": \n", detections))

# Get shapefiles
shape <- epiviz::PHEC_boundaries_2016
border_shape <- epiviz::UK_boundaries_2023

epi_map(
  dynamic = FALSE,  # Create static map
  params = list(
    df = regional_detections,
    value_col = "detections",
    data_areacode = "region",
    inc_shp = FALSE,                   # Use un-merged approach
    shp_name = shape,                  # Main shapefile
    shp_areacode = "phec16nm",         # Area code in main shapefile
    fill_palette = "YlOrRd",
    fill_opacity = 0.7,
    break_intervals = c(0, 500, 1000, 1500, 2000, 2500),
    break_labels = c("0-499", "500-999", "1000-1499", "1500-1999", "2000-2499", "2500+"),
    force_cat = TRUE,
    n_breaks = NULL,
    labels = "map_labels",
    map_title = "Number of Klebsiella Pneumoniae detections \nin UK public health regions",
    map_title_size = 12,
    map_title_colour = "orangered",
    map_footer = "Map represents simulated test data only.",
    map_footer_size = 10,
    map_footer_colour = "black",
    area_labels = FALSE,
    area_labels_topn = NULL,
    legend_title = "Number of \nDetections",
    legend_pos = "topright",
    map_zoom = NULL,
    # Border shapefile parameters
    border_shape_name = border_shape,  # Border shapefile
    border_code_col = "CTRY23NM",     # Area code in border shapefile
    border_areaname = c("Wales", "Northern Ireland", "Scotland")  # Areas to highlight
  )
)
```

**Interpretation**: This map includes border shapefiles to show country boundaries, providing additional geographic context for the regional analysis.

## Example 4: Interactive map with un-merged shapefile

Interactive maps are ideal for surveillance dashboards, allowing users to zoom, pan, and hover for detailed information.

### Create the interactive map

```{r interactive-london-map, fig.cap="Interactive choropleth of Staphylococcus aureus detections across London.", fig.alt="Interactive map of London local authorities coloured by detection counts."}
epi_map(
  dynamic = TRUE,   # Create interactive leaflet map
  params = list(
    df = london_detections,
    value_col = "detections",
    data_areacode = "local_authority_name",
    inc_shp = FALSE,
    shp_name = epiviz::London_LA_boundaries_2023,
    shp_areacode = "LAD23NM",
    fill_palette = "Blues",
    fill_opacity = 1.0,
    break_intervals = NULL,
    break_labels = NULL,
    force_cat = TRUE,
    n_breaks = NULL,
    labels = NULL,
    map_title = "Staphylococcus Aureus detections in London Local Authority Districts",
    map_title_size = 13,
    map_title_colour = "black",
    map_footer = "",
    map_footer_size = 12,
    map_footer_colour = "black",
    area_labels = TRUE,
    area_labels_topn = NULL,
    legend_title = "Number of \nDetections",
    legend_pos = "topright",
    map_zoom = data.frame(LONG = c(-0.12776), LAT = c(51.50735), zoom = c(8.7)),
    border_shape_name = NULL,
    border_code_col = NULL,
    border_areaname = NULL
  )
)
```

**Interpretation**: The interactive map allows detailed exploration of the spatial distribution, with hover information showing exact detection counts for each local authority.

## Example 5: Interactive map with border shapefile and area labels

Interactive maps can include border shapefiles and custom area labeling for comprehensive geographic analysis.

### Create the interactive map with borders and labels

```{r interactive-border-map, fig.cap="Interactive choropleth of Klebsiella pneumoniae detections with country borders and labels.", fig.alt="Interactive map of UK public health regions coloured by detections with highlighted country borders and top area labels."}
epi_map(
  dynamic = TRUE,   # Create interactive leaflet map
  params = list(
    df = regional_detections,
    value_col = "detections",
    data_areacode = "region",
    inc_shp = FALSE,
    shp_name = shape,
    shp_areacode = "phec16nm",
    fill_palette = "YlOrRd",
    fill_opacity = 0.7,
    break_intervals = c(0, 500, 1000, 1500, 2000, 2500),
    break_labels = c("0-499", "500-999", "1000-1499", "1500-1999", "2000-2499", "2500+"),
    force_cat = TRUE,
    n_breaks = NULL,
    labels = "map_labels",
    map_title = "Number of Klebsiella Pneumoniae detections \nin UK public health regions",
    map_title_size = 12,
    map_title_colour = "orangered",
    map_footer = "Map represents simulated test data only.",
    map_footer_size = 10,
    map_footer_colour = "black",
    area_labels = TRUE,                # Show area labels
    area_labels_topn = 5,              # Show top 5 areas
    legend_title = "Number of \nDetections",
    legend_pos = "topright",
    map_zoom = data.frame(LONG = c(-2.89479), LAT = c(54.793409), zoom = c(5)),  # UK center
    border_shape_name = border_shape,
    border_code_col = "CTRY23NM",
    border_areaname = c("Wales", "Northern Ireland", "Scotland")
  )
)
```

**Interpretation**: This comprehensive interactive map combines regional data visualization with country borders and area labeling, providing multiple layers of geographic information for surveillance analysis.

## Tips for epidemiological maps

1. **Data preparation**: Always aggregate your epidemiological data to the appropriate geographic level before mapping. The function expects pre-calculated counts or values.

2. **Shapefile approaches**:
   - **Un-merged** (`inc_shp = FALSE`): Use when you have separate data and shapefile
   - **Pre-merged** (`inc_shp = TRUE`): Use when you've already joined data with spatial boundaries

3. **Area code matching**: Ensure your area names in the data exactly match the names in the boundary data. Use `unique()` to check for mismatches.

4. **Color palettes**: Choose appropriate color schemes:
   - `"Blues"` for general use
   - `"YlOrRd"` for intensity (yellow to red)
   - `"Reds"` for high values
   - `"Greens"` for positive indicators

5. **Break intervals**: Use custom `break_intervals` and `break_labels` for meaningful categorization:
   ```r
   break_intervals = c(0, 500, 1000, 1500, 2000, 2500)
   break_labels = c("0-499", "500-999", "1000-1499", "1500-1999", "2000-2499", "2500+")
   ```

6. **Map zoom**: Use `map_zoom` to center and zoom the map appropriately:
   ```r
   map_zoom = data.frame(LONG = c(-0.12776), LAT = c(51.50735), zoom = c(8.7))
   ```

7. **Border shapefiles**: Add `border_shape_name` for additional geographic context like country boundaries.

8. **Area labels**: Use `area_labels = TRUE` and `area_labels_topn` to show labels for the most important areas.

9. **Interactive features**: Set `dynamic = TRUE` for interactive maps with zooming, panning, and hover information.

10. **Opacity**: Adjust `fill_opacity` (0-1) to control transparency of filled areas.

11. **Legend positioning**: Use `legend_pos` to place the legend where it doesn't obscure important map features.

12. **Custom labels**: Create custom labels in your data for more informative hover text and area labels.
