ROOT beenden:
.q
+, --, *, /
&, |, <<, >>, ~
&&, ||, !
C++ | FORTRAN | Bytes | ROOT | Bytes |
char | CHARACTER*1 | 1 | Char_t | 1 |
int | INTEGER | 2/4 | Int_t | 4 |
long | 4/8 | Long_t | 8 | |
float | REAL*4 | 4 | Float_t | 4 |
double | REAL*8 | 8 | Double_t | 8 |
root [0] 5**2 (int)25 root [1] 25.1*3.5 (double)8.78500000000000085e+01 root [2] 25.1**3.5 (double)7.92242296929665754e+04 root [3] sin(2) (double)9.09297426825681709e-01 root [4] tan(1) (double)1.55740772465490229e+00 root [5] atan(1) (double)7.85398163397448279e-01 root [6] atan(1)*4 (double)3.14159265358979312e+00 root [7] log(2) (double)6.93147180559945286e-01 root [8] exp(10) (double)2.20264657948067179e+04 root [9] exp(0) (double)1.00000000000000000e+00 root [10] exp(1) (double)2.71828182845904509e+00 root [14] 2<<10 (int)2048 root [15] 3<<10 (int)3072 root [16] sqrt(2) (double)1.41421356237309515e+00 root [17] atan2(1,1) (double)7.85398163397448279e-01 root [18] atan2(1,0) (double)1.57079632679489656e+00
Arbeiten mit ROOT heisst in der Praxis, dass man Objekte der jeweiligen ROOT Klassen erzeugt und dann Methoden dieser Objekte aufruft.
Einfaches Beispiel:
{ // book histo: tag, title, N-channels, xlow, x-high TH1F myhist("h1","Gauss Random Numbers",100,-5.,5.); // random generator object TRandom rng; for ( int i = 0; i<100000; i++ ) { double xrnd = rng.Gaus(); // Gaussian distributed Random number myhist.Fill( xrnd ); // Fill random number in histogram } myhist.Draw(); // Draw Histogramm }
root [40] Double_t s = 1; root [41] for ( Int_t i=1; i<70; i++ ) s *= i // Fakultaet root [42] s (Double_t)1.71122452428141297e+98 root [57] TMath::Gamma(70) // Dasselbe mit Gamma Fkt (Double_t)1.71122452441969184e+98
// file fak.C Double_t fak( Int_t n = 1 ) { Double_t t = 1; for ( Int_t i = 1; i <= n; i++ ) { t *= i; } return(t); } root [63] .x fak.C(99) // direkt ausfuehren 9.33262e+155 root [64] .L fak.C // oder erst Laden root [65] fak.C(99) // dann aufrufen 9.33262e+155
Zwei Arten von Macros:
int fillH1( int n=100000 ) { TH1F * h2 = new TH1F("h2","mytitle",100,0,1); for ( Int_t i = 0; i<n; i++ ) { h2->Fill(gRandom->Rndm()); } h2->Draw(); }
Optional können Argumente übergeben werden.
Alle Variablen, die in der Funktion angelegt werden, sind nach Ausführung wieder verschwunden (local scope).
{ int n=100000; TH1F * h2 = new TH1F("h2","mytitle",100,0,1); for ( Int_t i = 0; i<n; i++ ) { h2->Fill(gRandom->Rndm()); } h2->Draw(); }
Derselbe Effekt wie wenn diese Anweisungen direkt auf Root Kommandozeile eingegeben werden, insbesondere bleiben die Variablen erhalten (global scope)!
Datei wird von CINT interpretiert, es können mehrere Funktionen deklariert werden, Funktionsnamen beliebig, unabhängig von Dateiname.
Datei wird kompiliert und shared-object library erzeugt und dynamisch geladen ( myMacro_d.so).
#include <TH1F.h> #include <TRandom.h> void fillH1( int n=100000 ) { TH1F * h2 = new TH1F("h2","mytitle",100,0,1); for ( Int_t i = 0; i<n; i++ ) { h2->Fill(gRandom->Rndm()); } h2->Draw(); }
Alle verwendeten Klassen/Funktionen müssen über die entsprechenden Header Dateien deklariert werden!
Üblicher C++ Standard, sehr gute Performance.
root [60] TF1 *f1 = new TF1("f1","sin(x)", 0, 10 ); root [61] f1->Draw(); root [68] TF1 *f2 = new TF1("f2","cos(x)", 0, 10 ); root [69] f2->Draw(); root [70] f1->Draw("same"); root [76] TF1 *f4 = new TF1("f4","abs(f1)*exp(x)", 0, 10 ); root [77] f4->Draw(); root [78] TF2 *ff1 = new TF2("f5","abs(f1)*y", 0, 10, -10, 10 ); root [79] ff1->Draw()
root [83] TH1F * h1 = new TH1F("h1","mytitle",100,0,1); root [84] for ( Float_t x = 0; x<1; x += 1e-6 ) h1->Fill(x,x**3); root [85] h1->Draw(); root [80] TH1F * h2 = new TH1F("h2","mytitle",100,0,1); root [81] for ( Int_t i = 0; i<100000; i++ ) h2->Fill(gRandom->Rndm()); root [82] h2->Draw(); root [87] TH1F * h3 = new TH1F("h3","Random Gauss",100,-4,4); root [88] for ( Int_t i = 0; i<100000; i++ ) h3->Fill(gRandom->Gaus()); root [89] h3->Draw();
// file gausf.C { Int_t nit = 10, nrnd, i, j; Float_t mean[10], emean[10], xv[10], ex[10]; TH1F * h3 = new TH1F("h3","Random Gauss",100,-4,4); j =0; for ( i =0; i<nit; i++ ) { nrnd = 100*pow(2,i); xv[i] = i; ex[i] = 0.1; for ( ; j<nrnd; j++ ) { h3->Fill(gRandom->Gaus()); } h3->Fit("gaus","eq"); h3->Draw(); TF1 *fit = h3->GetFunction("gaus"); mean[i] = fit->GetParameter(1); emean[i] = fit->GetParError(1); cout << i << " Mean = " << mean[i] << " +- " << emean[i] << endl; } TCanvas *ce = new TCanvas("ce", "ce"); TGraphErrors *tg = new TGraphErrors( nit, xv, mean, ex, emean ); tg->Draw("AP"); } root [1] .x gausf.C
Ein Pointer ist eine Variable, die eine Speicheradresse enthält.
int b = 42; int *pb; // pb deklariert als pointer auf int pb = &b; // & ist Adress operator, liefert Adresse von b cout << b << endl; cout << pb << endl; // Kryptische Adresse cout << *pb << endl; // De-referenzieren: *pb == b double x = 7.256; double *px = &x; // px deklariert als pointer auf double px = &b; // illegal pointer auf double kann nicht Adresse von int nehmen
Direkte Variable vs Pointer in ROOT
{ // histogram variable direct TH1F h1("h1","mytitle",100,0,1); // h1 Variable vom Type TH1F // Object-method call: objectname.method( ... ) for ( int i = 0; i<1000000; i++ ) h1.Fill(gRandom->Rndm()); // Fill h1.Draw(); // Draw // histogram variable as pointer to hist, histo object created with new ... TH1F * h2 = new TH1F("h2","mytitle",100,0,1); // Object-method call: objectpointer->method( ... ) for ( int i = 0; i<1000000; i++ ) h2->Fill(gRandom->Rndm()); // Fill h2->Draw(); // Draw (*h2).Draw(); // altenative call (de-ref pointer).method( ... ) }
Warum Pointer?
Gültigkeitsbereich (Scope und Lifetime) von Variablen:
TH1F Makehist( int n = 100000) { // histogram variable direct TH1F h1("h1","mytitle",100,0,1); // h1 Variable vom Type TH1F // Object-method call: objectname.method( ... ) for ( int i = 0; i<n; i++ ) h1.Fill(gRandom->Rndm()); // Fill return( h1 ); // Object h1 will be deleted when function ends // returning h1 to caller requires complex copy operations --> discouraged } TH1F * Makehistp( int n = 100000) { // histogram variable direct TH1F * h1 = new TH1F("h1","mytitle",100,0,1); // h1 Variable vom Type TH1F * // Object-method call: objectname.method( ... ) for ( int i = 0; i<n; i++ ) h1->Fill(gRandom->Rndm()); // Fill return( h1 ); // Object h1 points to will stay beyond function end, // --> programmer's responsibility to delete it // returning pointer h1 to caller fine, no extra copy }
Wesentlich einfacher in Python: Alle Variablen sind quasi Pointer auf Objekte, automatisches Python Memory Management, ...
GDuckeck 2018-04-10