{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "806857a8",
   "metadata": {},
   "source": [
    "# Week 5 Lab — Error Propagation for Engineers and Scientists\n",
    "\n",
    "In this lab, we will study how uncertainty in measured variables affects the uncertainty of computed quantities.\n",
    "\n",
    "We will work through three parts:\n",
    "\n",
    "1. **Repeated measurements and uncertainty estimation**\n",
    "2. **Propagation of uncertainty for one variable**\n",
    "3. **Propagation of uncertainty for several variables**\n",
    "\n",
    "At the end of the lab, you should be able to:\n",
    "\n",
    "- compute the mean and sample standard deviation from repeated measurements,\n",
    "- report a measurement with uncertainty,\n",
    "- propagate uncertainty through simple formulas,\n",
    "- identify which measured variable contributes most to the final uncertainty."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "243d8bd5",
   "metadata": {},
   "source": [
    "## Part A — Repeated Measurements\n",
    "\n",
    "In real experiments, the same quantity is often measured several times.  \n",
    "These repeated measurements help us estimate:\n",
    "\n",
    "- a representative value of the quantity, using the **sample mean**,\n",
    "- the variability of the measurements, using the **sample standard deviation**.\n",
    "\n",
    "We begin with a small set of repeated voltage measurements."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "41fde6a2",
   "metadata": {},
   "source": [
    "### Repeated voltage measurements\n",
    "\n",
    "The following values represent repeated measurements of the same voltage."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "id": "2a424c85",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([4.98, 5.01, 5.  , 5.03, 4.99, 5.02, 4.97, 5.01])"
      ]
     },
     "execution_count": 2,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "import numpy as np\n",
    "import pandas as pd\n",
    "import matplotlib.pyplot as plt\n",
    "\n",
    "V_samples = np.array([4.98, 5.01, 5.00, 5.03, 4.99, 5.02, 4.97, 5.01])\n",
    "\n",
    "V_samples"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "701cbb86",
   "metadata": {},
   "source": [
    "### Compute the mean and sample standard deviation\n",
    "\n",
    "We will use:\n",
    "\n",
    "$$\\bar{x} = \\frac{1}{n}\\sum_{i=1}^n x_i$$\n",
    "\n",
    "and\n",
    "\n",
    "$$\n",
    "s = \\sqrt{\\frac{1}{n-1}\\sum_{i=1}^n (x_i-\\bar{x})^2}\n",
    "$$\n",
    "\n",
    "The mean gives a central value, while the sample standard deviation describes the spread of the repeated measurements."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "85752039",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Mean voltage = 5.0013 V\n",
      "Sample standard deviation = 0.0203 V\n"
     ]
    }
   ],
   "source": [
    "V_mean = np.mean(V_samples)\n",
    "V_std = np.std(V_samples, ddof=1)\n",
    "\n",
    "print(f\"Mean voltage = {V_mean:.4f} V\")\n",
    "print(f\"Sample standard deviation = {V_std:.4f} V\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "36199326",
   "metadata": {},
   "source": [
    "### Report the measurement\n",
    "\n",
    "A basic engineering report format is:\n",
    "\n",
    "$$\n",
    "V \\approx \\bar{V} \\pm s_V\n",
    "$$\n",
    "\n",
    "This is a practical summary of the measured value and its variability."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "id": "2d3cb5e5",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Reported measurement: V = 5.0013 +/- 0.0203 V\n"
     ]
    }
   ],
   "source": [
    "print(f\"Reported measurement: V = {V_mean:.4f} +/- {V_std:.4f} V\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "id": "68878355",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>trial</th>\n",
       "      <th>voltage_V</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>1</td>\n",
       "      <td>4.98</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>2</td>\n",
       "      <td>5.01</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>3</td>\n",
       "      <td>5.00</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>3</th>\n",
       "      <td>4</td>\n",
       "      <td>5.03</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>4</th>\n",
       "      <td>5</td>\n",
       "      <td>4.99</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>5</th>\n",
       "      <td>6</td>\n",
       "      <td>5.02</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>6</th>\n",
       "      <td>7</td>\n",
       "      <td>4.97</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>7</th>\n",
       "      <td>8</td>\n",
       "      <td>5.01</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "   trial  voltage_V\n",
       "0      1       4.98\n",
       "1      2       5.01\n",
       "2      3       5.00\n",
       "3      4       5.03\n",
       "4      5       4.99\n",
       "5      6       5.02\n",
       "6      7       4.97\n",
       "7      8       5.01"
      ]
     },
     "execution_count": 8,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# Table\n",
    "df_voltage = pd.DataFrame({\n",
    "    \"trial\": np.arange(1, len(V_samples) + 1),\n",
    "    \"voltage_V\": V_samples\n",
    "})\n",
    "\n",
    "df_voltage"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "id": "442f5528",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "[encoded data, 28668 characters]",
      "text/plain": [
       "<Figure size 800x400 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "plt.figure(figsize=(8, 4))\n",
    "plt.plot(df_voltage[\"trial\"], df_voltage[\"voltage_V\"], marker=\"o\", linestyle=\"none\", label=\"samples\")\n",
    "plt.axhline(V_mean, linestyle=\"--\", linewidth=2, label=f\"mean = {V_mean:.4f} V\")\n",
    "plt.xlabel(\"Trial\")\n",
    "plt.ylabel(\"Voltage [V]\")\n",
    "plt.title(\"Repeated Voltage Measurements\")\n",
    "plt.legend()\n",
    "plt.grid(True, alpha=0.3)\n",
    "plt.show()\n",
    "\n",
    "# Plot the repeated measurements\n",
    "#The dashed line shows the sample mean.  \n",
    "#This helps us visualize the spread of the measurements around the central value."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "b086bfda",
   "metadata": {},
   "source": [
    "### Exercise A\n",
    "\n",
    "Using the measurements above, answer the following:\n",
    "\n",
    "1. What is the estimated voltage?\n",
    "2. What does the sample standard deviation tell us?\n",
    "3. Are the measurements relatively precise or widely scattered?\n",
    "\n",
    "Write a short interpretation in your own words."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "420a5134",
   "metadata": {},
   "source": [
    "## Part B — Propagation of Uncertainty for One Variable\n",
    "\n",
    "Now we consider a quantity that is not measured directly, but computed from another measured variable.\n",
    "\n",
    "Suppose the output quantity is:\n",
    "\n",
    "$$\n",
    "A = \\pi r^2\n",
    "$$\n",
    "\n",
    "If the radius \\(r\\) has uncertainty, then the area \\(A\\) also has uncertainty.\n",
    "\n",
    "For one variable, we use the first-order propagation formula:\n",
    "\n",
    "$$\n",
    "\\sigma_A \\approx \\left|\\frac{dA}{dr}\\right| \\sigma_r\n",
    "$$"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "181c9bee",
   "metadata": {},
   "source": [
    "### Example: Area of a circle\n",
    "\n",
    "Let:\n",
    "\n",
    "- $r = 10.0$ mm\n",
    "- $\\sigma_r = 0.2$ mm\n",
    "\n",
    "Then:\n",
    "\n",
    "$$\n",
    "A = \\pi r^2\n",
    "$$\n",
    "\n",
    "and\n",
    "\n",
    "$$\n",
    "\\frac{dA}{dr} = 2\\pi r\n",
    "$$\n",
    "\n",
    "So the propagated uncertainty is:\n",
    "\n",
    "$$\n",
    "\\sigma_A \\approx |2\\pi r| \\sigma_r\n",
    "$$"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "98397e2f",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Radius: r = 10.000 ± 0.200 mm\n",
      "Area:   A = 314.159 ± 12.566 mm^2\n"
     ]
    }
   ],
   "source": [
    "r = 10.0\n",
    "sigma_r = 0.2\n",
    "\n",
    "A = np.pi * r**2\n",
    "sigma_A = abs(2 * np.pi * r) * sigma_r\n",
    "\n",
    "print(f\"Radius: r = {r:.3f} ± {sigma_r:.3f} mm\")\n",
    "print(f\"Area:   A = {A:.3f} ± {sigma_A:.3f} mm^2\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "d46b4d65",
   "metadata": {},
   "source": [
    "### Observe how the output uncertainty changes\n",
    "\n",
    "We now vary the uncertainty in the radius and observe how the area uncertainty changes.\n",
    "\n",
    "This helps us see that larger uncertainty in the input produces larger uncertainty in the output."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "id": "c3e0fb2f",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "[encoded data, 35760 characters]",
      "text/plain": [
       "<Figure size 800x400 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "sigma_r_values = np.linspace(0.01, 0.5, 100)\n",
    "sigma_A_values = abs(2 * np.pi * r) * sigma_r_values\n",
    "\n",
    "plt.figure(figsize=(8, 4))\n",
    "plt.plot(sigma_r_values, sigma_A_values)\n",
    "plt.xlabel(\"Uncertainty in radius, sigma_r [mm]\")\n",
    "plt.ylabel(\"Uncertainty in area, sigma_A [mm^2]\")\n",
    "plt.title(\"Propagation of Uncertainty: A = pi r^2\")\n",
    "plt.grid(True, alpha=0.3)\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "c1736d7c",
   "metadata": {},
   "source": [
    "### Exercise B\n",
    "\n",
    "Answer the following:\n",
    "\n",
    "1. If the uncertainty in radius doubles, what happens to the uncertainty in area?\n",
    "2. Why does the derivative appear in the propagation formula?\n",
    "3. For this example, is the relation between \\(\\sigma_r\\) and \\(\\sigma_A\\) linear?\n",
    "\n",
    "Write a brief explanation."
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": ".venv (3.14.2)",
   "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.14.2"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
