--- title: "Custom geometry: district-level NTL with custom boundaries" description: > Extract zonal NTL statistics over custom sf polygons (districts, constituencies, or any user-supplied geometry). output: rmarkdown::html_vignette vignette: > %\VignetteIndexEntry{Custom geometry: district-level NTL with custom boundaries} %\VignetteEngine{knitr::rmarkdown} %\VignetteEncoding{UTF-8} --- ```{r setup, include = FALSE} library(lightson) # Live downloads write to the user cache, so skip them on CRAN. live_ok <- identical(Sys.getenv("NOT_CRAN"), "true") if (live_ok) { rasters <- tryCatch(bhuvan_raster("IND", years = 2020:2022), error = function(e) list()) live_ok <- length(rasters) > 0 } knitr::opts_chunk$set( collapse = TRUE, comment = "#>", dev.args = list(bg = "transparent"), eval = live_ok ) ``` ```{r offline-notice, echo = FALSE, results = "asis", eval = !live_ok} cat("_Live data were not downloaded when this vignette was built, so its examples were not run. Run this vignette locally to see the output._") ``` `lightson` accepts any `sf` polygon layer. The workflow below starts with the bundled LGD state boundaries, then swaps in district-level GeoJSONs from [bharatviz](https://github.com/saketlab/bharatviz). ## State-level workflow (bundled boundaries) ```{r state-boundaries} library(sf) states <- get_india_admin("state") nrow(states) head(states[, c("state_name", "state_code")]) ``` Download Bhuvan WMS rasters for a subset of years. `bhuvan_raster()` derives the bounding box from the geometry: ```{r state-rasters} names(rasters) rasters[["2022"]] ``` Bhuvan WMS returns a classed map with four colours (< 5, 5-25, 26-200 and > 200 nW/cm^2/sr). `bhuvan_raster()` converts each class to a representative radiance (2.5, 15, 112.5 and 200), so values are banded rather than continuous, and the brightest class is a floor. ```{r state-panel} panel <- extract_panel(rasters, states, id_col = "state_name") head(panel) ``` ```{r state-trend, fig.width = 7, fig.height = 4} library(ggplot2) sel <- c("Bihar", "Maharashtra", "Tamil Nadu", "Uttar Pradesh") plot_ntl_trend( panel[panel$region_id %in% sel, ], region = sel, caption = "Source: ISRO Bhuvan NTL portal" ) ``` ```{r state-map, fig.width = 7, fig.height = 6} plot_ntl_map( rasters[["2022"]], polygons = states, title = "India nighttime lights, 2022" ) ``` ## District-level workflow ```{r district-boundaries, eval = FALSE} BHARATVIZ <- "https://bharatviz.org" districts <- sf::read_sf( file.path(BHARATVIZ, "India-bhuvan-districts.geojson") ) nrow(districts) ``` ```{r download-rasters, eval = FALSE} rasters_dist <- bhuvan_raster(districts, years = 2018:2023) names(rasters_dist) ``` ```{r extract-panel, eval = FALSE} panel_dist <- extract_panel(rasters_dist, districts, id_col = "district_name") head(panel_dist) ``` ```{r plot-trend, eval = FALSE, fig.width = 7, fig.height = 4} plot_ntl_trend(panel_dist, region = c("Mumbai", "Delhi", "Chennai", "Bengaluru")) ``` ```{r plot-map, eval = FALSE, fig.width = 7, fig.height = 6} plot_ntl_map(rasters_dist[["2022"]], polygons = districts) ``` ### LGD boundaries ```{r lgd, eval = FALSE} lgd <- sf::read_sf(file.path(BHARATVIZ, "India_LGD_districts.geojson")) panel_lgd <- extract_panel(rasters_dist, lgd, id_col = "district_name") head(panel_lgd) ``` ### Historical census boundaries ```{r historical, eval = FALSE} dist_2011 <- sf::read_sf(file.path(BHARATVIZ, "India-2011-districts.geojson")) panel_2011 <- extract_panel(rasters_dist, dist_2011) head(panel_2011) ``` `extract_panel()` picks the first character column as `region_id` automatically, or pass `id_col` explicitly. --- ## VIIRS path To use NASA VIIRS rasters, supply an [Earthdata token](https://urs.earthdata.nasa.gov/): ```{r viirs, eval = FALSE} token <- earthdata_token() rasters_viirs <- ntl_download(region = districts, years = 2018:2023, token = token) if (length(rasters_viirs) > 0) { panel_viirs <- extract_panel(rasters_viirs, districts, id_col = "district_name") head(panel_viirs) } ```