{"spec_id":"heatmap-calendar","library":"seaborn","language":"python","code":"\"\"\" anyplot.ai\nheatmap-calendar: Basic Calendar Heatmap\nLibrary: seaborn 0.13.2 | Python 3.13.14\nQuality: 88/100 | Updated: 2026-07-23\n\"\"\"\n\nimport os\n\nimport matplotlib.pyplot as plt\nimport numpy as np\nimport pandas as pd\nimport seaborn as sns\nfrom matplotlib.colors import LinearSegmentedColormap\n\n\n# Theme-adaptive chrome tokens (Imprint)\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\"\nINK_MUTED = \"#6B6A63\" if THEME == \"light\" else \"#A8A79F\"\n\nsns.set_theme(\n    style=\"ticks\",\n    rc={\n        \"figure.facecolor\": PAGE_BG,\n        \"axes.facecolor\": PAGE_BG,\n        \"axes.edgecolor\": INK_SOFT,\n        \"axes.labelcolor\": INK,\n        \"text.color\": INK,\n        \"xtick.color\": INK_SOFT,\n        \"ytick.color\": INK_SOFT,\n        \"grid.color\": INK,\n        \"grid.alpha\": 0.15,\n        \"legend.facecolor\": ELEVATED_BG,\n        \"legend.edgecolor\": INK_SOFT,\n    },\n)\n\n# Imprint sequential colormap (single-polarity contribution counts): brand green -> blue\nimprint_seq = LinearSegmentedColormap.from_list(\"imprint_seq\", [\"#009E73\", \"#4467A3\"])\n\n# Data - one year of daily activity (simulating GitHub-style contributions)\nnp.random.seed(42)\nstart_date = pd.Timestamp(\"2024-01-01\")\nend_date = pd.Timestamp(\"2024-12-31\")\ndates = pd.date_range(start=start_date, end=end_date, freq=\"D\")\n\n# Simulate daily activity with realistic patterns\n# Higher activity on weekdays, lower on weekends, with some variation\nbase_activity = np.random.exponential(scale=3, size=len(dates))\nweekday_boost = np.where(dates.weekday < 5, 1.5, 0.6)  # Weekdays higher\nactivity = (base_activity * weekday_boost).astype(int)\n# Add some zero days and cap max\nactivity = np.clip(activity, 0, 15)\n# Add more zeros for realism\nzero_mask = np.random.random(len(dates)) < 0.15\nactivity[zero_mask] = 0\n\ndf = pd.DataFrame({\"date\": dates, \"value\": activity})\n\n# Extract calendar components\ndf[\"weekday\"] = df[\"date\"].dt.weekday  # 0=Monday, 6=Sunday\ndf[\"month\"] = df[\"date\"].dt.month\n\n# Calculate week number as continuous count from start of year\n# This avoids issues with ISO week numbers crossing year boundaries\ndf[\"week_num\"] = ((df[\"date\"] - start_date).dt.days + start_date.weekday()) // 7\n\n# Track the single highest-activity day from the unclipped signal (several\n# days tie at the vmax=15 cap post-clip, so the pre-clip value picks one\n# genuine peak rather than an arbitrary tied cell).\npeak_row = df.loc[base_activity.argmax()]\n\n# Create pivot table for heatmap (weekdays as rows, weeks as columns)\npivot_df = df.pivot(index=\"weekday\", columns=\"week_num\", values=\"value\")\n\n# Explicit mask for missing calendar cells (partial final week) rather than\n# relying on implicit NaN blanking\nmissing_mask = pivot_df.isna()\n\n# Weekday labels (Monday at top)\nweekday_labels = [\"Mon\", \"Tue\", \"Wed\", \"Thu\", \"Fri\", \"Sat\", \"Sun\"]\n\n# Landscape canvas (16:9) -> 3200x1800 px at dpi=400. The 52-week x 7-day grid\n# is inherently wide, so landscape suits this calendar layout better than square.\nfig, ax = plt.subplots(figsize=(8, 4.5), dpi=400)\n\n# Create heatmap with the Imprint sequential colormap; cell borders match the\n# page background so gaps read as \"punched out\" rather than a harsh fixed color.\n# `mask` makes the partial-final-week handling explicit rather than relying on\n# implicit NaN blanking.\nsns.heatmap(\n    pivot_df,\n    ax=ax,\n    mask=missing_mask,\n    cmap=imprint_seq,\n    linewidths=0.8,\n    linecolor=PAGE_BG,\n    cbar_kws={\"label\": \"Daily Contributions\", \"shrink\": 0.7, \"aspect\": 18, \"fraction\": 0.035, \"pad\": 0.015},\n    vmin=0,\n    vmax=15,\n)\n\n# Set weekday labels on y-axis\nax.set_yticks(np.arange(7) + 0.5)\nax.set_yticklabels(weekday_labels, fontsize=8, rotation=0, color=INK_SOFT)\n\n# Create month labels, placed along the top of the grid (per spec)\n# Find first week of each month\nmonth_starts = df.groupby(\"month\")[\"week_num\"].min()\nmonth_labels = [\"Jan\", \"Feb\", \"Mar\", \"Apr\", \"May\", \"Jun\", \"Jul\", \"Aug\", \"Sep\", \"Oct\", \"Nov\", \"Dec\"]\n\nax.xaxis.set_ticks_position(\"top\")\nax.xaxis.set_label_position(\"top\")\nax.set_xticks([month_starts[m] + 0.5 for m in range(1, 13)])\nax.set_xticklabels(month_labels, fontsize=8, color=INK_SOFT)\n\n# Style adjustments\nax.set_xlabel(\"\")\nax.set_ylabel(\"\")\n\n# Reserve headroom above the top-mounted month labels so the title doesn't clip\nfig.subplots_adjust(top=0.80, bottom=0.06, left=0.08, right=0.96)\nfig.suptitle(\"heatmap-calendar · python · seaborn · anyplot.ai\", fontsize=12, y=0.96, color=INK)\nfig.text(\n    0.5,\n    0.885,\n    f\"Peak day: {peak_row['date']:%b %-d} · {int(peak_row['value'])} contributions\",\n    fontsize=9,\n    color=INK_SOFT,\n    ha=\"center\",\n)\n\n# Adjust colorbar chrome to match theme\ncbar = ax.collections[0].colorbar\ncbar.ax.tick_params(labelsize=8, color=INK_SOFT, labelcolor=INK_SOFT)\ncbar.ax.set_ylabel(\"Daily Contributions\", fontsize=10, color=INK)\ncbar.outline.set_edgecolor(INK_SOFT)\n\n# Remove tick marks (keep tick labels) for a clean grid look\nax.tick_params(top=False, bottom=False, left=False, right=False)\n\n# Ring out the single highest-activity day (the data-storytelling callout\n# above) directly on the grid\npeak_x = peak_row[\"week_num\"] + 0.5\npeak_y = peak_row[\"weekday\"] + 0.5\nax.plot(\n    peak_x, peak_y, marker=\"o\", markersize=9, markerfacecolor=\"none\", markeredgecolor=INK, markeredgewidth=1.4, zorder=5\n)\n\nplt.savefig(f\"plot-{THEME}.png\", dpi=400, facecolor=PAGE_BG)\n"}