CMR Snapshot: Provider Metadata Health, Today

Unlike vignette("cmr-landscape") – a fixed narrative of one exploration session, kept as a written record – this article re-queries CMR live, every time it’s built, and shows whatever the catalog looks like right now. Re-render it occasionally to see how these numbers drift as collections are added, retired, or have their metadata cleaned up.

library(cmrlifecycle)
library(dplyr)
Sys.time()
#> [1] "2026-10-15 00:46:10 UTC"

One collection, right now

A quick liveness + declared-coverage check, the way a new user would use this package day to day:

cmr_collection_liveness("MUR-JPL-L4-GLOB-v4.1")
#> # A tibble: 1 × 5
#>   short_name           provider lookback_days recent_granule_count is_live
#>   <chr>                <chr>            <dbl>                <int> <lgl>  
#> 1 MUR-JPL-L4-GLOB-v4.1 <NA>                60                   59 TRUE

cmr_find_collections(short_name = "MUR-JPL-L4-GLOB-v4.1") |>
  select(short_name, temporal_start, temporal_end, ends_at_present, granule_count)
#> # A tibble: 1 × 5
#>   short_name           temporal_start temporal_end ends_at_present granule_count
#>   <chr>                <chr>          <chr>        <lgl>                   <int>
#> 1 MUR-JPL-L4-GLOB-v4.1 2002-05-31T21… <NA>         FALSE                    8901

For contrast, a collection this package found to have no granules at all (see vignette("cmr-landscape")) – still true today?

cmr_find_collections(short_name = "AAS_4088_Adelie_occupancy_Mawson_Taylor") |>
  select(short_name, granule_count, temporal_start, temporal_end)
#> # A tibble: 1 × 4
#>   short_name                           granule_count temporal_start temporal_end
#>   <chr>                                        <int> <chr>          <chr>       
#> 1 AAS_4088_Adelie_occupancy_Mawson_Ta…             0 2015-02-15T00… 2015-02-15T…

ends_at_present, provider by provider, today

This re-runs the PO.DAAC-vs-LAADS comparison from vignette("cmr-landscape") fresh. Each provider costs just two requests (one for collection metadata, one for granule counts), so this is cheap enough to run on every build, even though the earlier deep-dive sampling (checking individual collections’ recent granule activity to validate the flag) is not repeated here.

providers <- c("POCLOUD", "LAADS")

breakdown <- lapply(providers, function(p) {
  cols <- cmr_all_collections(provider = p, delay = 0)
  tibble(
    provider = p,
    n_collections = nrow(cols),
    pct_true = round(100 * mean(cols$ends_at_present), 1),
    pct_ambiguous = round(100 * mean(!cols$ends_at_present &
                                        is.na(cols$temporal_end) &
                                        cols$granule_count > 0), 1)
  )
}) |> bind_rows()
#> page 1: 988/988 collections fetched
#> page 1: 195/195 collections fetched

breakdown
#> # A tibble: 2 × 4
#>   provider n_collections pct_true pct_ambiguous
#>   <chr>            <int>    <dbl>         <dbl>
#> 1 POCLOUD            988      4.1          33.6
#> 2 LAADS              195     68.2           2.1
barplot(breakdown$pct_true, names.arg = breakdown$provider,
        ylim = c(0, 100), ylab = "% of collections with ends_at_present = TRUE",
        main = "ends_at_present reliability by provider (live)")

Bar chart comparing the percentage of collections declaring ends_at_present = TRUE between POCLOUD and LAADS

As of the vignette("cmr-landscape") write-up (2026-08-25), this stood at 4.5% for POCLOUD and 70.7% for LAADS – if the bars above look different, that’s the catalog changing, which is exactly the point of re-running this rather than trusting a single snapshot.

A small live liveness sample

A tiny, cheap version of the “sample some ambiguous collections and check if they’re really still active” method from the landscape article – a handful of PO.DAAC collections that declare ends_at_present = FALSE with no end date, checked directly:

sample_check <- cmr_all_collections(provider = "POCLOUD", delay = 0) |>
  filter(!ends_at_present, is.na(temporal_end), granule_count > 0) |>
  slice_sample(n = 5) |>
  cmr_collection_liveness(delay = 0)
#> page 1: 988/988 collections fetched

sample_check
#> # A tibble: 5 × 5
#>   short_name                 provider lookback_days recent_granule_count is_live
#>   <chr>                      <chr>            <dbl>                <int> <lgl>  
#> 1 JASON_CS_S6B_L2_ALT_LR_RE… POCLOUD             60                 1511 TRUE   
#> 2 TELLUS_GRFO_L3_GFZ_RL06.3… POCLOUD             60                    1 TRUE   
#> 3 SWOT_L2_HR_PIXC_D          POCLOUD             60                    0 FALSE  
#> 4 AMSR2-REMSS-L3U_RT-v8.2    POCLOUD             60                   58 TRUE   
#> 5 JASON_CS_S6A_L2_ALT_HR_RE… POCLOUD             60                    0 FALSE
sprintf("%d of %d sampled collections were live in the last %d days",
        sum(sample_check$is_live), nrow(sample_check),
        sample_check$lookback_days[1])
#> [1] "3 of 5 sampled collections were live in the last 60 days"

Small samples like this move around run to run – see vignette("cmr-landscape") for a fuller (25-collection) version with more stable percentages.