{"spec_id":"bifurcation-basic","library":"muix","language":"javascript","code":"// anyplot.ai\n// bifurcation-basic: Bifurcation Diagram for Dynamical Systems\n// Library: muix 9.16.0 | JavaScript 22.23.3\n// Quality: 86/100 | Updated: 2026-10-24\nimport { ChartsContainer } from \"@mui/x-charts/ChartsContainer\";\nimport { ScatterPlot } from \"@mui/x-charts/ScatterChart\";\nimport { ChartsXAxis } from \"@mui/x-charts/ChartsXAxis\";\nimport { ChartsYAxis } from \"@mui/x-charts/ChartsYAxis\";\nimport { useXScale, useDrawingArea } from \"@mui/x-charts/hooks\";\n\nconst t = window.ANYPLOT_TOKENS;\n\n// Constants\nconst STATE_MIN = 0;\nconst STATE_MAX = 1;\nconst POINT_ALPHA = 0.55;\nconst R_PAD_SHARE = 0.02;\nconst LABEL_DX = -8; // labels sit left of their marker line\n// topShare: label height as a share of the drawing area, measured from its top\nconst BIFURCATION_POINTS = [\n  { r: 3.0, text: \"Period-2\", topShare: 0.06 },\n  { r: 3.449, text: \"Period-4\", topShare: 0.06 },\n  { r: 3.544, text: \"Period-8\", topShare: 0.86 },\n];\n\n// Columns: set these to your data's column names\nconst PARAMETER = \"Growth rate (r)\"; // role: parameter\nconst STATE = \"Steady-state population (x)\"; // role: state\n\n// Data: replace this block with your own records, one object per row\nconst data = (() => {\n  const rMin = 2.5;\n  const rMax = 4.0;\n  const rSteps = 1000;\n  const transient = 300;\n  const record = 120;\n  const x0 = 0.4;\n  const rows: { [key: string]: number }[] = [];\n  for (let i = 0; i < rSteps; i++) {\n    const r = rMin + ((rMax - rMin) * i) / (rSteps - 1);\n    let x = x0;\n    for (let n = 0; n < transient; n++) x = r * x * (1 - x);\n    for (let n = 0; n < record; n++) {\n      x = r * x * (1 - x);\n      rows.push({ [PARAMETER]: r, [STATE]: x });\n    }\n  }\n  return rows;\n})();\n\n// Plot: reads only data and the constants above\nlet rMin = Infinity;\nlet rMax = -Infinity;\nconst points = data.map((d, i) => {\n  const r = d[PARAMETER];\n  const x = d[STATE];\n  if (r < rMin) rMin = r;\n  if (r > rMax) rMax = r;\n  return { x: r, y: x, id: i };\n});\n\nconst rPad = (rMax - rMin) * R_PAD_SHARE;\n\nconst p0Int = parseInt(t.palette[0].slice(1), 16);\nconst pointColor = `rgba(${(p0Int >> 16) & 255}, ${(p0Int >> 8) & 255}, ${p0Int & 255}, ${POINT_ALPHA})`;\n\nconst TITLE = \"bifurcation-basic · javascript · muix · anyplot.ai\";\nconst SUBTITLE = `${points.length.toLocaleString(\"en-US\")} points · ${PARAMETER}: ${rMin.toLocaleString(\"en-US\")}–${rMax.toLocaleString(\"en-US\")}`;\nconst HEADER_H = 78;\n\nfunction Bifurcations() {\n  const xScale = useXScale(\"r\");\n  const { top, height } = useDrawingArea();\n\n  return (\n    <g>\n      {BIFURCATION_POINTS.filter((m) => m.r >= rMin && m.r <= rMax).map((m) => {\n        const x = xScale(m.r);\n        const labelY = top + m.topShare * height;\n        const labelText = `${m.text} (r ≈ ${m.r})`;\n        const pillW = labelText.length * 7.6 + 12;\n        const pillX = x + LABEL_DX - pillW + 4;\n        return (\n          <g key={m.r}>\n            <line\n              x1={x}\n              y1={top}\n              x2={x}\n              y2={top + height}\n              stroke={t.amber}\n              strokeWidth={1.5}\n              strokeDasharray=\"7 5\"\n              opacity={0.75}\n            />\n            <rect\n              x={pillX}\n              y={labelY - 15}\n              width={pillW}\n              height={22}\n              rx={4}\n              fill={t.pageBg}\n              fillOpacity={0.86}\n            />\n            <text\n              x={x + LABEL_DX}\n              y={labelY}\n              fill={t.ink}\n              textAnchor=\"end\"\n              style={{\n                fontSize: 14,\n                fontFamily: \"Inter, system-ui, sans-serif\",\n                fontWeight: 600,\n              }}\n            >\n              {labelText}\n            </text>\n          </g>\n        );\n      })}\n    </g>\n  );\n}\n\nexport default function Chart() {\n  const W = window.ANYPLOT_SIZE.width;\n  const H = window.ANYPLOT_SIZE.height;\n\n  return (\n    <div\n      style={{\n        width: W,\n        height: H,\n        background: t.pageBg,\n        fontFamily: \"Inter, system-ui, sans-serif\",\n        display: \"flex\",\n        flexDirection: \"column\",\n      }}\n    >\n      <div\n        style={{\n          height: HEADER_H,\n          display: \"flex\",\n          flexDirection: \"column\",\n          alignItems: \"center\",\n          justifyContent: \"center\",\n          gap: 4,\n        }}\n      >\n        <span style={{ fontSize: 22, fontWeight: 600, color: t.ink }}>\n          {TITLE}\n        </span>\n        <span style={{ fontSize: 15, color: t.inkSoft }}>{SUBTITLE}</span>\n      </div>\n      <ChartsContainer\n        width={W}\n        height={H - HEADER_H}\n        skipAnimation\n        colors={[pointColor]}\n        margin={{ top: 16, bottom: 20, left: 36, right: 36 }}\n        series={[\n          {\n            type: \"scatter\",\n            data: points,\n            markerSize: 1,\n            label: STATE,\n            xAxisId: \"r\",\n            yAxisId: \"x\",\n          },\n        ]}\n        xAxis={[\n          {\n            id: \"r\",\n            min: rMin - rPad,\n            max: rMax + rPad,\n            tickNumber: 10,\n            height: 64,\n            label: PARAMETER,\n            tickLabelStyle: { fontSize: 14, fill: t.inkSoft },\n            labelStyle: { fontSize: 16, fill: t.ink, fontWeight: 500 },\n          },\n        ]}\n        yAxis={[\n          {\n            id: \"x\",\n            min: STATE_MIN,\n            max: STATE_MAX,\n            width: 84,\n            tickNumber: 11,\n            label: STATE,\n            tickLabelStyle: { fontSize: 14, fill: t.inkSoft },\n            labelStyle: { fontSize: 16, fill: t.ink, fontWeight: 500 },\n          },\n        ]}\n        sx={{\n          \"& .MuiChartsAxis-line\": { stroke: t.inkSoft },\n          \"& .MuiChartsAxis-tick\": { stroke: t.inkSoft },\n        }}\n      >\n        <ScatterPlot />\n        <ChartsXAxis axisId=\"r\" />\n        <ChartsYAxis axisId=\"x\" />\n        <Bifurcations />\n      </ChartsContainer>\n    </div>\n  );\n}\n"}