Velocità della luce
This commit is contained in:
+262
@@ -0,0 +1,262 @@
|
||||
import marimo
|
||||
|
||||
__generated_with = "0.25.2"
|
||||
app = marimo.App(width="medium")
|
||||
|
||||
|
||||
@app.cell
|
||||
def _():
|
||||
import marimo as mo
|
||||
import numpy as np
|
||||
import pandas as pd
|
||||
import sympy as sp
|
||||
from scipy import stats
|
||||
|
||||
from pathlib import Path
|
||||
|
||||
import statistica
|
||||
|
||||
_outputs, defs = statistica.app.run()
|
||||
Data = defs["Data"]
|
||||
compat = defs["compat"]
|
||||
media_pesata = defs["media_pesata"]
|
||||
rimuovi_outlier = defs["rimuovi_outlier"]
|
||||
plot_gauss = defs["plot_gauss"]
|
||||
cartella_csv = Path(__file__).resolve().parent / "csv" / "velocita-C"
|
||||
# cartella_immagini = Path(__file__).resolve().parent / "LaTeX" / "immagini"
|
||||
|
||||
def leggi_csv(nome):
|
||||
dati = pd.read_csv(cartella_csv / nome, sep=";", decimal=",")
|
||||
dati.columns = dati.columns.astype(str).str.strip()
|
||||
dati = dati.dropna(axis=1, how="all")
|
||||
return dati.apply(pd.to_numeric, errors="coerce")
|
||||
|
||||
return Data, compat, leggi_csv, mo, pd, sp
|
||||
|
||||
|
||||
@app.cell(hide_code=True)
|
||||
def _(mo):
|
||||
mo.md(r"""
|
||||
# Velocità della luce — metodo di Foucault
|
||||
|
||||
$$c = \frac{4 f_2 D^2 \left|\omega_{fin}-\omega_{in}\right|}{(D+a-f_2)\left|x_{fin}-x_{in}\right|},
|
||||
\qquad \omega = 2\pi f_r$$
|
||||
|
||||
dove $\omega_{in},\ \omega_{fin}$ sono le pulsazioni di rotazione e
|
||||
$x_{in},\ x_{fin}$ le posizioni del fascio (zero arbitrario) relative alle
|
||||
due letture dello stesso punto sperimentale.
|
||||
|
||||
Le stime di $c$ dei singoli punti vengono combinate con una media pesata.
|
||||
""")
|
||||
return
|
||||
|
||||
|
||||
@app.cell(hide_code=True)
|
||||
def _(mo):
|
||||
mo.md(r"""
|
||||
## Costanti geometriche (parte sistematica)
|
||||
""")
|
||||
return
|
||||
|
||||
|
||||
@app.cell
|
||||
def _(Data, leggi_csv, pd, sp):
|
||||
_D1 = Data(leggi_csv("D1.csv"))
|
||||
_D1.stat_chauv("D", 0.01, False)
|
||||
|
||||
_D2 = Data(leggi_csv("D2.csv"))
|
||||
_D2.stat_chauv("D", 0.01, False)
|
||||
|
||||
_D3 = Data(leggi_csv("D3.csv"))
|
||||
_D3.stat_chauv("D", 0.01, False)
|
||||
|
||||
_D_tot = Data(None, analisi_stat = pd.DataFrame({
|
||||
"L1": [_D1.analisi_stat.D[0]], "uL1": [_D1.analisi_stat.uD[0]],
|
||||
"L2": [_D2.analisi_stat.D[0]], "uL2": [_D2.analisi_stat.uD[0]],
|
||||
"L3": [_D3.analisi_stat.D[0]], "uL3": [_D3.analisi_stat.uD[0]]
|
||||
}))
|
||||
|
||||
L1, L2, L3 = sp.symbols("L1 L2 L3", positive=True)
|
||||
D = L1 + L2 + L3
|
||||
_D_tot.calc_var(D, "D")
|
||||
|
||||
D, uD = _D_tot.analisi_stat.D[0], _D_tot.analisi_stat.uD[0] # Distanza specchio rotante - specchio concavo [m]
|
||||
a, ua = 0.376, 0.002 # Distanza lente - specchio rotante [m]
|
||||
f2, uf2 = 0.2536, 0.0005 # Lunghezza focale lente L2 [m]
|
||||
return D, a, f2, uD, ua, uf2
|
||||
|
||||
|
||||
@app.cell(hide_code=True)
|
||||
def _(mo):
|
||||
mo.md(r"""
|
||||
## Dati grezzi
|
||||
|
||||
Dati simulati, usati solo per verificare il procedimento.
|
||||
|
||||
- `C.csv`: una riga per punto sperimentale, con le quattro letture
|
||||
`f_iniziale`, `f_finale` in Hz e `x_iniziale`, `x_finale` in mm;
|
||||
- le frequenze sono negative per il verso di rotazione assunto;
|
||||
- `D1.csv`, `D2.csv`, `D3.csv`: le tre tratte che compongono
|
||||
$D=L_1+L_2+L_3$.
|
||||
|
||||
Dopo l'analisi statistica le posizioni vengono convertite da mm a m.
|
||||
""")
|
||||
return
|
||||
|
||||
|
||||
@app.cell
|
||||
def _(Data, leggi_csv):
|
||||
err_strum = {
|
||||
"f_finale" : 1,
|
||||
"f_iniziale": 1,
|
||||
"x_finale" : 0.01,
|
||||
"x_iniziale": 0.01
|
||||
} # risoluzione strumentale: Hz, mm
|
||||
|
||||
dati = Data(leggi_csv("C.csv"))
|
||||
dati.stat_chauv(list(err_strum.keys()), list(err_strum.values()))
|
||||
return (dati,)
|
||||
|
||||
|
||||
@app.cell
|
||||
def _(D, a, dati, f2, uD, ua, uf2):
|
||||
dati.analisi_stat["D"] = D
|
||||
dati.analisi_stat["uD"] = uD
|
||||
dati.analisi_stat["a"] = a
|
||||
dati.analisi_stat["ua"] = ua
|
||||
dati.analisi_stat["f2"] = f2
|
||||
dati.analisi_stat["uf2"] = uf2
|
||||
|
||||
dati.analisi_stat
|
||||
return
|
||||
|
||||
|
||||
@app.cell(hide_code=True)
|
||||
def _(mo):
|
||||
mo.md(r"""
|
||||
## Analisi con criterio di Chauvenet
|
||||
|
||||
Stessa analisi (`stat_chauv`) applicata sia ai punti con rotazione
|
||||
sia alla baseline. Poi si converte `d` da mm a m e si riportano
|
||||
$f_{r0}, d_0$ (baseline) come colonne costanti su tutte le righe dei
|
||||
punti principali, dato che è la stessa misura per tutti.
|
||||
""")
|
||||
return
|
||||
|
||||
|
||||
@app.cell
|
||||
def _(dati):
|
||||
# conversione mm -> m per le colonne di lunghezza
|
||||
for _col in ["x_finale", "ux_finale", "x_iniziale", "ux_iniziale"]:
|
||||
dati.analisi_stat[_col] = dati.analisi_stat[_col] * 1e-3
|
||||
|
||||
|
||||
dati.analisi_stat
|
||||
return
|
||||
|
||||
|
||||
@app.cell(hide_code=True)
|
||||
def _(mo):
|
||||
mo.md(r"""
|
||||
## Calcolo delle pulsazioni $\omega_{in}=2\pi f_{in}$ e $\omega_{fin}=2\pi f_{fin}$
|
||||
""")
|
||||
return
|
||||
|
||||
|
||||
@app.cell
|
||||
def _(dati, sp):
|
||||
_f_iniziale, _f_finale = sp.symbols("f_iniziale f_finale")
|
||||
dati.calc_var(2 * sp.pi * _f_iniziale, "omega_iniziale")
|
||||
dati.calc_var(2 * sp.pi * _f_finale, "omega_finale")
|
||||
|
||||
dati.analisi_stat
|
||||
return
|
||||
|
||||
|
||||
@app.cell(hide_code=True)
|
||||
def _(mo):
|
||||
mo.md(r"""
|
||||
## Calcolo di $c$ punto per punto
|
||||
|
||||
$D$, $a$ e $f_2$ sono riportate come colonne costanti **con le loro
|
||||
incertezze** (`uD`, `ua`, `uf2`), quindi `calc_var` propaga la parte
|
||||
geometrica insieme a quella sperimentale. Le colonne
|
||||
`%uc_f_iniziale`, `%uc_f_finale`, `uc_x_...` danno il peso percentuale di
|
||||
ciascun termine e mostrano quale incertezza domina il risultato.
|
||||
""")
|
||||
return
|
||||
|
||||
|
||||
@app.cell(hide_code=True)
|
||||
def _(formula_c, mo, sp):
|
||||
mo.md(f"""
|
||||
$c={sp.latex(formula_c)}$
|
||||
""")
|
||||
return
|
||||
|
||||
|
||||
@app.cell
|
||||
def _(dati, sp):
|
||||
_D, _a, _f2, _omega_iniziale, _omega_finale, _x_iniziale, _x_finale= sp.symbols("D a f2 omega_iniziale omega_finale x_iniziale x_finale", real=True)
|
||||
|
||||
formula_c = 4 * _f2 * _D**2 * sp.Abs(_omega_finale - _omega_iniziale) / ((_D + _a - _f2) * sp.Abs(_x_finale - _x_iniziale))
|
||||
dati.calc_var(formula_c, "c")
|
||||
|
||||
dati.analisi_stat
|
||||
return (formula_c,)
|
||||
|
||||
|
||||
@app.cell(hide_code=True)
|
||||
def _(mo):
|
||||
mo.md(r"""
|
||||
## Media pesata delle stime di $c$
|
||||
|
||||
Le stime indipendenti di $c$ — una per riga di `C.csv` — vengono combinate con
|
||||
pesi $w_i = 1/u_{c,i}^2$. Prima di combinarle, `media_pesata` applica il
|
||||
criterio di Chauvenet fra le stime; i punti rimossi sono riportati in `out`.
|
||||
|
||||
Si riportano $\tilde\chi^2$ (chi quadro ridotto), i gradi di libertà e
|
||||
$P(\chi^2)$ riferiti ai soli punti mantenuti.
|
||||
""")
|
||||
return
|
||||
|
||||
|
||||
@app.cell
|
||||
def _(dati):
|
||||
c_stat, uc_stat, chi2, dof, P, out= dati.media_pesata("c", info_outlier=True)
|
||||
|
||||
print(f"c (media pesata) = {c_stat:.6e} +- {uc_stat:.2e}")
|
||||
print(f"chi2 = {chi2:.3f}, dof = {dof}, P(chi2) = {P:.3f}")
|
||||
print(out)
|
||||
return c_stat, uc_stat
|
||||
|
||||
|
||||
@app.cell(hide_code=True)
|
||||
def _(mo):
|
||||
mo.md(r"""
|
||||
## Risultato finale e confronto col valore vero
|
||||
""")
|
||||
return
|
||||
|
||||
|
||||
@app.cell
|
||||
def _(c_stat, compat, mo, uc_stat):
|
||||
c_vero = 299792458.0
|
||||
_k, _diff = compat(c_stat, c_vero, uc_stat, 0.0)
|
||||
|
||||
mo.md(
|
||||
f"""
|
||||
$$c = \\left({c_stat/1e8:.3f} \\pm {uc_stat/1e8:.3f}\\right)\\times 10^8\\ \\mathrm{{m/s}}$$
|
||||
|
||||
Confronto col valore tabulato
|
||||
$c_{{tab}} = {c_vero/1e8:.3f}\\times 10^8\\ \\mathrm{{m/s}}$:
|
||||
differenza ${_diff:.2E}$ m/s, fattore di compatibilita **k = {_k:.2f}**,
|
||||
calcolato con $u_{{tab}}=0$, cioe $k=|c-c_{{tab}}|/u_c$.
|
||||
{"✅ compatibile ($k<2$)" if _k < 2 else "⚠️ non compatibile ($k\\ge 2$)"}
|
||||
"""
|
||||
)
|
||||
return
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
app.run()
|
||||
Reference in New Issue
Block a user