ATLAS Offline Software
Loading...
Searching...
No Matches
NTupleSvc.cxx File Reference
#include <EventLoopAlgs/NTupleSvc.h>
#include <fstream>
#include <memory>
#include <TBranchElement.h>
#include <TFile.h>
#include <TLeaf.h>
#include <TRegexp.h>
#include <TTree.h>
#include <EventLoop/Job.h>
#include <EventLoop/StatusCode.h>
#include <EventLoop/IWorker.h>
#include <EventLoopAlgs/WhiteBoardSvc.h>
#include <RootCoreUtils/Assert.h>
#include <format>
#include <stdexcept>

Go to the source code of this file.

Functions

 ClassImp (EL::NTupleSvc) namespace EL

Function Documentation

◆ ClassImp()

ClassImp ( EL::NTupleSvc )
Author
Nils Krumnack

Definition at line 32 of file NTupleSvc.cxx.

35{
36 NTupleSvc *getNTupleSvc (IWorker *worker, const std::string& outputStream,
37 const std::string& treeName)
38 {
39 RCU_REQUIRE_SOFT (worker != 0);
41 NTupleSvc *result = dynamic_cast<NTupleSvc*>
42 (worker->getAlg ("NTupleSvc_" + outputStream + "_" + treeName));
43 if (result == 0)
44 {
45 result = dynamic_cast<NTupleSvc*>
46 (worker->getAlg ("NTupleSvc_" + outputStream));
47 }
48 RCU_ASSERT2_SOFT (result != 0, "output algorithm not found");
49 return result;
50 }
51
52
53
54 void NTupleSvc ::
55 testInvariant () const
56 {}
57
58
59
60 NTupleSvc ::
61 NTupleSvc (const std::string& val_outputName)
62 : m_file (0), m_tree (0), m_initialized (false),
63 m_whiteboard (0)
64 {
65 RCU_REQUIRE_SOFT (!val_outputName.empty());
66
67 m_outputName = val_outputName;
68
69 RCU_NEW_INVARIANT (this);
70 }
71
72
73
74 NTupleSvc ::
75 ~NTupleSvc ()
76 {
78 }
79
80
81
82 void NTupleSvc ::
83 copyBranch (const std::string& name)
84 {
86 m_copyBranches.insert (name);
87 }
88
89
90
91 void NTupleSvc ::
92 copyBranchList (const std::string& fileName)
93 {
94 // no invariant used
95
96 std::ifstream file (fileName.c_str());
97 std::string line;
98 while (getline (file, line))
99 {
100 while (!line.empty() && isspace (line[0]))
101 line = line.substr (1);
102 while (!line.empty() && isspace (line[line.size()-1]))
103 line.pop_back();
104 if (!line.empty() && line[0] != '#')
105 copyBranch (line);
106 }
107 }
108
109
110
111 void NTupleSvc ::
112 addWhiteFloat (const std::string& varName)
113 {
115 m_whiteFloat.insert (varName);
116 }
117
118
119
120 void NTupleSvc ::
121 addWhiteArray (const std::string& varName)
122 {
124 m_whiteArray.insert (varName);
125 }
126
127
128
129 TTree *NTupleSvc ::
130 tree () const
131 {
132 RCU_READ_INVARIANT (this);
133 RCU_REQUIRE2_SOFT (m_tree != 0, "initialize() has been called");
134 return m_tree;
135 }
136
137
138
139 bool NTupleSvc ::
140 getFilterPassed () const
141 {
142 RCU_READ_INVARIANT (this);
143 return m_taken;
144 }
145
146
147
148 void NTupleSvc ::
149 setFilterPassed (bool passed)
150 {
152 if (passed)
153 m_taken = true;
154 }
155
156
157
158 const std::string& NTupleSvc ::
159 treeName () const
160 {
161 RCU_READ_INVARIANT (this);
162 return m_treeName;
163 }
164
165
166
167 void NTupleSvc ::
168 treeName (const std::string& val_treeName)
169 {
171 m_treeName = val_treeName;
172 }
173
174
175
176 const char *NTupleSvc ::
177 GetName () const
178 {
179 RCU_READ_INVARIANT (this);
180 return m_outputName.c_str();
181 }
182
183
184
185 StatusCode NTupleSvc ::
186 setupJob (Job& job)
187 {
189 RCU_REQUIRE2_SOFT (job.outputHas (m_outputName), ("output stream " + m_outputName + " not configured. try:\n EL::OutputStream output (\"" + m_outputName + "\");\n job.addOutput (output);").c_str());
190 return EL::StatusCode::SUCCESS;
191 }
192
193
194
195 EL::StatusCode NTupleSvc :: changeInput (bool /*firstFile*/)
196 {
198
199 m_connected = false;
200 return EL::StatusCode::SUCCESS;
201 }
202
203
204
205 EL::StatusCode NTupleSvc :: initialize ()
206 {
208
209 m_file = wk()->getOutputFile (m_outputName);
210 std::string name = m_treeName;
211 if (name.empty()) name = wk()->tree()->GetName();
212 TDirectory *curDir = gDirectory;
213 try
214 {
215 m_file->cd ();
216 m_tree = new TTree (name.c_str(), m_tree_title.c_str());
217 curDir->cd ();
218 } catch (...)
219 {
220 curDir->cd ();
221 }
222
223 // Turn off auto saving:
224 m_tree->SetAutoSave(10000);
225 // Flush the tree contents after collecting 30 MB in memory:
226 m_tree->SetAutoFlush( -30000000 );
227 TTree::SetBranchStyle(1);
228
229 return EL::StatusCode::SUCCESS;
230 }
231
232
233
234 EL::StatusCode NTupleSvc :: execute ()
235 {
237
238 m_taken = false;
239 return EL::StatusCode::SUCCESS;
240 }
241
242
243
244 EL::StatusCode NTupleSvc :: postExecute ()
245 {
247
248 initBranches ();
249
250 if (!m_taken)
251 return EL::StatusCode::SUCCESS;
252
253 copyInput ();
254
255 for (whiteInfoMIter iter = m_whiteInfo.begin(),
256 end = m_whiteInfo.end(); iter != end; ++ iter)
257 {
258 if (iter->array)
259 {
260 std::size_t size;
261 const float *values;
262 m_whiteboard->getArray (iter->name, size, values);
263 std::vector<float>(values,values+size).swap (iter->buffer);
264 } else
265 iter->buffer[0] = m_whiteboard->getFloat (iter->name);
266 }
267
268 m_tree->Fill ();
269 return EL::StatusCode::SUCCESS;
270 }
271
272
273
274 bool NTupleSvc ::
275 hasName (const std::string& name) const
276 {
277 RCU_READ_INVARIANT (this);
278 return
279 name == "NTupleSvc_" + m_outputName ||
280 name == "NTupleSvc_" + m_outputName + "_" + m_treeName;
281 }
282
283
284
285 void NTupleSvc ::
286 initBranches ()
287 {
288 if (m_initialized == false)
289 {
290 m_initialized = true;
291
292 std::set<std::string> branchList;
293
294 findBranches (branchList);
295 initOutput (branchList);
296
297 for (m_whiteFloatIter iter = m_whiteFloat.begin(),
298 end = m_whiteFloat.end(); iter != end; ++ iter)
299 {
300 WhiteInfo info;
301 info.name = *iter;
302 info.array = false;
303 m_whiteInfo.push_back (info);
304 }
305 for (m_whiteArrayIter iter = m_whiteArray.begin(),
306 end = m_whiteArray.end(); iter != end; ++ iter)
307 {
308 WhiteInfo info;
309 info.name = *iter;
310 info.array = true;
311 m_whiteInfo.push_back (info);
312 }
313 for (whiteInfoMIter iter = m_whiteInfo.begin(),
314 end = m_whiteInfo.end(); iter != end; ++ iter)
315 {
316 if (iter->array)
317 {
318 iter->pointer = &iter->buffer;
319 m_tree->Branch (iter->name.c_str(), &iter->pointer);
320 } else
321 {
322 iter->buffer.resize (1);
323 m_tree->Branch (iter->name.c_str(), &iter->buffer[0], (iter->name + "/F").c_str());
324 }
325 }
326 if (!m_whiteInfo.empty())
327 m_whiteboard = getWhiteBoardSvc (wk());
328 }
329 }
330
331
332 void NTupleSvc ::
333 findBranches (std::set<std::string>& branchList)
334 {
335 for (m_copyBranchesIter iter = m_copyBranches.begin(),
336 end = m_copyBranches.end(); iter != end; ++ iter)
337 {
338 std::size_t count = 0;
339 TRegexp pattern (*iter);
340 TObject *object = 0;
341
342 for (TIter branchIter (wk()->tree()->GetListOfBranches());
343 (object = branchIter());)
344 {
345 TString str (object->GetName());
346 Ssiz_t len = 0;
347
348 if (pattern.Index (str, &len) == 0 && len == str.Length())
349 {
350 branchList.insert (str.Data());
351 ++ count;
352 }
353 }
354 if (count == 0)
355 throw std::runtime_error ("could not find any branch that matches pattern \"" + *iter + "\"");
356 }
357 }
358
359
360
361 void NTupleSvc ::
362 initOutput (const std::string& branchName)
363 {
364 // rationale: this ensures that I am not copying branches twice
365 for (copyInfoMIter branch = m_copyInfo.begin(),
366 end = m_copyInfo.end(); branch != end; ++ branch)
367 {
368 if (branch->name == branchName)
369 return;
370 }
371
372 CopyInfo info;
373 info.name = branchName;
374 info.source = wk()->tree()->FindBranch (branchName.c_str());
375 if (info.source == 0)
376 throw std::runtime_error ("could not find input branch: " + branchName);
377
378 const char *className = info.source->GetClassName();
379 if (strlen (className) > 0)
380 {
381 info.target = m_tree->Branch (branchName.c_str(), className,
382 static_cast<void*>(0));
383 } else
384 {
385 static std::map<std::string,std::string> types;
386 if (types.empty())
387 {
388 types["Char_t"] = "B";
389 types["UChar_t"] = "b";
390 types["Short_t"] = "S";
391 types["UShort_t"] = "s";
392 types["Int_t"] = "I";
393 types["UInt_t"] = "i";
394 types["Float_t"] = "F";
395 types["Double_t"] = "D";
396 types["Long64_t"] = "L";
397 types["ULong64_t"] = "l";
398 types["Bool_t"] = "O";
399 }
400
401 std::string leaves;
402 TObject *object;
403 for (TIter iter = info.source->GetListOfLeaves(); (object = iter()); )
404 {
405 TLeaf *myleaf = dynamic_cast<TLeaf*>(object);
406 if (myleaf == 0)
407 throw std::runtime_error ("found non-leaf object in leaf list");
408
409 std::string typeName = myleaf->GetTypeName();
410 std::map<std::string,std::string>::const_iterator type
411 = types.find (typeName);
412 if (type == types.end())
413 throw std::runtime_error ("unknown leaf type " + typeName);
414
415 if (!leaves.empty())
416 leaves += ":";
417 leaves = leaves + myleaf->GetTitle() + "/" + type->second;
418 }
419 if (leaves.empty())
420 throw std::runtime_error ("failed to scan leaves of branch " + branchName);
421
422 for (std::string::size_type pos = 0;
423 (pos = leaves.find ("[", pos)) != std::string::npos; )
424 {
425 ++ pos;
426 std::string::size_type pos2 = leaves.find ("]", pos);
427 if (pos2 == std::string::npos)
428 throw std::runtime_error ("failed to scan leaf dimensions for " + leaves);
429 std::string dim = leaves.substr (pos, pos2 - pos);
430 if (!(dim[0] >= '0' && dim[0] <= '9'))
431 initOutput (dim);
432 }
433 info.target = m_tree->Branch (branchName.c_str(), static_cast<void*>(0),
434 leaves.c_str());
435 }
436 m_copyInfo.push_back (info);
437 }
438
439
440
441 void NTupleSvc ::
442 initOutput (const std::set<std::string>& branchList)
443 {
444 for (std::set<std::string>::const_iterator branch = branchList.begin(),
445 end = branchList.end(); branch != end; ++ branch)
446 initOutput (*branch);
447 }
448
449
450
451 void NTupleSvc ::
452 copyInput ()
453 {
454 if (!m_connected)
455 {
456 for (copyInfoMIter info = m_copyInfo.begin(),
457 end = m_copyInfo.end(); info != end; ++ info)
458 {
459 info->source = dynamic_cast<TBranch*>
460 (wk()->tree()->GetBranch (info->name.c_str()));
461 RCU_ASSERT2_SOFT (info->source != 0, ("source branch " + info->name + " not found for copying").c_str());
462 }
463 m_connected = true;
464 }
465
466 for (copyInfoMIter info = m_copyInfo.begin(),
467 end = m_copyInfo.end(); info != end; ++ info)
468 {
469 void *address = info->source->GetAddress();
470 if (address == 0)
471 {
472 std::size_t size = sizeof (void*);
473 TObject *object;
474 for (TIter iter = info->source->GetListOfLeaves();
475 (object = iter());)
476 {
477 TLeaf *myleaf = dynamic_cast<TLeaf*>(object);
478 RCU_ASSERT (myleaf != 0);
479 Int_t countval;
480 TLeaf *countleaf = myleaf->GetLeafCounter (countval);
481 if (countleaf)
482 countval = countleaf->GetMaximum();
483 if (countval < 0)
484 throw std::runtime_error (std::format ("could not determine size of leaf {} in branch {}", myleaf->GetName(), info->name));
485 if (countval == 0)
486 countval = 1;
487 const std::size_t mysize
488 = myleaf->GetOffset() + myleaf->GetLenType() * countval;
489 if (size < mysize)
490 size = mysize;
491 }
492 info->buffer.resize (size, 0);
493 info->source->SetStatus (1);
494 info->source->SetAddress (address = &info->buffer[0]);
495 }
496 RCU_ASSERT (address != 0);
497 info->target->SetAddress (address);
498 info->source->GetEntry (wk()->treeEntry(), 1);
499 }
500 }
501}
#define RCU_ASSERT(x)
Definition Assert.h:210
#define RCU_DESTROY_INVARIANT(x)
Definition Assert.h:223
#define RCU_ASSERT2_SOFT(x, y)
Definition Assert.h:157
#define RCU_CHANGE_INVARIANT(x)
Definition Assert.h:219
#define RCU_REQUIRE2_SOFT(x, y)
Definition Assert.h:143
#define RCU_NEW_INVARIANT(x)
Definition Assert.h:221
#define RCU_REQUIRE_SOFT(x)
Definition Assert.h:141
#define RCU_READ_INVARIANT(x)
Definition Assert.h:217
bool passed(DecisionID id, const DecisionIDContainer &)
checks if required decision ID is in the set of IDs in the container
static const std::vector< std::string > types
size_t size() const
Number of registered mappings.
int count(std::string s, const std::string &regx)
count how many occurances of a regx are in a string
Definition hcg.cxx:148
ID3PD * m_tree
Pointer to the ID3PD object used.
NTupleSvc * getNTupleSvc(IWorker *worker, const std::string &outputStream, const std::string &treeName="")
effects: get the skimming algorithm for the given output for this worker guarantee: strong failures: ...
::StatusCode StatusCode
StatusCode definition for legacy code.
WhiteBoardSvc * getWhiteBoardSvc(IWorker *worker)
effects: get the whiteboard service for this worker guarantee: strong failures: formula service not c...
NTupleSvc
Definition Lb2Lll.py:200
TChain * tree
TFile * file