{"spec_id":"heatmap-mandelbrot","library":"letsplot","language":"python","code":"\"\"\" anyplot.ai\nheatmap-mandelbrot: Mandelbrot Set Fractal Visualization\nLibrary: letsplot 4.10.1 | Python 3.13.13\nQuality: 90/100 | Updated: 2026-05-30\n\"\"\"\n\nimport os\n\nimport numpy as np\nimport pandas as pd\nfrom lets_plot import (\n    LetsPlot,\n    aes,\n    coord_fixed,\n    element_blank,\n    element_line,\n    element_rect,\n    element_text,\n    geom_raster,\n    ggplot,\n    ggsize,\n    guide_colorbar,\n    labs,\n    layer_tooltips,\n    scale_fill_gradient,\n    scale_x_continuous,\n    scale_y_continuous,\n    theme,\n    theme_minimal,\n)\nfrom lets_plot.export import ggsave\n\n\nLetsPlot.setup_html()\n\n# Theme-adaptive chrome (Imprint palette chrome tokens)\nTHEME = os.getenv(\"ANYPLOT_THEME\", \"light\")\nPAGE_BG = \"#FAF8F1\" if THEME == \"light\" else \"#1A1A17\"\nELEVATED_BG = \"#FFFDF6\" if THEME == \"light\" else \"#242420\"\nINK = \"#1A1A17\" if THEME == \"light\" else \"#F0EFE8\"\nINK_SOFT = \"#4A4A44\" if THEME == \"light\" else \"#B8B7B0\"\nINK_MUTED = \"#6B6A63\" if THEME == \"light\" else \"#A8A79F\"\n\n# Data — Mandelbrot set via smooth (normalized) iteration count\nx_min, x_max = -2.5, 1.0\ny_min, y_max = -1.25, 1.25\nwidth, height = 800, 571\nmax_iter = 100\n\nreal = np.linspace(x_min, x_max, width)\nimag = np.linspace(y_min, y_max, height)\nreal_grid, imag_grid = np.meshgrid(real, imag)\nc = real_grid + 1j * imag_grid\n\nz = np.zeros_like(c, dtype=complex)\niterations = np.full(c.shape, max_iter, dtype=float)\n\nfor i in range(max_iter):\n    mask = np.abs(z) <= 2\n    z[mask] = z[mask] ** 2 + c[mask]\n    escaped = mask & (np.abs(z) > 2)\n    if np.any(escaped):\n        abs_z = np.abs(z[escaped])\n        # Smooth coloring eliminates discrete banding\n        iterations[escaped] = i + 1 - np.log2(np.log2(abs_z))\n\n# Interior points (never escaped) → NaN → na_value black\ninterior = iterations >= max_iter\niterations[interior] = np.nan\n\ndf = pd.DataFrame({\"real\": real_grid.ravel(), \"imag\": imag_grid.ravel(), \"iterations\": iterations.ravel()})\n\n# Plot — Imprint sequential colormap (brand-green → blue) on escape-time data\nplot = (\n    ggplot(df, aes(x=\"real\", y=\"imag\", fill=\"iterations\"))\n    + geom_raster(\n        tooltips=layer_tooltips()\n        .format(\"@real\", \".3f\")\n        .format(\"@imag\", \".3f\")\n        .format(\"@iterations\", \".1f\")\n        .line(\"c = @real + @imag·i\")\n        .line(\"Iterations: @iterations\")\n    )\n    + scale_fill_gradient(\n        low=\"#009E73\",\n        high=\"#4467A3\",\n        na_value=\"#000000\",\n        name=\"Iterations\",\n        guide=guide_colorbar(barwidth=15, barheight=200, nbin=256),\n    )\n    + scale_x_continuous(name=\"Real Axis\", breaks=[-2.5, -2.0, -1.5, -1.0, -0.5, 0.0, 0.5, 1.0], expand=[0.01, 0])\n    + scale_y_continuous(name=\"Imaginary Axis\", breaks=[-1.0, -0.5, 0.0, 0.5, 1.0], expand=[0.01, 0])\n    + coord_fixed()\n    + labs(\n        title=\"heatmap-mandelbrot · letsplot · anyplot.ai\",\n        subtitle=\"Escape-time fractal with smooth iteration coloring on the complex plane\",\n        caption=\"z(n+1) = z(n)² + c · max iterations = 100 · interior points in black\",\n    )\n    + theme_minimal()\n    + theme(\n        plot_title=element_text(size=16, face=\"bold\", color=INK),\n        plot_subtitle=element_text(size=11, color=INK_SOFT, face=\"italic\"),\n        plot_caption=element_text(size=9, color=INK_MUTED),\n        axis_title=element_text(size=12, color=INK),\n        axis_text=element_text(size=10, color=INK_SOFT),\n        axis_line=element_line(color=INK_SOFT, size=0.3),\n        legend_title=element_text(size=10, color=INK),\n        legend_text=element_text(size=10, color=INK_SOFT),\n        legend_background=element_rect(fill=ELEVATED_BG, color=INK_SOFT),\n        panel_grid=element_blank(),\n        panel_background=element_rect(fill=PAGE_BG),\n        plot_background=element_rect(fill=PAGE_BG, color=PAGE_BG),\n        plot_margin=[20, 15, 10, 15],\n    )\n    + ggsize(800, 450)\n)\n\n# Save — canonical scale=4 → 3200×1800 px landscape\nggsave(plot, f\"plot-{THEME}.png\", path=\".\", scale=4)\nggsave(plot, f\"plot-{THEME}.html\", path=\".\")\n"}