## ----include = FALSE----------------------------------------------------------
knitr::opts_chunk$set(collapse = TRUE, comment = "#>", fig.width = 7, fig.height = 5)

## -----------------------------------------------------------------------------
library(ggplot2)
library(dplyr)
library(ggcircular)

## -----------------------------------------------------------------------------
boundary_angles <- tibble(
  theta = c(0.05, 0.10, 2 * pi - 0.10, 2 * pi - 0.05)
)

boundary_angles |>
  summarise(
    arithmetic_mean = mean(theta),
    circular_mean = mean_direction(theta),
    Rbar = mean_resultant_length(theta)
  )

## -----------------------------------------------------------------------------
glimpse(wind_directions)
glimpse(animal_steps)
glimpse(hourly_activity)
glimpse(axial_orientations)

## -----------------------------------------------------------------------------
wind_directions |>
  count(season, station)

## -----------------------------------------------------------------------------
directional <- c(0, pi)
axial <- c(0, pi)

tibble(
  case = c("directional", "axial"),
  Rbar = c(
    mean_resultant_length(directional),
    mean_resultant_length(axial, axial = TRUE)
  ),
  mean = c(
    mean_direction(directional),
    mean_direction(axial, axial = TRUE)
  )
)

## -----------------------------------------------------------------------------
tibble(
  degrees = c(0, 90, 180, 270),
  radians = deg_to_rad(degrees),
  hours = rad_to_hour(radians),
  compass = rad_to_compass(radians)
)

## -----------------------------------------------------------------------------
ggplot(wind_directions, aes(x = direction)) +
  geom_rose(bins = 16) +
  scale_x_circular_degrees() +
  coord_circular() +
  theme_circular()

## -----------------------------------------------------------------------------
ggplot(wind_directions, aes(x = direction)) +
  geom_rose(
    aes(fill = after_stat(proportion)),
    bins = 16,
    normalize = "proportion"
  ) +
  scale_x_circular_degrees() +
  coord_circular() +
  theme_rose()

## -----------------------------------------------------------------------------
ggplot(wind_directions, aes(x = direction, fill = season)) +
  geom_rose(bins = 16, alpha = 0.75) +
  facet_wrap(~ season) +
  scale_x_circular_degrees() +
  coord_circular() +
  theme_circular()

## -----------------------------------------------------------------------------
ggplot(wind_directions, aes(x = direction)) +
  geom_rose(aes(y = after_stat(density)), bins = 24, alpha = 0.35) +
  geom_circular_density(linewidth = 1) +
  scale_x_circular_degrees() +
  coord_circular() +
  theme_circular()

## -----------------------------------------------------------------------------
ggplot(wind_directions, aes(x = direction)) +
  geom_circular_density(bw = 0.25, linewidth = 1) +
  geom_circular_density(bw = 0.75, linetype = 2) +
  scale_x_circular_degrees() +
  coord_circular() +
  theme_circular()

## -----------------------------------------------------------------------------
wind_directions |>
  group_by(season) |>
  circular_summary(direction)

## -----------------------------------------------------------------------------
ggplot(wind_directions, aes(x = direction, colour = season)) +
  geom_circular_density(linewidth = 1) +
  geom_mean_direction(length = "resultant") +
  scale_x_circular_degrees() +
  coord_circular() +
  theme_circular()

## -----------------------------------------------------------------------------
circular_mean_ci(wind_directions$direction, method = "large_sample")
rayleigh_test(wind_directions$direction)

## -----------------------------------------------------------------------------
ggplot(wind_directions, aes(x = direction)) +
  geom_rose(bins = 16, alpha = 0.8) +
  stat_circular_test(test = "rayleigh", y = 1.1, size = 3) +
  scale_x_circular_degrees() +
  coord_circular() +
  theme_circular()

## -----------------------------------------------------------------------------
ggplot(wind_directions, aes(x = direction)) +
  geom_rose(bins = 16, aes(fill = after_stat(count))) +
  geom_mean_direction() +
  scale_x_circular_compass() +
  coord_circular(zero = "north", direction = "clockwise") +
  theme_compass()

## -----------------------------------------------------------------------------
axial_orientations |>
  group_by(group) |>
  circular_summary(orientation, axial = TRUE)

## -----------------------------------------------------------------------------
ggplot(axial_orientations, aes(x = orientation, fill = group)) +
  geom_rose(bins = 18, axial = TRUE, alpha = 0.7) +
  geom_mean_direction(axial = TRUE) +
  scale_x_circular_degrees(limits = c(0, pi)) +
  coord_circular() +
  theme_circular()

## -----------------------------------------------------------------------------
animal_steps |>
  group_by(state) |>
  summarise(
    mean_step = mean(step_length, na.rm = TRUE),
    median_step = median(step_length, na.rm = TRUE),
    .groups = "drop"
  )

## -----------------------------------------------------------------------------
ggplot(animal_steps, aes(x = x, y = y, group = id, colour = id)) +
  geom_path(alpha = 0.7) +
  coord_equal() +
  theme_minimal()

## -----------------------------------------------------------------------------
plot_state_angles(animal_steps, angle = turn_angle, state = state, type = "rose")

## -----------------------------------------------------------------------------
plot_state_angles(animal_steps, angle = turn_angle, state = state, type = "density")

## -----------------------------------------------------------------------------
fit_mix <- fit_vonmises_mixture(
  wind_directions$direction,
  k = 2,
  nstart = 3,
  seed = 2026,
  max_iter = 200
)

tidy_circular(fit_mix)
glance_circular(fit_mix)

## -----------------------------------------------------------------------------
ggplot(wind_directions, aes(x = direction)) +
  geom_rose(aes(y = after_stat(density)), bins = 24, alpha = 0.35) +
  stat_vonmises_mixture(fit = fit_mix, linewidth = 1) +
  scale_x_circular_degrees() +
  coord_circular() +
  theme_circular()

## -----------------------------------------------------------------------------
fit <- structure(
  list(
    y = wind_directions$direction[1:50],
    mui = normalize_angle(wind_directions$direction[1:50] + rnorm(50, 0, 0.15)),
    term_labels = c("intercept", "speed")
  ),
  class = "angular"
)

tidy_circular(fit)
glance_circular(fit)
circular_model_diagnostics(fit)

## -----------------------------------------------------------------------------
autoplot(fit, type = "residuals_density")

## -----------------------------------------------------------------------------
if (requireNamespace("posterior", quietly = TRUE)) {
  set.seed(1)
  draws <- posterior::draws_df(
    theta = rnorm(400, mean = pi / 3, sd = 0.25),
    phi = rnorm(400, mean = pi, sd = 0.35)
  )

  circular_draws <- as_circular_draws(draws, variables = c("theta", "phi"))
  summarise_circular_draws(circular_draws)
}

## -----------------------------------------------------------------------------
if (requireNamespace("posterior", quietly = TRUE)) {
  autoplot_circular_draws(circular_draws)
}

