{"spec_id":"heatmap-mandelbrot","library":"plotly","language":"python","code":"\"\"\" anyplot.ai\nheatmap-mandelbrot: Mandelbrot Set Fractal Visualization\nLibrary: plotly 6.7.0 | Python 3.13.13\nQuality: 87/100 | Created: 2026-05-30\n\"\"\"\n\nimport os\n\nimport numpy as np\nimport plotly.graph_objects as go\n\n\n# Theme 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\"\nGRID = \"rgba(26,26,23,0.15)\" if THEME == \"light\" else \"rgba(240,239,232,0.15)\"\nINSIDE_COLOR = \"#0D0D0A\"  # near-black for points inside the Mandelbrot set\n\n# Data: Mandelbrot set on the complex plane\n# Equal x/y extents (3.5 × 3.5 units) for square canvas\nx_min, x_max = -2.5, 1.0  # real axis — standard full view\ny_min, y_max = -1.75, 1.75  # imaginary axis — expanded to match x extent\nmax_iter = 256\nresolution = 1000  # square grid\n\nreal = np.linspace(x_min, x_max, resolution)\nimag = np.linspace(y_min, y_max, resolution)\nC = real[np.newaxis, :] + 1j * imag[:, np.newaxis]  # shape (resolution, resolution)\n\nZ = np.zeros_like(C)\nescape_count = np.zeros(C.shape, dtype=float)\nescaped = np.zeros(C.shape, dtype=bool)\n\nfor i in range(max_iter):\n    mask = ~escaped\n    Z[mask] = Z[mask] ** 2 + C[mask]\n    newly_escaped = mask & (np.abs(Z) > 2.0)\n    escape_count[newly_escaped] = i + 1\n    escaped |= newly_escaped\n\n# Smooth coloring: remove discrete banding via normalized iteration count\nabs_z = np.abs(Z)\nlog_z = np.log2(np.maximum(abs_z, 1.0 + 1e-10))\nlog_log_z = np.log2(np.maximum(log_z, 1e-10))\nsmooth = np.where(escaped, escape_count - log_log_z, -1.0)\n\n# Power-law (gamma=0.3) normalization spreads colors across the full exterior\n# much better than log or sqrt — most escaped pixels have low iteration counts,\n# so a strong gamma pulls the green→blue gradient into the near-boundary bands\ns_min = smooth[escaped].min()\ns_max = smooth[escaped].max()\nlinear_norm = (smooth - s_min) / (s_max - s_min)\ngamma_norm = np.power(np.maximum(linear_norm, 0.0), 0.3)\nz_data = np.where(escaped, gamma_norm * 0.98 + 0.02, 0.0)\n\n# Colorscale: inside set = near-black; escaped = Imprint sequential (green → blue)\ncolorscale = [[0.000, INSIDE_COLOR], [0.019, INSIDE_COLOR], [0.020, \"#009E73\"], [1.000, \"#4467A3\"]]\n\n# Plot\ntitle = \"heatmap-mandelbrot · python · plotly · anyplot.ai\"\ntitle_fontsize = round(16 * 67 / len(title)) if len(title) > 67 else 16\n\nfig = go.Figure(\n    go.Heatmap(\n        z=z_data,\n        x=real,\n        y=imag,\n        colorscale=colorscale,\n        showscale=True,\n        zmin=0.0,\n        zmax=1.0,\n        hovertemplate=\"Re: %{x:.3f}<br>Im: %{y:.3f}<extra></extra>\",\n        colorbar=dict(\n            thickness=12,\n            len=0.85,\n            title=dict(text=\"Escape count\", side=\"right\", font=dict(size=10, color=INK_SOFT)),\n            tickfont=dict(size=9, color=INK_SOFT),\n            bgcolor=PAGE_BG,\n            outlinecolor=INK_SOFT,\n            outlinewidth=1,\n            tickvals=[0.0, 0.5, 1.0],\n            ticktext=[\"Interior\", \"Mid\", \"Boundary\"],\n        ),\n    )\n)\n\nfig.update_layout(\n    autosize=False,\n    paper_bgcolor=PAGE_BG,\n    plot_bgcolor=PAGE_BG,\n    margin=dict(l=80, r=90, t=80, b=70),\n    title=dict(text=title, font=dict(size=title_fontsize, color=INK), x=0.5, xanchor=\"center\"),\n    xaxis=dict(\n        title=dict(text=\"Real Axis\", font=dict(size=12, color=INK)),\n        tickfont=dict(size=10, color=INK_SOFT),\n        gridcolor=GRID,\n        linecolor=INK_SOFT,\n        zerolinecolor=INK_SOFT,\n        zerolinewidth=1,\n    ),\n    yaxis=dict(\n        title=dict(text=\"Imaginary Axis\", font=dict(size=12, color=INK)),\n        tickfont=dict(size=10, color=INK_SOFT),\n        gridcolor=GRID,\n        linecolor=INK_SOFT,\n        zerolinecolor=INK_SOFT,\n        zerolinewidth=1,\n    ),\n    annotations=[\n        dict(\n            x=-1.25,\n            y=0.0,\n            text=\"Period-2 bulb\",\n            showarrow=True,\n            arrowhead=2,\n            arrowsize=1,\n            arrowwidth=1.5,\n            arrowcolor=INK_MUTED,\n            font=dict(size=10, color=INK_MUTED),\n            ax=55,\n            ay=-45,\n            xanchor=\"left\",\n        ),\n        dict(\n            x=-0.15,\n            y=0.65,\n            text=\"Main cardioid\",\n            showarrow=True,\n            arrowhead=2,\n            arrowsize=1,\n            arrowwidth=1.5,\n            arrowcolor=INK_MUTED,\n            font=dict(size=10, color=INK_MUTED),\n            ax=60,\n            ay=-40,\n            xanchor=\"left\",\n        ),\n    ],\n)\n\n# Save — square canvas: 2400×2400 via width=600, height=600, scale=4\nfig.write_image(f\"plot-{THEME}.png\", width=600, height=600, scale=4)\nfig.write_html(f\"plot-{THEME}.html\", include_plotlyjs=\"cdn\")\n"}