--- title: "radiatR design contract" description: > The design rules behind the radiatR API: which objects are rich classes, which stay plain tibbles, and the conventions the functions share. output: rmarkdown::html_vignette vignette: > %\VignetteIndexEntry{radiatR design contract} %\VignetteEngine{knitr::rmarkdown} %\VignetteEncoding{UTF-8} --- ```{r, include=FALSE} knitr::opts_chunk$set( collapse = TRUE, comment = "#>" ) ``` ```{r setup} library(radiatR) ``` radiatR keeps a tidyverse-shaped surface: data flows as plain tibbles addressed by column name, and rich objects are reserved for structure a flat table cannot hold safely. ## Rich objects, only where structure is irreducible - `Tracks` — trajectories with coordinate geometry, a per-trajectory reference frame, and transform history (invariants a bare tibble cannot enforce). - `circ_display()` — an orientation convention (zero direction, rotation). - `circ_regression()` — a fitted model (like `lm`). ## Everything else is a plain tibble, in and out Plain tibbles are addressed by a column-name argument (`angle_col = "heading"`). The `circular` package's `circular` objects are an internal implementation detail — built inside functions, never in a public signature or return. ## `headings_frame`: a dplyr-durable tibble subclass `headings_frame` is a tibble subclass that carries the display convention durably through dplyr verbs (via the `dplyr_reconstruct` contract), so a `mutate()`/`filter()` never silently drops the orientation. Read its metadata with the `hf_*` accessors. A plain data frame with a heading column is always an acceptable substitute — the class is an enhancement, never a requirement: ```{r, eval = requireNamespace("dplyr", quietly = TRUE)} data(cpunctatus) hd <- derive_headings(cpunctatus, rule = "distal") hd2 <- dplyr::filter(hd, is.finite(heading)) # class + display preserved class(hd2) hf_display(hd2) ```