---
title: "Introduction to rstac package"
author: "Rolf Simoes, Felipe Carvalho, and Gilberto Camara"
date: "2023-01-09"
output: 
  html_document:
    df_print: tibble
classoption: x11names
fontsize: 10,5pt
indent: yes
link-citations: yes
vignette: >
  %\VignetteIndexEntry{Introduction to rstac package}
  %\VignetteEngine{knitr::rmarkdown}
  %\VignetteEncoding{UTF-8}
---

```{r prepare, include = FALSE}
is_online <- tryCatch({
  res <- httr::GET("https://brazildatacube.dpi.inpe.br/stac/")
  !httr::http_error(res)
}, error = function(e) {
  FALSE
})

knitr::opts_chunk$set(
  collapse = TRUE,
  comment = "#>",
  eval = is_online
)
library(tibble)
```

```{r setup, eval=TRUE, echo=FALSE}
library(rstac)
```

# About rstac{-}

This document will introduce the concepts of the `rstac` package. `rstac` is an R client library for STAC that fully supports STAC API v1.0.0 and its earlier versions (>= v0.8.0).

The table shows the functions implemented by the `rstac` package according to 
the STAC API endpoints. For each endpoint, `rstac` has a specialized implementation. 


```{R endpoints, eval=TRUE, echo=FALSE}

data.frame(
  "**STAC** endpoints"   = c(
    "`/`", "`/stac`","`/collections`", "`/collections/{collectionId}`", 
    "`/collections/{collectionId}/items`", "`/collections/{collectionId}/items/{itemId}`", "`/search`", "`/stac/search`",
    "`/conformance`", "`/collections/{collectionId}/queryables`"
  ), "`rstac` functions" = c(
    "`stac()`", "`stac()`", "`collections()`", "`collections(collection_id)`",
    "`items()`", "`items(feature_id)`", "`stac_search()`", "`stac_search()`",
    "`conformance()`", "`queryables()`"
  ), "API version"      = c(
    ">= 0.9.0", "< 0.9.0", ">= 0.9.0", ">= 0.9.0", ">= 0.9.0", ">= 0.9.0",
    ">= 0.9.0", "< 0.9.0", ">= 0.9.0", ">= 1.0.0"
  ),
  check.names = FALSE
) %>% knitr::kable(format = "markdown")
```

The `rstac` package makes the requests explicitly. The `rstac` pipeline creates the endpoints with function concatenations and then requests them.

## Getting started{-}

Let's start by installing the `rstac` package:

```{r installing, eval=FALSE}
install.packages("rstac")
```

## Creating queries{-}

This tutorial use the STAC API made available by the [Brazil Data Cube (BDC)](http://www.brazildatacube.org/en/home-page-2/) project. BDC is a research, development, and technological innovation project of the National Institute for Space Research (INPE), Brazil.

Let's start by creating a query for the BDC catalog.

```{r queries-1, eval=TRUE}
s_obj <- stac("https://brazildatacube.dpi.inpe.br/stac/")
s_obj
```
The `RSTACQuery` object stores the metadata of the created query.
This metadata can be accessed as a list element during query creation.

```{r base-url, eval=TRUE}
s_obj$base_url
```
Endpoints are constructed through function concatenations provided by `rstac`. Some examples are shown below:

```{r queries-2, eval=TRUE}
s_obj |> 
  collections()
```

```{r queries-3, eval=TRUE}
s_obj |> 
  collections("S2-16D-2")
```

```{r queries-4, eval=TRUE}
s_obj |> 
  collections("S2-16D-2") |>
  items()
```

```{r queries-5, eval=TRUE}
s_obj |> 
  collections("S2-16D-2") |> 
  items(feature_id = "S2-16D_V2_015011_20190117")
```

```{r queries-6, eval=TRUE}
s_obj |> 
  stac_search(collections = c("CB4_64_16D_STK", "S2-16D-2")) |>
  ext_query("bdc:tile" == "022024")
```

## Making requests{-}

`rstac` package supports **GET** and **POST** HTTP 
methods. With future updates to the STAC specifications, it is intended to 
support other methods such as **PUT** and **DELETE**. 
In addition, it is possible to add more configuration options to the request, 
such as headers (`httr::add_headers()`) and cookies (`httr::set_cookies()`). 
These options are available in the `httr` package documentation in the [`config`](https://httr.r-lib.org/reference/config.html).

### HTTP GET: `get_request()`{-}

```{r request-1}
s_obj |>
  collections(collection_id = "CB4_64_16D_STK-1") |>
  items() |>
  get_request() 
```

### HTTP POST: `post_request()`{-}

```{r request-2}
s_obj |>
  stac_search(
    collections = c("CB4_64_16D_STK-1", "S2-16D-2"),
    datetime = "2021-01-01/2021-01-31",
    limit = 400) |>
  post_request()
```

Example of providing an additional argument to HTTP verb in a request:

```{r request-3}
s_obj |> 
  stac_search(collections = c("CB4_64_16D_STK-1", "S2-16D-2")) |>
  post_request(config = c(httr::add_headers("x-api-key" = "MY-KEY")))
```

## Visualization of the documents{-}

Each `rstac` object is mapped according to the endpoints of the STAC spec. In this way, each object has a different view. The format for viewing objects is in **Markdown**.

#### `STACCatalog` object{-}

```{r catalog}
s_obj |> 
  get_request()
```

#### `STACCollection` object{-}

```{r collection}
s_obj |>
  collections("S2-16D-2") |>
  get_request()
```

#### `STACItem` object{-}

```{r item}
s_obj |>
  collections("CB4_64_16D_STK-1") |>
  items(feature_id = "CB4_64_16D_STK_v001_021027_2020-07-11_2020-07-26") |>
  get_request()
```

#### `STACItemCollection` object{-}

```{r item-collection}
s_obj |> 
  stac_search(collections = c("CB4_64_16D_STK", "S2-16D-2")) |>
  get_request()
```


Besides, the `rstac` package provides several auxiliary functions for `STACItem` and `STACItemCollection` objects. These auxiliary functions operate at the item or asset level. Functions dedicated to items have the prefix `items_`. Otherwise, asset-oriented functions have the prefix `assets_`

## Items functions{-}

The `STACItemCollection` object have some facilitating functions to manipulate/extract information, for example:

- **`items_fields()`:** Lists fields names inside an item.
- **`items_filter()`:** Performs a filter by items according to expressions operating on the properties of a `STACItemCollection` object.
- **`items_fetch()`:** Performs the pagination of items.
- **`items_length()`:** Returns the number of items in an object.
- **`items_matched()`:** Returns the number of items matching the search criteria.
- **`items_assets()`:** Returns the assets name from `STACItemCollection` and `STACItem` objects.


It is interesting to verify the fields of items before filtering:

```{r fields}
s_obj |>
  stac_search(
    collections = "CB4_64_16D_STK-1",
    datetime = "2019-01-01/2019-12-31",
    limit = 100) |> 
  post_request() |>
  items_fields(field = "properties")
```

Let's filter items that have the percentage of clouds smaller than 10%:

```{r filter}
s_obj |>
  stac_search(
    collections = "CB4_64_16D_STK-1",
    datetime = "2019-01-01/2019-12-31",
    limit = 100) |> 
  post_request() |>
  items_filter(properties$`eo:cloud_cover` < 10)
```
Number of items returned in the query (in this case equal to the limit defined as parameter):

```{r length}
s_obj |>
  stac_search(
    collections = "CB4_64_16D_STK-1",
    datetime = "2019-01-01/2019-12-31",
    limit = 100) |> 
  post_request() |>
  items_length()
```
Number of matched items in the query:

```{r matched}
s_obj |>
  stac_search(
    collections = "CB4_64_16D_STK-1",
    datetime = "2019-01-01/2019-12-31",
    limit = 100) |>
  post_request() |>
  items_matched()
```
Paginating all items that were matched in the query:

```{r fetch}
items_fetched <- s_obj |>
  stac_search(
    collections = "CB4_64_16D_STK-1",
    datetime = "2019-01-01/2019-12-31",
    limit = 500) |>
  post_request() |>
  items_fetch(progress = FALSE)

items_fetched
```
Note that the 1127 has been recovered:

```{r length-2}
items_length(items_fetched)
```

Listing the assets of the retrieved items:

```{r assets}
items_assets(items_fetched)
```


## Assets functions{-}

- **`assets_download()`:**  Downloads the assets provided by the STAC API.
- **`assets_url()`:** Returns a character vector with each asset href. 
For the URL you can add the GDAL library drivers for the following schemes:
  - HTTP/HTTPS files;
  - S3 (AWS S3);
  - GS (Google Cloud Storage).
- **`assets_select()`:** Selects the assets of each item by its name.
- **`assets_rename()`:** Rename each asset using a named list or a function.

Listing the assets names of all items:

```{r assets-2}
s_obj |>
  stac_search(
    collections = "CB4_64_16D_STK-1",
    datetime = "2019-01-01/2019-12-31",
    limit = 10) |>
  post_request() |>
  items_assets()
```

Selecting assets that have names `"BAND14"` and `"NDVI"`

```{r assets-select}
selected_assets <- s_obj |>
  stac_search(
    collections = "CB4_64_16D_STK-1",
    datetime = "2019-01-01/2019-12-31",
    limit = 10) |>
  post_request() |>
  assets_select(asset_names = c("BAND14", "NDVI"))
```

```{r assets-3}
items_assets(selected_assets)
```

Listing asset urls from the selected bands:

```{r assets-url}
selected_assets |> 
  assets_url()
```

Renaming assets using the pattern `<old-name> = <new-name>`

```{r assets-renamed}
renamed_assets <- selected_assets |> 
  assets_rename(BAND14 = "B14")
renamed_assets
```

In the `assets` field of the output it can be seen that the asset's name has changed.
It is also possible to check the asset names using the `items_assets()` function.

```{r assets-4}
items_assets(renamed_assets)
```


## Asset preview{-}

`rstac` also provides a helper function to plot preview assets (e.g. thumbnail and quicklook).

```{r asset-preview-check, eval=TRUE, include=FALSE, echo=FALSE}
is_accessible <- is_online && tryCatch({
  res <- httr::HEAD(
    assets_url(items_fetched$features[[2]], asset_names = "thumbnail")
  )
  !httr::http_error(res)
}, error = function(e) {
  FALSE
})
```

```{r plot-preview, eval=is_accessible, fig.height=3, fig.width=5}
second_item <- items_fetched$features[[2]]
second_item |>
  assets_url(asset_names = "thumbnail") |>
  preview_plot()
```

Here, we selected the second item of `items_fetched`'s features and plotted its `thumbnail` asset.

# Conclusion{-}

The `rstac` package can be useful for querying and working with satellite imagery data from STAC APIs. It offers a simple interface for searching STAC items, exploring the results, and working with assets. Additional functionalities include reading and plotting preview images. This tutorial has provided a short introduction on how to use the package. For more about CQL2 in `rstac`, type the command `?ext_filter`.
