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) == "float") return GetObservableValue<float>(n);
627 if (GetObservableType(n) == "double") return GetObservableValue<double>(n);
628
629 cout << "TRestAnalysisTree::GetDblObservableValue. Type " << GetObservableType(n)
630 << " not supported! Returning zero" << endl;
631 return 0.;
632}
633
634RESTValue TRestAnalysisTree::AddObservable(const TString& observableName, const TString& observableType,
635 const TString& description) {
636 if (fStatus == None) fStatus = EvaluateStatus();
637
638 if (fStatus == Created) {
639 } else if (fStatus == Retrieved) {
640 cout << "REST_Warning: cannot add observable for retrieved tree with data!" << endl;
641 return -1;
642 } else if (fStatus == EmptyCloned) {
644 } else if (fStatus == Connected) {
645 } else if (fStatus == Filled) {
646 cout << "REST_Warning: cannot add observable! AnalysisTree is already filled" << endl;
647 return -1;
648 } else if (fChain != nullptr) {
649 cout << "Error! cannot add observable! AnalysisTree is in chain state" << endl;
650 return -1;
651 }
652
653 if (GetObservableID((string)observableName) == -1) {
654 RESTValue ptr = REST_Reflection::Assembly((string)observableType);
655 ptr.name = observableName;
656 if (!ptr.IsZombie()) {
657 fObservableNames.push_back(observableName);
658 fObservableIdMap[(string)observableName] = fObservableNames.size() - 1;
659 fObservableDescriptions.push_back(description);
660 fObservableTypes.push_back(observableType);
661 fObservables.push_back(ptr);
662
664 } else {
665 cout << "Error adding observable \"" << observableName << "\" with type \"" << observableType
666 << "\", type not found!" << endl;
667 return -1;
668 }
669 } else {
670 return GetObservableID((string)observableName);
671 }
672
673 return fObservables[fNObservables - 1];
674}
675
676void TRestAnalysisTree::PrintObservables() {
677 if (fStatus == None) fStatus = EvaluateStatus();
678
679 if (fStatus == Created) {
680 } else if (fStatus == Retrieved) {
681 cout << "TRestAnalysisTree::PrintObservables(): Reading entry 0" << endl;
682 GetEntry(0);
683 } else if (fStatus == EmptyCloned) {
684 cout << "REST_Warning: AnalysisTree is empty" << endl;
686 } else if (fStatus == Connected) {
687 cout << "REST_Warning: AnalysisTree is empty" << endl;
688 } else if (fStatus == Filled) {
689 }
690
691 cout.precision(15);
692 std::cout << "Entry : " << GetReadEntry() << std::endl;
693 std::cout << "> Event ID : " << GetEventID() << std::endl;
694 std::cout << "> Event Time : " << GetTimeStamp() << std::endl;
695 std::cout << "> Event Tag : " << GetSubEventTag() << std::endl;
696 std::cout << "-----------------------------------------" << std::endl;
697 cout.precision(6);
698
699 for (int n = 0; n < GetNumberOfObservables(); n++) {
700 PrintObservable(n);
701 }
702}
703
704// print the Nth observable in the observal list
705void TRestAnalysisTree::PrintObservable(int n) {
706 if (n < 0 || n >= fNObservables) {
707 return;
708 }
709 string obsVal = GetObservable(n).ToString();
710 int lengthRemaining = Console::GetWidth() - 14 - 45 - 13;
711
712 std::cout << "Observable : " << ToString(fObservableNames[n], 45)
713 << " Value : " << ToString(obsVal, lengthRemaining) << std::endl;
714}
715
716Int_t TRestAnalysisTree::GetEntry(Long64_t entry, Int_t getall) {
717 if (fStatus == None) fStatus = EvaluateStatus();
718
719 if (fStatus == Created) {
721 } else if (fStatus == Retrieved) {
723 } else if (fStatus == EmptyCloned) {
725 } else if (fStatus == Connected) {
726 } else if (fStatus == Filled) {
727 }
728
729 if (fChain != nullptr) {
730 return fChain->GetEntry(entry, getall);
731 } else {
732 return TTree::GetEntry(entry, getall);
733 }
734}
735
736void TRestAnalysisTree::SetEventInfo(TRestAnalysisTree* tree) {
737 if (fChain != nullptr) {
738 cout << "Error! cannot fill tree. AnalysisTree is in chain state" << endl;
739 return;
740 }
741
742 if (tree != nullptr) {
743 fEventID = tree->GetEventID();
744 fSubEventID = tree->GetSubEventID();
745 fTimeStamp = tree->GetTimeStamp();
746 *fSubEventTag = tree->GetSubEventTag();
747 fRunOrigin = tree->GetRunOrigin();
748 fSubRunOrigin = tree->GetSubRunOrigin();
749 }
750}
751
752void TRestAnalysisTree::SetEventInfo(TRestEvent* evt) {
753 if (fChain != nullptr) {
754 cout << "Error! cannot fill tree. AnalysisTree is in chain state" << endl;
755 return;
756 }
757
758 if (evt != nullptr) {
759 fEventID = evt->GetID();
760 fSubEventID = evt->GetSubID();
761 fTimeStamp = evt->GetTimeStamp().AsDouble();
762 *fSubEventTag = evt->GetSubEventTag();
763 fRunOrigin = evt->GetRunOrigin();
764 fSubRunOrigin = evt->GetSubRunOrigin();
765 }
766}
767
768Int_t TRestAnalysisTree::Fill() {
769 if (fStatus == None) fStatus = EvaluateStatus();
770
771 if (fChain != nullptr) {
772 cout << "Error! cannot fill tree. AnalysisTree is in chain state" << endl;
773 return -1;
774 }
775
776 fSetObservableIndex = 0;
777
778 if (fStatus == Filled) {
779 return TTree::Fill();
780 } else if (fStatus == Created) {
782 int a = TTree::Fill();
783 fStatus = EvaluateStatus();
784 return a;
785 } else if (fStatus == Retrieved) {
787 int a = TTree::Fill();
788 fStatus = EvaluateStatus();
789 return a;
790 } else if (fStatus == EmptyCloned) {
792 int a = TTree::Fill();
793 fStatus = EvaluateStatus();
794 return a;
795 } else if (fStatus == Connected) {
797 int a = TTree::Fill();
798 fStatus = EvaluateStatus();
799 return a;
800 }
801 return -1;
802}
803
808 if (fChain != nullptr) {
809 cout << "Error! cannot set observable! AnalysisTree is in chain state" << endl;
810 return;
811 }
812 if (id == -1) {
813 // this means we want to find observable id by its name
814 id = GetObservableID(obs.name);
815 // if not found, we have a chance to create observable
816 if (id == -1) {
817 AddObservable(obs.name, obs.type);
818 id = GetObservableID(obs.name);
819 }
820 } else if (id == (int)fObservables.size()) {
821 // this means we want to add observable directly
822 AddObservable(obs.name, obs.type);
823 id = GetObservableID(obs.name);
824 }
825 if (id != -1) {
826 if (obs.type != fObservables[id].type) {
827 // if the observable branches are not created, and the type doesn't match,
828 // we still have the chance to fix. We reset fObservableTypes and fObservableMemory
829 // according to the input type value.
830 cout << "Warning: SetObservableValue(): setting value with different type. Observable : "
831 << obs.name << ", existing type: " << fObservables[id].type
832 << ", value to add is in type: " << obs.type << ", trying to update to the new type."
833 << endl;
834 fObservableTypes[id] = obs.type;
835 string name = fObservables[id].name;
836 fObservables[id].Destroy();
837 fObservables[id] = REST_Reflection::Assembly(obs.type);
838 fObservables[id].name = name;
839 }
840 obs >> fObservables[id];
841 }
842}
843
871 value.name = name;
872 SetObservable(-1, value);
873}
874
882Bool_t TRestAnalysisTree::EvaluateCuts(const string& cut) {
883 std::vector<string> cuts = Split(cut, "&&", false, true);
884
885 for (auto& cut : cuts) {
886 if (!EvaluateCut(cut)) {
887 return false;
888 }
889 }
890
891 return true;
892}
893
900Bool_t TRestAnalysisTree::EvaluateCut(const string& cut) {
901 const std::vector<string> validOperators = {"==", "<=", ">=", "!=", "=", ">", "<"};
902
903 if (cut.find("&&") != string::npos) return EvaluateCuts(cut);
904
905 string operation, observable;
906 Double_t value = -1;
907 for (const auto& validOperator : validOperators) {
908 if (cut.find(validOperator) != string::npos) {
909 operation = validOperator;
910 observable = (string)cut.substr(0, cut.find(operation));
911 value = std::stod((string)cut.substr(cut.find(operation) + operation.length(), string::npos));
912 break;
913 }
914 }
915
916 if (operation.empty())
917 cout << "TRestAnalysisTree::EvaluateCut. Invalid operator in cut definition! " << cut << endl;
918
919 Double_t val = GetDblObservableValue(observable);
920 if (operation == "==" && value == val) return true;
921 if (operation == "!=" && value != val) 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 if (operation == "<" && val < value) return true;
927
928 return false;
929}
930
935vector<string> TRestAnalysisTree::GetCutObservables(const string& cut_str) {
936 const std::vector<string> validOperators = {"==", "<=", ">=", "!=", "=", ">", "<"};
937
938 std::vector<string> cuts = Split(cut_str, "&&", false, true);
939
940 vector<string> obsNames;
941 for (auto& cut : cuts) {
942 string operation, observable;
943 for (const auto& validOperator : validOperators) {
944 if (cut.find(validOperator) != string::npos) {
945 obsNames.push_back((string)cut.substr(0, cut.find(validOperator)));
946 break;
947 }
948 }
949 }
950 return obsNames;
951}
952
956void TRestAnalysisTree::EnableBranches(vector<string> obsNames) {
957 for (auto& obsName : obsNames) this->SetBranchStatus(obsName.c_str(), true);
958}
959
963void TRestAnalysisTree::DisableBranches(vector<string> obsNames) {
964 for (auto& obsName : obsNames) this->SetBranchStatus(obsName.c_str(), false);
965}
966
970void TRestAnalysisTree::EnableAllBranches() { this->SetBranchStatus("*", true); }
971
975void TRestAnalysisTree::DisableAllBranches() { this->SetBranchStatus("*", false); }
976
984void TRestAnalysisTree::EnableQuickObservableValueSetting() { this->fQuickSetObservableValue = true; }
985
988void TRestAnalysisTree::DisableQuickObservableValueSetting() { this->fQuickSetObservableValue = false; }
989
994Double_t TRestAnalysisTree::GetObservableIntegral(const TString& obsName, Double_t xLow, Double_t xHigh) {
995 Int_t id = GetObservableID((std::string)obsName);
996
997 if (id < 0) {
998 RESTError << "TRestAnalysisTree::GetObservableIntegral. Observable not found! : " << obsName
999 << RESTendl;
1000 return 0;
1001 }
1002
1003 Double_t sum = 0;
1004 for (Int_t n = 0; n < TTree::GetEntries(); n++) {
1005 TTree::GetEntry(n);
1006 Double_t value = GetDblObservableValue(id);
1007
1008 if (xLow != -1 && xHigh != -1 && (value < xLow || value > xHigh)) continue;
1009 sum += value;
1010 }
1011
1012 return sum;
1013}
1014
1019Double_t TRestAnalysisTree::GetObservableAverage(const TString& obsName, Double_t xLow, Double_t xHigh) {
1020 Int_t id = GetObservableID((std::string)obsName);
1021
1022 if (id < 0) {
1023 RESTError << "TRestAnalysisTree::GetObservableAverage. Observable not found! : " << obsName
1024 << RESTendl;
1025 return 0;
1026 }
1027
1028 Double_t sum = 0;
1029 Int_t N = 0;
1030 for (Int_t n = 0; n < TTree::GetEntries(); n++) {
1031 TTree::GetEntry(n);
1032 Double_t value = GetDblObservableValue(id);
1033
1034 if (xLow != -1 && xHigh != -1 && (value < xLow || value > xHigh)) continue;
1035 N++;
1036 sum += value;
1037 }
1038
1039 if (N <= 0) return 0;
1040
1041 return sum / N;
1042}
1043
1048Double_t TRestAnalysisTree::GetObservableRMS(const TString& obsName, Double_t xLow, Double_t xHigh) {
1049 Double_t mean = GetObservableAverage(obsName, xLow, xHigh);
1050
1051 Int_t id = GetObservableID((std::string)obsName);
1052
1053 Double_t sum = 0;
1054 Int_t N = 0;
1055 for (Int_t n = 0; n < TTree::GetEntries(); n++) {
1056 TTree::GetEntry(n);
1057 Double_t value = GetDblObservableValue(id);
1058
1059 if (xLow != -1 && xHigh != -1 && (value < xLow || value > xHigh)) continue;
1060 N++;
1061
1062 sum += (value - mean) * (value - mean);
1063 }
1064
1065 if (N <= 0) return 0;
1066
1067 return TMath::Sqrt(sum / N);
1068}
1069
1074Double_t TRestAnalysisTree::GetObservableMaximum(const TString& obsName, Double_t xLow, Double_t xHigh) {
1075 Int_t id = GetObservableID((std::string)obsName);
1076
1077 if (id < 0) {
1078 RESTError << "TRestAnalysisTree::GetObservableMaximum. Observable not found! : " << obsName
1079 << RESTendl;
1080 return 0;
1081 }
1082
1083 Double_t max = -DBL_MAX;
1084 for (Int_t n = 0; n < TTree::GetEntries(); n++) {
1085 TTree::GetEntry(n);
1086 Double_t value = GetDblObservableValue(id);
1087
1088 if (xLow != -1 && xHigh != -1 && (value < xLow || value > xHigh)) continue;
1089 if (value > max) max = value;
1090 }
1091
1092 return max;
1093}
1094
1099Double_t TRestAnalysisTree::GetObservableMinimum(const TString& obsName, Double_t xLow, Double_t xHigh) {
1100 Int_t id = GetObservableID((std::string)obsName);
1101
1102 if (id < 0) {
1103 RESTError << "TRestAnalysisTree::GetObservableMinimum. Observable not found! : " << obsName
1104 << RESTendl;
1105 return 0;
1106 }
1107
1108 Double_t min = DBL_MAX;
1109 for (Int_t n = 0; n < TTree::GetEntries(); n++) {
1110 TTree::GetEntry(n);
1111 Double_t value = GetDblObservableValue(id);
1112
1113 if (xLow != -1 && xHigh != -1 && (value < xLow || value > xHigh)) continue;
1114 if (value < min) min = value;
1115 }
1116
1117 return min;
1118}
1119
1144Double_t TRestAnalysisTree::GetObservableContour(const TString& obsName, const TString& obsWeight,
1145 Double_t level, Int_t nBins, Double_t xLow, Double_t xHigh) {
1146 if (level > 1 || level < 0) {
1147 RESTWarning << "Level is : " << level << RESTendl;
1148 RESTWarning << "Level must be between 0 and 1" << RESTendl;
1149 return 0;
1150 }
1151
1152 Double_t integral = this->GetIntegral(obsWeight, xLow, xHigh);
1153
1154 TString histDefinition = Form("hc(%5d,%lf,%lf)", nBins, xLow, xHigh);
1155 if (xHigh == -1)
1156 this->Draw(obsName + ">>hc", obsWeight);
1157 else
1158 this->Draw(obsName + ">>" + histDefinition, obsWeight);
1159
1160 TH1F* htemp = (TH1F*)gPad->GetPrimitive("hc");
1161
1162 Double_t sum = 0;
1163 for (int i = 0; i < htemp->GetNbinsX(); i++) {
1164 sum += htemp->GetBinContent(i + 1);
1165
1166 if (sum > level * integral) return htemp->GetBinCenter(i + 1);
1167 }
1168 return 0;
1169}
1170
1175
1176std::vector<std::string> TRestAnalysisTree::GetObservableNames() {
1177 std::vector<std::string> names;
1178
1179 auto branches = GetListOfBranches();
1180 for (int i = 0; i < branches->GetEntries(); i++) {
1181 names.push_back((string)branches->At(i)->GetName());
1182 }
1183
1184 return names;
1185}
1186
1190Int_t TRestAnalysisTree::WriteAsTTree(const char* name, Int_t option, Int_t bufsize) {
1191 TTree* tree = new TTree();
1192
1193 char* dest = (char*)tree + sizeof(TObject);
1194 char* from = (char*)this + sizeof(TObject);
1195
1196 constexpr size_t n = sizeof(TTree) - sizeof(TObject);
1197
1198 // copy the data of the created TTree to a temporary location
1199 char* temp = (char*)malloc(n);
1200 memcpy(temp, dest, n);
1201
1202 // copy the data of this TRestAnalysisTree to TTree, and call the new TTree to write
1203 memcpy(dest, from, n);
1204 int result = tree->Write(name, option, bufsize);
1205
1206 // restore the data of the created TTree, then we can free it!
1207 memcpy(dest, temp, n);
1208 free(temp);
1209 delete tree;
1210
1211 return result;
1212}
1213
1219Bool_t TRestAnalysisTree::AddChainFile(const string& _file) {
1220 auto file = std::unique_ptr<TFile>{TFile::Open(_file.c_str(), "update")};
1221 if (!file->IsOpen()) {
1222 RESTWarning << "TRestAnalysisTree::AddChainFile(): failed to open file " << _file << RESTendl;
1223 return false;
1224 }
1225
1226 if (this->GetRunOrigin() == 0) {
1227 this->GetEntry(0);
1228 }
1229
1230 auto tree = (TRestAnalysisTree*)file->Get("AnalysisTree");
1231 if (tree != nullptr && tree->GetEntry(0)) {
1232 if (tree->GetEntry(0) > 0) {
1233 if (tree->GetRunOrigin() == this->GetRunOrigin()) {
1234 // this is a valid tree
1235 delete tree;
1236
1237 if (fChain == nullptr) {
1238 fChain = new TChain("AnalysisTree", "Chained AnalysisTree");
1239 fChain->Add(this->GetCurrentFile()->GetName());
1240 }
1241 return fChain->Add(_file.c_str()) == 1;
1242 }
1243 RESTWarning
1244 << "TRestAnalysisTree::AddChainFile(): invalid file, AnalysisTree in file has different "
1245 "run id!"
1246 << RESTendl;
1247 }
1248 RESTWarning << "TRestAnalysisTree::AddChainFile(): invalid file, AnalysisTree in file is empty!"
1249 << RESTendl;
1250 delete tree;
1251 }
1252 RESTWarning << "TRestAnalysisTree::AddChainFile(): invalid file, file does not contain an AnalysisTree!"
1253 << RESTendl;
1254
1255 return false;
1256}
1257
1264 if (fChain == nullptr) {
1265 return TTree::GetTree();
1266 }
1267 return (TTree*)fChain;
1268}
1269
1276Long64_t TRestAnalysisTree::LoadTree(Long64_t entry) {
1277 if (fChain == nullptr) {
1278 return TTree::LoadTree(entry);
1279 } else {
1280 return fChain->LoadTree(entry);
1281 }
1282
1283 return -2;
1284}
1285
1286Long64_t TRestAnalysisTree::GetEntries() const {
1287 if (fChain == nullptr) {
1288 return TTree::GetEntries();
1289 }
1290 return fChain->GetEntries();
1291}
1292
1293Long64_t TRestAnalysisTree::GetEntries(const char* sel) {
1294 if (fChain == nullptr) {
1295 return TTree::GetEntries(sel);
1296 }
1297 return fChain->GetEntries(sel);
1298}
1299
1300TRestAnalysisTree::~TRestAnalysisTree() { delete fSubEventTag; }
void SetValue(const T &val)
Set the value of the wrapped type.
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.
bool IsZombie() const
If this object type wrapper is invalid.
std::string ToString() const
Convert the wrapped object to std::string.
std::string name
Name field.
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(const std::string &typeName)
Wrap information an object of type: typeName, memory is not allocated.
TRestReflector Assembly(const 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.