tdaq-develop-2025-02-12
RootFileExplorer.cpp
1 #include "otsdaq/RootUtilities/RootFileExplorer.h"
2 #include "otsdaq/Macros/MessageTools.h"
3 // clang-format off
4 //================================================================================================
5 RootFileExplorer::RootFileExplorer(
6  std::string fSystemPath ,
7  std::string fRootPath ,
8  std::string fFoldersPath ,
9  std::string fHistName ,
10  std::string fRFoldersPath,
11  std::string fFileName ,
12  TFile * rootFile
13  ) : rootTagName_("ROOT")
14 {
15  fSystemPath_ = fSystemPath ;
16  fRootPath_ = fRootPath ;
17  fFoldersPath_ = fFoldersPath ;
18  fHistName_ = fHistName ;
19  fRFoldersPath_ = fRFoldersPath ;
20  fFileName_ = fFileName ;
21  STDLINE(std::string("fSystemPath : ")+fSystemPath_ ,ACCyan);
22  STDLINE(std::string("fRootPath : ")+fRootPath_ ,ACCyan);
23  STDLINE(std::string("fFoldersPath : ")+fFoldersPath_ ,ACCyan);
24  STDLINE(std::string("fHistName : ")+fHistName_ ,ACCyan);
25  STDLINE(std::string("fRFoldersPath: ")+fRFoldersPath_,ACCyan);
26  STDLINE(std::string("fFileName : ")+fFileName_ ,ACCyan);
27  level_ = 0 ;
28  counter_ = 0 ;
29  debug_ = true ;
30  isALeaf_[true] = "true" ;
31  isALeaf_[false] = "false" ;
32  rootFile_ = rootFile ;
33  anchorNodeLast_ = NULL ;
34  hierarchyPaths_.clear() ;
35 
36 }
37 
38 //================================================================================================
39 xercesc::DOMDocument * RootFileExplorer::initialize(bool liveDQMFlag)
40 {
41 
42  liveDQMFlag_ = liveDQMFlag;
43 
44  try
45  {
46  xercesc::XMLPlatformUtils::Initialize(); // Initialize Xerces infrastructure
47  }
48  catch(xercesc::XMLException& e)
49  {
50  string msg = xercesc::XMLString::transcode(e.getMessage()) ;
51  }
52 
53  theImplementation_ = xercesc::DOMImplementationRegistry::getDOMImplementation(xercesc::XMLString::transcode("Core"));
54 
55  if(theImplementation_)
56  {
57  try
58  {
59  theDocument_ = theImplementation_->createDocument(
60  xercesc::XMLString::transcode("http://www.w3.org/2001/XMLSchema-instance"),
61  xercesc::XMLString::transcode(rootTagName_.c_str()),
62  0
63  );
64  }
65  catch(const xercesc::OutOfMemoryException&)
66  {
67  XERCES_STD_QUALIFIER cerr << "OutOfMemoryException"
68  << XERCES_STD_QUALIFIER endl;
69  }
70  catch(const xercesc::DOMException& e)
71  {
72  XERCES_STD_QUALIFIER cerr << "DOMException code is: "
73  << e.code
74  << " "
75  << xercesc::XMLString::transcode(e.getMessage())
76  << XERCES_STD_QUALIFIER endl;
77  }
78  catch(const xercesc::XMLException& e)
79  {
80  STDLINE(string("Error Message: ")+xercesc::XMLString::transcode(e.getMessage()),ACRed) ;
81  }
82  catch(...)
83  {
84  XERCES_STD_QUALIFIER cerr << "An error occurred creating the theDocument_"
85  << XERCES_STD_QUALIFIER endl;
86  }
87  }
88  else
89  {
90  XERCES_STD_QUALIFIER cerr << "Requested theImplementation_ is not supported"
91  << XERCES_STD_QUALIFIER endl;
92  }
93 
94  this->initializeXMLWriter() ;
95 
96  if( liveDQMFlag_ )
97  {
98  rootElement_ = theDocument_->getDocumentElement();
99 
100  ss_.str(""); ss_ << "Main anchor (document): " << rootElement_ ;
101  STDLINE(ss_.str(),string(ACCyan)+string(ACReverse)) ;
102  STDLINE(rootFile_->GetName(),string(ACCyan)+string(ACReverse)) ;
103 
104  this->makeLiveDQMBinaryTree(rootFile_,0,"",NULL) ;
105  }
106  else
107  {
108  string fName = fSystemPath_ +string("/") +
109  fRootPath_ ;
110  if( fFoldersPath_.length() > 0 ) fName += string("/") + fFoldersPath_;
111  if( fFileName_ .length() > 0 ) fName += string("/") + fFileName_ ;
112  STDLINE(string("Opening fFileName_: ")+fFileName_, ACYellow) ;
113  STDLINE(string("Opening fName : ")+fName , ACYellow) ;
114  rootFile_ = new TFile(fName.c_str()) ;
115 
116  if( debug_) rootFile_->ls() ;
117 
118  rootElement_ = theDocument_->getDocumentElement();
119 
120  this->makeDirectoryBinaryTree(rootFile_,0,NULL) ;
121  }
122 
123  return theDocument_ ;
124 }
125 //==========================================================================================
126 xercesc::DOMElement * RootFileExplorer::populateBinaryTreeNode(xercesc::DOMElement * anchorNode,
127  std::string name ,
129  bool isLeaf )
130 {
131  ss_.str(""); ss_ << "fRFoldersPath_: " << fRFoldersPath_ ; STDLINE(ss_.str(),ACGreen) ;
132  ss_.str(""); ss_ << "previous : " << previousAncestor_; STDLINE(ss_.str(),ACGreen) ;
133  xercesc::DOMElement * nodes ;
134  if( theNodes_.find(previousAncestor_) == theNodes_.end() ) // a new node
135  {
136  nodes = theDocument_->createElement( xercesc::XMLString::transcode("nodes" ));
137  ss_.str(""); ss_ << "NEW nodes (" << nodes << ") for name " << name ; STDLINE(ss_.str(),"") ;
138  anchorNode->appendChild(nodes);
139  theNodes_ [previousAncestor_] = nodes ;
140  theNodeName_[previousAncestor_] = name ;
141  }
142  else // Is already there
143  {
144  nodes = theNodes_.find(previousAncestor_)->second ;
145  ss_.str(""); ss_ << name << " points to an OLD nodes (" << nodes << ") parallel to " << theNodeName_[previousAncestor_]; STDLINE(ss_.str(),"") ;
146  }
147  xercesc::DOMElement * node = theDocument_->createElement( xercesc::XMLString::transcode("node" ));
148  node->setAttribute(xercesc::XMLString::transcode("class" ),
149  xercesc::XMLString::transcode("x-tree-icon x-tree-icon-parent")) ;
150  nodes->appendChild(node);
151 
152  ss_.str(""); ss_ << "Attaching node " << node << " previousAncestor_ " << previousAncestor_ << " to nodes " << nodes; STDLINE(ss_.str(),"") ;
153 
154  xercesc::DOMElement * ancestor = theDocument_->createElement (xercesc::XMLString::transcode("ancestor"));
155  xercesc::DOMText * ancestorVal = theDocument_->createTextNode(xercesc::XMLString::transcode(previousAncestor_.c_str()));
156  ancestor->appendChild(ancestorVal);
157  node->appendChild(ancestor);
158 
159  xercesc::DOMElement * fSystemPath = theDocument_->createElement( xercesc::XMLString::transcode("fSystemPath" ));
160  node->appendChild(fSystemPath);
161 
162  xercesc::DOMText * fSystemPathVal = theDocument_->createTextNode(xercesc::XMLString::transcode(fSystemPath_.c_str() ));
163  fSystemPath->appendChild(fSystemPathVal);
164 
165  xercesc::DOMElement * fRootPath = theDocument_->createElement( xercesc::XMLString::transcode("fRootPath" ));
166  node->appendChild(fRootPath);
167 
168  xercesc::DOMText * fRootPathVal = theDocument_->createTextNode(xercesc::XMLString::transcode(fRootPath_.c_str() ));
169  fRootPath->appendChild(fRootPathVal);
170 
171  xercesc::DOMElement * fFoldersPath = theDocument_->createElement( xercesc::XMLString::transcode("fFoldersPath" ));
172  node->appendChild(fFoldersPath);
173 
174  xercesc::DOMText * fFoldersPathVal = theDocument_->createTextNode(xercesc::XMLString::transcode(fFoldersPath_.c_str()));
175  fFoldersPath->appendChild(fFoldersPathVal);
176 
177  xercesc::DOMElement * fDisplayName = NULL ;
178  xercesc::DOMElement * fFileName = NULL ;
179  xercesc::DOMElement * fRFoldersPath = NULL ;
180  xercesc::DOMElement * fHistName = NULL ;
181 
182  xercesc::DOMText * fDisplayNameVal = NULL ;
183  xercesc::DOMText * fFileNameVal = NULL ;
184  xercesc::DOMText * fRFoldersPathVal = NULL ;
185  xercesc::DOMText * fHistNameVal = NULL ;
186 
187  fDisplayName = theDocument_->createElement( xercesc::XMLString::transcode("fDisplayName" ));
188  fRFoldersPath = theDocument_->createElement( xercesc::XMLString::transcode("fRFoldersPath" ));
189  fHistName = theDocument_->createElement( xercesc::XMLString::transcode("fHistName" ));
190  fFileName = theDocument_->createElement( xercesc::XMLString::transcode("fFileName" ));
191 
192  fFileNameVal = theDocument_->createTextNode(xercesc::XMLString::transcode(fFileName_.c_str() ));
193  fHistNameVal = theDocument_->createTextNode(xercesc::XMLString::transcode(fHistName_.c_str() ));
194  fRFoldersPathVal = theDocument_->createTextNode(xercesc::XMLString::transcode(fRFoldersPath_.c_str()));
195 
196  if(isLeaf)
197  {
198  fDisplayNameVal = theDocument_->createTextNode(xercesc::XMLString::transcode(fHistName_.c_str() ));
199  }
200  else
201  {
202  fDisplayNameVal = theDocument_->createTextNode(xercesc::XMLString::transcode(name.c_str() ));
203  }
204 
205  node ->appendChild(fDisplayName );
206  node ->appendChild(fRFoldersPath );
207  node ->appendChild(fFileName );
208  node ->appendChild(fHistName );
209 
210  fDisplayName ->appendChild(fDisplayNameVal );
211  fFileName ->appendChild(fFileNameVal );
212  fHistName ->appendChild(fHistNameVal );
213  fRFoldersPath->appendChild(fRFoldersPathVal);
214 
215  xercesc::DOMElement * leaf = theDocument_->createElement( xercesc::XMLString::transcode("leaf" ));
216  node->appendChild(leaf);
217 
218  xercesc::DOMText * leafVal = theDocument_->createTextNode(xercesc::XMLString::transcode(isALeaf_[isLeaf].c_str()));
219  leaf->appendChild(leafVal);
220 
222 
234 
244  return node;
245 }
246 //================================================================================================
247 void RootFileExplorer::makeLiveDQMBinaryTree(TDirectory * currentDir,
248  int level ,
249  std::string subDirName,
250  xercesc::DOMElement * anchorNode )
251 {
253  if( !anchorNode) anchorNode = rootElement_ ;
254  currentDir = currentDir->GetDirectory(subDirName.c_str()) ;
255  if(currentDir != 0)
256  {
258  TObject* obj;
259  TIter nextobj(currentDir->GetList());
262  while((obj = (TObject*)nextobj()))
263  {
264  string objName = obj->GetName() ;
265  ss_.str("") ; ss_ << "Exploring " << objName << " class: " << string(obj->ClassName()); STDLINE(ss_.str(),"") ;
266  if( string(obj->ClassName()) == "TTree" ) continue ;
267  if( string(obj->ClassName()) == "TNtuple" ) continue ;
268  if( string(obj->ClassName()) == "TGeoManager" ) continue ;
269  if( string(obj->ClassName()) == "TGeoVolume" ) continue ;
270  if( obj->IsFolder() )
271  {
272  ss_.str("") ; ss_ << "Enter " << objName ;
273  STDLINE(ss_.str(),"") ;
274  hierarchyPaths_.push_back(objName) ;
275  fRFoldersPath_ = "" ;
276  fHistName_ = "" ;
277  for(int i=0; i<(int)hierarchyPaths_.size(); ++i) {fRFoldersPath_ += hierarchyPaths_[i];}
278  computeRFoldersPath() ;
279  previousAncestor_ = currentDir->GetName() ;
280  anchorNodeLast_ = this->populateBinaryTreeNode(anchorNode, string(obj->GetName()), false) ;
281  makeLiveDQMBinaryTree(currentDir,level+1,objName,anchorNodeLast_) ;
282  fHistName_ = obj->GetName () ;
283  fHistTitle_ = obj->GetTitle() ;
284  if(theNodes_.find(previousAncestor_) != theNodes_.end())
285  {
286  this->shrinkHierarchyPaths(1) ;
287  //theNodes_.erase(theNodes_.find(previousAncestor_)) ;
288  }
289  computeRFoldersPath() ;
290 
291  }
292  else // is TH1 or TCanvas
293  {
294  fHistName_ = obj->GetName() ;
295  previousAncestor_ = currentDir->GetName() ;
296  anchorNode = this->populateBinaryTreeNode(anchorNodeLast_, fHistName_, true) ;
297  }
298  }
299  }
300  else
301  {
302  STDLINE("No currentDir!!!",string(ACRed)+string(ACReverse)) ;
303  }
304 }
305 //================================================================================================
306 void RootFileExplorer::makeDirectoryBinaryTree(TDirectory * currentDirectory,
307  int level ,
308  xercesc::DOMElement * anchorNode )
309 {
310  if( !anchorNode ) anchorNode = rootElement_ ;
311  if( !anchorNodeLast_ ) anchorNodeLast_ = anchorNode ;
312 
313  TKey * keyH = NULL ;
314  TIter hList(currentDirectory->GetListOfKeys());
316  while((keyH = (TKey*)hList()))
317  {
318  std::string objName = keyH->GetName() ;
319  ss_.str("") ; ss_ << "Exploring " << objName << " level: " << level << " COUNTER: " << ++counter_;
321  string what = keyH->GetClassName () ;
322  if( what == "TTree" ) continue ;
323  if( what == "TNtuple" ) continue ;
324  if( what == "TGeoManager" ) continue ;
325  if( what == "TGeoVolume" ) continue ;
326  if( what == "TDirectoryFile" )
327  {
328  ss_.str("") ; ss_ << "Enter " << objName << " level: " << level ;
330  previousAncestor_ = currentDirectory->GetName() ;
331  currentDirectory->cd(objName.c_str());
332  TDirectory * subDir = gDirectory ;
333  hierarchyPaths_.push_back(std::string(subDir->GetName())) ;
334 
335  computeRFoldersPath() ;
336  fHistName_ = "" ;
338  anchorNodeLast_ = this->populateBinaryTreeNode(anchorNode, objName, false) ;
339  this->makeDirectoryBinaryTree(subDir,level+1,anchorNodeLast_) ;
340  this->shrinkHierarchyPaths(1) ;
341  computeRFoldersPath() ;
342  }
343  else
344  {
345  fHistName_ = objName ;
346  STDLINE(fHistName_,ACCyan) ;
347  previousAncestor_ = currentDirectory->GetName() ;
349  anchorNode = this->populateBinaryTreeNode(anchorNodeLast_, objName, true ) ;
350  }
351  }
352 }
353 //================================================================================================
354 void RootFileExplorer::computeRFoldersPath(void)
355 {
356  fRFoldersPath_ = "" ;
357  for(int i=0; i<(int)hierarchyPaths_.size(); ++i)
358  {
359  fRFoldersPath_ += hierarchyPaths_[i] + "/";
360  }
361 }
362 //================================================================================================
363 void RootFileExplorer::dumpHierarchyPaths(string what)
364 {
365  ss_.str("") ; ss_ << what << " - hierarchyPaths_.size(): " << hierarchyPaths_.size() ;
366  STDLINE(ss_.str(),"") ;
367  for(int i=0; i<(int)hierarchyPaths_.size(); i++)
368  {
369  ss_.str("") ; ss_ << i << "] " << hierarchyPaths_[i] ;
370  STDLINE(ss_.str(),"") ;
371  }
372 }
373 //================================================================================================
374 std::string RootFileExplorer::computeHierarchyPaths(void)
375 {
376  this->dumpHierarchyPaths("Computing...") ;
377  std::string name = "" ;
378  for(int i=0; i<(int)hierarchyPaths_.size(); i++)
379  {
380  name += hierarchyPaths_[i] ;
381  if( i != (int)hierarchyPaths_.size() - 1 ) name += string("/") ;
382  }
383  return name ;
384 }
385 //================================================================================================
386 void RootFileExplorer::shrinkHierarchyPaths(int number)
387 {
388  for(int i=0; i<number; ++i)
389  {
390  if( hierarchyPaths_.size() > 0 ) hierarchyPaths_.pop_back() ;
391  }
392 }
393 //================================================================================================
394 void RootFileExplorer::initializeXMLWriter(void)
395 {
396  XMLCh tempStr[100];
397  XMLString::transcode("LS", tempStr, 99);
398  DOMImplementation *impl = DOMImplementationRegistry::getDOMImplementation(tempStr);
399  theSerializer_ = ((DOMImplementationLS*)impl)->createLSSerializer();
400  if (theSerializer_->getDomConfig()->canSetParameter(XMLUni::fgDOMWRTDiscardDefaultContent, true))
401  theSerializer_->getDomConfig()->setParameter(XMLUni::fgDOMWRTDiscardDefaultContent, true);
402 
403  if (theSerializer_->getDomConfig()->canSetParameter(XMLUni::fgDOMWRTFormatPrettyPrint, true))
404  theSerializer_->getDomConfig()->setParameter(XMLUni::fgDOMWRTFormatPrettyPrint, true);
405 
406  myFormTarget_ = new StdOutFormatTarget();
407  theOutput_ = ((DOMImplementationLS*)impl)->createLSOutput();
408  theOutput_->setByteStream(myFormTarget_);
409 }
410 //================================================================================================
411 string RootFileExplorer::blanks(int level)
412 {
413  string s = "" ;
414  for(int i=0; i<level; ++i)
415  {
416  s += "\t" ;
417  }
418  return s ;
419 }
420 
421 // clang-format on
xercesc::DOMElement * populateBinaryTreeNode(xercesc::DOMElement *anchorNode, std::string name, bool isLeaf)
void makeLiveDQMBinaryTree(TDirectory *currentDirectory, int indent, std::string subDirName, xercesc::DOMElement *anchorNode)
void makeDirectoryBinaryTree(TDirectory *currentDirectory, int indent, xercesc::DOMElement *anchorNode)