ATLAS Offline Software
VectorFillerToolBase.cxx
Go to the documentation of this file.
1 /*
2  Copyright (C) 2002-2023 CERN for the benefit of the ATLAS collaboration
3 */
16 #include "GaudiKernel/System.h"
17 #include "TClass.h"
18 #include "TROOT.h"
19 #include "TDataType.h"
20 #include "TVirtualCollectionProxy.h"
21 #include <cstring>
22 #include <cassert>
23 
24 
25 namespace D3PD {
26 
27 
31 inline
33 {
34  *m_addr += m_valdiff;
35 }
36 
37 
41 inline
43 {
44  for (Var& v : *this) {
45  v.next();
46  }
47 }
48 
49 
57  const std::string& name,
58  const IInterface* parent)
59  : AthAlgTool (type, name, parent),
60  m_metadata (),
61  m_prefix (),
62  m_blockFillers (this),
63  m_tree (0),
64  m_nrow (0),
65  m_nobj (0),
66  m_objIndex (0)
67 {
68  declareProperty ("BlockFillers", m_blockFillers,
69  "List of contained block filler tools.");
70  declareProperty ("Prefix", m_prefix = "",
71  "Variable name prefix for the contained blocks.");
72  declareProperty ("NrowName", m_nrowName = "n",
73  "Name of the variable for the count of rows. "
74  "Omitted if empty.");
75  declareProperty ("NobjName", m_nobjName = "",
76  "Name of the variable for the count of objects. "
77  "Omitted if empty.");
78  declareProperty ("ObjIndexName", m_objIndexName = "",
79  "Name of the variable for the object index. "
80  "Omitted if empty.");
81 }
82 
83 
89 {
91  CHECK( m_blockFillers.retrieve() );
92  return StatusCode::SUCCESS;
93 }
94 
95 
100 {
101  // Don't clear the m_vars variable, because some memory will never be freed
102  // in that case...
103  return StatusCode::SUCCESS;
104 }
105 
106 
113 {
114  // Create the count/index variables.
115  if (!m_nrowName.empty()) {
117  "Number of ntuple rows.") );
119  "Number of ntuple rows.") );
120  }
121  if (!m_nobjName.empty()) {
123  "Number of objects.") );
125  "Number of objects.") );
126  }
127  if (!m_objIndexName.empty())
129  "Index of this object.") );
130 
131  // Book child variables.
132  for (size_t i = 0; i < m_blockFillers.size(); i++)
133  CHECK( m_blockFillers[i]->book() );
134 
135  return StatusCode::SUCCESS;
136 }
137 
138 
148 {
149  m_tree = tree;
150 
151  // Get the type of object we'll get from the iteration.
152  const std::type_info& ti = it.elementTypeinfo();
153 
154  // Configure all child tools.
155  for (size_t i = 0; i < m_blockFillers.size(); i++)
156  CHECK( m_blockFillers[i]->configureD3PD (this, ti) );
157 
158  return StatusCode::SUCCESS;
159 }
160 
161 
167 void VectorFillerToolBase::maybeExtend (size_t& n, size_t& sz)
168 {
169  if (n >= sz) {
170  sz = std::max(static_cast<size_t>(16), 2*sz);
171  m_vars.resize_all (sz, n);
172  }
173 }
174 
175 
197  size_t objndx,
198  size_t& n,
199  size_t& sz,
200  const std::vector<unsigned long>& codes_in,
201  std::vector<unsigned long>& codes_out)
202 {
203  codes_out.resize (m_blockFillers.size());
204 
205  // Extend vectors if needed.
206  maybeExtend (n, sz);
207 
208  // Loop over block fillers.
209  bool all_empty = true;
210  for (size_t j = 0; j < m_blockFillers.size(); j++) {
211  StatusCode scode =
212  m_blockFillers[j]->fillUntyped(obj,
213  codes_in[j] == IBlockFillerTool::AGAIN);
214  codes_out[j] = scode.getCode();
215  if (codes_out[j] != IBlockFillerTool::EMPTY)
216  all_empty = false;
217  CHECK( IBlockFillerTool::againok (scode) );
218  }
219 
220  // If all tools returned empty, then ignore this row.
221  // But don't ignore it if there are no block fillers at all
222  // (it may be that an associator tool will be filling variables).
223  if (!all_empty || m_blockFillers.empty()) {
224  if (m_objIndex)
225  *m_objIndex = objndx;
226 
227  // Count rows and update variable pointers.
228  ++n;
229  m_vars.next_all();
230  }
231 
232  return StatusCode::SUCCESS;
233 }
234 
235 
245 {
246  // Set variable vectors to the expected size.
247  m_vars.resize_all (sizeHint);
248  size_t n = 0;
249  size_t nobj = 0;
250  size_t sz = sizeHint;
251 
252  std::vector<unsigned long> codes_in;
253  std::vector<unsigned long> codes_out;
254 
255  // Loop over objects.
256  // Note: @c nextUntyped may try to fill variables. Make sure there's space.
257  maybeExtend (n, sz);
258  while (const void* obj = it.nextUntyped() ) {
259  // AGAIN processing.
260  codes_in.clear();
261  codes_in.resize (m_blockFillers.size(), StatusCode(StatusCode::SUCCESS).getCode());
262  CHECK( fillOnce (obj, nobj, n, sz, codes_in, codes_out) );
263  codes_in = codes_out;
264  while (std::find (codes_out.begin(), codes_out.end(),
265  (unsigned long)IBlockFillerTool::AGAIN)
266  != codes_out.end())
267  {
268  CHECK( fillOnce (obj, nobj, n, sz, codes_in, codes_out) );
269  }
270 
271  ++nobj;
272 
273  it.releaseElementUntyped (obj);
274  maybeExtend (n, sz);
275  }
276 
277  // Set vectors to the proper final size.
278  if (sz != n)
279  m_vars.resize_all (n);
280 
281  // Save the counts.
282  if (m_nrow)
283  *m_nrow = n;
284  if (m_nobj)
285  *m_nobj = nobj;
286 
287  return StatusCode::SUCCESS;
288 }
289 
290 
307  const std::type_info& ti,
308  void* & ptr,
309  const std::string& docstring /*= ""*/,
310  const void* defval /*= 0*/)
311 {
312  if (!m_tree) {
313  // Called from constructor --- just initialize pointer.
314  ptr = 0;
315  return StatusCode::SUCCESS;
316  }
317 
318  // Default value handling.
319  size_t defsize = 0;
320  char* defcopied = 0;
321  if (defval) {
322  EDataType dt = TDataType::GetType (ti);
323  switch (dt) {
324  case kChar_t:
325  case kUChar_t:
326  case kShort_t:
327  case kUShort_t:
328  case kInt_t:
329  case kUInt_t:
330  case kLong_t:
331  case kULong_t:
332  case kFloat_t:
333  case kDouble_t:
334  case kDouble32_t:
335  case kchar:
336  case kBool_t:
337  case kLong64_t:
338  case kULong64_t:
339  case kFloat16_t:
340  // ok
341  break;
342 
343  default:
344  REPORT_MESSAGE (MSG::ERROR)
345  << "Requested a default value for variable " << name
346  << " of type " << System::typeinfoName (ti)
347  << "; but default values are only supported for basic types.";
348  return StatusCode::FAILURE;
349  }
350 
351  TDataType* tdt = gROOT->GetType (TDataType::GetTypeName (dt));
352  assert (tdt != 0);
353  defsize = tdt->Size();
354  defcopied = new char[defsize];
355  std::memcpy (defcopied, defval, defsize);
356  }
357 
358  m_vars.push_back (Var (name, ti, ptr, docstring, defcopied, defsize));
359  CHECK( m_vars.back().init (&m_metadata, m_prefix) );
360  CHECK( m_vars.back().init (m_tree, m_prefix) );
361 
362  return StatusCode::SUCCESS;
363 }
364 
365 
383 VectorFillerToolBase::addDimensionedVariable (const std::string& /*name*/,
384  const std::type_info& /*ti*/,
385  void* & /*ptr*/,
386  const std::string& /*dim*/,
387  const std::string& /*docstring = ""*/,
388  const void* /*defval = 0*/)
389 {
390  REPORT_MESSAGE(MSG::ERROR) << "addDimensionedVariable not yet implemented.";
391  return StatusCode::FAILURE;
392 }
393 
394 
409  const std::type_info& ti,
410  void* & ptr,
411  const std::string& docstring,
412  char* defval,
413  size_t defsize)
414  : m_name (name),
415  m_ti (&ti),
416  m_addr (reinterpret_cast<char**> (&ptr)),
417  m_docstring (docstring),
418  m_proxy (0),
419  m_valdiff (0),
420  m_contptr (0),
421  m_default (defval),
422  m_defsize (defsize)
423 {
424 }
425 
426 
433  const std::string& prefix)
434 {
435  // Get the name of the element variable.
436  std::string eltname = typeinfoToName (*m_ti);
437 
438  // Use vector<int> instead of vector<bool>.
439  if (eltname == "bool")
440  eltname = "int";
441 
442  // Construct the vector name.
443  std::string vname = "std::vector<" + eltname;
444  if (vname[vname.size()-1] == '>')
445  vname += ' ';
446  vname += '>';
447 
448  // Fetch the root dictionary for the vector and find the proxy.
449  TClass* cls = TClass::GetClass (vname.c_str());
450  if (!cls) {
451  REPORT_MESSAGE(MSG::ERROR) << "Can't find TClass for type "
452  << vname
453  << " for variable "
454  << prefix + m_name;
455  return StatusCode::FAILURE;
456  }
457  m_proxy = cls->GetCollectionProxy();
458 
459  if (!m_proxy) {
460  REPORT_MESSAGE(MSG::ERROR) << "Can't find root collection proxy for type "
461  << vname
462  << " for variable "
463  << prefix + m_name;
464  return StatusCode::FAILURE;
465  }
466 
467  if (!m_proxy->GetCollectionClass() ||
468  !m_proxy->GetCollectionClass()->GetTypeInfo())
469  {
470  REPORT_MESSAGE(MSG::ERROR) << "Dictionary error for collection class "
471  << vname
472  << " for variable "
473  << prefix + m_name;
474  return StatusCode::FAILURE;
475  }
476 
477  // Will be set at the first resize().
478  m_valdiff = 0;
479 
480  // Create the vector.
481  m_contptr = 0;
482  return tree->addVariable (prefix + m_name,
483  *m_proxy->GetCollectionClass()->GetTypeInfo(),
484  // cppcheck-suppress nullPointer; false positive
485  m_contptr,
486  m_docstring);
487 }
488 
489 
496 {
497  // Resize the vector.
498  TVirtualCollectionProxy::TPushPop pushcont (m_proxy, m_contptr);
499  size_t oldsz = m_proxy->Size();
500  m_proxy->Allocate (sz, false);
501  if (sz == 0) {
502  *m_addr = 0;
503  return;
504  }
505 
506  char* begin = static_cast<char*> (m_proxy->At(0));
507 
508  // Calculate the element offset, if needed.
509  // We do this by finding the difference between the first two
510  // elements, so we can only do this if there are at least two elements
511  // in the vector. But if there are less than two elements, then
512  // the offset doesn't matter anyway.
513  if (m_valdiff == 0 && sz >= 2)
514  m_valdiff = static_cast<char*> (m_proxy->At(1)) - begin;
515 
516  // Set the pointer properly.
517  *m_addr = begin + pos * m_valdiff;
518 
519  // Fill in default value if requested.
520  if (m_default && sz > oldsz) {
521  if (sz == 1) {
522  std::memcpy (begin, m_default, m_defsize);
523  }
524  else {
525  assert (m_defsize <= m_valdiff);
526  for (char* p = begin + oldsz * m_valdiff;
527  p < begin + sz * m_valdiff;
528  p += m_valdiff)
529  {
530  std::memcpy (p, m_default, m_defsize);
531  }
532  }
533  }
534 }
535 
536 
543 {
544  delete [] m_default;
545 }
546 
547 
552 {
553  for (Var& v : *this) {
554  v.free();
555  }
556 }
557 
558 
564 void VectorFillerToolBase::Vars::resize_all (size_t sz, size_t pos /*= 0*/)
565 {
566  for (Var& v : *this) {
567  v.resize (sz, pos);
568  }
569 }
570 
571 
572 } // namespace D3PD
D3PD::IAddVariable
Common interface for adding a variable to a tuple.
Definition: IAddVariable.h:70
D3PD::VectorFillerToolBase::doBook
StatusCode doBook()
Declare tuple variables.
Definition: VectorFillerToolBase.cxx:112
fitman.sz
sz
Definition: fitman.py:527
max
#define max(a, b)
Definition: cfImp.cxx:41
find
std::string find(const std::string &s)
return a remapped string
Definition: hcg.cxx:135
D3PD::VectorFillerToolBase::addVariable
virtual StatusCode addVariable(const std::string &name, const std::type_info &ti, void *&ptr, const std::string &docstring="", const void *defval=0)
Add a variable to the tuple.
Definition: VectorFillerToolBase.cxx:306
D3PD::VectorFillerToolBase::m_nrowName
std::string m_nrowName
Property: Name of the variable for the count of rows.
Definition: VectorFillerToolBase.h:193
AthCommonDataStore< AthCommonMsg< AlgTool > >::declareProperty
Gaudi::Details::PropertyBase & declareProperty(Gaudi::Property< T > &t)
Definition: AthCommonDataStore.h:145
D3PD::VectorFillerToolBase::Var::free
void free()
Free allocated storage.
Definition: VectorFillerToolBase.cxx:542
initialize
void initialize()
Definition: run_EoverP.cxx:894
D3PD::VectorFillerToolBase::Var::m_addr
char ** m_addr
Pointer to the variable pointer.
Definition: VectorFillerToolBase.h:290
xAOD::char
char
Definition: TrigDecision_v1.cxx:38
tree
TChain * tree
Definition: tile_monitor.h:30
PlotCalibFromCool.begin
begin
Definition: PlotCalibFromCool.py:94
skel.it
it
Definition: skel.GENtoEVGEN.py:396
CaloClusterListBadChannel.cls
cls
Definition: CaloClusterListBadChannel.py:8
LArDigits2NtupleDumper.tdt
tdt
Definition: LArDigits2NtupleDumper.py:121
D3PD::VectorFillerToolBase::m_metadata
ObjectMetadata m_metadata
Metadata about the variables created by this tool.
Definition: VectorFillerToolBase.h:180
D3PD::IIteration
Abstract interface for iterating over a set of things.
Definition: IIteration.h:41
D3PD::VectorFillerToolBase::Var::init
StatusCode init(IAddVariable *tree, const std::string &prefix)
Initialize the variable.
Definition: VectorFillerToolBase.cxx:432
dbg::ptr
void * ptr(T *p)
Definition: SGImplSvc.cxx:74
D3PD::VectorFillerToolBase::doConfigure
StatusCode doConfigure(IAddVariable *tree, IIteration &it)
Configure the tool.
Definition: VectorFillerToolBase.cxx:147
D3PD::VectorFillerToolBase::Var::m_valdiff
size_t m_valdiff
Offset between collection elements.
Definition: VectorFillerToolBase.h:299
D3PD::IBlockFillerTool::EMPTY
@ EMPTY
Definition: IBlockFillerTool.h:70
D3PD::VectorFillerToolBase::m_vars
Vars m_vars
All booked variables.
Definition: VectorFillerToolBase.h:346
D3PD::VectorFillerToolBase::Var::next
void next()
Move the variable pointer to the next element.
Definition: VectorFillerToolBase.cxx:32
D3PD::VectorFillerToolBase::Var
Description for a single variable.
Definition: VectorFillerToolBase.h:228
D3PD
Block filler tool for noisy FEB information.
Definition: CaloCellDetailsFillerTool.cxx:29
D3PD::VectorFillerToolBase::maybeExtend
void maybeExtend(size_t &n, size_t &sz)
Extend vectors if needed.
Definition: VectorFillerToolBase.cxx:167
python.utils.AtlRunQueryDQUtils.p
p
Definition: AtlRunQueryDQUtils.py:210
D3PD::IBlockFillerTool::againok
static StatusCode againok(StatusCode sc)
StatusCode check helper: change AGAIN or EMPTY to SUCCESS.
lumiFormat.i
int i
Definition: lumiFormat.py:85
D3PD::VectorFillerToolBase::m_nobjName
std::string m_nobjName
Property: Name of the variable for the count of objects.
Definition: VectorFillerToolBase.h:197
beamspotman.n
n
Definition: beamspotman.py:731
EL::StatusCode
::StatusCode StatusCode
StatusCode definition for legacy code.
Definition: PhysicsAnalysis/D3PDTools/EventLoop/EventLoop/StatusCode.h:22
D3PD::VectorFillerToolBase::initialize
virtual StatusCode initialize()
Standard Gaudi initialize method.
Definition: VectorFillerToolBase.cxx:88
CaloNoise_fillDB.dt
dt
Definition: CaloNoise_fillDB.py:58
D3PD::VectorFillerToolBase::m_nobj
int * m_nobj
Variable for the object count.
Definition: VectorFillerToolBase.h:210
D3PD::VectorFillerToolBase::m_tree
IAddVariable * m_tree
The parent tree.
Definition: VectorFillerToolBase.h:204
D3PD::VectorFillerToolBase::fillOnce
StatusCode fillOnce(const void *obj, size_t objndx, size_t &n, size_t &sz, const std::vector< unsigned long > &codes_in, std::vector< unsigned long > &codes_out)
Make one loop over block filler tools.
Definition: VectorFillerToolBase.cxx:196
D3PD::VectorFillerToolBase::doFill
StatusCode doFill(IIteration &it, size_t sizeHint)
Fill objects from an IIteration.
Definition: VectorFillerToolBase.cxx:244
checkCorrelInHIST.prefix
dictionary prefix
Definition: checkCorrelInHIST.py:391
D3PD::VectorFillerToolBase::Var::resize
void resize(size_t sz, size_t pos)
Resize the vector.
Definition: VectorFillerToolBase.cxx:495
test_pyathena.parent
parent
Definition: test_pyathena.py:15
D3PD::typeinfoToName
std::string typeinfoToName(const std::type_info &ti)
Convert from a type_info to a name.
Definition: TypeNameConversions.cxx:130
CHECK
#define CHECK(...)
Evaluate an expression and check for errors.
Definition: Control/AthenaKernel/AthenaKernel/errorcheck.h:422
name
std::string name
Definition: Control/AthContainers/Root/debug.cxx:221
errorcheck.h
Helpers for checking error return status codes and reporting errors.
D3PD::ObjectMetadata::addVariable
virtual StatusCode addVariable(const std::string &name, const std::type_info &ti, void *&ptr, const std::string &docstring="", const void *defval=0)
This function can be used to save the metadata about a D3PD variable.
Definition: ObjectMetadata.cxx:109
VectorFillerToolBase.h
Common code for wrapping filled variables up into a vector.
D3PD::VectorFillerToolBase::Var::Var
Var(const std::string &name, const std::type_info &ti, void *&ptr, const std::string &dim, char *defval, size_t defsize)
Constructor.
Definition: VectorFillerToolBase.cxx:408
D3PD::VectorFillerToolBase::m_objIndex
int * m_objIndex
Variable for the object index.
Definition: VectorFillerToolBase.h:213
D3PD::VectorFillerToolBase::addDimensionedVariable
virtual StatusCode addDimensionedVariable(const std::string &name, const std::type_info &ti, void *&ptr, const std::string &dim, const std::string &docstring="", const void *defval=0)
Add a variable to the tuple.
Definition: VectorFillerToolBase.cxx:383
REPORT_MESSAGE
#define REPORT_MESSAGE(LVL)
Report a message.
Definition: Control/AthenaKernel/AthenaKernel/errorcheck.h:365
python.LumiBlobConversion.pos
pos
Definition: LumiBlobConversion.py:18
python.PyAthena.v
v
Definition: PyAthena.py:154
D3PD::VectorFillerToolBase::m_nrow
int * m_nrow
Variable for the row count.
Definition: VectorFillerToolBase.h:207
python.CaloScaleNoiseConfig.type
type
Definition: CaloScaleNoiseConfig.py:78
D3PD::IAddVariable::addVariable
StatusCode addVariable(const std::string &name, T *&ptr, const std::string &docstring="")
Add a variable to the tuple.
D3PD::VectorFillerToolBase::finalize
virtual StatusCode finalize()
Standard Gaudi finalize method.
Definition: VectorFillerToolBase.cxx:99
D3PD::VectorFillerToolBase::m_objIndexName
std::string m_objIndexName
Property: Name of the variable for the object index.
Definition: VectorFillerToolBase.h:201
D3PD::VectorFillerToolBase::m_prefix
std::string m_prefix
Property: Variable prefix for this block.
Definition: VectorFillerToolBase.h:184
AthAlgTool
Definition: AthAlgTool.h:26
D3PD::VectorFillerToolBase::m_blockFillers
ToolHandleArray< IBlockFillerTool > m_blockFillers
Property: The list of block filler tools.
Definition: VectorFillerToolBase.h:189
python.PyAthena.obj
obj
Definition: PyAthena.py:132
TypeNameConversions.h
Utility functions for converting between type names, type_info, and CLIDs.
IIteration.h
Abstract interface for iterating over a set of things.
D3PD::VectorFillerToolBase::Vars::~Vars
~Vars()
Destructor.
Definition: VectorFillerToolBase.cxx:551
D3PD::VectorFillerToolBase::VectorFillerToolBase
VectorFillerToolBase(const std::string &type, const std::string &name, const IInterface *parent)
Standard Gaudi tool constructor.
Definition: VectorFillerToolBase.cxx:56
D3PD::VectorFillerToolBase::Vars::resize_all
void resize_all(size_t sz, size_t pos=0)
Resize all vector.
Definition: VectorFillerToolBase.cxx:564
D3PD::IBlockFillerTool::AGAIN
@ AGAIN
Definition: IBlockFillerTool.h:69
D3PD::VectorFillerToolBase::Vars::next_all
void next_all()
Move all variable pointers to the next element.
Definition: VectorFillerToolBase.cxx:42