{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "c000",
   "metadata": {},
   "source": [
    "# E190BO — Environment Check\n",
    "\n",
    "Run the one cell below. If it prints `ALL CHECKS PASSED` and draws a curve, your laptop is\n",
    "set up correctly for the semester.\n",
    "\n",
    "**Before you run it:** check the kernel name in the top-right corner. It must say\n",
    "**Python (E190BO)**. If it says anything else, click it and switch.\n",
    "\n",
    "Show this output at your Lab 0 check-in. If something fails, read the \"If you see this error\"\n",
    "section of `SETUP.md` — and if that does not resolve it, bring it to lab or office hours.\n",
    "Do not leave it until an assignment is due.\n",
    "\n",
    "*Run this again at the start of each assignment, and any time a new package is announced.*"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "id": "c001",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2026-09-01T07:53:55.109308Z",
     "iopub.status.busy": "2026-09-01T07:53:55.109083Z",
     "iopub.status.idle": "2026-09-01T07:54:05.303299Z",
     "shell.execute_reply": "2026-09-01T07:54:05.302229Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Python   3.13.5 (Darwin)\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "numpy    2.1.3\n",
      "pandas   2.2.3\n",
      "mpl      3.10.0\n",
      "kernel   /private/tmp/claude-502/-Users-ttsai-Development-Teaching-E190BO-F26/a6bef1ea-a633-414f-9f67-d754045c69a3/scratchpad/e190bo/.venv/bin/python\n",
      "pandas   ok\n",
      "broadcast (3, 4) ok\n"
     ]
    },
    {
     "data": {
      "image/png": "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",
      "text/plain": [
       "<Figure size 450x250 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\n",
      "ALL CHECKS PASSED\n"
     ]
    }
   ],
   "source": [
    "import sys, platform\n",
    "\n",
    "print(\"Python  \", sys.version.split()[0], f\"({platform.system()})\")\n",
    "assert sys.version_info[:2] == (3, 13), (\n",
    "    f\"This kernel is running Python {sys.version.split()[0]}, but the whole class runs 3.13. \"\n",
    "    \"Two likely causes: (1) the kernel in the top-right corner is not 'Python (E190BO)' -- \"\n",
    "    \"switch it; or (2) your .venv was built by the wrong interpreter -- delete it and redo \"\n",
    "    \"SETUP.md Step 3, using python3.13 / py -3.13 explicitly.\")\n",
    "\n",
    "import numpy as np, pandas as pd, matplotlib, sklearn\n",
    "from importlib.metadata import version\n",
    "import matplotlib.pyplot as plt\n",
    "print(\"numpy   \", np.__version__)\n",
    "print(\"pandas  \", pd.__version__)\n",
    "print(\"mpl     \", matplotlib.__version__)\n",
    "print(\"sklearn \", sklearn.__version__)\n",
    "print(\"anthropic\", version(\"anthropic\"))\n",
    "print(\"dotenv  \", version(\"python-dotenv\"))\n",
    "\n",
    "# exact versions, not minimums: everyone in the class runs the same ones, so that a\n",
    "# notebook behaving differently is never explained by a package version\n",
    "assert np.__version__ == \"2.1.3\", f\"expected numpy 2.1.3, got {np.__version__}\"\n",
    "assert pd.__version__ == \"2.2.3\", f\"expected pandas 2.2.3, got {pd.__version__}\"\n",
    "assert matplotlib.__version__ == \"3.10.0\", f\"expected matplotlib 3.10.0, got {matplotlib.__version__}\"\n",
    "assert sklearn.__version__ == \"1.6.1\", f\"expected scikit-learn 1.6.1, got {sklearn.__version__}\"\n",
    "assert version(\"anthropic\") == \"1.8.0\", f\"expected anthropic 1.8.0, got {version('anthropic')}\"\n",
    "assert version(\"python-dotenv\") == \"1.2.3\", f\"expected python-dotenv 1.2.3, got {version('python-dotenv')}\"\n",
    "\n",
    "# you are running inside the course environment, not some other Python\n",
    "print(\"kernel  \", sys.executable)\n",
    "if \".venv\" not in sys.executable:\n",
    "    print(\"   ^^ WARNING: this does not look like your ~/e190bo/.venv environment.\")\n",
    "    print(\"      Check that the kernel in the top-right corner says 'Python (E190BO)'.\")\n",
    "\n",
    "# pandas can build and summarize a table\n",
    "dfx = pd.DataFrame({\"a\": [1, 2, 3], \"b\": [4.0, 5.0, 6.0]})\n",
    "assert dfx.shape == (3, 2) and dfx[\"b\"].mean() == 5.0\n",
    "print(\"pandas   ok\")\n",
    "\n",
    "# broadcasting: a (3,1) column plus a (4,) row should give a (3,4) grid\n",
    "grid = np.arange(3).reshape(3, 1) + np.arange(4)\n",
    "assert grid.shape == (3, 4) and grid[2, 3] == 5\n",
    "print(\"broadcast\", grid.shape, \"ok\")\n",
    "\n",
    "# scikit-learn: used in Lab 2 to generate a small synthetic dataset\n",
    "from sklearn.datasets import make_classification\n",
    "Xc, yc = make_classification(n_samples=20, n_features=4, n_redundant=0,\n",
    "                             n_informative=4, n_classes=3, random_state=1)\n",
    "assert Xc.shape == (20, 4) and yc.shape == (20,)\n",
    "print(\"sklearn  ok\")\n",
    "\n",
    "t = np.linspace(0, 4, 200)\n",
    "plt.figure(figsize=(4.5, 2.5))\n",
    "plt.plot(t, 3 * np.exp(-0.6 * t) * np.sin(4 * t))\n",
    "plt.title(\"if you can see this curve, you are set\")\n",
    "plt.grid(alpha=.3); plt.show()\n",
    "\n",
    "print(\"\\nALL CHECKS PASSED\")"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.13.5"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
