{"spec_id":"gantt-basic","library":"letsplot","language":"python","code":"\"\"\" anyplot.ai\ngantt-basic: Basic Gantt Chart\nLibrary: letsplot 4.9.0 | Python 3.13.13\nQuality: 90/100 | Updated: 2026-05-10\n\"\"\"\n\nimport os\nfrom datetime import datetime\n\nimport pandas as pd\nfrom lets_plot import *\n\n\nLetsPlot.setup_html()\n\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\"\nRULE = \"rgba(26,26,23,0.10)\" if THEME == \"light\" else \"rgba(240,239,232,0.10)\"\n\nIMPRINT = [\"#009E73\", \"#C475FD\", \"#4467A3\", \"#BD8233\", \"#AE3030\", \"#2ABCCD\"]\n\n# Data - Software Development Project\ntasks_data = {\n    \"task\": [\n        \"Requirements Gathering\",\n        \"System Design\",\n        \"UI/UX Design\",\n        \"Backend Development\",\n        \"Frontend Development\",\n        \"Database Setup\",\n        \"API Integration\",\n        \"Unit Testing\",\n        \"Integration Testing\",\n        \"User Acceptance Testing\",\n        \"Documentation\",\n        \"Deployment\",\n    ],\n    \"category\": [\n        \"Planning\",\n        \"Planning\",\n        \"Design\",\n        \"Development\",\n        \"Development\",\n        \"Development\",\n        \"Development\",\n        \"Testing\",\n        \"Testing\",\n        \"Testing\",\n        \"Documentation\",\n        \"Deployment\",\n    ],\n    \"start\": [\n        datetime(2025, 1, 6),\n        datetime(2025, 1, 13),\n        datetime(2025, 1, 20),\n        datetime(2025, 1, 27),\n        datetime(2025, 2, 3),\n        datetime(2025, 1, 27),\n        datetime(2025, 2, 17),\n        datetime(2025, 2, 10),\n        datetime(2025, 2, 24),\n        datetime(2025, 3, 3),\n        datetime(2025, 2, 17),\n        datetime(2025, 3, 10),\n    ],\n    \"end\": [\n        datetime(2025, 1, 10),\n        datetime(2025, 1, 17),\n        datetime(2025, 1, 31),\n        datetime(2025, 2, 14),\n        datetime(2025, 2, 21),\n        datetime(2025, 2, 7),\n        datetime(2025, 2, 28),\n        datetime(2025, 2, 21),\n        datetime(2025, 3, 7),\n        datetime(2025, 3, 14),\n        datetime(2025, 3, 7),\n        datetime(2025, 3, 14),\n    ],\n}\n\ndf = pd.DataFrame(tasks_data)\n\n# Convert dates to numeric for plotting (days since project start)\nproject_start = datetime(2025, 1, 6)\nproject_today = datetime(2025, 2, 17)\n\ndf[\"start_days\"] = [(d - project_start).days for d in df[\"start\"]]\ndf[\"end_days\"] = [(d - project_start).days for d in df[\"end\"]]\ndf[\"duration\"] = df[\"end_days\"] - df[\"start_days\"]\n\n# Map categories to colors (Okabe-Ito palette)\ncategory_colors = {\n    \"Planning\": IMPRINT[0],\n    \"Design\": IMPRINT[1],\n    \"Development\": IMPRINT[2],\n    \"Testing\": IMPRINT[3],\n    \"Documentation\": IMPRINT[4],\n    \"Deployment\": IMPRINT[5],\n}\ndf[\"color\"] = df[\"category\"].map(category_colors)\n\n# Order tasks by start date and assign y positions\ndf = df.sort_values(\"start_days\", ascending=False).reset_index(drop=True)\ndf[\"y_pos\"] = range(len(df))\n\n# Create the Gantt chart using horizontal bars (geom_segment)\nplot = (\n    ggplot(df, aes(x=\"start_days\", y=\"y_pos\"))\n    + geom_segment(aes(xend=\"end_days\", yend=\"y_pos\", color=\"category\"), size=12, alpha=0.85)\n    + geom_point(aes(color=\"category\"), size=4, shape=15)  # Start markers\n    + geom_point(aes(x=\"end_days\", color=\"category\"), size=4, shape=15)  # End markers\n    + geom_vline(xintercept=(project_today - project_start).days, color=INK_SOFT, size=1.5, linetype=\"dashed\")\n    + scale_y_continuous(breaks=list(df[\"y_pos\"]), labels=list(df[\"task\"]), expand=[0.05, 0.05])\n    + scale_x_continuous(\n        name=\"Project Timeline (Days from Start)\",\n        breaks=[0, 7, 14, 21, 28, 35, 42, 49, 56, 63, 70],\n        labels=[\n            \"Week 1\",\n            \"Week 2\",\n            \"Week 3\",\n            \"Week 4\",\n            \"Week 5\",\n            \"Week 6\",\n            \"Week 7\",\n            \"Week 8\",\n            \"Week 9\",\n            \"Week 10\",\n            \"Week 11\",\n        ],\n    )\n    + scale_color_manual(values=IMPRINT, name=\"Phase\")\n    + labs(title=\"gantt-basic · letsplot · anyplot.ai\", x=\"Project Timeline\", y=\"Tasks\")\n    + theme_minimal()\n    + theme(\n        plot_background=element_rect(fill=PAGE_BG, color=PAGE_BG),\n        panel_background=element_rect(fill=PAGE_BG),\n        plot_title=element_text(size=28, color=INK),\n        axis_title_x=element_text(size=22, color=INK),\n        axis_title_y=element_text(size=22, color=INK),\n        axis_text_x=element_text(size=16, color=INK_SOFT, angle=45),\n        axis_text_y=element_text(size=16, color=INK_SOFT),\n        axis_line=element_line(color=INK_SOFT),\n        legend_background=element_rect(fill=ELEVATED_BG, color=INK_SOFT),\n        legend_title=element_text(size=18, color=INK),\n        legend_text=element_text(size=16, color=INK_SOFT),\n        legend_position=\"right\",\n        panel_grid_major_x=element_line(color=RULE, size=0.3),\n        panel_grid_major_y=element_line(color=RULE, size=0.2),\n        panel_grid_minor=element_blank(),\n    )\n    + ggsize(1600, 900)\n)\n\n# Save as PNG (scale 3x for 4800 × 2700 px)\nggsave(plot, f\"plot-{THEME}.png\", scale=3, path=\".\")\n\n# Save interactive HTML version\nggsave(plot, f\"plot-{THEME}.html\", path=\".\")\n"}