Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2021-02-14 14:33:47

0001 /**
0002  *
0003  *  Class: multiPlotter
0004  *
0005  *  Description:  
0006  *  This macro will draw histograms from a list of root files and write them
0007  *  to a target root file. The target file is newly created and must not be
0008  *  identical to one of the source files.
0009  *  Option: create a pdf file and / or a directory of gif files
0010  *
0011  *  This code is based on the hadd.C example by Rene Brun and Dirk Geppert,
0012  *  which had a problem with directories more than one level deep.
0013  *  (see macro hadd_old.C for this previous implementation).
0014  *
0015  *
0016  *  Authors:
0017  *  A. Everett Purdue University
0018  *  
0019  **/
0020 
0021 #include "Riostream.h"
0022 #include "TCanvas.h"
0023 #include "TChain.h"
0024 #include "TFile.h"
0025 #include "TH1.h"
0026 #include "TH2.h"
0027 #include "TKey.h"
0028 #include "TTree.h"
0029 #include <TGraph.h>
0030 #include <TLegend.h>
0031 #include <TPDF.h>
0032 #include <TROOT.h>
0033 #include <TStyle.h>
0034 #include <TSystem.h>
0035 #include <cstring>
0036 
0037 #include <boost/program_options.hpp>
0038 #include <iostream>
0039 #include <fstream>
0040 
0041 TList *FileList;
0042 TFile *Target;
0043 TPDF *pdf;
0044 TLegend *gLegend;
0045 TString *baseName;
0046 bool makeGraphic;
0047 
0048 void drawLoop(TDirectory *target, TList *sourcelist, TCanvas *c1);
0049 
0050 int main(int argc, char *argv[]) {
0051   // Default arguments
0052   std::string outbase = "canvas";
0053   std::string outname = outbase + ".root";
0054   std::string pdfname = outbase + ".pdf";
0055   bool makePdf = false;
0056   makeGraphic = false;
0057   std::string infileName;
0058   std::vector<std::string> inFileVector;
0059   inFileVector.clear();
0060 
0061   //--- Get parameters from command line ---//
0062   boost::program_options::options_description desc("Available options for multiPlotter");
0063   desc.add_options()("help,h", "Print this help message")("infile,i",
0064                                                           boost::program_options::value<std::string>(),
0065                                                           //     "Input file name (Default is validation.root)")
0066                                                           "Input file name")(
0067       "outfile,o",
0068       boost::program_options::value<std::string>(),
0069       "Sets output files to <outfile>.root/.pdf (default is canvas)")("pdf,p", "Make a PDF file")(
0070       "graphic,g", "makes a gif file for each TCanvas");
0071 
0072   std::string usage = "\nSample multiPlotter usage::\n";
0073   usage += "\"multiPlotter -o validation-canvas -i validation.root\"\n ";
0074   usage += "\t input= validation.root\n";
0075   usage += "\t output= validation-canvas.root\n";
0076   usage += "\"multiPlotter -g -p -o validation-canvas -i \"validation_01.root validation_02.root\" \"\n";
0077   usage += "\t input= validation_01.root AND validation_02.root\n";
0078   usage += "\t output= validation-canvas.root\n";
0079   usage += "\t         validation-canvas.pdf\n";
0080   usage +=
0081       "\t         gif files in validation-canvas/ \n\t\t\t (a directory tree which has the same \n\t\t\t directory "
0082       "structure as validation-canvas.root\n";
0083   usage += "\n";
0084 
0085   boost::program_options::positional_options_description pos;
0086   boost::program_options::variables_map vmap;
0087 
0088   try {
0089     boost::program_options::store(
0090         boost::program_options::command_line_parser(argc, argv).options(desc).positional(pos).run(), vmap);
0091   } catch (boost::program_options::error const &x) {
0092     std::cerr << "Unable to parse options:\n" << x.what() << "\n\n";
0093     std::cerr << desc << usage << std::endl;
0094     return 1;
0095   }
0096 
0097   boost::program_options::notify(vmap);
0098   if (vmap.count("help")) {
0099     std::cout << desc << usage << std::endl;
0100     return 1;
0101   }
0102   if (vmap.count("outfile")) {
0103     outbase = vmap["outfile"].as<std::string>();
0104     outname = outbase + ".root";
0105     pdfname = outbase + ".pdf";
0106   }
0107   if (vmap.count("pdf")) {
0108     makePdf = true;
0109   }
0110   if (vmap.count("graphic")) {
0111     makeGraphic = true;
0112   }
0113   if (vmap.count("infile")) {
0114     infileName = vmap["infile"].as<std::string>();
0115     /*
0116     std::ifstream inFile(infileName.c_str()) ;
0117     if (inFile.is_open()) { //--- input files listed in a file ---//
0118       while ( !inFile.eof() ) {
0119     std::string skipped ;
0120     getline(inFile,skipped) ; 
0121     inFileVector.push_back( skipped ) ;
0122       }
0123     } else 
0124     */
0125     {  //--- Assume the file is a space-separated list of files -//
0126       size_t strStart = 0;
0127       for (size_t itr = infileName.find(" ", 0); itr != std::string::npos; itr = infileName.find(" ", itr)) {
0128         std::string skipped = infileName.substr(strStart, (itr - strStart));
0129         itr++;
0130         strStart = itr;
0131         inFileVector.push_back(skipped);
0132       }
0133       //--- Fill the last entry ---//
0134       inFileVector.push_back(infileName.substr(strStart, infileName.length()));
0135     }
0136   } else {
0137     std::cout << " *** No input file given: please define one " << std::endl;
0138     return 0;
0139   }
0140 
0141   TDirectory *target = TFile::Open(TString(outname), "RECREATE");
0142 
0143   baseName = new TString(outbase);
0144   baseName->Append("/");
0145 
0146   TList *sourcelist = new TList();
0147   for (std::vector<std::string>::size_type i = 0; i < inFileVector.size(); i++) {
0148     std::cout << inFileVector[i] << " " << std::endl;
0149     sourcelist->Add(TFile::Open(TString(inFileVector[i])));
0150   }
0151 
0152   TCanvas *c1 = new TCanvas("c1");
0153   pdf = nullptr;
0154   if (makePdf)
0155     pdf = new TPDF(TString(pdfname));
0156   //  int pageNumber = 2 ;
0157   // double titleSize = 0.050 ;
0158 
0159   gROOT->SetStyle("Plain");
0160   gStyle->SetPalette(1);
0161   //gStyle->SetOptStat(111111) ;
0162   gStyle->SetOptStat(0);
0163   c1->UseCurrentStyle();
0164   gROOT->ForceStyle();
0165 
0166   drawLoop(target, sourcelist, c1);
0167 
0168   if (makePdf)
0169     pdf->Close();
0170   target->Close();
0171   return 0;
0172 }
0173 
0174 void drawLoop(TDirectory *target, TList *sourcelist, TCanvas *c1) {
0175   TString path((char *)strstr(target->GetPath(), ":"));
0176   path.Remove(0, 2);
0177 
0178   TString sysString(path);
0179   sysString.Prepend(baseName->Data());
0180 
0181   TFile *first_source = (TFile *)sourcelist->First();
0182   first_source->cd(path);
0183   TDirectory *current_sourcedir = gDirectory;
0184   //gain time, do not add the objects in the list in memory
0185   Bool_t status = TH1::AddDirectoryStatus();
0186   TH1::AddDirectory(kFALSE);
0187 
0188   // loop over all keys in this directory
0189   TIter nextkey(current_sourcedir->GetListOfKeys());
0190   TKey *key, *oldkey = nullptr;
0191   while ((key = (TKey *)nextkey())) {
0192     //keep only the highest cycle number for each key
0193     if (oldkey && !strcmp(oldkey->GetName(), key->GetName()))
0194       continue;
0195 
0196     // read object from first source file
0197     first_source->cd(path);
0198     TObject *obj = key->ReadObj();
0199 
0200     if (obj->IsA()->InheritsFrom("TH1") && !obj->IsA()->InheritsFrom("TH2")) {
0201       // descendant of TH1 -> merge it
0202       gLegend = new TLegend(.7, .15, .95, .4, "");
0203       gLegend->SetHeader(gDirectory->GetName());
0204       Color_t color = 1;
0205       Style_t style = 22;
0206       TH1 *h1 = (TH1 *)obj;
0207       h1->SetLineColor(color);
0208       h1->SetMarkerStyle(style);
0209       h1->SetMarkerColor(color);
0210       h1->Draw();
0211       TString tmpName(first_source->GetName());
0212       gLegend->AddEntry(h1, tmpName, "LP");
0213       c1->Update();
0214 
0215       // loop over all source files and add the content of the
0216       // correspondant histogram to the one pointed to by "h1"
0217       TFile *nextsource = (TFile *)sourcelist->After(first_source);
0218       while (nextsource) {
0219         // make sure we are at the correct directory level by cd'ing to path
0220         nextsource->cd(path);
0221         TKey *key2 = (TKey *)gDirectory->GetListOfKeys()->FindObject(h1->GetName());
0222         if (key2) {
0223           TH1 *h2 = (TH1 *)key2->ReadObj();
0224           color++;
0225           style++;
0226           h2->SetLineColor(color);
0227           h2->SetMarkerStyle(style);
0228           h2->SetMarkerColor(color);
0229           h2->Draw("same");
0230           TString tmpName(nextsource->GetName());
0231           gLegend->AddEntry(h2, tmpName, "LP");
0232           gLegend->Draw("same");
0233           c1->Update();
0234           //- delete h2;
0235         }
0236 
0237         nextsource = (TFile *)sourcelist->After(nextsource);
0238       }
0239     } else if (obj->IsA()->InheritsFrom("TH2")) {
0240       // descendant of TH2 -> merge it
0241       gLegend = new TLegend(.85, .15, 1.0, .30, "");
0242       gLegend->SetHeader(gDirectory->GetName());
0243       Color_t color = 1;
0244       Style_t style = 22;
0245       TH2 *h1 = (TH2 *)obj;
0246       h1->SetLineColor(color);
0247       h1->SetMarkerStyle(style);
0248       h1->SetMarkerColor(color);
0249       h1->Draw();
0250       TString tmpName(first_source->GetName());
0251       gLegend->AddEntry(h1, tmpName, "LP");
0252       c1->Update();
0253 
0254       // loop over all source files and add the content of the
0255       // correspondant histogram to the one pointed to by "h1"
0256       TFile *nextsource = (TFile *)sourcelist->After(first_source);
0257       while (nextsource) {
0258         // make sure we are at the correct directory level by cd'ing to path
0259         nextsource->cd(path);
0260         TKey *key2 = (TKey *)gDirectory->GetListOfKeys()->FindObject(h1->GetName());
0261         if (key2) {
0262           TH2 *h2 = (TH2 *)key2->ReadObj();
0263           color++;
0264           style++;
0265           h2->SetLineColor(color);
0266           h2->SetMarkerStyle(style);
0267           h2->SetMarkerColor(color);
0268           h2->Draw("same");
0269           TString tmpName(nextsource->GetName());
0270           gLegend->AddEntry(h2, tmpName, "LP");
0271           gLegend->Draw("same");
0272           c1->Update();
0273           //- delete h2;
0274         }
0275         nextsource = (TFile *)sourcelist->After(nextsource);
0276       }
0277     } else if (obj->IsA()->InheritsFrom("TGraph")) {
0278       obj->IsA()->Print();
0279       gLegend = new TLegend(.7, .15, .95, .4, "");
0280       gLegend->SetHeader(gDirectory->GetName());
0281       Color_t color = 1;
0282       Style_t style = 22;
0283       TGraph *h1 = (TGraph *)obj;
0284       h1->SetLineColor(color);
0285       h1->SetMarkerStyle(style);
0286       h1->SetMarkerColor(color);
0287       h1->GetHistogram()->Draw();
0288       h1->Draw();
0289       TString tmpName(first_source->GetName());
0290       gLegend->AddEntry(h1, tmpName, "LP");
0291       c1->Update();
0292 
0293       // loop over all source files and add the content of the
0294       // correspondant histogram to the one pointed to by "h1"
0295       TFile *nextsource = (TFile *)sourcelist->After(first_source);
0296       while (nextsource) {
0297         // make sure we are at the correct directory level by cd'ing to path
0298         nextsource->cd(path);
0299         TKey *key2 = (TKey *)gDirectory->GetListOfKeys()->FindObject(h1->GetName());
0300         if (key2) {
0301           TGraph *h2 = (TGraph *)key2->ReadObj();
0302           color++;
0303           style++;
0304           h2->SetLineColor(color);
0305           h2->SetMarkerStyle(style);
0306           h2->SetMarkerColor(color);
0307           h2->Draw("same");
0308           TString tmpName(nextsource->GetName());
0309           gLegend->AddEntry(h2, tmpName, "LP");
0310           gLegend->Draw("same");
0311           c1->Update();
0312           //- delete h2;
0313         }
0314 
0315         nextsource = (TFile *)sourcelist->After(nextsource);
0316       }
0317     } else if (obj->IsA()->InheritsFrom("TTree")) {
0318       std::cout << "I don't draw trees" << std::endl;
0319     } else if (obj->IsA()->InheritsFrom("TDirectory")) {
0320       // it's a subdirectory
0321       std::cout << "Found subdirectory " << obj->GetName() << std::endl;
0322 
0323       // create a new subdir of same name and title in the target file
0324       target->cd();
0325       TDirectory *newdir = target->mkdir(obj->GetName(), obj->GetTitle());
0326 
0327       // create a new subdir of same name in the file system
0328       TString newSysString(sysString + "/" + obj->GetName());
0329       if (makeGraphic)
0330         gSystem->mkdir(newSysString.Data(), kTRUE);
0331 
0332       // newdir is now the starting point of another round of merging
0333       // newdir still knows its depth within the target file via
0334       // GetPath(), so we can still figure out where we are in the recursion
0335       drawLoop(newdir, sourcelist, c1);
0336 
0337     } else {
0338       // object is of no type that we know or can handle
0339       std::cout << "Unknown object type, name: " << obj->GetName() << " title: " << obj->GetTitle() << std::endl;
0340     }
0341 
0342     // now write the merged TCanvas (which is "in" obj) to the target file
0343     // note that this will just store obj in the current directory level,
0344     // which is not persistent until the complete directory itself is stored
0345     // by "target->Write()" below
0346     if (obj) {
0347       target->cd();
0348 
0349       if (obj->IsA()->InheritsFrom("TH1") || obj->IsA()->InheritsFrom("TGraph")) {
0350         //   && !obj->IsA()->InheritsFrom("TH2") ) {
0351         TString newName(obj->GetName());
0352         newName.ReplaceAll("(", 1, "_", 1);
0353         newName.ReplaceAll(")", 1, "_", 1);
0354         c1->SetName(newName);
0355         c1->Write(c1->GetName(), TObject::kOverwrite);
0356 
0357         if (makeGraphic) {
0358           if (gROOT->IsBatch()) {
0359             c1->Print("temp.eps");
0360             gSystem->Exec("pstopnm -ppm -xborder 0 -yborder 0 -portrait temp.eps");
0361             char tempCommand[200];
0362             sprintf(tempCommand, "ppmtogif temp.eps001.ppm > %s/%s.gif", sysString.Data(), c1->GetName());
0363             gSystem->Exec(tempCommand);
0364           } else {
0365             c1->Print(sysString + "/" + TString(c1->GetName()) + ".gif");
0366           }
0367         }
0368       }
0369     }
0370     //if(gLegend) delete gLegend;
0371   }  // while ( ( TKey *key = (TKey*)nextkey() ) )
0372 
0373   // save modifications to target file
0374   target->SaveSelf(kTRUE);
0375   TH1::AddDirectory(status);
0376 }