Aggiunta dati e versione finale di focale lente

This commit is contained in:
2026-11-06 10:26:45 +01:00
parent a85cc602f2
commit 8425ff90da
12 changed files with 715 additions and 328 deletions
@@ -0,0 +1,11 @@
p ;q
38,8;68,6
66,3;41,0
42,6;63,6
49,4;52,9
64,7;42,2
48,7;54,1
51,1;50,1
48,7;55,0
50,7;51,0
63,9;42,2
1 p q
2 38,8 68,6
3 66,3 41,0
4 42,6 63,6
5 49,4 52,9
6 64,7 42,2
7 48,7 54,1
8 51,1 50,1
9 48,7 55,0
10 50,7 51,0
11 63,9 42,2
@@ -0,0 +1,11 @@
q ;h
68,6;21,70
41,0;8,20
63,6;18,90
41,4;8,00
42,7;8,75
51,8;13,00
55,4;15,05
43,2;9,00
39,6;6,60
41,2;7,30
1 q h
2 68,6 21,70
3 41,0 8,20
4 63,6 18,90
5 41,4 8,00
6 42,7 8,75
7 51,8 13,00
8 55,4 15,05
9 43,2 9,00
10 39,6 6,60
11 41,2 7,30
@@ -0,0 +1,11 @@
a ;d1 ;d2
108,7;40,0;68,0
106,6;41,0;64,0
103,7;42,0;57,5
110,3;44,5;55,5
103,2;43,5;61,0
107,0;42,5;67,0
110,5;38,5;70,0
104,0;45,0;59,0
101,7;45,0;56,0
105,0;42,0;58,0
1 a d1 d2
2 108,7 40,0 68,0
3 106,6 41,0 64,0
4 103,7 42,0 57,5
5 110,3 44,5 55,5
6 103,2 43,5 61,0
7 107,0 42,5 67,0
8 110,5 38,5 70,0
9 104,0 45,0 59,0
10 101,7 45,0 56,0
11 105,0 42,0 58,0
@@ -0,0 +1,8 @@
p;q
5,4;73,7
5,7;50,5
5,4;86,7
5,2;98,8
5,3;105,3
5,4;77,1
5,5;66,9
1 p q
2 5,4 73,7
3 5,7 50,5
4 5,4 86,7
5 5,2 98,8
6 5,3 105,3
7 5,4 77,1
8 5,5 66,9
@@ -0,0 +1,9 @@
q;h
11,1;22,00
20,3;42,20
27,9;62,45
36,2;85,10
43,9;106,15
43,7;105,00
48,5;105,50
7,3;8,30
1 q h
2 11,1 22,00
3 20,3 42,20
4 27,9 62,45
5 36,2 85,10
6 43,9 106,15
7 43,7 105,00
8 48,5 105,50
9 7,3 8,30
@@ -0,0 +1,11 @@
a ;d1 ;d2
24,6;18,4;6,7
26,6;20,8;6,3
32,2;26,5;6,0
37,9;32,6;5,4
45,4;40,5;5,3
55,2;49,8;5,2
39,5;34,1;5,4
33,2;27,2;5,6
23,7;17,0;6,6
41,2;35,7;5,5
1 a d1 d2
2 24,6 18,4 6,7
3 26,6 20,8 6,3
4 32,2 26,5 6,0
5 37,9 32,6 5,4
6 45,4 40,5 5,3
7 55,2 49,8 5,2
8 39,5 34,1 5,4
9 33,2 27,2 5,6
10 23,7 17,0 6,6
11 41,2 35,7 5,5
@@ -0,0 +1,2 @@
freccia1;freccia2;freccia3;freccia4;freccia5;freccia6;freccia7;freccia8;freccia9;freccia10;freccia11
11,90;11,70;11,80;11,95;11,85;11,95;11,90;11,85;11,90;11,95;11,85
1 freccia1 freccia2 freccia3 freccia4 freccia5 freccia6 freccia7 freccia8 freccia9 freccia10 freccia11
2 11,90 11,70 11,80 11,95 11,85 11,95 11,90 11,85 11,90 11,95 11,85
@@ -0,0 +1,2 @@
s252B1;s252B2;s252B3;s252B4;s252B5;s252B6;s252B7;s252B8
6,45;6,35;6,40;6,45;6,50;6,45;6,40;6,45
1 s252B1 s252B2 s252B3 s252B4 s252B5 s252B6 s252B7 s252B8
2 6,45 6,35 6,40 6,45 6,50 6,45 6,40 6,45
@@ -0,0 +1,2 @@
s48B1;s48B2;s48B3;s48B4;s48B5;s48B6;s48B7;s48B8
6,45;6,45;6,50;6,45;6,40;6,40;6,45;6,40
1 s48B1 s48B2 s48B3 s48B4 s48B5 s48B6 s48B7 s48B8
2 6,45 6,45 6,50 6,45 6,40 6,40 6,45 6,40
+537 -312
View File
@@ -1,402 +1,627 @@
import marimo import marimo
__generated_with = "0.25.0" __generated_with = "0.25.2"
app = marimo.App(width="medium") app = marimo.App(width="medium", auto_download=["html"])
@app.cell @app.cell
def _(): def _():
import marimo as mo import marimo as mo
return (mo,)
@app.cell(hide_code=True)
def _(mo):
mo.md(r"""
# Misura della distanza focale di una lente convergente
Quattro stime, tutte basate sull'equazione della lente sottile $\frac{1}{f}=\frac{1}{p}+\frac{1}{q}$ e sull'ingrandimento $m=\frac{q}{p}=\frac{l_{Freccia}}{L}$ (con $L$ = lunghezza dell'oggetto):
1. **Punti coniugati**: $f=\dfrac{p\,q}{p+q}$
2. **a) $p$ e ingrandimento**: $f=\dfrac{p\,m}{1+m}$
2. **b) $q$ e ingrandimento**: $f=\dfrac{q}{1+m}$
3. **Bessel**: $f=\dfrac{D^2-d^2}{4D}$ (vedi sotto)
Le incertezze sono propagate con `Data.calc_var` di `statistica.py`.
""")
return
@app.cell
def _():
import numpy as np import numpy as np
import pandas as pd import pandas as pd
import sympy as sp import sympy as sp
from scipy import stats from scipy import stats
from pathlib import Path
import statistica import statistica
# Esegue statistica.py
_outputs, defs = statistica.app.run() _outputs, defs = statistica.app.run()
Data = defs["Data"] Data = defs["Data"]
compat = defs["compat"] compat = defs["compat"]
media_pesata = defs["media_pesata"]
media_pesata_dersimonian_laird = defs["media_pesata_dersimonian_laird"]
rimuovi_outlier = defs["rimuovi_outlier"]
plot_gauss = defs["plot_gauss"] plot_gauss = defs["plot_gauss"]
return Data, compat, np, pd, plot_gauss, sp, stats cartella_csv = Path(__file__).resolve().parent / "csv" / "focaleLente"
cartella_immagini = Path(__file__).resolve().parent / "LaTeX" / "immagini"
return (
Data,
cartella_csv,
cartella_immagini,
compat,
media_pesata,
mo,
np,
pd,
plot_gauss,
rimuovi_outlier,
sp,
)
@app.cell(hide_code=True) @app.cell(hide_code=True)
def _(mo): def _(mo):
mo.md(r""" mo.md(r"""
## Dati # Misura della distanza focale
**Le righe sono a coppie (0-1, 2-3, 4-5, ...)** per il metodo di Bessel: le due righe di una coppia hanno la **stessa distanza sorgente-schermo** $D=p+q$ e corrispondono alle due posizioni della lente con immagine nitida. Sono usati solo i CSV presenti in `csv/focaleLente`.
In una posizione la lente è vicina alla sorgente (immagine ingrandita, $p$ piccolo), nell'altra è vicina allo schermo (immagine rimpicciolita, $p$ grande): le due posizioni sono **coniugate**, cioè $p$ e $q$ si scambiano ($p_B=q_A$, $q_B=p_A$) e gli ingrandimenti sono uno il reciproco dell'altro. - **m1, punti coniugati:** $f = pq/(p+q)$
- **m2, $q$ e ingrandimento:** $f = q/(1+h/L)$
- **m3, Bessel:** $f = d_1d_2/a$
Ordine delle righe dentro la coppia indifferente. Il metodo con $p$ e ingrandimento non viene usato perché non è stata
misurata la grandezza necessaria.
Le distanze da metro sono in cm con errore strumentale `0.1 cm`.
Le misure da calibro ventesimale sono in mm con errore strumentale
`0.05 mm`.
""") """)
return return
@app.cell @app.cell
def _(Data, pd): def _(cartella_csv, pd):
dfFenditura = pd.DataFrame({ def leggi_csv(nome):
"l1": [10.05,], dati = pd.read_csv(cartella_csv / nome, sep=";", decimal=",")
"l2": [10.00,], dati.columns = dati.columns.astype(str).str.strip()
"l3": [10.03,], dati = dati.dropna(axis=1, how="all")
"l4": [9.94, ], return dati.apply(pd.to_numeric, errors="coerce")
"l5": [9.99, ],
})
datiFenditura = Data(dfFenditura) m1_48B = leggi_csv("lenti per csv 2(48B_m1).csv")
datiFenditura.stat_chauv(["l"], [0.02]) m1_252B = leggi_csv("lenti per csv 2(252B_m1).csv")
datiFenditura m2_48B = leggi_csv("lenti per csv 2(48B_m2).csv")
m2_252B = leggi_csv("lenti per csv 2(252B_m2).csv")
lunghezzaOggetto = datiFenditura.analisi_stat.l[0] # variabile che contiene la lunghezza dell'oggetto m3_48B = leggi_csv("lenti per csv 2(48B_m3).csv")
ulunghezzaOggetto = datiFenditura.analisi_stat.ul[0] # variabile che contiene l'errore sulla lunghezza dell'oggetto m3_252B = leggi_csv("lenti per csv 2(252B_m3).csv")
return lunghezzaOggetto, ulunghezzaOggetto spessore_48B_df = leggi_csv("lenti per csv 2(spessore 48B).csv")
spessore_252B_df = leggi_csv("lenti per csv 2(spessore 252B).csv")
dimensione_freccia_df = leggi_csv("lenti per csv 2(dimensione freccia).csv")
return (
dimensione_freccia_df,
m1_252B,
m1_48B,
m2_252B,
m2_48B,
m3_252B,
m3_48B,
spessore_252B_df,
spessore_48B_df,
)
@app.cell @app.cell
def _(pd): def _(Data, dimensione_freccia_df, spessore_252B_df, spessore_48B_df):
df = pd.DataFrame({ _df_spessore_48B = Data(spessore_48B_df)
"p1": [23.82, 41.22, 20.58, 53.91, 19.38, 65.51], _df_spessore_48B.stat_chauv("s48B", 0.05, False)
"p2": [23.39, 41.62, 20.94, 54.35, 19.07, 65.62], spessore_48B = _df_spessore_48B.analisi_stat.s48B[0] /10
"p3": [23.49, 41.54, 20.40, 54.72, 19.43, 65.70], uspessore_48B = _df_spessore_48B.analisi_stat.us48B[0]/10
"p4": [23.57, 41.57, 20.84, 54.32, 19.79, 65.51],
"p5": [23.33, 41.21, 20.32, 54.17, 19.37, 65.19],
"q1": [41.51, 23.98, 54.07, 21.30, 65.28, 19.65], _df_spessore_252B = Data(spessore_252B_df)
"q2": [41.51, 23.53, 53.91, 20.80, 65.19, 19.72], _df_spessore_252B.stat_chauv("s252B", 0.05, False)
"q3": [40.99, 23.37, 54.71, 20.76, 65.23, 19.58], spessore_252B = _df_spessore_252B.analisi_stat.s252B[0] /10
"q4": [41.82, 24.09, 54.80, 20.81, 65.46, 19.17], uspessore_252B = _df_spessore_252B.analisi_stat.us252B[0]/10
"q5": [41.69, 23.47, 54.17, 20.69, 65.19, 19.39],
"lFreccia1": [17.64, 5.58, 26.22, 3.80, 33.77, 2.94], _df_freccia = Data(dimensione_freccia_df)
"lFreccia2": [17.67, 5.64, 26.17, 3.75, 33.69, 2.95], _df_freccia.stat_chauv("freccia", 0.05, False)
"lFreccia3": [17.70, 5.54, 26.21, 3.84, 33.70, 3.03], freccia = _df_freccia.analisi_stat.freccia[0] /10
"lFreccia4": [17.66, 5.71, 26.14, 3.81, 33.77, 3.04], ufreccia = _df_freccia.analisi_stat.ufreccia[0]/10
"lFreccia5": [17.66, 5.64, 26.09, 3.88, 33.77, 3.00], return (
}) freccia,
spessore_252B,
spessore_48B,
ufreccia,
uspessore_252B,
uspessore_48B,
)
# incertezze strumentali (risoluzione) di p, q, lFreccia
err_strum = {"p": 0.1, "q": 0.1, "lFreccia": 0.05} @app.cell(hide_code=True)
df def _(
return df, err_strum freccia,
mo,
spessore_252B,
spessore_48B,
ufreccia,
uspessore_252B,
uspessore_48B,
):
mo.md("## Misure accessorie")
(spessore_48B, uspessore_48B), (spessore_252B, uspessore_252B), (freccia, ufreccia)
return
@app.cell
def _(
Data,
m1_252B,
m1_48B,
spessore_252B,
spessore_48B,
uspessore_252B,
uspessore_48B,
):
data48Bm1 = Data(m1_48B.copy())
data48Bm1.analisi_stat = m1_48B.copy()
data48Bm1.analisi_stat["up"] = 0.1
data48Bm1.analisi_stat["uq"] = 1 #Potevamo muovere lo schermo di ... e non notavamo differenze
data48Bm1.analisi_stat["s"] = spessore_48B
data48Bm1.analisi_stat["us"] = uspessore_48B
data252Bm1 = Data(m1_252B.copy())
data252Bm1.analisi_stat = m1_252B.copy()
data252Bm1.analisi_stat["up"] = 1 #Potevamo muovere lo schermo di ... e non notavamo differenze
data252Bm1.analisi_stat["uq"] = 1 #Potevamo muovere lo schermo di ... e non notavamo differenze
data252Bm1.analisi_stat["s"] = spessore_252B
data252Bm1.analisi_stat["us"] = uspessore_252B
data48Bm1.analisi_stat, data252Bm1.analisi_stat
return data252Bm1, data48Bm1
@app.cell
def _(sp):
p, q, s = sp.symbols("p q s", positive=True)
peff, qeff = sp.symbols("peff qeff", positive=True)
peff = p - (s/2)
qeff = q + (s/2)
return peff, qeff
@app.cell
def _(data252Bm1, data48Bm1, peff, qeff):
f1 = peff * qeff / (peff + qeff)
data48Bm1.calc_var(peff, "peff")
data252Bm1.calc_var(peff, "peff")
data48Bm1.calc_var(qeff, "qeff")
data252Bm1.calc_var(qeff, "qeff")
data48Bm1.calc_var(f1, "f1")
data252Bm1.calc_var(f1, "f1")
risultato48Bm1 = data48Bm1.analisi_stat[["peff", "upeff", "qeff", "uqeff", "f1", "uf1"]]
risultato252Bm1 = data252Bm1.analisi_stat[["peff", "upeff", "qeff", "uqeff", "f1", "uf1"]]
return risultato252Bm1, risultato48Bm1
@app.cell(hide_code=True) @app.cell(hide_code=True)
def _(mo): def _(mo):
mo.md(r""" mo.md(r"""
## Analisi statistica (criterio di Chauvenet) ## Metodo 1: punti coniugati
Per ogni configurazione: media, incertezza statistica + strumentale, ed `p` e `q` sono in cm, quindi anche `f1` è in cm.
eventuali outlier scartati. Alla tabella si aggiunge la lunghezza
dell'oggetto, comune a tutte le righe.
""") """)
return return
@app.cell @app.cell
def _(Data, df, err_strum, lunghezzaOggetto, ulunghezzaOggetto): def _(risultato252Bm1, risultato48Bm1):
dati = Data(df) risultato48Bm1, risultato252Bm1
dati.stat_chauv(list(err_strum.keys()), list(err_strum.values())) return
dati.analisi_stat["lunghezzaOggetto"] = lunghezzaOggetto
dati.analisi_stat["ulunghezzaOggetto"] = ulunghezzaOggetto
dati.analisi_stat @app.cell
return (dati,) def _(
Data,
freccia,
m2_252B,
m2_48B,
spessore_252B,
spessore_48B,
ufreccia,
uspessore_252B,
uspessore_48B,
):
data48Bm2 = Data(m2_48B.copy())
data48Bm2.analisi_stat = m2_48B.copy()
data48Bm2.analisi_stat["uq"] = 1 #La freccia era sempre a fuoco per ogni q
data48Bm2.analisi_stat["h"] /= 10
data48Bm2.analisi_stat["uh"] = 0.1 #No guide fisse e calibro nell'vuoto siderale
data48Bm2.analisi_stat["L"] = freccia
data48Bm2.analisi_stat["uL"] = ufreccia
data48Bm2.analisi_stat["s"] = spessore_48B
data48Bm2.analisi_stat["us"] = uspessore_48B
data252Bm2 = Data(m2_252B.copy())
data252Bm2.analisi_stat = m2_252B.copy()
data252Bm2.analisi_stat["uq"] = 0.1
data252Bm2.analisi_stat["h"] /= 10
data252Bm2.analisi_stat["uh"] = 0.02
data252Bm2.analisi_stat["L"] = freccia
data252Bm2.analisi_stat["uL"] = ufreccia
data252Bm2.analisi_stat["s"] = spessore_252B
data252Bm2.analisi_stat["us"] = uspessore_252B
return data252Bm2, data48Bm2
@app.cell
def _(data252Bm2, data48Bm2, np, qeff, sp):
h, L, theta= sp.symbols("h L theta", positive=True)
data48Bm2.calc_var(qeff, "qeff")
data252Bm2.calc_var(qeff, "qeff")
data48Bm2.analisi_stat["theta"] = np.radians(15)
data48Bm2.analisi_stat["utheta"] = (np.radians(15) - np.radians(5)) / 2 # data48Bm2.analisi_stat["theta"] / (2* np.sqrt(3))
data252Bm2.analisi_stat["theta"] = np.radians(15)
data252Bm2.analisi_stat["utheta"] = (np.radians(15) - np.radians(5)) / 2
f2bCorretto = qeff / (1 + h * sp.cos(theta) / L) # / 1.0353 # [1; 1.0353]
f2b = qeff / (1 + h / L) #Senza correzione si theta per vedere come è
data48Bm2.calc_var(f2b, "f2b_senza")
data252Bm2.calc_var(f2b, "f2b_senza")
data48Bm2.calc_var(f2bCorretto, "f2b")
data252Bm2.calc_var(f2bCorretto, "f2b")
risultato48Bm2 = data48Bm2.analisi_stat[["qeff", "uqeff", "h", "uh", "f2b", "uf2b"]]
risultato252Bm2 = data252Bm2.analisi_stat[["qeff", "uqeff", "h", "uh", "f2b", "uf2b"]]
risultato48Bm2_senza = data48Bm2.analisi_stat[["qeff", "uqeff", "h", "uh", "f2b_senza", "uf2b_senza"]]
risultato252Bm2_senza = data252Bm2.analisi_stat[["qeff", "uqeff", "h", "uh", "f2b_senza", "uf2b_senza"]]
data48Bm2.analisi_stat, data252Bm2.analisi_stat,
return (
risultato252Bm2,
risultato252Bm2_senza,
risultato48Bm2,
risultato48Bm2_senza,
)
@app.cell(hide_code=True) @app.cell(hide_code=True)
def _(mo): def _(mo):
mo.md(r""" mo.md(r"""
## Metodo 1 — punti coniugati ## Metodo 2: $q$ e ingrandimento
""")
return
`q` e `L` sono in cm e `h` è in mm. Il rapporto `h/L` è adimensionale,
@app.cell(hide_code=True) perché confronta la dimensione dell'immagine con quella dell'oggetto.
def _(f1, mo, sp): Il risultato `f2b` è in cm.
mo.md(f"""
$f = {sp.latex(f1)}$
""") """)
return return
@app.cell @app.cell
def _(dati, sp): def _(risultato252Bm2, risultato48Bm2):
_p, _q = sp.symbols("p q", positive=True) risultato48Bm2, risultato252Bm2
return
f1 = _p * _q / (_p + _q)
dati.calc_var(f1, "f1") @app.cell
def _(Data, m3_252B, m3_48B):
data48Bm3 = Data(m3_48B.copy())
data48Bm3.analisi_stat = m3_48B.copy()
data48Bm3.analisi_stat["ua"] = 0.3
data48Bm3.analisi_stat["ud1"] = 0.1 # Non notavamo differenze in 0.3 cm
data48Bm3.analisi_stat["ud2"] = 0.1
res_1 = dati.analisi_stat[["f1", "uf1", "%uf1_p", "%uf1_q"]] data252Bm3 = Data(m3_252B.copy())
res_1 data252Bm3.analisi_stat = m3_252B.copy()
return f1, res_1 data252Bm3.analisi_stat["ua"] = 0.3
data252Bm3.analisi_stat["ud1"] = 1 # No differenze notate in 1 cm
data252Bm3.analisi_stat["ud2"] = 1
return data252Bm3, data48Bm3
@app.cell
def _(data252Bm3, data48Bm3, sp):
a, d1, d2 = sp.symbols("a d1 d2", positive=True, real=True)
delta = d1 - d2
data48Bm3.calc_var(delta, "delta")
data252Bm3.calc_var(delta, "delta")
f3 = (a**2 - delta**2) / (4*a)
data48Bm3.calc_var(f3, "f3")
data252Bm3.calc_var(f3, "f3")
risultato48Bm3 = data48Bm3.analisi_stat[["a", "ua", "d1", "ud1", "d2", "ud2", "f3", "uf3"]]
risultato252Bm3 = data252Bm3.analisi_stat[["a", "ua", "d1", "ud1", "d2", "ud2", "f3", "uf3"]]
data48Bm3.analisi_stat
return risultato252Bm3, risultato48Bm3
@app.cell(hide_code=True) @app.cell(hide_code=True)
def _(mo): def _(mo):
mo.md(r""" mo.md(r"""
## Metodo 2a — $p$ e ingrandimento ## Metodo 3: Bessel
`a`, `d1` e `d2` sono in cm. Si usa direttamente
""") """)
return return
@app.cell
def _(risultato252Bm3, risultato48Bm3):
risultato48Bm3, risultato252Bm3
return
@app.cell
def _(
rimuovi_outlier,
risultato252Bm1,
risultato252Bm2,
risultato252Bm3,
risultato48Bm1,
risultato48Bm2,
risultato48Bm3,
):
f48B_m1_puliti, out48B_m1 = rimuovi_outlier(
risultato48Bm1["f1"].to_numpy(), risultato48Bm1["uf1"].mean()
)
f48B_m2_puliti, out48B_m2 = rimuovi_outlier(
risultato48Bm2["f2b"].to_numpy(), risultato48Bm2["uf2b"].mean()
)
f48B_m3_puliti, out48B_m3 = rimuovi_outlier(
risultato48Bm3["f3"].to_numpy(), risultato48Bm3["uf3"].mean()
)
f252B_m1_puliti, out252B_m1 = rimuovi_outlier(
risultato252Bm1["f1"].to_numpy(), risultato252Bm1["uf1"].mean()
)
f252B_m2_puliti, out252B_m2 = rimuovi_outlier(
risultato252Bm2["f2b"].to_numpy(), risultato252Bm2["uf2b"].mean()
)
f252B_m3_puliti, out252B_m3 = rimuovi_outlier(
risultato252Bm3["f3"].to_numpy(), risultato252Bm3["uf3"].mean()
)
outlier_fuochi = {
"48B m1": out48B_m1,
"48B m2": out48B_m2,
"48B m3": out48B_m3,
"252B m1": out252B_m1,
"252B m2": out252B_m2,
"252B m3": out252B_m3,
}
return (
f252B_m1_puliti,
f252B_m2_puliti,
f252B_m3_puliti,
f48B_m1_puliti,
f48B_m2_puliti,
f48B_m3_puliti,
outlier_fuochi,
)
@app.cell(hide_code=True) @app.cell(hide_code=True)
def _(f2a, mo, sp): def _(mo, outlier_fuochi):
mo.md(f""" mo.md("## Outlier dei fuochi")
$f = {sp.latex(f2a)}$ outlier_fuochi
""")
return return
@app.cell @app.cell
def _(dati, sp): def _(
_p, _lF, _L = sp.symbols("p lFreccia lunghezzaOggetto", positive=True) f252B_m1_puliti,
_m = _lF / _L f252B_m2_puliti,
f252B_m3_puliti,
f48B_m1_puliti,
f48B_m2_puliti,
f48B_m3_puliti,
media_pesata,
np,
pd,
risultato252Bm1,
risultato252Bm2,
risultato252Bm3,
risultato48Bm1,
risultato48Bm2,
risultato48Bm3,
):
f48B_m1, u48B_m1, chi2_48B_m1, dof_48B_m1, P_48B_m1 = media_pesata(
f48B_m1_puliti, risultato48Bm1["uf1"].loc[risultato48Bm1["f1"].isin(f48B_m1_puliti)]
)
f48B_m2, u48B_m2, chi2_48B_m2, dof_48B_m2, P_48B_m2 = media_pesata(
f48B_m2_puliti, risultato48Bm2["uf2b"].loc[risultato48Bm2["f2b"].isin(f48B_m2_puliti)]
)
f48B_m3, u48B_m3, chi2_48B_m3, dof_48B_m3, P_48B_m3 = media_pesata(
f48B_m3_puliti, risultato48Bm3["uf3"].loc[risultato48Bm3["f3"].isin(f48B_m3_puliti)]
)
f2a = _p * _m / (1 + _m) f252B_m1, u252B_m1, chi2_252B_m1, dof_252B_m1, P_252B_m1 = media_pesata(
f252B_m1_puliti, risultato252Bm1["uf1"].loc[risultato252Bm1["f1"].isin(f252B_m1_puliti)]
)
f252B_m2, u252B_m2, chi2_252B_m2, dof_252B_m2, P_252B_m2 = media_pesata(
f252B_m2_puliti, risultato252Bm2["uf2b"].loc[risultato252Bm2["f2b"].isin(f252B_m2_puliti)]
)
f252B_m3, u252B_m3, chi2_252B_m3, dof_252B_m3, P_252B_m3 = media_pesata(
f252B_m3_puliti, risultato252Bm3["uf3"].loc[risultato252Bm3["f3"].isin(f252B_m3_puliti)]
)
dati.calc_var(f2a, "f2a") risultati_finali = pd.DataFrame({
"48B - m1": [f48B_m1, u48B_m1, chi2_48B_m1, dof_48B_m1, P_48B_m1],
"48B - m2": [f48B_m2, u48B_m2, chi2_48B_m2, dof_48B_m2, P_48B_m2],
"48B - m3": [f48B_m3, u48B_m3, chi2_48B_m3, dof_48B_m3, P_48B_m3],
"252B - m1": [f252B_m1, u252B_m1, chi2_252B_m1, dof_252B_m1, P_252B_m1],
"252B - m2": [f252B_m2, u252B_m2, chi2_252B_m2, dof_252B_m2, P_252B_m2],
"252B - m3": [f252B_m3, u252B_m3, chi2_252B_m3, dof_252B_m3, P_252B_m3],
}, index=["f [cm]", "u [cm]", "chi2", "dof", "P"]).T
res_2a = dati.analisi_stat[ risultati_finali["u_corr [cm]"] = risultati_finali["u [cm]"] * np.sqrt(
["f2a", "uf2a", "%uf2a_p", "%uf2a_lFreccia", "%uf2a_lunghezzaOggetto"] np.maximum(1, risultati_finali["chi2"] / risultati_finali["dof"])
] )
res_2a risultati_finali
return f2a, res_2a return (risultati_finali,)
@app.cell(hide_code=True) @app.cell(hide_code=True)
def _(mo): def _(
mo.md(r""" cartella_immagini,
## Metodo 2b — $q$ e ingrandimento media_pesata,
""") plot_gauss,
return rimuovi_outlier,
risultati_finali,
risultato252Bm2_senza,
risultato48Bm2_senza,
):
f48B_m2_senza_puliti, _ = rimuovi_outlier(
risultato48Bm2_senza["f2b_senza"].to_numpy(),
risultato48Bm2_senza["uf2b_senza"].mean(),
)
f252B_m2_senza_puliti, _ = rimuovi_outlier(
risultato252Bm2_senza["f2b_senza"].to_numpy(),
risultato252Bm2_senza["uf2b_senza"].mean(),
)
f48B_m2_senza, u48B_m2_senza, _, _, _ = media_pesata(
f48B_m2_senza_puliti,
risultato48Bm2_senza["uf2b_senza"].loc[
risultato48Bm2_senza["f2b_senza"].isin(f48B_m2_senza_puliti)
],
)
f252B_m2_senza, u252B_m2_senza, _, _, _ = media_pesata(
f252B_m2_senza_puliti,
risultato252Bm2_senza["uf2b_senza"].loc[
risultato252Bm2_senza["f2b_senza"].isin(f252B_m2_senza_puliti)
],
)
@app.cell(hide_code=True)
def _(f2b, mo, sp):
mo.md(f"""
$f = {sp.latex(f2b)}$
""")
return
@app.cell
def _(dati, sp):
_q, _lF, _L = sp.symbols("q lFreccia lunghezzaOggetto", positive=True)
_m = _lF / _L
f2b = _q / (1 + _m)
dati.calc_var(f2b, "f2b")
res_2b = dati.analisi_stat[
["f2b", "uf2b", "%uf2b_q", "%uf2b_lFreccia", "%uf2b_lunghezzaOggetto"]
]
res_2b
return f2b, res_2b
@app.cell(hide_code=True)
def _(mo):
mo.md(r"""
## Metodo 3 — Bessel
Sorgente e schermo sono a distanza fissa $D>4f$. Esistono due posizioni della lente, distanti $d$ tra loro, con immagine nitida.
Per la prima (A) $p_A=\frac{D-d}{2}$, $q_A=\frac{D+d}{2}$, quindi
$$f=\frac{p_Aq_A}{p_A+q_A}=\frac{D^2-d^2}{4D}$$
Ogni coppia di righe dà **una** stima di $f$.
Le quattro misure $p_A,q_A,p_B,q_B$ misurano tutte $D$ e $d$ (con A = posizione a $p$ minore):
$$D=\frac{p_A+q_A+p_B+q_B}{2},\qquad d=\frac{p_B-p_A+q_A-q_B}{2}$$
**Attenzione alla propagazione:** $D$ e $d$ sono combinazioni delle stesse quattro misure, quindi *non* sono indipendenti.
Propagare $f(D,d)$ trattandoli come indipendenti sbaglierebbe l'incertezza: $f$ viene perciò propagata direttamente da $p_A,q_A,p_B,q_B$ (che sono misure indipendenti). $D$ e $d$ (con le loro incertezze) sono calcolati solo per i controlli.
""")
return
@app.cell
def _(dati, pd):
_s = dati.analisi_stat
assert len(_s) % 2 == 0, "Bessel: servono righe a coppie (0-1, 2-3, ...)"
_righe, _etichette = [], []
for _k in range(0, len(_s), 2):
_a, _b = _s.iloc[_k], _s.iloc[_k + 1]
if float(_a["p"]) > float(_b["p"]): # A = posizione con p minore
_a, _b = _b, _a
_righe.append({
"pA": float(_a["p"]), "upA": float(_a["up"]),
"qA": float(_a["q"]), "uqA": float(_a["uq"]),
"pB": float(_b["p"]), "upB": float(_b["up"]),
"qB": float(_b["q"]), "uqB": float(_b["uq"]),
})
_etichette.append(f"{_k}-{_k + 1}")
coppie = pd.DataFrame(_righe, index=_etichette)
coppie
return (coppie,)
@app.cell
def _(Data, coppie, dati, sp):
_pA, _qA, _pB, _qB = sp.symbols("pA qA pB qB", positive=True)
_D = (_pA + _qA + _pB + _qB) / 2
_d = (_pB - _pA + _qA - _qB) / 2
f3 = (_D**2 - _d**2) / (4 * _D)
datiBessel = Data(dati.campione, analisi_stat=coppie.copy())
datiBessel.calc_var(_D, "D")
datiBessel.calc_var(_d, "d")
datiBessel.calc_var(f3, "f3")
res_3 = datiBessel.analisi_stat[
["D", "uD", "d", "ud", "f3", "uf3", "%uf3_pA", "%uf3_qA", "%uf3_pB", "%uf3_qB"]
]
res_3.index = coppie.index
res_3
return (res_3,)
@app.cell(hide_code=True)
def _(mo):
mo.md(r"""
### Controlli di consistenza del metodo di Bessel
- $D$ deve essere uguale nelle due righe: $p_A+q_A$ vs $p_B+q_B$
- $d$ misurato con $p$ ($p_B-p_A$) e con $q$ ($q_A-q_B$) deve coincidere
- condizione di applicabilità $D>4f$
Compatibilità con `compat` (k < 2).
""")
return
@app.cell
def _(compat, coppie, np, pd, res_3):
_c = coppie
_DA, _uDA = _c.pA + _c.qA, np.sqrt(_c.upA**2 + _c.uqA**2)
_DB, _uDB = _c.pB + _c.qB, np.sqrt(_c.upB**2 + _c.uqB**2)
_dp, _udp = _c.pB - _c.pA, np.sqrt(_c.upA**2 + _c.upB**2)
_dq, _udq = _c.qA - _c.qB, np.sqrt(_c.uqA**2 + _c.uqB**2)
_kD, _ = compat(_DA, _DB, _uDA, _uDB)
_kd, _ = compat(_dp, _dq, _udp, _udq)
controlli_bessel = pd.DataFrame({
"D_A": _DA, "D_B": _DB, "k(D)": _kD, "D compatibili": _kD < 2,
"d da p": _dp, "d da q": _dq, "k(d)": _kd, "d compatibili": _kd < 2,
"D > 4f": res_3["D"] > 4 * res_3["f3"],
})
controlli_bessel
return
@app.cell(hide_code=True)
def _(mo):
mo.md(r"""
## Risultati finali
Per ogni metodo si combinano le stime (una per configurazione; una per
coppia nel metodo 3) con la **media pesata** ($w_i = 1/u_i^2$). Si
riportano anche $\chi^2$ e $P(\chi^2)$ di compatibilità delle stime con
un valore costante: se $\chi^2/\mathrm{dof}>1$ l'incertezza va ingrandita
di $\sqrt{\chi^2/\mathrm{dof}}$ (colonna `u_corr`).
""")
return
@app.cell
def _(np, pd, res_1, res_2a, res_2b, res_3, stats):
def media_pesata(f, uf):
f, uf = np.asarray(f, float), np.asarray(uf, float)
w = 1 / uf**2
fm = np.sum(w * f) / np.sum(w)
ufm = 1 / np.sqrt(np.sum(w))
chi2 = np.sum(w * (f - fm) ** 2)
dof = len(f) - 1
return fm, ufm, chi2, dof, stats.chi2.sf(chi2, dof)
_righe = {}
for _nome, _res, _c in [
("1 - punti coniugati", res_1, "f1"),
("2a - p e ingrandimento", res_2a, "f2a"),
("2b - q e ingrandimento", res_2b, "f2b"),
("3 - Bessel", res_3, "f3"),
]:
_fm, _u, _chi2, _dof, _P = media_pesata(_res[_c], _res[f"u{_c}"])
_righe[_nome] = {
"f [cm]": _fm, "u": _u,
"chi2": _chi2, "dof": _dof, "P": _P,
"u_corr": _u * np.sqrt(max(1.0, _chi2 / _dof)),
}
risultati = pd.DataFrame(_righe).T
risultati
return (risultati,)
@app.cell(hide_code=True)
def _(mo):
mo.md(r"""
## Compatibilità tra i metodi e confronto grafico
""")
return
@app.cell
def _(compat, pd, risultati):
_nomi = list(risultati.index)
_righe = []
for _i in range(len(_nomi)):
for _j in range(_i + 1, len(_nomi)):
_a, _b = risultati.loc[_nomi[_i]], risultati.loc[_nomi[_j]]
_k, _diff = compat(_a["f [cm]"], _b["f [cm]"], _a["u_corr"], _b["u_corr"])
_righe.append({"metodi": f"{_nomi[_i][:2].strip()} vs {_nomi[_j][:2].strip()}",
"differenza": _diff, "k": _k,
"compatibili (k<2)": bool(_k < 2)})
pd.DataFrame(_righe).set_index("metodi")
return
@app.cell
def _(plot_gauss, risultati):
plot_gauss([ plot_gauss([
(r["f [cm]"], r["u_corr"], _i, _n.strip()) (
for _i, (_n, r) in enumerate(risultati.iterrows()) risultati_finali.loc["48B - m1", "f [cm]"],
]) risultati_finali.loc["48B - m1", "u_corr [cm]"],
0,
"48B m1",
),
(
risultati_finali.loc["48B - m2", "f [cm]"],
risultati_finali.loc["48B - m2", "u_corr [cm]"],
1,
"48B m2",
),
(
risultati_finali.loc["48B - m3", "f [cm]"],
risultati_finali.loc["48B - m3", "u_corr [cm]"],
2,
"48B m3",
)
], cartella_immagini / "1.png", "Lente 48B - correzione angolare")
plot_gauss([
(
risultati_finali.loc["252B - m1", "f [cm]"],
risultati_finali.loc["252B - m1", "u_corr [cm]"],
3,
"252B m1",
),
(
risultati_finali.loc["252B - m2", "f [cm]"],
risultati_finali.loc["252B - m2", "u_corr [cm]"],
4,
"252B m2",
),
(
risultati_finali.loc["252B - m3", "f [cm]"],
risultati_finali.loc["252B - m3", "u_corr [cm]"],
5,
"252B m3",
),
], cartella_immagini / "2.png", "Lente 252B - correzione angolare")
plot_gauss([
(
risultati_finali.loc["48B - m1", "f [cm]"],
risultati_finali.loc["48B - m1", "u_corr [cm]"],
0,
"48B m1",
),
(f48B_m2_senza, u48B_m2_senza, 1, "48B m2 senza correzione"),
(
risultati_finali.loc["48B - m3", "f [cm]"],
risultati_finali.loc["48B - m3", "u_corr [cm]"],
2,
"48B m3",
),
], cartella_immagini / "3.png", "Lente 48B - senza correzione angolare")
plot_gauss([
(
risultati_finali.loc["252B - m1", "f [cm]"],
risultati_finali.loc["252B - m1", "u_corr [cm]"],
3,
"252B m1",
),
(f252B_m2_senza, u252B_m2_senza, 4, "252B m2 senza correzione"),
(
risultati_finali.loc["252B - m3", "f [cm]"],
risultati_finali.loc["252B - m3", "u_corr [cm]"],
5,
"252B m3",
),
], cartella_immagini / "4.png", "Lente 252B - senza correzione angolare")
return
@app.cell
def _(compat, pd, risultati_finali):
k_48B_m1_m2, diff_48B_m1_m2 = compat(
risultati_finali.loc["48B - m1", "f [cm]"],
risultati_finali.loc["48B - m2", "f [cm]"],
risultati_finali.loc["48B - m1", "u_corr [cm]"],
risultati_finali.loc["48B - m2", "u_corr [cm]"],
)
k_48B_m1_m3, diff_48B_m1_m3 = compat(
risultati_finali.loc["48B - m1", "f [cm]"],
risultati_finali.loc["48B - m3", "f [cm]"],
risultati_finali.loc["48B - m1", "u_corr [cm]"],
risultati_finali.loc["48B - m3", "u_corr [cm]"],
)
k_48B_m2_m3, diff_48B_m2_m3 = compat(
risultati_finali.loc["48B - m2", "f [cm]"],
risultati_finali.loc["48B - m3", "f [cm]"],
risultati_finali.loc["48B - m2", "u_corr [cm]"],
risultati_finali.loc["48B - m3", "u_corr [cm]"],
)
k_252B_m1_m2, diff_252B_m1_m2 = compat(
risultati_finali.loc["252B - m1", "f [cm]"],
risultati_finali.loc["252B - m2", "f [cm]"],
risultati_finali.loc["252B - m1", "u_corr [cm]"] ,
risultati_finali.loc["252B - m2", "u_corr [cm]"] ,
)
k_252B_m1_m3, diff_252B_m1_m3 = compat(
risultati_finali.loc["252B - m1", "f [cm]"],
risultati_finali.loc["252B - m3", "f [cm]"],
risultati_finali.loc["252B - m1", "u_corr [cm]"] ,
risultati_finali.loc["252B - m3", "u_corr [cm]"] ,
)
k_252B_m2_m3, diff_252B_m2_m3 = compat(
risultati_finali.loc["252B - m2", "f [cm]"],
risultati_finali.loc["252B - m3", "f [cm]"],
risultati_finali.loc["252B - m2", "u_corr [cm]"] ,
risultati_finali.loc["252B - m3", "u_corr [cm]"] ,
)
confronti_metodi = pd.DataFrame({
"48B m1 vs m2": [k_48B_m1_m2, diff_48B_m1_m2, k_48B_m1_m2 < 2],
"48B m1 vs m3": [k_48B_m1_m3, diff_48B_m1_m3, k_48B_m1_m3 < 2],
"48B m2 vs m3": [k_48B_m2_m3, diff_48B_m2_m3, k_48B_m2_m3 < 2],
"252B m1 vs m2": [k_252B_m1_m2, diff_252B_m1_m2, k_252B_m1_m2 < 2],
"252B m1 vs m3": [k_252B_m1_m3, diff_252B_m1_m3, k_252B_m1_m3 < 2],
"252B m2 vs m3": [k_252B_m2_m3, diff_252B_m2_m3, k_252B_m2_m3 < 2],
}, index=["k", "differenza [cm]", "compatibili (k < 2)"]).T
confronti_metodi
return
@app.cell(hide_code=True)
def _(mo):
mo.md(r"""
# Parte interessante
Ora ragioniamo sul perché avvengono certi fenomeni.
Risulta facile comprendere che il metodo 2 è quello più _sballato_ perché?
Probabilmente abbiamo sofferto nel prendere h che subisce effetti di distorsione dovuti al fatto di avere lo schermo non fissato
una correzione di 15° è già sufficiente a sistemare il problema. Ovviamente oltre la correzione bisogna aggiungere degli errori su questa idea che sono $\sim$al valore stesso
Sicuramente ci sono altri errori strumentali non considerati correttamente in quanto i $\chi^2$ son completamente fuori scala
""")
return return
+1
View File
@@ -5,6 +5,7 @@ description = "Add your description here"
readme = "README.md" readme = "README.md"
requires-python = ">=3.14" requires-python = ">=3.14"
dependencies = [ dependencies = [
"altair>=6.3.0",
"marimo>=0.25.0", "marimo>=0.25.0",
"matplotlib>=3.11.2", "matplotlib>=3.11.2",
"numpy>=2.5.3", "numpy>=2.5.3",
+110 -16
View File
@@ -1,6 +1,6 @@
import marimo import marimo
__generated_with = "0.25.0" __generated_with = "0.25.2"
app = marimo.App() app = marimo.App()
@@ -163,7 +163,7 @@ def _(np, pd, stats):
return campione, rimossi return campione, rimossi
def stat_chauv(self, prefissi, err_strumentale): def stat_chauv(self, prefissi, err_strumentale, err_della_media = True):
campione_df = self.campione # riferimento al DataFrame originale (non sovrascritto) campione_df = self.campione # riferimento al DataFrame originale (non sovrascritto)
if isinstance(prefissi, str): if isinstance(prefissi, str):
@@ -185,15 +185,16 @@ def _(np, pd, stats):
valori_puliti, rimossi = rimuovi_outlier(valori, err_strum) valori_puliti, rimossi = rimuovi_outlier(valori, err_strum)
n = len(valori_puliti) n = len(valori_puliti)
s = valori_puliti.std(ddof=1) / np.sqrt(n) s = valori_puliti.std(ddof=1)
if err_della_media: s /= np.sqrt(n)
u = np.sqrt(s**2 + err_strum**2) u = np.sqrt(s**2 + err_strum**2)
self.analisi_stat.at[i, prefix] = valori_puliti.mean() self.analisi_stat.loc[i, prefix] = valori_puliti.mean()
self.analisi_stat.at[i, f"u{prefix}_strum"] = err_strum self.analisi_stat.loc[i, f"u{prefix}_strum"] = err_strum
self.analisi_stat.at[i, f"u{prefix}_stat"] = s self.analisi_stat.loc[i, f"u{prefix}_stat"] = s
self.analisi_stat.at[i, f"u{prefix}"] = u self.analisi_stat.loc[i, f"u{prefix}"] = u
self.analisi_stat.at[i, f"n{prefix}"] = n self.analisi_stat.loc[i, f"n{prefix}"] = n
self.analisi_stat.at[i, f"out{prefix}"] = rimossi self.analisi_stat.loc[i, f"out{prefix}"] = rimossi
return self return self
@@ -201,6 +202,95 @@ def _(np, pd, stats):
return return
@app.cell(hide_code=True)
def _(mo):
mo.md(r"""
# Media pesata
input:
- array x: valori
- array ux: uvalori
output:
- xm: x medio
- uxm: sigma x medio
- chi2: $\chi^2$
- dof: gradi di libertà
- Pchi2: $P(\chi^2)$
data:
- prefix: prefisso del nome della variabile
""")
return
@app.cell
def _(np, stats):
def media_pesata(x, ux):
x, ux = np.asarray(x, float), np.asarray(ux, float)
w = 1 / ux**2
xm = np.sum(w * x) / np.sum(w)
uxm = 1 / np.sqrt(np.sum(w))
chi2 = np.sum(w * (x - xm) ** 2)
dof = len(x) - 1
return xm, uxm, chi2/dof, dof, stats.chi2.sf(chi2, dof)
def media_pesata_data(self, prefix):
return media_pesata(self.analisi_stat[prefix], self.analisi_stat[f"u{prefix}"])
Data.media_pesata = media_pesata_data
return
@app.cell
def _(np, stats):
def media_pesata_dersimonian_laird(x, ux):
x, ux = np.asarray(x, float), np.asarray(ux, float)
n = len(x)
dof = n - 1
if n <= 1:
raise ValueError("Il dataset deve contenere almeno due misure.")
if np.any(ux <= 0):
raise ValueError("Le incertezze (ux) devono essere strettamente maggiori di zero.")
# --- STEP 1: Calcolo standard (Effetti Fissi) per stimare il Chi2 originale ---
w_fixed = 1 / ux**2
sum_w_fixed = np.sum(w_fixed)
xm_fixed = np.sum(w_fixed * x) / sum_w_fixed
chi2_fixed = np.sum(w_fixed * (x - xm_fixed) ** 2)
# --- STEP 2: Stima della varianza extra (Tau^2) ---
# Formula di DerSimonian-Laird
sum_w2_fixed = np.sum(w_fixed**2)
numerator = chi2_fixed - dof
denominator = sum_w_fixed - (sum_w2_fixed / sum_w_fixed)
# Tau^2 non può essere negativo. Se il Chi2 è minore del dof, Tau^2 = 0
tau2 = max(0.0, numerator / denominator)
# --- STEP 3: Ricalcolo con Effetti Casuali (Random Effects) ---
w_random = 1 / (ux**2 + tau2)
sum_w_random = np.sum(w_random)
xm_random = np.sum(w_random * x) / sum_w_random
uxm_random = 1 / np.sqrt(sum_w_random)
# Nota: Il p-value finale del Chi2 si riferisce alla consistenza iniziale dei dati
p_value = stats.chi2.sf(chi2_fixed, dof)
return {
"media": xm_random,
"errore_media": uxm_random,
"tau2": tau2,
"tau": np.sqrt(tau2),
"chi2_originale": chi2_fixed,
"dof": dof,
"p_value": p_value
}
return
@app.cell(hide_code=True) @app.cell(hide_code=True)
def _(mo): def _(mo):
mo.md(r""" mo.md(r"""
@@ -589,7 +679,7 @@ def _(mo):
@app.cell @app.cell
def _(np, plt, sns, stats): def _(np, plt, sns, stats):
def plot_gauss(gaussiane): def plot_gauss(gaussiane, percorso=None, titolo="Confronto dei metodi"):
# Creazione figura # Creazione figura
plt.figure(figsize=(12, 7)) plt.figure(figsize=(12, 7))
@@ -600,10 +690,10 @@ def _(np, plt, sns, stats):
for mu, sigma, _, _ in gaussiane: for mu, sigma, _, _ in gaussiane:
minimoLocale = mu - 4 * sigma minimoLocale = mu - 4 * sigma
massimoLocale = mu + 4 * sigma massimoLocale = mu + 4 * sigma
if minimoLocale < xMin: if minimoLocale < xMin:
xMin = minimoLocale xMin = minimoLocale
if massimoLocale > xMax: if massimoLocale > xMax:
xMax = massimoLocale xMax = massimoLocale
@@ -613,7 +703,7 @@ def _(np, plt, sns, stats):
for mu, sigma, colore, etichetta in gaussiane: for mu, sigma, colore, etichetta in gaussiane:
y = stats.norm.pdf(x, mu, sigma) y = stats.norm.pdf(x, mu, sigma)
plt.plot(x, y, color=sns.color_palette()[colore], linewidth=1, label=etichetta) plt.plot(x, y, color=sns.color_palette()[colore], linewidth=1, label=etichetta)
puntiLinee = [mu - sigma, mu, mu + sigma] puntiLinee = [mu - sigma, mu, mu + sigma]
for px in puntiLinee: for px in puntiLinee:
py = stats.norm.pdf(px, mu, sigma) py = stats.norm.pdf(px, mu, sigma)
@@ -621,13 +711,17 @@ def _(np, plt, sns, stats):
ymin=0, ymax=py, ymin=0, ymax=py,
colors=sns.color_palette()[colore], colors=sns.color_palette()[colore],
linestyles='dashed', linewidth=1) linestyles='dashed', linewidth=1)
# Dettagli estetici finali # Dettagli estetici finali
plt.ylim(bottom=0) plt.ylim(bottom=0)
plt.title('Confronto dati') plt.title(titolo)
plt.xlabel('k') plt.xlabel('Focale Lente [$cm$]')
plt.ylabel('Densità di probabilità [$cm^{-1}$]')
plt.legend() plt.legend()
if percorso is not None:
plt.savefig(str(percorso), dpi=200, bbox_inches="tight")
# Mostriamo il grafico # Mostriamo il grafico
plt.show() plt.show()