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