---
title: "Introduction to tooth"
output: rmarkdown::html_vignette
vignette: >
  %\VignetteIndexEntry{Introduction to tooth}
  %\VignetteEngine{knitr::rmarkdown}
  %\VignetteEncoding{UTF-8}
---

```{r setup, include = FALSE}
knitr::opts_chunk$set(
  collapse = TRUE,
  comment = "#>",
  fig.width = 14,
  fig.height = 5,
  dpi = 100
)
```

The **tooth** package provides tools for dental public health research:
caries index calculation, odontogram heatmap visualisations, and tooth
numbering conversion.

## Sample Data

The package includes `sim_exam`, a simulated dataset with 20 patients,
7 teeth per quadrant, and 7 surfaces per tooth (5 coronal + 2 root).

```{r}
library(tooth)
data(sim_exam)
head(sim_exam)
```

## Calculating DMFT

`calc_dmft()` takes long-format surface data and returns one row per
person with Decayed (DT), Filled (FT), Missing (MT), and combined index
counts.

```{r}
dmft <- calc_dmft(sim_exam)
head(dmft)
```

```{r}
summary(dmft[, c("DT", "FT", "MT", "DMFT", "num_teeth")])
```

### Stratification

Add a grouping variable and pass it via `strata`:

```{r}
sim_exam$treatment <- ifelse(
  as.numeric(gsub("P", "", sim_exam$record_id)) <= 10, "SDF", "ART"
)

dmft_by_arm <- calc_dmft(sim_exam, strata = "treatment")
head(dmft_by_arm)
```

### Separate Root Caries

```{r}
dmft_root <- calc_dmft(sim_exam, root_lesion_col = "lesion_code")
head(dmft_root[, c("record_id", "DT", "MT", "DMFT", "RDT")])
```

`RDT` (root-decayed teeth) is counted independently from coronal `DT`.

## Calculating DMFS

```{r}
dmfs <- calc_dmfs(sim_exam)
head(dmfs)
```

## Drawing a Single Tooth

`draw_tooth()` returns polygon geometry for one tooth. Use it to
understand the surface layout or build custom visualisations.

```{r fig.width=5, fig.height=5}
library(ggplot2)

sv <- data.frame(
  tooth_surface = c("buc", "lin", "mes", "dis", "occ", "rootb", "rootl"),
  prop = c(0.12, 0.05, 0.30, 0.25, 0.45, 0.08, 0.03)
)

parts <- draw_tooth("ur1", "ur", 1, TRUE, sv,
                    surfaces = c("buc","lin","mes","dis","occ","rootb","rootl"),
                    display_label = "FDI 11")

ggplot() +
  geom_polygon(data = parts$crown,
               aes(x = x, y = y, group = group_id, fill = value),
               color = "grey50") +
  geom_polygon(data = parts$roots,
               aes(x = x, y = y, group = group_id, fill = value),
               color = "grey50") +
  geom_segment(data = parts$diags,
               aes(x = x, y = y, xend = xend, yend = yend),
               color = "grey50") +
  geom_path(data = parts$outline, aes(x = x, y = y),
            color = "grey40") +
  geom_text(data = parts$labels,
            aes(x = x, y = y, label = label),
            size = 5, fontface = "bold", color = "grey40") +
  geom_text(data = parts$num_label,
            aes(x = x, y = y, label = label),
            size = 7, fontface = "bold") +
  scale_fill_gradient(low = "white", high = "#C62828",
                      limits = c(0, 0.5), name = "Proportion") +
  coord_fixed() +
  theme_void() +
  theme(plot.background = element_rect(fill = "white", color = NA))
```

Surface abbreviations: **B** = Buccal, **L** = Lingual, **M** = Mesial,
**D** = Distal, **O** = Occlusal, **RB** = Root-Buccal,
**RL** = Root-Lingual.

## Odontogram Heatmaps

### Preparing data

Aggregate surface data to proportions per tooth-surface:

```{r}
library(dplyr)

decay_prop <- sim_exam %>%
  filter(tooth_surface %in% c("buc", "lin", "mes", "dis", "occ")) %>%
  group_by(tooth_num, tooth_surface) %>%
  summarise(
    prop = mean(lesion_code %in% 3:6 & act == 2, na.rm = TRUE),
    .groups = "drop"
  )
```

### Basic odontogram

```{r}
build_odontogram(
  data = decay_prop,
  teeth_per_quadrant = 7,
  title = "Active Caries Proportion by Surface",
  legend_title = "Caries\nProportion",
  surfaces = c("buc", "lin", "mes", "dis", "occ")
)
```

### With root surfaces (RB and RL)

```{r}
decay_all <- sim_exam %>%
  group_by(tooth_num, tooth_surface) %>%
  summarise(
    prop = mean(lesion_code %in% 3:6 & act == 2, na.rm = TRUE),
    .groups = "drop"
  )

build_odontogram(
  data = decay_all,
  teeth_per_quadrant = 7,
  title = "Active Caries \u2014 Coronal and Root Surfaces",
  legend_title = "Caries\nProportion",
  surfaces = c("buc", "lin", "mes", "dis", "occ", "rootb", "rootl")
)
```

### No surface labels

Set `show_labels = FALSE` for a cleaner publication-ready look:

```{r}
build_odontogram(
  data = decay_prop,
  teeth_per_quadrant = 7,
  title = "Active Caries \u2014 Clean Export",
  surfaces = c("buc", "lin", "mes", "dis", "occ"),
  show_labels = FALSE,
  tooth_label_size = 3.5
)
```

### FDI tooth numbering

Display tooth numbers in FDI (ISO 3950) notation instead of quadrant
format:

```{r}
build_odontogram(
  data = decay_prop,
  teeth_per_quadrant = 7,
  title = "Active Caries \u2014 FDI Numbering",
  surfaces = c("buc", "lin", "mes", "dis", "occ"),
  numbering = "fdi"
)
```

### Fixed colour scale

Use `min_val` and `max_val` to ensure consistent colour scales across
multiple plots:

```{r}
build_odontogram(
  data = decay_prop,
  teeth_per_quadrant = 7,
  title = "Fixed Scale (0 to 0.5)",
  surfaces = c("buc", "lin", "mes", "dis", "occ"),
  min_val = 0, max_val = 0.5
)
```

### Stratified by treatment arm

```{r fig.height=10}
decay_by_arm <- sim_exam %>%
  filter(tooth_surface %in% c("buc", "lin", "mes", "dis", "occ")) %>%
  group_by(treatment, tooth_num, tooth_surface) %>%
  summarise(
    prop = mean(lesion_code %in% 3:6 & act == 2, na.rm = TRUE),
    .groups = "drop"
  )

build_odontogram(
  data = decay_by_arm,
  teeth_per_quadrant = 7,
  title = "Active Caries",
  legend_title = "Caries\nProportion",
  surfaces = c("buc", "lin", "mes", "dis", "occ"),
  strata = "treatment",
  ncol = 1
)
```

### Custom strata labels

Rename strata panels with `strata_labels`:

```{r fig.height=10}
build_odontogram(
  data = decay_by_arm,
  teeth_per_quadrant = 7,
  title = "Active Caries",
  surfaces = c("buc", "lin", "mes", "dis", "occ"),
  strata = "treatment",
  strata_labels = c("SDF" = "Silver Diamine Fluoride",
                    "ART" = "Atraumatic Restorative Treatment"),
  ncol = 1
)
```

### Summary statistics per stratum

Pass a `stats` data frame to display sample size and clinical measures
below each panel title:

```{r fig.height=10}
# Compute stats from DMFT results
dmft_summary <- dmft_by_arm %>%
  group_by(treatment) %>%
  summarise(
    n = dplyr::n(),
    mean_DT = round(mean(DT, na.rm = TRUE), 1),
    mean_DMFT = round(mean(DMFT, na.rm = TRUE), 1),
    .groups = "drop"
  )
dmft_summary

build_odontogram(
  data = decay_by_arm,
  teeth_per_quadrant = 7,
  title = "Active Caries",
  surfaces = c("buc", "lin", "mes", "dis", "occ"),
  strata = "treatment",
  stats = dmft_summary,
  ncol = 1
)
```

### Significance testing with p-value stars

Add `stats_test`, `stats_var`, and `stats_raw` to compute and display
significance stars comparing strata:

```{r fig.height=10}
build_odontogram(
  data = decay_by_arm,
  teeth_per_quadrant = 7,
  title = "Active Caries",
  surfaces = c("buc", "lin", "mes", "dis", "occ"),
  strata = "treatment",
  stats = dmft_summary,
  stats_test = "wilcox",
  stats_var = "DMFT",
  stats_raw = dmft_by_arm,
  ncol = 1
)
```

Stars follow: `***` p < 0.001, `**` p < 0.01, `*` p < 0.05,
`ns` otherwise. Use `stats_test = "t"` for a t-test or
`stats_test = "wilcox"` for a Wilcoxon rank-sum (non-parametric).

### Footnote

Add an abbreviation key and p-value definitions below the plot:

```{r fig.height=11}
build_odontogram(
  data = decay_by_arm,
  teeth_per_quadrant = 7,
  title = "Active Caries",
  surfaces = c("buc", "lin", "mes", "dis", "occ"),
  strata = "treatment",
  stats = dmft_summary,
  stats_test = "wilcox",
  stats_var = "DMFT",
  stats_raw = dmft_by_arm,
  footnote = paste0(
    "B = Buccal, L = Lingual, M = Mesial, D = Distal, O = Occlusal.\n",
    "DT = Decayed Teeth, DMFT = Decayed/Missing/Filled Teeth.\n",
    "* p < 0.05, ** p < 0.01, *** p < 0.001 (Wilcoxon rank-sum test)."
  ),
  ncol = 1
)
```

## Primary Dentition

For primary teeth, use `dentition = "primary"` (5 teeth per quadrant):

```{r fig.width=12}
primary_teeth <- paste0(
  rep(c("ur", "ul", "lr", "ll"), each = 5), rep(1:5, 4)
)
d_primary <- expand.grid(
  tooth_num = primary_teeth,
  tooth_surface = c("buc", "lin", "mes", "dis", "occ"),
  stringsAsFactors = FALSE
)
d_primary$prop <- runif(nrow(d_primary), 0, 0.5)

build_odontogram(
  data = d_primary,
  dentition = "primary",
  title = "Primary Dentition \u2014 Simulated Caries",
  color_high = "#E65100",
  surfaces = c("buc", "lin", "mes", "dis", "occ"),
  show_roots = FALSE
)
```

## Tooth Numbering Conversion

Convert between FDI (ISO 3950), Universal (ADA), and quadrant notation:

```{r}
tooth_convert("11", from = "fdi", to = "quadrant")
tooth_convert("ur1", from = "quadrant", to = "universal")
tooth_convert(c("11", "21", "36", "46"), from = "fdi", to = "quadrant")
```

## Tooth Configuration

Generate a layout table for any arch configuration:

```{r}
tooth_config("permanent", teeth_per_quadrant = 7)
tooth_config("primary")
```
