{"spec_id":"point-basic","library":"altair","language":"python","code":"\"\"\" anyplot.ai\npoint-basic: Point Estimate Plot\nLibrary: altair 6.1.0 | Python 3.13.13\nQuality: 94/100 | Updated: 2026-05-11\n\"\"\"\n\nimport os\nfrom pathlib import Path\n\n\n# Change to script directory to ensure files save in the right place\nos.chdir(Path(__file__).parent)\n\nimport altair as alt\nimport numpy as np\nimport pandas as pd\n\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# Okabe-Ito palette - first series is always #009E73 (brand green)\nBRAND = \"#009E73\"\nSECONDARY = \"#C475FD\"\nREFERENCE_LINE = \"#888888\"\n\n# Data - Treatment effect estimates with 95% confidence intervals\nnp.random.seed(42)\ngroups = [\"Treatment A\", \"Treatment B\", \"Treatment C\", \"Treatment D\", \"Control\", \"Placebo\"]\nestimates = [2.4, 1.8, 3.1, -0.5, 0.2, 0.8]\nci_widths = [0.8, 1.2, 0.6, 1.0, 0.9, 1.1]\nlower = [e - w for e, w in zip(estimates, ci_widths, strict=True)]\nupper = [e + w for e, w in zip(estimates, ci_widths, strict=True)]\n\ndf = pd.DataFrame({\"Group\": groups, \"Estimate\": estimates, \"Lower\": lower, \"Upper\": upper})\n\n# Base chart for points\npoints = (\n    alt.Chart(df)\n    .mark_point(size=400, filled=True, color=BRAND)\n    .encode(\n        x=alt.X(\"Estimate:Q\", title=\"Effect Size\", scale=alt.Scale(domain=[-3, 5])),\n        y=alt.Y(\"Group:N\", title=None, sort=None),\n        tooltip=[\"Group:N\", \"Estimate:Q\", \"Lower:Q\", \"Upper:Q\"],\n    )\n)\n\n# Error bars (confidence intervals)\nerror_bars = (\n    alt.Chart(df)\n    .mark_rule(strokeWidth=3, color=BRAND)\n    .encode(x=alt.X(\"Lower:Q\"), x2=alt.X2(\"Upper:Q\"), y=alt.Y(\"Group:N\", sort=None))\n)\n\n# Error bar caps (left)\ncaps_left = (\n    alt.Chart(df).mark_tick(thickness=3, size=20, color=BRAND).encode(x=alt.X(\"Lower:Q\"), y=alt.Y(\"Group:N\", sort=None))\n)\n\n# Error bar caps (right)\ncaps_right = (\n    alt.Chart(df).mark_tick(thickness=3, size=20, color=BRAND).encode(x=alt.X(\"Upper:Q\"), y=alt.Y(\"Group:N\", sort=None))\n)\n\n# Reference line at zero (null hypothesis)\nreference_line = (\n    alt.Chart(pd.DataFrame({\"x\": [0]}))\n    .mark_rule(strokeDash=[8, 4], strokeWidth=2, color=REFERENCE_LINE)\n    .encode(x=alt.X(\"x:Q\"))\n)\n\n# Combine layers\nchart = (\n    alt.layer(reference_line, error_bars, caps_left, caps_right, points)\n    .properties(\n        width=1600,\n        height=900,\n        background=PAGE_BG,\n        title=alt.Title(\"point-basic · altair · anyplot.ai\", fontSize=28, anchor=\"middle\"),\n    )\n    .configure_axis(\n        labelFontSize=18,\n        titleFontSize=22,\n        labelColor=INK_SOFT,\n        titleColor=INK,\n        domainColor=INK_SOFT,\n        tickColor=INK_SOFT,\n        gridColor=INK,\n        gridOpacity=0.10,\n    )\n    .configure_view(fill=PAGE_BG, stroke=INK_SOFT, strokeWidth=1)\n    .configure_title(color=INK)\n)\n\n# Save outputs\nchart.save(f\"plot-{THEME}.png\", scale_factor=3.0)\nchart.save(f\"plot-{THEME}.html\")\n"}