{"spec_id":"heatmap-calendar","library":"letsplot","language":"python","code":"\"\"\" anyplot.ai\nheatmap-calendar: Basic Calendar Heatmap\nLibrary: letsplot 4.11.0 | Python 3.13.14\nQuality: 89/100 | Updated: 2026-07-23\n\"\"\"\n# ruff: noqa: F405\n\nimport os\nimport shutil\n\nimport numpy as np\nimport pandas as pd\nfrom lets_plot import *\n\n\nLetsPlot.setup_html()\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\"\n\n# Imprint sequential colormap (brand green -> blue) for single-polarity activity counts\nIMPRINT_SEQ_LOW = \"#009E73\"\nIMPRINT_SEQ_HIGH = \"#4467A3\"\n\n# Data - Generate one year of daily activity data\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# Generate realistic activity data (like GitHub contributions), with a mild\n# year-end ramp-up so the \"peak in December\" narrative is genuinely visible\nvalues = []\nfor date in dates:\n    seasonal_factor = 0.35 + 1.3 * (date.month - 1) / 11\n    base = np.random.poisson(5 * seasonal_factor)\n    if date.dayofweek >= 5:\n        base = int(base * 0.4)\n    if np.random.random() < 0.1:\n        base = int(base * 3)\n    if np.random.random() < 0.15:\n        base = 0\n    values.append(base)\n\ndf = pd.DataFrame({\"date\": dates, \"value\": values})\ndf[\"date_str\"] = df[\"date\"].dt.strftime(\"%b %d, %Y\")\ndf[\"weekday\"] = df[\"date\"].dt.dayofweek  # 0=Monday, 6=Sunday\ndf[\"month\"] = df[\"date\"].dt.month\ndf[\"week_of_year\"] = (df[\"date\"] - start_date).dt.days // 7\n\nweekday_labels = [\"Mon\", \"Tue\", \"Wed\", \"Thu\", \"Fri\", \"Sat\", \"Sun\"]\nmonth_names = [\"Jan\", \"Feb\", \"Mar\", \"Apr\", \"May\", \"Jun\", \"Jul\", \"Aug\", \"Sep\", \"Oct\", \"Nov\", \"Dec\"]\nmonth_positions = df.groupby(\"month\")[\"week_of_year\"].min().tolist()\n\npeak_month = month_names[df.groupby(\"month\")[\"value\"].mean().idxmax() - 1]\nweekday_mean = df[df[\"weekday\"] < 5][\"value\"].mean()\nweekend_mean = df[df[\"weekday\"] >= 5][\"value\"].mean()\nweekend_drop_pct = round((1 - weekend_mean / weekday_mean) * 100)\n\n# Plot\nanyplot_theme = theme(\n    plot_background=element_rect(fill=PAGE_BG, color=PAGE_BG),\n    panel_background=element_rect(fill=PAGE_BG),\n    panel_border=element_blank(),\n    panel_grid=element_blank(),\n    axis_ticks=element_blank(),\n    axis_line=element_blank(),\n    plot_title=element_text(color=INK, size=20, hjust=0.5),\n    plot_subtitle=element_text(color=INK_SOFT, size=13, hjust=0.5),\n    axis_title=element_text(color=INK_SOFT, size=13),\n    axis_text_x=element_text(size=12, color=INK_SOFT),\n    axis_text_y=element_text(size=12, color=INK_SOFT),\n    legend_background=element_rect(fill=ELEVATED_BG, color=INK_SOFT),\n    legend_text=element_text(color=INK_SOFT, size=11),\n    legend_title=element_text(color=INK, size=13),\n)\n\nplot = (\n    ggplot(df, aes(x=\"week_of_year\", y=\"weekday\", fill=\"value\"))\n    + geom_tile(\n        tooltips=layer_tooltips().line(\"@date_str\").line(\"Activity: @value\"),\n        color=PAGE_BG,\n        size=0.8,\n        width=0.9,\n        height=0.9,\n    )\n    + scale_fill_gradient(low=IMPRINT_SEQ_LOW, high=IMPRINT_SEQ_HIGH, name=\"Activity\")\n    + scale_y_reverse(breaks=[0, 1, 2, 3, 4, 5, 6], labels=weekday_labels)\n    + scale_x_continuous(breaks=month_positions, labels=month_names)\n    + labs(\n        title=\"heatmap-calendar · python · letsplot · anyplot.ai\",\n        subtitle=f\"Peak activity in {peak_month} · Weekends show ~{weekend_drop_pct}% less activity\",\n        x=\"Month (2024)\",\n        y=\"Day of Week\",\n    )\n    + theme_minimal()\n    + anyplot_theme\n    + ggsize(600, 600)\n)\n\n# Save as PNG and HTML\nggsave(plot, f\"plot-{THEME}.png\", scale=4, path=\".\")\nggsave(plot, f\"plot-{THEME}.html\", path=\".\")\n\n# Clean up lets-plot-images directory if created\nif os.path.exists(\"lets-plot-images\"):\n    shutil.rmtree(\"lets-plot-images\")\n"}