Jpp  19.0.0
the software that should make you happy
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
JTreeBranchAddresses.hh
Go to the documentation of this file.
1 #ifndef __JTREE_BRANCH_ADDRESSES_H__
2 #define __JTREE_BRANCH_ADDRESSES_H__
3 
4 #include <iostream>
5 
6 #include "JLang/JException.hh"
7 #include "JROOT/JRootAddress.hh"
8 #include "JROOT/JRootClass.hh"
9 #include "Jeep/JPrint.hh"
10 #include "TDataMember.h"
11 #include "TTree.h"
12 
13 namespace JROOT {
14 
15 /* to_vector converts a list of Root TObjects into a list
16  * of those objects names
17  */
19 {
21 
22  TIter next(col);
23  TObject* object{nullptr};
24  while ((object = next()) != nullptr) {
25  names.emplace_back(object->GetName());
26  }
27  return names;
28 }
29 
30 using JLANG::JException;
31 
32 /**
33  * Class responsible to setup TTree branch addresses
34  * for reading objects of type T.
35  *
36  */
37 template <typename T>
39 
40  public:
41  /*
42  * Set the branch(es) address(es) to read objects of type T.
43  *
44  * If the tree contains a single branch we assume that branch contains
45  * objects of type T.
46  *
47  * If the tree contains several branches we check whether those branches
48  * correspond to the full list of T data members. If that's the case
49  * the tree is a flat (one branch per data member) representation of T
50  * and setup the branches accordingly. If not, we throw an exception.
51  */
52  void setBranchAddress(TTree& tree)
53  {
54  TObjArray* branches = tree.GetListOfBranches();
55  // single branch
56  if (branches->GetEntries() == 1) {
57  tree.SetBranchAddress(branches->First()->GetName(), &this->address);
58  return;
59  }
60 
61  // if more than one branch, check those are the data members of T
62  TClass* t_class = TClass::GetClass<T>();
63  if (t_class == nullptr) {
64  THROW(JException, "Could not get class " << typeid(T).name());
65  }
66 
67  auto branch_names = to_vector(tree.GetListOfBranches());
68  auto all_member_names = to_vector(t_class->GetListOfRealData());
69 
70  std::vector<std::string> member_names;
71 
72  // remove TObject specific members
73  std::copy_if(all_member_names.begin(), all_member_names.end(), std::back_inserter(member_names),
74  [](const std::string& member_name)
75  { return !JRootClass::is_tobject_member(member_name.c_str()); });
76 
77  std::sort(branch_names.begin(), branch_names.end());
78  std::sort(member_names.begin(), member_names.end());
79 
80  // all members must have a corresponding branch
81  // (but more branches are allowed, we just don't handle them here)
82  if (std::includes(branch_names.begin(), branch_names.end(), member_names.begin(),
83  member_names.end())) {
84 
85  this->address = new T;
86 
87  auto* base = reinterpret_cast<uint8_t*>(this->address);
88 
89  for (const auto& member_name : member_names) {
90  auto* member = static_cast<TDataMember*>(t_class->GetDataMember(member_name.c_str()));
91  tree.SetBranchAddress(member_name.c_str(),
92  reinterpret_cast<void*>(base + member->GetOffset()));
93  }
94  return;
95  }
96 
97  // if we cannot configure the tree, try to give some relevant information
98  // to the user who will have to deal with the exception...
99  THROW(JException, "Members of type " << typeid(T).name() << "\n"
100  << JEEPZ() << member_names << "\nBranches in tree\n"
101  << JEEPZ() << branch_names);
102  }
103 };
104 } // namespace JROOT
105 
106 #endif
General exception.
Definition: JException.hh:24
Exceptions.
#define THROW(JException_t, A)
Marco for throwing exception with std::ostream compatible message.
Definition: JException.hh:712
Definition: JRoot.hh:19
Class responsible to setup TTree branch addresses for reading objects of type T.
I/O formatting auxiliaries.
Auxiliary classd for address handling within TTree or TChain.
Definition: JRootAddress.hh:19
do set_variable OUTPUT_DIRECTORY $WORKDIR T
Auxiliary data structure for streaming of STL containers.
Definition: JPrint.hh:65
then usage $script< detector file >< PMTparametersfile > nThe list of optional parameters includes
then fatal The output file must have the wildcard in the name
Definition: JCanberra.sh:31
std::vector< std::string > to_vector(TCollection *col)
static bool is_tobject_member(const char *name)
Check if name is one of TObject own data members (fBits or fUniqueID, for Root &lt;= 6...
Definition: JRootClass.hh:138