{"spec_id":"map-route-path","library":"plotnine","language":"python","code":"\"\"\" anyplot.ai\nmap-route-path: Route Path Map\nLibrary: plotnine 0.15.4 | Python 3.13.13\nQuality: 87/100 | Updated: 2026-05-21\n\"\"\"\n\nimport os\n\nimport numpy as np\nimport pandas as pd\nfrom plotnine import (\n    aes,\n    coord_fixed,\n    element_blank,\n    element_line,\n    element_rect,\n    element_text,\n    geom_path,\n    geom_point,\n    geom_polygon,\n    ggplot,\n    labs,\n    scale_color_cmap,\n    theme,\n    theme_minimal,\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\"\nPARK_FILL = \"#C8E6C9\" if THEME == \"light\" else \"#1B3A1F\"\nPARK_COLOR = \"#4CAF50\" if THEME == \"light\" else \"#388E3C\"\nLAKE_FILL = \"#81D4FA\" if THEME == \"light\" else \"#0D3B52\"\nLAKE_COLOR = \"#0288D1\" if THEME == \"light\" else \"#01579B\"\n\n# Data\nnp.random.seed(42)\n\nbase_lat = 47.82\nbase_lon = -121.75\nn_points = 200\nt = np.linspace(0, 2 * np.pi, n_points)\n\nradius_lat = 0.08 + 0.02 * np.sin(3 * t)\nradius_lon = 0.12 + 0.03 * np.cos(2 * t)\nnoise_lat = np.random.normal(0, 0.002, n_points)\nnoise_lon = np.random.normal(0, 0.003, n_points)\n\nlat = base_lat + radius_lat * np.sin(t) + noise_lat\nlon = base_lon + radius_lon * np.cos(t) + noise_lon\n\ndf_trail = pd.DataFrame({\"lat\": lat, \"lon\": lon, \"sequence\": range(n_points)})\ndf_trail[\"lat_smooth\"] = df_trail[\"lat\"].rolling(window=3, center=True, min_periods=1).mean()\ndf_trail[\"lon_smooth\"] = df_trail[\"lon\"].rolling(window=3, center=True, min_periods=1).mean()\ndf_trail[\"progress\"] = df_trail[\"sequence\"] / (n_points - 1) * 100\n\nstart_point = df_trail.iloc[[0]].copy()\nend_point = df_trail.iloc[[-1]].copy()\n\npark_boundary_lon = [\n    base_lon - 0.20,\n    base_lon - 0.18,\n    base_lon - 0.10,\n    base_lon + 0.05,\n    base_lon + 0.15,\n    base_lon + 0.18,\n    base_lon + 0.15,\n    base_lon + 0.05,\n    base_lon - 0.08,\n    base_lon - 0.18,\n    base_lon - 0.20,\n]\npark_boundary_lat = [\n    base_lat - 0.05,\n    base_lat + 0.05,\n    base_lat + 0.12,\n    base_lat + 0.14,\n    base_lat + 0.10,\n    base_lat,\n    base_lat - 0.10,\n    base_lat - 0.12,\n    base_lat - 0.10,\n    base_lat - 0.08,\n    base_lat - 0.05,\n]\ndf_park = pd.DataFrame(\n    {\"lon\": park_boundary_lon, \"lat\": park_boundary_lat, \"order\": range(len(park_boundary_lon)), \"area\": \"park\"}\n)\n\nlake_t = np.linspace(0, 2 * np.pi, 20)\nlake_lon = base_lon + 0.03 + 0.025 * np.cos(lake_t)\nlake_lat = base_lat + 0.02 + 0.015 * np.sin(lake_t)\ndf_lake = pd.DataFrame({\"lon\": lake_lon, \"lat\": lake_lat, \"order\": range(len(lake_t)), \"area\": \"lake\"})\n\n# Plot\nplot = (\n    ggplot()\n    + geom_polygon(aes(x=\"lon\", y=\"lat\"), data=df_park, fill=PARK_FILL, color=PARK_COLOR, size=0.5, alpha=0.7)\n    + geom_polygon(aes(x=\"lon\", y=\"lat\"), data=df_lake, fill=LAKE_FILL, color=LAKE_COLOR, size=0.4, alpha=0.8)\n    + geom_path(\n        aes(x=\"lon_smooth\", y=\"lat_smooth\", color=\"progress\"), data=df_trail, size=2.5, alpha=0.85, lineend=\"round\"\n    )\n    + geom_point(\n        aes(x=\"lon_smooth\", y=\"lat_smooth\"),\n        data=start_point,\n        color=\"#2E7D32\",\n        fill=\"#4CAF50\",\n        size=5,\n        shape=\"o\",\n        stroke=1.5,\n    )\n    + geom_point(\n        aes(x=\"lon_smooth\", y=\"lat_smooth\"),\n        data=end_point,\n        color=\"#C62828\",\n        fill=\"#EF5350\",\n        size=5,\n        shape=\"s\",\n        stroke=1.5,\n    )\n    + scale_color_cmap(cmap_name=\"viridis\", name=\"Trail Progress (%)\")\n    + coord_fixed(ratio=1.3)\n    + labs(title=\"map-route-path · python · plotnine · anyplot.ai\", x=\"Longitude (°)\", y=\"Latitude (°)\")\n    + theme_minimal()\n    + theme(\n        figure_size=(8, 4.5),\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, size=0.3, alpha=0.10),\n        panel_grid_minor=element_blank(),\n        panel_border=element_rect(color=INK_SOFT, fill=None),\n        axis_title=element_text(size=10, color=INK),\n        axis_text=element_text(size=8, color=INK_SOFT),\n        axis_line=element_line(color=INK_SOFT),\n        plot_title=element_text(size=12, color=INK),\n        legend_title=element_text(size=8, color=INK),\n        legend_text=element_text(size=8, color=INK_SOFT),\n        legend_background=element_rect(fill=ELEVATED_BG, color=INK_SOFT),\n        legend_position=\"right\",\n    )\n)\n\n# Save\nplot.save(f\"plot-{THEME}.png\", dpi=400, width=8, height=4.5, units=\"in\", verbose=False)\n"}