{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "bdf377b8",
   "metadata": {},
   "source": [
    "Tutto quello che c'è da sapere sulla molla 2, possibilmente con la massima chiarezza."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "id": "3a34cc3f",
   "metadata": {},
   "outputs": [],
   "source": [
    "# Heavy lifting\n",
    "import numpy as np\n",
    "import pandas as pd\n",
    "from scipy import stats\n",
    "\n",
    "# Mostrare i dati\n",
    "import ipysheet\n",
    "from IPython.display import display\n",
    "import matplotlib.pyplot as plt\n",
    "import seaborn as sns\n",
    "\n",
    "# Calcolo simbolico\n",
    "import sympy as sp\n",
    "\n",
    "\n",
    "G = 9.806\n",
    "uG = 0.004"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "0eaece9c",
   "metadata": {},
   "source": [
    "# Calibro"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "960e68a5",
   "metadata": {},
   "source": [
    "## Import dati e ricerca outlier"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "id": "1e2fabea",
   "metadata": {},
   "outputs": [],
   "source": [
    "# Funzioni criterio di Chauvenet\n",
    "\n",
    "# Probabilità\n",
    "def p_t_student(valori, err_strumentale):\n",
    "  n   = len(valori)\n",
    "  GdL = n - 1\n",
    "  if n <= 2:\n",
    "    return np.ones(n)\n",
    "\n",
    "  media = valori.mean()\n",
    "  s     = valori.std(ddof=1)\n",
    "  if s == 0:\n",
    "    return np.ones(n)\n",
    "\n",
    "  s = np.sqrt(s**2 + err_strumentale**2)\n",
    "  return 2 * (1 - stats.t.cdf(np.abs(valori - media) / s, df=GdL))\n",
    "\n",
    "# Indice del peggiore outlier o None\n",
    "def trova_outlier(valori, err_strumentale):\n",
    "  n       = len(valori)\n",
    "  soglia  = 1 / (2 * n)\n",
    "  p       = p_t_student(valori, err_strumentale)\n",
    "  idx_min = np.argmin(p)\n",
    "\n",
    "  if p[idx_min] < soglia:\n",
    "      return idx_min\n",
    "  return None\n",
    "\n",
    "# Rimuove outlier\n",
    "def rimuovi_outlier(valori, err_strumentale):\n",
    "  rimossi  = []\n",
    "  campione = valori.copy()\n",
    "\n",
    "  while len(campione) > 2:\n",
    "    idx = trova_outlier(campione, err_strumentale)\n",
    "\n",
    "    if idx is None: # nessun outlier: stop\n",
    "      break\n",
    "\n",
    "    rimossi.append(campione[idx])\n",
    "    campione = np.delete(campione, idx)\n",
    "\n",
    "  return campione, rimossi\n",
    "\n",
    "# return media u rimossi []\n",
    "def stats_riga(valori_raw, err_strumentale):\n",
    "  # caso 0\n",
    "  if len(valori_raw) == 0:\n",
    "    return {\"media\": np.nan, \"u_strum\": err_strumentale, \"u_stat\": np.nan, \"u\": np.nan, \"n\": 0, \"rimossi\": []}\n",
    "\n",
    "  # caso 1\n",
    "  if len(valori_raw) == 1:\n",
    "    return {\"media\": valori_raw[0], \"u_strum\": err_strumentale, \"u_stat\": np.nan, \"u\": np.nan, \"n\": 1, \"rimossi\": []}\n",
    "\n",
    "  # caso n>1\n",
    "  puliti, rimossi = rimuovi_outlier(valori_raw, err_strumentale)\n",
    "\n",
    "  media = puliti.mean()\n",
    "\n",
    "  s = puliti.std(ddof=1)\n",
    "  n = len(puliti)\n",
    "  s = s / np.sqrt(n)\n",
    "  u = np.sqrt(s**2 + err_strumentale**2)\n",
    "\n",
    "  return {\"media\": media, \"u_strum\": err_strumentale, \"u_stat\": s, \"u\": u, \"n\": n, \"rimossi\": rimossi}"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "id": "264a5b1d",
   "metadata": {},
   "outputs": [],
   "source": [
    "# Accessor: aggiunta metodi ai df\n",
    "\n",
    "# Nasconde specificamente l'avviso di sovrascrittura dell'accessor\n",
    "import warnings\n",
    "warnings.filterwarnings(\"ignore\", message=\"registration of accessor\")\n",
    "\n",
    "@pd.api.extensions.register_dataframe_accessor(\"acc\")\n",
    "\n",
    "class Miei_Metodi:\n",
    "\n",
    "    def __init__(self, pandas_obj):\n",
    "        self._df = pandas_obj\n",
    "    \n",
    "    # Calcola la statistica con Criterio di Chauvenet\n",
    "    def calcola_stats(self, df, prefix, err_strumentale):\n",
    "        cols = [col for col in df.columns if col.startswith(prefix)]\n",
    "\n",
    "        for i, row in df.iterrows():\n",
    "            valori = row[cols].dropna().values.astype(float)\n",
    "            ans    = stats_riga(valori, err_strumentale)\n",
    "\n",
    "            self._df.at[i, prefix]              = ans[\"media\"]\n",
    "            self._df.at[i, f\"u{prefix}_strum\"]  = ans[\"u_strum\"]\n",
    "            self._df.at[i, f\"u{prefix}_stat\"]   = ans[\"u_stat\"]\n",
    "            self._df.at[i, f\"u{prefix}\"]        = ans[\"u\"]\n",
    "            self._df.at[i, f\"n{prefix}\"]        = int(ans[\"n\"])\n",
    "            self._df.at[i, f\"out{prefix}\"]      = str(ans[\"rimossi\"])\n",
    "\n",
    "        return self._df"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "id": "a5ff5ff5",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "F  = g*m\n",
      "sigma_F = sqrt(g**2*sigma_m**2 + m**2*sigma_g**2)\n",
      "\n",
      "Formula LaTeX:\n",
      "F = g m\n",
      "sigma_F = \\sqrt{g^{2} \\sigma_{m}^{2} + m^{2} \\sigma_{g}^{2}}\n"
     ]
    }
   ],
   "source": [
    "# Calcolo simbolico F\n",
    "\n",
    "# simboli\n",
    "m, x, g = sp.symbols('m x g', positive=True)\n",
    "sigma_m, sigma_x, sigma_g = sp.symbols('sigma_m sigma_x sigma_g', positive=True)\n",
    "\n",
    "F = m * g\n",
    "\n",
    "# derivate parziali\n",
    "dF_dm = sp.diff(F, m)\n",
    "dF_dg = sp.diff(F, g)\n",
    "\n",
    "sigma_F = sp.sqrt((dF_dm * sigma_m)**2 + (dF_dg * sigma_g)**2)\n",
    "\n",
    "print(\"F  =\", F)\n",
    "print(\"sigma_F =\", sigma_F)\n",
    "print(\"\\nFormula LaTeX:\")\n",
    "print(f\"F = {sp.latex(F)}\")\n",
    "print(f\"sigma_F = {sp.latex(sigma_F.simplify())}\")\n",
    "\n",
    "# funzioni numeriche\n",
    "F_fn  = sp.lambdify((m, g),  F,  'numpy')\n",
    "uF_fn = sp.lambdify((m, sigma_m, g, sigma_g), sigma_F, 'numpy')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "id": "e649eddc",
   "metadata": {},
   "outputs": [],
   "source": [
    "# Import dati, analisi statistica medie e ricerca outlier\n",
    "\n",
    "dfCalibro_raw = pd.read_csv(r'molla2Calibro.csv')\n",
    "\n",
    "# Costanti strumentali\n",
    "ERR_CALIBRO = 0.02 / np.sqrt(24)\n",
    "ERR_BILANCIA = 0.01 / np.sqrt(12)\n",
    "\n",
    "# Chauvenet e poi statistica di base\n",
    "dfCalibro = pd.DataFrame()\n",
    "dfCalibro = dfCalibro.acc.calcola_stats(dfCalibro_raw, \"dx\", ERR_CALIBRO)\n",
    "dfCalibro = dfCalibro.acc.calcola_stats(dfCalibro_raw, \"m\",  ERR_BILANCIA)\n",
    "\n",
    "# Aggiunta delle forze\n",
    "dfCalibro[\"F\"]  = F_fn(dfCalibro[\"m\"],  G)\n",
    "dfCalibro[\"uF\"] = uF_fn(dfCalibro[\"m\"], dfCalibro[\"um\"], G, uG)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "id": "42ff21d6",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "application/vnd.jupyter.widget-view+json": {
       "model_id": "722fa004f851472cb356ab99ec9c396b",
       "version_major": 2,
       "version_minor": 0
      },
      "text/plain": [
       "Sheet(cells=(Cell(column_end=0, column_start=0, row_start=0, squeeze_row=False, type='numeric', value=[212.08,…"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "sheet = ipysheet.from_dataframe(dfCalibro)\n",
    "\n",
    "display(sheet)\n",
    "# dfCalibro.head(2).to_json(orient=\"records\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "c58a6e26",
   "metadata": {},
   "source": [
    "## Regressione lineare\n",
    "Regressione e residui"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "id": "dfab4331",
   "metadata": {},
   "outputs": [],
   "source": [
    "# Funzioni regressione\n",
    "\n",
    "def sigma_y_equiv(x, y, sigma_x, sigma_y):\n",
    "  # Stima iniziale di A con sola sigma_y\n",
    "  sy2 = sigma_y**2\n",
    "  Sw   = np.sum(1 / sy2)\n",
    "  Sx   = np.sum(x / sy2)\n",
    "  Sxx  = np.sum(x**2 / sy2)\n",
    "  Sy   = np.sum(y / sy2)\n",
    "  Sxy  = np.sum(x * y / sy2)\n",
    "  delta = Sxx * Sw - Sx**2\n",
    "  A_est = (Sxy * Sw - Sx * Sy) / delta\n",
    "\n",
    "  # Propagazione\n",
    "  sigma_eq = np.sqrt(sigma_y**2 + A_est**2 * sigma_x**2)\n",
    "  return sigma_eq\n",
    "\n",
    "\n",
    "def reg_lin(x, y, sigma_x, sigma_y):\n",
    "  x = np.asarray(x, dtype=float)\n",
    "  y = np.asarray(y, dtype=float)\n",
    "  sigma_x = np.asarray(sigma_x, dtype=float)\n",
    "  sigma_y = np.asarray(sigma_y, dtype=float)\n",
    "\n",
    "  # Propagazione errore x → y\n",
    "  sigma_y_eq = sigma_y_equiv(x, y, sigma_x, sigma_y)\n",
    "\n",
    "  # Somme pesate\n",
    "  w    = 1.0 / sigma_y_eq**2\n",
    "  Sw   = np.sum(w)\n",
    "  Sx   = np.sum(w * x)\n",
    "  Sxx  = np.sum(w * x**2)\n",
    "  Sy   = np.sum(w * y)\n",
    "  Sxy  = np.sum(w * x * y)\n",
    "  delta = Sxx * Sw - Sx**2\n",
    "\n",
    "  # Parametri\n",
    "  A      = (Sxy * Sw - Sx * Sy)  / delta\n",
    "  B      = (Sxx * Sy - Sxy * Sx) / delta\n",
    "  sigma_A = np.sqrt(Sw  / delta)\n",
    "  sigma_B = np.sqrt(Sxx / delta)\n",
    "  cov_AB  = -Sx / delta\n",
    "\n",
    "  # Chi quadro\n",
    "  x2  = np.sum((y - A * x - B)**2 / sigma_y_eq**2)\n",
    "  dof = len(x) - 2\n",
    "  P = stats.chi2.sf(x2, dof)\n",
    "\n",
    "  return A, B, sigma_A, sigma_B, cov_AB, x2, P"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "id": "5d7ca0a0",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Residuo:\n",
      "  r = x + B/A - y/A\n",
      "\n",
      "Formula LaTeX:\n",
      "  r       = x + \\frac{B}{A} - \\frac{y}{A}\n",
      "  sigma_r = \\sqrt{\\frac{A^{4} \\sigma_{x}^{2} + A^{2} \\left(\\sigma_{B}^{2} + \\sigma_{y}^{2}\\right) - 2 A cov_{AB} \\left(B - y\\right) + \\sigma_{A}^{2} \\left(B - y\\right)^{2}}{A^{4}}}\n"
     ]
    }
   ],
   "source": [
    "# Calcolo simbolico residui\n",
    "\n",
    "A, B, x, y = sp.symbols('A B x y', real=True)\n",
    "sigma_A, sigma_B, sigma_x, sigma_y = sp.symbols('sigma_A sigma_B sigma_x sigma_y', positive=True)\n",
    "cov_AB = sp.symbols('cov_AB', real=True)\n",
    "\n",
    "# Residuo: r = x - (y/A - B/A)\n",
    "r = x - (y / A - B / A)\n",
    "\n",
    "# Propagazione errore (con covarianza A,B)\n",
    "dr_dA  = sp.diff(r, A)\n",
    "dr_dB  = sp.diff(r, B)\n",
    "dr_dx  = sp.diff(r, x)\n",
    "dr_dy  = sp.diff(r, y)\n",
    "\n",
    "sigma_r  = sp.sqrt(\n",
    "  (dr_dA * sigma_A)**2 +\n",
    "  (dr_dB * sigma_B)**2 +\n",
    "  (dr_dx * sigma_x)**2 +\n",
    "  (dr_dy * sigma_y)**2 +\n",
    "  2 * dr_dA * dr_dB * cov_AB\n",
    ")\n",
    "\n",
    "# Funzioni numeriche\n",
    "r_fn      = sp.lambdify((x , y , A , B ), r, 'numpy')\n",
    "sigma_r_fn = sp.lambdify(\n",
    "  (x , y , A , B , sigma_x , sigma_y , sigma_A , sigma_B , cov_AB ),\n",
    "  sigma_r , 'numpy'\n",
    ")\n",
    "\n",
    "print(\"Residuo:\")\n",
    "print(f\"  r = {r }\")\n",
    "print(f\"\\nFormula LaTeX:\")\n",
    "print(f\"  r       = {sp.latex(r)}\")\n",
    "print(f\"  sigma_r = {sp.latex(sp.simplify(sigma_r))}\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "id": "cd68b201",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Ax + B : \n",
      "AC      = 3.2009 ± 0.0033\n",
      "BC      = 1161.4139 ± 0.4685\n",
      "cov_ABC = 0.001384\n",
      "chi²    = 4.3285\n",
      "P(chi², ∞)= 0.1148\n"
     ]
    }
   ],
   "source": [
    "# Regressione lineare\n",
    "\n",
    "AC, BC, uAC, uBC, covABC, chiC, PC = reg_lin(-dfCalibro[\"dx\"], dfCalibro[\"F\"], dfCalibro[\"udx\"], dfCalibro[\"uF\"])\n",
    "print(\"Ax + B : \")\n",
    "print(f\"AC      = {AC:.4f} ± {uAC:.4f}\")\n",
    "print(f\"BC      = {BC:.4f} ± {uBC:.4f}\")\n",
    "print(f\"cov_ABC = {covABC:.6f}\")\n",
    "print(f\"chi²    = {chiC:.4f}\")\n",
    "print(f\"P(chi², ∞)= {PC:.4f}\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "id": "68eb66dc",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "[encoded data, 63248 characters]",
      "text/plain": [
       "<Figure size 800x500 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "# Plot regressione\n",
    "\n",
    "SCALA = 50\n",
    "fig, ax = plt.subplots(figsize=(8, 5))\n",
    "\n",
    "x_data = -dfCalibro[\"dx\"]\n",
    "y_data =  dfCalibro[\"F\"]\n",
    "\n",
    "x_fit = np.linspace(x_data.min(), x_data.max(), 300)\n",
    "y_fit = AC * x_fit + BC\n",
    "\n",
    "ax.errorbar(\n",
    "    x_data, y_data,\n",
    "    xerr=SCALA * dfCalibro[\"udx\"], yerr=SCALA * dfCalibro[\"uF\"],\n",
    "    fmt='o', color=sns.color_palette()[0],\n",
    "    ecolor='gray', elinewidth=1, capsize=3,\n",
    "    markersize=5, label=f\"Dati (barre errore x{SCALA})\"\n",
    ")\n",
    "ax.plot(\n",
    "    x_fit, y_fit,\n",
    "    color='red', linewidth=1.5,\n",
    "    label=f\"$A={AC:.4f}\\\\pm{uAC:.4f}$\\n\"\n",
    "          f\"$B={BC:.2f}\\\\pm{uBC:.2f}$\\n\"\n",
    "          f\"$P(chi², ∞)= {PC:.4f}$\\n\"\n",
    ")\n",
    "\n",
    "sns.despine(ax=ax)\n",
    "ax.set_xlabel(r\"$- x$  [mm]\")\n",
    "ax.set_ylabel(\"F  [mN]\")\n",
    "ax.set_title(\"Fit lineare — Molla 2 (calibro)\")\n",
    "ax.legend(fontsize=9)\n",
    "ax.grid(True, linestyle=':', linewidth=0.5, alpha=0.7)\n",
    "\n",
    "plt.tight_layout()\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "id": "f98a3612",
   "metadata": {},
   "outputs": [],
   "source": [
    "# Calcolo numerico residui\n",
    "\n",
    "dfCalibro[\"r\"] = r_fn(\n",
    "  -dfCalibro[\"dx\"],\n",
    "  dfCalibro[\"F\"],\n",
    "  AC,\n",
    "  BC\n",
    ")\n",
    "\n",
    "dfCalibro[\"ur\"] = sigma_r_fn(\n",
    "  -dfCalibro[\"dx\"], dfCalibro[\"F\"],\n",
    "  AC, BC,\n",
    "  dfCalibro[\"udx\"], dfCalibro[\"uF\"],\n",
    "  uAC, uBC, covABC\n",
    ")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "id": "831a4ac6",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "[encoded data, 46048 characters]",
      "text/plain": [
       "<Figure size 800x500 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "# Plot residui\n",
    " \n",
    "fig, ax = plt.subplots(figsize=(8, 5))\n",
    "\n",
    "# Residui con barre d'errore\n",
    "ax.errorbar(\n",
    "    dfCalibro[\"F\"], dfCalibro[\"r\"],\n",
    "    xerr=dfCalibro[\"uF\"], yerr=dfCalibro[\"ur\"],\n",
    "    fmt='o', color=sns.color_palette()[0],\n",
    "    ecolor='gray', elinewidth=1, capsize=3,\n",
    "    markersize=5, label=\"Residui\"\n",
    ")\n",
    "\n",
    "# Linea dello zero\n",
    "ax.axhline(0, color='red', linestyle='--', linewidth=1)\n",
    "\n",
    "# Estetica\n",
    "sns.despine(ax=ax)\n",
    "ax.set_xlabel(\"F  [mN]\")\n",
    "ax.set_ylabel(r\"Residuo $x_i - \\left(\\frac{y_i}{A} - \\frac{B}{A}\\right)$  [mm]\")\n",
    "ax.set_title(\"Residui della regressione — Molla 2 (calibro)\")\n",
    "ax.legend()\n",
    "ax.grid(True, linestyle=':', linewidth=0.5, alpha=0.7)\n",
    "\n",
    "plt.tight_layout()\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "id": "5643144a",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\n",
      "Probabilità chi quadro con uR invece di sigmaY_equiv\n",
      "P(chi², ∞)= 0.1900\n"
     ]
    }
   ],
   "source": [
    "# Chi2 alternativo\n",
    "\n",
    "x2  = np.sum(dfCalibro['r']**2 / dfCalibro['ur']**2)\n",
    "dof = 4 - 2\n",
    "P = stats.chi2.sf(x2, dof)\n",
    "print('\\nProbabilità chi quadro con uR invece di sigmaY_equiv')\n",
    "print(f\"P(chi², ∞)= {P:.4f}\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "1b104df9",
   "metadata": {},
   "source": [
    "# Sonar statico"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "4efaca0d",
   "metadata": {},
   "source": [
    "## Sonar senza correzione $v_{suono}$"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "414d21e7",
   "metadata": {},
   "source": [
    "### Import dei dati, medie e incertezze\n",
    "- masse, $\\omega$, c, t trattati come prima"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "id": "d6195b96",
   "metadata": {},
   "outputs": [],
   "source": [
    "dfSonar_raw = pd.read_csv(r'molla2Sonar.csv')\n",
    "\n",
    "ERR_OMEGA = 0.000001 / np.sqrt(12)\n",
    "ERR_C = 0.000001 / np.sqrt(12)\n",
    "ERR_CRONOMETRO = 0.01 / np.sqrt(12)\n",
    "\n",
    "# Tutto trattato esattamente come prima\n",
    "dfSonar = pd.DataFrame()\n",
    "dfSonar = dfSonar.acc.calcola_stats(dfSonar_raw, \"m\",  ERR_BILANCIA)\n",
    "dfSonar = dfSonar.acc.calcola_stats(dfSonar_raw, \"w\",  ERR_OMEGA)\n",
    "dfSonar = dfSonar.acc.calcola_stats(dfSonar_raw, \"c\",  ERR_C)\n",
    "dfSonar = dfSonar.acc.calcola_stats(dfSonar_raw, \"t\",  ERR_CRONOMETRO)\n",
    "\n",
    "# Aggiunta delle forze\n",
    "dfSonar[\"F\"]  = F_fn(dfSonar[\"m\"],  G)\n",
    "dfSonar[\"uF\"] = uF_fn(dfSonar[\"m\"], dfSonar[\"um\"], G, uG)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "id": "02e2d183",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "application/vnd.jupyter.widget-view+json": {
       "model_id": "0ee5a718b7a14194847b0a7f62c703ce",
       "version_major": 2,
       "version_minor": 0
      },
      "text/plain": [
       "Sheet(cells=(Cell(column_end=0, column_start=0, row_end=4, row_start=0, squeeze_row=False, type='numeric', val…"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "sheet = ipysheet.from_dataframe(dfSonar)\n",
    "\n",
    "display(sheet)\n",
    "# dfSonar.head(4).to_json(orient=\"records\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "e4e07ecd",
   "metadata": {},
   "source": [
    "### Regressione lineare"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "id": "06f9ccef",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Ax + B : \n",
      "AS      = 3.2192 ± 0.0027\n",
      "BS      = 2042.5203 ± 1.0326\n",
      "cov_ABS = 0.002760\n",
      "chi²    = 9.0319\n",
      "P(chi², ∞)= 0.0289\n"
     ]
    }
   ],
   "source": [
    "# Regressione lineare\n",
    "\n",
    "AS, BS, uAS, uBS, covABS, chiS, PS = reg_lin(-dfSonar[\"c\"], dfSonar[\"F\"], dfSonar[\"uc\"], dfSonar[\"uF\"])\n",
    "print(\"Ax + B : \")\n",
    "print(f\"AS      = {AS:.4f} ± {uAS:.4f}\")\n",
    "print(f\"BS      = {BS:.4f} ± {uBS:.4f}\")\n",
    "print(f\"cov_ABS = {covABS:.6f}\")\n",
    "print(f\"chi²    = {chiS:.4f}\")\n",
    "print(f\"P(chi², ∞)= {PS:.4f}\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "id": "75653d7a",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "[encoded data, 57328 characters]",
      "text/plain": [
       "<Figure size 800x500 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "# Plot regressione\n",
    "\n",
    "SCALA = 100\n",
    "fig, ax = plt.subplots(figsize=(8, 5))\n",
    "\n",
    "x_data = -dfSonar[\"c\"]\n",
    "y_data =  dfSonar[\"F\"]\n",
    "\n",
    "x_fit = np.linspace(x_data.min(), x_data.max(), 300)\n",
    "y_fit = AS * x_fit + BS\n",
    "\n",
    "ax.errorbar(\n",
    "    x_data, y_data,\n",
    "    xerr=SCALA * dfSonar[\"uc\"], yerr=SCALA * dfSonar[\"uF\"],\n",
    "    fmt='o', color=sns.color_palette()[0],\n",
    "    ecolor='gray', elinewidth=1, capsize=3,\n",
    "    markersize=5, label=f\"Dati (barre errore x{SCALA})\"\n",
    ")\n",
    "ax.plot(\n",
    "    x_fit, y_fit,\n",
    "    color='red', linewidth=1.5,\n",
    "    label=f\"$A={AS:.4f}\\\\pm{uAS:.4f}$\\n\"\n",
    "          f\"$B={BS:.1f}\\\\pm{uBS:.1f}$\\n\"\n",
    "          f\"$P(chi², ∞)= {PS:.4f}$\\n\"\n",
    ")\n",
    "\n",
    "sns.despine(ax=ax)\n",
    "ax.set_xlabel(r\"$- x$  [mm]\")\n",
    "ax.set_ylabel(\"F  [mN]\")\n",
    "ax.set_title(\"Fit lineare — Molla 2 (sonar statico senza correzione)\")\n",
    "ax.legend(fontsize=9)\n",
    "ax.grid(True, linestyle=':', linewidth=0.5, alpha=0.7)\n",
    "\n",
    "plt.tight_layout()\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "id": "09445aac",
   "metadata": {},
   "outputs": [],
   "source": [
    "# Calcolo numerico residui\n",
    "\n",
    "dfSonar[\"r\"] = r_fn(\n",
    "  -dfSonar[\"c\"],\n",
    "  dfSonar[\"F\"],\n",
    "  AS,\n",
    "  BS\n",
    ")\n",
    "\n",
    "dfSonar[\"ur\"] = sigma_r_fn(\n",
    "  -dfSonar[\"c\"], dfSonar[\"F\"],\n",
    "  AS, BS,\n",
    "  dfSonar[\"uc\"], dfSonar[\"uF\"],\n",
    "  uAS, uBS, covABS\n",
    ")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "id": "1ecf9ab2",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "[encoded data, 50292 characters]",
      "text/plain": [
       "<Figure size 800x500 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "# Plot Residui\n",
    "\n",
    "fig, ax = plt.subplots(figsize=(8, 5))\n",
    "\n",
    "# Residui con barre d'errore\n",
    "ax.errorbar(\n",
    "    dfSonar[\"F\"], dfSonar[\"r\"],\n",
    "    xerr=dfSonar[\"uF\"], yerr=dfSonar[\"ur\"],\n",
    "    fmt='o', color=sns.color_palette()[0],\n",
    "    ecolor='gray', elinewidth=1, capsize=3,\n",
    "    markersize=5, label=\"Residui\"\n",
    ")\n",
    "\n",
    "# Linea dello zero\n",
    "ax.axhline(0, color='red', linestyle='--', linewidth=1)\n",
    "\n",
    "# Estetica\n",
    "sns.despine(ax=ax)\n",
    "ax.set_xlabel(\"F  [mN]\")\n",
    "ax.set_ylabel(r\"Residuo $x_i - \\left(\\frac{y_i}{A} - \\frac{B}{A}\\right)$  [mm]\")\n",
    "ax.set_title(\"Residui della regressione — Molla 2 (sonar statico senza correzione)\")\n",
    "ax.legend()\n",
    "ax.grid(True, linestyle=':', linewidth=0.5, alpha=0.7)\n",
    "\n",
    "plt.tight_layout()\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "affcb57a",
   "metadata": {},
   "source": [
    "## Sonar con correzione $v_{suono}$\n",
    "- La velocità del suono dipende dalla temperatura -> anche la distanza misurata dal sonar\n",
    "- Formula di Cramer 1993\n",
    "- !! Io (Giulia) ho usato un'altra formula, non capisco il perchè di quella di Jacopo"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "id": "4088453c",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "c = 0.049862877088008*c_raw*v0/sqrt(T + 273.15)\n",
      "sigma_c = v0*sqrt(0.000621576627873448*c_raw**2*sigma_T**2 + 0.00248630651149379*sigma_c_raw**2*(T + 273.15)**2)/(T + 273.15)**(3/2)\n",
      "\n",
      "Formula LaTeX:\n",
      "c = \\frac{0.049862877088008 c_{raw} v_{0}}{\\sqrt{T + 273.15}}\n",
      "sigma_c = \\frac{v_{0} \\sqrt{0.000621576627873448 c_{raw}^{2} \\sigma_{T}^{2} + 0.00248630651149379 \\sigma_{c raw}^{2} \\left(T + 273.15\\right)^{2}}}{\\left(T + 273.15\\right)^{\\frac{3}{2}}}\n"
     ]
    }
   ],
   "source": [
    "# Funzioni c\n",
    "\n",
    "# simboli\n",
    "v0, T, c_raw = sp.symbols('v0 T c_raw', positive=True)\n",
    "sigma_T, sigma_c_raw = sp.symbols('sigma_T sigma_c_raw', positive=True)\n",
    "\n",
    "# velocità corretta e posizione\n",
    "# v = 331.3 * sp.sqrt(1 + T / 273.15)\n",
    "v = 20.055 * sp.sqrt(T + 273.15)\n",
    "c = c_raw * v0 / v\n",
    "\n",
    "# derivate parziali\n",
    "dc_dcraw = sp.diff(c, c_raw)\n",
    "dc_dT    = sp.diff(c, T)\n",
    "\n",
    "sigma_c = sp.sqrt((dc_dcraw * sigma_c_raw)**2 + (dc_dT * sigma_T)**2)\n",
    "\n",
    "print(\"c =\", c)\n",
    "print(\"sigma_c =\", sigma_c.simplify())\n",
    "print(\"\\nFormula LaTeX:\")\n",
    "print(f\"c = {sp.latex(c)}\")\n",
    "print(f\"sigma_c = {sp.latex(sigma_c.simplify())}\")\n",
    "\n",
    "# funzioni numeriche\n",
    "c_fn  = sp.lambdify((c_raw, T, v0), c, 'numpy')\n",
    "uc_fn = sp.lambdify((c_raw, sigma_c_raw, T, sigma_T, v0), sigma_c, 'numpy')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 21,
   "id": "1584a5d4",
   "metadata": {},
   "outputs": [],
   "source": [
    "# Calcolo numerico c\n",
    "\n",
    "Temperatura = (23.6+21.2) / 2\n",
    "Temperatura1 = 21.2\n",
    "Temperatura2 = 23.6\n",
    "uTemperatura = (23.6-21.2) / np.sqrt(12)\n",
    "Velocita_impostata = 343.0\n",
    "\n",
    "dfSonarCorrezione = dfSonar.copy()\n",
    "\n",
    "dfSonarCorrezione['c']  =  c_fn(dfSonarCorrezione['c'], Temperatura, Velocita_impostata)\n",
    "dfSonarCorrezione['uc'] = uc_fn(dfSonarCorrezione['c'], dfSonarCorrezione['uc'],\n",
    "                      Temperatura, uTemperatura,\n",
    "                      Velocita_impostata)\n",
    "dfSonarCorrezione['cA']  =  c_fn(dfSonarCorrezione['c'], Temperatura1, Velocita_impostata)\n",
    "dfSonarCorrezione['cB']  =  c_fn(dfSonarCorrezione['c'], Temperatura2, Velocita_impostata)\n",
    "dfSonarCorrezione['vecchioC'] = dfSonar['c']\n",
    "dfSonarCorrezione['vecchioUc'] = dfSonar['uc']"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "id": "ac4860fa",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "application/vnd.jupyter.widget-view+json": {
       "model_id": "b540b35e61894ffeb58f5f85aecfb401",
       "version_major": 2,
       "version_minor": 0
      },
      "text/plain": [
       "Sheet(cells=(Cell(column_end=0, column_start=0, row_end=4, row_start=0, squeeze_row=False, type='numeric', val…"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "sheet = ipysheet.from_dataframe(dfSonarCorrezione)\n",
    "\n",
    "display(sheet)\n",
    "# dfSonar.head(4).to_json(orient=\"records\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "74f92463",
   "metadata": {},
   "source": [
    "### Regressione lineare"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 23,
   "id": "8917049c",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Fit completo:   chi²=9.03,  P=0.0289\n",
      "Temperatura :  chi²=0.952,  P=0.8129\n",
      "\n",
      "A:  3.2192 ± 0.0027  to  3.2390 ± 0.0076\n",
      "B:  2042.5203 ± 1.0326  to  2043.7514 ± 2.5703\n"
     ]
    }
   ],
   "source": [
    "#Regressione lineare\n",
    "\n",
    "AS2, BS2, uAS2, uBS2, covABS2, chiS2, PS2 = reg_lin(-dfSonarCorrezione[\"c\"], dfSonarCorrezione[\"F\"], dfSonarCorrezione[\"uc\"], dfSonarCorrezione[\"uF\"])\n",
    "\n",
    "print(f\"Fit completo:   chi²={chiS:.2f},  P={PS:.4f}\")\n",
    "print(f\"Temperatura :  chi²={chiS2:.3f},  P={PS2:.4f}\")\n",
    "print()\n",
    "print(f\"A:  {AS:.4f} ± {uAS:.4f}  to  {AS2:.4f} ± {uAS2:.4f}\")\n",
    "print(f\"B:  {BS:.4f} ± {uBS:.4f}  to  {BS2:.4f} ± {uBS2:.4f}\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 24,
   "id": "d5646b8c",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "[encoded data, 63820 characters]",
      "text/plain": [
       "<Figure size 800x500 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "# Plot regressione\n",
    "\n",
    "SCALA = 50\n",
    "fig, ax = plt.subplots(figsize=(8, 5))\n",
    "\n",
    "x_data = -dfSonarCorrezione[\"c\"]\n",
    "y_data =  dfSonarCorrezione[\"F\"]\n",
    "\n",
    "x_fit = np.linspace(x_data.min(), x_data.max(), 300)\n",
    "y_fit = AS2 * x_fit + BS2\n",
    "\n",
    "ax.errorbar(\n",
    "    x_data, y_data,\n",
    "    xerr=SCALA * dfSonarCorrezione[\"uc\"], yerr=SCALA * dfSonarCorrezione[\"uF\"],\n",
    "    fmt='o', color=sns.color_palette()[0],\n",
    "    ecolor='gray', elinewidth=1, capsize=3,\n",
    "    markersize=5, label=f\"Dati (barre errore x{SCALA})\"\n",
    ")\n",
    "ax.plot(\n",
    "    x_fit, y_fit,\n",
    "    color='red', linewidth=1.5,\n",
    "    label=f\"$A={AS2:.4f}\\\\pm{uAS:.4f}$\\n\"\n",
    "          f\"$B={BS2:.1f}\\\\pm{uBS:.1f}$\\n\"\n",
    "          f\"$P(chi², ∞)= {PS2:.4f}$\\n\"\n",
    ")\n",
    "\n",
    "sns.despine(ax=ax)\n",
    "ax.set_xlabel(r\"$- x$  [mm]\")\n",
    "ax.set_ylabel(\"F  [mN]\")\n",
    "ax.set_title(\"Fit lineare — Molla 2 (sonar statico con correzione)\")\n",
    "ax.legend(fontsize=9)\n",
    "ax.grid(True, linestyle=':', linewidth=0.5, alpha=0.7)\n",
    "\n",
    "plt.tight_layout()\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 25,
   "id": "e35a9456",
   "metadata": {},
   "outputs": [],
   "source": [
    "# Calcolo numerico residui\n",
    "\n",
    "dfSonarCorrezione[\"r\"] = r_fn(\n",
    "  -dfSonarCorrezione[\"c\"],\n",
    "  dfSonarCorrezione[\"F\"],\n",
    "  AS2,\n",
    "  BS2\n",
    ")\n",
    "\n",
    "dfSonarCorrezione[\"ur\"] = sigma_r_fn(\n",
    "  -dfSonarCorrezione[\"c\"], dfSonarCorrezione[\"F\"],\n",
    "  AS2, BS2,\n",
    "  dfSonarCorrezione[\"uc\"], dfSonarCorrezione[\"uF\"],\n",
    "  uAS2, uBS2, covABS2\n",
    ")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 26,
   "id": "8de2a48e",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "[encoded data, 55392 characters]",
      "text/plain": [
       "<Figure size 800x500 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "# Plot residui\n",
    "\n",
    "fig, ax = plt.subplots(figsize=(8, 5))\n",
    "\n",
    "# Residui con barre d'errore\n",
    "ax.errorbar(\n",
    "    dfSonarCorrezione[\"F\"], dfSonarCorrezione[\"r\"],\n",
    "    xerr=dfSonarCorrezione[\"uF\"], yerr=dfSonarCorrezione[\"ur\"],\n",
    "    fmt='o', color=sns.color_palette()[0],\n",
    "    ecolor='gray', elinewidth=1, capsize=3,\n",
    "    markersize=5, label=\"Residui\"\n",
    ")\n",
    "\n",
    "# Linea dello zero\n",
    "ax.axhline(0, color='red', linestyle='--', linewidth=1)\n",
    "\n",
    "# Estetica\n",
    "sns.despine(ax=ax)\n",
    "ax.set_xlabel(\"F  [mN]\")\n",
    "ax.set_ylabel(r\"Residuo $x_i - \\left(\\frac{y_i}{A} - \\frac{B}{A}\\right)$  [mm]\")\n",
    "ax.set_title(\"Residui della regressione — Molla 2 (sonar statico con correzione)\")\n",
    "ax.legend()\n",
    "ax.grid(True, linestyle=':', linewidth=0.5, alpha=0.7)\n",
    "\n",
    "plt.tight_layout()\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "b575ad7d",
   "metadata": {},
   "source": [
    "# Sonar dinamico\n",
    "Ancora non abbiamo il parametro $\\alpha$, quindi useremo $\\alpha = \\frac 1 3$. Lo imposto nel csv così è più facile da cambiare con il metodo della molla\n",
    "- !! Succede qualcosa di strano con Meq"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 27,
   "id": "af6143df",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Massa molla = 15.4300 ± 0.0029\n"
     ]
    }
   ],
   "source": [
    "# Calcolo numerico massa molla\n",
    "\n",
    "dfMasse_raw = pd.DataFrame([[15.43, 15.43, 15.43]], columns=[\"m1\", \"m2\", \"m3\"])\n",
    "\n",
    "dfMasse = pd.DataFrame()\n",
    "dfMasse = dfMasse.acc.calcola_stats(dfMasse_raw, \"m\",  ERR_BILANCIA)\n",
    "\n",
    "massaMolla  = dfMasse.m[0]\n",
    "umassaMolla = dfMasse.um[0]\n",
    "print(f\"Massa molla = {massaMolla:.4f} ± {umassaMolla:.4f}\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 28,
   "id": "a1e69bd3",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "1/Meq = 1000/(alp*m_molla + m_osc)\n",
      "sigma_1/Meq = 1000*sqrt(alp**2*sigma_m_molla**2 + m_molla**2*sigma_alp**2 + sigma_m_osc**2)/(alp*m_molla + m_osc)**2\n",
      "\n",
      "Formula LaTeX:\n",
      "1/Meq = \\frac{1000}{alp m_{molla} + m_{osc}}\n",
      "sigma_1/Meq = \\frac{1000 \\sqrt{alp^{2} \\sigma_{m molla}^{2} + m_{molla}^{2} \\sigma_{alp}^{2} + \\sigma_{m osc}^{2}}}{\\left(alp m_{molla} + m_{osc}\\right)^{2}}\n"
     ]
    }
   ],
   "source": [
    "# Calcolo simbolico Meq\n",
    "\n",
    "# simboli\n",
    "m_osc, alp, m_molla = sp.symbols('m_osc alp m_molla', positive=True)\n",
    "sigma_m_osc, sigma_alp, sigma_m_molla = sp.symbols('sigma_m_osc sigma_alp sigma_m_molla', positive=True)\n",
    "\n",
    "# massa equivalente\n",
    "Meq = 1 / (m_osc + alp * m_molla) * 1000\n",
    "\n",
    "# derivate parziali\n",
    "dMeq_dm_osc   = sp.diff(Meq, m_osc)\n",
    "dMeq_dalp     = sp.diff(Meq, alp)\n",
    "dMeq_dm_molla = sp.diff(Meq, m_molla)\n",
    "\n",
    "sigma_Meq = sp.sqrt(\n",
    "    (dMeq_dm_osc   * sigma_m_osc  )**2 +\n",
    "    (dMeq_dalp     * sigma_alp    )**2 +\n",
    "    (dMeq_dm_molla * sigma_m_molla)**2\n",
    ")\n",
    "\n",
    "print(\"1/Meq =\", Meq)\n",
    "print(\"sigma_1/Meq =\", sigma_Meq.simplify())\n",
    "print(\"\\nFormula LaTeX:\")\n",
    "print(f\"1/Meq = {sp.latex(Meq)}\")\n",
    "print(f\"sigma_1/Meq = {sp.latex(sigma_Meq.simplify())}\")\n",
    "\n",
    "# funzioni numeriche\n",
    "Meq_fn  = sp.lambdify((m_osc, alp, m_molla), Meq, 'numpy')\n",
    "uMeq_fn = sp.lambdify((m_osc, sigma_m_osc, alp, sigma_alp, m_molla, sigma_m_molla), sigma_Meq, 'numpy')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 29,
   "id": "56679fc4",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "w2 = w**2\n",
      "sigma_w2 = 2*sigma_w*w\n",
      "\n",
      "Formula LaTeX:\n",
      "w2 = w^{2}\n",
      "sigma_w2 = 2 \\sigma_{w} w\n"
     ]
    }
   ],
   "source": [
    "# Calcolo simbolico w^2\n",
    "\n",
    "# simboli\n",
    "w = sp.symbols('w', positive=True)\n",
    "sigma_w = sp.symbols('sigma_w', positive=True)\n",
    "\n",
    "# omega^2\n",
    "w2 = w**2\n",
    "\n",
    "# derivata parziale\n",
    "dw2_dw = sp.diff(w2, w)\n",
    "\n",
    "sigma_w2 = sp.sqrt((dw2_dw * sigma_w)**2)\n",
    "\n",
    "print(\"w2 =\", w2)\n",
    "print(\"sigma_w2 =\", sigma_w2.simplify())\n",
    "print(\"\\nFormula LaTeX:\")\n",
    "print(f\"w2 = {sp.latex(w2)}\")\n",
    "print(f\"sigma_w2 = {sp.latex(sigma_w2.simplify())}\")\n",
    "\n",
    "# funzioni numeriche\n",
    "w2_fn  = sp.lambdify((w), w2, 'numpy')\n",
    "uw2_fn = sp.lambdify((w, sigma_w), sigma_w2, 'numpy')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 30,
   "id": "455271a9",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "application/vnd.jupyter.widget-view+json": {
       "model_id": "371558377daf421fbae4ee1e04dd9b3a",
       "version_major": 2,
       "version_minor": 0
      },
      "text/plain": [
       "Sheet(cells=(Cell(column_end=0, column_start=0, row_end=4, row_start=0, squeeze_row=False, type='numeric', val…"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "# Calcolo numerico Meq e w^2\n",
    "\n",
    "dfSonar['alp'] = 1/3\n",
    "dfSonar['ualp'] = 0.000000000001\n",
    "\n",
    "dfSonar['1/Meq'] = Meq_fn(dfSonar['m'], dfSonar['alp'], massaMolla)\n",
    "dfSonar['u1/Meq']= uMeq_fn(dfSonar['m'], dfSonar['um'], dfSonar['alp'], dfSonar['ualp'], massaMolla, umassaMolla)\n",
    "\n",
    "dfSonar['Omega2'] = w2_fn(dfSonar['w'])\n",
    "dfSonar['uOmega2']= uw2_fn(dfSonar['w'], dfSonar['uw'])\n",
    "\n",
    "\n",
    "sheet = ipysheet.from_dataframe(dfSonar)\n",
    "display(sheet)\n",
    "# dfSonar.head(4).to_json(orient=\"records\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "30a9d21f",
   "metadata": {},
   "source": [
    "## Regressione lineare"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 31,
   "id": "02119d66",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Ax + B : \n",
      "AD      = 3.1496 ± 0.0009\n",
      "BD      = 0.7065 ± 0.0094\n",
      "cov_ABD = -0.000008\n",
      "chi²    = 15.1289\n",
      "P(chi², ∞)= 0.0017\n"
     ]
    }
   ],
   "source": [
    "# Regressione lineare\n",
    "\n",
    "AD, BD, uAD, uBD, covABD, chiD, PD = reg_lin( dfSonar[\"1/Meq\"], dfSonar[\"Omega2\"], dfSonar[\"u1/Meq\"], dfSonar[\"uOmega2\"])\n",
    "\n",
    "print(\"Ax + B : \")\n",
    "print(f\"AD      = {AD:.4f} ± {uAD:.4f}\")\n",
    "print(f\"BD      = {BD:.4f} ± {uBD:.4f}\")\n",
    "print(f\"cov_ABD = {covABD:.6f}\")\n",
    "print(f\"chi²    = {chiD:.4f}\")\n",
    "print(f\"P(chi², ∞)= {PD:.4f}\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 32,
   "id": "de571f32",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "[encoded data, 62816 characters]",
      "text/plain": [
       "<Figure size 800x500 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "# Plot regressione\n",
    "\n",
    "SCALA = 1000\n",
    "fig, ax = plt.subplots(figsize=(8, 5))\n",
    "\n",
    "x_data =  dfSonar[\"1/Meq\"]\n",
    "y_data =  dfSonar[\"Omega2\"]\n",
    "\n",
    "x_fit = np.linspace(0, x_data.max(), 300)\n",
    "y_fit = AD * x_fit + BD\n",
    "\n",
    "ax.errorbar(\n",
    "    x_data, y_data,\n",
    "    xerr=SCALA * dfSonar[\"u1/Meq\"], yerr=SCALA * dfSonar[\"uOmega2\"],\n",
    "    fmt='o', color=sns.color_palette()[0],\n",
    "    ecolor='gray', elinewidth=1, capsize=3,\n",
    "    markersize=5, label=f\"Dati (barre errore x{SCALA})\"\n",
    ")\n",
    "ax.plot(\n",
    "    x_fit, y_fit,\n",
    "    color='red', linewidth=1.5,\n",
    "    label=f\"$A={AD:.5f}\\\\pm{uAD:.5f}$\\n\"\n",
    "          f\"$B={BD:.4f}\\\\pm{uBD:.4f}$\\n\"\n",
    "          f\"P(chi², ∞)= {PD:.4f}\\n\"\n",
    ")\n",
    "\n",
    "\n",
    "plt.xlim(left=0)\n",
    "plt.ylim(bottom=0)\n",
    "\n",
    "sns.despine(ax=ax)\n",
    "ax.set_xlabel(r\"1/Meq  [Kg$^{-1}$]\")\n",
    "ax.set_ylabel(r\"$\\omega^2$  [s$^{-2}$]\")\n",
    "ax.set_title(\"Fit lineare — Molla 2 (sonar dinamico)\")\n",
    "ax.legend(fontsize=9)\n",
    "ax.grid(True, linestyle=':', linewidth=0.5, alpha=0.7)\n",
    "\n",
    "plt.tight_layout()\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 33,
   "id": "96f12fe6",
   "metadata": {},
   "outputs": [],
   "source": [
    "# Calcolo numerico residui\n",
    "\n",
    "dfSonar[\"R\"] = r_fn(\n",
    "  dfSonar[\"1/Meq\"],\n",
    "  dfSonar[\"Omega2\"],\n",
    "  AD,\n",
    "  BD\n",
    ")\n",
    "\n",
    "dfSonar[\"uR\"] = sigma_r_fn(\n",
    "  dfSonar[\"1/Meq\"], dfSonar[\"Omega2\"],\n",
    "  AD, BD,\n",
    "  dfSonar[\"u1/Meq\"], dfSonar[\"uOmega2\"],\n",
    "  uAD, uBD, covABD\n",
    ")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 34,
   "id": "c87033e0",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "[encoded data, 58080 characters]",
      "text/plain": [
       "<Figure size 800x500 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "# Plot residui\n",
    "\n",
    "fig, ax = plt.subplots(figsize=(8, 5))\n",
    "\n",
    "# Residui con barre d'errore\n",
    "ax.errorbar(\n",
    "    dfSonar[\"Omega2\"], dfSonar[\"R\"],\n",
    "    xerr=dfSonar[\"uOmega2\"], yerr=dfSonar[\"uR\"],\n",
    "    fmt='o', color=sns.color_palette()[0],\n",
    "    ecolor='gray', elinewidth=1, capsize=3,\n",
    "    markersize=5, label=\"Residui\"\n",
    ")\n",
    "\n",
    "# Linea dello zero\n",
    "ax.axhline(0, color='red', linestyle='--', linewidth=1)\n",
    "\n",
    "# Estetica\n",
    "sns.despine(ax=ax)\n",
    "ax.set_xlabel(r\"$\\omega^2$  [s$^{-2}$]\")\n",
    "ax.set_ylabel(r\"Residuo $x_i - \\left(\\frac{y_i}{A} - \\frac{B}{A}\\right)$  [Kg$^{-1}$]\")\n",
    "ax.set_title(\"Residui della regressione — Molla 2 (sonar dinamico)\")\n",
    "ax.legend()\n",
    "ax.grid(True, linestyle=':', linewidth=0.5, alpha=0.7)\n",
    "\n",
    "plt.tight_layout()\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "d35498c5",
   "metadata": {},
   "source": [
    "# Cronometro"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 35,
   "id": "97921cfc",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "wt = 38*pi/w\n",
      "w2t = 1444*pi**2/w**2\n",
      "sigma_w2t = 2888*pi**2*sigma_t/w**3\n",
      "\n",
      "Formula LaTeX:\n",
      "w2t = \\frac{1444 \\pi^{2}}{w^{2}}\n",
      "sigma_w2t = \\frac{2888 \\pi^{2} \\sigma_{t}}{w^{3}}\n"
     ]
    }
   ],
   "source": [
    "# Calcolo w^2 da t/20\n",
    "\n",
    "# simboli\n",
    "t = sp.symbols('w', positive=True)\n",
    "sigma_t = sp.symbols('sigma_t', positive=True)\n",
    "\n",
    "# omega^2\n",
    "wt = (2 * sp.pi) / (t/19)\n",
    "w2t = wt**2\n",
    "\n",
    "# derivata parziale\n",
    "dw2t_dt = sp.diff(w2t, t)\n",
    "\n",
    "sigma_w2t = sp.sqrt((dw2t_dt * sigma_t)**2)\n",
    "\n",
    "print(\"wt =\", wt)\n",
    "print(\"w2t =\", w2t)\n",
    "print(\"sigma_w2t =\", sigma_w2t.simplify())\n",
    "print(\"\\nFormula LaTeX:\")\n",
    "print(f\"w2t = {sp.latex(w2t)}\")\n",
    "print(f\"sigma_w2t = {sp.latex(sigma_w2t.simplify())}\")\n",
    "\n",
    "# funzioni numeriche\n",
    "w2t_fn  = sp.lambdify((t), w2t, 'numpy')\n",
    "uw2t_fn = sp.lambdify((t, sigma_t), sigma_w2t, 'numpy')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 36,
   "id": "0b3f8a4e",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "application/vnd.jupyter.widget-view+json": {
       "model_id": "57acfdfd8a2242a9bb2338407fefd332",
       "version_major": 2,
       "version_minor": 0
      },
      "text/plain": [
       "Sheet(cells=(Cell(column_end=0, column_start=0, row_end=4, row_start=0, squeeze_row=False, type='numeric', val…"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "dfSonar['Omega2t'] = w2t_fn(dfSonar['t'])\n",
    "dfSonar['uOmega2t']= uw2t_fn(dfSonar['t'], dfSonar['ut'])\n",
    "\n",
    "sheet = ipysheet.from_dataframe(dfSonar)\n",
    "display(sheet)\n",
    "# dfSonar.head(4).to_json(orient=\"records\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 37,
   "id": "0421b1cb",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Ax + B : \n",
      "ACr      = 3.0896 ± 0.0419\n",
      "BCr      = 1.1894 ± 0.4871\n",
      "cov_ABCr = -0.019876\n",
      "chi²    = 3.2171\n",
      "P(chi², ∞)= 0.3593\n"
     ]
    }
   ],
   "source": [
    "# Regressione lineare\n",
    "\n",
    "ACr, BCr, uACr, uBCr, covABCr, chiCr, PCr = reg_lin( dfSonar[\"1/Meq\"], dfSonar[\"Omega2t\"], dfSonar[\"u1/Meq\"], dfSonar[\"uOmega2t\"])\n",
    "\n",
    "print(\"Ax + B : \")\n",
    "print(f\"ACr      = {ACr:.4f} ± {uACr:.4f}\")\n",
    "print(f\"BCr      = {BCr:.4f} ± {uBCr:.4f}\")\n",
    "print(f\"cov_ABCr = {covABCr:.6f}\")\n",
    "print(f\"chi²    = {chiCr:.4f}\")\n",
    "print(f\"P(chi², ∞)= {PCr:.4f}\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 38,
   "id": "739c2c88",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "[encoded data, 61060 characters]",
      "text/plain": [
       "<Figure size 800x500 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "SCALA = 50\n",
    "fig, ax = plt.subplots(figsize=(8, 5))\n",
    "\n",
    "x_data =  dfSonar[\"1/Meq\"]\n",
    "y_data =  dfSonar[\"Omega2t\"]\n",
    "\n",
    "x_fit = np.linspace(0, x_data.max(), 300)\n",
    "y_fit = ACr * x_fit + BCr\n",
    "\n",
    "ax.errorbar(\n",
    "    x_data, y_data,\n",
    "    xerr=SCALA * dfSonar[\"u1/Meq\"], yerr=SCALA * dfSonar[\"uOmega2t\"],\n",
    "    fmt='o', color=sns.color_palette()[0],\n",
    "    ecolor='gray', elinewidth=1, capsize=3,\n",
    "    markersize=5, label=f\"Dati (barre errore x{SCALA})\"\n",
    ")\n",
    "ax.plot(\n",
    "    x_fit, y_fit,\n",
    "    color='red', linewidth=1.5,\n",
    "    label=f\"$A={ACr:.3f}\\\\pm{uACr:.3f}$\\n\"\n",
    "          f\"$B={BCr:.2f}\\\\pm{uBCr:.2f}$\\n\"\n",
    "          f\"P(chi², ∞)= {PCr:.4f}\\n\"\n",
    ")\n",
    "\n",
    "\n",
    "plt.xlim(left=0)\n",
    "plt.ylim(bottom=0)\n",
    "\n",
    "sns.despine(ax=ax)\n",
    "ax.set_xlabel(r\"1/Meq  [Kg$^{-1}$]\")\n",
    "ax.set_ylabel(r\"$\\omega^2$  [s$^{-2}$]\")\n",
    "ax.set_title(\"Fit lineare — Molla 2 (cronometro)\")\n",
    "ax.legend(fontsize=9)\n",
    "ax.grid(True, linestyle=':', linewidth=0.5, alpha=0.7)\n",
    "\n",
    "plt.tight_layout()\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 39,
   "id": "2fb7140a",
   "metadata": {},
   "outputs": [],
   "source": [
    "# Residui\n",
    "\n",
    "dfSonar[\"Rc\"] = r_fn(\n",
    "  dfSonar[\"1/Meq\"],\n",
    "  dfSonar[\"Omega2t\"],\n",
    "  ACr,\n",
    "  BCr\n",
    ")\n",
    "\n",
    "dfSonar[\"uRc\"] = sigma_r_fn(\n",
    "  dfSonar[\"1/Meq\"], dfSonar[\"Omega2t\"],\n",
    "  ACr, BCr,\n",
    "  dfSonar[\"u1/Meq\"], dfSonar[\"uOmega2t\"],\n",
    "  uACr, uBCr, covABCr\n",
    ")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 40,
   "id": "b44b497b",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "[encoded data, 44268 characters]",
      "text/plain": [
       "<Figure size 800x500 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "fig, ax = plt.subplots(figsize=(8, 5))\n",
    "\n",
    "# Residui con barre d'errore\n",
    "ax.errorbar(\n",
    "    dfSonar[\"Omega2t\"], dfSonar[\"Rc\"],\n",
    "    xerr=dfSonar[\"uOmega2t\"], yerr=dfSonar[\"uRc\"],\n",
    "    fmt='o', color=sns.color_palette()[0],\n",
    "    ecolor='gray', elinewidth=1, capsize=3,\n",
    "    markersize=5, label=\"Residui\"\n",
    ")\n",
    "\n",
    "# Linea dello zero\n",
    "ax.axhline(0, color='red', linestyle='--', linewidth=1)\n",
    "\n",
    "# Estetica\n",
    "sns.despine(ax=ax)\n",
    "ax.set_xlabel(r\"$\\omega^2$  [s$^{-2}$]\")\n",
    "ax.set_ylabel(r\"Residuo $x_i - \\left(\\frac{y_i}{A} - \\frac{B}{A}\\right)$  [Kg$^{-1}$]\")\n",
    "ax.set_title(\"Residui della regressione — Molla 2 (cronometro)\")\n",
    "ax.legend()\n",
    "ax.grid(True, linestyle=':', linewidth=0.5, alpha=0.7)\n",
    "\n",
    "plt.tight_layout()\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "255e0632",
   "metadata": {},
   "source": [
    "# Raccolta finale dati"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 41,
   "id": "e87e24b7",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Calibro\n",
      "AC      = 3.2009 ± 0.0033\n",
      "BC      = 1161.4139 ± 0.4685\n",
      "cov_ABC = 0.001384\n",
      "chi²    = 4.3285\n",
      "GdL     = 4\n",
      "P(chi², ∞)= 0.1148\n",
      "\n",
      "Sonar statico senza correzione\n",
      "AS      = 3.2192 ± 0.0027\n",
      "BS      = 2042.5203 ± 1.0326\n",
      "cov_ABS = 0.002760\n",
      "chi²    = 9.0319\n",
      "GdL     = 5\n",
      "P(chi², ∞)= 0.0289\n",
      "\n",
      "Sonar statico con correzione\n",
      "AS      = 3.2390 ± 0.0076\n",
      "BS      = 2043.7514 ± 2.5703\n",
      "cov_ABS = 0.018946\n",
      "chi²    = 0.9520\n",
      "GdL     = 5\n",
      "P(chi², ∞)= 0.8129\n",
      "\n",
      "Sonar dinamico\n",
      "AD      = 3.1496 ± 0.0009\n",
      "BD      = 0.7065 ± 0.0094\n",
      "cov_ABD = -0.000008\n",
      "chi²    = 15.1289\n",
      "GdL     = 5\n",
      "P(chi², ∞)= 0.0017\n",
      "\n",
      "Cronometro\n",
      "ACr      = 3.0896 ± 0.0419\n",
      "BCr      = 1.1894 ± 0.4871\n",
      "cov_ABCr = -0.019876\n",
      "chi²    = 3.2171\n",
      "P(chi², ∞)= 0.3593\n"
     ]
    }
   ],
   "source": [
    "# Stampa regressioni\n",
    "\n",
    "print(\"Calibro\")\n",
    "print(f\"AC      = {AC:.4f} ± {uAC:.4f}\")\n",
    "print(f\"BC      = {BC:.4f} ± {uBC:.4f}\")\n",
    "print(f\"cov_ABC = {covABC:.6f}\")\n",
    "print(f\"chi²    = {chiC:.4f}\")\n",
    "print(f\"GdL     = {len(dfCalibro)}\")\n",
    "print(f\"P(chi², ∞)= {PC:.4f}\")\n",
    "\n",
    "print(\"\\nSonar statico senza correzione\")\n",
    "print(f\"AS      = {AS:.4f} ± {uAS:.4f}\")\n",
    "print(f\"BS      = {BS:.4f} ± {uBS:.4f}\")\n",
    "print(f\"cov_ABS = {covABS:.6f}\")\n",
    "print(f\"chi²    = {chiS:.4f}\")\n",
    "print(f\"GdL     = {len(dfSonar)}\")\n",
    "print(f\"P(chi², ∞)= {PS:.4f}\")\n",
    "\n",
    "print(\"\\nSonar statico con correzione\")\n",
    "print(f\"AS      = {AS2:.4f} ± {uAS2:.4f}\")\n",
    "print(f\"BS      = {BS2:.4f} ± {uBS2:.4f}\")\n",
    "print(f\"cov_ABS = {covABS2:.6f}\")\n",
    "print(f\"chi²    = {chiS2:.4f}\")\n",
    "print(f\"GdL     = {len(dfSonar)}\")\n",
    "print(f\"P(chi², ∞)= {PS2:.4f}\")\n",
    "\n",
    "print(\"\\nSonar dinamico\")\n",
    "print(f\"AD      = {AD:.4f} ± {uAD:.4f}\")\n",
    "print(f\"BD      = {BD:.4f} ± {uBD:.4f}\")\n",
    "print(f\"cov_ABD = {covABD:.6f}\")\n",
    "print(f\"chi²    = {chiD:.4f}\")\n",
    "print(f\"GdL     = {len(dfSonar)}\")\n",
    "print(f\"P(chi², ∞)= {PD:.4f}\")\n",
    "\n",
    "print(\"\\nCronometro\")\n",
    "print(f\"ACr      = {ACr:.4f} ± {uACr:.4f}\")\n",
    "print(f\"BCr      = {BCr:.4f} ± {uBCr:.4f}\")\n",
    "print(f\"cov_ABCr = {covABCr:.6f}\")\n",
    "print(f\"chi²    = {chiCr:.4f}\")\n",
    "print(f\"P(chi², ∞)= {PCr:.4f}\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "c9fc6bca",
   "metadata": {},
   "source": [
    "# Compatibilità"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 42,
   "id": "0bc96952",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "[encoded data, 50200 characters]",
      "text/plain": [
       "<Figure size 1200x700 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "# Plot gaussiane\n",
    "\n",
    "# Parametri gaussiane\n",
    "# (media, deviazione standard, colore, nome)\n",
    "gaussiane = [\n",
    "    (AC, uAC, 1, 'calibro'),\n",
    "    (AS2, uAS2, 2, 'sonar statico'),\n",
    "    (AD, uAD, 4, 'sonar dinamico'),\n",
    "    (ACr, uACr, 8, 'cronometro')\n",
    "]\n",
    "\n",
    "# Creazione figura\n",
    "plt.figure(figsize=(12, 7))\n",
    "\n",
    "# Creazione asse x\n",
    "xMin = float('inf')\n",
    "xMax = float('-inf')\n",
    "for mu, sigma, _, _ in gaussiane:\n",
    "    minimoLocale = mu - 3 * sigma\n",
    "    massimoLocale = mu + 3 * sigma\n",
    "    \n",
    "    if minimoLocale < xMin:\n",
    "        xMin = minimoLocale\n",
    "    \n",
    "    if massimoLocale > xMax:\n",
    "        xMax = massimoLocale\n",
    "x = np.linspace(xMin, xMax, 1000)\n",
    "\n",
    "# Ciclo gaussiane\n",
    "for mu, sigma, colore, etichetta in gaussiane:\n",
    "    \n",
    "    y = stats.norm.pdf(x, mu, sigma)\n",
    "    plt.plot(x, y, color=sns.color_palette()[colore], linewidth=1, label=etichetta)\n",
    "    \n",
    "    puntiLinee = [mu - sigma, mu, mu + sigma]\n",
    "    for px in puntiLinee:\n",
    "        py = stats.norm.pdf(px, mu, sigma) \n",
    "        plt.vlines(x=px, ymin=0, ymax=py, colors=sns.color_palette()[colore], linestyles='dashed', linewidth=1)\n",
    "        \n",
    "# Dettagli estetici finali\n",
    "plt.ylim(bottom=0)\n",
    "plt.title('Confronto dati')\n",
    "plt.xlabel('k')\n",
    "plt.legend()\n",
    "\n",
    "# Mostriamo il grafico\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 43,
   "id": "da18d444",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Compatibilità calibro e sonar statico:\n",
      "k = 4.59\n",
      "\n",
      "Compatibilità cronometro e sonar dinamico:\n",
      "k = 1.43\n",
      "\n",
      "Dati statici e dinamici sono visibilmente incompatibili\n"
     ]
    }
   ],
   "source": [
    "# Fattori di compatibilità\n",
    "\n",
    "def print_k(x1, u1, x2, u2):\n",
    "    k = abs(x1-x2) / np.sqrt(u1**2 + u2**2)\n",
    "    print(f\"k = {k:.2f}\\n\")\n",
    "\n",
    "print(\"Compatibilità calibro e sonar statico:\")\n",
    "print_k(AC, uAC, AS2, uAS2)\n",
    "\n",
    "print(\"Compatibilità cronometro e sonar dinamico:\")\n",
    "print_k(ACr, uACr, AD, uAD)\n",
    "\n",
    "print(\"Dati statici e dinamici sono visibilmente incompatibili\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 44,
   "id": "5b70e361",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "ADin = 3.14960 ± 0.00087\n"
     ]
    }
   ],
   "source": [
    "# Media pesata dati dinamici\n",
    "\n",
    "ADin = ( ACr/(uACr**2) + AD/(uAD**2) ) / ( 1/(uACr**2) + 1/(uAD**2) )\n",
    "uADin = 1 / np.sqrt( 1/(uACr**2) + 1/(uAD**2) )\n",
    "\n",
    "print(f\"ADin = {ADin:.5f} ± {uADin:.5f}\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 45,
   "id": "d4af85a1",
   "metadata": {},
   "outputs": [],
   "source": [
    "# Compatibilità con t di Student\n",
    "\n",
    "def p_t_student_compatibilita(x, ux, gx, y, uy, gy):\n",
    "  GdL = gx + gy - 2\n",
    "  s2 = ( (gx - 1) * ux**2  +  (gy - 1) * uy**2 ) / GdL\n",
    "  sigma2 = ( s2 / gx )  + ( s2 / gy )\n",
    "  t = abs(x - y) / np.sqrt( sigma2 )\n",
    "\n",
    "  return {\"p\": 2 * (1 - stats.t.cdf(abs(t), df=GdL)), \"t\": t}"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 46,
   "id": "57de948b",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Compatibilità: Calibro vs Sonar statico\n",
      "Sigma             t    p-value\n",
      "------------------------------\n",
      "1σ           6.8065     0.0065\n",
      "2σ           3.4033     0.0424\n",
      "3σ           2.2688     0.1080\n",
      "\n",
      "\n",
      "Compatibilità: Calibro vs Sonar statico corretto\n",
      "Sigma             t    p-value\n",
      "------------------------------\n",
      "1σ           6.4291     0.0076\n",
      "2σ           3.2145     0.0488\n",
      "3σ           2.1430     0.1215\n",
      "\n",
      "\n",
      "Compatibilità: Calibro vs Sonar dinamico\n",
      "Sigma             t    p-value\n",
      "------------------------------\n",
      "1σ          27.2592     0.0001\n",
      "2σ          13.6296     0.0009\n",
      "3σ           9.0864     0.0028\n",
      "\n",
      "\n",
      "Compatibilità: Sonar Dinamico vs Sonar statico\n",
      "Sigma             t    p-value\n",
      "------------------------------\n",
      "1σ          42.0848     0.0000\n",
      "2σ          21.0424     0.0000\n",
      "3σ          14.0283     0.0001\n",
      "\n",
      "\n",
      "Compatibilità: Sonar Dinamico vs cronometro\n",
      "Sigma             t    p-value\n",
      "------------------------------\n",
      "1σ           2.4807     0.0682\n",
      "2σ           1.2404     0.2826\n",
      "3σ           0.8269     0.4548\n"
     ]
    }
   ],
   "source": [
    "print(\"Compatibilità: Calibro vs Sonar statico\")\n",
    "print(f\"{'Sigma':<10} {'t':>8} {'p-value':>10}\")\n",
    "print(\"-\" * 30)\n",
    "for n in [1, 2, 3]:\n",
    "    res = p_t_student_compatibilita(AC, uAC*n, len(dfCalibro)-2,\n",
    "                                    AS,  uAS*n, len(dfSonar)-2)\n",
    "    print(f\"{n}σ         {res['t']:>8.4f} {res['p']:>10.4f}\")\n",
    "\n",
    "print(\"\\n\\nCompatibilità: Calibro vs Sonar statico corretto\")\n",
    "print(f\"{'Sigma':<10} {'t':>8} {'p-value':>10}\")\n",
    "print(\"-\" * 30)\n",
    "for n in [1, 2, 3]:\n",
    "    res = p_t_student_compatibilita(AC, uAC*n, len(dfCalibro)-2,\n",
    "                                    AS2,  uAS2*n, len(dfSonar)-2)\n",
    "    print(f\"{n}σ         {res['t']:>8.4f} {res['p']:>10.4f}\")\n",
    "\n",
    "print(\"\\n\\nCompatibilità: Calibro vs Sonar dinamico\")\n",
    "print(f\"{'Sigma':<10} {'t':>8} {'p-value':>10}\")\n",
    "print(\"-\" * 30)\n",
    "for n in [1, 2, 3]:\n",
    "    res = p_t_student_compatibilita(AC, uAC*n, len(dfCalibro)-2,\n",
    "                                    AD,  uAD*n,  len(dfSonar)-2)\n",
    "    print(f\"{n}σ         {res['t']:>8.4f} {res['p']:>10.4f}\")\n",
    "\n",
    "print(\"\\n\\nCompatibilità: Sonar Dinamico vs Sonar statico\")\n",
    "print(f\"{'Sigma':<10} {'t':>8} {'p-value':>10}\")\n",
    "print(\"-\" * 30)\n",
    "for n in [1, 2, 3]:\n",
    "    res = p_t_student_compatibilita(AD,  uAD*n,  len(dfSonar)-2,\n",
    "                                    AS, uAS*n, len(dfSonar)-2)\n",
    "    print(f\"{n}σ         {res['t']:>8.4f} {res['p']:>10.4f}\")\n",
    "\n",
    "print(\"\\n\\nCompatibilità: Sonar Dinamico vs cronometro\")\n",
    "print(f\"{'Sigma':<10} {'t':>8} {'p-value':>10}\")\n",
    "print(\"-\" * 30)\n",
    "for n in [1, 2, 3]:\n",
    "    res = p_t_student_compatibilita(AD,  uAD*n,  len(dfSonar)-2,\n",
    "                                    ACr, uACr*n, len(dfSonar)-2)\n",
    "    print(f\"{n}σ         {res['t']:>8.4f} {res['p']:>10.4f}\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "b66ccc91",
   "metadata": {},
   "source": [
    "# Note finali\n",
    "SI VEDE LA RISONANZA E LA DEFORMAZIONE DELLE MASSE EQUIVALENTI (NON È LINEARE)"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "base",
   "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.11"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
