SFrame 3.6
core/src/SCycleBaseNTuple.cxx
Go to the documentation of this file.
00001 // $Id: SCycleBaseNTuple.cxx 335 2012-11-21 14:11:47Z krasznaa $
00002 /***************************************************************************
00003  * @Project: SFrame - ROOT-based analysis framework for ATLAS
00004  * @Package: Core
00005  *
00006  * @author Stefan Ask       <Stefan.Ask@cern.ch>           - Manchester
00007  * @author David Berge      <David.Berge@cern.ch>          - CERN
00008  * @author Johannes Haller  <Johannes.Haller@cern.ch>      - Hamburg
00009  * @author A. Krasznahorkay <Attila.Krasznahorkay@cern.ch> - CERN/Debrecen
00010  *
00011  ***************************************************************************/
00012 
00013 // System include(s):
00014 #include <string.h>
00015 
00016 // STL include(s):
00017 #include <algorithm>
00018 #include <typeinfo>
00019 
00020 // ROOT include(s):
00021 #include <TFile.h>
00022 #include <TTree.h>
00023 #include <TChain.h>
00024 #include <TBranch.h>
00025 #include <TROOT.h>
00026 #include <TList.h>
00027 #include <TFriendElement.h>
00028 #include <TVirtualIndex.h>
00029 #include <TTreeFormula.h>
00030 
00031 // Local include(s):
00032 #include "../include/SCycleBaseNTuple.h"
00033 #include "../include/SInputData.h"
00034 #include "../include/SCycleConfig.h"
00035 #include "../include/SCycleOutput.h"
00036 #include "../include/STreeType.h"
00037 
00038 static const Double_t EPSILON = 1e-15;
00039 
00040 #ifndef DOXYGEN_IGNORE
00041 ClassImp( SCycleBaseNTuple )
00042 #endif // DOXYGEN_IGNORE
00043 
00047 SCycleBaseNTuple::SCycleBaseNTuple()
00048    : SCycleBaseBase(), m_inputTrees(), m_inputBranches(),
00049      m_outputTrees(), m_metaInputTrees(), m_outputVarPointers(), m_output( 0 ) {
00050 
00051    REPORT_VERBOSE( "SCycleBaseNTuple constructed" );
00052 }
00053 
00057 SCycleBaseNTuple::~SCycleBaseNTuple() {
00058 
00059    DeleteInputVariables();
00060    REPORT_VERBOSE( "SCycleBaseNTuple destructed" );
00061 }
00062 
00063 void SCycleBaseNTuple::SetNTupleOutput( TList* output ) {
00064 
00065    m_output = output;
00066    return;
00067 }
00068 
00069 TList* SCycleBaseNTuple::GetNTupleOutput() const {
00070 
00071    return m_output;
00072 }
00073 
00085 TTree* SCycleBaseNTuple::GetMetadataTree( const char* name ) const throw( SError ) {
00086 
00087    // The result tree:
00088    TTree* result = 0;
00089 
00090    // See if this is an input tree:
00091    try {
00092       result = GetInputMetadataTree( name );
00093       return result;
00094    } catch( const SError& error ) {
00095       if( error.request() <= SError::SkipFile ) {
00096          REPORT_VERBOSE( "Input metadata tree with name \"" << name << "\" not found" );
00097       } else {
00098          REPORT_ERROR( "Exception message caught with message: " << error.what() );
00099          throw;
00100       }
00101    }
00102 
00103    // See if this is an output tree:
00104    try {
00105       result = GetOutputMetadataTree( name );
00106       return result;
00107    } catch( const SError& error ) {
00108       if( error.request() <= SError::SkipFile ) {
00109          REPORT_VERBOSE( "Output metadata tree with name \"" << name << "\" not found" );
00110       } else {
00111          REPORT_ERROR( "Exception message caught with message: " << error.what() );
00112          throw;
00113       }
00114    }
00115 
00116    //
00117    // Throw an exception if the tree hasn't been found:
00118    //
00119    SError error( SError::SkipFile );
00120    error << "Couldn't find metadata TTree with name: " << name;
00121    throw error;
00122 
00123    return result;
00124 }
00125 
00134 TTree* SCycleBaseNTuple::GetInputMetadataTree( const char* name ) const throw( SError ) {
00135 
00136    //
00137    // Strip off the directory name from the given tree name:
00138    //
00139    TString tname( name );
00140    if( tname.Contains( "/" ) ) {
00141       REPORT_VERBOSE( "Tokenizing the metadata tree name: " << tname );
00142       TObjArray* array = tname.Tokenize( "/" );
00143       TObjString* real_name = dynamic_cast< TObjString* >( array->Last() );
00144       tname = real_name->GetString();
00145       delete array;
00146    }
00147 
00148    REPORT_VERBOSE( "Looking for input metadata tree with name: " << tname );
00149 
00150    //
00151    // Look for such a metadata tree:
00152    //
00153    for( std::vector< TTree* >::const_iterator it = m_metaInputTrees.begin();
00154         it != m_metaInputTrees.end(); ++it ) {
00155       if( *it ) {
00156          if( tname == ( *it )->GetName() ) {
00157             REPORT_VERBOSE( "Found input metadata tree with name " << tname 
00158                             << " at " << ( *it ) );
00159             return *it;
00160          }
00161       }
00162    }
00163 
00164    //
00165    // Throw an exception if the tree hasn't been found:
00166    //
00167    SError error( SError::SkipFile );
00168    error << "Couldn't find input metadata TTree with name: " << tname;
00169    throw error;
00170 
00171    return 0;
00172 }
00173 
00182 TTree* SCycleBaseNTuple::GetOutputMetadataTree( const char* name ) const throw( SError ) {
00183 
00184    //
00185    // Strip off the directory name from the given tree name:
00186    //
00187    TString tname( name );
00188    if( tname.Contains( "/" ) ) {
00189       REPORT_VERBOSE( "Tokenizing the metadata tree name: " << tname );
00190       TObjArray* array = tname.Tokenize( "/" );
00191       TObjString* real_name = dynamic_cast< TObjString* >( array->Last() );
00192       tname = real_name->GetString();
00193       delete array;
00194    }
00195 
00196    REPORT_VERBOSE( "Looking for output metadata tree with name: " << tname );
00197 
00198    //
00199    // Look for such a metadata tree:
00200    //
00201    for( std::vector< TTree* >::const_iterator it = m_metaOutputTrees.begin();
00202         it != m_metaOutputTrees.end(); ++it ) {
00203       if( *it ) {
00204          if( tname == ( *it )->GetName() ) {
00205             REPORT_VERBOSE( "Found output metadata tree with name " << tname 
00206                             << " at " << ( *it ) );
00207             return *it;
00208          }
00209       }
00210    }
00211 
00212    //
00213    // Throw an exception if the tree hasn't been found:
00214    //
00215    SError error( SError::SkipFile );
00216    error << "Couldn't find input metadata TTree with name: " << tname;
00217    throw error;
00218 
00219    return 0;
00220 }
00221 
00227 TTree* SCycleBaseNTuple::GetInputTree( const char* treeName ) const throw( SError ) {
00228 
00229    //
00230    // Look for such input tree:
00231    //
00232    TString tname( treeName );
00233    for( std::vector< TTree* >::const_iterator it = m_inputTrees.begin();
00234         it != m_inputTrees.end(); ++it ) {
00235       if( *it ) {
00236          if( tname == ( *it )->GetName() ) {
00237             REPORT_VERBOSE( "Found input tree with name " << treeName 
00238                             << " at " << ( *it ) );
00239             return *it;
00240          }
00241       }
00242    }
00243 
00244    //
00245    // Throw an exception if the tree hasn't been found:
00246    //
00247    SError error( SError::SkipFile );
00248    error << "Couldn't find input TTree with name: " << treeName;
00249    throw error;
00250 
00251    return 0;
00252 }
00253 
00254 TTree* SCycleBaseNTuple::GetOutputTree( const char* treeName ) const throw( SError ) {
00255 
00256    //
00257    // Look for such output tree:
00258    //
00259    TString tname( treeName );
00260    for( std::vector< TTree* >::const_iterator it = m_outputTrees.begin();
00261         it != m_outputTrees.end(); ++it ) {
00262       if( *it ) {
00263          if( tname == ( *it )->GetName() ) {
00264             REPORT_VERBOSE( "Found output tree with name " << treeName 
00265                             << " at " << ( *it ) );
00266             return *it;
00267          }
00268       }
00269    }
00270 
00271    //
00272    // Throw an exception if the tree hasn't been found:
00273    //
00274    SError error( SError::SkipFile );
00275    error << "Couldn't find output TTree with name: " << treeName;
00276    throw error;
00277 
00278    return 0;
00279 }
00280 
00292 void SCycleBaseNTuple::CreateOutputTrees( const SInputData& iD,
00293                                           std::vector< TTree* >& outTrees,
00294                                           TFile* outputFile ) throw( SError ) {
00295 
00296    // sanity checks
00297    if( outTrees.size() ) {
00298       m_logger << WARNING << "Vector of output trees is not empty in "
00299                << "\"CreateOutputTrees\"!"  << SLogger::endmsg;
00300    }
00301 
00302    // Clear the vector of output trees:
00303    m_outputTrees.clear();
00304    m_metaOutputTrees.clear();
00305 
00306    // Clear the vector of output variable pointers:
00307    m_outputVarPointers.clear();
00308 
00309    const std::vector< STree >* sOutTree = iD.GetTrees( STreeType::OutputSimpleTree );
00310 
00311    // Open output file / create output trees
00312    gROOT->cd();
00313 
00314    //
00315    // Create all the regular output trees, but don't create any branches in them
00316    // just yet.
00317    //
00318    const Int_t branchStyle = 1;
00319    const Int_t autoSave = 10000000;
00320    if( sOutTree ) {
00321       for( std::vector< STree >::const_iterator st = sOutTree->begin();
00322            st != sOutTree->end(); ++st ) {
00323 
00324          m_logger << DEBUG << "Creating output event tree with name: "
00325                   << st->treeName << SLogger::endmsg;
00326 
00327          TTree* tree = new TTree( st->treeName.Data(), TString( "Format: User" ) +
00328                                   ", data type: " + iD.GetType() );
00329 
00330          tree->SetAutoSave( autoSave );
00331          TTree::SetBranchStyle( branchStyle );
00332 
00333          outTrees.push_back( tree );
00334          m_outputTrees.push_back( tree );
00335 
00336          if( outputFile ) {
00337             tree->SetDirectory( outputFile );
00338             REPORT_VERBOSE( "Attached TTree \"" << st->treeName.Data()
00339                             << "\" to file: " << outputFile->GetName() );
00340          } else {
00341             SCycleOutput* out = new SCycleOutput( tree, st->treeName );
00342             m_output->Add( out );
00343             REPORT_VERBOSE( "Keeping TTree \"" << st->treeName.Data()
00344                             << "\" in memory" );
00345          }
00346       }
00347    }
00348 
00349    //
00350    // Create the metadata output trees. These don't have to be reported back to the
00351    // caller, since the user will be responsible for filling them.
00352    //
00353    const std::vector< STree >* sMetaTrees = iD.GetTrees( STreeType::OutputMetaTree );
00354    if( sMetaTrees ) {
00355       for( std::vector< STree >::const_iterator mt = sMetaTrees->begin();
00356            mt != sMetaTrees->end(); ++mt ) {
00357 
00358          //
00359          // Split the name into the name of the tree and the name of the
00360          // directory:
00361          //
00362          TString tname( mt->treeName ), dirname( "" );
00363          if( tname.Contains( "/" ) ) {
00364             REPORT_VERBOSE( "Tokenizing the metadata tree name: " << tname );
00365             TObjArray* array = tname.Tokenize( "/" );
00366             TObjString* real_name = dynamic_cast< TObjString* >( array->Last() );
00367             tname = real_name->GetString();
00368             if( array->GetSize() > 1 ) {
00369                for( Int_t i = 0; i < array->GetSize() - 1; ++i ) {
00370                   TObjString* dirletname = dynamic_cast< TObjString* >( array->At( i ) );
00371                   if( ! dirletname ) continue;
00372                   if( dirletname->GetString() == "" ) continue;
00373                   if( dirletname->GetString() == tname ) break;
00374                   dirname += ( dirname == "" ? dirletname->GetString() : "/" + dirletname->GetString() );
00375                }
00376             }
00377             delete array;
00378          }
00379 
00380          m_logger << DEBUG << "Creating output metadata tree with name: "
00381                   << tname  << " in directory: " << dirname << SLogger::endmsg;
00382 
00383          TTree* tree = new TTree( tname, TString( "Format: User" ) +
00384                                   ", data type: " + iD.GetType() );
00385 
00386          tree->SetAutoSave( autoSave );
00387          TTree::SetBranchStyle( branchStyle );
00388 
00389          m_metaOutputTrees.push_back( tree );
00390 
00391          if( outputFile ) {
00392             tree->SetDirectory( MakeSubDirectory( dirname, outputFile ) );
00393             REPORT_VERBOSE( "Attached TTree \"" << mt->treeName
00394                             << "\" to file: " << outputFile->GetName() );
00395          } else {
00396             SCycleOutput* out = new SCycleOutput( tree, tname, dirname );
00397             m_output->Add( out );
00398             REPORT_VERBOSE( "Keeping TTree \"" << mt->treeName
00399                             << "\" in memory" );
00400          }
00401       }
00402    }
00403 
00404    return;
00405 }
00406 
00415 void SCycleBaseNTuple::SaveOutputTrees( TDirectory* /*output*/ ) throw( SError ) {
00416 
00417    // Remember which directory we were in:
00418    TDirectory* savedir = gDirectory;
00419 
00420    // Save each regular output tree:
00421    for( std::vector< TTree* >::iterator tree = m_outputTrees.begin();
00422         tree != m_outputTrees.end(); ++tree ) {
00423       TDirectory* dir = ( *tree )->GetDirectory();
00424       if( dir ) dir->cd();
00425       ( *tree )->Write();
00426       ( *tree )->AutoSave();
00427       ( *tree )->SetDirectory( 0 );
00428       delete ( *tree );
00429    }
00430 
00431    // Save each metadata output tree:
00432    for( std::vector< TTree* >::iterator tree = m_metaOutputTrees.begin();
00433         tree != m_metaOutputTrees.end(); ++tree ) {
00434       TDirectory* dir = ( *tree )->GetDirectory();
00435       if( dir ) dir->cd();
00436       ( *tree )->Write();
00437       ( *tree )->AutoSave();
00438       ( *tree )->SetDirectory( 0 );
00439       delete ( *tree );
00440    }
00441 
00442    // Go back to the original directory:
00443    gDirectory = savedir;
00444 
00445    return;
00446 }
00447 
00459 void SCycleBaseNTuple::LoadInputTrees( const SInputData& iD,
00460                                        TTree* main_tree,
00461                                        TFile*& inputFile ) throw( SError ) {
00462 
00463    REPORT_VERBOSE( "Loading/accessing the event-level input trees" );
00464 
00465    //
00466    // Initialize some variables:
00467    //
00468    const std::vector< STree >* sInTree = iD.GetTrees( STreeType::InputSimpleTree );
00469    const std::vector< STree >* sMetaTree = iD.GetTrees( STreeType::InputMetaTree );
00470    Bool_t firstPassed = kFALSE;
00471    Int_t nEvents = 0;
00472    m_inputTrees.clear();
00473    m_inputBranches.clear();
00474    DeleteInputVariables();
00475    m_metaInputTrees.clear();
00476 
00477    //
00478    // Access the physical file that is currently being opened:
00479    //
00480    inputFile = 0;
00481    if( GetConfig().GetRunMode() == SCycleConfig::LOCAL ) {
00482       TChain* chain = dynamic_cast< TChain* >( main_tree );
00483       if( ! chain ) {
00484          throw SError( "In LOCAL running the input TTree is not a TChain!",
00485                        SError::StopExecution );
00486       }
00487       inputFile = chain->GetFile();
00488    } else if( GetConfig().GetRunMode() == SCycleConfig::PROOF ) {
00489       inputFile = main_tree->GetCurrentFile();
00490    } else {
00491       throw SError( "Running mode not recongnised", SError::SkipCycle );
00492       return;
00493    }
00494    if( ! inputFile ) {
00495       throw SError( "Couldn't get the input file pointer!", SError::SkipFile );
00496       return;
00497    }
00498    REPORT_VERBOSE( "Accessed the pointer to the input file: " << inputFile );
00499 
00500    //
00501    // Handle the regular input trees:
00502    //
00503    if( sInTree ) {
00504       for( std::vector< STree >::const_iterator st = sInTree->begin(); st != sInTree->end();
00505            ++st ) {
00506 
00507          REPORT_VERBOSE( "Now trying to access TTree: " << st->treeName );
00508 
00509          TTree* tree = dynamic_cast< TTree* >( inputFile->Get( st->treeName ) );
00510          if( ! tree ) {
00511             SError error( SError::SkipFile );
00512             error << "Tree " << st->treeName << " doesn't exist in File "
00513                   << inputFile->GetName();
00514             throw error;
00515          }
00516 
00517          // do we need this at all now that we loop over the branches
00518          // one-by-one?
00519          
00520          // Remove friends if any, for better performance
00521          bool skipFriends = true; // can be made configurable
00522          if( skipFriends ) {
00523             TList* flist = tree->GetListOfFriends();
00524             TIter nextf( flist );
00525             TFriendElement* fe = 0;
00526             while( ( fe = ( TFriendElement* ) nextf() ) ) {
00527                m_logger << DEBUG << "Remove friend " << fe->GetName() << " from tree " 
00528                         << tree->GetName() << SLogger::endmsg;
00529                flist->Remove( fe );
00530                delete fe;
00531                fe = 0;
00532             }
00533          }
00534          // Delete index if any, for better performance
00535          bool deleteIndex = true; // can be made configurable
00536          if( deleteIndex ) {
00537             if( tree->GetTreeIndex() ) {
00538                m_logger << DEBUG << "Delete index from tree " 
00539                         << tree->GetName() << SLogger::endmsg;
00540                tree->SetTreeIndex( 0 );
00541                delete tree->GetTreeIndex();
00542             }
00543          }
00544 
00545          m_inputTrees.push_back( tree );
00546          if( firstPassed && tree->GetEntries() != nEvents ) {
00547             SError error( SError::SkipFile );
00548             error << "Conflict in number of entries - Tree " << tree->GetName()
00549                   << " has " << tree->GetEntries() << ", NOT "
00550                   << nEvents;
00551             throw error;
00552          } else if( ! firstPassed ) {
00553             firstPassed = kTRUE;
00554             nEvents = tree->GetEntries();
00555          }
00556       }
00557    }
00558 
00559    //
00560    // Handle the metadata trees:
00561    //
00562    if( sMetaTree ) {
00563       for( std::vector< STree >::const_iterator mt = sMetaTree->begin();
00564            mt != sMetaTree->end(); ++mt ) {
00565 
00566          TTree* tree = dynamic_cast< TTree* >( inputFile->Get( mt->treeName ) );
00567          if( ! tree ) {
00568             SError error( SError::SkipFile );
00569             error << "Tree " << mt->treeName << " doesn't exist in File "
00570                   << inputFile->GetName();
00571             throw error;
00572          } else {
00573             m_metaInputTrees.push_back( tree );
00574          }
00575       }
00576    }
00577 
00578    return;
00579 }
00580 
00589 void SCycleBaseNTuple::GetEvent( Long64_t entry ) throw( SError ) {
00590 
00591    // Tell all trees to update their cache:
00592    for( std::vector< TTree* >::const_iterator it = m_inputTrees.begin();
00593         it != m_inputTrees.end(); ++it ) {
00594       ( *it )->LoadTree( entry );
00595    }
00596 
00597    // Load the current entry for all the regular input variables:
00598    for( std::vector< TBranch* >::const_iterator it = m_inputBranches.begin();
00599         it != m_inputBranches.end(); ++it ) {
00600       ( *it )->GetEntry( entry );
00601    }
00602 
00603    return;
00604 }
00605 
00614 Double_t SCycleBaseNTuple::CalculateWeight( const SInputData& inputData,
00615                                             Long64_t entry ) {
00616 
00617    // the type of this input data
00618    const TString& type    = inputData.GetType();
00619    const TString& version = inputData.GetVersion();
00620 
00621    Double_t weight = 0.;
00622    Double_t totlum = 0.;
00623 
00624    if( inputData.GetType() == "data" ) {
00625       REPORT_VERBOSE( "Data" );
00626       weight = 1.;
00627       return weight;
00628    }
00629 
00630    //iterate over vector of input data and addup the weight for the type of this input data
00631    for( std::vector< SInputData >::const_iterator iD = GetConfig().GetInputData().begin();
00632         iD != GetConfig().GetInputData().end(); ++iD ) {
00633 
00634       if( ( iD->GetType() == type ) && ( iD->GetVersion() == version ) ) {
00635 
00636          const std::vector< SGeneratorCut >& sgencuts = iD->GetSGeneratorCuts();
00637          Bool_t inside = kTRUE;
00638 
00639          for( std::vector< SGeneratorCut >::const_iterator sgc = sgencuts.begin();
00640               sgc != sgencuts.end(); ++sgc ) {
00641           
00642             // loop over the trees 
00643             for( std::vector< TTree* >::const_iterator it = m_inputTrees.begin();
00644                  it != m_inputTrees.end(); ++it ) {
00645 
00646                // consider the one with the correct name
00647                if( ( *it )->GetName() == sgc->GetTreeName() ) {
00648                   // check for this entry, if Formula is true  
00649                   TString teststring = sgc->GetFormula();
00650                   TTreeFormula f( "testFormula", teststring.Data(), *it );
00651                   // if true for all cuts, then add the Lumi of this input data to totlum
00652                   if( ! f.EvalInstance( entry ) ) inside = kFALSE;
00653                   break;
00654                }
00655 
00656             }
00657          }
00658          if( inside ) totlum += iD->GetScaledLumi();
00659       }
00660    }
00661 
00662    if( totlum > EPSILON ) 
00663       weight = ( GetConfig().GetTargetLumi() / totlum );
00664   
00665    return weight;
00666 }
00667 
00673 void SCycleBaseNTuple::ClearCachedTrees() {
00674 
00675    m_inputTrees.clear();
00676    m_inputBranches.clear();
00677    m_outputTrees.clear();
00678    m_metaInputTrees.clear();
00679    m_metaOutputTrees.clear();
00680 
00681    DeleteInputVariables();
00682 
00683    return;
00684 }
00685 
00696 const char* SCycleBaseNTuple::RootType( const char* typeid_type ) throw( SError ) {
00697 
00698    if( strlen( typeid_type ) != 1 ) {
00699       throw SError( "SCycleBaseNTuple::RootType received complex object description",
00700                     SError::StopExecution );
00701    }
00702 
00703    switch( typeid_type[ 0 ] ) {
00704 
00705    case 'c':
00706       return "B";
00707       break;
00708    case 'h':
00709       return "b";
00710       break;
00711    case 's':
00712       return "S";
00713       break;
00714    case 't':
00715       return "s";
00716       break;
00717    case 'i':
00718       return "I";
00719       break;
00720    case 'j':
00721       return "i";
00722       break;
00723    case 'f':
00724       return "F";
00725       break;
00726    case 'd':
00727       return "D";
00728       break;
00729    case 'x':
00730       return "L";
00731       break;
00732    case 'y':
00733       return "l";
00734       break;
00735    case 'b':
00736       return "O";
00737       break;
00738 
00739    }
00740 
00741    throw SError( "Unknown primitive type encountered: " + TString( typeid_type ),
00742                  SError::StopExecution );
00743    return "";
00744 }
00745 
00753 const char* SCycleBaseNTuple::TypeidType( const char* root_type ) throw( SError ) {
00754 
00755    if( ! strcmp( root_type, "Char_t" ) ) {
00756       return "c";
00757    } else if( ! strcmp( root_type, "UChar_t" ) ) {
00758       return "h";
00759    } else if( ! strcmp( root_type, "Short_t" ) ) {
00760       return "s";
00761    } else if( ! strcmp( root_type, "UShort_t" ) ) {
00762       return "t";
00763    } else if( ! strcmp( root_type, "Int_t" ) ) {
00764       return "i";
00765    } else if( ! strcmp( root_type, "UInt_t" ) ) {
00766       return "j";
00767    } else if( ! strcmp( root_type, "Float_t" ) ) {
00768       return "f";
00769    } else if( ! strcmp( root_type, "Double_t" ) ) {
00770       return "d";
00771    } else if( ! strcmp( root_type, "Long64_t" ) ) {
00772       return "x";
00773    } else if( ! strcmp( root_type, "ULong64_t" ) ) {
00774       return "y";
00775    } else if( ! strcmp( root_type, "Bool_t" ) ) {
00776       return "b";
00777    }
00778 
00779    throw SError( "Unknown ROOT primitive type encountered: " + TString( root_type ),
00780                  SError::StopExecution );
00781    return "";
00782 }
00783 
00788 void SCycleBaseNTuple::RegisterInputBranch( TBranch* br ) throw( SError ) {
00789 
00790    if( std::find( m_inputBranches.begin(), m_inputBranches.end(), br ) !=
00791        m_inputBranches.end() ) {
00792       m_logger << DEBUG << "Branch '" << br->GetName() << "' already registered!"
00793                << SLogger::endmsg;
00794    } else {
00795       m_inputBranches.push_back( br );
00796    }
00797 
00798    return;
00799 }
00800 
00807 void SCycleBaseNTuple::DeleteInputVariables() {
00808 
00809    for( std::list< TObject* >::iterator it = m_inputVarPointers.begin();
00810         it != m_inputVarPointers.end(); ++it ) {
00811       delete ( *it );
00812    }
00813    m_inputVarPointers.clear();
00814 
00815    return;
00816 }
00817 
00826 TDirectory*
00827 SCycleBaseNTuple::MakeSubDirectory( const TString& path,
00828                                     TDirectory* dir ) const throw( SError ) {
00829 
00830    if( ! path.Length() ) return dir;
00831 
00832    TDirectory* result = 0;
00833    if( ! ( result = dir->GetDirectory( path ) ) ) {
00834 
00835       REPORT_VERBOSE( "Creating directory: "
00836                       << dir->GetPath() << "/" << path );
00837 
00838       //
00839       // Break up the path name at the slashes:
00840       //
00841       TObjArray* directories = path.Tokenize( "/" );
00842 
00843       //
00844       // Create each necessary directory:
00845       //
00846       result = dir;
00847       TDirectory* tempDir = 0;
00848       for( Int_t i = 0; i < directories->GetSize(); ++i ) {
00849 
00850          TObjString* path_element = dynamic_cast< TObjString* >( directories->At( i ) );
00851          if( ! path_element ) continue;
00852          if( path_element->GetString() == "" ) continue;
00853 
00854          REPORT_VERBOSE( "Accessing directory: " << path_element->GetString() );
00855          if( ! ( tempDir = result->GetDirectory( path_element->GetString() ) ) ) {
00856             REPORT_VERBOSE( "Directory doesn't exist, creating it..." );
00857             if( ! ( tempDir = result->mkdir( path_element->GetString(), "dummy title" ) ) ) {
00858                SError error( SError::SkipInputData );
00859                error << "Couldn't create directory: " << path
00860                      << " in the output file!";
00861                throw error;
00862             }
00863          }
00864          result = tempDir;
00865 
00866       }
00867 
00868       // Delete the object created by TString::Tokenize(...):
00869       delete directories;
00870 
00871    }
00872 
00873    return result;
00874 }