ROOT:Tips Tricks

 

float/double
source 

linux, gcc 4.9, glibc 2.20

root [1] float_double float min = 1.17549e-38 float max = 3.40282e+38 double min = 2.22507e-308 double max = 1.79769e+308 float epsilon = 0.0000001 19209289550781250000000000000000000000000000000000000 => 1.19209e-07 double epsilon = 0.0000000000000002 22044604925031308084726333618164062500000000 => 2.22045e-16 number   1234567890123456789012345.1234567890123456789012345 as float 1234567 946798590058299392.000000 => 1.23457e+24 as double 1234567890123456 824475648.000000 => 1.23457e+24 number   1234567890123456789012345.0 as float 1234567 946798590058299392.000000 => 1.23457e+24 as double 1234567890123456 824475648.000000 => 1.23457e+24 number   0.1234567890123456789012345 as float 0. 1234567 91043281555175781250000000000000000000000000000000000 => 0.123457 as double 0. 1234567890123456 77369886232099815970286726951599121093750000 => 0.123457 number    1234567890123456789012345 (no decimal) as float 1096246353119412224.000000 => 1.09625e+18 as double 1096246371337559936.000000 => 1.09625e+18 number   9.123e+22 as float 9123000 3119595695636480.000000 => 9.123e+22 as double 9123000000000000 4718592.000000 => 9.123e+22 number   9.123e+40 as float inf => inf as double 9123000000000000 6312383662990803305758720.000000 => 9.123e+40 number   9.123e-10 as float 0.000000000 9123000 13311551083461381494998931884765625000000000 => 9.123e-10 as double 0.000000000 9123000000000000 44597902336461579114734732343094947 => 9.123e-10 number   9.123e-50 as float 0.000000000000000000000000000000000000000000000000000000000000 => 0 as double 0.000000000000000000000000000000000000000000000000091230000000 => 9.123e-50

second bit status word
UShort_t    fBits2;
 * http://root.cern.ch/root/html/TAxis.html

TClonesArray
loop { TClonesArray &hits = *fTDCHits; new(hits[fNTDCHits++]) TTDCHit(ch, tld); } Uses a TClonesArray which reduces the number of new/delete calls.
 * https://root.cern.ch/root/html/TClonesArray.html

V slucke sa stale vola normal constructor (ale bez delete)

loop { // TTDCHit *const hit = static_cast(fTDCHits->ConstructedAt(fNTDCHits++)); TTDCHit *hit = (TTDCHit *)fTDCHits->ConstructedAt(fNTDCHits++); hit->Set(ch, tld); } hit->SetChannelTime(ch, tld); To reduce the number of call to the constructor (especially useful if the user class requires memory allocation), the object can be added (and constructed when needed) using ConstructedAt which only calls the constructor once per slot.

Always returns an already constructed object. If the slot is being used for the first time, it calls the default constructor otherwise it returns the object as is (unless a string is passed as the 2nd argument to the function in which case, it also calls Clear(second_argument) on the object). Simpler and more efficient even in case where the TTDCHit/TTrack class allocates memory.

V slucke sa vola sa iba jeden (resp. maximum z fNTDCHits) default constructor. V funkcii Set preto musim zabezpecit 'resetovanie' premennych (z predchadzajuceho hitu) alebo pouzit/volat extra funkciu hit->Clear alebo priamo volat ConstructedAt(Int_t idx, Option_t *clear_options). Kedze v TClonesArray mozu byt len objekty odvodene od TObject, moze nastat situacia, ze je potrebne 'resetovat' aj premenne (fUniqueID, fBits) v TObject (TObject::Clear je na dnesny den prazdna funkcia)

Particle *const p = static_cast(particles_.ConstructedAt(nActive_++)); Event *const newEvent = static_cast(events.ConstructedAt(j));

Clone or Copy
What is the actual difference between the results of a TObject->Clone and TObject->Copy ?
 * https://root.cern.ch/phpBB3/viewtopic.php?t=11471

The difference is the interface (one create a new object, the other update an existing object)

Double_32 dictionary generation
gROOT->ProcessLine("struct D32Holder { Double32_t var; //[0, 4096, 13] };"); myTree->Branch("var", TClass::GetClass("D32Holder"), &var); myTree->Branch("var", "D32Holder", (void*)&var); gInterpreter->Declare("struct D32Holder { Double32_t var; //[0, 4096, 13]\n};"); void *p = (void*)&var; myTree->Branch("var", "D32Holder", (void*)&p);
 * https://root.cern.ch/phpBB3/viewtopic.php?f=3&t=19626

Tree and SetAutoSave

 * When large Trees are produced, it is safe to activate the AutoSave procedure.
 * Each AutoSave generates a new key on the file. Once the key with the tree header has been written, the previous cycle (if any) is deleted.
 * calling TTree::SetAutoSave with a small value (or calling TTree::AutoSave too frequently) is an expensive operation. You should make tests for your own application to find a compromise between speed and the quantity of information you may loose in case of a job crash.
 * => ak nepotrebujem mat istotu moznosti recovery (napr. straty danych pri necakanom skonceni programu) tak dam velku hodnotu a tree header sa ulozi az uplne na konci, resp. az po velkej hodnote entries/bytes
 * => tree;1 => 1 cycle bude vzdy ak SetAutoSave > entries; inak sa ulozi aj predchadzajuci cycle (for deleting the previous cycle and just stay with the newest one )

test file: tree pp, events = 43714
 * fTree->SetAutoSave(100);  // autosave when 100 entries  (!!! filling about 10.5 sec. !!!)  !!! expensive operation !!!
 * pp;438 => 43714 entries
 * pp;437 => 43700 entries   (437*100 = 43700)


 * fTree->SetAutoSave(1000); // autosave when 1000 entries (filling about 2.0 sec.)
 * pp;44 => 43714 entries
 * pp;43 => 43000 entries     (43*1000 = 43000)


 * fTree->SetAutoSave(50000); // autosave when 50000 entries (filling about 1.5 sec.)
 * pp;1  => 43714 entries


 * fTree->SetAutoSave(-300000000); // DEFAULT, autosave when 300000000 bytes (unzipped) written (filling about 1.5 sec.)
 * pp;1  => 43714 entries

misc

 * http://root.cern.ch/files/
 * http://root.cern.ch/files/fw.C

Tree compression
data file: /home/musinsky/TQDC_sample/vmeRUN114_2015-02-20_02-24-02.dat size  = 1672234636 bytes (418058659 words) spills = 99 events = 2065816 vmeRUN114_2015-02-20_02-24-02.dat => 1595M (SSD disk, PC strela04) TDC + TQDC SetCompressionSettings(ROOT::CompressionSettings(ROOT::kUseGlobalSetting, 1)) DEFAULT

root [] .x d.C

settings 1 algorithm 0 level    1 factor   2.79228 Info in : Destructor Info in : Destructor Real time 0:00:35.814060, CP time 33.160 Real time 0:00:35.260297, CP time 32.980

root [] gStrela->AnalyzeEntries Real time 0:00:32.734012, CP time 32.710 Real time 0:00:32.887350, CP time 32.840

TDC + TQDC SetCompressionSettings(ROOT::CompressionSettings(ROOT::kUseGlobalSetting, 0)) NO COMPRESSION

root [] .x d.C

settings 0 algorithm 0 level    0 factor   1.00001 => vme_data.root => 1187M Info in : Destructor Info in : Destructor Real time 0:00:20.595933, CP time 15.830           !!!!!!!!!!!!!!!!!!!! Real time 0:00:20.444206, CP time 16.220

root [] gStrela->AnalyzeEntries Real time 0:00:28.762151, CP time 28.740 Real time 0:00:29.007629, CP time 28.990

TDC + TQDC SetCompressionSettings(ROOT::CompressionSettings(ROOT::kUseGlobalSetting, 2))

root [] .x d.C

settings 2 algorithm 0 level    2 factor   2.71566 Info in : Destructor Info in : Destructor Real time 0:00:36.719002, CP time 35.660 Real time 0:00:35.929452, CP time 35.590

root [] gStrela->AnalyzeEntries Real time 0:00:32.512738, CP time 32.500 Real time 0:00:32.428839, CP time 32.410

TDC + TQDC SetCompressionSettings(ROOT::CompressionSettings(ROOT::kUseGlobalSetting, 5))

root [] .x d.C

settings 5 algorithm 0 level    5 factor   2.72555 Info in : Destructor Info in : Destructor Real time 0:00:56.073635, CP time 54.390 Real time 0:00:56.018901, CP time 54.940

root [] gStrela->AnalyzeEntries Real time 0:00:32.388135, CP time 32.360 Real time 0:00:32.398775, CP time 32.380

TDC + TQDC SetCompressionSettings(ROOT::CompressionSettings(ROOT::kUseGlobalSetting, 9))

root [] .x d.C

settings 9 algorithm 0 level    9 factor   2.75533 Info in : Destructor Info in : Destructor Real time 0:03:01.095543, CP time 180.740 Real time 0:02:59.151411, CP time 178.600

root [] gStrela->AnalyzeEntries Real time 0:00:32.280681, CP time 32.270 Real time 0:00:32.255684, CP time 32.230

C/C++ stack/heap
// funkcia int getaddrinfo(p1, p2, p3, struct addrinfo **res); // priame volanie struct addrinfo *result; getaddrinfo(p1, p2, p3, &result);
 * http://stackoverflow.com/questions/5423766/getaddrinfo-addrinfo-result-in-stack-or-heap

// retrieving a pointer to pointer (the addrinfo list head) void GetAddrInfo(struct addrinfo **update) {   getaddrinfo(p1, p2, p3, update); } struct addrinfo *myresult; GetAddrInfo(&myresult); // or void GetAddrInfo(struct addrinfo **update) {   struct addrinfo *res; getaddrinfo(p1, p2, p3, &res); *update = res;  // save the pointer to the struct } struct addrinfo *myresult; GetAddrInfo(&myresult);

C/C++ difference
C style pass-by-reference (C or C++) int x = 0; fun(&x); // now x = 1 fun(int *xx) *xx = 1;

C++ style pass-by-reference (only C++) int x = 0; fun(x); // now x = 1 fun(int &xx) xx = 1;


 * exit vs. return: exit = All open stdio(3) streams are flushed and closed. Files created by tmpfile(3) are removed ...

sizeof

 * sizeof is a compile time operator
 * sizeof is evaluated at compile time
 * sizeof is always computed at compile time in C89. Since C99 and variable length arrays, it is computed at run time when a variable length array is part of the expression in the sizeof operand.

mc
shell/i/.root View=%view{ascii} rootls -1lt %f 2>/dev/null
 * 1) ROOT