---
title: "Data Cubes with STAC"
output: rmarkdown::html_vignette
vignette: >
  %\VignetteIndexEntry{Data Cubes with STAC}
  %\VignetteEngine{knitr::rmarkdown}
  %\VignetteEncoding{UTF-8}
---


High-resolution satellites generate many snapshot images each with a limited field of view or spatial extent.  In order to see a larger area in space, and/or observe changes across space and time, we need to assemble these many snapshots into a mosaic or "data cube" that we can analyze as a cohesive whole. 


[EARTHDATA STAC CATALOGS](https://radiantearth.github.io/stac-browser/#/external/cmr.earthdata.nasa.gov/stac/)


```{r, include = FALSE}
knitr::opts_chunk$set(
  collapse = TRUE,
  comment = "#>",
  fig.path="img/",
  message = FALSE,
  warning = FALSE
)
```

```{r setup, message=FALSE}
library(rstac)
library(gdalcubes)
gdalcubes_options(parallel = TRUE)
```


### Earth Data Authentication

First let's get EDL authentication out of the way.
For cloud data from almost any other STAC catalog (NOAA, USGS, Planetary Computer, etc), authentication is either unnecessary or already provided by the STAC API, but NASA EDL is special. 

As usual, we can handle this with `edl_netrc()`.  Because the `gdalcubes` package doesn't respect global environmental variables, we use a helper utility to export those into it's configuration as well. 


```{r}
library(earthdatalogin)
edl_netrc()
with_gdalcubes()
```


## Search via STAC

We will now use the `rstac` package to search one or more NASA collections for data that falls into our desired bounding box of space and time:

```{r}
url <- "https://cmr.earthdata.nasa.gov/stac/LPCLOUD"
collection <- "HLSL30_2.0"
  

url <- "https://cmr.earthdata.nasa.gov/cloudstac/LPCLOUD"
collection <- "HLSL30.v2.0"

bbox <- c(xmin=-123, ymin=37.25, xmax=-122.0, ymax=38.25) 
start <- "2022-01-01T00:00:00Z" # NASA requires this format
end <- "2022-05-31T00:00:00Z"



# HLSL30 is landstat-conventions harmonized, HSLS30 is sentinel-conventions in harmonized
# Find all assets from the desired catalog:
items <- stac(url) |> 
  stac_search(collections = collection,
              bbox = bbox,
              datetime = paste(start,end, sep = "/")) |>
  post_request() |>
  items_fetch()
```
```{r}
href = items$features[[1]]$assets[["B04"]]$href

library(terra)
r = terra::rast(href, vsi=TRUE)
srs = terra::crs(r)
r
```


```{r}
# crs info missing!
# items$features[[1]]$properties
```



Note that `r length(items$features)` features have matched our search criteria! Each feature represents a 'snapshot' image taken by the satellite as it passes by (this is a harmonized product so actually there's quite a lot of post-processing.)  Each feature thus shares the same bounding box, projection, and timestamp, but may consist of many different 'assets', different COG files representing the different spectral bands on the satellite camera instrument.  Each feature can potentially include quite extensive metadata about the feature, including details of instrument itself or from post-processing, such as cloud cover.  Unfortunately, EarthData's STAC metadata tends to be quite sparse. 


## Building a Data Cube





```{r}
# RGB bands + cloud cover mask
col <- stac_image_collection(items$features, 
                             skip_image_metadata = TRUE, # srs not in stac meta!!
                             srs = srs, 
                             asset_names = c("B02", "B03", "B04", "Fmask"))

# use a cloud mask -- see
# https://lpdaac.usgs.gov/documents/1326/HLS_User_Guide_V2.pdf

cloud_mask <- image_mask("Fmask", bits=c(1,2,3), values = c(1,1,1))
```




```{r}
# Desired data cube shape & resolution
v = cube_view(srs = srs,
              extent = col,
              nx = 512, ny = 512, dt = "P2M",
              aggregation ="first", resampling = "near")
```


```{r sf_bay}
# Here we go! note eval is lazy

bench::bench_time({
  raster_cube(col, v, mask=cloud_mask) |>
  select_bands(c("B02","B03", "B04")) |>
  write_ncdf("tmp.nc", overwrite=TRUE)
  
})
```

```{r}
ncdf_cube("nomask.nc") |>  plot(rgb=3:1)

```

```{r}
```





```{r}
items <-
  stac("https://earth-search.aws.element84.com/v0/") |>
  stac_search(collections = "sentinel-s2-l2a-cogs",
              bbox = bbox,
              datetime = paste(start, end, sep="/")) |>
  post_request() |>
  items_fetch()

col <- stac_image_collection(items$features, asset_names = c("B02", "B03", "B04", "SCL"))

v = cube_view(srs = "EPSG:4326",
              extent = col,
              nx = 1024, ny = 1024, dt = "P1M",
              aggregation ="first", resampling = "near")

mask <- image_mask("SCL", values=c(3, 8, 9)) # mask clouds and cloud shadows

bench::bench_time({
  raster_cube(col, v, mask=mask) |>
  select_bands(c("B02","B03", "B04")) |>
  write_ncdf("tmp.nc", overwrite=TRUE)
  
})

ncdf_cube("tmp.nc") |>  plot(rgb=3:1)

```


