-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathdft_stac_cube.Rd
More file actions
137 lines (120 loc) · 6.29 KB
/
Copy pathdft_stac_cube.Rd
File metadata and controls
137 lines (120 loc) · 6.29 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
% Generated by roxygen2: do not edit by hand
% Please edit documentation in R/dft_stac_cube.R
\name{dft_stac_cube}
\alias{dft_stac_cube}
\title{Fetch a masked spectral-index cube from a STAC catalog}
\usage{
dft_stac_cube(
aoi,
source = "sentinel-2-l2a",
index = "kndvi",
datetime = NULL,
res = 10,
crs = NULL,
dt = "P1M",
aggregation = "median",
resampling = "bilinear",
clip = TRUE,
cloud_cover_max = 60,
months = NULL,
mask_values = NULL,
cache_dir = NULL,
force = FALSE,
sign_fn = rstac::sign_planetary_computer()
)
}
\arguments{
\item{aoi}{An \code{sf} polygon defining the area of interest.}
\item{source}{Character. A cube source name for \code{\link[=dft_stac_config]{dft_stac_config()}} (default
\code{"sentinel-2-l2a"}). Must be a source with \code{cube = TRUE}.}
\item{index}{Character. Spectral index from \code{\link[=dft_index_table]{dft_index_table()}} (default
\code{"kndvi"}). Determines which band roles (and thus assets) are fetched.}
\item{datetime}{Character. ISO 8601 interval \code{"start/end"}. When \code{NULL}, uses
\code{available_datetime} from \code{\link[=dft_stac_config]{dft_stac_config()}}.}
\item{res}{Numeric. Output pixel size in CRS units (default 10).}
\item{crs}{Character. Target CRS as an EPSG string. When \code{NULL}, auto-detected
from the AOI centroid's UTM zone.}
\item{dt}{Character. ISO 8601 duration for the temporal aggregation window
(default \code{"P1M"}, monthly). The cadence \code{\link[=dft_rast_break]{dft_rast_break()}}'s \code{frequency}
must agree with.}
\item{aggregation}{Character. Temporal aggregation for multiple scenes in one
\code{dt} window (default \code{"median"}).}
\item{resampling}{Character. Spatial resampling (default \code{"bilinear"}).}
\item{clip}{Logical. When \code{TRUE} (default), clip the returned stack to the AOI
polygon with \code{terra::mask()} (cells outside → \code{NA} on every layer), so
\code{\link[=dft_rast_break]{dft_rast_break()}} / \code{\link[=dft_rast_trend]{dft_rast_trend()}} reduce only in-polygon pixels. Set
\code{FALSE} to keep the full bounding box (e.g. for surrounding context, or to
mask later with a different polygon). Note this clips the \emph{output} only — the
full bbox of COGs is still streamed either way (the AOI cannot be pushed into
the read on the pinned gdalcubes build; see \code{inst/notes/gdalcubes-pc-gotchas.md}).}
\item{cloud_cover_max}{Numeric. Scene-level \code{eo:cloud_cover} maximum percent
for the STAC pre-filter (default 60).}
\item{months}{Integer vector of calendar months (1-12) to keep, or \code{NULL}
(default) for all. Restricting to the growing season (e.g. \code{6:9}) both
sharpens the vegetation signal — snow and low-sun winter scenes carry no
vegetation information — and cuts the number of scenes streamed. Months with
no retained scenes become \code{NA} in the monthly cube, so the per-pixel series
stays regular at \code{frequency = 12} for \code{\link[=dft_rast_break]{dft_rast_break()}}. Prefer a longer
\code{datetime} window when using this, so enough growing-season history remains
to fit a stable BFAST baseline.}
\item{mask_values}{Integer vector of mask-band classes to exclude. When
\code{NULL}, uses \code{mask_values} from \code{\link[=dft_stac_config]{dft_stac_config()}} (e.g. Sentinel-2 SCL
cloud / shadow / cirrus classes).}
\item{cache_dir}{Character. Cache directory. When \code{NULL}, uses
\code{\link[=dft_cache_path]{dft_cache_path()}}.}
\item{force}{Logical. Re-fetch even if cached, overwriting the cached raster
(default \code{FALSE}).}
\item{sign_fn}{A signing function for STAC assets. Default is
\code{\link[rstac:items_sign_planetary_computer]{rstac::sign_planetary_computer()}}.}
}
\value{
A \link[terra:SpatRaster-class]{terra::SpatRaster} index stack — one layer per time step, with a
time value per layer — cached as a GeoTIFF. By default (\code{clip = TRUE}) the
stack is clipped to the AOI polygon (cloud-masked, cells outside the polygon
\code{NA}), so the reduced raster from \code{\link[=dft_rast_break]{dft_rast_break()}} is already polygon-tight;
pass \code{clip = FALSE} for the full AOI \strong{bounding box}. For sources with a
reflectance-offset baseline boundary (Sentinel-2), items are split at the
boundary and offset-corrected per side, so a series crossing it carries no
artificial index step.
}
\description{
Sibling of \code{\link[=dft_stac_fetch]{dft_stac_fetch()}} for continuous change detection. Where
\code{\link[=dft_stac_fetch]{dft_stac_fetch()}} materializes one categorical raster per year, this builds
a sub-annual reflectance cube, masks clouds, computes a spectral index over
band roles, and returns the index time series as a \code{SpatRaster} (one layer
per time step) — the input to \code{\link[=dft_rast_break]{dft_rast_break()}} for per-pixel trajectory
breakpoint detection.
}
\details{
The index stack is materialized once to a GeoTIFF under \code{\link[=dft_cache_path]{dft_cache_path()}}
as \verb{<source>/cube_<key>.tif}, keyed by a hash of the AOI geometry and every
cube-affecting parameter. Because it is invariant to \code{\link[=dft_rast_break]{dft_rast_break()}}'s
parameters, caching it here makes bfast parameter sweeps cheap — they re-read
the local raster instead of re-streaming COGs.
Three STAC-query specifics distinguish cube mode from \code{\link[=dft_stac_fetch]{dft_stac_fetch()}}:
pagination via \code{\link[rstac:items_functions]{rstac::items_fetch()}} is mandatory (a monthly multi-year query
returns hundreds of items; a single page silently truncates); the query uses
\code{intersects} with the AOI geometry, not a bounding box (floodplain polygons
are highly non-rectangular); and a scene-level \code{eo:cloud_cover} pre-filter
shrinks the collection before any pixel is read, complementing per-pixel mask
filtering.
}
\examples{
\dontrun{
# Monthly kNDVI cube for a floodplain reach (requires network + gdalcubes)
aoi <- sf::st_read(system.file("extdata", "example_aoi.gpkg", package = "drift"))
cube <- dft_stac_cube(
aoi,
source = "sentinel-2-l2a",
index = "kndvi",
datetime = "2019-01-01/2023-12-31",
dt = "P1M"
)
breaks <- dft_rast_break(cube, start = c(2022, 1))
}
}
\seealso{
\code{\link[=dft_rast_break]{dft_rast_break()}} (the reducer that consumes this cube),
\code{\link[=dft_index_expr]{dft_index_expr()}} (the index applied), \code{\link[=dft_stac_fetch]{dft_stac_fetch()}} (categorical
sibling).
}