{"spec_id":"polar-line","library":"plotnine","language":"python","code":"\"\"\" anyplot.ai\npolar-line: Polar Line Plot\nLibrary: plotnine 0.15.4 | Python 3.13.13\nQuality: 89/100 | Created: 2026-05-12\n\"\"\"\n\nimport os\nimport sys\n\n\n# Remove script directory from sys.path to avoid importing local plotnine.py\nscript_dir = os.path.dirname(os.path.abspath(__file__))\nsys.path = [p for p in sys.path if os.path.abspath(p) != script_dir and os.path.abspath(p) != os.getcwd()]\n\nimport numpy as np\nimport pandas as pd\nfrom plotnine import (\n    aes,\n    element_line,\n    element_rect,\n    element_text,\n    geom_path,\n    geom_point,\n    ggplot,\n    ggsave,\n    labs,\n    scale_color_manual,\n    theme,\n    theme_minimal,\n    xlim,\n    ylim,\n)\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\"\nIMPRINT = [\"#009E73\", \"#C475FD\", \"#4467A3\", \"#BD8233\", \"#AE3030\", \"#2ABCCD\", \"#954477\"]\n\n# Data: Hourly activity patterns for two weeks\nnp.random.seed(42)\n\n# Hours as angles (0-360 degrees = 24 hours)\nhours = np.arange(0, 24)\nhours_deg = hours * 15  # 360 / 24 = 15 degrees per hour\n\n# Week 1: typical activity pattern (higher during day)\nweek1_activity = 40 + 35 * np.sin(np.radians(hours_deg - 90)) + np.random.randn(24) * 3\n\n# Week 2: shifted pattern (busier mornings)\nweek2_activity = 45 + 30 * np.sin(np.radians(hours_deg - 120)) + np.random.randn(24) * 3\n\n# Convert polar to Cartesian coordinates\ntheta_rad_week1 = np.radians(hours_deg)\ntheta_rad_week2 = np.radians(hours_deg)\n\n# Close the loop\nhours_closed = np.append(hours_deg, hours_deg[0])\nweek1_closed = np.append(week1_activity, week1_activity[0])\nweek2_closed = np.append(week2_activity, week2_activity[0])\ntheta_rad_closed = np.append(theta_rad_week1, theta_rad_week1[0])\n\nx_week1 = week1_closed * np.cos(theta_rad_closed)\ny_week1 = week1_closed * np.sin(theta_rad_closed)\nx_week2 = week2_closed * np.cos(theta_rad_closed)\ny_week2 = week2_closed * np.sin(theta_rad_closed)\n\n# Create dataframe\ndf = pd.DataFrame(\n    {\n        \"x\": np.concatenate([x_week1, x_week2]),\n        \"y\": np.concatenate([y_week1, y_week2]),\n        \"week\": [\"Week 1\"] * len(x_week1) + [\"Week 2\"] * len(x_week2),\n        \"order\": list(range(len(x_week1))) + list(range(len(x_week2))),\n    }\n)\n\n# Plot theme\nanyplot_theme = theme(\n    plot_background=element_rect(fill=PAGE_BG, color=PAGE_BG),\n    panel_background=element_rect(fill=PAGE_BG, color=PAGE_BG),\n    panel_grid_major=element_line(color=INK, size=0.2, alpha=0.08),\n    panel_grid_minor=element_line(color=INK, size=0.1, alpha=0.04),\n    axis_title=element_text(size=20, color=INK),\n    axis_text=element_text(size=16, color=INK_SOFT),\n    axis_line=element_line(color=INK_SOFT, size=0.5),\n    plot_title=element_text(size=24, color=INK),\n    legend_background=element_rect(fill=ELEVATED_BG, color=INK_SOFT),\n    legend_text=element_text(size=16, color=INK_SOFT),\n    legend_title=element_text(size=16, color=INK),\n    figure_size=(16, 9),\n)\n\n# Create plot\nplot = (\n    ggplot(df, aes(x=\"x\", y=\"y\", color=\"week\", order=\"order\"))\n    + geom_path(size=1.5, alpha=0.8)\n    + geom_point(size=3.5, alpha=0.7)\n    + scale_color_manual(values=IMPRINT[:2])\n    + xlim(-80, 80)\n    + ylim(-80, 80)\n    + labs(title=\"polar-line · plotnine · anyplot.ai\", x=\"\", y=\"\", color=\"Period\")\n    + theme_minimal()\n    + anyplot_theme\n)\n\n# Save\noutput_path = os.path.join(os.path.dirname(__file__), f\"plot-{THEME}.png\")\nggsave(plot, filename=output_path, dpi=300, width=16, height=9)\n"}