{"spec_id":"polar-basic","library":"plotly","language":"python","code":"\"\"\" anyplot.ai\npolar-basic: Basic Polar Chart\nLibrary: plotly 6.9.0 | Python 3.13.14\nQuality: 88/100 | Updated: 2026-07-24\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\"\nGRID = \"rgba(26,26,23,0.15)\" if THEME == \"light\" else \"rgba(240,239,232,0.15)\"\n\n# Imprint categorical palette — canonical order, abstract speed bins\nIMPRINT_PALETTE = [\"#009E73\", \"#C475FD\", \"#4467A3\", \"#BD8233\"]\n\n# Data - Wind rose: observed wind direction & speed at a coastal weather station\nnp.random.seed(42)\nn_obs = 2000\ncompass_dirs = [\"N\", \"NNE\", \"NE\", \"ENE\", \"E\", \"ESE\", \"SE\", \"SSE\", \"S\", \"SSW\", \"SW\", \"WSW\", \"W\", \"WNW\", \"NW\", \"NNW\"]\nprevailing_deg = 247.5  # WSW is the prevailing direction at this station\n\ndirection_rad = np.random.vonmises(np.radians(prevailing_deg), kappa=2.0, size=n_obs)\ndirection_deg = np.degrees(direction_rad) % 360\ndir_idx = ((direction_deg + 11.25) // 22.5).astype(int) % 16\n\nalignment = np.clip(np.cos(direction_rad - np.radians(prevailing_deg)), 0, 1)\nspeed = np.random.gamma(shape=2.2, scale=6.0, size=n_obs) * (0.6 + 0.6 * alignment)\n\nspeed_bins = [\"0-10 km/h\", \"10-20 km/h\", \"20-30 km/h\", \"30+ km/h\"]\nspeed_bin_idx = np.clip(np.digitize(speed, [10, 20, 30]), 0, 3)\n\ncounts = np.zeros((16, 4))\nnp.add.at(counts, (dir_idx, speed_bin_idx), 1)\nfreq_pct = counts / n_obs * 100\n\n# Radial ticks: fold the \"Frequency\" axis label into the outermost tick text\n# instead of a separate rotated title, so it never overlaps the tick values.\nradial_max = int(np.ceil(freq_pct.sum(axis=1).max() / 5) * 5)\nradial_tickvals = list(range(0, radial_max + 5, 5))\nradial_ticktext = [f\"{v}%\" for v in radial_tickvals]\nradial_ticktext[-1] = f\"Frequency {radial_ticktext[-1]}\"\n\n# Plot\nfig = go.Figure()\n\nfor j, (label, color) in enumerate(zip(speed_bins, IMPRINT_PALETTE, strict=True)):\n    fig.add_trace(\n        go.Barpolar(\n            r=freq_pct[:, j],\n            theta=compass_dirs,\n            name=label,\n            marker={\"color\": color, \"line\": {\"color\": PAGE_BG, \"width\": 1}},\n            hovertemplate=f\"<b>%{{theta}}</b><br>{label}: %{{r:.1f}}%<extra></extra>\",\n        )\n    )\n\nfig.update_layout(\n    autosize=False,\n    barmode=\"stack\",\n    title={\n        \"text\": \"polar-basic · python · plotly · anyplot.ai\",\n        \"font\": {\"size\": 16, \"color\": INK},\n        \"x\": 0.5,\n        \"xanchor\": \"center\",\n    },\n    polar={\n        \"bgcolor\": PAGE_BG,\n        \"radialaxis\": {\n            \"visible\": True,\n            \"tickmode\": \"array\",\n            \"tickvals\": radial_tickvals,\n            \"ticktext\": radial_ticktext,\n            \"tickfont\": {\"size\": 10, \"color\": INK_SOFT},\n            \"gridcolor\": GRID,\n            \"gridwidth\": 0.5,\n            \"linecolor\": INK_SOFT,\n            \"linewidth\": 1,\n            \"angle\": 56.25,\n        },\n        \"angularaxis\": {\n            \"categoryarray\": compass_dirs,\n            \"categoryorder\": \"array\",\n            \"direction\": \"clockwise\",\n            \"rotation\": 90,\n            \"tickfont\": {\"size\": 10, \"color\": INK_SOFT},\n            \"gridcolor\": GRID,\n            \"gridwidth\": 0.5,\n            \"linecolor\": INK_SOFT,\n            \"linewidth\": 0.75,\n        },\n    },\n    legend={\n        \"title\": {\"text\": \"Wind speed\", \"font\": {\"size\": 10, \"color\": INK_SOFT}},\n        \"font\": {\"size\": 10, \"color\": INK_SOFT},\n        \"bgcolor\": ELEVATED_BG,\n        \"bordercolor\": INK_SOFT,\n        \"borderwidth\": 1,\n        \"orientation\": \"h\",\n        \"x\": 0.5,\n        \"xanchor\": \"center\",\n        \"y\": -0.08,\n    },\n    paper_bgcolor=PAGE_BG,\n    font={\"color\": INK},\n    margin={\"l\": 60, \"r\": 60, \"t\": 90, \"b\": 90},\n)\n\n# Save\nfig.write_image(f\"plot-{THEME}.png\", width=600, height=600, scale=4)\nfig.write_html(f\"plot-{THEME}.html\", include_plotlyjs=\"cdn\")\n"}