ST and VPP workflows

Seasonal Trajectories (ST)

Preview

Catalogue access requires WEkEO and is therefore shown without being executed during vignette builds.

st_preview <- download_st(
  start = "2020-04-01",
  end = "2020-06-30",
  tile_id = "30TXM",
  product = c("PPI", "QFLAG"),
  download = FALSE
)

Download

st_download <- download_st(
  start = "2020-04-01",
  end = "2020-06-30",
  tile_id = "30TXM",
  product = c("PPI", "QFLAG"),
  output_dir = file.path(tempdir(), "HRVPP_ST"),
  overwrite = FALSE,
  prompt = TRUE
)

Extract PPI

Raster extraction examples require user-supplied HR-VPP files and polygons and are not executed during the package build.

st_ts <- extract_ts(
  x = file.path(tempdir(), "HRVPP_ST", "PPI"),
  polygons = parcels,
  id_col = "Parcel_ID",
  fun = "median"
)

Assess temporal completeness

The temporal API can be demonstrated with a self-contained series.

st_example <- data.frame(
  ID = rep(c("parcel_1", "parcel_2"), each = 4),
  Date = rep(as.Date("2020-04-01") + c(0, 10, 20, 30), 2),
  Value = c(0.20, 0.31, NA, 0.58, 0.18, 0.29, 0.43, 0.55)
)
plan <- temporal_plan(st_example, expected_step = 10)
missingness <- summarize_missingness(plan)
completeness <- assess_ts_quality(plan)
missingness
#>         ID      start        end expected_step_days n_expected n_observed_dates
#> 1 parcel_1 2020-04-01 2020-05-01                 10          4                4
#> 2 parcel_2 2020-04-01 2020-05-01                 10          4                4
#>   n_absent_dates n_value_na n_usable date_completeness value_completeness
#> 1              0          1        3                 1               0.75
#> 2              0          0        4                 1               1.00
#>   missing_fraction
#> 1             0.25
#> 2             0.00
completeness
#> TSGenerator time-series quality assessment
#> Rows:     2
#> Windows:  full series
#> 
#> Very low      Low   Medium     High 
#>        0        0        1        1

Do not interpret these completeness classes as ST-QFLAG confidence classes.

Apply ST-QFLAG when required

The code definitions themselves are available offline:

st_qflag_classes <- quality_info("ST")
st_qflag_classes
#>   Code                  Class Rank AcceptDefault
#> 1    0                No data    0         FALSE
#> 2    1 Filled - extrapolation    1         FALSE
#> 3    2 Filled - interpolation    2         FALSE
#> 4    3                    Low    3          TRUE
#> 5    4                 Medium    4          TRUE
#> 6    5                   High    5          TRUE
#>                                                       Definition
#> 1                                  Time series was not processed
#> 2    Clear-sky observation on one side outside the 91-day window
#> 3 Clear-sky observations on both sides outside the 91-day window
#> 4           1-2 clear-sky land observations in the 91-day window
#> 5           3-8 clear-sky land observations in the 91-day window
#> 6   More than 8 clear-sky land observations in the 91-day window

Masking requires matching user-supplied target and QFLAG rasters:

st_clean <- mask_quality(
  x = st_raster,
  quality = st_qflag_raster,
  type = "ST",
  min_quality = 4
)

The default ST quality policy and any stricter threshold should be reported in the methods of a scientific analysis.

Vegetation Phenology and Productivity (VPP)

Preview/download selected parameters

vpp_preview <- download_vpp(
  start = "2020-01-01",
  end = "2020-12-31",
  tile_id = "30TXM",
  product = c("SOSD", "MAXD", "EOSD", "LENGTH", "MAXV", "AMPL"),
  season = "s1",
  download = FALSE
)

Product-aware extraction

vpp <- extract_vpp(
  x = file.path(tempdir(), "HRVPP_VPP"),
  polygons = parcels,
  id_col = "Parcel_ID",
  fun = "median"
)

The output separates Date and numeric Value. This avoids treating encoded phenological dates like continuous spectral values.

VPP quality

quality_info("VPP")
#>    Code           Class Rank AcceptDefault
#> 1     0         No data    0         FALSE
#> 2     1 No season found    0         FALSE
#> 3     2          Filled    1         FALSE
#> 4     3        Reserved   NA         FALSE
#> 5     4             Low    2         FALSE
#> 6     5             Low    2         FALSE
#> 7     6             Low    2         FALSE
#> 8     7          Medium    3          TRUE
#> 9     8          Medium    3          TRUE
#> 10    9          Medium    3          TRUE
#> 11   10            High    4          TRUE
#>                                                                       Definition
#> 1                                                  Time series was not processed
#> 2                         No season found although the time series was processed
#> 3     Insufficient clear-sky observations in green-up, green-down and green-peak
#> 4                                                                       Reserved
#> 5                           More than 2 clear-sky observations during green-down
#> 6                           More than 2 clear-sky observations during green-peak
#> 7                             More than 2 clear-sky observations during green-up
#> 8              More than 2 clear-sky observations during green-up and green-peak
#> 9              More than 2 clear-sky observations during green-up and green-down
#> 10           More than 2 clear-sky observations during green-peak and green-down
#> 11 More than 2 clear-sky observations during green-up, green-down and green-peak
vpp_clean <- mask_quality(
  x = vpp_raster,
  quality = vpp_qflag,
  type = "VPP"
)

The default VPP mask retains medium/high confidence codes. Use explicit keep_codes when the study requires a different policy.

Missingness modelling

A small synthetic table keeps the vignette deterministic and independent of external files. A modest basis dimension keeps the example fast and appropriate for the number of unique DOY values.

missingness_data <- expand.grid(
  Year = 2020:2021,
  DOY = seq(20, 340, by = 40),
  Replicate = 1:3
)
missingness_data$Value <- seq_len(nrow(missingness_data)) / nrow(missingness_data)
missingness_data$Value[seq(3, nrow(missingness_data), by = 7)] <- NA_real_

fit <- model_missingness(
  missingness_data,
  year_col = "Year",
  doy_col = "DOY",
  value_col = "Value",
  k = 5
)

plot_missingness(fit, sos = 85, max_doy = 160, eos = 280)

The model and plot are separate objects. This makes the statistical result reusable without hidden plotting side effects.