FairRoot
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
RootOutFileManager.h
Go to the documentation of this file.
1 /*
2  * File: RootOutFileManager.h
3  * Author: winckler
4  *
5  * Created on October 7, 2014, 9:40 PM
6  */
7 
8 #ifndef ROOTOUTFILEMANAGER_H
9 #define ROOTOUTFILEMANAGER_H
10 
11 // std
12 #include <iostream>
13 #include <string>
14 #include <vector>
15 
16 // ROOT
17 #include <Rtypes.h>
18 #include <TClonesArray.h>
19 #include <TFile.h>
20 #include <TFolder.h>
21 #include <TKey.h>
22 #include <TList.h>
23 #include <TObjString.h>
24 #include <TTree.h>
25 
26 // FairRoot
27 #include "FairLogger.h"
28 
29 #include <FairMQMessage.h>
30 #include <options/FairMQProgOptions.h>
31 
32 template<typename DataType>
34 {
35  public:
37  : fFilename()
38  , fTreeName()
39  , fBranchName()
40  , fClassName()
41  , fFileOption()
42  , fUseClonesArray(false)
43  , fFlowMode(true)
44  , fWrite(false)
45  , fOutFile(nullptr)
46  , fTree(nullptr)
47  , fOutput(nullptr)
48  , fOutputData(nullptr)
49  , fFolder(nullptr)
50  {}
51 
52  RootOutFileManager(const std::string& filename,
53  const std::string& treeName,
54  const std::string& branchName,
55  const std::string& className,
56  const std::string& fileOption)
57  : fFilename(filename)
58  , fTreeName(treeName)
59  , fBranchName(branchName)
60  , fClassName(className)
61  , fFileOption(fileOption)
62  , fUseClonesArray(false)
63  , fFlowMode(true)
64  , fWrite(false)
65  , fOutFile(nullptr)
66  , fTree(nullptr)
67  , fOutput(nullptr)
68  , fOutputData(nullptr)
69  , fFolder(nullptr)
70  {}
71 
72  RootOutFileManager(const RootOutFileManager&) = delete;
74 
76  {
77  if (fFlowMode && fWrite) {
78  fTree->Write("", TObject::kOverwrite);
79  }
80 
81  delete fTree;
82 
83  if (fOutFile) {
84  if (fOutFile->IsOpen()) {
85  fOutFile->Close();
86  }
87  delete fOutFile;
88  }
89 
90  delete fFolder;
91  }
92 
93  void SetFileProperties(const std::string& filename,
94  const std::string& treeName,
95  const std::string& branchName,
96  const std::string& className = "",
97  const std::string& fileOption = "RECREATE",
98  bool useClonesArray = false,
99  bool flowMode = true)
100  {
101  fFilename = filename;
102  fTreeName = treeName;
103  fBranchName = branchName;
104  fClassName = className;
105  fFileOption = fileOption;
106  fUseClonesArray = useClonesArray;
107  fFlowMode = flowMode;
108  if (!std::is_base_of<TObject, DataType>::value && fUseClonesArray) {
109  fUseClonesArray = false;
110  LOG(warn) << "Deactivate TClonesArray method: the data class must inherit from TObject.";
111  }
112  }
113 
114  void SetFileProperties(const FairMQProgOptions& config)
115  {
116  fFilename = config.GetValue<std::string>("output-file-name");
117  fTreeName = config.GetValue<std::string>("output-file-tree");
118  fBranchName = config.GetValue<std::string>("output-file-branch");
119  fClassName = config.GetValue<std::string>("hit-classname");
120  fFileOption = config.GetValue<std::string>("output-file-option");
121  fUseClonesArray = config.GetValue<bool>("use-clones-array");
122  fFlowMode = config.GetValue<bool>("flow-mode");
123 
124  if (!std::is_base_of<TObject, DataType>::value && fUseClonesArray) {
125  fUseClonesArray = false;
126  LOG(warn) << "Deactivate TClonesArray method: the data class must inherit from TObject.";
127  }
128  }
129 
130  void AddToFile(std::vector<DataType>& inputData)
131  {
132  if (fUseClonesArray) {
133  fOutput->Delete();
134 
135  for (unsigned int i = 0; i < inputData.size(); ++i) {
136  new ((*fOutput)[i]) DataType(inputData.at(i));
137  }
138 
139  if (fOutput->IsEmpty()) {
140  LOG(debug) << "RootOutFileManager::AddToFile(vector<DataType>&): No Output array!";
141  }
142 
143  fTree->Fill();
144  } else {
145  for (unsigned int i = 0; i < inputData.size(); ++i) {
146  fOutputData = &inputData.at(i);
147  fTree->Fill();
148  }
149  }
150  if (!fFlowMode) {
151  fTree->Write("", TObject::kOverwrite);
152  }
153  }
154 
155  void AddToFile(DataType* objArr, long size)
156  {
157  // todo : check if fine when update option
158  if (fUseClonesArray) {
159  fOutput->Delete();
160 
161  for (unsigned int i = 0; i < size; ++i) {
162  new ((*fOutput)[i]) DataType(objArr[i]);
163  }
164 
165  if (fOutput->IsEmpty()) {
166  LOG(debug) << "RootOutFileManager::AddToFile(vector<DataType>&): No Output array!";
167  }
168 
169  fTree->Fill();
170  if (!fFlowMode) {
171  fTree->Write("", TObject::kOverwrite);
172  }
173  } else {
174  std::vector<DataType> dataVector(objArr, objArr + size);
175  AddToFile(dataVector);
176  }
177  }
178 
179  void AddToFile(TClonesArray* inputData)
180  {
181  if (fUseClonesArray) {
182  fOutput = inputData;
183  fTree->SetBranchAddress(fBranchName.c_str(), &fOutput);
184 
185  if (fOutput->IsEmpty()) {
186  LOG(debug) << "RootOutFileManager::AddToFile(TClonesArray*): No Output array!";
187  }
188  fTree->Fill();
189  if (!fFlowMode) {
190  fTree->Write("", TObject::kOverwrite);
191  }
192  } else {
193  LOG(debug) << "RootOutFileManager::AddToFile(TClonesArray*): TClonesArray not set as output container";
194  }
195  }
196 
197  void AddToFile(FairMQMessage* msg)
198  {
199  int inputSize = msg->GetSize();
200  int numInput = 0;
201  if (inputSize > 0) {
202  numInput = inputSize / sizeof(DataType);
203  }
204  fOutputData = static_cast<DataType*>(msg->GetData());
205  AddToFile(fOutputData, numInput);
206  }
207 
208  void AddToFile(std::unique_ptr<TClonesArray>& input) { AddToFile(input.get()); }
209 
211  {
212  fWrite = true;
213  fOutFile = TFile::Open(fFilename.c_str(), fFileOption.c_str());
214 
215  bool updateTree = false;
216 
217  // if given option is update attempt to get tree from file
218  if (fFileOption == "UPDATE") {
219  fTree = static_cast<TTree*>(fOutFile->Get(fTreeName.c_str()));
220  if (fTree) {
221  updateTree = true;
222  LOG(info) << "Update tree";
223  } else {
224  updateTree = false;
225  LOG(info) << "Create new tree";
226  }
227  }
228 
229  // if tree not found or option is not UPDATE, create a new tree
230  if (!updateTree) {
231  fTree = new TTree(fTreeName.c_str(), "Test output");
232  }
233 
234  // direct storage or TClonesArray
235  if (fUseClonesArray) {
236  fOutput = new TClonesArray(fClassName.c_str());
237  if (updateTree) {
238  fTree->SetBranchAddress(fBranchName.c_str(), &fOutput);
239  } else {
240  fTree->Branch(fBranchName.c_str(), "TClonesArray", &fOutput);
241  }
242  } else {
243  if (updateTree) {
244  fTree->SetBranchAddress(fBranchName.c_str(), &fOutputData);
245  } else {
246  fTree->Branch(fBranchName.c_str(), fClassName.c_str(), &fOutputData);
247  }
248  }
249 
250  fFolder = new TFolder("cbmroot", "/cbmroot");
251  TList* branchNameList = new TList();
252  branchNameList->AddLast(new TObjString(fBranchName.c_str()));
253  branchNameList->Write("BranchList", TObject::kSingleKey);
254 
255  branchNameList->Delete();
256  delete branchNameList;
257  }
258  void InitTCA(const std::string& classname);
259 
260  std::vector<std::vector<DataType>> GetAllObj(const std::string& filename,
261  const std::string& treename,
262  const std::string& branchname)
263  {
264  fWrite = false;
265 
266  TFile* file = TFile::Open(filename.c_str(), "READ");
267 
268  std::vector<std::vector<DataType>> allObj;
269  std::vector<DataType> tempObj;
270 
271  if (file) {
272  fTree = static_cast<TTree*>(file->Get(fTreeName.c_str()));
273  } else {
274  LOG(error) << "Could not open file" << fTreeName.c_str();
275  }
276 
277  if (fTree) {
278  if (fUseClonesArray) {
279  fOutput = new TClonesArray(fClassName.c_str());
280  fTree->SetBranchAddress(fBranchName.c_str(), &fOutput);
281 
282  for (Long64_t i = 0; i < fTree->GetEntries(); i++) {
283  tempObj.clear();
284  fTree->GetEntry(i);
285  for (Int_t iobj = 0; iobj < fOutput->GetEntriesFast(); ++iobj) {
286  DataType* data = reinterpret_cast<DataType*>(fOutput->At(iobj));
287  if (!data) {
288  continue;
289  }
290  tempObj.push_back(*data);
291  }
292  allObj.push_back(tempObj);
293  }
294  } else {
295  fTree->SetBranchAddress(branchname.c_str(), &fOutputData);
296  for (Long64_t i = 0; i < fTree->GetEntries(); i++) {
297  fTree->GetEntry(i);
298  DataType data = *fOutputData;
299  tempObj.push_back(data);
300  }
301  allObj.push_back(tempObj);
302  }
303  } else {
304  LOG(error) << "Could not find tree " << treename.c_str();
305  }
306 
307  if (file) {
308  file->Close();
309  }
310  return allObj;
311  }
312 
313  template<typename... Args>
314  void Serialize(Args&&... args)
315  {
316  AddToFile(std::forward<Args>(args)...);
317  }
318 
319  protected:
320  virtual void Init()
321  {
322  fWrite = true;
323  fOutFile = TFile::Open(fFilename.c_str(), fFileOption.c_str());
324 
325  bool updateTree = false;
326 
327  // if given option is update attempt to get tree from file
328  if (fFileOption == "UPDATE") {
329  fTree = static_cast<TTree*>(fOutFile->Get(fTreeName.c_str()));
330  if (fTree) {
331  updateTree = true;
332  LOG(info) << "Update tree";
333  } else {
334  updateTree = false;
335  LOG(info) << "Create new tree";
336  }
337  }
338 
339  // if tree not found or option is not UPDATE, create a new tree
340  if (!updateTree) {
341  fTree = new TTree(fTreeName.c_str(), "Test output");
342  }
343 
344  // direct storage or TClonesArray
345  if (fUseClonesArray) {
346  fOutput = new TClonesArray(fClassName.c_str());
347  if (updateTree) {
348  fTree->SetBranchAddress(fBranchName.c_str(), &fOutput);
349  } else {
350  fTree->Branch(fBranchName.c_str(), "TClonesArray", &fOutput);
351  }
352  } else {
353  if (updateTree) {
354  fTree->SetBranchAddress(fBranchName.c_str(), &fOutputData);
355  } else {
356  fTree->Branch(fBranchName.c_str(), fClassName.c_str(), &fOutputData);
357  }
358  }
359  }
360 
361  std::string fFilename;
362  std::string fTreeName;
363  std::string fBranchName;
364  std::string fClassName;
365  std::string fFileOption;
367  bool fFlowMode;
368  bool fWrite;
369 
370  TFile* fOutFile;
371  TTree* fTree;
372  TClonesArray* fOutput;
373  DataType* fOutputData;
374  TFolder* fFolder;
375 };
376 
377 #endif /* ROOTOUTFILEMANAGER_H */
void InitTCA(const std::string &classname)
void AddToFile(FairMQMessage *msg)
RootOutFileManager(const std::string &filename, const std::string &treeName, const std::string &branchName, const std::string &className, const std::string &fileOption)
TClonesArray * fOutput
void AddToFile(std::unique_ptr< TClonesArray > &input)
RootOutFileManager operator=(const RootOutFileManager &)=delete
void SetFileProperties(const FairMQProgOptions &config)
void AddToFile(std::vector< DataType > &inputData)
void Serialize(Args &&...args)
void SetFileProperties(const std::string &filename, const std::string &treeName, const std::string &branchName, const std::string &className="", const std::string &fileOption="RECREATE", bool useClonesArray=false, bool flowMode=true)
void AddToFile(DataType *objArr, long size)
std::vector< std::vector< DataType > > GetAllObj(const std::string &filename, const std::string &treename, const std::string &branchname)
void AddToFile(TClonesArray *inputData)