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