Back to home page

sPhenix code displayed by LXR

 
 

    


File indexing completed on 2025-08-06 08:11:53

0001 // 'MergeFiles.C'
0002 // Derek Anderson
0003 // 09.25.2020
0004 //
0005 // Merges root files.  Adapted from code
0006 // by Nihar Sahoo.
0007 
0008 #include <fstream>
0009 #include <string.h>
0010 #include "TChain.h"
0011 #include "TFile.h"
0012 #include "TH1.h"
0013 #include "TTree.h"
0014 #include "TKey.h"
0015 #include "Riostream.h"
0016 
0017 
0018 
0019 // forward declaration of 'MergeRootFile(TDirectory*, TList*)'
0020 void MergeRootfile(TDirectory *target, TList *sourcelist);
0021 
0022 
0023 
0024 void MergeFiles(const Int_t nFiles=100, const TString filelist= "file.list", const TString outputrootfiles ="test.root") {
0025 
0026   ifstream files;
0027   //files.open("file2.list");
0028   files.open(filelist);
0029   
0030   char file_stm[800];
0031   int line=0;
0032 
0033   TList *FileList; 
0034   TFile *Target; 
0035 
0036 
0037   TString filename_output;
0038   TString chain_;
0039   Int_t start_num = 0;
0040   Int_t end_num = 4;
0041   
0042   Target = TFile::Open(outputrootfiles, "RECREATE"); 
0043   FileList = new TList(); 
0044 
0045   while(files.good()) {
0046         files >> file_stm;
0047 
0048             // quick fix [Derek, 06.02.2017]
0049             if ((line + 1) > nFiles) {
0050               cout << "WARNING: Whoah there, tiger! Only need " << nFiles << " files!\n"
0051                    << "         Moving on to processing files."
0052                    << endl;
0053               break;
0054             }
0055         
0056         //___________________
0057         
0058         TFile f(file_stm);        
0059   
0060         //      Target = TFile::Open( chain_, "RECREATE" ); 
0061 
0062         
0063         Bool_t fOk = f.IsZombie();
0064         cout<<"file# "<<line<<"  "<< file_stm<<"  zombi= "<<fOk<<endl;
0065         
0066         if(!fOk)
0067           {
0068         FileList->Add(TFile::Open(file_stm));
0069           }
0070     
0071 
0072         
0073         if (!files.good()) break;
0074         line++;
0075       }
0076     MergeRootfile( Target, FileList );  
0077 
0078 
0079 }  // end 'TriggerResolutionStudy_MergeFiles(Int_t, TString, TString)'
0080 
0081 
0082 
0083 void MergeRootfile( TDirectory *target, TList *sourcelist ) {
0084 
0085   //  cout << "Target path: " << target->GetPath() << endl;
0086   TString path( (char*)strstr( target->GetPath(), ":" ) );
0087   path.Remove( 0, 2 );
0088 
0089   TFile *first_source = (TFile*)sourcelist->First();
0090   first_source->cd( path );
0091   TDirectory *current_sourcedir = gDirectory;
0092   //gain time, do not add the objects in the list in memory
0093   Bool_t status = TH1::AddDirectoryStatus();
0094   TH1::AddDirectory(kFALSE);
0095 
0096   // loop over all keys in this directory
0097   TChain *globChain = 0;
0098   TIter nextkey( current_sourcedir->GetListOfKeys() );
0099   TKey *key, *oldkey=0;
0100   while ( (key = (TKey*)nextkey())) {
0101 
0102     //keep only the highest cycle number for each key
0103     if (oldkey && !strcmp(oldkey->GetName(),key->GetName())) continue;
0104 
0105     // read object from first source file
0106     first_source->cd( path );
0107     TObject *obj = key->ReadObj();
0108 
0109     if ( obj->IsA()->InheritsFrom( TH1::Class() ) ) {
0110       // descendant of TH1 -> merge it
0111 
0112       //      cout << "Merging histogram " << obj->GetName() << endl;
0113       TH1 *h1 = (TH1*)obj;
0114 
0115       // loop over all source files and add the content of the
0116       // correspondant histogram to the one pointed to by "h1"
0117       TFile *nextsource = (TFile*)sourcelist->After( first_source );
0118       while ( nextsource ) {
0119 
0120     // make sure we are at the correct directory level by cd'ing to path
0121     nextsource->cd( path );
0122     TKey *key2 = (TKey*)gDirectory->GetListOfKeys()->FindObject(h1->GetName());
0123     if (key2) {
0124       TH1 *h2 = (TH1*)key2->ReadObj();
0125       h1->Add( h2 );
0126       delete h2;
0127     }
0128 
0129     nextsource = (TFile*)sourcelist->After( nextsource );
0130       }
0131     }
0132     else if ( obj->IsA()->InheritsFrom( TTree::Class() ) ) {
0133 
0134       // loop over all source files create a chain of Trees "globChain"
0135       const char* obj_name= obj->GetName();
0136 
0137       globChain = new TChain(obj_name);
0138       globChain->Add(first_source->GetName());
0139       TFile *nextsource = (TFile*)sourcelist->After( first_source );
0140       //      const char* file_name = nextsource->GetName();
0141       // cout << "file name  " << file_name << endl;
0142       while ( nextsource ) {
0143 
0144     globChain->Add(nextsource->GetName());
0145     nextsource = (TFile*)sourcelist->After( nextsource );
0146       }
0147 
0148     } else if ( obj->IsA()->InheritsFrom( TDirectory::Class() ) ) {
0149       // it's a subdirectory
0150 
0151       cout << "Found subdirectory " << obj->GetName() << endl;
0152 
0153       // create a new subdir of same name and title in the target file
0154       target->cd();
0155       TDirectory *newdir = target->mkdir( obj->GetName(), obj->GetTitle() );
0156 
0157       // newdir is now the starting point of another round of merging
0158       // newdir still knows its depth within the target file via
0159       // GetPath(), so we can still figure out where we are in the recursion
0160       MergeRootfile( newdir, sourcelist );
0161 
0162     } else {
0163 
0164       // object is of no type that we know or can handle
0165       cout << "Unknown object type, name: "
0166        << obj->GetName() << " title: " << obj->GetTitle() << endl;
0167     }
0168 
0169     // now write the merged histogram (which is "in" obj) to the target file
0170     // note that this will just store obj in the current directory level,
0171     // which is not persistent until the complete directory itself is stored
0172     // by "target->Write()" below
0173     if ( obj ) {
0174       target->cd();
0175 
0176       //!!if the object is a tree, it is stored in globChain...
0177       if(obj->IsA()->InheritsFrom( TTree::Class() ))
0178     globChain->Merge(target->GetFile(),0,"keep");
0179       else
0180     obj->Write( key->GetName() );
0181     }
0182 
0183   } // while ( ( TKey *key = (TKey*)nextkey() ) )
0184 
0185   // save modifications to target file
0186   target->SaveSelf(kTRUE);
0187   TH1::AddDirectory(status);
0188 }  // end 'MergeRootFiles(TDirectory*, TList*)'
0189 
0190 // End ------------------------------------------------------------------------