---
title: "Introduction to vayuayan"
date: "`r Sys.Date()`"
output: rmarkdown::html_vignette
vignette: >
  %\VignetteIndexEntry{Introduction to vayuayan}
  %\VignetteEngine{knitr::rmarkdown}
  %\VignetteEncoding{UTF-8}
---

```{r setup, include = FALSE}
NOT_CRAN <- identical(tolower(Sys.getenv("NOT_CRAN", "false")), "true")
# network chunks need NOT_CRAN and a reachable CPCB feed
CPCB_OK <- NOT_CRAN && tryCatch(
  {
    httr::status_code(httr::HEAD(
      "https://airquality.cpcb.gov.in/caaqms/iit_rss_feed_with_coordinates",
      httr::timeout(5)
    )) < 400
  },
  error = function(e) FALSE
)
knitr::opts_chunk$set(
  collapse = TRUE,
  comment = "#>",
  fig.width = 7,
  fig.height = 5,
  eval = CPCB_OK
)
```

# Introduction

**vayuayan** (वायुअयन) is an R package that downloads and analyzes air quality
data. The data comes from WUSTL ACAG satellite PM2.5 (global) and the CPCB and
OAQ monitoring networks (India). The name contains two Sanskrit words:

- Vayu (वायु) means wind or air.
- Ayan (अयन) means path, journey or movement.

Together, "Vayuayan" means "the path of wind."

## Installation

```{r install, eval=FALSE}
# Install from GitHub
devtools::install_github("saketlab/vayuayan", subdir = "R")
```

## Data sources

The package gives access to three data sources:

1. WUSTL ACAG satellite PM2.5 data from Washington University
   - Global coverage at 0.01 degree (approximately 1 km) resolution
   - Monthly and annual data (1998 to 2024, product V6.GL.03)

2. The CPCB (Central Pollution Control Board) monitoring network in India
   - Historical and real-time AQI data
   - Station-level and city-level data

3. The OAQ (Open Air Quality) low-cost sensor networks in India
   - Many providers, for example Airnet
   - Daily, monthly, and annual data

## Quick start

```{r quickstart, eval = TRUE}
library(vayuayan)
library(dplyr)

vayuayan_welcome()
```

# Historical AQI data

The `cpcb_` functions give access to historical air quality data from the
Central Pollution Control Board.

## Available data

The lists of states, cities and stations come from a CPCB station directory
in the package. Thus, you can use these calls offline.

```{r historical_explore, eval = TRUE}
states <- cpcb_get_state_list()
head(states)

cities <- cpcb_get_city_list("Maharashtra")
head(cities)

stations <- cpcb_get_station_list("Mumbai")
head(stations)
```

### Station coordinates

```{r add_coords, eval = TRUE}
delhi_stations <- cpcb_add_coords(cpcb_get_station_list("Delhi"))
head(delhi_stations)
```

## Daily data in long format

`cpcb_city_daily()` downloads the CPCB daily file for each city. The function
returns one row for each day. The package caches the files. Thus, subsequent
calls read the files from disk.

```{r city_daily}
daily <- cpcb_city_daily(c("Delhi", "Mumbai"), 2024, cache_dir = tempdir())

daily %>%
  group_by(city, month) %>%
  summarise(pm25 = mean(value), .groups = "drop")
```

`cpcb_station_daily()` does the same for stations:

```{r station_daily}
station_daily <- cpcb_station_daily(
  head(delhi_stations$value, 3), 2025,
  cache_dir = tempdir()
)
count(station_daily, station_id)
```

`cpcb_download_city_data()` and `cpcb_download_station_data()` save the raw
CPCB sheet. Use these functions to get the file.

# Live AQI data

The live readings come from the public station feed. The feed contains only
the data of the last hour.

```{r live_aqi}
nearest <- cpcb_get_nearest_station(coords = c(19.0760, 72.8777))
nearest

aqi_data <- cpcb_get_live_aqi_data(station_id = nearest$station_id)
aqi_data$metrics
```

Without arguments, `cpcb_get_live_aqi_data()` finds the station nearest to
your IP location.

## Station summaries

`stations_to_dataframe()` changes the live feed into one row for each
station. Each row also has an AQI category.

```{r live_table}
live <- stations_to_dataframe(cpcb_get_all_india())

live %>%
  group_by(state_id) %>%
  summarise(
    stations = n(),
    live = sum(live),
    avg_aqi = mean(avg_aqi, na.rm = TRUE),
    .groups = "drop"
  ) %>%
  arrange(desc(stations)) %>%
  head(10)

count(live, aqi_category, sort = TRUE)
```

```{r live_map}
library(ggplot2)
library(sf)

aqi_colors <- c(
  "Good"         = "green",
  "Satisfactory" = "lightgreen",
  "Moderate"     = "yellow",
  "Poor"         = "orange",
  "Very Poor"    = "red",
  "Severe"       = "darkred",
  "No Data"      = "grey70"
)

live %>%
  filter(live) %>%
  st_as_sf(coords = c("longitude", "latitude"), crs = 4326) %>%
  ggplot() +
  geom_sf(aes(color = aqi_category), size = 2, alpha = 0.6) +
  scale_color_manual(values = aqi_colors) +
  labs(title = "Live CPCB monitoring stations", color = "AQI category") +
  theme_minimal()
```

# PM2.5 satellite data

The `pm25_` functions process satellite PM2.5 data from WUSTL ACAG
(product V6.GL.03 on the AWS Open Data registry). The Asia subset
(`region = "AS"`) includes India. The file of this subset is smaller than the
global file. The package caches the files in
`tools::R_user_dir("vayuayan", "cache")`.
The vignette build does not run these chunks.

```{r pm25_setup, eval = FALSE}
pm25_nc <- pm25_download_netcdf(2023, 11, region = "AS")
delhi <- india_boundary(state = "Delhi")
```

## Regional statistics

```{r pm25_stats, eval = FALSE}
pm25_get_stats(
  geojson_file = "https://geo.bharatviz.org/geojsons/cities/delhi.geojson",
  nc_file      = pm25_nc
)

pm25_get_stats(
  geojson_file = "https://geo.bharatviz.org/geojsons/districts/India_LGD_districts.geojson",
  nc_file      = pm25_nc,
  group_by     = "state_name"
)
```

## Maps

```{r pm25_map, eval = FALSE}
r <- pm25_load_netcdf_bbox(pm25_nc, delhi, var = "PM25", mask = TRUE)
pm25_map(r, delhi, title = "Delhi, November 2023")
```

## Cache management

```{r pm25_cache, eval = FALSE}
pm25_list_cached_files()
pm25_clear_cache()
```

# Utility functions

```{r utilities, eval = TRUE}
clean_station_name("Dr. Karni Singh Shooting Range, Delhi - DPCC")

get_aqi_categories(c(42, 180, 320))

# Mumbai to Delhi, in km
haversine_distance(19.0760, 72.8777, 28.7041, 77.1025)
```
