{"spec_id":"andrews-curves","library":"altair","language":"python","code":"\"\"\" anyplot.ai\nandrews-curves: Andrews Curves for Multivariate Data\nLibrary: altair 6.1.0 | Python 3.13.13\nQuality: 92/100 | Updated: 2026-05-15\n\"\"\"\n\nimport os\nimport sys\n\n\n# Remove script directory from sys.path to avoid importing local altair.py\nscript_dir = os.path.dirname(os.path.abspath(__file__))\nif script_dir in sys.path:\n    sys.path.remove(script_dir)\n\nimport altair as alt\nimport numpy as np\nimport pandas as pd\nfrom sklearn.datasets import load_iris\nfrom sklearn.preprocessing import StandardScaler\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\nIMPRINT = [\"#009E73\", \"#C475FD\", \"#4467A3\"]\n\n# Load and prepare data\nnp.random.seed(42)\niris = load_iris()\nX = iris.data\ny = iris.target\nspecies_names = [\"Setosa\", \"Versicolor\", \"Virginica\"]\n\n# Normalize variables to similar scales\nscaler = StandardScaler()\nX_scaled = scaler.fit_transform(X)\n\n# Andrews curve transformation\n# f(t) = x1/sqrt(2) + x2*sin(t) + x3*cos(t) + x4*sin(2t) + x5*cos(2t) + ...\nn_points = 100\nt = np.linspace(-np.pi, np.pi, n_points)\n\n# Compute Andrews curves for each observation\ncurves_data = []\nfor obs_idx in range(len(X_scaled)):\n    x = X_scaled[obs_idx]\n    curve = np.zeros(n_points)\n    curve += x[0] / np.sqrt(2)\n\n    for i in range(1, len(x)):\n        freq = (i + 1) // 2\n        if i % 2 == 1:\n            curve += x[i] * np.sin(freq * t)\n        else:\n            curve += x[i] * np.cos(freq * t)\n\n    for pt_idx in range(n_points):\n        curves_data.append(\n            {\"t\": t[pt_idx], \"value\": curve[pt_idx], \"observation\": obs_idx, \"species\": species_names[y[obs_idx]]}\n        )\n\ndf = pd.DataFrame(curves_data)\n\n# Create chart\nchart = (\n    alt.Chart(df)\n    .mark_line(opacity=0.5, size=2)\n    .encode(\n        x=alt.X(\n            \"t:Q\",\n            title=\"t (radians)\",\n            axis=alt.Axis(labelFontSize=18, titleFontSize=22, labelColor=INK_SOFT, titleColor=INK),\n        ),\n        y=alt.Y(\n            \"value:Q\",\n            title=\"Andrews Curve Value\",\n            axis=alt.Axis(labelFontSize=18, titleFontSize=22, labelColor=INK_SOFT, titleColor=INK),\n        ),\n        color=alt.Color(\n            \"species:N\",\n            title=\"Species\",\n            scale=alt.Scale(domain=species_names, range=IMPRINT),\n            legend=alt.Legend(\n                titleFontSize=18,\n                labelFontSize=16,\n                titleColor=INK,\n                labelColor=INK_SOFT,\n                fillColor=ELEVATED_BG,\n                strokeColor=INK_SOFT,\n            ),\n        ),\n        detail=\"observation:N\",\n        tooltip=[\"species:N\", \"observation:N\"],\n    )\n    .properties(\n        width=1600,\n        height=900,\n        background=PAGE_BG,\n        title=alt.Title(\"andrews-curves · altair · anyplot.ai\", fontSize=28, color=INK),\n    )\n    .configure_axis(domainColor=INK_SOFT, tickColor=INK_SOFT, gridColor=INK, gridOpacity=0.10)\n    .configure_view(fill=PAGE_BG, stroke=None)\n    .configure_title(color=INK)\n    .configure_legend(\n        titleFontSize=18,\n        labelFontSize=16,\n        titleColor=INK,\n        labelColor=INK_SOFT,\n        fillColor=ELEVATED_BG,\n        strokeColor=INK_SOFT,\n    )\n)\n\n# Save as PNG and HTML\nchart.save(f\"plot-{THEME}.png\", scale_factor=3.0)\nchart.save(f\"plot-{THEME}.html\")\n"}