dk(), aseg(), and tracula() atlases now ship in the
brain_polygons format, joining suit(). They install and plot without
sf (and its GDAL / GEOS / PROJ system libraries) — previously they were
sf-backed, so plotting them still required sf even though the package
itself did not. The conversion is lossless, so figures are unchanged;
callers who want sf geometry can still obtain it on demand with
as_sf_atlas().Atlas and atlas-data print methods now render the first n (default 10)
rows of their data as a plain data.frame, summarising list-columns as
compact <int [n]> / <df [r x c]> tokens. Output no longer depends on
whether tibble happens to be installed (the package tags frames as
tbl_df only for cosmetics and does not depend on tibble), which makes
printed output — and the snapshot tests that capture it — deterministic
across environments.
plot.ggseg_atlas() now draws contextual regions (those not in the atlas
core) behind the labelled core regions, instead of in alphabetical label
order. Previously a context region whose label sorted after a core region
could be drawn on top of it and occlude small structures (e.g. neighbouring
subcortical structures hiding the hypothalamic subunits). This matches the
ordering already used by the geom_brain() / as.data.frame() path.
sfheaders joins Imports. sf moves from Imports to Suggests. The
package can now be installed without GDAL / GEOS / PROJ system libraries —
enabling wasm builds and air-gapped installs. Functions that genuinely need
sf (e.g. validate_sf(), as.data.frame.ggseg_atlas(), plot.ggseg_atlas(),
the atlas_view_* repositioning helpers) check requireNamespace("sf") at
entry and error with a clear pointer to as_polygon_atlas() if sf is
unavailable. The bundled dk, aseg, and tracula atlases still carry
their sf slots, so callers who have sf installed see no behavioural change.
brain_polygons representation: a nested tibble keyed by label, with a
geometry list-column containing per-view, per-ring point coordinates
(view, x, y, group, subgroup). Renderable directly by
geom_polygon() via the subgroup aesthetic (which handles holes
through grid::pathGrob even-odd fill).brain_polygons losslessly. The sf-side
conversion uses sfheaders (pure Rcpp, no GDAL/GEOS/PROJ system libraries),
enabling wasm builds and air-gapped installation paths. The low-level
converters are internal; the public API is the atlas-level as_sf_atlas() /
as_polygon_atlas() and the atlas_sf() / atlas_polygons() accessors.validate_data_labels() checks 2D label coverage against whichever 2D source
is present (sf or polygons), preserving the same 80%/90% thresholds.vignette("migrating-atlases") — a three-line recipe for
downstream atlas-package maintainers to migrate their data/*.rda to the
sf-optional polygon format with migrate_atlas_files().as_polygon_atlas() now aborts with an actionable message naming
migrate_atlas_files() when it meets a still-sf-backed atlas on an install
where sf is not available, instead of a generic "sf is required" error.Atlas 2D geometry now lives in a single atlas$data$geom slot whose class
(sf or brain_polygons) determines the rendering path. The parallel sf and
polygons slots are gone — conversion between the two is lossless, so only one
representation is ever stored.
atlas_geom(), atlas_polygons(), atlas_geometry_type(),
is_atlas_sf(), is_atlas_polygon(). atlas_sf() now converts from the
polygon representation when needed and is the single interception point for
ggseg plotting. atlas_geom() falls back to a legacy sf slot, so atlases
built before this change keep working. Reverse dependencies should call these
accessors rather than reaching into atlas$data.ggseg_data_cortical() / ggseg_data_subcortical() /
ggseg_data_cerebellar() / ggseg_data_tract() now take a single geom
argument. A released sf argument is still accepted via ... (converted to
polygons via sf_to_polygons()) with a deprecation warning.as_polygon_atlas() / as_sf_atlas() set the single geom slot.migrate_atlas_files() rewrites atlases to the single geom slot
(polygons by default; keep_sf = TRUE stores sf). It walks a package's
data/ directory and rewrites every ggseg_atlas .rda. Intended for
downstream atlas-package maintainers across the ggsegverse ecosystem.plot.ggseg_atlas() is reimplemented with base graphics
(graphics::polygon() / graphics::polypath()), and ggplot2 is dropped
from Imports — the package no longer depends on ggplot2 for its own plotting.
plot() now returns the atlas invisibly rather than a ggplot object; it is
called for its side effect. Each spatially separate piece (e.g. a hemisphere
surface or a slice) is drawn in its own panel, arranged in a near-square grid
for a legible overview of the atlas. Code that captured the return value to
add ggplot2 layers (plot(atlas) + ...) must be updated.show.legend argument is removed; the base-R plot draws no legend. Extra
arguments in ... are forwarded to the underlying polygon() / polypath()
primitives (e.g. lwd, border).vdiffr is dropped from Suggests; the plot tests no longer snapshot SVG.atlas_palette() now takes a ggseg_atlas object only (its first argument
is atlas). Looking an atlas up by name string (e.g. atlas_palette("dk"))
is no longer supported — pass the atlas, e.g. atlas_palette(dk()).suit() bundled atlas — the SUIT cerebellar parcellation (lobules + deep
nuclei) from ggsegSUIT, stored in the sf-optional polygon (geom) format with
3D vertices (lobules) and meshes (nuclei). ggseg.formats now ships one atlas of
each kind: dk() (cortical), aseg() (subcortical), tracula() (tract),
suit() (cerebellar).atlas_region_op() combines two sets of region geometry with a boolean
operation per view (difference, intersection, union, symdifference),
writing the result to a new region. Boolean ops need a geometry engine, so
this helper always requires sf; a polygon-only atlas is rehydrated for the
operation and the result returned in polygon form.atlas_region_contextual() now operates on whichever 2D representation an
atlas carries (sf and/or polygons) and keeps both in sync — it needs no
sf for a polygon-only atlas. It also gains an ignore.case argument.polygons slot behind
a freshly rewritten sf slot; the two 2D representations stay consistent
after every operation.atlas_context_remove(), atlas_view_remove(), atlas_view_keep(),
atlas_view_remove_region(), atlas_view_remove_small(),
atlas_view_gather(), and atlas_view_reorder() now run on polygon-only
atlases with no sf installed. Filtering, polygon area (shoelace), and view
repositioning are implemented in pure R against the brain_polygons
coordinate table; the polygon results match the sf path to floating-point
precision. sf-backed atlases continue to use the existing sf code path
unchanged.atlas_views() reads view names from polygons when sf is absent.atlas_region_keep() and atlas_region_remove() no longer drop 2D geometry
on polygon-only atlases (they previously rebuilt from the sf slot only).sf nor polygons.dplyr and tidyr Imports in favour of base-R equivalents,
shrinking the recursive dependency tree from 32 to 20 packages (also removes
tibble, pillar, purrr, stringi, stringr, tidyselect, generics,
magrittr and more). Returned data objects keep the tbl_df/tbl classes
so they continue to integrate with tibble/dplyr workflows, but tibble
is no longer required at install time.print() for a ggseg_atlas now shows the first 10 core rows by default
(atlases can have hundreds of regions); pass n to control how many rows
print, e.g. print(dk(), n = 50).atlas_sf() no longer re-sorts geometry rows alphabetically by label. The
underlying merge() defaulted to sort = TRUE, which discarded the
context-behind-core draw order established by the manipulation helpers, so
contextual regions could draw on top of focus regions. The ordering is now
preserved and re-applied after the join, matching as.data.frame().atlas_type() can again guess the type of an atlas whose type is unset:
guess_type() now reads views from the unified $data geometry slot instead
of the legacy bare $sf slot, which a modern ggseg_atlas never populates
(it previously always guessed "subcortical").read_atlas_files() extracts the subject id by stripping the subjects_dir
prefix by length rather than as a regular expression, so directories
containing regex metacharacters (or a trailing slash) no longer yield the
wrong subject.read_freesurfer_table(measure = ) strips the _<measure> suffix literally
from the end of each label instead of with an unanchored regex, so a label
that contains the measure mid-string is no longer over-stripped.atlas_palette() given a non-atlas object now errors with a class-specific
message instead of interpolating the whole object into "Could not find
atlas".?ggseg.formats alias
are now derived from DESCRIPTION (previously titled "Plot brain
segmentations with ggplot" and aliased as ggseg).utils::globalVariables() registration, which no
longer referenced any global used by the package.data-raw/make_hex.R.goodpractice + tidyverse check suite as a
CI hard gate, at 100% line coverage. Formatting is enforced with air and
linting with lintr.ggseg_data_cerebellar() gains an optional meshes parameter for deep
cerebellar structures (e.g. dentate, interposed, fastigial nuclei) that
are not on the SUIT cortical surface. Surface regions use vertices
(shared SUIT mesh), deep structures use individual meshes (like
subcortical atlases).vertices + meshes labels against
core when both are present, rather than requiring each to cover all labels
independently.rebuild_atlas_data() preserves cerebellar data type and handles mixed
vertices + meshes correctly.reposition_views() now handles sfc_GEOMETRY (mixed geometry types) by
casting to MULTIPOLYGON before coordinate operations.atlas_view_gather() is more robust against non-sf or empty sf data,
preventing errors in subcortical and tract pipelines.Initial CRAN release. Extracts and formalises the atlas data structures that
were previously embedded in ggseg and ggseg3d.
ggseg_atlas() constructor with typed data containers for cortical,
subcortical, tract, and cerebellar atlases.is_ggseg_atlas(), is_cortical_atlas(),
is_subcortical_atlas(), is_tract_atlas(), is_cerebellar_atlas().as_ggseg_atlas(), as.data.frame(), and as.list()
methods.plot() method for quick atlas visualisation via ggplot2.atlas_type(), atlas_regions(), atlas_labels(), atlas_palette(),
atlas_sf(), atlas_vertices(), atlas_meshes(), and atlas_views()
for querying atlas contents without reaching into slots.atlas_region_keep(),
atlas_region_remove(), atlas_region_rename(),
atlas_region_contextual().atlas_core_add().atlas_view_keep(), atlas_view_remove(),
atlas_view_remove_region(), atlas_view_remove_small(),
atlas_view_gather(), atlas_view_reorder().dk() (Desikan-Killiany cortical),
aseg() (FreeSurfer subcortical), and tracula() (white matter tracts).get_brain_mesh() and get_cerebellar_mesh() provide 3D surface meshes
for rendering.convert_legacy_brain_atlas() and unify_legacy_atlases() bridge old
ggseg/ggseg3d atlas objects to the unified format.brain_atlas(), brain_regions(), etc.) ease
migration from the old API.read_freesurfer_stats(), read_atlas_files(), and
read_freesurfer_table() for reading FreeSurfer statistics into R.