{"spec_id":"heatmap-stripes-climate","library":"matplotlib","language":"python","code":"\"\"\" anyplot.ai\nheatmap-stripes-climate: Climate Warming Stripes\nLibrary: matplotlib 3.10.9 | Python 3.13.13\nQuality: 92/100 | Updated: 2026-06-02\n\"\"\"\n\nimport os\n\nimport matplotlib.patheffects as pe\nimport matplotlib.pyplot as plt\nimport numpy as np\nfrom matplotlib.colors import LinearSegmentedColormap, TwoSlopeNorm\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# Data - synthetic global temperature anomalies (1850-2024) relative to 1961-1990 baseline\nnp.random.seed(42)\nyears = np.arange(1850, 2025)\nn_years = len(years)\n\nbase_trend = np.piecewise(\n    years.astype(float),\n    [years < 1910, (years >= 1910) & (years < 1945), (years >= 1945) & (years < 1975), years >= 1975],\n    [\n        lambda y: -0.3 + (y - 1850) * 0.002,\n        lambda y: -0.2 + (y - 1910) * 0.008,\n        lambda y: 0.0 + (y - 1945) * 0.001,\n        lambda y: 0.03 + (y - 1975) * 0.02,\n    ],\n)\nnoise = np.random.normal(0, 0.08, n_years)\nanomalies = base_trend + noise\n\n# Imprint diverging colormap: blue (cold) -> warm-neutral -> red (warm)\n# Lighter dark midpoint (#5C5852) preserves visual separation from near-black background\nmidpoint = \"#D4CFC6\" if THEME == \"light\" else \"#5C5852\"\nimprint_div_r = LinearSegmentedColormap.from_list(\"imprint_div_r\", [\"#4467A3\", midpoint, \"#AE3030\"])\n\nvmax = max(abs(anomalies.min()), abs(anomalies.max()))\nnorm = TwoSlopeNorm(vmin=-vmax, vcenter=0, vmax=vmax)\n\n# Plot - landscape 3200x1800 canvas (figsize=(8, 4.5) at dpi=400)\nfig, ax = plt.subplots(figsize=(8, 4.5), dpi=400, facecolor=PAGE_BG)\nax.set_facecolor(PAGE_BG)\n\n# Stripes panel: ~3:1 aspect ratio, raised to leave room below for colorbar scale\nax.set_position([0.02, 0.22, 0.96, 0.57])\n\nstripe_data = anomalies.reshape(1, -1)\nimg = ax.imshow(\n    stripe_data,\n    aspect=\"auto\",\n    cmap=imprint_div_r,\n    norm=norm,\n    extent=[years[0] - 0.5, years[-1] + 0.5, 0, 1],\n    interpolation=\"nearest\",\n)\n\n# Minimal style: no axes, labels, ticks, or gridlines per spec\nax.axis(\"off\")\n\n# Title via ax.set_title — standard positioning contract, sits just above stripe panel\ntitle_str = \"heatmap-stripes-climate · python · matplotlib · anyplot.ai\"\ntitle_obj = ax.set_title(title_str, fontsize=12, fontweight=\"medium\", color=INK, pad=10)\ntitle_obj.set_path_effects([pe.withStroke(linewidth=3, foreground=PAGE_BG)])\n\n# Temperature anomaly scale — thin horizontal colorbar beneath the stripes\ncax = fig.add_axes([0.10, 0.10, 0.80, 0.045])\ncbar = fig.colorbar(img, cax=cax, orientation=\"horizontal\")\ncbar.set_ticks([-vmax, 0.0, vmax])\ncbar.set_ticklabels([f\"−{vmax:.1f}°C\", \"0\", f\"+{vmax:.1f}°C\"])\ncbar.ax.tick_params(labelsize=7, colors=INK_SOFT, length=2, width=0.5)\ncbar.outline.set_edgecolor(INK_SOFT)\ncbar.outline.set_linewidth(0.5)\n\n# Save\nplt.savefig(f\"plot-{THEME}.png\", dpi=400, facecolor=PAGE_BG)\n"}