--- title: "Migrating atlas packages to sf-optional" output: rmarkdown::html_vignette vignette: > %\VignetteIndexEntry{Migrating atlas packages to sf-optional} %\VignetteEngine{knitr::rmarkdown} %\VignetteEncoding{UTF-8} --- ```{r} #| label: setup-opts #| include: false knitr::opts_chunk$set( collapse = TRUE, comment = "#>" ) ``` ```{r} #| label: setup library(ggseg.formats) ``` Since the **sf-optional** milestone (ggseg 2.2), a `ggseg_atlas` stores its 2D geometry in a single `geom` slot that can hold either an `sf` table or the sf-optional `brain_polygons` representation. The polygon form renders identically through the `geom_polygon`-based path in ggseg, but carries no dependency on the sf class machinery — so atlases keep working on wasm builds and air-gapped installs where sf (and its GDAL/GEOS/PROJ system libraries) cannot be installed. This vignette is for maintainers of downstream atlas packages (`ggsegFreeSurfer`, `ggsegSchaefer`, `ggsegGlasser`, …). Your package ships `brain_atlas`/`ggseg_atlas` objects as `.rda` files under `data/`. Migrating means rewriting those files once so the geometry is stored as polygons, then dropping sf from your `DESCRIPTION`. ## The recipe From the root of your atlas package, run: ```r # 1. rewrite every atlas in data/ into the polygon format ggseg.formats::migrate_atlas_files("data") # 2. drop sf from DESCRIPTION (it is no longer needed at install or run time) usethis::use_package("sf", type = "Suggests") # 3. rebuild the package data documentation and reinstall devtools::document() ``` That is the whole migration. Commit the rewritten `data/*.rda`, push, and release. ## What `migrate_atlas_files()` does It walks the directory, loads each `.rda`, finds every atlas object inside, converts its `geom` to `brain_polygons`, drops any legacy `sf`/`polygons` slots, and saves the file back with `xz` compression. Files with nothing to migrate are left untouched, and it reports what it changed: ```r ggseg.formats::migrate_atlas_files("data") #> ✔ Migrated `dk.rda`. #> ✔ Migrated `aseg.rda`. #> ℹ Skipped `palette.rda` (nothing to migrate). ``` The conversion reads sf coordinates, so **sf must be installed on the machine you run the migration from**. This is a one-time maintainer step; the published package no longer needs sf. It is idempotent — running it twice is a no-op on already-migrated files, so it is safe to wire into a `data-raw/` build script. ### Keeping sf instead If your atlas package genuinely needs sf geometry (for example it exposes geometric operations), pass `keep_sf = TRUE` to normalise everything into the single `geom` slot as sf rather than polygons: ```r ggseg.formats::migrate_atlas_files("data", keep_sf = TRUE) ``` ## Verifying the result After migrating, the geometry is sf-optional and round-trips losslessly. You can rehydrate sf on demand with `as_sf_atlas()`, and go back with `as_polygon_atlas()`: ```{r} #| label: roundtrip poly <- as_polygon_atlas(dk()) is_atlas_polygon(poly) atlas_labels(poly) |> head() ``` A migrated atlas plots through ggseg with no sf installed. If a lite-only install meets an atlas that is *still* sf-backed, `as_polygon_atlas()` converts it on the fly when sf is available, and otherwise aborts with a message naming `migrate_atlas_files()` — the signal that the atlas package itself needs the one-time migration above.