{"spec_id":"radar-basic","library":"plotly","language":"python","code":"\"\"\" anyplot.ai\nradar-basic: Basic Radar Chart\nLibrary: plotly 6.9.0 | Python 3.13.14\nQuality: 92/100 | Updated: 2026-07-24\n\"\"\"\n\nimport os\n\nimport plotly.graph_objects as go\n\n\nTHEME = os.getenv(\"ANYPLOT_THEME\", \"light\")\n\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 categorical palette — first series always brand green\nIMPRINT = [\"#009E73\", \"#C475FD\", \"#4467A3\", \"#BD8233\", \"#AE3030\", \"#2ABCCD\", \"#954477\"]\n\n# Derive translucent fill colors from the Imprint hexes (no hardcoded rgba)\nr0, g0, b0 = bytes.fromhex(IMPRINT[0][1:])\nr1, g1, b1 = bytes.fromhex(IMPRINT[1][1:])\nFILL_SENIOR = f\"rgba({r0}, {g0}, {b0}, 0.25)\"\nFILL_JUNIOR = f\"rgba({r1}, {g1}, {b1}, 0.25)\"\n\n# Data - Employee performance comparison across competencies\ncategories = [\"Communication\", \"Technical Skills\", \"Teamwork\", \"Problem Solving\", \"Leadership\", \"Creativity\"]\n\nsenior_values = [85, 92, 78, 88, 72, 80]\njunior_values = [70, 65, 82, 68, 55, 75]\n\n# Close the polygon by repeating the first point\ncategories_closed = categories + [categories[0]]\nsenior_closed = senior_values + [senior_values[0]]\njunior_closed = junior_values + [junior_values[0]]\n\nfig = go.Figure()\n\nfig.add_trace(\n    go.Scatterpolar(\n        r=senior_closed,\n        theta=categories_closed,\n        fill=\"toself\",\n        fillcolor=FILL_SENIOR,\n        line={\"color\": IMPRINT[0], \"width\": 3.5},\n        marker={\"size\": 11, \"color\": IMPRINT[0]},\n        name=\"Senior Developer\",\n        hovertemplate=\"<b>Senior Developer</b><br>%{theta}: %{r}<extra></extra>\",\n    )\n)\n\nfig.add_trace(\n    go.Scatterpolar(\n        r=junior_closed,\n        theta=categories_closed,\n        fill=\"toself\",\n        fillcolor=FILL_JUNIOR,\n        line={\"color\": IMPRINT[1], \"width\": 2.5},\n        marker={\"size\": 11, \"color\": IMPRINT[1], \"line\": {\"width\": 1, \"color\": INK}},\n        name=\"Junior Developer\",\n        hovertemplate=\"<b>Junior Developer</b><br>%{theta}: %{r}<extra></extra>\",\n    )\n)\n\n# Distinctive plotly-native callout: a starred point + inline text label, placed\n# directly in polar coordinates (no paper-space annotation math needed) to draw\n# the eye to the one axis where Junior overtakes Senior.\nfig.add_trace(\n    go.Scatterpolar(\n        r=[junior_values[2]],\n        theta=[categories[2]],\n        mode=\"markers+text\",\n        marker={\"size\": 20, \"symbol\": \"star\", \"color\": IMPRINT[1], \"line\": {\"width\": 1.5, \"color\": INK}},\n        text=[\"Junior leads\"],\n        textposition=\"middle left\",\n        textfont={\"size\": 13, \"color\": INK},\n        showlegend=False,\n        hoverinfo=\"skip\",\n    )\n)\n\nfig.update_layout(\n    autosize=False,\n    width=600,\n    height=600,\n    title={\n        \"text\": \"radar-basic · python · plotly · anyplot.ai\",\n        \"font\": {\"size\": 20, \"color\": INK},\n        \"x\": 0.5,\n        \"xanchor\": \"center\",\n    },\n    polar={\n        \"bgcolor\": PAGE_BG,\n        \"domain\": {\"x\": [0.08, 0.92], \"y\": [0.12, 0.88]},\n        \"radialaxis\": {\n            \"visible\": True,\n            \"range\": [0, 100],\n            \"tickvals\": [20, 40, 60, 80, 100],\n            \"tickfont\": {\"size\": 13, \"color\": INK_SOFT},\n            \"gridcolor\": GRID,\n            \"linecolor\": INK_SOFT,\n            # Offset into the gap between the \"Technical Skills\" and \"Teamwork\"\n            # spokes so the tick values don't collide with any axis label.\n            \"angle\": 0,\n        },\n        \"angularaxis\": {\n            \"rotation\": 90,\n            \"direction\": \"clockwise\",\n            \"tickfont\": {\"size\": 16, \"color\": INK},\n            \"gridcolor\": GRID,\n            \"linecolor\": INK_SOFT,\n        },\n    },\n    paper_bgcolor=PAGE_BG,\n    font={\"color\": INK},\n    showlegend=True,\n    legend={\n        \"orientation\": \"h\",\n        \"font\": {\"size\": 13, \"color\": INK_SOFT},\n        \"bgcolor\": ELEVATED_BG,\n        \"bordercolor\": INK_SOFT,\n        \"borderwidth\": 1,\n        \"x\": 0.5,\n        \"y\": 0.02,\n        \"xanchor\": \"center\",\n        \"yanchor\": \"top\",\n    },\n    margin={\"l\": 70, \"r\": 70, \"t\": 90, \"b\": 70},\n)\n\n# Square format — ideal for symmetric polar charts. Canonical 2400×2400 px.\nfig.write_image(f\"plot-{THEME}.png\", width=600, height=600, scale=4)\nfig.write_html(f\"plot-{THEME}.html\", include_plotlyjs=\"cdn\")\n"}