{"spec_id":"polar-basic","library":"letsplot","language":"python","code":"\"\"\" anyplot.ai\npolar-basic: Basic Polar Chart\nLibrary: letsplot 4.11.0 | Python 3.13.14\nQuality: 89/100 | Updated: 2026-07-24\n\"\"\"\n\nimport math\nimport os\n\nimport numpy as np\nimport pandas as pd\nfrom lets_plot import (\n    LetsPlot,\n    aes,\n    coord_polar,\n    element_blank,\n    element_line,\n    element_rect,\n    element_text,\n    geom_path,\n    geom_point,\n    geom_polygon,\n    geom_text,\n    ggplot,\n    ggsize,\n    labs,\n    layer_tooltips,\n    position_nudge,\n    scale_x_continuous,\n    scale_y_continuous,\n    theme,\n)\nfrom lets_plot.export import ggsave\n\n\nLetsPlot.setup_html()\n\n# Theme tokens (Imprint palette — theme-adaptive chrome)\nTHEME = os.getenv(\"ANYPLOT_THEME\", \"light\")\nPAGE_BG = \"#FAF8F1\" if THEME == \"light\" else \"#1A1A17\"\nINK = \"#1A1A17\" if THEME == \"light\" else \"#F0EFE8\"\nINK_SOFT = \"#4A4A44\" if THEME == \"light\" else \"#B8B7B0\"\nBRAND = \"#009E73\"  # Imprint palette position 1\n\n# Data - hourly temperature readings over a 24-hour diurnal cycle\nnp.random.seed(42)\nhours = np.arange(0, 24)\nbase_temp = 15 + 10 * np.sin((hours - 6) * math.pi / 12)\ntemperatures = base_temp + np.random.randn(24) * 2\n\ndf = pd.DataFrame({\"hour\": hours, \"temperature\": temperatures})\n# Duplicate the first point at hour=24 to close the loop in polar coordinates\ndf_path = pd.concat([df, df.iloc[[0]].assign(hour=24)], ignore_index=True)\n\n# Focal points — call out the diurnal peak and overnight low\npeak = df.loc[df[\"temperature\"].idxmax()]\ntrough = df.loc[df[\"temperature\"].idxmin()]\nhighlights = pd.DataFrame(\n    {\n        \"hour\": [peak[\"hour\"], trough[\"hour\"]],\n        \"temperature\": [peak[\"temperature\"], trough[\"temperature\"]],\n        \"label\": [f\"{peak['temperature']:.0f}°C peak\", f\"{trough['temperature']:.0f}°C low\"],\n    }\n)\npeak_label = highlights.iloc[[0]]\ntrough_label = highlights.iloc[[1]]\n\n# Hour labels at standard 3-hour intervals\nhour_breaks = [0, 3, 6, 9, 12, 15, 18, 21]\nhour_labels = [\"00:00\", \"03:00\", \"06:00\", \"09:00\", \"12:00\", \"15:00\", \"18:00\", \"21:00\"]\n\n# Donut-hole radial scale: the lower limit sits well below the coldest reading so\n# no hour collapses onto the origin where the 8 angular gridlines converge.\nradius_breaks = [5, 10, 15, 20, 25]\nradius_limits = [-8, 29]\n\n# Distinctive lets-plot touch: formatted hover tooltips on each hourly reading\npoint_tooltips = (\n    layer_tooltips()\n    .format(\"@hour\", \"{}:00\")\n    .format(\"@temperature\", \".1f\")\n    .line(\"Hour|@hour\")\n    .line(\"Temperature|@temperature°C\")\n)\n\n# Theme\nanyplot_theme = theme(\n    plot_background=element_rect(fill=PAGE_BG, color=PAGE_BG),\n    panel_background=element_rect(fill=PAGE_BG),\n    panel_grid_major=element_line(color=INK_SOFT, size=0.3),\n    panel_grid_minor=element_blank(),\n    axis_title=element_text(color=INK, size=14),\n    axis_text=element_text(color=INK_SOFT, size=12),\n    axis_ticks=element_blank(),\n    axis_line=element_blank(),\n    plot_title=element_text(color=INK, size=16),\n)\n\n# Plot using coord_polar for an idiomatic lets-plot polar chart\nplot = (\n    ggplot(df_path, aes(x=\"hour\", y=\"temperature\"))\n    + geom_polygon(fill=BRAND, color=BRAND, size=0, alpha=0.15)\n    + geom_path(color=BRAND, size=1.2)\n    + geom_point(data=df, color=BRAND, size=3, tooltips=point_tooltips)\n    + geom_point(data=highlights, color=BRAND, size=5)\n    + geom_text(data=peak_label, mapping=aes(label=\"label\"), color=INK, size=3.5, position=position_nudge(x=-1.6, y=-1))\n    + geom_text(\n        data=trough_label, mapping=aes(label=\"label\"), color=INK, size=3.5, position=position_nudge(x=-1.8, y=9)\n    )\n    + scale_x_continuous(breaks=hour_breaks, labels=hour_labels, limits=[0, 24], expand=[0, 0])\n    + scale_y_continuous(breaks=radius_breaks, limits=radius_limits, expand=[0, 0])\n    + coord_polar(theta=\"x\", start=0, direction=1)\n    + labs(title=\"polar-basic · letsplot · anyplot.ai\", x=\"\", y=\"Temperature (°C)\")\n    + ggsize(600, 600)\n    + anyplot_theme\n)\n\n# Save\nggsave(plot, f\"plot-{THEME}.png\", path=\".\", scale=4)\nggsave(plot, f\"plot-{THEME}.html\", path=\".\")\n"}