---
title: "Choosing and comparing nighttime-light sources"
description: >
  Compare Bhuvan and NASA Black Marble coverage, units, authentication,
  and appropriate India workflows.
output: rmarkdown::html_vignette
vignette: >
  %\VignetteIndexEntry{Choosing and comparing nighttime-light sources}
  %\VignetteEngine{knitr::rmarkdown}
  %\VignetteEncoding{UTF-8}
---



This vignette's output is pre-rendered from live ISRO Bhuvan and NASA
Earthdata data (see `vignettes/source-comparison.Rmd.orig`), since NASA's
LAADS DAAC can be too slow for a CI build. To refresh it, re-knit the `.orig`
file locally with `EARTHDATA_TOKEN` set and copy the result over
`source-comparison.Rmd`.

`lightson` exposes related but non-interchangeable products. Choose a
source based on the period, update frequency, measurement units, and intended
analysis. Do not append their raw values into a single time series.

## At a glance

| Source/product | Coverage | Cadence | Approx. resolution | Values | Authentication |
|---|---:|---:|---:|---|---|
| ISRO Bhuvan NTL | 2012--2024 | Annual | 500 m | Classed radiance (4 bands) | None |
| NASA VNP46A4 | 2012--2025 | Annual | 500 m | Radiance, nW/cm^2/sr | Earthdata token |
| NASA VNP46A3 | 2012--present | Monthly | 500 m | Radiance, nW/cm^2/sr | Earthdata token |
| NASA VNP46A2 | 2012--near-present | Daily | 500 m | Radiance, nW/cm^2/sr | Earthdata token |

Availability can lag acquisition. In particular, completed annual composites
are normally published well into the following year. Check the provider when
reproducibility depends on an exact latest date.

## Bhuvan: simple India annual data

Bhuvan is convenient when an unauthenticated India-only workflow matters. Its
state statistics endpoint returns physical radiance statistics, but its WMS
serves a four-class colour map. `bhuvan_raster()` converts each class to a
representative radiance, so it cannot recover continuous values.

The examples below use a handful of states over 2021-2022 and the bundled LGD
state boundaries, keeping every fetch small.


``` r
library(lightson)

states <- get_india_admin("state")
sel <- c("Bihar", "West Bengal")
states_sel <- states[states$state_name %in% sel, ]

state_stats <- bhuvan_stats(years = 2021:2022)
bhuvan_maps <- bhuvan_raster(states_sel, years = 2021:2022)
#> Using cached: bhuvan_ec05c5bc4c11_2021.tif
#> Using cached: bhuvan_ec05c5bc4c11_2022.tif
```

Bhuvan uses VNP46A4 Collection 1 for 2012-2023 and Collection 2 from 2024.
The processing change creates a discontinuity, so a 2023-2024 difference
must not be interpreted directly as growth. For a consistent calibrated
2012-2025 annual panel, prefer NASA Collection 2 for every year.

## NASA Black Marble: annual, monthly, and daily

All three NASA products use the same Earthdata bearer token; the example
below uses the annual product. Requests are scoped to `states_sel` so only
the (single) VIIRS tile covering those two states downloads:


``` r
token <- earthdata_token()

annual <- ntl_download(
  states_sel,
  years = 2021:2022, token = token,
  product = "annual"
)
```

Daily downloads (`product = "daily"`) default to `quality = "high"`,
retaining mandatory QA flag zero. This rejects cloud contamination and other
poor retrievals but can leave missing pixels. Use `quality = "all"` only when
you intend to inspect and apply the quality bands yourself. Daily data are
near-current rather than a true real-time feed.

Use annual data for long-run development panels, monthly data for seasonal or
short-run economic change, and daily data for narrowly dated events such as
power outages. Aggregating QA-filtered daily observations into a monthly
statistic is not automatically equivalent to the official VNP46A3 composite.

## Comparison

Use the same polygons and aggregation statistic for both sources. Here the
comparison uses the two states already downloaded above, over 2021-2022, so
it does not cross Bhuvan's 2024 collection break.


``` r
viirs_panel <- extract_panel(annual, states_sel, id_col = "state_name")
viirs_panel$source <- "NASA VNP46A4 C2"
viirs_panel$units <- "nW/cm^2/sr"

bhuvan_panel <- extract_panel(bhuvan_maps, states_sel, id_col = "state_name")
bhuvan_panel$source <- "ISRO Bhuvan WMS"
bhuvan_panel$units <- "Classed radiance"
```

Raw levels cannot be compared because the units differ. A useful diagnostic is
to express each state and source relative to its own 2021 value. An index of
120 then means that the source reports a 20% increase since 2021; it does not
mean that the two sensors observed the same absolute brightness.


``` r
comparison <- rbind(viirs_panel, bhuvan_panel)
comparison <- ntl_index(
  comparison,
  baseline = 2021,
  group_cols = c("source", "region_id"),
  index_col = "index_2021"
)

library(ggplot2)
ggplot(comparison, aes(year, index_2021, colour = source)) +
  geom_hline(yintercept = 100, colour = "grey60", linetype = 2) +
  geom_line(linewidth = 0.8) +
  geom_point(size = 2) +
  facet_wrap(~region_id) +
  labs(
    x = NULL, y = "Index (2021 = 100)",
    title = "Within-source nighttime-light change",
    subtitle = "Index trajectories are comparable; raw levels are not",
    colour = NULL
  ) +
  theme_ntl() +
  theme(legend.position = "bottom")
```

![plot of chunk indexed-comparison](source-comparison-fig/indexed-comparison-1.png)

Check whether conclusions depend on the source instead of relying only on the
figure. The following produces one correlation per state across the two
overlap years and ranks states with the weakest agreement:


``` r
agreement <- ntl_source_agreement(viirs_panel, bhuvan_panel)
head(agreement, 10)
#>     region_id correlation observations
#> 2 West Bengal          -1            2
#> 1       Bihar           1            2
```

With only two overlap observations this correlation is a diagnostic, not a
validation statistic.

For an outage study using daily data, use pre-event and post-event windows,
compare affected states with unaffected controls, and record the exact QA
rule. Do not fill cloudy daily observations with zero.

For most India economic panels, the preferred core series is VNP46A4
Collection 2 from 2012 onward. Bhuvan remains useful for unauthenticated India
exploration and for its pre-aggregated state statistics.
