epwshiftr’s recommended workflow is now Create Future EPW Files, built around shift_*(), EsgStore, Downloader, and EpwMorpher.

This guide covers migration from the published CRAN v0.1.4 API, which is preserved on the legacy branch. Those functions and their profile switches are no longer exported by the current package. Current releases expose one canonical calculation contract per method through the scale-specific transform constructors. This article maps old workflow concepts to store-native concepts; projects that require exact legacy numerical output should retain their frozen legacy software environment.

Development API naming update

Earlier development versions used the names below. Update calls and qualified references to the current names; argument lists, return values, and execution behavior are unchanged. The old development names are no longer exported. This naming update does not change the CRAN v0.1.4 API retained on legacy.

Earlier development name Current name Responsibility
shift_future_epw() shift_epw_future() Run a future-weather batch from baseline EPWs and climate scenarios.
shift_reference_epw() shift_epw_reanalysis() Generate annual ERA5 EPWs from local or downloaded data.
shift_epw() shift_epw_write() Write transformed weather to EPWs in the store.
shift_export_epw() shift_epw_export() Export workflow EPWs, writing them first when given transformed weather.
shift_reference_plan() shift_reference_from_plan() Configure a reference using existing extraction plan IDs.

shift_plan() and shift_reference_historical() keep their names. Reference constructors configure inputs; EPW entry points execute generation or delivery. The CLI command names and persisted workflow stage names are unchanged.

Concept Map

Legacy step Store-native replacement Why it changed
init_cmip6_index() shift_request() plus shift_datasets() / shift_collect() Search and file metadata are now query snapshots and result objects instead of one monolithic local index.
summary_database() EsgStore file catalog and storage_report() File identity, local paths, checksums, and artifacts live in a durable manifest.
match_coord() shift_site() and EsgStore$plan_region() Site metadata and extraction plans are explicit workflow objects.
extract_data() shift_extract() or EsgStore$extract() Extraction writes partitioned Parquet artifacts and records coverage.
morphing_epw() shift_morph() or EpwMorpher$run() Morphing factors and diagnostics are store-native and resumable.
future_epw() shift_epw_write() or EpwMorpher$write_epw() EPW outputs are registered with case metadata and artifact provenance.

Old Shape

A simplified legacy script looked like this:

index <- init_cmip6_index(...)
summary <- summary_database(...)
coord <- match_coord(epw, summary)
data <- extract_data(coord, years = 2060)
morphed <- morphing_epw(data, years = 2060)
future_epw(morphed)

That path assumed a local CMIP6 file index and passed large data objects between steps.

New High-Level Shape

The store-native path keeps durable state in the store and passes small stage objects between steps.

transform <- monthly_transform("epwshiftr")
variables <- transform@required_inputs$model_future@variable_sets[[1L]]

site <- shift_site(
    id = "SIN",
    lon = 103.98,
    lat = 1.37,
    label = "Singapore",
    epw = epw
)

request <- shift_request(
    project = "CMIP6",
    time = 2060L,
    filters = list(
        activity_id = "ScenarioMIP",
        source_id = "MPI-ESM1-2-LR",
        experiment_id = "ssp585",
        variant_label = "r1i1p1f1",
        frequency = "mon",
        variable_id = variables,
        data_node = "esgf.ceda.ac.uk",
        table_id = "Amon"
    ),
    options = list(index_node = "https://esgf-data.dkrz.de")
)

epws <- request |>
    shift_collect(store = "~/cmip6-singapore-store") |>
    shift_extract(site = site, periods = epw_morph_periods(`2060s` = 2060L)) |>
    shift_morph(
        baseline = site,
        transform = transform,
        strict = TRUE
    ) |>
    shift_epw_write()

Use shift_status(), shift_diagnostics(), shift_coverage(), shift_outputs(), and shift_data() to inspect stage state.

Select a Current Canonical Method

Select the original morphing transform published by Belcher et al. when matching historical model data are available. The reference belongs to this run and is not stored inside the reusable transform:

run <- shift_epw_future(
    sites = shift_site(epw = epw),
    climate = shift_cmip6(
        model = "MPI-ESM1-2-LR",
        scenarios = "ssp585",
        member = "r1i1p1f1"
    ),
    periods = list(`2060s` = 2060L),
    transform = monthly_transform("original_morphing"),
    reference = historical_reference(1995:2014),
    dir = "outputs/future-epw"
)

Use monthly_transform("epwshiftr") for the package’s enhanced monthly method. The two methods have separate canonical definitions; the current API does not offer a profile or physical-policy switch that mixes them.

New Lower-Level Shape

If your legacy script needed tight control over indexing, downloads, extraction, or morphing, split it into the lower-level engines instead of recreating the old global index.

transform <- monthly_transform("epwshiftr")
variables <- transform@required_inputs$model_future@variable_sets[[1L]]

query <- esg_query("https://esgf-data.dkrz.de")$
    activity_id("ScenarioMIP")$
    experiment_id("ssp585")$
    source_id("MPI-ESM1-2-LR")$
    variant_label("r1i1p1f1")$
    frequency("mon")$
    variable_id(variables)$
    data_node("esgf.ceda.ac.uk")$
    params(table_id = "Amon")

datasets <- query$collect(type = "Dataset")
files <- datasets$collect(type = "File", fields = "*")$
    filter_time("2060-01-01", "2060-12-31", method = "drs")

store <- EsgStore$new("~/cmip6-singapore-store")
query_id <- store$add_files(files, label = "singapore-ssp585-2060")

plan <- store$plan_region(
    query_id = query_id,
    lon = 103.98,
    lat = 1.37,
    time = c("2060-01-01T00:00:00Z", "2060-12-31T23:59:59Z"),
    site_id = "SIN",
    variable_id = variables
)

store$extract(plan_id = plan$plan_id, fallback = "auto")

morpher <- epw_morpher(
    store,
    epw = epw,
    site_id = "SIN",
    transform = transform
)
morpher$workflow(
    plan_id = plan$plan_id,
    periods = epw_morph_periods(`2060s` = 2060L),
    strict = TRUE,
    dir = "outputs/future-epw"
)

See ESGF query results, ESG stores, and EpwMorpher for the details behind each layer.

Migration Checks

Before replacing a legacy script, make these choices explicit:

  • Use shift_request() filters that match the old scenario, source, variant, frequency, table, and variables.
  • Select one canonical transform explicitly and keep model or observed references as execution inputs.
  • In enhanced monthly workflows, prefer shift_cmip6(table = NULL) so atmospheric variables and optional snd can use their native CMIP tables.
  • Decide whether you need full NetCDF downloads. The new default reads OPeNDAP first; insert shift_download() only when you intentionally want local source files.
  • Read source-variable requirements from the selected transform when building a manual low-level ESGF request.
  • Replace file-system scans with store validation and coverage checks.
  • Compare output EPW names and case grouping through shift_outputs() rather than relying on legacy directory conventions.

When to Keep the Legacy Branch

Keep using the legacy branch or epwshiftr v0.1.4 only when a project depends on removed function signatures, exact legacy object classes, old file naming, or a frozen software environment that cannot migrate. The current package does not emulate removed profiles through compatibility wrappers.

For new work, use the store-native API. It gives better diagnostics, durable metadata, resumable downloads, artifact tracking, and a clearer route from ESGF records to generated EPW files.