RootOutput.cxx 11.4 KB
Newer Older
1
/*****************************************************************************
2
 * Copyright (C) 2009-2021   this file is part of the NPTool Project         *
3 4 5 6 7 8 9 10 11
 *                                                                           *
 * For the licensing terms see $NPTOOL/Licence/NPTool_Licence                *
 * For the list of contributors see $NPTOOL/Licence/Contributors             *
 *****************************************************************************/

/*****************************************************************************
 * Original Author: N. de Sereville  contact address: deserevi@ipno.in2p3.fr *
 *                                                                           *
 * Creation Date  : 21/07/09                                                 *
12
 * Last update    : 10/05/21                                                 *
13 14 15 16 17
 *---------------------------------------------------------------------------*
 * Decription: This class is a singleton class which deals with the ROOT     *
 *             output file and tree both for NPSimulation and NPAnalysis.    *
 *---------------------------------------------------------------------------*
 * Comment:                                                                  *
deserevi's avatar
deserevi committed
18
 *   + 03/02/11: Add support for TAsciiFile objects (N. de Sereville)        *
19
 *   + 10/05/21: Add support for split tree output (A. Matta)                *
20 21 22 23
 *                                                                           *
 *                                                                           *
 *****************************************************************************/

Unknown's avatar
Unknown committed
24
#include <iostream>
25
#include <fstream>
Unknown's avatar
Unknown committed
26 27 28
#include <cstdlib>

#include "RootOutput.h"
deserevi's avatar
deserevi committed
29
#include "NPOptionManager.h"
Unknown's avatar
Unknown committed
30 31 32

using namespace std;

33
RootOutput* RootOutput::instance = 0;
34
////////////////////////////////////////////////////////////////////////////////
35
RootOutput* RootOutput::getInstance(std::string fileNameBase, std::string treeNameBase,bool split){
36 37
  // A new instance of RootOutput is created if it does not exist:
  if (instance == 0) {
38
    instance = new RootOutput(fileNameBase.c_str(), treeNameBase.c_str(),split);
39
  }
Unknown's avatar
Unknown committed
40

41 42
  // The instance of RootOutput is returned:
  return instance;
Unknown's avatar
Unknown committed
43 44
}

45 46
////////////////////////////////////////////////////////////////////////////////
void RootOutput::Destroy(){ 
47 48 49 50
  if (instance != 0) {
    delete instance;
    instance = 0;
  }
Unknown's avatar
Unknown committed
51 52
}

53
////////////////////////////////////////////////////////////////////////////////
54
RootOutput::RootOutput(std::string fileNameBase, std::string treeNameBase,bool split){
55

56 57 58 59 60
  pSplit = (split || NPOptionManager::getInstance()->IsSplit());
  cout << endl << "/////////// ROOT Output files ///////////" << endl;
  cout << "Initializing ouput trees and files ";
  if(pSplit)
    cout << "in split mode (one tree per detector)" << endl;
61 62
  else
    cout << endl;
63 64
  pTreeName=treeNameBase;
  pCurrentDirectory= gDirectory;
65 66
  bool analysis=false;
  bool simulation=false;
67 68

  if(NPOptionManager::getInstance()->IsAnalysis()){
69 70
    analysis = true;
  }
71
  else if(NPOptionManager::getInstance()->IsSimulation()){
72 73
    simulation= true;
  }
Unknown's avatar
Unknown committed
74

75 76 77 78 79 80 81 82 83 84 85 86 87
  // Setup the base name
  if(analysis)
    pBaseName = NPOptionManager::getInstance()->GetAnalysisOutputPath();
  else if(simulation)
    pBaseName = NPOptionManager::getInstance()->GetSimulationOutputPath();
  else
    pBaseName="./";

  pBaseName += "/"+fileNameBase;

  if (fileNameBase.find("root")==std::string::npos) 
    pBaseName += ".root";

88
  // removing "//" from path
89 90 91
//  while(size_t pos = pBaseName.find("//")!=std::string::npos){
//    pBaseName.erase(pos);
//  }
92

93 94 95 96 97 98 99 100 101 102 103
  if(pSplit){
    // Create a folder for all the trees
    string stripname = pBaseName;
    stripname.erase(stripname.find(".root"),5);
    string path = stripname.substr(0,stripname.rfind("/"));
    string filebase = stripname.substr(stripname.rfind("/")+1);
    string command = "mkdir -p "+stripname;
    int res = system(command.c_str());
    if(res!=0){
      std::cout << "Error creating folder " << stripname << std::endl;
      exit(1);
104
    }
105 106 107 108 109 110 111 112 113 114 115 116 117 118 119
    // create the master file 
    pMasterFile=stripname+"/"+filebase+".tree";
    ofstream master(pMasterFile.c_str(),std::ofstream::trunc);
    master.close();
  }
  else{
    CreateTreeAndFile("global");
  }
  /////
  // Create the last file 
  if(treeNameBase=="SimulatedTree"){
    string path = getenv("NPTOOL");
    path+="/.last_sim_file";
    ofstream last_sim_file(path.c_str());
    last_sim_file << "Tree "<< pTreeName <<endl
120
      << " " << pBaseName <<endl;
121 122
    last_sim_file.close();
  }
123

124 125 126 127 128 129 130 131
  else if(treeNameBase=="PhysicsTree"){
    string path = getenv("NPTOOL");
    path+="/.last_phy_file";
    ofstream last_phy_file(path.c_str());
    last_phy_file << "Tree "<< pTreeName<<endl
      << " " << pBaseName <<endl;
    last_phy_file.close();
  }
132

133 134 135 136 137 138 139 140
  else if(treeNameBase=="ResultTree"){
    string path = getenv("NPTOOL");
    path+="/.last_res_file";
    ofstream last_res_file(path.c_str());
    last_res_file << "Tree " << pTreeName << endl 
      << " " << pBaseName<<endl;
    last_res_file.close();
  }
141

142 143 144 145 146 147 148 149
  else{
    string path = getenv("NPTOOL");
    path+="/.last_any_file";
    ofstream last_any_file(path.c_str());
    last_any_file << "Tree " << pTreeName <<endl
      << " " << pBaseName<< endl;
    last_any_file.close();
  }
150 151


152 153
  InitAsciiFiles();
}
154

155 156 157 158
////////////////////////////////////////////////////////////////////////////////
void RootOutput::CreateTreeAndFile(std::string name){
  // Create the tree only if does not exist already
  string file_name=pBaseName;
159

160
  if(pRootFiles.find(name)==pRootFiles.end()){
161 162 163 164 165 166 167
    if(pSplit){
      string  strip= pBaseName.substr(pBaseName.rfind("/"));
      strip = strip.substr(0,strip.rfind(".root"));
      string  insertion= "_"+name;
      file_name.insert(file_name.rfind(".root"),insertion);
      file_name.insert(file_name.rfind("/"),strip);
    }
168 169 170 171
    cout << " - Creating output file " << file_name.c_str() << endl;
    pRootFiles[name] = new TFile(file_name.c_str(), "RECREATE");
    pRootTrees[name] = new TTree(pTreeName.c_str(), "Data created / analysed with the nptool package");
    pRootFiles[name]->SetCompressionLevel(1);
172

173 174
    // Init TAsciiFile objects
    gDirectory->cd(pCurrentDirectory->GetPath()); 
175

176 177 178 179
    if(NPOptionManager::getInstance()->GetCircularTree()){
      cout << "Information: Output tree is set to circular mode" << endl;
      pRootTrees[name]->SetCircular(1000); 
    }
180

181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211
    if(pSplit){// Add the tree to the .tree file
      ofstream master(pMasterFile.c_str(),std::ofstream::app);
      file_name = file_name.substr(file_name.rfind("/")+1);
      master << file_name.c_str() << endl;
      master.close();
    }
  } 
  //
  /*
     for(auto it = m_DetectorMap.begin() ; it!=m_DetectorMap.end() ;++it){
     string insertion = "_"+it->first;
     master << filebase << insertion << ".root" << std::endl;
     string filename=path+"/"+filebase+"/"+filebase+insertion+".root";
     auto file = new TFile(filename.c_str(),"RECREATE");
     string treename = "RawTree_"+it->first;
     auto tree = new TTree("RawTree",treename.c_str());
     m_TreeMap[it->first]=tree;
     m_FileMap[it->first]=file;
     tree->SetDirectory(file);
     std::cout << "Splitting tree: " << filename << std::endl;
     it->second->InitBranch(tree);
     }
     master.close();

*/
}
////////////////////////////////////////////////////////////////////////////////
void RootOutput::Fill(){
 for(auto it = pRootTrees.begin();it!=pRootTrees.end();it++){
  it->second->Fill();
 } 
deserevi's avatar
deserevi committed
212 213
}

214
////////////////////////////////////////////////////////////////////////////////
215
void RootOutput::InitAsciiFiles(){
216 217 218 219 220
  // get NPOptionManager pointer
  NPOptionManager* OptionManager  = NPOptionManager::getInstance();

  // Event generator
  // Get file name from NPOptionManager
Adrien Matta's avatar
Adrien Matta committed
221
  std::string fileNameEG = OptionManager->GetReactionFile();
222
  pEventGenerator = new TAsciiFile();
Adrien Matta's avatar
Adrien Matta committed
223 224
  pEventGenerator->SetNameTitle("EventGenerator", fileNameEG.c_str());
  pEventGenerator->Append(fileNameEG.c_str());
225 226
  //pEventGenerator->Write(0,TAsciiFile::kOverwrite);

227 228
  // Detector configuration 
  // Get file name from NPOptionManager
Adrien Matta's avatar
Adrien Matta committed
229
  std::string fileNameDC = OptionManager->GetDetectorFile();
230
  pDetectorConfiguration = new TAsciiFile();
Adrien Matta's avatar
Adrien Matta committed
231 232
  pDetectorConfiguration->SetNameTitle("DetectorConfiguration", fileNameDC.c_str());
  pDetectorConfiguration->Append(fileNameDC.c_str());
233
  //pDetectorConfiguration->Write(0,TAsciiFile::kOverwrite);
234 235 236 237 238

  // Run to treat file
  // Get file name from NPOptionManager
  pRunToTreatFile = new TAsciiFile();
  if (!OptionManager->IsDefault("RunToTreat")) {
Adrien Matta's avatar
Adrien Matta committed
239 240 241
    std::string fileNameRT = OptionManager->GetRunToReadFile();
    pRunToTreatFile->SetNameTitle("RunToTreat", fileNameRT.c_str());
    pRunToTreatFile->Append(fileNameRT.c_str());
242
    //pRunToTreatFile->Write(0,TAsciiFile::kOverwrite);
243 244 245 246 247
  }

  // Calibration files
  pCalibrationFile = new TAsciiFile();
  if (!OptionManager->IsDefault("Calibration")) {
Adrien Matta's avatar
Adrien Matta committed
248 249
    std::string fileNameCal = OptionManager->GetCalibrationFile();
    pCalibrationFile->SetNameTitle("Calibration", fileNameCal.c_str());
250
    //pCalibrationFile->Write(0,TAsciiFile::kOverwrite);
251 252 253 254 255
  }

  // Analysis configuration files
  pAnalysisConfigFile = new TAsciiFile();
  pAnalysisConfigFile->SetNameTitle("AnalysisConfig", "AnalysisConfig");
256
  //pAnalysisConfigFile->Write(0,TAsciiFile::kOverwrite);
Unknown's avatar
Unknown committed
257 258
}

259 260
////////////////////////////////////////////////////////////////////////////////
RootOutput::~RootOutput(){ 
261
  // The data is written to the file and the tree is closed:
262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287
  if (pRootFiles.size()>0) {
    cout << endl << endl << "Root Output summary" << endl;
    TDirectory* pCurrentDirectory= gDirectory;
    for(auto it = pRootFiles.begin(); it!=pRootFiles.end();it++){
      cout << " - " <<it->first << " tree and file " << endl;
      gDirectory->cd(it->second->GetPath());
      // write TAsciiFile if used
      // EventGenerator
      if (!pEventGenerator->IsEmpty()) pEventGenerator->Write(0,TAsciiFile::kOverwrite);
      // DetectorConfiguration
      if (!pDetectorConfiguration->IsEmpty()) pDetectorConfiguration->Write(0,TAsciiFile::kOverwrite);
      // CalibrationFile
      if (!pCalibrationFile->IsEmpty()) pCalibrationFile->Write(0,TAsciiFile::kOverwrite);
      // RunToTreatFile
      if (!pRunToTreatFile->IsEmpty()) pRunToTreatFile->Write(0,TAsciiFile::kOverwrite);
      // Analysis ConfigFile
      if (!pAnalysisConfigFile->IsEmpty()) pAnalysisConfigFile->Write(0,TAsciiFile::kOverwrite);

      cout << "  -> Number of entries in the " << it->first << " Tree: " << pRootTrees[it->first]->GetEntries() << endl;
      cout << "  -> Number of bites written to file: " << pRootTrees[it->first]->Write(0, TObject::kOverwrite) << endl;
      it->second->Flush();
      it->second->Purge(1);

      gDirectory->cd(pCurrentDirectory->GetPath());
      it->second->Close();
    }
288 289 290 291 292
  }

  else {
    cout << "\033[1;31mNo histograms and Tree !\033[0m" << endl;
  }
Unknown's avatar
Unknown committed
293
}
294

295
////////////////////////////////////////////////////////////////////////////////
296 297 298
TFile* RootOutput::GetFile(std::string name)  {
  if(!pSplit)
    name="global";
299

300 301
  if(pRootFiles.find(name)!=pRootFiles.end())
    return pRootFiles[name];
302
  else{
303
    std::cout << "Error: Requested file for detector " << name << " does not exist" << std::endl;
304 305
    exit(1);
  }
306 307 308 309 310 311 312 313 314 315 316 317
  return 0;
}

////////////////////////////////////////////////////////////////////////////////
TTree* RootOutput::GetTree(std::string name) {
  if(!pSplit)
    name="global";

  if(pRootTrees.find(name)==pRootTrees.end())
    CreateTreeAndFile(name);
  
  return pRootTrees[name];
318
}
319