{"spec_id":"heatmap-stripes-climate","library":"seaborn","language":"python","code":"\"\"\" anyplot.ai\nheatmap-stripes-climate: Climate Warming Stripes\nLibrary: seaborn 0.13.2 | Python 3.13.13\nQuality: 92/100 | Updated: 2026-06-02\n\"\"\"\n\nimport os\n\nimport matplotlib.pyplot as plt\nimport numpy as np\nimport seaborn as sns\nfrom matplotlib.colors import LinearSegmentedColormap\n\n\n# Theme 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\"\n\n# Imprint diverging colormap — blue=cold, red=warm (reversed imprint_div for semantic clarity)\n# Use INK_MUTED (#A8A79F) as dark midpoint so near-zero stripes stay visible against dark bg\nmidpoint = \"#FAF8F1\" if THEME == \"light\" else \"#A8A79F\"\nimprint_div = LinearSegmentedColormap.from_list(\"imprint_div\", [\"#4467A3\", midpoint, \"#AE3030\"])\n\n# Data\nnp.random.seed(42)\nyears = np.arange(1850, 2025)\nn_years = len(years)\n\nbaseline_trend = np.concatenate(\n    [\n        np.linspace(-0.3, -0.2, 60),\n        np.linspace(-0.2, -0.1, 40),\n        np.linspace(-0.1, 0.1, 30),\n        np.linspace(0.1, 0.5, 25),\n        np.linspace(0.5, 1.3, 20),\n    ]\n)\nnoise = np.random.normal(0, 0.12, n_years)\nanomalies = baseline_trend + noise\nanomaly_matrix = anomalies.reshape(1, -1)\n\n# Plot — landscape 3200×1800 px (stripes need wide format per spec)\nfig, ax = plt.subplots(figsize=(8, 4.5), dpi=400, facecolor=PAGE_BG)\nax.set_facecolor(PAGE_BG)\n\nvmax = max(abs(anomalies.min()), abs(anomalies.max()))\n\nsns.heatmap(\n    anomaly_matrix,\n    ax=ax,\n    cmap=imprint_div,\n    center=0,\n    vmin=-vmax,\n    vmax=vmax,\n    cbar=False,\n    xticklabels=False,\n    yticklabels=False,\n    square=False,\n    linewidths=0,\n    linecolor=\"none\",\n)\n\n# Style — pure stripe visualization: no axes, no labels, no gridlines per spec\nax.set_axis_off()\n# 3:1 aspect ratio per spec: 0.98×3200=3136 px wide, 0.60×1800=1080 px tall → 2.9:1\nax.set_position([0.01, 0.15, 0.98, 0.60])\n\n# Title\ntitle = \"heatmap-stripes-climate · python · seaborn · anyplot.ai\"\nn = len(title)\nratio = 67 / n if n > 67 else 1.0\ntitle_fontsize = max(round(12 * ratio), 8)\nfig.text(0.5, 0.88, title, ha=\"center\", va=\"center\", fontsize=title_fontsize, fontweight=\"medium\", color=INK)\n\n# Year markers — larger for readability, anchored below the stripe band\nfig.text(0.015, 0.07, str(years[0]), fontsize=10, color=INK_SOFT, ha=\"left\")\nfig.text(0.985, 0.07, str(years[-1]), fontsize=10, color=INK_SOFT, ha=\"right\")\n\n# Save — no bbox_inches='tight' to preserve exact 3200×1800 canvas\nplt.savefig(f\"plot-{THEME}.png\", dpi=400, facecolor=PAGE_BG)\n"}