---
title: "Modern surveillance data from OpenDataSUS"
author: "Renato Prado Siqueira"
date: "`r Sys.Date()`"
output: rmarkdown::html_vignette
vignette: >
  %\VignetteIndexEntry{Modern surveillance data from OpenDataSUS}
  %\VignetteEngine{knitr::rmarkdown}
  %\VignetteEncoding{UTF-8}
---

```{r setup, include=FALSE}
knitr::opts_chunk$set(echo = TRUE, collapse = TRUE, comment = "#>")
library(datasus)
```

## Overview

OpenDataSUS publishes record-level surveillance files separately from
TABNET. `datasus` provides a generic catalog client and convenience functions
for frequently used datasets:

| Dataset | Function | Standardization key |
|:--|:--|:--|
| Serious adverse events following immunization | `esavi()` | `"esavi"` |
| Influenza-like illness notifications | `esus_sindrome_gripal()` | `"sindrome_gripal"` |
| Individual PNI doses | `pni_doses()` | `"pni_doses"` |
| COVID-19 hospital occupancy | `ocupacao_hospitalar()` | `"ocupacao_hospitalar"` |

## Search before downloading

Search the catalog and inspect its resources before requesting a large file:

```{r discovery, eval=FALSE}
opendatasus_catalogo("ESAVI")
opendatasus_catalogo("doses aplicadas PNI")

resources <- opendatasus_recursos("esavi")
resources[, c("id", "nome", "formato", "ano", "tamanho")]
```

`"last"` follows the latest partition found in the live catalog. Use an
explicit year and month when the analysis must remain reproducible.

## Start with selected columns

The convenience functions accept `n_max` for exploratory reads and `colunas`
to avoid parsing fields that are not needed:

```{r wrappers, eval=FALSE}
events <- esavi(
  n_max = 1000,
  colunas = c(
    "nu_notificacao", "dt_notificacao", "nu_idade", "ds_sexo"
  ),
  normalizar = TRUE
)

illness <- esus_sindrome_gripal(
  uf = "MS",
  ano = 2024,
  n_max = 1000,
  colunas = c(
    "dataNotificacao", "municipioIBGE", "idade", "sexo"
  ),
  normalizar = TRUE
)

doses <- pni_doses(
  ano = 2026,
  mes = 1,
  n_max = 1000,
  colunas = c(
    "co_paciente", "dt_vacina", "co_vacina",
    "co_municipio_paciente"
  ),
  normalizar = TRUE
)

occupancy <- ocupacao_hospitalar(
  ano = 2022,
  n_max = 1000,
  colunas = c(
    "dataNotificacao", "cnes", "ocupacaoHospitalarUti"
  ),
  normalizar = TRUE
)
```

Column names supplied to `colunas` are the names in the source file.
With `normalizar = TRUE`, the returned names are the stable analysis names
defined by the package dictionary.

## Standardize an existing data frame

Standardization can also be applied after data have been imported elsewhere.
This offline example uses fields from the ESAVI dictionary:

```{r standardize}
raw_events <- data.frame(
  nu_notificacao = c("A-001", "A-002"),
  dt_notificacao = c("2026-01-10", "2026-01-11"),
  nu_idade = c("34", "67"),
  ds_sexo = c("Feminino", "Masculino"),
  stringsAsFactors = FALSE
)

events <- datasus_padronizar(raw_events, sistema = "esavi")
str(events)
```

The dictionary documents source names, standardized names, semantic labels
and expected classes:

```{r dictionary}
head(datasus_dicionario("esavi"), 8)
```

## Detect schema drift

`datasus_validar_esquema()` checks whether important fields are present and
whether their classes agree with the curated schema:

```{r schema}
validation <- datasus_validar_esquema(
  events,
  sistema = "esavi",
  campos = c(
    "id_notificacao", "data_notificacao", "idade", "sexo"
  )
)
validation
```

Set `estrito = TRUE` in automated pipelines to stop when a required field is
missing or has an incompatible class:

```{r strict-schema, eval=FALSE}
datasus_validar_esquema(
  events,
  sistema = "esavi",
  campos = c("id_notificacao", "data_notificacao"),
  estrito = TRUE
)
```

## Resources split into multiple physical files

Some historical influenza-like illness resources publish their physical
files as links in the resource description. Expand them before building a
download plan:

```{r multipart, eval=FALSE}
resources <- opendatasus_recursos(
  "notificacoes-de-sindrome-gripal-leve-2020"
)
ms_id <- resources$id[
  resources$formato == "CSV" & grepl("^Dados MS", resources$nome)
][1]

files <- opendatasus_arquivos(
  "notificacoes-de-sindrome-gripal-leve-2020",
  recurso = ms_id,
  formato = "CSV"
)
files[, c("recurso", "ano", "parte", "url")]
```

`esus_sindrome_gripal()` reads all these parts transparently and applies
`n_max` across the combined result, rather than independently to every file.

## Provenance

Downloaded data retain the resource identifier, official URLs, update and
download times, local cache paths and checksums:

```{r provenance, eval=FALSE}
provenance <- datasus_proveniencia(events)
str(provenance)
```

Use `atualizar = TRUE` to ignore a cached copy and obtain the current portal
version.
