Diana Software
QRootFileWriterBase.cc
Go to the documentation of this file.
1 #include "QRootFileWriterBase.hh"
2 #include <iostream>
3 #include <sstream>
4 #include <TFile.h>
5 #include <unistd.h>
6 #include "QEvent.hh"
7 #include "QTree.hh"
8 #include "QAliases.hh"
9 #include "QGlobalRWFactory.hh"
10 #include "QEventInspector.hh"
11 #include "QString.hh"
12 #include "QDianaR.hh"
13 #include "QOptions.hh"
14 #include "QBool.hh"
15 #include "TKey.h"
16 
17 #include <sys/stat.h>
18 
19 using namespace Diana;
20 
21 //_____________________________________________________________________________
22 QRootFileWriterBase::QRootFileWriterBase() : QFileWriter(".root") {
23  fRootOutput = 0;
24  fTree = 0;
25 }
26 //_____________________________________________________________________________
27 void QRootFileWriterBase::Open(const std::string &filename,
28  const QEventInspector &evi) {
29  if(filename == fRWCommon->fReaderCurrentFileName)
30  Panic("Output filename is equal to input filename");
31 
32 
33  fReaderWriterFiles[fRWCommon->fReaderCurrentFileName] = filename;
34  // get configuration
35  std::string treeDescription = GetString("Description", "Diana tree",false);
36 
37  fRootOutput = new TFile(filename.c_str(),"RECREATE");
38  if(!fRootOutput || fRootOutput->IsZombie())
39  Panic("cannot open file: %s",filename.c_str());
40 
41  // set the file permissions
42  int FilePermissions = strtol(GetString("FilePermissions","0644",false).c_str(),NULL,8);
43  chmod(filename.c_str(),FilePermissions);
44 
45  // convert address to strine
47  fTree = new QTree(treeDescription.c_str());
48 
49  QTreeInfo& treeInfo = fTree->GetTreeInfo();
50  treeInfo.fSoftwareRevision =
51  QOptions::GetInstance().GetParameter("General.DIANA_SWREVISION").
52  GetString();
53  treeInfo.fVersionTag =
54  QOptions::GetInstance().GetParameter("General.DIANA_VERSIONTAG").GetString();
55 
56  const QVdt::QVdt_vector& vec =
57  QOptions::GetInstance().GetParameter("General.DIANA_EXTSWREVISION").
58  GetVector();
59  for(size_t s = 0; s < vec.size(); s++) {
60  const QVdt& p = vec[s];
61  treeInfo.fExtSWVersion[p.GetName()]=p.GetString();
62  }
63 
64  QAliases aliases = evi.GetAliases();
65  std::string diana_install = "";
66  try {
67  diana_install = QOptions::GetInstance().GetString("CFGVar.DIANA_INSTALL");
68  diana_install += "/";
69  } catch(...) {};
70  std::string AliasFileName =
71  GetString("AliasFileName",diana_install+"cfg/aliases.txt");
72  std::string CustomAliasFileName = GetString("CustomAliasFileName","",false);
73  if(AliasFileName != "") {
74  Debug("Adding aliases from %s",AliasFileName.c_str());
75  QError err = aliases.FillFromFile(AliasFileName);
76  if(err != QERR_SUCCESS) {
77  std::stringstream str;
78  str<<err;
79  Error("%s",str.str().c_str());
80  }
81  }
82  if(CustomAliasFileName != "") {
83  Debug("Adding aliases from %s",CustomAliasFileName.c_str());
84  QError err = aliases.FillFromFile(CustomAliasFileName);
85  if(err != QERR_SUCCESS) {
86  std::stringstream str;
87  str<<err;
88  Error("%s",str.str().c_str());
89  }
90  }
91 
92  std::vector<QEventLabel> evDataLabels = evi.GetWriteLabels();
93  std::vector<QEventLabel>::const_iterator evLabelIter = evDataLabels.begin();
94  bool inclusive = GetBool("InclusiveMode",true,false);
95  while(evLabelIter != evDataLabels.end()) {
96  QEventLabel label = *evLabelIter;
97  QObject** peventData = evi.Get(label.owner.c_str(),label.name.c_str());
98  QObject* eventData = (*peventData);
99 
100  bool add = !fAppendToInput || eventData->IsJustAdded();
101  if(GetBool(label.GetStringLabel(),inclusive,false) && add) {
102  std::string newOwner = GetString(label.GetStringLabel() + ":NewOwner","",
103  false);
104  if(newOwner != "") {
105  QEventLabel newLabel = label;
106  newLabel.owner = newOwner;
107  Warn("Changed owner of %s into %s, this is a dangerous action",
108  label.GetStringLabel().c_str(),newLabel.GetStringLabel().c_str());
109  label = newLabel;
110  }
111  std::string labelstr = label.GetStringLabel();
112  std::string brnamestr = labelstr + ".";
113  Debug("Adding branch %s of type %s",
114  brnamestr.c_str(),eventData->GetName());
115  fTree->Branch(brnamestr.c_str(),eventData->GetName(),peventData);
116 
117  std::map<std::string, std::string> aliasMap = aliases.Find(label);
118  std::map<std::string, std::string>::const_iterator iter =
119  aliasMap.begin();
120 
121 
122  while(iter != aliasMap.end()) {
123  std::string path;
124  if(iter->second =="") {
125  path = labelstr;
126  } else {
127  path = labelstr+std::string(".")+iter->second;
128 
129  }
130  const char* al = iter->first.c_str();
131  const char* ap = path.c_str();
132  Debug("Adding alias %s for %s",al,ap);
133  fTree->SetAlias(al,ap);
134  iter++;
135  }
136  }
137 
138  evLabelIter++;
139  }
140  QError err;
141  fGlobalWriter =
143 }
144 //_____________________________________________________________________________
146  if(fSkipGenerated && evi.GetEvent().Get<QBool>("Reader","GeneratedEvent"))
147  return;
148  fTree->Fill();
149  if(fGlobalWriter)
150  fGlobalWriter->Set(Form("%s@FlushCache",GetName().c_str()),
152 }
153 //_____________________________________________________________________________
155  if(fGlobalWriter)
156  fGlobalWriter->Set(Form("%s@FlushCache",GetName().c_str()),
158  if(!fAppendToInput) {
160  return;
161  }
162 
163  Close();
164 
165  AppendToInput();
166 
167  // remove files
168  std::map<std::string,std::string>::iterator iter =
169  fReaderWriterFiles.begin();
170  while(iter != fReaderWriterFiles.end()) {
171  remove(iter->second.c_str());
172  iter++;
173  }
174  RemoveFilesList();
175 }
177 
178  // check that number of entries matches
179  std::map<std::string,std::string>::const_iterator iter =
180  fReaderWriterFiles.begin();
181  bool match = true;
182  std::string input = "", output = "";
183  Long64_t inputEntries = 0, outputEntries = 0;
184  while(iter != fReaderWriterFiles.end() && match) {
185  input = iter->first;
186  output = iter->second;
187  Debug("Reader file \"%s\"; writer file \"%s\"",input.c_str(),
188  output.c_str());
189 
190  TFile* ifile = new TFile(input.c_str());
191  if(!ifile || ifile->IsZombie() || access(input.c_str(),W_OK)) {
192  Error("Input file %s is not writable! Merge with input failed. Input "
193  "files not touched. Output saved on specified files.",
194  input.c_str());
195  SetRunAgain(0);
196  WriteFilesList();
197  return;
198  }
199  QTree* itree = (QTree*)ifile->Get("qtree");
200  inputEntries = itree->GetEntries();
201  TFile* ofile = new TFile(output.c_str());
202  QTree* otree = (QTree*)ofile->Get("qtree");
203  outputEntries = otree->GetEntries();
204  if(inputEntries > 0 && inputEntries == outputEntries) match = true;
205  else match = false;
206  iter++;
207  }
208  iter = fReaderWriterFiles.begin();
209  if(!match) {
210  Error("Input file %s has %llu entries while output file %s has %llu "
211  "entries: merge with input failed. Input files not touched. Output"
212  " saved on specified files.",input.c_str(),inputEntries,
213  output.c_str(),outputEntries);
214  SetRunAgain(0);
215  WriteFilesList();
216  return;
217  }
218  else {
219  while(iter != fReaderWriterFiles.end()){
220  // merge on each file
221  input = iter->first;
222  output = iter->second;
223  Info("Merging %s into %s",output.c_str(),input.c_str());
224  AppendFileToFile(output.c_str(),input.c_str());
225  iter++;
226  }
227  }
228 }
229 //_____________________________________________________________________________
231  if(fRootOutput) {
232  //File
233  std::string fname = fRootOutput->GetName();
234  fRootOutput->Write("",TObject::kOverwrite);
235  fRootOutput->Close();
236  delete fRootOutput;
237  fTree = NULL;
238  fRootOutput = NULL;
239  }
240 }
241 //_____________________________________________________________________________
242 void QRootFileWriterBase::AppendFileToFile(const char *fromFile,
243  const char *toFile) const {
244  // qtree
245  TFile ofile(fromFile);
246  QTree* otree = (QTree*)ofile.Get("qtree");
247  TFile* ifile = new TFile (toFile,"UPDATE");
248  QTree* itree = (QTree*)ifile->Get("qtree");
249 
250  // rename output qtree into qtree_sequenceName and make it
251  // friend of qtree.
252  TString friendname = "qtree";
253  friendname += "_";
254  friendname += GetSequence().GetName();
255 
256  // remove tree in input file
257  if(ifile->FindObject(friendname.Data()) &&
258  !QOptions::GetInstance().GetBool("General.OverWrite") &&
259  !GetBool("OverWriteEvent",false,false)
260  ) {
261  Panic("AppendToInput: Input file already contains a QTree with name %s. You may want to set the OverWriteEvent=true option to this module or run diana with the option -O or remove the QTree manually with diana-rootfilehandler. Best regards.",friendname.Data());
262  }
263  ifile->Delete(friendname+";*");
264  // remove tree from friend list
265  TObject* fele = 0;
266  TList* flist = itree->GetListOfFriends();
267  if(flist) fele = flist->FindObject(friendname.Data());
268  if(fele) itree->GetListOfFriends()->Remove(fele);
269  ifile->cd();
270 
271  // clone new tree and add it to input file
272  QTree* otree2 = dynamic_cast<QTree *>(otree->CloneTree(-1,"fast"));
273  otree2->SetName(friendname);
274  itree->AddFriend(otree2);
275  ifile->Write("",TObject::kOverwrite);
276 
277  // global quantities
278  if(TDirectory* dir = ofile.GetDirectory(ROOT_GLOBAL_DIR)) {
279  TList* list = dir->GetListOfKeys();
280  if(list && list->GetSize() > 0) {
281  TDirectory* rootGlobalDir = ifile->GetDirectory(ROOT_GLOBAL_DIR);
282  if(rootGlobalDir == 0)
283  rootGlobalDir =
284  ifile->mkdir(ROOT_GLOBAL_DIR,"Diana global objects");
285  rootGlobalDir->cd();
286 
287  TIter nextobj(list);
288  while (TKey* key = (TKey *) nextobj()) {
289  TString fullPath = ROOT_GLOBAL_DIR;
290  fullPath += "/";
291  fullPath += key->GetName();
292  TString thisKey = key->GetName();
293  rootGlobalDir->Delete(thisKey+";*");
294  ofile.Get(fullPath)->Write(key->GetName());
295  }
296  }
297  }
298 
299  ifile->Write("",TObject::kOverwrite);
300  delete ifile;
301 
302  ofile.Close();
303 }
304 //_____________________________________________________________________________
ap
Definition: CheckOFShape.C:47
err
Definition: CheckOF.C:114
QVector vec(3)
#define ROOT_GLOBAL_DIR
Definition: QDianaR.hh:4
#define Q_CURRENT_WRITER
Definition: QDiana.hh:40
@ QERR_SUCCESS
Definition: QError.hh:27
QError FillFromFile(const std::string &filename)
Definition: QAliases.cc:63
std::map< std::string, std::string > Find(const QEventLabel &label) const
Definition: QAliases.cc:25
QTreeInfo & GetTreeInfo()
Definition: QBaseTree.cc:21
bool wrapped into a QObject
Definition: QBool.hh:17
error class with error type and description
Definition: QError.hh:115
Visitor class to inspect the QEvent content.
QEvent & GetEvent()
Get the event.
std::vector< QEventLabel > GetWriteLabels() const
Get labels of QObjects to be written.
QObject ** Get(const char *owner, const char *name) const
Get reference of a QObject (can be used with TTree::SetBranchAddress).
const QAliases & GetAliases() const
get aliases (const version)
label for QObject in the QEvent
Definition: QEventLabel.hh:23
std::string GetStringLabel() const
get string in the format "owner@name"
Definition: QEventLabel.cc:48
std::string owner
owner of the QObject
Definition: QEventLabel.hh:60
std::string name
name of the QObject
Definition: QEventLabel.hh:62
void Get(const char *owner, ReadHandle< Q > &handle) const
Get a QObject Handle in read mode.
Definition: QEvent.hh:74
virtual void Done()
Done method called by the framework.
Definition: QFileWriter.cc:170
QGlobalWriter * GetWriter(const std::string &filename, QError &err)
get writer
static QGlobalWriterDispatcher & GetInstance()
QError Set(const std::string &name, const Q &obj, const std::string &descr="")
Set QObject, owned by the caller, - leave it undeclared if you can't implement it.
static QOptions & GetInstance()
Definition: QOptions.cc:23
QGlobalWriter * fGlobalWriter
The current global writer for the file.
void AppendToInput()
Append the output files to the input files.
std::map< std::string, std::string > fReaderWriterFiles
Map of output files and the input files they are synced to.
void Close()
Close any open files.
QTFilePointer fRootOutputAddress
Pointer to the output file.
TFile * fRootOutput
The current file being written.
QRootFileWriterBase()
Default ctor.
void Dump(const Diana::QEventInspector &evi)
Write the event to the output tree.
bool fSkipGenerated
Option to skip events that are generated by the reader.
void Done()
Done run at the end of the event loop.
virtual void Open(const std::string &filename, const Diana::QEventInspector &evi)
Open a file.
bool fAppendToInput
Flag to specify append to input.
virtual void AppendFileToFile(const char *fromFile, const char *toFile) const
Merge an individual file into another.
QTree * fTree
The current tree being written.
std::string fVersionTag
Definition: QTreeInfo.hh:15
std::string fSoftwareRevision
Definition: QTreeInfo.hh:14
std::map< std::string, std::string > fExtSWVersion
Definition: QTreeInfo.hh:16
TTree used in diana.
Definition: QTree.hh:19
Variable Data Type.
Definition: QVdt.hh:26
std::vector< QVdt > QVdt_vector
Definition: QVdt.hh:38
const std::string & GetString() const
Definition: QVdt.cc:225
std::string GetName() const
Definition: QVdt.hh:68
the Diana namespace is needed because sometimes we use Qt libraries, that use same class names of our...