ROOT III (I/O+TTree+TNtuple) Grzegorz Stefanek Jan Kochanowski University Grzegorz Stefanek 1
Struktura plików ROOT ROOT operacje I/O - pliki ROOT mają strukturę katalogu w których podkatalogi i obiekty są zorganizowane w nieograniczoną ilość poziomów - format plików ROOT jest niezależny maszynowo - w programach/skryptach plik jest obiektem klasy TFile - struktura i zawartość pliku może być przegłądana z użyciem przeglądarki, tzn. obiektu klasy TBrowser - struktura fizyczna i własności pliku mogą być przeglądane z wykorzystaniem metody TFile::Map() - każdy plik ROOT posiada nagłówek opisujący podstawowe parametry/własności pliku - wszystkie klasy zapisane w pliku są opisane w liście zwanej StreamerInfo -bezpośredni (nie-sekwencyjny) dostęp do elementów pliku zapewniają klucze (TKeys) będace obiektami klasy TKey oraz metoda TFile::Get() Grzegorz Stefanek 2
Struktura plików ROOT ROOT operacje I/O Przykład: { char name[10],title[10]; TObjArray Hlist(0); //utworzenie tablicy histogramów TH1F *h; //utworzenie wskaźnika do hist // utworzenie 15 histogramów i dodanie do tablicy obiektów for (Int_t i=0;i<15;i++) { sprintf(name, h%d,i); sprintf(title, histogram nr:%d,i); h = new TH1F(name,title,100,-4,4); Hlist.Add(h); h->fillrandom( gaus,1000); } // otwarcie pliku i zapis tablicy histogramów TFile f( histogramy.root, recreate ); Hlist.Write(); f.close(); } Grzegorz Stefanek 3
ROOT operacje I/O Struktura plików ROOT Otwieranie, przeglądanie plików: Tfile f( demo.root ); Tbrowser browser; Sprawdzenie poprawności otwarcia pliku: Tfile f( histogramy.root ); if(f.iszombie() { cout<< Blad otwarcia pliku <<endl; exit(-1); } else {. } Grzegorz Stefanek 4
ROOT operacje I/O Struktura plików ROOT f.map() nagłowek histogramy StreamerInfo data/czas adres liczba klasa wspólczynnik pocz. bytow kompresji rekordu Grzegorz Stefanek 5
Struktura plików ROOT ROOT operacje I/O Nagłówek pliku zawiera szczegółowe informacje o pliku i pozwala zidentyfikować go jako zgodnego z formatem ROOT. fversion pośrednio wskazuje na rozmiar pliku. nfree i fnbytesfree opisuje obszar pliku dostepny do wykorzystania. Grzegorz Stefanek 6
Struktura plików ROOT ROOT operacje I/O StreamerInfo zawiera szczegółowe informacje o wszystkich klasach zapisanych w pliku, dostępne przez polecenie Tfile::ShowStreamerInfo. W rzeczywistości polecenie to pokazuje jedynie pierwsza linie opisu. Grzegorz Stefanek 7
Struktura plików ROOT ROOT operacje I/O ROOT zawiera zlożony mechanizm odzyskiwania zawartosci plików w przypadku problemów podczas sesji, TFile::Recover() Metoda TFile::Map() odczytuje informacje sekwencyjnie. Dostęp sekwencjny jest niewystarczający gdy przeprowadzamy analizę. Potrzebny jest bezpośredni dostęp do obiektów w pliku z wykorzystaniem kluczy (TKeys) pełniących role indeksów obiektów. Grzegorz Stefanek 8
ROOT operacje I/O Struktura plików ROOT Metoda TFile::Get() znajduje obiekt o kluczu TKey o żądanej nazwie, TH1F *h9 = (TH1F*)f.Get( h9 ); Przykład. (FileKey.C) TFile f( histogramy.root ); TIter next(f.getlistofkeys()); TKey *key; while((key=(tkey*)next())) { printf( key:%s points to an object of class: %s at %d\n, key->getname(); key->getclassname(), key->getseekkey()); } Grzegorz Stefanek 9
ROOT operacje I/O Struktura plików ROOT Przykład. (FileKey.C) output Obok listy kluczy występują też inne listy: TFile::fFree, TFile::fListHead Grzegorz Stefanek 10
ROOT operacje I/O Struktura plików ROOT Grzegorz Stefanek 11
Struktura plików ROOT ROOT operacje I/O Obiekt klasy TFile zachowuje się jak obiekt klasy TDirectory (jest katalogiem). Jak w każdym katalogu można wyświetlać jego zawartość i tworzyć podkatalogi. Podczas sesji ROOT cały czas jesteśmy w katalogu, bierzacy katalog jest przechowywany w gdirectory. TFile f( histogramy.root ); f.ls(); // wyświetlenie zawartości pliku gdirectory->pwd(); // bierzący katalog gdirectory->ls( -m ); // obiekty w pamięci gdirectory->ls( -d ); // obiekty na dysku gdirectory->getlist()->ls(); // lista obiektow w pamięci hist->setdirectory(newdir); // histogram w nowym katalogu hist->write(); // zapis obiektu na dysk f->write(); // zapis wszystkich obiektów na dysk f->close(); // zamknięcie pliku Grzegorz Stefanek 12
ROOT TTree/TNtuple Dla zapisywania dużej liczby obiektów tej samej klasy ROOT udostępnia specjalnie do tego celu przeznaczone klasy TTree (drzewo), TNtuple. Klasa Ttree została zoptymizowana w celu ograniczenia zajmowanej przestrzeni dyskowej oraz zwiększenia szybkości dostępu do obiektów w pliku. TTree pozwala na przechowanie wszystkich typów (prostych i złożonych) danych: obiektów i tablic obiektów. TNtuple jest przeznaczone do przechowywania liczb rzeczywistych. W Ttree zapisujemy bufory danych zwane gałęziami i wypełniamy je danymi pełniącymi rolę liści. Bufory są zapisywane, gdy zostaną całkowicie zapełnione. Obiekty w TTree nie są zapisywane pojedyńczo lecz grupowane i zapisywane grupowo, dlatego pliku tworzone są mniejsze niż dla obiektów zapisywanych pojedyńczo. Grzegorz Stefanek 13
ROOT TTree/TNtuple Użycie TTree pozwala na znaczące skompresowanie nagłówków obiektów, całkowity nagłówek jest redukowany z 60 do 4 bajtów. TTree optymizuje czas dostępu do pliku. Dane są zapisywane w gałęziach pliku, a każda gałąź może być odczytana niezależnie od wszystkich pozostałych. Przykład: Załóżmy że mamy 1mln przypadków zawierających dane Px, Py, a chcemy policzyć Px 2 + Py 2 dla każdego przypadku i wypełnić histogram. Dla danych zapisanych standardowo (bez TTree) należy wykonać: wczytać do pamięci każdy przypadek w całości pobrać Px, Py dla każdego przypadku policzyć Px 2 + Py 2 wypełnić histogram Musimy to wykonać 1mln razy co jest bardzo czasochłonne, a przecież nie potrzebujemy całych przypadków. Grzegorz Stefanek 14
ROOT TTree/TNtuple Jeśli używamy TTree z jedną gałęzią zawierającą Px, a drugą zawierająca Py. Wówczas możemy przeczytać wszystkie wartości Px, Py czytając jedynie gałęzie Px, Py. Przykład: Proste drzewo (TTree), staff.root/ staff.c / cernstaff.dat Cechy skryptu: definiuje strukturę staff_t opisującą cechy personelu CERNu otwiera plik ASCII, tworzy plik..root oraz drzewo TTree tworzy trzy gałęzie drzewa /staff, Division, Nation/ wraz z adresami początkowymi liści w oparciu o strukturę staff_t wczytuje dane z pliku ASCII i zapisuje do struktury staff oraz wypełnia drzewo tree zamyka plik ASCII i zapisuje plik ROOT (z drzewem tree) na dysk f->write() zapisuje drzewo tree drzewo jest zapisane w pliku staff.root Grzegorz Stefanek 15
ROOT TTree/TNtuple Dostęp do wejść w ramach drzewa zapewnia metoda TTree::Show. Przykładowy dostęp do wejścia nr 10: TFile f( staff.root ); T->Show(10); Grzegorz Stefanek 16
ROOT TTree/TNtuple Dostęp do struktury drzewa (ilość wejść, gałęzie, drzewa) zapewnia metoda TTree::Print. Przykładowy dostęp do struktury drzewa: T->Print(); Grzegorz Stefanek 17
ROOT TTree/TNtuple Przeskanowanie zawartości wybranych liści w ramach drzewa zapewnia metoda TTree::Scan Przykładowe skanowanie kilku liści w ramach drzewa T->Scan( Cost:Age:Children ); Grzegorz Stefanek 18
TTree Viewer (przeglądarka drzew). ROOT TTree/TNtuple TTree Viewer pozwala na szybkie i proste przeglądanie struktury i własności drzew w plikach. Uruchamianie: - klikniecie myszą na TTree i wyselekcjonowanie StartViewer - TFile f( staff.root ); T->StartViewer() - gsystem->load( libtreeviewer.so ); new TTreeViewer(); // start TTree Viewer bez pliku Grzegorz Stefanek 19
ROOT TTree/TNtuple TTree Viewer (przeglądarka drzew). Komendy użytkownika Opcje rysowania Nazwa histogramu -> Panel z listą drzew i ich gałęzi <- Panel z listą zmiennych i liści Grzegorz Stefanek 20
ROOT TTree/TNtuple TTree Viewer (przeglądarka drzew). Przełącznik modu rysowania histogramu Przekierowanie TTree::Scan do pliku ASCII Zapis sesji do pliku historii Rysowanie wielowymiarowych histogramów Grzegorz Stefanek 21
TTree Viewer (przeglądarka drzew). Pasek ustawiania początku, końca zakresu wejść ROOT TTree/TNtuple Nazwa listy wejściowej (TList) Nazwa listy wyjściowej (TList) Grzegorz Stefanek 22
TBranch gałęzie drzewa ROOT TTree/TNtuple gałąź jest elementem drzewa i jest klasy TBranch dla dodania gałęzi do drzewa należy uzyć metody TTree::Branch() organizacja gałęzi pozwala na zoptymalizowanie danych dla projektowanego ich użycia jeśli dwie zmienne są niezależne i nie będą używane razem to powinny być umieszczone w osobnych gałęziach jeśli zmienne są związane (jak np. współrzędne punktów) to należy je umieścić w tej samej gałęzi każda z gałęzi może być zapisywana do oddzielnego pliku gałęzie mogą się znacznie różnic w zależności od tego jakie informacje (listy zmiennych prostych, całe złożone obiekty, zawartość katalogu, tablice obiektów) są w nich zapisane Grzegorz Stefanek 23
TBranch gałąź z listą zmiennych ROOT TTree/TNtuple Tworzenie listy: tree->branch( EV_Branch,&event, temp/f:ntrack/i:nseq:flag/i ); gdzie EV_Branch nazwa gałęzi &event adress od którego musi być czytany pierwszy element listy temp/f zmienna typu rzeczywistego ntrack/i zmienna typu integer flag/i zmienna typu integer bez znaku ogólnie trzeci parametr ma postać <Zmienna>/<Typ>:<Zmienna>/<Typ> gdzie <Typ>= C łańcuch znakowy zakończony 0, B,S,I,L integer (8,16,32,64 bity) ze znakiem, b,s,i,l integer (8,16,32,64 bity) bez znaku, F,D liczba rzeczywista (32,64 bity) Brak oznaczenia typu oznacza poprzedni (w parametrze) typ lub F. Nazwy liści nie zapewniają dostąpu do zmiennych. Zmienne występujące w trzecim parametrze TTree::TBrach muszą być umieszczane w strukturze (staff.c). Grzegorz Stefanek 24
TBranch gałąź z listą zmiennych ROOT TTree/TNtuple Lista może zawierać całą tablicę zmiennych: Float_t f[10]; tree->branch( fbranch,f, f[10]/f ); w tym tablicę o zmiennym rozmiarze TFile *f = new TFile( photon.root, recreate ); Int_t nphot; Float_t E[500]; TTree* nemcphotons = new TTree( nemcphotons, EMC Photons ); nemcphotons->branch( nphot,&nphot, nphot/i ); nemcphotons->branch( E,E, E[nPhot]/F ); Grzegorz Stefanek 25
TBranch gałąź zawierająca obiekt ROOT TTree/TNtuple Przykład:.L libevent.so // biblioteka z definicja klasy Event TFile *f = new TFile( ObjectFile.root, RECREATE ); TTree *tree = new TTree( T, Object Tree ); Event *event = new Event(); // wskaznik do obiektu klasy Event tree->branch( EventBranch, Event,&event,32000,99); gdzie EventBranch nazwa gałęzi Event klasa obiektu &event adres wskaźnika do umieszczanego obiektu 32000 standardowy rozmiar bufora (32000 bytes) w tej konfiguracji 99 poziom rozszczepienia gałęzi na podgałęzie Rozszczepienie gałęzi tworzenie podgałęzi dla każdego elementu danych w ramach obiektu. Poziom rozszczepienia może wynosić 0 (1 gałąź), 1 (każdy element danych obiektu ma gałąź), 2,3, 99. Im więcej gałęzi ( rozszczepień) tym mniejszy rozmiar bufora. Grzegorz Stefanek 26
TBranch gałąź zawierająca obiekt ROOT TTree/TNtuple Dwie klasy ROOT dedykowane obiektom : TObjArray, TClonesArray. TObjArray słuzy do przechowywania obiektów różnych klas, TClonesArray przechowuje obiekty tej samej klasy czyli każdy obiekt ma ten sam rozmiar. Dla TObjArray pamięć musi być przydzielana i zwalniana dla każdego Obiektu, TClonesArray używa ciągle tego samego fragmentu pamięci. Przykład: Mamy 100.000 przypadków z 10000 śladów każdy, czyli razem 10 9 śladów. Używając TObjArray dla śladów musimy przydzielać/zwalniać pamięć 10 9 razy co wymaga kilku godzin. Używając TClonesArray nie potrzebujemy dodatkowego czasu na manipulowanie pamięcią. Grzegorz Stefanek 27
ROOT TTree/TNtuple TBranch gałęzie z katalogów, ze zbiorów elementów (kolekcji) tree->branch( /afolder ); // tworzy gałąź z każdego // elementu w katalogu // zwraca całkowitą liczbę gałęzi tree->branch(*acollection, 8000, 99, *col); gdzie acollection wskaźnik do zbioru 8000 rozmiar bufora 99 stopien rozszczepienia col nazwa rozpoczynająca każda gałąź (col_ ) Metoda Branch tworzy jedną gałąź z każdego elementu kolekcji. Poziom rozszczepienia może być różny w zależności od tego czy każdy z elementów kolekcji jest klasy TCollection czy tez nie. Grzegorz Stefanek 28
ROOT TTree/TNtuple TTree przykłady: 1) Prosty przykład zapisu i odczytu z pliku z drzewem tree1.c Zawiera główna funkcję tree1 oraz funkcje zapisu tree1w i odczytu tree1r. Jeśli skrypt nie jest uruchamiany w wersji batch to wyświetla drzewo w przeglądarce i i TreeViewer. Metody uruchomienia: >.x tree1.c // uruchamiana cala funkcja // z wykorzystaniem interpretera >.x tree1.c++ // uruchomienie po wykonaniu kompilacji // z wykorzystaniem kompilatora >.L tree1.c // wczytanie skryptu do ROOTa > tree1w() // uruchomienie funkcji ze skryptu > tree1r() // uruchomienie funkcji ze skryptu t1->setbranchaddress() ustawienie adressu do zmiennej w drzewie t1->getentry() pobranie jednego wejścia w drzewie Grzegorz Stefanek 29
ROOT TTree/TNtuple TTree przykłady: 2) Bardziej złożony przykład (tree2.c) pokazujący jak: - jak tworzyć gałęzie ze struktur C++ - jak utworzyć gałąź z tablicy o stałym rozmiarze - jak utworzyć gałąź z tablicy o zmiennym rozmiarze - jak czytać określone gałęzie - jak wypełniać histogramy z gałęzi - jak wykorzystać TTree::Draw dla prezentacji histogramu 3D W przykładzie wykorzystywany jest pakiet Geant3, a struktura jest wypełniana przez funkcje Geant3 w każdym kroku w polu magnetyczny (funkcja helixstep). Dla wypełniania drzewa wystarczy metoda TTree::Fill Tworzenie gałęzi z tablicy o stałym rozmiarze: > t2.branch( vect,gstep.vect, vect[7]/f ); Tworzenie gałęzi z tablicy o zmiennym rozmiarze: > t2.branch( nmec,&gstep.nmec, nmec/i ); > t2.branch( lmec,gstep.lmec, lmec[nmec]/i ); Grzegorz Stefanek 30
TTree przykłady: 2) Analiza w przykładzie (tree2.c): ROOT TTree/TNtuple Odczyt pojedynczej gałęzi zamiast całej struktury. > TBranch *b_destep = t2->getbranch( destep ); Ustawienie adresu do gałęzi destep. > b_destep->setaddress(&destep); Użycie metody TTree::GetEntry dla pobrania zawartości gałęzi. > b_destep->getentry(i); Wypełnienie histogramu wejściami z gałęzi destep. > hdestep->fill(destep); Narysowanie histogramu i dopasowanie funkcji Gaussa. > hdestep->fit( gaus ); Dodatkowo rysowana jest trajektoria cząstki z wykorzystaniem trzech wartości zapisanych w wektorze > t2->draw( vect[0]:vect[1]:vect[2] ); Grzegorz Stefanek 31
ROOT TTree/TNtuple TTree 3 opcje czytania (GetEntry) przypadków z drzewa: Event *event =0; T.SetBranchAddress( event,&event); 1) Standardowa (rekomendowana) for (Int_t i=0;i<nentries;i++) { T.GetEntry(i); } 2) Z wykorzystaniem AutoDelete TBranch *branch = T.GetBranch( event ); branch->setaddress(&event); branch->setautodelete(ktrue); for (Int_t i=0;i<nentries;i++) { T.GetEntry(i); } 3) Z samodzielnym kasowaniem przypadku for (Int_t i=0;i<nentries;i++) { delete event; event = 0; T.GetEntry(i); } Grzegorz Stefanek 32
ROOT TTree/TNtuple Bardziej złożone przykłady drzew w plikach: - hsimple.root (ntuple) - tree_01i_shift_pion.root (analiza efektu flow dla hiperonów Λ) - t49run4047.root (dane eksperymentu NA49 w formacie ROOT) Grzegorz Stefanek 33
ROOT Tekst/Latex Tekst może być dodawany wprost na histogramach (w oknach). Edytor posiada wbudowany element związany z edycja teksu (toolbar ) Tekst może być: - modyfikowany - przemieszczany -skalowany - obracany Grzegorz Stefanek 34
ROOT Tekst/Latex Elementy ROOT wykorzystujące Latex: -tytuły histogramów h->settitle( p_{t} distribution ); -tytuły osi histogramów h->getxaxix("p_{t} (GeV/c) "); h->getyaxis(nevents); - legenda do wykresu TLegend *legend1=new TLegend(0.25,0.58,0.4,0.8); legend1->setfillcolor(10); legend1->settextfont(72); legend1->settextsize(0.045); legend1->setbordersize(0); legend1->addentry(gr1," #pi^{+}, #pi^{-} ","p"); legend1->addentry(gr4," K^{0}_{s} ","p"); legend1->addentry(gr2," p ","p"); legend1->addentry(gr3," #Lambda ","p"); Grzegorz Stefanek 35
ROOT Tekst/Latex Elementy ROOT wykorzystujące Latex: -komentaże TLatex gty; gty->settextcolor(1); gty->settextsize(0.04); gty->settextalign(12); gty->settextangle(90); gty.drawlatex(0.95,0.006,"#gamma = 2#sigma[GeV]"); - formuły matematyczne = Grzegorz Stefanek 36
ROOT Tekst/Latex Złożone przykłady wykorzystania Latex a w pakiecie ROOT: latex.c latex2.c latex3.c symbole greckie latex4.c symbole matematyczne latex5.c Grzegorz Stefanek 37