REST-for-Physics  v2.3
Rare Event Searches ToolKit for Physics
TRestAnalysisTree.cxx
1/*************************************************************************
2 * This file is part of the REST software framework. *
3 * *
4 * Copyright (C) 2016 GIFNA/TREX (University of Zaragoza) *
5 * For more information see http://gifna.unizar.es/trex *
6 * *
7 * REST is free software: you can redistribute it and/or modify *
8 * it under the terms of the GNU General Public License as published by *
9 * the Free Software Foundation, either version 3 of the License, or *
10 * (at your option) any later version. *
11 * *
12 * REST is distributed in the hope that it will be useful, *
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
15 * GNU General Public License for more details. *
16 * *
17 * You should have a copy of the GNU General Public License along with *
18 * REST in $REST_PATH/LICENSE. *
19 * If not, see http://www.gnu.org/licenses/. *
20 * For the list of contributors see $REST_PATH/CREDITS. *
21 *************************************************************************/
22
85
86#include "TRestAnalysisTree.h"
87
88#include <TFile.h>
89#include <TH1F.h>
90#include <TLeaf.h>
91#include <TObjArray.h>
92
93#include "TRestStringHelper.h"
94#include "TRestStringOutput.h"
95
96using namespace std;
97
98ClassImp(TRestAnalysisTree) using namespace std;
99
100TRestAnalysisTree::TRestAnalysisTree() : TTree() {
101 SetName("AnalysisTree");
102 SetTitle("REST Analysis tree");
103
104 Initialize();
105}
106
107TRestAnalysisTree::TRestAnalysisTree(TTree* tree) : TTree() {
108 SetName("AnalysisTree");
109 SetTitle("Linked to " + (TString)tree->GetName());
110
111 Initialize();
112
113 tree->GetEntry(0);
114
115 TObjArray* lfs = tree->GetListOfLeaves();
116 for (int i = 0; i < lfs->GetLast() + 1; i++) {
117 TLeaf* lf = (TLeaf*)lfs->UncheckedAt(i);
118 RESTValue obs;
119 ReadLeafValueToObservable(lf, obs);
120 obs.name = lf->GetName();
121 SetObservable(-1, obs);
122 }
123}
124
125TRestAnalysisTree* TRestAnalysisTree::ConvertFromTTree(TTree* tree) {
126 if (tree->ClassName() == (TString) "TRestAnalysisTree") {
127 return (TRestAnalysisTree*)tree;
128 }
129
130 return new TRestAnalysisTree(tree);
131}
132
133TRestAnalysisTree::TRestAnalysisTree(const TString& name, const TString& title) : TTree(name, title) {
134 SetName(name);
135 SetTitle(title);
136
137 Initialize();
138}
139
140void TRestAnalysisTree::Initialize() {
141 fRunOrigin = 0;
142 fSubRunOrigin = 0;
143 fEventID = 0;
144 fSubEventID = 0;
145 fSubEventTag = new TString();
146 fTimeStamp = 0;
147
148 fStatus = 0;
149 fNObservables = 0;
150 fChain = nullptr;
151
152 fObservableIdMap.clear();
153 fObservableIdSearchMap.clear();
154 fObservableDescriptions.clear();
155 fObservableNames.clear();
156 fObservables.clear();
157}
158
165Int_t TRestAnalysisTree::GetObservableID(const string& obsName) {
167 auto iter = fObservableIdMap.find(obsName);
168 if (iter != fObservableIdMap.end()) {
169 return iter->second;
170 } else {
171 return -1;
172 }
173}
174
181Int_t TRestAnalysisTree::GetMatchedObservableID(const string& obsName) {
182 // if (ObservableExists(obsName)) return GetObservableID(obsName);
183 auto iter = fObservableIdSearchMap.find(obsName);
184 if (iter != fObservableIdSearchMap.end()) {
185 return iter->second;
186 } else {
187 vector<int> diffs;
188 for (auto& fObservableName : fObservableNames) {
189 string obs = (string)fObservableName;
190 int diff1 = DiffString(obs, obsName);
191
192 obs = obs.substr(obs.find('_') + 1, -1);
193 int diff2 = DiffString(obs, obsName);
194
195 diffs.push_back(min(diff1, diff2));
196 }
197
198 int matchedCount = 0;
199 int minPos = 0;
200 int min = 1e5;
201 for (unsigned int i = 0; i < diffs.size(); i++) {
202 if (min > diffs[i]) {
203 min = diffs[i];
204 minPos = i;
205 }
206 if (diffs[i] == 0) {
207 matchedCount++;
208 }
209 }
210
211 if (matchedCount == 1) {
212 cout << "TRestAnalysisTree::GetObservableID(): Find observable " << fObservableNames[minPos]
213 << " for obs name: " << obsName << endl;
214 fObservableIdSearchMap[obsName] = minPos;
215 return minPos;
216 } else if (matchedCount == 0) {
217 RESTError << "TRestAnalysisTree::GetObservableID(): No Matching observable found" << RESTendl;
218 if (min <= 2) {
219 RESTError << "did you mean \"" << fObservableNames[minPos] << "\" ?" << RESTendl;
220 fObservableIdSearchMap[obsName] = -1;
221 return -1;
222 }
223 } else {
224 RESTWarning << "TRestAnalysisTree::GetObservableID(): Multiple observables found" << RESTendl;
225 RESTWarning
226 << "Please specify the full observable name (e.g, sAna_ThresholdIntegral) in your code. "
227 << RESTendl;
228 RESTWarning << "Returning the first matched observable : " << fObservableNames[minPos]
229 << RESTendl;
230 fObservableIdSearchMap[obsName] = minPos;
231 return minPos;
232 }
233 }
234 fObservableIdSearchMap[obsName] = -1;
235 return -1;
236}
237
243Bool_t TRestAnalysisTree::ObservableExists(const string& obsName) {
245 return fObservableIdMap.count(obsName) > 0;
246}
247
252// Status | Nbranches | NObservables | Entries | Description
253// 1. Created | 0 | 0 | 0 | The AnalysisTree is just created in code
254// 2. Retrieved | >=6 | 0 | >0 | The AnalysisTree is just retrieved from file
255// 3. EmptyCloned | >=6 | 0 | 0 | The AnalysisTree is cloned from another
256// tree, it is empty
257// 4. Connected | >=6 | >=Nbranches-6 | 0 | Local observables are created and connected
258// to the branches. We can still modify observables in this case.
259// 5. Filled | >=6 | =NObs | >0 | Local observables are created and connected
260// to the branches, and entry > 0. We cannot modify observables in this case. if Nbranches == 6, We regard the
261// tree as Connected/Filled
262//
263// Status | AddObs Logic | Fill Logic | GetEntry Logic
264// 1. Created | Allowed | ->4, ->5 | ->4
265// 2. Retrieved | Denied | ->5 | ->5
266// 3. EmptyCloned | ->4 | ->4, ->5 | ->4
267// 4. Connected | Allowed | ->5 | Allowed
268// 5. Filled | Denied | Allowed | Allowed
269//
271 int NBranches = GetListOfBranches()->GetEntriesFast();
272 int NObsInList = fObservables.size();
273 int Entries = GetEntriesFast();
274
275 // if (fROOTTree != nullptr) {
276 // return TRestAnalysisTree_Status::ROOTTree;
277 //}
278
279 if (NBranches == 0) {
280 return TRestAnalysisTree_Status::Created;
281 }
282
283 if (NBranches > 6) {
284 if (NObsInList == 0) {
285 if (Entries > 0) {
286 return TRestAnalysisTree_Status::Retrieved;
287 } else {
288 return TRestAnalysisTree_Status::EmptyCloned;
289 }
290 } else {
291 if (Entries > 0) {
292 return TRestAnalysisTree_Status::Filled;
293 } else {
294 return TRestAnalysisTree_Status::Connected;
295 }
296 }
297 } else if (NBranches == 6) {
298 auto br = (TBranch*)GetListOfBranches()->UncheckedAt(0);
299 if ((int*)br->GetAddress() != &fRunOrigin) {
300 if (Entries > 0) {
301 return TRestAnalysisTree_Status::Retrieved;
302 } else {
303 return TRestAnalysisTree_Status::EmptyCloned;
304 }
305 } else {
306 if (Entries > 0) {
307 return TRestAnalysisTree_Status::Filled;
308 } else {
309 return TRestAnalysisTree_Status::Connected;
310 }
311 }
312 } else {
313 return TRestAnalysisTree_Status::Error;
314 }
315
316 return TRestAnalysisTree_Status::Error;
317}
318
328 // connect basic event branches
329 TBranch* br1 = GetBranch("runOrigin");
330 TBranch* br2 = GetBranch("subRunOrigin");
331 TBranch* br3 = GetBranch("eventID");
332 TBranch* br4 = GetBranch("subEventID");
333 TBranch* br5 = GetBranch("timeStamp");
334 TBranch* br6 = GetBranch("subEventTag");
335
336 if (br1 && br2 && br3 && br4 && br5 && br6) {
337 br1->SetAddress(&fRunOrigin);
338 br2->SetAddress(&fSubRunOrigin);
339 br3->SetAddress(&fEventID);
340 br4->SetAddress(&fSubEventID);
341 br5->SetAddress(&fTimeStamp);
342 br6->SetAddress(&fSubEventTag);
343 } else {
344 cout << "REST Error: TRestAnalysisTree::ConnectBranches(): event branches does not exist!" << endl;
345 exit(1);
346 }
347
348 // create observables(no assembly) from stored observable info.
349 fObservables = std::vector<RESTValue>(GetNumberOfObservables());
350 for (int i = 0; i < GetNumberOfObservables(); i++) {
351 fObservables[i] = REST_Reflection::WrapType((string)fObservableTypes[i]);
352 fObservables[i].name = fObservableNames[i];
353 }
355
356 if (fChain) {
357 fChain->GetEntry(0);
358 } else {
359 TTree::GetEntry(0);
360 }
361
362 for (int i = 0; i < GetNumberOfObservables(); i++) {
363 TBranch* branch = GetBranch(fObservableNames[i]);
364 if (branch != nullptr) {
365 if (branch->GetAddress() != nullptr) {
366 if ((string)branch->ClassName() != "TBranch") {
367 // for TBranchElement the saved address is char**
368 fObservables[i].address = *(char**)branch->GetAddress();
369 } else {
370 // for TBranch the saved address is char*
371 fObservables[i].address = branch->GetAddress();
372 }
373 } else {
374 fObservables[i].Assembly();
375 branch->SetAddress(fObservables[i].address);
376 }
377 }
378 }
379
380 fStatus = EvaluateStatus();
381}
382
392 if (!GetBranch("runOrigin")) Branch("runOrigin", &fRunOrigin);
393 if (!GetBranch("subRunOrigin")) Branch("subRunOrigin", &fSubRunOrigin);
394 if (!GetBranch("eventID")) Branch("eventID", &fEventID);
395 if (!GetBranch("subEventID")) Branch("subEventID", &fSubEventID);
396 if (!GetBranch("timeStamp")) Branch("timeStamp", &fTimeStamp);
397 if (!GetBranch("subEventTag")) Branch("subEventTag", fSubEventTag);
398
399 for (int n = 0; n < GetNumberOfObservables(); n++) {
400 TString typeName = fObservableTypes[n];
401 TString brName = fObservableNames[n];
402 char* ref = fObservables[n].address;
403
404 TBranch* branch = GetBranch(brName);
405 if (branch == nullptr) {
406 if (typeName == "double") {
407 this->Branch(brName, (double*)ref);
408 } else if (typeName == "float") {
409 this->Branch(brName, (float*)ref);
410 } else if (typeName == "long double") {
411 this->Branch(brName, (long double*)ref);
412 } else if (typeName == "bool") {
413 this->Branch(brName, (bool*)ref);
414 } else if (typeName == "char") {
415 this->Branch(brName, (char*)ref);
416 } else if (typeName == "int") {
417 this->Branch(brName, (int*)ref);
418 } else if (typeName == "short") {
419 this->Branch(brName, (short*)ref);
420 } else if (typeName == "unsigned char") {
421 this->Branch(brName, (unsigned char*)ref);
422 } else if (typeName == "unsigned int") {
423 this->Branch(brName, (unsigned int*)ref);
424 } else if (typeName == "unsigned short") {
425 this->Branch(brName, (unsigned short*)ref);
426 } else if (typeName == "long") {
427 this->Branch(brName, (long*)ref);
428 } else if (typeName == "long long") {
429 this->Branch(brName, (long long*)ref);
430 } else if (typeName == "unsigned long") {
431 this->Branch(brName, (unsigned long*)ref);
432 } else if (typeName == "unsigned long long") {
433 this->Branch(brName, (unsigned long long*)ref);
434 } else {
435 this->Branch(brName, typeName, ref);
436 }
437
438 this->GetBranch(brName)->SetTitle("(" + typeName + ") " + fObservableDescriptions[n]);
439 }
440 }
441
442 fStatus = EvaluateStatus();
443}
444
445void TRestAnalysisTree::InitObservables() {
446 fObservables = std::vector<RESTValue>(GetNumberOfObservables());
447 for (int i = 0; i < GetNumberOfObservables(); i++) {
448 fObservables[i] = REST_Reflection::WrapType((string)fObservableTypes[i]);
449 fObservables[i].name = fObservableNames[i];
450 }
452}
453
460 if (fObservableIdMap.size() != fObservableNames.size()) {
461 fObservableIdMap.clear();
462 for (unsigned int i = 0; i < fObservableNames.size(); i++) {
463 fObservableIdMap[(string)fObservableNames[i]] = i;
464 }
465 if (fObservableIdMap.size() != fObservableNames.size()) {
466 cout << "REST ERROR! duplicated or blank observable name!" << endl;
467 }
468 }
469}
470
471void TRestAnalysisTree::ReadLeafValueToObservable(TLeaf* lf, RESTValue& obs) {
472 if (lf == nullptr || lf->GetLen() == 0) return;
473
474 if (obs.IsZombie()) {
475 // this means we need to determine the observable type first
476 string type;
477 string leafdef(lf->GetBranch()->GetTitle());
478 if (leafdef.find("[") == string::npos) {
479 // there is no [] mark in the leaf. The leaf is a single values
480 switch (leafdef[leafdef.size() - 1]) {
481 case 'C':
482 type = "string";
483 break;
484 case 'B':
485 type = "char";
486 break;
487 case 'S':
488 type = "stort";
489 break;
490 case 'I':
491 type = "int";
492 break;
493 case 'F':
494 type = "float";
495 break;
496 case 'D':
497 type = "double";
498 break;
499 case 'L':
500 type = "long long";
501 break;
502 case 'O':
503 type = "bool";
504 break;
505 default:
506 RESTError << "Unsupported leaf definition: " << leafdef << "! Assuming int" << RESTendl;
507 type = "int";
508 }
509 } else {
510 switch (leafdef[leafdef.size() - 1]) {
511 case 'I':
512 type = "vector<int>";
513 break;
514 case 'F':
515 type = "vector<float>";
516 break;
517 case 'D':
518 type = "vector<double>";
519 break;
520 default:
521 RESTError << "Unsupported leaf definition: " << leafdef << "! Assuming vector<int>"
522 << RESTendl;
523 type = "vector<int>";
524 }
525 }
526 obs = REST_Reflection::Assembly(type);
527 }
528
529 // start to fill value
530 if (obs.is_data_type) {
531 // the observable is basic type, we directly set it address from leaf
532 obs.address = (char*)lf->GetValuePointer();
533 } else if (obs.type == "vector<double>") {
534 auto ptr = (double*)lf->GetValuePointer();
535 vector<double> val(ptr, ptr + lf->GetLen());
536 obs.SetValue(val);
537 } else if (obs.type == "vector<int>") {
538 int* ptr = (int*)lf->GetValuePointer();
539 vector<int> val(ptr, ptr + lf->GetLen());
540 obs.SetValue(val);
541 } else if (obs.type == "vector<float>") {
542 auto ptr = (float*)lf->GetValuePointer();
543 vector<float> val(ptr, ptr + lf->GetLen());
544 obs.SetValue(val);
545 } else if (obs.type == "string") {
546 char* ptr = (char*)lf->GetValuePointer();
547 string val(ptr, lf->GetLen());
548 obs.SetValue(val);
549 } else {
550 RESTWarning << "Unsupported observable type to convert from TLeaf!" << RESTendl;
551 }
552}
553
554RESTValue TRestAnalysisTree::GetObservable(const string& obsName) {
555 Int_t id = GetObservableID(obsName);
556 if (id == -1) return {};
557 return GetObservable(id);
558}
559
562RESTValue TRestAnalysisTree::GetObservable(Int_t n) {
563 if (n >= fNObservables) {
564 cout << "Error! TRestAnalysisTree::GetObservable(): index outside limits!" << endl;
565 return {};
566 }
567
568 if (fChain != nullptr) {
569 return ((TRestAnalysisTree*)fChain->GetTree())->GetObservable(n);
570 }
571
572 return fObservables[n];
573}
577 if (n >= fNObservables) {
578 cout << "Error! TRestAnalysisTree::GetObservableName(): index outside limits!" << endl;
579 return "";
580 }
581 return fObservableNames[n];
582}
586 if (n >= fNObservables) {
587 cout << "Error! TRestAnalysisTree::GetObservableDescription(): index outside limits!" << endl;
588 return "";
589 }
590 return fObservableDescriptions[n];
591}
595 if (n >= fNObservables) {
596 cout << "Error! TRestAnalysisTree::GetObservableType(): index outside limits!" << endl;
597 return "double";
598 }
599 return fObservableTypes[n];
600}
603TString TRestAnalysisTree::GetObservableType(const string& obsName) {
604 Int_t id = GetObservableID(obsName);
605 if (id == -1) return "NotFound";
606 return GetObservableType(id);
607}
612Double_t TRestAnalysisTree::GetDblObservableValue(const string& obsName) {
613 return GetDblObservableValue(GetObservableID(obsName));
614}
620 if (n >= fNObservables) {
621 cout << "Error! TRestAnalysisTree::GetDblObservableValue(): index outside limits!" << endl;
622 return 0;
623 }
624
625 if (GetObservableType(n) == "int") return GetObservableValue<int>(n);
626 if (GetObservableType(n) == "double") return GetObservableValue<double>(n);
627
628 cout << "TRestAnalysisTree::GetDblObservableValue. Type " << GetObservableType(n)
629 << " not supported! Returning zero" << endl;
630 return 0.;
631}
632
633RESTValue TRestAnalysisTree::AddObservable(const TString& observableName, const TString& observableType,
634 const TString& description) {
635 if (fStatus == None) fStatus = EvaluateStatus();
636
637 if (fStatus == Created) {
638 } else if (fStatus == Retrieved) {
639 cout << "REST_Warning: cannot add observable for retrieved tree with data!" << endl;
640 return -1;
641 } else if (fStatus == EmptyCloned) {
643 } else if (fStatus == Connected) {
644 } else if (fStatus == Filled) {
645 cout << "REST_Warning: cannot add observable! AnalysisTree is already filled" << endl;
646 return -1;
647 } else if (fChain != nullptr) {
648 cout << "Error! cannot add observable! AnalysisTree is in chain state" << endl;
649 return -1;
650 }
651
652 if (GetObservableID((string)observableName) == -1) {
653 RESTValue ptr = REST_Reflection::Assembly((string)observableType);
654 ptr.name = observableName;
655 if (!ptr.IsZombie()) {
656 fObservableNames.push_back(observableName);
657 fObservableIdMap[(string)observableName] = fObservableNames.size() - 1;
658 fObservableDescriptions.push_back(description);
659 fObservableTypes.push_back(observableType);
660 fObservables.push_back(ptr);
661
663 } else {
664 cout << "Error adding observable \"" << observableName << "\" with type \"" << observableType
665 << "\", type not found!" << endl;
666 return -1;
667 }
668 } else {
669 return GetObservableID((string)observableName);
670 }
671
672 return fObservables[fNObservables - 1];
673}
674
675void TRestAnalysisTree::PrintObservables() {
676 if (fStatus == None) fStatus = EvaluateStatus();
677
678 if (fStatus == Created) {
679 } else if (fStatus == Retrieved) {
680 cout << "TRestAnalysisTree::PrintObservables(): Reading entry 0" << endl;
681 GetEntry(0);
682 } else if (fStatus == EmptyCloned) {
683 cout << "REST_Warning: AnalysisTree is empty" << endl;
685 } else if (fStatus == Connected) {
686 cout << "REST_Warning: AnalysisTree is empty" << endl;
687 } else if (fStatus == Filled) {
688 }
689
690 cout.precision(15);
691 std::cout << "Entry : " << GetReadEntry() << std::endl;
692 std::cout << "> Event ID : " << GetEventID() << std::endl;
693 std::cout << "> Event Time : " << GetTimeStamp() << std::endl;
694 std::cout << "> Event Tag : " << GetSubEventTag() << std::endl;
695 std::cout << "-----------------------------------------" << std::endl;
696 cout.precision(6);
697
698 for (int n = 0; n < GetNumberOfObservables(); n++) {
699 PrintObservable(n);
700 }
701}
702
703// print the Nth observable in the observal list
704void TRestAnalysisTree::PrintObservable(int n) {
705 if (n < 0 || n >= fNObservables) {
706 return;
707 }
708 string obsVal = GetObservable(n).ToString();
709 int lengthRemaining = Console::GetWidth() - 14 - 45 - 13;
710
711 std::cout << "Observable : " << ToString(fObservableNames[n], 45)
712 << " Value : " << ToString(obsVal, lengthRemaining) << std::endl;
713}
714
715Int_t TRestAnalysisTree::GetEntry(Long64_t entry, Int_t getall) {
716 if (fStatus == None) fStatus = EvaluateStatus();
717
718 if (fStatus == Created) {
720 } else if (fStatus == Retrieved) {
722 } else if (fStatus == EmptyCloned) {
724 } else if (fStatus == Connected) {
725 } else if (fStatus == Filled) {
726 }
727
728 if (fChain != nullptr) {
729 return fChain->GetEntry(entry, getall);
730 } else {
731 return TTree::GetEntry(entry, getall);
732 }
733}
734
735void TRestAnalysisTree::SetEventInfo(TRestAnalysisTree* tree) {
736 if (fChain != nullptr) {
737 cout << "Error! cannot fill tree. AnalysisTree is in chain state" << endl;
738 return;
739 }
740
741 if (tree != nullptr) {
742 fEventID = tree->GetEventID();
743 fSubEventID = tree->GetSubEventID();
744 fTimeStamp = tree->GetTimeStamp();
745 *fSubEventTag = tree->GetSubEventTag();
746 fRunOrigin = tree->GetRunOrigin();
747 fSubRunOrigin = tree->GetSubRunOrigin();
748 }
749}
750
751void TRestAnalysisTree::SetEventInfo(TRestEvent* evt) {
752 if (fChain != nullptr) {
753 cout << "Error! cannot fill tree. AnalysisTree is in chain state" << endl;
754 return;
755 }
756
757 if (evt != nullptr) {
758 fEventID = evt->GetID();
759 fSubEventID = evt->GetSubID();
760 fTimeStamp = evt->GetTimeStamp().AsDouble();
761 *fSubEventTag = evt->GetSubEventTag();
762 fRunOrigin = evt->GetRunOrigin();
763 fSubRunOrigin = evt->GetSubRunOrigin();
764 }
765}
766
767Int_t TRestAnalysisTree::Fill() {
768 if (fStatus == None) fStatus = EvaluateStatus();
769
770 if (fChain != nullptr) {
771 cout << "Error! cannot fill tree. AnalysisTree is in chain state" << endl;
772 return -1;
773 }
774
775 fSetObservableIndex = 0;
776
777 if (fStatus == Filled) {
778 return TTree::Fill();
779 } else if (fStatus == Created) {
781 int a = TTree::Fill();
782 fStatus = EvaluateStatus();
783 return a;
784 } else if (fStatus == Retrieved) {
786 int a = TTree::Fill();
787 fStatus = EvaluateStatus();
788 return a;
789 } else if (fStatus == EmptyCloned) {
791 int a = TTree::Fill();
792 fStatus = EvaluateStatus();
793 return a;
794 } else if (fStatus == Connected) {
796 int a = TTree::Fill();
797 fStatus = EvaluateStatus();
798 return a;
799 }
800 return -1;
801}
802
807 if (fChain != nullptr) {
808 cout << "Error! cannot set observable! AnalysisTree is in chain state" << endl;
809 return;
810 }
811 if (id == -1) {
812 // this means we want to find observable id by its name
813 id = GetObservableID(obs.name);
814 // if not found, we have a chance to create observable
815 if (id == -1) {
816 AddObservable(obs.name, obs.type);
817 id = GetObservableID(obs.name);
818 }
819 } else if (id == (int)fObservables.size()) {
820 // this means we want to add observable directly
821 AddObservable(obs.name, obs.type);
822 id = GetObservableID(obs.name);
823 }
824 if (id != -1) {
825 if (obs.type != fObservables[id].type) {
826 // if the observable branches are not created, and the type doesn't match,
827 // we still have the chance to fix. We reset fObservableTypes and fObservableMemory
828 // according to the input type value.
829 cout << "Warning: SetObservableValue(): setting value with different type. Observable : "
830 << obs.name << ", existing type: " << fObservables[id].type
831 << ", value to add is in type: " << obs.type << ", trying to update to the new type."
832 << endl;
833 fObservableTypes[id] = obs.type;
834 string name = fObservables[id].name;
835 fObservables[id].Destroy();
836 fObservables[id] = REST_Reflection::Assembly(obs.type);
837 fObservables[id].name = name;
838 }
839 obs >> fObservables[id];
840 }
841}
842
870 value.name = name;
871 SetObservable(-1, value);
872}
873
881Bool_t TRestAnalysisTree::EvaluateCuts(const string& cut) {
882 std::vector<string> cuts = Split(cut, "&&", false, true);
883
884 for (auto& cut : cuts) {
885 if (!EvaluateCut(cut)) {
886 return false;
887 }
888 }
889
890 return true;
891}
892
899Bool_t TRestAnalysisTree::EvaluateCut(const string& cut) {
900 const std::vector<string> validOperators = {"==", "<=", ">=", "!=", "=", ">", "<"};
901
902 if (cut.find("&&") != string::npos) return EvaluateCuts(cut);
903
904 string operation, observable;
905 Double_t value = -1;
906 for (const auto& validOperator : validOperators) {
907 if (cut.find(validOperator) != string::npos) {
908 operation = validOperator;
909 observable = (string)cut.substr(0, cut.find(operation));
910 value = std::stod((string)cut.substr(cut.find(operation) + operation.length(), string::npos));
911 break;
912 }
913 }
914
915 if (operation.empty())
916 cout << "TRestAnalysisTree::EvaluateCut. Invalid operator in cut definition! " << cut << endl;
917
918 Double_t val = GetDblObservableValue(observable);
919 if (operation == "==" && value == val) return true;
920 if (operation == "!=" && value != val) return true;
921 if (operation == "<=" && val <= value) return true;
922 if (operation == ">=" && val >= value) return true;
923 if (operation == "=" && val == value) return true;
924 if (operation == ">" && val > value) return true;
925 if (operation == "<" && val < value) return true;
926
927 return false;
928}
929
934vector<string> TRestAnalysisTree::GetCutObservables(const string& cut_str) {
935 const std::vector<string> validOperators = {"==", "<=", ">=", "!=", "=", ">", "<"};
936
937 std::vector<string> cuts = Split(cut_str, "&&", false, true);
938
939 vector<string> obsNames;
940 for (auto& cut : cuts) {
941 string operation, observable;
942 for (const auto& validOperator : validOperators) {
943 if (cut.find(validOperator) != string::npos) {
944 obsNames.push_back((string)cut.substr(0, cut.find(validOperator)));
945 break;
946 }
947 }
948 }
949 return obsNames;
950}
951
955void TRestAnalysisTree::EnableBranches(vector<string> obsNames) {
956 for (auto& obsName : obsNames) this->SetBranchStatus(obsName.c_str(), true);
957}
958
962void TRestAnalysisTree::DisableBranches(vector<string> obsNames) {
963 for (auto& obsName : obsNames) this->SetBranchStatus(obsName.c_str(), false);
964}
965
969void TRestAnalysisTree::EnableAllBranches() { this->SetBranchStatus("*", true); }
970
974void TRestAnalysisTree::DisableAllBranches() { this->SetBranchStatus("*", false); }
975
983void TRestAnalysisTree::EnableQuickObservableValueSetting() { this->fQuickSetObservableValue = true; }
984
987void TRestAnalysisTree::DisableQuickObservableValueSetting() { this->fQuickSetObservableValue = false; }
988
993Double_t TRestAnalysisTree::GetObservableIntegral(const TString& obsName, Double_t xLow, Double_t xHigh) {
994 Int_t id = GetObservableID((std::string)obsName);
995
996 if (id < 0) {
997 RESTError << "TRestAnalysisTree::GetObservableIntegral. Observable not found! : " << obsName
998 << RESTendl;
999 return 0;
1000 }
1001
1002 Double_t sum = 0;
1003 for (Int_t n = 0; n < TTree::GetEntries(); n++) {
1004 TTree::GetEntry(n);
1005 Double_t value = GetDblObservableValue(id);
1006
1007 if (xLow != -1 && xHigh != -1 && (value < xLow || value > xHigh)) continue;
1008 sum += value;
1009 }
1010
1011 return sum;
1012}
1013
1018Double_t TRestAnalysisTree::GetObservableAverage(const TString& obsName, Double_t xLow, Double_t xHigh) {
1019 Int_t id = GetObservableID((std::string)obsName);
1020
1021 if (id < 0) {
1022 RESTError << "TRestAnalysisTree::GetObservableAverage. Observable not found! : " << obsName
1023 << RESTendl;
1024 return 0;
1025 }
1026
1027 Double_t sum = 0;
1028 Int_t N = 0;
1029 for (Int_t n = 0; n < TTree::GetEntries(); n++) {
1030 TTree::GetEntry(n);
1031 Double_t value = GetDblObservableValue(id);
1032
1033 if (xLow != -1 && xHigh != -1 && (value < xLow || value > xHigh)) continue;
1034 N++;
1035 sum += value;
1036 }
1037
1038 if (N <= 0) return 0;
1039
1040 return sum / N;
1041}
1042
1047Double_t TRestAnalysisTree::GetObservableRMS(const TString& obsName, Double_t xLow, Double_t xHigh) {
1048 Double_t mean = GetObservableAverage(obsName, xLow, xHigh);
1049
1050 Int_t id = GetObservableID((std::string)obsName);
1051
1052 Double_t sum = 0;
1053 Int_t N = 0;
1054 for (Int_t n = 0; n < TTree::GetEntries(); n++) {
1055 TTree::GetEntry(n);
1056 Double_t value = GetDblObservableValue(id);
1057
1058 if (xLow != -1 && xHigh != -1 && (value < xLow || value > xHigh)) continue;
1059 N++;
1060
1061 sum += (value - mean) * (value - mean);
1062 }
1063
1064 if (N <= 0) return 0;
1065
1066 return TMath::Sqrt(sum / N);
1067}
1068
1073Double_t TRestAnalysisTree::GetObservableMaximum(const TString& obsName, Double_t xLow, Double_t xHigh) {
1074 Int_t id = GetObservableID((std::string)obsName);
1075
1076 if (id < 0) {
1077 RESTError << "TRestAnalysisTree::GetObservableMaximum. Observable not found! : " << obsName
1078 << RESTendl;
1079 return 0;
1080 }
1081
1082 Double_t max = -DBL_MAX;
1083 for (Int_t n = 0; n < TTree::GetEntries(); n++) {
1084 TTree::GetEntry(n);
1085 Double_t value = GetDblObservableValue(id);
1086
1087 if (xLow != -1 && xHigh != -1 && (value < xLow || value > xHigh)) continue;
1088 if (value > max) max = value;
1089 }
1090
1091 return max;
1092}
1093
1098Double_t TRestAnalysisTree::GetObservableMinimum(const TString& obsName, Double_t xLow, Double_t xHigh) {
1099 Int_t id = GetObservableID((std::string)obsName);
1100
1101 if (id < 0) {
1102 RESTError << "TRestAnalysisTree::GetObservableMinimum. Observable not found! : " << obsName
1103 << RESTendl;
1104 return 0;
1105 }
1106
1107 Double_t min = DBL_MAX;
1108 for (Int_t n = 0; n < TTree::GetEntries(); n++) {
1109 TTree::GetEntry(n);
1110 Double_t value = GetDblObservableValue(id);
1111
1112 if (xLow != -1 && xHigh != -1 && (value < xLow || value > xHigh)) continue;
1113 if (value < min) min = value;
1114 }
1115
1116 return min;
1117}
1118
1143Double_t TRestAnalysisTree::GetObservableContour(const TString& obsName, const TString& obsWeight,
1144 Double_t level, Int_t nBins, Double_t xLow, Double_t xHigh) {
1145 if (level > 1 || level < 0) {
1146 RESTWarning << "Level is : " << level << RESTendl;
1147 RESTWarning << "Level must be between 0 and 1" << RESTendl;
1148 return 0;
1149 }
1150
1151 Double_t integral = this->GetIntegral(obsWeight, xLow, xHigh);
1152
1153 TString histDefinition = Form("hc(%5d,%lf,%lf)", nBins, xLow, xHigh);
1154 if (xHigh == -1)
1155 this->Draw(obsName + ">>hc", obsWeight);
1156 else
1157 this->Draw(obsName + ">>" + histDefinition, obsWeight);
1158
1159 TH1F* htemp = (TH1F*)gPad->GetPrimitive("hc");
1160
1161 Double_t sum = 0;
1162 for (int i = 0; i < htemp->GetNbinsX(); i++) {
1163 sum += htemp->GetBinContent(i + 1);
1164
1165 if (sum > level * integral) return htemp->GetBinCenter(i + 1);
1166 }
1167 return 0;
1168}
1169
1174
1175std::vector<std::string> TRestAnalysisTree::GetObservableNames() {
1176 std::vector<std::string> names;
1177
1178 auto branches = GetListOfBranches();
1179 for (int i = 0; i < branches->GetEntries(); i++) {
1180 names.push_back((string)branches->At(i)->GetName());
1181 }
1182
1183 return names;
1184}
1185
1189Int_t TRestAnalysisTree::WriteAsTTree(const char* name, Int_t option, Int_t bufsize) {
1190 TTree* tree = new TTree();
1191
1192 char* dest = (char*)tree + sizeof(TObject);
1193 char* from = (char*)this + sizeof(TObject);
1194
1195 constexpr size_t n = sizeof(TTree) - sizeof(TObject);
1196
1197 // copy the data of the created TTree to a temporary location
1198 char* temp = (char*)malloc(n);
1199 memcpy(temp, dest, n);
1200
1201 // copy the data of this TRestAnalysisTree to TTree, and call the new TTree to write
1202 memcpy(dest, from, n);
1203 int result = tree->Write(name, option, bufsize);
1204
1205 // restore the data of the created TTree, then we can free it!
1206 memcpy(dest, temp, n);
1207 free(temp);
1208 delete tree;
1209
1210 return result;
1211}
1212
1218Bool_t TRestAnalysisTree::AddChainFile(const string& _file) {
1219 auto file = std::unique_ptr<TFile>{TFile::Open(_file.c_str(), "update")};
1220 if (!file->IsOpen()) {
1221 RESTWarning << "TRestAnalysisTree::AddChainFile(): failed to open file " << _file << RESTendl;
1222 return false;
1223 }
1224
1225 if (this->GetRunOrigin() == 0) {
1226 this->GetEntry(0);
1227 }
1228
1229 auto tree = (TRestAnalysisTree*)file->Get("AnalysisTree");
1230 if (tree != nullptr && tree->GetEntry(0)) {
1231 if (tree->GetEntry(0) > 0) {
1232 if (tree->GetRunOrigin() == this->GetRunOrigin()) {
1233 // this is a valid tree
1234 delete tree;
1235
1236 if (fChain == nullptr) {
1237 fChain = new TChain("AnalysisTree", "Chained AnalysisTree");
1238 fChain->Add(this->GetCurrentFile()->GetName());
1239 }
1240 return fChain->Add(_file.c_str()) == 1;
1241 }
1242 RESTWarning
1243 << "TRestAnalysisTree::AddChainFile(): invalid file, AnalysisTree in file has different "
1244 "run id!"
1245 << RESTendl;
1246 }
1247 RESTWarning << "TRestAnalysisTree::AddChainFile(): invalid file, AnalysisTree in file is empty!"
1248 << RESTendl;
1249 delete tree;
1250 }
1251 RESTWarning << "TRestAnalysisTree::AddChainFile(): invalid file, file does not contain an AnalysisTree!"
1252 << RESTendl;
1253
1254 return false;
1255}
1256
1263 if (fChain == nullptr) {
1264 return TTree::GetTree();
1265 }
1266 return (TTree*)fChain;
1267}
1268
1275Long64_t TRestAnalysisTree::LoadTree(Long64_t entry) {
1276 if (fChain == nullptr) {
1277 return TTree::LoadTree(entry);
1278 } else {
1279 return fChain->LoadTree(entry);
1280 }
1281
1282 return -2;
1283}
1284
1285Long64_t TRestAnalysisTree::GetEntries() const {
1286 if (fChain == nullptr) {
1287 return TTree::GetEntries();
1288 }
1289 return fChain->GetEntries();
1290}
1291
1292Long64_t TRestAnalysisTree::GetEntries(const char* sel) {
1293 if (fChain == nullptr) {
1294 return TTree::GetEntries(sel);
1295 }
1296 return fChain->GetEntries(sel);
1297}
1298
1299TRestAnalysisTree::~TRestAnalysisTree() { delete fSubEventTag; }
void SetValue(const T &val)
Set the value of the wrapped type.
std::string ToString()
Convert the wrapped object to std::string.
std::string type
Type of the wrapped object.
char * address
Address of the wrapped object.
bool is_data_type
Pointer to the corresponding TDataType helper, if the wrapped object is in data type.
std::string name
Name field.
bool IsZombie()
If this object type wrapper is invalid.
REST core data-saving helper based on TTree.
TString GetObservableDescription(Int_t n)
Get the observable description according to id.
void DisableQuickObservableValueSetting()
It will disable quick observable value setting.
std::vector< std::string > GetCutObservables(const std::string &cut_str)
It will return a list with the names found in a string with conditions, as given in methods as Evalua...
void UpdateObservables()
Update observables stored in the tree.
Double_t GetObservableContour(const TString &obsName, const TString &obsIndexer, Double_t level=0.5, Int_t nBins=-1, Double_t xLow=-1, Double_t xHigh=-1)
This method generates a histogram of the the observable obsName given in the argument weighting it wi...
void EnableAllBranches()
It will enable all branches in the tree.
void EnableQuickObservableValueSetting()
It will enable quick observable value setting.
Long64_t LoadTree(Long64_t entry)
Overrides TTree::LoadTree(), to set current tree according to the given entry number,...
Bool_t AddChainFile(const std::string &file)
Add a series output file like TChain.
TString GetObservableName(Int_t n)
Get the observable name according to id.
void UpdateBranches()
Update branches in the tree.
Double_t GetObservableIntegral(const TString &obsName, Double_t xLow=-1, Double_t xHigh=-1)
It returns the integral of the observable considering the given range. If no range is given the full ...
TChain * fChain
used for quick search of certain observables
Bool_t EvaluateCuts(const std::string &expression)
This method will receive a string with several analysis observables/cuts in the same fashion as used ...
TTree * GetTree() const
Overrides TTree::GetTree(), to get the actual tree used in case of chain operation(fCurrentTree !...
Double_t GetObservableMaximum(const TString &obsName, Double_t xLow=-1, Double_t xHigh=-1)
It returns the maximum value of obsName considering the given range. If no range is given the full hi...
Int_t GetObservableID(const std::string &obsName)
Get the index of the specified observable.
void MakeObservableIdMap()
Update the map of observable name to observable id.
Int_t GetMatchedObservableID(const std::string &obsName)
Get the index of the observable, erasing the prefix if exists.
Double_t GetObservableAverage(const TString &obsName, Double_t xLow=-1, Double_t xHigh=-1)
It returns the average of the observable considering the given range. If no range is given the full h...
void DisableBranches(std::vector< std::string > obsNames)
It will disable the branches given by argument.
Double_t GetObservableRMS(const TString &obsName, Double_t xLow=-1, Double_t xHigh=-1)
It returns the RMS of the observable considering the given range. If no range is given the full histo...
Double_t GetDblObservableValue(const std::string &obsName)
Get double value of the observable, according to the name.
TString GetObservableType(Int_t n)
Get the observable type according to id.
std::vector< std::string > GetObservableNames()
It returns a vector with strings containing all the observables that exist in the analysis tree.
void DisableAllBranches()
It will disable all branches in the tree.
Double_t GetObservableMinimum(const TString &obsName, Double_t xLow=-1, Double_t xHigh=-1)
It returns the minimum value of obsName considering the given range. If no range is given the full hi...
int EvaluateStatus()
Evaluate the Status of this tree.
Bool_t ObservableExists(const std::string &obsName)
Get if the specified observable exists.
Int_t fNObservables
in case multiple files for reading
void EnableBranches(std::vector< std::string > obsNames)
It will enable the branches given by argument.
Bool_t EvaluateCut(const std::string &expression)
This method will evaluate a condition on one analysis observable constructed as "observable>value"....
void SetObservable(Int_t id, RESTValue obs)
Set the value of observable whose id is as specified.
Int_t WriteAsTTree(const char *name=0, Int_t option=0, Int_t bufsize=0)
It writes TRestAnalysisTree as TTree, in order to migrate files to pure ROOT users.
A base class for any REST event.
Definition: TRestEvent.h:38
TRestReflector WrapType(std::string typeName)
Wrap information an object of type: typeName, memory is not allocated.
TRestReflector Assembly(std::string typeName)
Assembly an object of type: typeName, returning the allocated memory address and size.
std::vector< std::string > Split(std::string in, std::string separator, bool allowBlankString=false, bool removeWhiteSpaces=false, int startPos=-1)
Split the input string according to the given separator. Returning a vector of fragments.
Int_t DiffString(const std::string &source, const std::string &target)
Returns the number of different characters between two strings.