{"spec_id":"area-mountain-panorama","library":"plotnine","language":"python","code":"\"\"\" anyplot.ai\narea-mountain-panorama: Mountain Panorama Profile with Labeled Peaks\nLibrary: plotnine 0.15.7 | Python 3.13.14\nQuality: 87/100 | Updated: 2026-06-30\n\"\"\"\n\nimport os\n\nimport numpy as np\nimport pandas as pd\nfrom plotnine import (\n    aes,\n    coord_cartesian,\n    element_blank,\n    element_line,\n    element_rect,\n    element_text,\n    geom_line,\n    geom_point,\n    geom_ribbon,\n    geom_segment,\n    geom_text,\n    ggplot,\n    labs,\n    scale_x_continuous,\n    scale_y_continuous,\n    theme,\n    theme_minimal,\n)\n\n\n# Imprint palette / theme-adaptive chrome tokens\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\"\nINK_MUTED = \"#6B6A63\" if THEME == \"light\" else \"#A8A79F\"\nBRAND = \"#009E73\"  # Imprint palette position 1 — peak markers (data elements)\nMOUNTAIN = \"#263040\"  # Dark slate — spec requires dark solid fill for dusk/photo-like feel\n\n# Wallis (Valais) panorama from Gornergrat vantage\npeaks = (\n    pd.DataFrame(\n        {\n            \"name\": [\n                \"Weisshorn\",\n                \"Zinalrothorn\",\n                \"Ober Gabelhorn\",\n                \"Dent Blanche\",\n                \"Matterhorn\",\n                \"Liskamm\",\n                \"Castor\",\n                \"Pollux\",\n                \"Breithorn\",\n                \"Monte Rosa\",\n                \"Strahlhorn\",\n                \"Rimpfischhorn\",\n                \"Allalinhorn\",\n                \"Alphubel\",\n                \"Täschhorn\",\n                \"Dom\",\n            ],\n            \"angle_deg\": [4, 12, 19, 26, 38, 60, 67, 72, 78, 90, 105, 113, 122, 130, 137, 144],\n            \"elevation_m\": [\n                4506,\n                4221,\n                4063,\n                4358,\n                4478,\n                4527,\n                4223,\n                4092,\n                4164,\n                4634,\n                4190,\n                4199,\n                4027,\n                4206,\n                4491,\n                4545,\n            ],\n        }\n    )\n    .sort_values(\"angle_deg\")\n    .reset_index(drop=True)\n)\n\nFLOOR = 2500\n\n# Piecewise-linear tent/triangle functions — spec forbids Gaussian bumps;\n# each peak contributes a sharp triangular profile with asymmetric linear flanks\nnp.random.seed(42)\nn_samples = 1600\nangles = np.linspace(-3, 152, n_samples)\n\n# Undulating base ridge (valley floors and connecting ridges between peaks)\nbase_ridge = 2750 + 80 * np.sin(angles / 14) + 55 * np.sin(angles / 4.5 + 0.7)\nelevation = base_ridge.copy()\n\nfor _, p in peaks.iterrows():\n    # Per-peak seed for reproducible asymmetric flank widths independent of iteration order\n    rng = np.random.RandomState(int(p[\"angle_deg\"] * 17 + 3))\n    left_w = rng.uniform(6, 14)  # degrees from apex to left base\n    right_w = rng.uniform(5, 11)  # degrees from apex to right base (asymmetric)\n    peak_h = p[\"elevation_m\"] - FLOOR\n\n    dist = angles - p[\"angle_deg\"]\n    tent = np.where(\n        dist < 0,\n        np.maximum(0.0, 1.0 + dist / left_w),  # linear rise on left flank\n        np.maximum(0.0, 1.0 - dist / right_w),  # linear fall on right flank\n    )\n    elevation = np.maximum(elevation, FLOOR + peak_h * tent)\n\n# Window=3 only: preserves rocky jaggedness while removing single-point spikes\nridge_noise = np.random.normal(0, 28, n_samples)\nelevation = elevation + ridge_noise\nelevation = pd.Series(elevation).rolling(window=3, center=True, min_periods=1).mean().values\nelevation = np.maximum(elevation, FLOOR)\n\nskyline = pd.DataFrame({\"angle_deg\": angles, \"elevation_m\": elevation, \"y_floor\": FLOOR})\n\n# 3-row stagger — 3 vertical tiers break up the dense 0–78° cluster\nrow_map = {\n    \"Weisshorn\": 0,\n    \"Zinalrothorn\": 1,\n    \"Ober Gabelhorn\": 2,\n    \"Dent Blanche\": 0,\n    \"Matterhorn\": 1,\n    \"Liskamm\": 0,\n    \"Castor\": 2,\n    \"Pollux\": 1,\n    \"Breithorn\": 0,\n    \"Monte Rosa\": 2,\n    \"Strahlhorn\": 1,\n    \"Rimpfischhorn\": 0,\n    \"Allalinhorn\": 2,\n    \"Alphubel\": 1,\n    \"Täschhorn\": 0,\n    \"Dom\": 2,\n}\nrow_y = {0: 5050, 1: 5250, 2: 5450}\npeaks[\"row\"] = peaks[\"name\"].map(row_map)\npeaks[\"label_y\"] = peaks[\"row\"].map(row_y)\npeaks[\"leader_top\"] = peaks[\"label_y\"] - 80\npeaks[\"label\"] = peaks.apply(lambda r: f\"{r['name']}\\n{int(r['elevation_m']):,} m\", axis=1)\npeaks[\"is_anchor\"] = peaks[\"name\"] == \"Matterhorn\"\n\nothers = peaks[~peaks[\"is_anchor\"]]\nanchor = peaks[peaks[\"is_anchor\"]]\n\nplot = (\n    ggplot()\n    # Dark silhouette fill — photo-like, evening/dusk alpine feel\n    + geom_ribbon(aes(x=\"angle_deg\", ymin=\"y_floor\", ymax=\"elevation_m\"), data=skyline, fill=MOUNTAIN, alpha=1.0)\n    # Ridgeline outline for crispness at the sky-mountain boundary\n    + geom_line(aes(x=\"angle_deg\", y=\"elevation_m\"), data=skyline, color=INK_SOFT, size=0.4, alpha=0.35)\n    # Leader lines from summit up to label tier\n    + geom_segment(\n        aes(x=\"angle_deg\", xend=\"angle_deg\", y=\"elevation_m\", yend=\"leader_top\"),\n        data=others,\n        color=INK_MUTED,\n        size=0.35,\n    )\n    + geom_segment(\n        aes(x=\"angle_deg\", xend=\"angle_deg\", y=\"elevation_m\", yend=\"leader_top\"), data=anchor, color=INK, size=0.65\n    )\n    # Summit markers — brand green data elements marking each labeled peak\n    + geom_point(\n        aes(x=\"angle_deg\", y=\"elevation_m\"), data=others, size=2.0, color=PAGE_BG, fill=BRAND, stroke=0.5, shape=\"o\"\n    )\n    + geom_point(\n        aes(x=\"angle_deg\", y=\"elevation_m\"), data=anchor, size=3.2, color=PAGE_BG, fill=BRAND, stroke=0.9, shape=\"o\"\n    )\n    # Peak labels — Matterhorn bold as focal summit\n    + geom_text(\n        aes(x=\"angle_deg\", y=\"label_y\", label=\"label\"), data=others, size=3.0, color=INK, ha=\"center\", va=\"bottom\"\n    )\n    + geom_text(\n        aes(x=\"angle_deg\", y=\"label_y\", label=\"label\"),\n        data=anchor,\n        size=3.8,\n        color=INK,\n        ha=\"center\",\n        va=\"bottom\",\n        fontweight=\"bold\",\n    )\n    + scale_x_continuous(expand=(0.005, 0))\n    + scale_y_continuous(\n        breaks=[2500, 3000, 3500, 4000, 4500, 5000], labels=[\"2,500\", \"3,000\", \"3,500\", \"4,000\", \"4,500\", \"5,000\"]\n    )\n    + coord_cartesian(xlim=(-2, 151), ylim=(2500, 5700))\n    + labs(\n        x=\"\",\n        y=\"Elevation (m)\",\n        title=\"Wallis from Gornergrat · area-mountain-panorama · python · plotnine · anyplot.ai\",\n    )\n    + theme_minimal()\n    + theme(\n        figure_size=(8, 4.5),\n        text=element_text(size=7, color=INK_SOFT),\n        plot_title=element_text(size=11, color=INK, ha=\"left\", margin={\"b\": 8}),\n        axis_title_y=element_text(size=10, color=INK, margin={\"r\": 8}),\n        axis_text_y=element_text(size=8, color=INK_SOFT),\n        axis_text_x=element_blank(),\n        axis_ticks=element_blank(),\n        axis_line=element_blank(),\n        panel_grid_major_x=element_blank(),\n        panel_grid_major_y=element_line(color=INK_SOFT, size=0.25, alpha=0.12),\n        panel_grid_minor=element_blank(),\n        panel_border=element_blank(),\n        plot_background=element_rect(fill=PAGE_BG, color=PAGE_BG),\n        panel_background=element_rect(fill=PAGE_BG, color=PAGE_BG),\n        plot_margin=0.03,\n    )\n)\n\nplot.save(f\"plot-{THEME}.png\", dpi=400, width=8, height=4.5, units=\"in\", verbose=False)\n"}