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 <RootCoreUtils/ThrowMsg.h>

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 31 of file NTupleSvc.cxx.

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