{"spec_id":"wireframe-3d-basic","library":"plotly","language":"python","code":"\"\"\" anyplot.ai\nwireframe-3d-basic: Basic 3D Wireframe Plot\nLibrary: plotly 6.9.0 | Python 3.13.14\nQuality: 86/100 | Updated: 2026-08-04\n\"\"\"\n\nimport os\n\nimport numpy as np\nimport plotly.graph_objects as go\n\n\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\"\nGRID = \"rgba(26,26,23,0.10)\" if THEME == \"light\" else \"rgba(240,239,232,0.10)\"\n\n# Imprint diverging colormap - height is a signed deviation around z=0\nimprint_div = [[0.0, \"#AE3030\"], [0.5, PAGE_BG], [1.0, \"#4467A3\"]]\n\n# Data - 24x24 grid with ripple function z = sin(sqrt(x^2 + y^2))\nx = np.linspace(-5, 5, 24)\ny = np.linspace(-5, 5, 24)\nX, Y = np.meshgrid(x, y)\nR = np.sqrt(X**2 + Y**2)\nZ = np.sin(R)\n\nfig = go.Figure()\n\n# Lines along the x-direction (rows), height-mapped via the Imprint diverging scale\nfor i in range(Z.shape[0]):\n    z_values = Z[i, :]\n    fig.add_trace(\n        go.Scatter3d(\n            x=X[i, :],\n            y=Y[i, :],\n            z=z_values,\n            mode=\"lines\",\n            line={\n                \"color\": z_values,\n                \"colorscale\": imprint_div,\n                \"showscale\": False,\n                \"width\": 3.5,\n                \"cmin\": -1,\n                \"cmax\": 1,\n            },\n            showlegend=False,\n            hovertemplate=\"<b>Point</b><br>X: %{x:.2f}<br>Y: %{y:.2f}<br>Z: %{z:.3f}<extra></extra>\",\n        )\n    )\n\n# Lines along the y-direction (columns) - the last one carries the shared colorbar\nfor j in range(Z.shape[1]):\n    z_values = Z[:, j]\n    is_last = j == Z.shape[1] - 1\n    fig.add_trace(\n        go.Scatter3d(\n            x=X[:, j],\n            y=Y[:, j],\n            z=z_values,\n            mode=\"lines\",\n            line={\n                \"color\": z_values,\n                \"colorscale\": imprint_div,\n                \"showscale\": is_last,\n                \"width\": 3.5,\n                \"cmin\": -1,\n                \"cmax\": 1,\n                \"colorbar\": {\n                    \"title\": {\"text\": \"Height\", \"font\": {\"size\": 14, \"color\": INK}},\n                    \"tickfont\": {\"size\": 11, \"color\": INK_SOFT},\n                    \"outlinecolor\": INK_SOFT,\n                    \"outlinewidth\": 1,\n                    \"bgcolor\": ELEVATED_BG,\n                    \"len\": 0.6,\n                    \"thickness\": 18,\n                    \"x\": 0.8,\n                }\n                if is_last\n                else None,\n            },\n            showlegend=False,\n            hovertemplate=\"<b>Point</b><br>X: %{x:.2f}<br>Y: %{y:.2f}<br>Z: %{z:.3f}<extra></extra>\",\n        )\n    )\n\nfig.update_layout(\n    autosize=False,\n    title={\n        \"text\": \"wireframe-3d-basic · python · plotly · anyplot.ai\",\n        \"font\": {\"size\": 16, \"color\": INK},\n        \"x\": 0.5,\n        \"xanchor\": \"center\",\n    },\n    # Short axis titles avoid rotated-label collisions on the mandated canvas;\n    # the formula lives in the annotation below instead of the z-axis title.\n    scene={\n        \"xaxis\": {\n            \"title\": {\"text\": \"Radius (x)\", \"font\": {\"size\": 14, \"color\": INK}},\n            \"tickfont\": {\"size\": 11, \"color\": INK_SOFT},\n            \"gridcolor\": GRID,\n            \"zerolinecolor\": INK_SOFT,\n            \"linecolor\": INK_SOFT,\n            \"backgroundcolor\": PAGE_BG,\n        },\n        \"yaxis\": {\n            \"title\": {\"text\": \"Radius (y)\", \"font\": {\"size\": 14, \"color\": INK}},\n            \"tickfont\": {\"size\": 11, \"color\": INK_SOFT},\n            \"gridcolor\": GRID,\n            \"zerolinecolor\": INK_SOFT,\n            \"linecolor\": INK_SOFT,\n            \"backgroundcolor\": PAGE_BG,\n        },\n        \"zaxis\": {\n            \"title\": {\"text\": \"Height (z)\", \"font\": {\"size\": 14, \"color\": INK}},\n            \"tickfont\": {\"size\": 11, \"color\": INK_SOFT},\n            \"gridcolor\": GRID,\n            \"zerolinecolor\": INK_SOFT,\n            \"linecolor\": INK_SOFT,\n            \"backgroundcolor\": PAGE_BG,\n        },\n        \"camera\": {\n            \"eye\": {\"x\": 1.6, \"y\": 1.6, \"z\": 1.0}  # ~30° elevation, ~45° azimuth\n        },\n        \"aspectmode\": \"cube\",\n        \"domain\": {\"x\": [0.0, 0.78], \"y\": [0.0, 0.94]},\n    },\n    annotations=[\n        {\n            \"text\": \"z = sin(√(x² + y²))\",\n            \"font\": {\"size\": 12, \"color\": INK_SOFT},\n            \"x\": 0.5,\n            \"y\": 0.95,\n            \"xref\": \"paper\",\n            \"yref\": \"paper\",\n            \"showarrow\": False,\n        }\n    ],\n    paper_bgcolor=PAGE_BG,\n    plot_bgcolor=PAGE_BG,\n    margin={\"l\": 20, \"r\": 110, \"t\": 90, \"b\": 30},\n)\n\n# Save PNG (3200x1800) and interactive HTML\nfig.write_image(f\"plot-{THEME}.png\", width=800, height=450, scale=4)\nfig.write_html(f\"plot-{THEME}.html\", include_plotlyjs=\"cdn\")\n"}