{"spec_id":"line-annotated-events","library":"pygal","language":"python","code":"\"\"\" anyplot.ai\nline-annotated-events: Annotated Line Plot with Event Markers\nLibrary: pygal 3.1.0 | Python 3.13.13\nQuality: 92/100 | Updated: 2026-05-16\n\"\"\"\n\nimport os\n\nimport numpy as np\nimport pygal\nfrom pygal.style import Style\n\n\nTHEME = os.getenv(\"ANYPLOT_THEME\", \"light\")\nPAGE_BG = \"#FAF8F1\" if THEME == \"light\" else \"#1A1A17\"\nINK = \"#1A1A17\" if THEME == \"light\" else \"#F0EFE8\"\nINK_MUTED = \"#6B6A63\" if THEME == \"light\" else \"#A8A79F\"\n\nIMPRINT = (\"#009E73\", \"#C475FD\", \"#4467A3\", \"#BD8233\", \"#AE3030\", \"#2ABCCD\", \"#954477\")\n\n# Data - Stock price over a year with quarterly events\nnp.random.seed(42)\nn_days = 250  # Trading days in a year\n\n# Generate realistic stock-like price data with trend and volatility\nbase_price = 150\nreturns = np.random.randn(n_days) * 0.012\nprices = base_price * np.cumprod(1 + returns)\n\n# Event data - indices and labels\nevents = [(31, \"Q4 Earnings\"), (94, \"Q1 Earnings\"), (136, \"Product Launch\"), (157, \"Q2 Earnings\"), (220, \"Q3 Earnings\")]\n\n# Custom style with theme-adaptive colors\ncustom_style = Style(\n    background=PAGE_BG,\n    plot_background=PAGE_BG,\n    foreground=INK,\n    foreground_strong=INK,\n    foreground_subtle=INK_MUTED,\n    colors=IMPRINT,\n    title_font_size=28,\n    label_font_size=22,\n    major_label_font_size=18,\n    legend_font_size=16,\n    value_font_size=14,\n    stroke_width=3,\n)\n\n# Create XY chart for precise coordinate control\nchart = pygal.XY(\n    width=4800,\n    height=2700,\n    style=custom_style,\n    title=\"line-annotated-events · pygal · anyplot.ai\",\n    x_title=\"Trading Day (2024)\",\n    y_title=\"Stock Price (USD)\",\n    show_dots=False,\n    stroke_style={\"width\": 3, \"linecap\": \"round\"},\n    show_legend=True,\n    legend_at_bottom=True,\n    show_x_guides=False,\n    show_y_guides=True,\n    margin=120,\n    margin_bottom=200,\n    margin_left=200,\n    margin_right=150,\n    print_values=False,\n    interpolate=\"cubic\",\n    range=(min(prices) * 0.95, max(prices) * 1.05),\n    xrange=(0, n_days),\n    x_labels_major_count=6,\n    show_minor_x_labels=False,\n)\n\n# Set x-axis labels\nchart.x_labels = [0, 50, 100, 150, 200, 250]\n\n# Add main stock price line as XY coordinates\nprice_data = [(i, prices[i]) for i in range(n_days)]\nchart.add(\"Stock Price\", price_data, stroke_style={\"width\": 3})\n\n# Add event markers with vertical lines\n# Each event is visualized as a prominent vertical line with dot marker\ny_min = min(prices) * 0.95\ny_max = max(prices) * 1.05\n\nfor day_idx, label in events:\n    event_price = prices[day_idx]\n\n    # Create vertical line from bottom to the event point\n    vertical_line = [(day_idx, y_min), (day_idx, event_price)]\n\n    # Add vertical line with prominent styling\n    chart.add(label, vertical_line, stroke_style={\"width\": 8, \"dasharray\": \"20, 12\"}, show_dots=True, dots_size=8)\n\n# Render outputs\nchart.render_to_png(f\"plot-{THEME}.png\")\n\nwith open(f\"plot-{THEME}.html\", \"wb\") as f:\n    f.write(chart.render())\n"}