{"spec_id":"recurrence-basic","library":"chartjs","language":"javascript","code":"// anyplot.ai\n// recurrence-basic: Recurrence Plot for Nonlinear Time Series\n// Library: chartjs 4.4.7 | JavaScript 22.22.3\n// Quality: 90/100 | Created: 2026-06-10\n\n//# anyplot-orientation: square\n\nconst t = window.ANYPLOT_TOKENS;\n\n// Logistic map: x_{n+1} = r * x_n * (1 - x_n), chaotic regime r=3.9\nconst N = 200;\nconst r = 3.9;\nconst series = new Array(N);\nseries[0] = 0.4;\nfor (let i = 1; i < N; i++) {\n  series[i] = r * series[i - 1] * (1 - series[i - 1]);\n}\n\n// Binary recurrence matrix — state pair (i,j) is recurrent when |x_i - x_j| < epsilon\nconst epsilon = 0.12;\nconst recMatrix = [];\nfor (let i = 0; i < N; i++) {\n  recMatrix[i] = new Uint8Array(N);\n  for (let j = 0; j < N; j++) {\n    if (Math.abs(series[i] - series[j]) < epsilon) {\n      recMatrix[i][j] = 1;\n    }\n  }\n}\n\nconst canvas = document.createElement(\"canvas\");\ndocument.getElementById(\"container\").appendChild(canvas);\n\n// Plugin: draw plot area background then the recurrence matrix before datasets layer\nconst recurrencePlugin = {\n  id: \"recurrenceMatrix\",\n  beforeDatasetsDraw(chart) {\n    const { ctx, chartArea } = chart;\n    const { left, top, right, bottom } = chartArea;\n    const cellW = (right - left) / N;\n    const cellH = (bottom - top) / N;\n\n    ctx.save();\n\n    // Plot area background\n    ctx.fillStyle = t.pageBg;\n    ctx.fillRect(left, top, right - left, bottom - top);\n\n    // Recurrent pairs in Imprint brand green\n    ctx.fillStyle = t.palette[0];\n    for (let i = 0; i < N; i++) {\n      const x = left + i * cellW;\n      for (let j = 0; j < N; j++) {\n        if (recMatrix[i][j]) {\n          // Canvas y increases downward; j=0 maps to bottom of chart area\n          ctx.fillRect(x, top + (N - 1 - j) * cellH, cellW + 0.5, cellH + 0.5);\n        }\n      }\n    }\n\n    ctx.restore();\n  },\n};\n\nnew Chart(canvas, {\n  type: \"scatter\",\n  data: { datasets: [] },\n  plugins: [recurrencePlugin],\n  options: {\n    responsive: true,\n    maintainAspectRatio: false,\n    animation: false,\n    plugins: {\n      title: {\n        display: true,\n        text: \"recurrence-basic · javascript · chartjs · anyplot.ai\",\n        color: t.ink,\n        font: { size: 22 },\n        padding: { top: 12, bottom: 18 },\n      },\n      legend: { display: false },\n    },\n    scales: {\n      x: {\n        type: \"linear\",\n        min: 0,\n        max: N,\n        ticks: { color: t.inkSoft, font: { size: 14 }, maxTicksLimit: 6 },\n        grid: { color: t.grid },\n        border: { color: t.inkSoft },\n        title: {\n          display: true,\n          text: \"Time index i\",\n          color: t.ink,\n          font: { size: 16 },\n          padding: { top: 8 },\n        },\n      },\n      y: {\n        type: \"linear\",\n        min: 0,\n        max: N,\n        ticks: { color: t.inkSoft, font: { size: 14 }, maxTicksLimit: 6 },\n        grid: { color: t.grid },\n        border: { color: t.inkSoft },\n        title: {\n          display: true,\n          text: \"Time index j\",\n          color: t.ink,\n          font: { size: 16 },\n          padding: { bottom: 8 },\n        },\n      },\n    },\n  },\n});\n"}