Hall-D Software  alpha
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
DTreeInterface.h
Go to the documentation of this file.
1 #ifndef DTreeInterface_h
2 #define DTreeInterface_h
3 
4 #include <map>
5 #include <typeindex>
6 #include <typeinfo>
7 #include <type_traits>
8 #include <string>
9 #include <iostream>
10 #include <sstream>
11 
12 #include <TROOT.h>
13 #include <TTree.h>
14 #include <TFile.h>
15 #include <TDirectory.h>
16 #include <TObject.h>
17 #include <TClonesArray.h>
18 #include <TVector2.h>
19 #include <TVector3.h>
20 #include <TLorentzVector.h>
21 
22 #include <JANA/JApplication.h>
23 #include <particleType.h>
24 
25 #include "DTreeInterfaceObjects.h"
26 
27 using namespace std;
28 
30 {
31  //WARNING: This class ASSUMES that the only things you are saving to the given output files are trees managed by DTreeInterface objects.
32  //Saving anything else to these files will probably not work! And would be unwise anyway ...
33 
34  //Usage: Create anywhere, as long as it will live for the life of the time you want to fill the tree.
35  //Regardless of how many threads act in that part of the code.
36  //Just delete it whenever you're done. TTree is saved and TFile is closed when all interfaces to a given file are deleted.
37  //E.g. Create in plugin/factory init(), delete in plugin/factory fini()
38  //E.g. Create in analysis action Initialize(), delete in analysis action destructor
39 
40  //ASSUME: One leaf per branch: No splitting
41  //ASSUME: Tree only stores: Fundamental type objects (not const char*!!), Fundamental type arrays, TObject's, TClonesArray's
42  //ASSUME: TObject's are of type TVector3 & TLorentzVector: Need to expand template type calls if more are used
43 
44  public:
45 
46  /**************************************************************** INITIALIZE ****************************************************************/
47 
48  //Only public way to construct a DTreeInterface //Forces allocation on the heap
49  //MUST DELETE WHEN FINISHED: OR ELSE DATA WON'T BE SAVED!!!
50  static DTreeInterface* Create_DTreeInterface(string locTreeName, string locFileName);
51 
52  //Destructor
53  ~DTreeInterface(void);
54 
55  // Is optional. If needed array size is not specified, it will be set to a default value.
56  void Set_InitialArraySize(string locArraySizeBranchName, UInt_t locInitialSize);
57 
58  bool Create_Branches(const DTreeBranchRegister& locTreeBranchRegister);
59 
60  void Set_TreeIndexBranchNames(string locTreeIndex_MajorBranchName, string locTreeIndex_MinorBranchName = "0");
61 
62  //Check/read info
63  bool Get_BranchesCreatedFlag(void) const;
64  const TList* Get_UserInfo(void) const;
65 
66  /******************************************************************* FILL *******************************************************************/
67 
68  void Fill(DTreeFillData& locTreeFillData); //not const: needs to reset arrays
69 
70  private:
71 
72  /**************************************************************** INITIALIZE ****************************************************************/
73 
74  //Constructors
75  DTreeInterface(string locTreeName, string locFileName);
76  DTreeInterface(void); //private default constructor: cannot call
77 
78  //Init
79  void GetOrCreate_FileAndTree(string locTreeName);
80 
81  /*************************************************************** MISCELLANEOUS **************************************************************/
82 
83  //For ROOT type string for fundamental data variables
84  //Defined in https://root.cern.ch/root/htmldoc/TTree.html
85  template<typename DType> struct DROOTTypeString { static const char* GetTypeString() {return "";} }; // Main template class
86 
87  /************************************************************** CREATE BRANCHES *************************************************************/
88 
89  void Create_Branch(const DTreeBranchRegister& locTreeBranchRegister, string locBranchName, map<string, size_t>& locFundamentalArraySizeMap);
90  void Create_Branch(string locBranchName, type_index locTypeIndex, size_t locArraySize, string locArraySizeName);
91 
92  //Enable this version if type inherits from TObject //void: is return type
93  template <typename DType> typename enable_if<std::is_base_of<TObject, DType>::value, void>::type
94  Create_Branch(string locBranchName, size_t locArraySize, string locArraySizeName);
95 
96  //Enable this version if type does NOT inherit from TObject //void: is return type
97  template <typename DType> typename enable_if<!std::is_base_of<TObject, DType>::value, void>::type
98  Create_Branch(string locBranchName, size_t locArraySize, string locArraySizeName);
99 
100  template <typename DType> void Create_Branch_Fundamental(string locBranchName);
101  template <typename DType> void Create_Branch_TObject(string locBranchName);
102  template <typename DType> void Create_Branch_FundamentalArray(string locBranchName, string locArraySizeString, unsigned int locInitialSize);
103  template <typename DType> void Create_Branch_ClonesArray(string locBranchName, unsigned int locSize);
104 
105  /******************************************************************* FILL *******************************************************************/
106 
107  void Change_ArraySize(string locBranchName, type_index locTypeIndex, size_t locNewArraySize);
108  template <typename DType> void Change_ArraySize(string locBranchName, int locNewArraySize);
109  void Fill(string locBranchName, type_index locTypeIndex, void* locVoidPointer, bool locIsArrayFlag, size_t locArrayIndex = 0);
110  template <typename DType> void Fill_TObject(string locBranchName, DType& locObject, bool locIsArrayFlag, size_t locArrayIndex);
111 
112  /*************************************************************** GET POINTERS ***************************************************************/
113 
114  template <typename DType> DType* Get_Pointer_Fundamental(string locBranchName) const;
115  template <typename DType> DType* Get_Pointer_TObject(string locBranchName) const;
116  TClonesArray* Get_Pointer_TClonesArray(string locBranchName);
117 
118  /******************************************** STATIC-VARIABLE-ACCESSING PRIVATE MEMBER FUNCTIONS ********************************************/
119 
120  //Some variables needs to be shared amongst threads (e.g. the array sizes for the branches)
121  //However, you cannot make them global/extern/static/static-member variables in the header file:
122  //They would be in the header file, and the header file is included in the ANALYSIS library AND in each plugin that uses it
123  //When a header file is included in a src file, it's contents are essentially copied directly into it
124  //Thus there are two instances of each static variable: one in each translation unit (library)
125  //Supposedly(?) they are linked together during runtime when loading, so there is (supposedly) no undefined behavior.
126  //However, this causes a double free (double-deletion) when these libraries are closed at the end of the program, crashing it.
127  //Thus the variables must be in a single source file that is compiled into a single library
128  //However, you (somehow?) cannot make them global/extern variables in the source file
129  //This also (somehow?) causes the double-free problem above for (at least) stl containers
130  //It works for pointers-to-stl-containers and fundamental types, but I dunno why.
131  //It's not good encapsulation anyway though.
132  //THE SOLUTION:
133  //Define the variables as static, in the source file, WITHIN A PRIVATE MEMBER FUNCTION.
134  //Thus the static variables themselves only have function scope.
135  //Access is only available via the private member function, thus access is fully controlled.
136  //They are shared amongst threads, so locks are necessary, but since they are private this class can handle it internally
137 
138  map<string, int>& Get_NumWritersByFileMap(void) const;
139  map<string, size_t>& Get_FundamentalArraySizeMap(TTree* locTree) const;
140 
141  /************************************************************** MEMBER VARIABLES ************************************************************/
142 
143  TTree* dTree;
144  string dFileName;
147 
148  /******************************************************** BRANCH MEMORY AND TYPE MAPPING ****************************************************/
149 
150  //These objects are kept here because they must be kept somewhere:
151  //branches addresses of pointers, so pointers must reside somewhere permanent
152  //However, for fundamental objects/arrays: memory stored in the branches themselves: don't need to hold onto them
153  size_t dMaxArraySize = 1000;
154  Long64_t dAutoFlush = -5000000; //if 200 trees at once, and want them to take at most 1GB of RAM before flush, then flush every 5MB: -5000000 //default every 30MB
155  map<string, TClonesArray*> dMemoryMap_ClonesArray;
156  map<string, TObject*> dMemoryMap_TObject;
157 };
158 
159 /******************************************************************** GET POINTERS ********************************************************************/
160 
161 //GET POINTERS
162 template <typename DType> inline DType* DTreeInterface::Get_Pointer_Fundamental(string locBranchName) const
163 {
164  TBranch* locBranch = dTree->GetBranch(locBranchName.c_str());
165  return ((locBranch != NULL) ? (DType*)locBranch->GetAddress() : NULL);
166 }
167 
168 template <typename DType> inline DType* DTreeInterface::Get_Pointer_TObject(string locBranchName) const
169 {
170  TBranch* locBranch = dTree->GetBranch(locBranchName.c_str());
171  return ((locBranch != NULL) ? *(DType**)locBranch->GetAddress() : NULL);
172 }
173 
174 inline TClonesArray* DTreeInterface::Get_Pointer_TClonesArray(string locBranchName)
175 {
176  TBranch* locBranch = dTree->GetBranch(locBranchName.c_str());
177  return ((locBranch != NULL) ? *(TClonesArray**)locBranch->GetAddress() : NULL);
178 }
179 
180 /******************************************************************* CREATE BRANCHES ******************************************************************/
181 
182 template <typename DType> inline typename enable_if<std::is_base_of<TObject, DType>::value, void>::type
183 DTreeInterface::Create_Branch(string locBranchName, size_t locArraySize, string locArraySizeName)
184 {
185  if(locArraySize == 0)
186  Create_Branch_TObject<DType>(locBranchName);
187  else
188  Create_Branch_ClonesArray<DType>(locBranchName, locArraySize);
189 }
190 
191 template <typename DType> inline typename enable_if<!std::is_base_of<TObject, DType>::value, void>::type
192 DTreeInterface::Create_Branch(string locBranchName, size_t locArraySize, string locArraySizeName)
193 {
194  if(locArraySize == 0)
195  Create_Branch_Fundamental<DType>(locBranchName);
196  else
197  Create_Branch_FundamentalArray<DType>(locBranchName, locArraySizeName, locArraySize);
198 }
199 
200 template <typename DType> inline void DTreeInterface::Create_Branch_Fundamental(string locBranchName)
201 {
202  if(dTree->GetBranch(locBranchName.c_str()) != NULL)
203  return; //already created
204 
205  string locTypeString = DROOTTypeString<DType>::GetTypeString();
206  string locTypeName = locBranchName + string("/") + locTypeString;
207  dTree->Branch(locBranchName.c_str(), new DType(), locTypeName.c_str());
208 }
209 
210 template <typename DType> inline void DTreeInterface::Create_Branch_TObject(string locBranchName)
211 {
212  if(dTree->GetBranch(locBranchName.c_str()) != NULL)
213  return; //already created
214 
215  dMemoryMap_TObject[locBranchName] = (TObject*)(new DType());
216  dTree->Branch(locBranchName.c_str(), (DType**)&(dMemoryMap_TObject[locBranchName]), 32000, 0); //0: don't split
217 }
218 
219 template <typename DType> inline void DTreeInterface::Create_Branch_FundamentalArray(string locBranchName, string locArraySizeString, unsigned int locInitialSize)
220 {
221  if(dTree->GetBranch(locBranchName.c_str()) != NULL)
222  return; //already created
223 
224  string locTypeString = DROOTTypeString<DType>::GetTypeString();
225  string locArrayName = locBranchName + string("[") + locArraySizeString + string("]/") + locTypeString;
226  dTree->Branch(locBranchName.c_str(), new DType[locInitialSize], locArrayName.c_str());
227 }
228 
229 template <typename DType> inline void DTreeInterface::Create_Branch_ClonesArray(string locBranchName, unsigned int locInitialSize)
230 {
231  if(dTree->GetBranch(locBranchName.c_str()) != NULL)
232  return; //already created
233 
234  dMemoryMap_ClonesArray[locBranchName] = new TClonesArray(DType::Class()->GetName(), locInitialSize);
235  dTree->Branch(locBranchName.c_str(), &(dMemoryMap_ClonesArray[locBranchName]), 32000, 0); //0: don't split
236 }
237 
238 /************************************************************** TEMPLATE SPECIALIZATIONS **************************************************************/
239 
240 //template<> struct DTreeInterface::DROOTTypeString<const char*> { static const char* GetTypeString() {return "C";} };
241 template<> struct DTreeInterface::DROOTTypeString<Char_t> { static const char* GetTypeString() {return "B";} };
242 template<> struct DTreeInterface::DROOTTypeString<UChar_t> { static const char* GetTypeString() {return "b";} };
243 template<> struct DTreeInterface::DROOTTypeString<Short_t> { static const char* GetTypeString() {return "S";} };
244 template<> struct DTreeInterface::DROOTTypeString<UShort_t> { static const char* GetTypeString() {return "s";} };
245 template<> struct DTreeInterface::DROOTTypeString<Int_t> { static const char* GetTypeString() {return "I";} };
246 template<> struct DTreeInterface::DROOTTypeString<UInt_t> { static const char* GetTypeString() {return "i";} };
247 template<> struct DTreeInterface::DROOTTypeString<Float_t> { static const char* GetTypeString() {return "F";} };
248 template<> struct DTreeInterface::DROOTTypeString<Double_t> { static const char* GetTypeString() {return "D";} };
249 template<> struct DTreeInterface::DROOTTypeString<Long64_t> { static const char* GetTypeString() {return "L";} };
250 template<> struct DTreeInterface::DROOTTypeString<ULong64_t> { static const char* GetTypeString() {return "l";} };
251 template<> struct DTreeInterface::DROOTTypeString<Bool_t> { static const char* GetTypeString() {return "O";} };
252 
253 /******************************************************************* MISCELLANEOUS ********************************************************************/
254 
255 inline void DTreeInterface::Set_TreeIndexBranchNames(string locTreeIndex_MajorBranchName, string locTreeIndex_MinorBranchName)
256 {
257  dTreeIndex_MajorBranchName = locTreeIndex_MajorBranchName;
258  dTreeIndex_MinorBranchName = locTreeIndex_MinorBranchName;
259 }
260 
261 //INCREASE ARRAY SIZE
262 template <typename DType> inline void DTreeInterface::Change_ArraySize(string locBranchName, int locNewArraySize)
263 {
264  //create a new, larger array if the current one is too small
265  //DOES NOT copy the old results! In other words, only call BETWEEN entries, not DURING an entry
266  DType* locOldBranchAddress = Get_Pointer_Fundamental<DType>(locBranchName);
267  dTree->SetBranchAddress(locBranchName.c_str(), new DType[locNewArraySize]);
268  delete[] locOldBranchAddress;
269 }
270 
271 template <typename DType> inline void DTreeInterface::Fill_TObject(string locBranchName, DType& locObject, bool locIsArrayFlag, size_t locArrayIndex)
272 {
273  if(locIsArrayFlag)
274  {
275  TClonesArray* locClonesArray = Get_Pointer_TClonesArray(locBranchName);
276  *(DType*)locClonesArray->ConstructedAt(locArrayIndex) = locObject;
277  }
278  else
279  *Get_Pointer_TObject<DType>(locBranchName) = locObject;
280 }
281 
282 #endif //DTreeInterface_h
DType * Get_Pointer_TObject(string locBranchName) const
map< string, TClonesArray * > dMemoryMap_ClonesArray
void Change_ArraySize(string locBranchName, type_index locTypeIndex, size_t locNewArraySize)
DType * Get_Pointer_Fundamental(string locBranchName) const
char string[256]
axes Fill(100, 100)
void Create_Branch(const DTreeBranchRegister &locTreeBranchRegister, string locBranchName, map< string, size_t > &locFundamentalArraySizeMap)
string dTreeIndex_MinorBranchName
void Fill_TObject(string locBranchName, DType &locObject, bool locIsArrayFlag, size_t locArrayIndex)
void Create_Branch_Fundamental(string locBranchName)
void Set_TreeIndexBranchNames(string locTreeIndex_MajorBranchName, string locTreeIndex_MinorBranchName="0")
void Create_Branch_ClonesArray(string locBranchName, unsigned int locSize)
void Create_Branch_FundamentalArray(string locBranchName, string locArraySizeString, unsigned int locInitialSize)
map< string, TObject * > dMemoryMap_TObject
static const char * GetTypeString()
TClonesArray * Get_Pointer_TClonesArray(string locBranchName)
string dTreeIndex_MajorBranchName
void Create_Branch_TObject(string locBranchName)