ARTEMIS-CRIB
 
Loading...
Searching...
No Matches
TTreePeriodicEventStore.cc
Go to the documentation of this file.
1/**
2 * @file TTreePeriodicEventStore.cc
3 * @brief
4 * @author Kodai Okawa <okawa@cns.s.u-tokyo.ac.jp>
5 * @date 2023-08-01 22:36:36
6 * @note last modified: 2025-03-04 19:20:39
7 * @details just modify the process() from TTreeEventStore to return 0
8 */
9
11
12#include <TChain.h>
13#include <TEventHeader.h>
14#include <TLeaf.h>
15#include <TObjString.h>
16#include <TSystem.h>
17
18/// ROOT macro for class implementation
20
21namespace art::crib {
22
24 RegisterProcessorParameter("FileName", "The name of input file", fFileName, fFileName);
25 RegisterProcessorParameter("TreeName", "The name of input tree", fTreeName, fTreeName);
26 RegisterProcessorParameter("MaxEventNum", "The maximum event number to be analyzed.", fMaxEventNum, 0L);
27}
31
32/**
33 * @details
34 * Init method:
35 * 1) Retrieve fCondition from TEventCollection
36 * 2) Get file list from shell command
37 * 3) Build TChain if necessary
38 * 4) Set branch addresses (primitive or class objects)
39 * 5) Load the first entry and get total entry counts
40 */
41void TTreePeriodicEventStore::Init(TEventCollection *col) {
42 // 1) Get fCondition pointer from TEventCollection (for TLoop control)
43 void **tmpCondRef = col->Get(TLoop::kConditionName)->GetObjectRef();
44 if (!tmpCondRef) {
45 Error("Init", "fCondition: tmpCondRef is null");
46 return;
47 }
48 fCondition = reinterpret_cast<TConditionBit **>(tmpCondRef);
49 if (!fCondition) {
50 Error("Init", "fCondition is null after reinterpret_cast");
51 return;
52 }
53 if (*fCondition) {
54 TConditionBit *condPtr = dynamic_cast<TConditionBit *>(*fCondition);
55 if (!condPtr) {
56 Error("Init", "fCondition: *fCondition is not a TConditionBit!");
57 return;
58 }
59 } else {
60 Warning("Init", "fCondition: *fCondition is null. It might be set later?");
61 }
62
63 // 2) Get the list of files
64 auto filelist = gSystem->GetFromPipe(Form("ls -tr %s", fFileName.Data()));
65 auto *allfiles = filelist.Tokenize("\n");
66 if (!allfiles) {
67 SetStateError(Form("No files matched '%s'", fFileName.Data()));
68 if (fCondition)
69 (*fCondition)->Set(TLoop::kStopLoop);
70 return;
71 }
72
73 // Check MaxEventNum
74 if (fMaxEventNum == 0) {
75 SetStateError("MaxEventNum == 0 => No event is processed.");
76 if (fCondition)
77 (*fCondition)->Set(TLoop::kStopLoop);
78 return;
79 }
80
81 // 3) Build TChain if fTree is not created yet
82 if (!fTree) {
83 auto *chain = new TChain(fTreeName);
84 for (int i = 0, n = allfiles->GetEntriesFast(); i < n; ++i) {
85 auto *strObj = dynamic_cast<TObjString *>(allfiles->At(i));
86 if (!strObj)
87 continue;
88 Info("Init", "Add '%s'", (strObj->GetString()).Data());
89 chain->Add(strObj->GetString());
90 }
91 fTree = chain;
92 }
93
94 if (!fTree) {
95 Error("Init", "Failed to create TChain for tree = '%s'", fTreeName.Data());
96 if (fCondition)
97 (*fCondition)->Set(TLoop::kStopLoop);
98 return;
99 }
100
101 // Initialize event counters
102 fEventNum = 0;
103 fCurrentNum = 0;
104
105 // 4) Explore each branch and set addresses
106 std::vector<TBranch *> useBranch;
107 TIter nextBr(fTree->GetListOfBranches());
108 while (auto *br = dynamic_cast<TBranch *>(nextBr())) {
109 TClass *cl = nullptr;
110 EDataType dtype = kNoType_t;
111 // If GetExpectedType fails, skip
112 if (br->GetExpectedType(cl, dtype)) {
113 Warning("Init", "Unresolved type for branch '%s'", br->GetName());
114 continue;
115 }
116
117 // Case A: Primitive type
118 if (!cl) {
119 // We force arrSize to be at least 1
120 int arrSize = 1;
121 if (auto *leaf = br->GetLeaf(br->GetName())) {
122 leaf = leaf->GetLeafCounter(arrSize);
123 if (arrSize < 1) {
124 arrSize = 1; // enforce a minimum of 1
125 }
126 }
127 void *arrPtr = nullptr;
128 switch (dtype) {
129 case kInt_t:
130 arrPtr = new Int_t[arrSize];
131 break;
132 case kFloat_t:
133 arrPtr = new Float_t[arrSize];
134 break;
135 case kDouble_t:
136 arrPtr = new Double_t[arrSize];
137 break;
138 default:
139 break;
140 }
141 if (!arrPtr) {
142 continue;
143 }
144
145 // Register this array in TEventCollection
146 col->Add(new TEventObject(
147 br->GetName(),
148 arrPtr,
149 TString(TDataType::GetTypeName(dtype)),
150 nullptr));
151 auto **objRef = col->Get(br->GetName())->GetObjectRef();
152 if (!objRef) {
153 Error("Init", "Branch '%s': tmpRef is null (unexpected)", br->GetName());
154 continue;
155 }
156 fTree->SetBranchAddress(br->GetName(), *objRef);
157 useBranch.emplace_back(br);
158 Info("Init", "branch : %s (type=%s, size=%d)",
159 br->GetName(), TDataType::GetTypeName(dtype), arrSize);
160 }
161 // Case B: Class type (including TClonesArray)
162 else {
163 // Check TClonesArray
164 if (cl == TClonesArray::Class()) {
165 TClonesArray *arr = nullptr;
166 // Temporarily enable only this branch to check its class info
167 fTree->SetBranchStatus("*", 0);
168 fTree->SetBranchStatus(br->GetName(), 1);
169 fTree->SetBranchAddress(br->GetName(), &arr);
170 fTree->GetEntry(0);
171
172 if (arr) {
173 TClass *realcls = arr->GetClass();
174 if (!realcls || !realcls->GetNew()) {
175 // If the class cannot be instantiated, skip
176 cl = nullptr;
177 }
178 }
179 br->ResetAddress();
180 }
181
182 // If still valid, create an instance and set address
183 if (cl) {
184 // Create a new object of this class
185 auto *obj = static_cast<TObject *>(cl->New());
186 col->Add(br->GetName(), obj, kTRUE);
187
188 void **tmpRef = col->Get(br->GetName())->GetObjectRef();
189 if (!tmpRef) {
190 Error("Init", "Branch '%s': tmpRef is null (unexpected)", br->GetName());
191 continue;
192 }
193
194 auto **objRef = reinterpret_cast<TObject **>(tmpRef);
195 if (!objRef) {
196 Error("Init", "Branch '%s': objRef is null after cast", br->GetName());
197 continue;
198 }
199 if (*objRef) {
200 TObject *checkObj = dynamic_cast<TObject *>(*objRef);
201 if (!checkObj) {
202 Error("Init",
203 "Branch '%s': *objRef is not a TObject. Type mismatch?",
204 br->GetName());
205 continue;
206 }
207 }
208
209 fTree->SetBranchAddress(br->GetName(), objRef);
210
211 useBranch.emplace_back(br);
212
213 // If it's TEventHeader, store pointer in fEventHeader
214 if (cl == TEventHeader::Class()) {
215 fEventHeader = static_cast<art::TEventHeader *>(obj);
216 }
217 Info("Init", "Branch: %s (class=%s)", br->GetName(), cl->GetName());
218 }
219 }
220 }
221
222 // Add user info objects to the collection
223 TIter nextInfo(fTree->GetUserInfo());
224 while (auto *infoObj = nextInfo()) {
225 col->AddInfo(infoObj->GetName(), infoObj, kTRUE);
226 }
227
228 // Enable only branches we decided to use
229 fTree->SetBranchStatus("*", 0);
230 for (auto *br : useBranch) {
231 fTree->SetBranchStatus(br->GetName(), 1);
232 }
233
234 // Load the first entry and get total entries
235 fTree->LoadTree(0);
236 fTree->GetEntry(0);
237 fTreeEventNum = fTree->GetEntries();
238}
239
240/**
241 * @details
242 * Process method: called for each event
243 * - Load entry from fTree
244 * - Increment counters
245 * - Wrap around if needed
246 * - Stop if reaching fMaxEventNum
247 */
249 fTree->GetEntry(fCurrentNum);
250 ++fCurrentNum;
251 ++fEventNum;
252
253 // Wrap around if we reach the end of the tree
254 if (fCurrentNum == fTreeEventNum) {
255 fCurrentNum = 0;
256 }
257 // Stop if we reached the maximum events
258 if (fMaxEventNum == fEventNum) {
259 SetStopLoop();
260 SetEndOfRun();
261 }
262}
263
265 return (fEventHeader) ? fEventHeader->GetRunNumber() : 0;
266}
267
269 return "";
270}
271
273 return (fEventHeader) ? std::string(fEventHeader->GetRunName()) : "";
274}
275
276} // namespace art::crib
ClassImp(art::crib::TTreePeriodicEventStore)
ROOT macro for class implementation.
Declaration of TTreePeriodicEventStore for periodic event handling in a TTree.
A processor class that implements periodic event reading from a TTree.
void Init(TEventCollection *col) override
Initializes the TTreePeriodicEventStore with the given event collection.
TString fFileName
The name (or pattern) of the input file(s). Default is "temp.root".
Int_t GetRunNumber() const override
Returns the run number of the current event.
Long_t fCurrentNum
The current entry index in the TTree.
Long_t fEventNum
The current event number within the run.
TString fTreeName
The name of the TTree to be processed. Default is "tree".
Long_t fTreeEventNum
The total number of events in the TTree.
void Process() override
Processes one event from the TTree.
TEventHeader * fEventHeader
! Pointer to the TEventHeader object read from the TTree.
TTree * fTree
! Pointer to the TTree object that holds event data.
std::string GetStrRunName() const
Returns the run name as a std::string.
Long_t fMaxEventNum
The maximum number of events to process.
const char * GetRunName() const override
Returns the run name as a C-style string.
return to the guide