Scopo di questa sessione di laboratorio e' sviluppare la simulazione di uno degli esperimenti del laboratorio del secondo anno.
Lo sviluppo di simulazioni trova applicazioni in molti problemi di fisica, sia sperimentale che teorica.
Ad esso sara` abbinato l'approfondimento dell'utilizzo dei pacchetti di ROOT per la determinazione dei parametri di una funzione dal best-fit ai dati presenti in un istogramma.
Una misura sperimentale consiste nella raccolta di un insieme di dati, che non
sono esatti, ma di cui è generalmente nota la distribuzione statistica (tipicamente
si assume una distribuzione gaussiana attorno al valore vero). Generalmente
questi dati vengono poi elaborati per dedurne il valore di grandezze fisiche
interessanti. Per esempio, dalle misure del periodo di oscillazione
e della lunghezza
di un pendolo, si può ricavare il valore dell'accelerazione
di gravità:
In un caso come questo, in cui la dipendenza funzionale della grandezza fisica
significativa dalle quantità misurate è relativamente semplice, possiamo stimare
l'errore su
attraverso le semplici formule di propagazione degli errori:
Tuttavia molto spesso un esperimento richiede un'analisi dei dati molto più complessa e non è possibile dare una semplice formula matematica per connettere le variabili misurate (e le loro incertezze) con le variabili derivate (e le loro incertezze). In altri casi l'ipotesi stessa di errori gaussiani non è valida. In tal caso si deve procedere ad una simulazione del processo di analisi dei dati per essere in grado di valutare se il procedimento è corretto e dare una stima delle incertezze.
In pratica il processo logico che si segue e` il seguente:
Tale processo viene anche utilizzato durante il progetto di nuovi esperimenti, per rispondere a domande del tipo: "Se voglio ottenere un certo errore sulla grandezza fondamentale X, con quale errore devo misurare le quantità osservabili W, Y e Z?"
Tutte queste domande sono di carattere statistico e, mentre spesso l'esperimento possiamo eseguirlo una volta sola, una simulazione puo` essere ripetuta un numero grande di volte e quindi ricavare le proprieta` statistiche dalla distribuzione di risultati.
In gergo spesso le parole errore ed incertezza sono utilizzate in maniera interscambiabile.
In quanto segue, useremo i due termini in maniera molto piu` specifica (notate che questa non e` una convenzione universale):
In una simulazione noi sappiamo direttamente l'errore, e dalla sua disctibuzione calcoliamo l'incertezza della misura reale.
In una misura reale, in cui il valore vero non e' conosciuto, possiamo solo parlare di incertezza.
La dipendenza dell'indice di rifrazione dalla lunghezza d'onda della luce
incidente viene descritta dalla legge di Cauchy:
L'esperienza dello spettrometro a prisma si propone di misurare l'indice di rifrazione del materiale di un prisma per le diverse lunghezze d'onda di una lampada al mercurio onde determinare i parametri A e B che caratterizzano tale materiale.
Nell'esperimento l'unico tipo di grandezze che vengono misurate sono gli angoli, per cui possiamo assumere un'incertezza uguale per tutte le misure angolari e pari a:
L'esperienza di laboratorio prevede la sequenza di misure:
|
Il programma prevede di simulare un esperimento completo:
Questo esperimento deve essere ripetuto 10000 volte, ed i risultati di ogni esperimento stampati su di un file in modo da poter poi essere analizzati con ROOT.
Si noti che la posizione iniziale della lampada e del prisma sono arbitrarie: dipendono da come li ha lasciati il gruppo che ha fatto l'esperienza il giorno prima, o potrebbero essere stati spostati casualmente. Quindi i valori veri di θ0 e θ1 sono casuali e diversi da esperimento a esperimento: possono essere presi da una distribuzione uniforme tra 0o e 360o.
La struttura del programma potrebbe essere come segue:
int main() {
int Nesperimenti=10000;
int Nlambda=7;
double n=new double[Nlambda];
// inizializzazione delle altre variabili
...
ofstream f("risultati.dat");
TRandom generatore(0);
for ( int i=0; i<Nesperimenti; i++) {
// calcolo dei valori veri per questo esperimento
...
// aggiunta degli errori di misura
...
for (int j=0; j<Nlambda; j++) {
n[j]=... // calcolo dell'indice di rifrazione
f << "\t" << n[j];
}
// per fare il fit che determina A e B, utilizzeremo una funzione
// particolare, in un primo momento possiamo tralasciare
// questo punto che completeremo piu` tardi.
// parametriCauchy(A,sigmaA,B,sigmaB,n);
// f << "\t" << A << "\t" << B;
f << endl;
}
f.close();
return 0;
}
Ci preoccuperemo in un secondo tempo di realizzare la funzione per determinare A e B dagli indici di rifrazione misurati, per il momento limitiamoci a calcolare gli indici di rifrazione misurati ed osservare delle quantita` relative ad essi.
Questa parte non e` fattibile con la distributione di ROOT per Windows distribuita nel CD, quindi deve essere eseguita o collegandosi ai PC del laboratorio, oppure con delle macro, invece che con un programma compilato.
Leggendo il frammento di codice precedente, vi sarete resi conto che questo e' un programma compilato (utilizza una funzione main), all'interno del quale vogliamo utilizzare delle classi di ROOT (il generatore di numeri casuali TRandom).
Il C++ e' molto potente nel permetterci di riutilizzare oggetti scritti da altri, ma per poterlo fare questo dobbiamo seguire strettamente alcune regole:
%.o : %.cxx
g++ -c -I$ROOT_SYS/include $<
simulazione : simulazione.o
g++ -Wall -o $@ $^ $LIBS
Fare un grafico bidimensionale degli errori per una lunghezza d'onda in
funzione degli errori su di un'altra lunghezza d'onda di vostra scelta.
Questo grafico dovrebbe mostrare un certo grado di correlazione:
Avere dati correlati, significa in pratica che, se uno dei due e`
sbagliato in una certa direzione (troppo alto o troppo basso), anche l'altro
tendera` ad avere un errore nella stessa direzione.
La correlazione viene valutata quantitativamente calcolando il coefficiente di
correlazione:
Calcolatene il valore in questo caso.
Per verificare l'origine della correlazione, provate ad azzerare tutti gli errori e poi a riattivare a turno una sola sorgente di errore. Per ognuna delle quantita` misurate, θ1, θ2, θ0 e θm(λ), valutare:
Avendo misurato dei valori di n(λ) per diverse lunghezze
d'onda, possiamo definire come migliore stima dei parametri A e
B, date le nostre misure sperimentali, quella coppia di parametri
che minimizza il χ2:
Ci sono diversi pacchetti di software che effettuano questo tipo di
minimizzazioni, noi vedremo come farlo dentro ROOT.
Il modo standard e' quello di mettere i dati in un grafico, e poi utilizzare
il metodo Fit della classe TGraph per fare
la minimizzazione. Siccome dei nostri punti noi conosciamo anche l'errore,
l'oggetto migliore per immagazzinare i dati e` un
TGraphErrors, che e` completamente analogo a un
TGraph, ma ha il metodo aggiuntivo
void SetPointError(int punto,double incertezzax,double incertezzay)
che permette di inserire degli errori su di un punto.
Un frammento di codice per impacchettare i dati potrebbe essere:
int Nlambda=7;
double lambda[7]={579.1,577.0,546.1,491.6,435.8,407.7,404.7};
double s=0.00055; // valore tipico per l'incertezza su n
TGraphErrors g;
for (int i=0; i<Nlambda; i++) {
g.SetPoint(i,lambda[i],n[i]); // punto (lambda,n)
g.SetPointError(i,0.,s); // incertezza e' 0 su lambda e 0.00055 per n
}
Il passo successivo e' definire una funzione da adattare ai dati osservati. Questa funzione dovra` dare l'indice di rifrazione in funzione della lunghezza d'onda e dipendere dai parametri A e B.
ROOT usa la classe TF1 per descrivere una funzione parametrica monodimensionale.
Ci sono due possibilita` per definire una funzione TF1:
double cauchyfun(double *x, double *p) {
return sqrt(p[0]+p[1]/(x[0]*x[0]));
}
TF1 Cauchy("Cauchy",cauchyfun,0.,10000.,2)
Al primo anno avete provato a fare fit usando delle funzioni predefinite (gaussiane e polinomi). Per queste funzioni speciali ROOT e' in grado di determinare un buon punto di partenza per la procedure di minimizzazione.
Per una funzione generica, questo non e` possibile e spetta all'utente
fornire una stima iniziale dei parametri. Questo puo` venire fatto attraverso
il metodo
void SetParameter(int parametro, double valore)
Siccome il valore di partenza alla fine puo` determinare il minimo che
viene trovato, bisogna assicurarsi di darne una posizione verosimile.
Una parte facoltativa dell'esercizio potrebbe essere verificare se il
risultato della minimizzazione dipende o meno dai valori iniziali.
Nel nostro caso specifico, potremmo inizializzare i valori di A e B con il seguente frammento di codice:
Cauchy.SetParameter(0,2.); Cauchy.SetParameter(1,50000.);
Praticamente bastera` fare:
g.Fit(Cauchy,"Q")
semplicemente per evitare di avere un uscita intricata con stampe
troppo prolisse.
Una volta effettuato il fit, dobbiamo recuperare i risultati per stamparli su file nel formato che preferiamo o metterli in un istogramma.
Questo si puo` fare utilizzando i metodi
double GetParameter(int parametro)
double GetParError(int parametro)
della classe TF1:
A = Cauchy.GetParameter(0); // parametro A sA= Cauchy.GetParError(0); // errore sul parametro A B = Cauchy.GetParameter(1); // parametro B sB= Cauchy.GetParError(1); // errore sul parametro B
Modificare il programma che calcola gli indici di rifrazione, per completare
ogni singolo esperimento con la determinazione di A e B. Questo si potrebbe
realizzare costruendo una funzione separata:
void parametriCauchy(double& A, double& sA, double& B, double& sB, double* n)
che prende come input il vettore n degli indici di
rifrazione misurati e restituisce i valori ottenuti nelle variabili
A, sA, B e
sB.
Tale funzione potete costruirla facilmente mettendo assieme nel modo opportuno tutti i frammenti di codice delle parti precedenti.
Anche in questo caso si tratta di valutare l'incertezza del metodo di misura dalla distribuzione degli scarti dei parametri A e B rispetto al proprio valore vero.
Si confronti il valore cosi' ottenuto con quello degli errori sA ed sB determinati da ROOT nei due casi:
N.B.: perche' i valori di sA ed sB e' necessario che il grafico venga costruito utilizzando le incertezze corretti su n(λ) e queste sono diverse per i due casi (nel secondo caso ci sono meno sorgenti di errore e quindi σn sara` piu` piccolo).
La motivazione di questo comportamento e' che, nel calcolo degli errori, ROOT assume che non ci sia correlazione tra i punti misurati. Questa assunzione e' vera nel secondo caso, ma non nel primo.
Il motivo per cui si assume assenza di correlazione tra i vari punti e' che le formule relative sono piu` semplici (anche le formule che il Taylor da' per i fit lineari sono valide solo in questa ipotesi).
E' possibile dare delle formule analitiche anche per il caso di punti correlati, ma sono cosi' scomode da usare che, alla fine, quasi sempre, una simulazione e' una strada piu` conveniente per ottenere la risposta corretta.
In laboratorio sono state prese delle misure di ampiezza di oscillazione in funzione della frequenza di una forzante, con un'incertezza sulla singola misura di 0.01 unita` di ampiezza. Le trovate nel file datiRisonanza.txt, in cui la prima colonna indica le frequenza in Hz e la seconda le ampiezze in unita` arbitrarie.
Presi i punti sperimentali cosi' ottenuti, provare a ricavare ampiezza, fase e frequenza facendo un fit ai dati: i valori ottenuti dal fit sono compatibili con i valori veri ottenuti dalla simulazione? Ripetere la procedura di misura e fit 100 volte e costruire un istogramma delle frequenze ottenute.