{"spec_id":"recurrence-basic","library":"ggplot2","language":"r","code":"#' anyplot.ai\n#' recurrence-basic: Recurrence Plot for Nonlinear Time Series\n#' Library: ggplot2 3.5.1 | R 4.4.1\n#' Quality: 88/100 | Created: 2026-06-10\n\nlibrary(ggplot2)\nlibrary(ragg)\n\nset.seed(42)\n\n# Theme tokens — Imprint palette, theme-adaptive chrome\nTHEME       <- Sys.getenv(\"ANYPLOT_THEME\", \"light\")\nPAGE_BG     <- if (THEME == \"light\") \"#FAF8F1\" else \"#1A1A17\"\nELEVATED_BG <- if (THEME == \"light\") \"#FFFDF6\" else \"#242420\"\nINK         <- if (THEME == \"light\") \"#1A1A17\" else \"#F0EFE8\"\nINK_SOFT    <- if (THEME == \"light\") \"#4A4A44\" else \"#B8B7B0\"\nIMPRINT_PALETTE <- c(\n  \"#009E73\",  # 1 — brand green (first categorical series)\n  \"#C475FD\",  # 2 — lavender\n  \"#4467A3\",  # 3 — blue\n  \"#BD8233\",  # 4 — ochre\n  \"#AE3030\",  # 5 — matte red\n  \"#2ABCCD\",  # 6 — cyan\n  \"#954477\",  # 7 — rose\n  \"#99B314\"   # 8 — lime\n)\n\n# Data: logistic map in chaotic regime (r = 3.9, 300 steps)\nn_steps <- 300\nr_param <- 3.9\nx_series <- numeric(n_steps)\nx_series[1] <- 0.4\nfor (i in 2:n_steps) {\n  x_series[i] <- r_param * x_series[i - 1] * (1 - x_series[i - 1])\n}\n\n# Time-delay embedding (Takens' theorem): dim = 2, delay = 5\nemb_dim <- 2\ndelay   <- 5\nn_emb   <- n_steps - (emb_dim - 1) * delay\nstates  <- matrix(0.0, nrow = n_emb, ncol = emb_dim)\nfor (d in seq_len(emb_dim)) {\n  start_idx  <- (d - 1) * delay + 1\n  states[, d] <- x_series[start_idx:(start_idx + n_emb - 1)]\n}\n\n# Pairwise Euclidean distances; binary threshold at 5th percentile\ndist_mat      <- as.matrix(dist(states))\nnonzero_dists <- dist_mat[dist_mat > 0]\nepsilon       <- quantile(nonzero_dists, 0.05)\nrecurrence    <- as.integer(dist_mat <= epsilon)\n\n# Long data frame for geom_raster\nn_pts  <- nrow(states)\nrec_df <- data.frame(\n  i         = rep(seq_len(n_pts), times = n_pts),\n  j         = rep(seq_len(n_pts), each  = n_pts),\n  recurrent = recurrence\n)\n\nplot_title    <- \"Logistic Map · recurrence-basic · r · ggplot2 · anyplot.ai\"\nplot_subtitle <- \"r = 3.9 (chaotic regime) · short diagonal bands signal deterministic recurrence\"\n\n# Plot: binary recurrence matrix with diagonal reference + storytelling annotation\np <- ggplot(rec_df, aes(x = i, y = j, fill = factor(recurrent))) +\n  geom_raster(interpolate = FALSE) +\n  # Diagonal reference line emphasising the main recurrence axis (LOI)\n  geom_abline(\n    slope = 1, intercept = 0,\n    color = IMPRINT_PALETTE[3], linewidth = 0.5, alpha = 0.55\n  ) +\n  # Arrow annotation pointing to off-diagonal band structure\n  annotate(\n    \"segment\",\n    x = n_pts * 0.16, xend = n_pts * 0.26,\n    y = n_pts * 0.96, yend = n_pts * 0.81,\n    arrow = arrow(length = unit(0.12, \"cm\"), type = \"closed\"),\n    color = INK_SOFT, linewidth = 0.55\n  ) +\n  annotate(\n    \"text\",\n    x = n_pts * 0.10, y = n_pts * 0.98,\n    label = \"off-diagonal bands\\n= determinism\",\n    color = INK_SOFT, size = 2.7, hjust = 0.5, lineheight = 0.9\n  ) +\n  scale_fill_manual(\n    values = c(\"0\" = PAGE_BG, \"1\" = IMPRINT_PALETTE[1]),\n    guide  = \"none\"\n  ) +\n  scale_x_continuous(expand = c(0, 0), breaks = seq(50, n_pts, by = 50)) +\n  scale_y_continuous(expand = c(0, 0), breaks = seq(50, n_pts, by = 50)) +\n  coord_fixed(ratio = 1) +\n  labs(\n    title    = plot_title,\n    subtitle = plot_subtitle,\n    x        = \"Time Index\",\n    y        = \"Time Index\"\n  ) +\n  theme_minimal(base_size = 8) +\n  theme(\n    plot.background     = element_rect(fill = PAGE_BG, color = PAGE_BG),\n    panel.background    = element_rect(fill = PAGE_BG, color = NA),\n    panel.grid.major    = element_blank(),\n    panel.grid.minor    = element_blank(),\n    panel.border        = element_rect(color = INK_SOFT, fill = NA, linewidth = 0.5),\n    axis.title          = element_text(color = INK,      size = 10),\n    axis.text           = element_text(color = INK_SOFT, size = 9),\n    plot.title          = element_text(color = INK,      size = 12, hjust = 0.5),\n    plot.subtitle       = element_text(color = INK_SOFT, size = 9,  hjust = 0.5),\n    plot.title.position = \"plot\",\n    plot.margin         = margin(16, 16, 12, 12, unit = \"pt\")\n  )\n\n# Save — square canvas: 2400 × 2400 px (width=6, height=6, dpi=400)\nggsave(\n  filename = sprintf(\"plot-%s.png\", THEME),\n  plot     = p,\n  device   = ragg::agg_png,\n  width    = 6,\n  height   = 6,\n  units    = \"in\",\n  dpi      = 400\n)\n"}