Skip to contents

anatomical_error_partitioning() quantifies how much variance in trackway parameters is due to footprint landmark placement uncertainty (degree of anatomical fidelity) versus genuine between-trackway (biological) differences, using simulation only (no observer effects).

Usage

anatomical_error_partitioning(
  data,
  error_radius,
  variables,
  gauge_size = NA,
  n_sim = 200,
  distribution = c("uniform", "gaussian"),
  seed = NULL
)

Arguments

data

A trackway R object. See tps_to_track.

error_radius

Numeric; single radius (m) applied to footprints of all trackways or a numeric vector of length length(data$Trajectories) with per-trackway tolerances.

variables

A character vector specifying the movement parameters to be used. Valid parameter names include: "TurnAng", "sdTurnAng", "PathLen", "BeelineLen", "StLength", "sdStLength", "StrideLen", "PaceLen", "Sinuosity", "Straightness", "TrackWidth", "Gauge", "PaceAng", "StepAng", "Velocity", "sdVelocity", "MaxVelocity", "MinVelocity". See track_param and cluster_track for details.

gauge_size

Numeric. Pes/manus length (or width) used to compute Gauge as Trackway_width / gauge_size. See track_param for details.

n_sim

Integer; number of Monte Carlo jitter simulations per trackway. Default is 200.

distribution

A character string indicating the jitter model. Options are "uniform" (points uniformly within a disk of radius r; default) or "gaussian" (SD = r/2 on X and Y, truncated at 3 SD).

seed

Optional integer for reproducibility. Default is NULL.

Value

An "error_partitioning" R object consisting of a list containing the following elements:

summary

Data frame of variance components per variable. Columns: variable, component, variance, percent, and \(R^2_c\). Components are trackway (biological), anatomical (within-trackway simulation variance), and Residual (from the model on simulation means).

snr

Data frame with the signal-to-noise ratio per variable. Columns: variable, bio_component (always "trackway"), bio_var, error_var, and SNR. The ratio is $$SNR = Var(trackway) / [Var(anatomical) + Var(Residual)].$$

qc

Compact quality-control table per variable with SNR, a qualitative SNR_rating ("weak", "moderate", "strong"), the top_component by percent, its top_percent, \(R^2_c\), and an observer_note (always "anatomical-only" for this function).

models

NULL. Placeholder kept for consistency with the observer-inclusive workflow. No observer models are fitted here.

analysis_table

Long data frame with all simulated values for every trackway across all Monte Carlo runs (variables joined with trackway IDs and simulation labels).

formulae

A short note describing the simulation-only decomposition (within-trackway anatomical variance from simulations, plus a random-intercept model on simulation means: \(y \sim 1 + (1|trackway)\); angles handled via sine–cosine).

trackway_names

Character vector of internal trackway labels used in the analysis.

Details

The function estimates how much of the variability in trackway metrics can be attributed to positional uncertainty in footprint landmarks, rather than to true biological differences among trackways. It asks, in essence: "If landmarks were slightly misplaced by up to error_radius, how much would that affect our computed parameters?" For each trackway, landmarks are repeatedly perturbed within the specified spatial tolerance, the medial trajectory is reconstructed, and parameters are recalculated across Monte Carlo simulations. The resulting variance in each metric is then decomposed into a between-trackway component (biological signal) and a within-trackway component (anatomical noise).

The error_radius represents expected imprecision in reference-point digitization (e.g., preservation quality, erosion, deformation, or subjective landmark interpretation). By specifying a realistic tolerance, users can evaluate how sensitive each metric is to anatomical or taphonomic uncertainty and identify parameters that remain stable despite imperfect preservation.

For every trackway and simulation, landmarks are randomly displaced within a circular area of radius r, using either a uniform model ("uniform") or a truncated Gaussian on X and Y with SD = r/2 ("gaussian", truncated at ±3 SD). Each perturbed landmark set is converted to a medial trajectory (midpoints between consecutive footprints, as in tps_to_track()), and parameters are recalculated via track_param(). For each metric \(Y\), total variance is partitioned via the law of total variance into:

  • trackway (biological) — variance of simulation means among trackways;

  • anatomical — mean of within-trackway variances across simulations;

  • Residual — residual from the random-intercept model on simulation means (no observer terms in this simulation-only setup).

Angular variables (TurnAng, PaceAng) are embedded in sine–cosine space to handle circularity and avoid 0°/360° discontinuities (Fisher, 1995).

A signal-to-noise ratio quantifies robustness: $$\mathrm{SNR} = \frac{\mathrm{Var}(\mathrm{trackway})} {\mathrm{Var}(\mathrm{anatomical}) + \mathrm{Var}(\mathrm{Residual})}.$$ As a rule of thumb:

  • SNR < 1 — anatomical error exceeds biology (weak);

  • SNR ~ 1–2 — biology and anatomical error are comparable (moderate);

  • SNR > 2 — biology dominates (strong).

A compact QC table reports SNR, the qualitative rating, the top component by percent, and the conditional \(R^2_c\).

References

Fisher, N. I. (1995). Statistical Analysis of Circular Data. Cambridge University Press.

Author

Humberto G. Ferrón

humberto.ferron@uv.es

Macroevolution and Functional Morphology Research Group (www.macrofun.es)

Cavanilles Institute of Biodiversity and Evolutionary Biology

Calle Catedrático José Beltrán Martínez, nº 2

46980 Paterna - Valencia - Spain

Phone: +34 (9635) 44477

Examples

# Example 1: PaluxyRiver, small jitter (2 cm), uniform noise
# Expect relatively stable metrics and higher SNR.
set.seed(1)
ep_small <- anatomical_error_partitioning(
  data         = PaluxyRiver,
  error_radius = 0.02,
  variables    = c("BeelineLen", "Straightness", "TurnAng"),
  n_sim        = 10
)
ep_small$qc
#>       variable        SNR SNR_rating top_component top_percent      R2_c
#> 1   BeelineLen 2734.80404     strong      trackway    99.96345 0.9996345
#> 2 Straightness   22.61413     strong      trackway    95.76525 0.9576525
#> 3      TurnAng 1471.30665     strong      trackway    99.93208 0.9993208
#>                observer_estimable
#> 1 no (anatomical-only, sim-based)
#> 2 no (anatomical-only, sim-based)
#> 3 no (anatomical-only, sim-based)

# Example 2: PaluxyRiver, larger jitter (8 cm) to see SNR drop
# Inflate anatomical uncertainty; SNR should typically decrease.
set.seed(1)
ep_large <- anatomical_error_partitioning(
  data         = PaluxyRiver,
  error_radius = 0.08,
  variables    = c("BeelineLen", "Straightness", "TurnAng"),
  n_sim        = 10
)
ep_large$qc
#>       variable        SNR SNR_rating top_component top_percent      R2_c
#> 1   BeelineLen 165.040390     strong      trackway    99.39774 0.9939774
#> 2 Straightness   2.187696     strong      trackway    68.62938 0.6862938
#> 3      TurnAng  90.802197     strong      trackway    98.91070 0.9891070
#>                observer_estimable
#> 1 no (anatomical-only, sim-based)
#> 2 no (anatomical-only, sim-based)
#> 3 no (anatomical-only, sim-based)

# Example 3: MountTom subset + Gaussian jitter (3 cm, truncated at ±3 SD)
# Demonstrates alternative noise model and a reduced dataset.
sbMountTom <- subset_track(
  MountTom,
  tracks = c(1, 2, 3, 4, 7, 8, 9, 13, 15, 16, 18)
)
set.seed(2)
ep_gauss <- anatomical_error_partitioning(
  data         = sbMountTom,
  error_radius = 0.03,
  variables    = c("StLength", "sdStLength", "PaceAng"),
  n_sim        = 10,
  distribution = "gaussian"
)
ep_gauss$snr
#>              variable bio_component     bio_var    error_var        SNR
#> StLength     StLength      trackway 0.058217558 1.031312e-05 5644.99846
#> sdStLength sdStLength      trackway 0.001165249 2.973018e-05   39.19415
#> PaceAng       PaceAng      trackway 0.005343677 2.543369e-04   21.01023

# Example 4: PaluxyRiver with heterogeneous per-trackway tolerances
# Alternate 2 cm / 5 cm across trackways; highlights mixed preservation quality.
set.seed(3)
rads <- rep(c(0.02, 0.05),
            length.out = length(PaluxyRiver$Footprints))
ep_het <- anatomical_error_partitioning(
  data         = PaluxyRiver,
  error_radius = rads,
  variables    = c("TrackWidth", "Sinuosity", "PaceAng"),
  n_sim        = 10
)
ep_het$summary
#>                variable  component     variance    percent      R2_c
#> TrackWidth.1 TrackWidth   trackway 3.740549e-02 99.7499311 0.9974993
#> TrackWidth.2 TrackWidth anatomical 9.377402e-05  0.2500689 0.9974993
#> TrackWidth.3 TrackWidth   Residual 0.000000e+00  0.0000000 0.9974993
#> Sinuosity.1   Sinuosity   trackway 3.086845e-03 98.6831363 0.9868314
#> Sinuosity.2   Sinuosity anatomical 4.119198e-05  1.3168637 0.9868314
#> Sinuosity.3   Sinuosity   Residual 0.000000e+00  0.0000000 0.9868314
#> PaceAng.1       PaceAng   trackway 8.498442e-02 99.7797710 0.9977977
#> PaceAng.2       PaceAng anatomical 1.875734e-04  0.2202290 0.9977977
#> PaceAng.3       PaceAng   Residual 0.000000e+00  0.0000000 0.9977977

# Example 5: Angles only (circular handling via sine–cosine embedding)
# Focus on orientation metrics; output includes averaged sin/cos components.
set.seed(4)
ep_ang <- anatomical_error_partitioning(
  data         = PaluxyRiver,
  error_radius = 0.04,
  variables    = c("TurnAng", "PaceAng"),
  n_sim        = 10
)
ep_ang$summary
#>           variable  component     variance    percent      R2_c
#> TurnAng.1  TurnAng   trackway 4.283363e-04 99.8192789 0.9981928
#> TurnAng.2  TurnAng anatomical 7.754955e-07  0.1807211 0.9981928
#> TurnAng.3  TurnAng   Residual 0.000000e+00  0.0000000 0.9981928
#> PaceAng.1  PaceAng   trackway 8.475987e-02 99.7051248 0.9970512
#> PaceAng.2  PaceAng anatomical 2.506750e-04  0.2948752 0.9970512
#> PaceAng.3  PaceAng   Residual 0.000000e+00  0.0000000 0.9970512