{"spec_id":"scatter-regression-lowess","library":"pygal","language":"python","code":"\"\"\" anyplot.ai\nscatter-regression-lowess: Scatter Plot with LOWESS Regression\nLibrary: pygal 3.1.0 | Python 3.13.13\nQuality: 86/100 | Updated: 2026-05-14\n\"\"\"\n\nimport os\n\nimport numpy as np\nimport pygal\nfrom pygal.style import Style\nfrom statsmodels.nonparametric.smoothers_lowess import lowess\n\n\n# Theme tokens\nTHEME = os.getenv(\"ANYPLOT_THEME\", \"light\")\nPAGE_BG = \"#FAF8F1\" if THEME == \"light\" else \"#1A1A17\"\nINK = \"#1A1A17\" if THEME == \"light\" else \"#F0EFE8\"\nINK_SOFT = \"#4A4A44\" if THEME == \"light\" else \"#B8B7B0\"\nINK_MUTED = \"#6B6A63\" if THEME == \"light\" else \"#A8A79F\"\n\nIMPRINT = (\"#009E73\", \"#C475FD\", \"#4467A3\", \"#BD8233\", \"#AE3030\", \"#2ABCCD\", \"#954477\")\n\n# Data - Drug dose-response relationship with non-linear effect\nnp.random.seed(42)\nn_points = 150\n\n# Drug concentration in mg/L (log-spaced for pharmacological realism)\nconcentration = np.linspace(0.1, 50, n_points)\n\n# Enzyme activity response: sigmoidal with saturation and hormesis effect\nbase_response = 25 + 55 * (1 - np.exp(-concentration / 8)) - 10 * np.exp(-concentration / 3)\nnoise = np.random.normal(0, 4, n_points)\nactivity = base_response + noise\n\n# Calculate LOWESS smoothed curve\nlowess_result = lowess(activity, concentration, frac=0.35, return_sorted=True)\nconc_smooth = lowess_result[:, 0]\nactivity_smooth = lowess_result[:, 1]\n\n# Custom style with theme-adaptive tokens\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    opacity=0.6,\n    opacity_hover=0.9,\n)\n\n# Create XY chart for scatter plot\nchart = pygal.XY(\n    width=4800,\n    height=2700,\n    style=custom_style,\n    title=\"scatter-regression-lowess · pygal · anyplot.ai\",\n    x_title=\"Drug Concentration (mg/L)\",\n    y_title=\"Enzyme Activity (%)\",\n    show_dots=True,\n    dots_size=8,\n    stroke=False,\n    show_x_guides=True,\n    show_y_guides=True,\n)\n\n# Add scatter points (brand green - Okabe-Ito position 1)\nscatter_data = list(zip(concentration, activity, strict=True))\nchart.add(\"Observed Response\", scatter_data, stroke=False, dots_size=10)\n\n# Add LOWESS curve (vermillion - Okabe-Ito position 2)\nlowess_data = list(zip(conc_smooth, activity_smooth, strict=True))\nchart.add(\"LOWESS Fit (frac=0.35)\", lowess_data, stroke=True, show_dots=False, stroke_style={\"width\": 6})\n\n# Save as PNG and HTML with theme suffix\nchart.render_to_png(f\"plot-{THEME}.png\")\nwith open(f\"plot-{THEME}.html\", \"wb\") as f:\n    f.write(chart.render())\n"}