ROOT logo
// @(#)root/tree:$Id: TTreeCloner.cxx 27252 2009-01-27 04:02:16Z pcanal $
// Author: Philippe Canal 07/11/2005

/*************************************************************************
 * Copyright (C) 1995-2000, Rene Brun and Fons Rademakers.               *
 * All rights reserved.                                                  *
 *                                                                       *
 * For the licensing terms see $ROOTSYS/LICENSE.                         *
 * For the list of contributors see $ROOTSYS/README/CREDITS.             *
 *************************************************************************/

//////////////////////////////////////////////////////////////////////////
//                                                                      //
// TTreeCloner                                                          //
//                                                                      //
// Class implementing or helping  the various TTree cloning method      //
//                                                                      //
//////////////////////////////////////////////////////////////////////////

#include "TBasket.h"
#include "TBranch.h"
#include "TBranchClones.h"
#include "TBranchElement.h"
#include "TStreamerInfo.h"
#include "TBranchRef.h"
#include "TError.h"
#include "TProcessID.h"
#include "TMath.h"
#include "TTree.h"
#include "TTreeCloner.h"
#include "TFile.h"
#include "TLeafB.h"
#include "TLeafI.h"
#include "TLeafL.h"

TTreeCloner::TTreeCloner(TTree *from, TTree *to, Option_t *method) :
   fIsValid(kTRUE),
   fFromTree(from),
   fToTree(to),
   fMethod(method),
   fFromBranches( from ? from->GetListOfLeaves()->GetEntries()+1 : 0),
   fToBranches( to ? from->GetListOfLeaves()->GetEntries()+1 : 0),
   fMaxBaskets(CollectBranches()),
   fBasketBranchNum(new UInt_t[fMaxBaskets]),
   fBasketNum(new UInt_t[fMaxBaskets]),
   fBasketSeek(new Long64_t[fMaxBaskets]),
   fBasketEntry(new Long64_t[fMaxBaskets]),
   fBasketIndex(new UInt_t[fMaxBaskets]),
   fCloneMethod(TTreeCloner::kDefault),
   fToStartEntries(0)
{
   // Constructor.  This object would transfer the data from
   // 'from' to 'to' using the method indicated in method.
   //
   // The value of the parameter 'method' determines in which 
   // order the branches' baskets are written to the output file.
   //
   // When a TTree is filled the data is stored in the individual
   // branches' basket.  Each basket is written individually to 
   // the disk as soon as it is full.  In consequence the baskets 
   // of branches that contain 'large' data chunk are written to
   // the disk more often.
   //
   // There is currently 3 supported sorting order:
   //    SortBasketsByOffset (the default)
   //    SortBasketsByBranch
   //    SortBasketsByEntry
   //
   // When using SortBasketsByOffset the baskets are written in
   // the output file in the same order as in the original file
   // (i.e. the basket are sorted on their offset in the original
   // file; Usually this also means that the baskets are sorted
   // on the index/number of the _last_ entry they contain)
   // 
   // When using SortBasketsByBranch all the baskets of each 
   // individual branches are stored contiguously.  This tends to 
   // optimize reading speed when reading a small number (1->5) of 
   // branches, since all their baskets will be clustered together 
   // instead of being spread across the file.  However it might
   // decrease the performance when reading more branches (or the full 
   // entry).
   // 
   // When using SortBasketsByEntry the baskets with the lowest
   // starting entry are written first.  (i.e. the baskets are 
   // sorted on the index/number of the first entry they contain). 
   // This means that on the file the baskets will be in the order
   // in which they will be needed when reading the whole tree
   // sequentially.
   //

   TString opt(method);
   opt.ToLower();
   if (opt.Contains("sortbasketsbybranch")) {
      //::Info("TTreeCloner::TTreeCloner","use: kSortBasketsByBranch");
      fCloneMethod = TTreeCloner::kSortBasketsByBranch;
   } else if (opt.Contains("sortbasketsbyentry")) {
      //::Info("TTreeCloner::TTreeCloner","use: kSortBasketsByEntry");
      fCloneMethod = TTreeCloner::kSortBasketsByEntry;
   } else {
      //::Info("TTreeCloner::TTreeCloner","use: kSortBasketsByOffset");
      fCloneMethod = TTreeCloner::kSortBasketsByOffset;
   }
   if (fToTree) fToStartEntries = fToTree->GetEntries();
}

Bool_t TTreeCloner::Exec()
{
   // Execute the cloning.

   CopyStreamerInfos();
   CopyProcessIds();
   CloseOutWriteBaskets();
   CollectBaskets();
   SortBaskets();
   WriteBaskets();
   CopyMemoryBaskets();

   return kTRUE;
}

TTreeCloner::~TTreeCloner()
{
   // TTreeCloner destructor

   delete [] fBasketBranchNum;
   delete [] fBasketNum;
   delete [] fBasketSeek;
   delete [] fBasketEntry;
   delete [] fBasketIndex;
}

void TTreeCloner::CloseOutWriteBaskets()
{
   // Before we can start adding new basket, we need to flush to
   // disk the partially filled baskets (the WriteBasket)

   for(Int_t i=0; i<fToBranches.GetEntries(); ++i) {
      TBranch *to = (TBranch*)fToBranches.UncheckedAt(i);
      to->FlushOneBasket(to->GetWriteBasket());
   }
}

UInt_t TTreeCloner::CollectBranches(TBranch *from, TBranch *to)
{
   // Fill the array of branches, adding the branch 'from' and 'to',
   // and matching the sub-branches of the 'from' and 'to' branches.
   // Returns the total number of baskets in all the from branch and
   // it sub-branches.

   // Since this is called from the constructor, this can not be a virtual function

   UInt_t numBaskets = 0;
   if (from->InheritsFrom(TBranchClones::Class())) {
      TBranchClones *fromclones = (TBranchClones*)from;
      TBranchClones *toclones = (TBranchClones*)to;
      numBaskets += CollectBranches(fromclones->fBranchCount,toclones->fBranchCount);
   
   } else if (from->InheritsFrom(TBranchElement::Class())) {
      Int_t nb = from->GetListOfLeaves()->GetEntries();
      Int_t fnb= to->GetListOfLeaves()->GetEntries();
      if (nb!=fnb && (nb==0 || fnb==0)) {
         // We might be in the case where one branch is split
         // while the other is not split.  We must reject this match.
         Error("TTreeCloner::CollectBranches",
               "The export branch and the import branch do not have the same split level. (The branch name is %s.)", 	 
               from->GetName());
         fIsValid = kFALSE;
         return 0;
      }

      TBranchElement *fromelem = (TBranchElement*)from;
      TBranchElement *toelem   = (TBranchElement*)to;
      if (fromelem->fMaximum > toelem->fMaximum) toelem->fMaximum = fromelem->fMaximum;
   } else {

      Int_t nb = from->GetListOfLeaves()->GetEntries();
      Int_t fnb= to->GetListOfLeaves()->GetEntries();
      if (nb!=fnb) {
         Error("TTreeCloner::CollectBranches",
            "The export branch and the import branch (%s) do not have the same number of leaves (%d vs %d)",
            from->GetName(), fnb,nb);
         fIsValid = kFALSE;
         return 0;
      }
      for (Int_t i=0;i<nb;i++)  {
         TLeaf *fromleaf_gen = (TLeaf*)from->GetListOfLeaves()->At(i);
         if (fromleaf_gen->IsA()==TLeafI::Class()) {
            TLeafI *fromleaf = (TLeafI*)from->GetListOfLeaves()->At(i);
            TLeafI *toleaf   = (TLeafI*)to->GetListOfLeaves()->At(i);
            if (fromleaf->GetMaximum() > toleaf->GetMaximum()) 
               toleaf->SetMaximum( fromleaf->GetMaximum() );
            if (fromleaf->GetMinimum() < toleaf->GetMinimum()) 
               toleaf->SetMinimum( fromleaf->GetMinimum() );
         } else if (fromleaf_gen->IsA()==TLeafL::Class()) {
            TLeafL *fromleaf = (TLeafL*)from->GetListOfLeaves()->At(i);
            TLeafL *toleaf   = (TLeafL*)to->GetListOfLeaves()->At(i);
            if (fromleaf->GetMaximum() > toleaf->GetMaximum()) 
               toleaf->SetMaximum( fromleaf->GetMaximum() );
            if (fromleaf->GetMinimum() < toleaf->GetMinimum()) 
               toleaf->SetMinimum( fromleaf->GetMinimum() );
         } else if (fromleaf_gen->IsA()==TLeafB::Class()) {
            TLeafB *fromleaf = (TLeafB*)from->GetListOfLeaves()->At(i);
            TLeafB *toleaf   = (TLeafB*)to->GetListOfLeaves()->At(i);
            if (fromleaf->GetMaximum() > toleaf->GetMaximum()) 
               toleaf->SetMaximum( fromleaf->GetMaximum() );
            if (fromleaf->GetMinimum() < toleaf->GetMinimum()) 
               toleaf->SetMinimum( fromleaf->GetMinimum() );
         }
      }

   }

   fFromBranches.AddLast(from);
   fToBranches.AddLast(to);

   numBaskets += from->GetWriteBasket();
   numBaskets += CollectBranches(from->GetListOfBranches(),to->GetListOfBranches());

   return numBaskets;
}

UInt_t TTreeCloner::CollectBranches(TObjArray *from, TObjArray *to)
{
   // Fill the array of branches, matching the branches of the 'from' and 'to' arrays.
   // Returns the total number of baskets in all the branches.

   // Since this is called from the constructor, this can not be a virtual function

   Int_t fnb = from->GetEntries();
   Int_t tnb = to->GetEntries();
   if (!fnb || !tnb) {
      return 0;
   }

   UInt_t numBasket = 0;
   Int_t fi = 0;
   Int_t ti = 0;
   while (ti < tnb) {
      TBranch* fb = (TBranch*) from->UncheckedAt(fi);
      TBranch* tb = (TBranch*) to->UncheckedAt(ti);
      Int_t firstfi = fi;
      while (strcmp(fb->GetName(), tb->GetName())) {
         ++fi;
         if (fi >= fnb) {
            // continue at the beginning
            fi = 0;
         }
         if (fi==firstfi) {
            // We tried all the branches and there is not match.
            fb = 0;
            break;
         }
         fb = (TBranch*) from->UncheckedAt(fi);
      }
      if (fb) {
         numBasket += CollectBranches(fb, tb);
         ++fi;
         if (fi >= fnb) {
           fi = 0;
         }
      }
      ++ti;
   }
   return numBasket;
}


UInt_t TTreeCloner::CollectBranches()
{
   // Fill the array of branches, matching the branches of the 'from' and 'to' TTrees
   // Returns the total number of baskets in all the branches.

   // Since this is called from the constructor, this can not be a virtual function

   UInt_t numBasket = CollectBranches(fFromTree->GetListOfBranches(),
                                      fToTree->GetListOfBranches());

   if (fFromTree->GetBranchRef()) {
      fToTree->BranchRef();
      numBasket += CollectBranches(fFromTree->GetBranchRef(),fToTree->GetBranchRef());
   }
   return numBasket;
}

void TTreeCloner::CollectBaskets()
{
   // Collect the information about the on-file basket that need
   // to be copied.

   UInt_t len = fFromBranches.GetEntries();

   for(UInt_t i=0,bi=0; i<len; ++i) {
      TBranch *from = (TBranch*)fFromBranches.UncheckedAt(i);
      for(Int_t b=0; b<from->GetWriteBasket(); ++b,++bi) {
         fBasketBranchNum[bi] = i;
         fBasketNum[bi] = b;
         fBasketSeek[bi] = from->GetBasketSeek(b);
         fBasketEntry[bi] = from->GetBasketEntry()[b];
         fBasketIndex[bi] = bi;
      }
   }
}

void TTreeCloner::CopyStreamerInfos()
{
   // Make sure that all the needed TStreamerInfo are
   // present in the output file

   TFile *fromFile = fFromTree->GetDirectory()->GetFile();
   TFile *toFile = fToTree->GetDirectory()->GetFile();
   TList *l = fromFile->GetStreamerInfoList();
   TIter next(l);
   TStreamerInfo *oldInfo;
   while ( (oldInfo = (TStreamerInfo*)next()) ) {
      TStreamerInfo *curInfo = 0;
      TClass *cl = TClass::GetClass(oldInfo->GetName());

      if ((cl->IsLoaded() && (cl->GetNew()!=0 || cl->HasDefaultConstructor()))
          || !cl->IsLoaded())  {
         // Insure that the TStreamerInfo is loaded
         curInfo = (TStreamerInfo*)cl->GetStreamerInfo(oldInfo->GetClassVersion());
         if (oldInfo->GetClassVersion()==1) {
            // We may have a Foreign class let's look using the
            // checksum:
            TStreamerInfo *matchInfo = (TStreamerInfo*)cl->FindStreamerInfo(oldInfo->GetCheckSum());
            if (matchInfo) {
               curInfo = matchInfo;
            }
         }
         curInfo->TagFile(toFile);
      } else {
         // If there is no default constructor the GetStreamerInfo
         // will not work. It also means (hopefully) that an
         // inheriting class has a streamerInfo in the list (which
         // will induces the setting of this streamerInfo)

         oldInfo->TagFile(toFile);
      }
   }
   delete l;
}

void TTreeCloner::CopyMemoryBaskets()
{
   // Transfer the basket from the input file to the output file

   TBasket *basket = 0;
   for(Int_t i=0; i<fToBranches.GetEntries(); ++i) {
      TBranch *from = (TBranch*)fFromBranches.UncheckedAt( i );
      TBranch *to   = (TBranch*)fToBranches.UncheckedAt( i );

      basket = from->GetListOfBaskets()->GetEntries() ? from->GetBasket(from->GetWriteBasket()) : 0;
      if (basket) {
         basket = (TBasket*)basket->Clone();
         basket->SetBranch(to);
         to->AddBasket(*basket, kFALSE, fToStartEntries+from->GetBasketEntry()[from->GetWriteBasket()]);
      } else {
         to->AddLastBasket(  fToStartEntries+from->GetBasketEntry()[from->GetWriteBasket()] );
      }
      // In older files, if the branch is a TBranchElement non-terminal 'object' branch, it's basket will contain 0
      // events, in newer file in the same case, the write basket will be missing.
      if (from->GetEntries()!=0 && from->GetWriteBasket()==0 && (basket==0 || basket->GetNevBuf()==0)) {
         to->SetEntries(to->GetEntries()+from->GetEntries());
      }
   }
}

void TTreeCloner::CopyProcessIds()
{
   // Make sure that all the needed TStreamerInfo are
   // present in the output file

   // NOTE: We actually need to merge the ProcessId somehow :(

   TFile *fromfile = fFromTree->GetDirectory()->GetFile();
   TFile *tofile = fToTree->GetDirectory()->GetFile();

   fPidOffset = tofile->GetNProcessIDs();

   TIter next(fromfile->GetListOfKeys());
   TKey *key;
   TDirectory::TContext cur(gDirectory,fromfile);
   while ((key = (TKey*)next())) {
      if (!strcmp(key->GetClassName(),"TProcessID")) {
         TProcessID *pid = (TProcessID*)key->ReadObjectAny(0);

         //UShort_t out = TProcessID::WriteProcessID(id,tofile);
         UShort_t out = 0;
         TObjArray *pids = tofile->GetListOfProcessIDs();
         Int_t npids = tofile->GetNProcessIDs();
         Bool_t wasIn = kFALSE;
         for (Int_t i=0;i<npids;i++) {
            if (pids->At(i) == pid) {out = (UShort_t)i; wasIn = kTRUE; break;}
         }

         if (!wasIn) {
            TDirectory *dirsav = gDirectory;
            tofile->cd();
            tofile->SetBit(TFile::kHasReferences);
            pids->AddAtAndExpand(pid,npids);
            pid->IncrementCount();
            char name[32];
            sprintf(name,"ProcessID%d",npids);
            pid->Write(name);
            tofile->IncrementProcessIDs();
            if (gDebug > 0) {
               printf("WriteProcessID, name=%s, file=%s\n",name,tofile->GetName());
            }
            if (dirsav) dirsav->cd();
            out = (UShort_t)npids;
         }
         if (out<fPidOffset) {
            Error("CopyProcessIDs","Copied %s from %s might already exist!\n",
                  pid->GetName(),fromfile->GetName());
         }
      }
   }
}

void TTreeCloner::SortBaskets()
{
   // Sort the basket according to the user request.

   // Currently this sort __has to__ preserve the order
   // of basket for each individual branch.

   switch (fCloneMethod) {
      case kSortBasketsByBranch:
         // nothing to do, it is already sorted.
         break;
      case kSortBasketsByEntry:
         TMath::Sort( fMaxBaskets, fBasketEntry, fBasketIndex, kFALSE );
         break;
      case kSortBasketsByOffset:
      default:
         TMath::Sort( fMaxBaskets, fBasketSeek, fBasketIndex, kFALSE );
         break;
   }
}

void TTreeCloner::WriteBaskets()
{
   // Transfer the basket from the input file to the output file

   TBasket *basket = new TBasket();
   for(UInt_t j=0; j<fMaxBaskets; ++j) {
      TBranch *from = (TBranch*)fFromBranches.UncheckedAt( fBasketBranchNum[ fBasketIndex[j] ] );
      TBranch *to   = (TBranch*)fToBranches.UncheckedAt( fBasketBranchNum[ fBasketIndex[j] ] );

      TFile *tofile = to->GetFile(0);
      TFile *fromfile = from->GetFile(0);

      Int_t index = fBasketNum[ fBasketIndex[j] ];

      Long64_t pos = from->GetBasketSeek(index);
      if (pos!=0) {
         if (from->GetBasketBytes()[index] == 0) {
            from->GetBasketBytes()[index] = basket->ReadBasketBytes(pos, fromfile);
         }
         Int_t len = from->GetBasketBytes()[index];

         basket->LoadBasketBuffers(pos,len,fromfile);
         basket->IncrementPidOffset(fPidOffset);
         basket->CopyTo(tofile);
         to->AddBasket(*basket,kTRUE,fToStartEntries + from->GetBasketEntry()[index]);
      } else {
         TBasket *frombasket = from->GetBasket( index );
         if (frombasket->GetNevBuf()>0) {
            TBasket *tobasket = (TBasket*)frombasket->Clone();
            tobasket->SetBranch(to);
            to->AddBasket(*tobasket, kFALSE, fToStartEntries+from->GetBasketEntry()[index]);
            to->FlushOneBasket(to->GetWriteBasket());
         }
      }
   }
   delete basket;
}
 TTreeCloner.cxx:1
 TTreeCloner.cxx:2
 TTreeCloner.cxx:3
 TTreeCloner.cxx:4
 TTreeCloner.cxx:5
 TTreeCloner.cxx:6
 TTreeCloner.cxx:7
 TTreeCloner.cxx:8
 TTreeCloner.cxx:9
 TTreeCloner.cxx:10
 TTreeCloner.cxx:11
 TTreeCloner.cxx:12
 TTreeCloner.cxx:13
 TTreeCloner.cxx:14
 TTreeCloner.cxx:15
 TTreeCloner.cxx:16
 TTreeCloner.cxx:17
 TTreeCloner.cxx:18
 TTreeCloner.cxx:19
 TTreeCloner.cxx:20
 TTreeCloner.cxx:21
 TTreeCloner.cxx:22
 TTreeCloner.cxx:23
 TTreeCloner.cxx:24
 TTreeCloner.cxx:25
 TTreeCloner.cxx:26
 TTreeCloner.cxx:27
 TTreeCloner.cxx:28
 TTreeCloner.cxx:29
 TTreeCloner.cxx:30
 TTreeCloner.cxx:31
 TTreeCloner.cxx:32
 TTreeCloner.cxx:33
 TTreeCloner.cxx:34
 TTreeCloner.cxx:35
 TTreeCloner.cxx:36
 TTreeCloner.cxx:37
 TTreeCloner.cxx:38
 TTreeCloner.cxx:39
 TTreeCloner.cxx:40
 TTreeCloner.cxx:41
 TTreeCloner.cxx:42
 TTreeCloner.cxx:43
 TTreeCloner.cxx:44
 TTreeCloner.cxx:45
 TTreeCloner.cxx:46
 TTreeCloner.cxx:47
 TTreeCloner.cxx:48
 TTreeCloner.cxx:49
 TTreeCloner.cxx:50
 TTreeCloner.cxx:51
 TTreeCloner.cxx:52
 TTreeCloner.cxx:53
 TTreeCloner.cxx:54
 TTreeCloner.cxx:55
 TTreeCloner.cxx:56
 TTreeCloner.cxx:57
 TTreeCloner.cxx:58
 TTreeCloner.cxx:59
 TTreeCloner.cxx:60
 TTreeCloner.cxx:61
 TTreeCloner.cxx:62
 TTreeCloner.cxx:63
 TTreeCloner.cxx:64
 TTreeCloner.cxx:65
 TTreeCloner.cxx:66
 TTreeCloner.cxx:67
 TTreeCloner.cxx:68
 TTreeCloner.cxx:69
 TTreeCloner.cxx:70
 TTreeCloner.cxx:71
 TTreeCloner.cxx:72
 TTreeCloner.cxx:73
 TTreeCloner.cxx:74
 TTreeCloner.cxx:75
 TTreeCloner.cxx:76
 TTreeCloner.cxx:77
 TTreeCloner.cxx:78
 TTreeCloner.cxx:79
 TTreeCloner.cxx:80
 TTreeCloner.cxx:81
 TTreeCloner.cxx:82
 TTreeCloner.cxx:83
 TTreeCloner.cxx:84
 TTreeCloner.cxx:85
 TTreeCloner.cxx:86
 TTreeCloner.cxx:87
 TTreeCloner.cxx:88
 TTreeCloner.cxx:89
 TTreeCloner.cxx:90
 TTreeCloner.cxx:91
 TTreeCloner.cxx:92
 TTreeCloner.cxx:93
 TTreeCloner.cxx:94
 TTreeCloner.cxx:95
 TTreeCloner.cxx:96
 TTreeCloner.cxx:97
 TTreeCloner.cxx:98
 TTreeCloner.cxx:99
 TTreeCloner.cxx:100
 TTreeCloner.cxx:101
 TTreeCloner.cxx:102
 TTreeCloner.cxx:103
 TTreeCloner.cxx:104
 TTreeCloner.cxx:105
 TTreeCloner.cxx:106
 TTreeCloner.cxx:107
 TTreeCloner.cxx:108
 TTreeCloner.cxx:109
 TTreeCloner.cxx:110
 TTreeCloner.cxx:111
 TTreeCloner.cxx:112
 TTreeCloner.cxx:113
 TTreeCloner.cxx:114
 TTreeCloner.cxx:115
 TTreeCloner.cxx:116
 TTreeCloner.cxx:117
 TTreeCloner.cxx:118
 TTreeCloner.cxx:119
 TTreeCloner.cxx:120
 TTreeCloner.cxx:121
 TTreeCloner.cxx:122
 TTreeCloner.cxx:123
 TTreeCloner.cxx:124
 TTreeCloner.cxx:125
 TTreeCloner.cxx:126
 TTreeCloner.cxx:127
 TTreeCloner.cxx:128
 TTreeCloner.cxx:129
 TTreeCloner.cxx:130
 TTreeCloner.cxx:131
 TTreeCloner.cxx:132
 TTreeCloner.cxx:133
 TTreeCloner.cxx:134
 TTreeCloner.cxx:135
 TTreeCloner.cxx:136
 TTreeCloner.cxx:137
 TTreeCloner.cxx:138
 TTreeCloner.cxx:139
 TTreeCloner.cxx:140
 TTreeCloner.cxx:141
 TTreeCloner.cxx:142
 TTreeCloner.cxx:143
 TTreeCloner.cxx:144
 TTreeCloner.cxx:145
 TTreeCloner.cxx:146
 TTreeCloner.cxx:147
 TTreeCloner.cxx:148
 TTreeCloner.cxx:149
 TTreeCloner.cxx:150
 TTreeCloner.cxx:151
 TTreeCloner.cxx:152
 TTreeCloner.cxx:153
 TTreeCloner.cxx:154
 TTreeCloner.cxx:155
 TTreeCloner.cxx:156
 TTreeCloner.cxx:157
 TTreeCloner.cxx:158
 TTreeCloner.cxx:159
 TTreeCloner.cxx:160
 TTreeCloner.cxx:161
 TTreeCloner.cxx:162
 TTreeCloner.cxx:163
 TTreeCloner.cxx:164
 TTreeCloner.cxx:165
 TTreeCloner.cxx:166
 TTreeCloner.cxx:167
 TTreeCloner.cxx:168
 TTreeCloner.cxx:169
 TTreeCloner.cxx:170
 TTreeCloner.cxx:171
 TTreeCloner.cxx:172
 TTreeCloner.cxx:173
 TTreeCloner.cxx:174
 TTreeCloner.cxx:175
 TTreeCloner.cxx:176
 TTreeCloner.cxx:177
 TTreeCloner.cxx:178
 TTreeCloner.cxx:179
 TTreeCloner.cxx:180
 TTreeCloner.cxx:181
 TTreeCloner.cxx:182
 TTreeCloner.cxx:183
 TTreeCloner.cxx:184
 TTreeCloner.cxx:185
 TTreeCloner.cxx:186
 TTreeCloner.cxx:187
 TTreeCloner.cxx:188
 TTreeCloner.cxx:189
 TTreeCloner.cxx:190
 TTreeCloner.cxx:191
 TTreeCloner.cxx:192
 TTreeCloner.cxx:193
 TTreeCloner.cxx:194
 TTreeCloner.cxx:195
 TTreeCloner.cxx:196
 TTreeCloner.cxx:197
 TTreeCloner.cxx:198
 TTreeCloner.cxx:199
 TTreeCloner.cxx:200
 TTreeCloner.cxx:201
 TTreeCloner.cxx:202
 TTreeCloner.cxx:203
 TTreeCloner.cxx:204
 TTreeCloner.cxx:205
 TTreeCloner.cxx:206
 TTreeCloner.cxx:207
 TTreeCloner.cxx:208
 TTreeCloner.cxx:209
 TTreeCloner.cxx:210
 TTreeCloner.cxx:211
 TTreeCloner.cxx:212
 TTreeCloner.cxx:213
 TTreeCloner.cxx:214
 TTreeCloner.cxx:215
 TTreeCloner.cxx:216
 TTreeCloner.cxx:217
 TTreeCloner.cxx:218
 TTreeCloner.cxx:219
 TTreeCloner.cxx:220
 TTreeCloner.cxx:221
 TTreeCloner.cxx:222
 TTreeCloner.cxx:223
 TTreeCloner.cxx:224
 TTreeCloner.cxx:225
 TTreeCloner.cxx:226
 TTreeCloner.cxx:227
 TTreeCloner.cxx:228
 TTreeCloner.cxx:229
 TTreeCloner.cxx:230
 TTreeCloner.cxx:231
 TTreeCloner.cxx:232
 TTreeCloner.cxx:233
 TTreeCloner.cxx:234
 TTreeCloner.cxx:235
 TTreeCloner.cxx:236
 TTreeCloner.cxx:237
 TTreeCloner.cxx:238
 TTreeCloner.cxx:239
 TTreeCloner.cxx:240
 TTreeCloner.cxx:241
 TTreeCloner.cxx:242
 TTreeCloner.cxx:243
 TTreeCloner.cxx:244
 TTreeCloner.cxx:245
 TTreeCloner.cxx:246
 TTreeCloner.cxx:247
 TTreeCloner.cxx:248
 TTreeCloner.cxx:249
 TTreeCloner.cxx:250
 TTreeCloner.cxx:251
 TTreeCloner.cxx:252
 TTreeCloner.cxx:253
 TTreeCloner.cxx:254
 TTreeCloner.cxx:255
 TTreeCloner.cxx:256
 TTreeCloner.cxx:257
 TTreeCloner.cxx:258
 TTreeCloner.cxx:259
 TTreeCloner.cxx:260
 TTreeCloner.cxx:261
 TTreeCloner.cxx:262
 TTreeCloner.cxx:263
 TTreeCloner.cxx:264
 TTreeCloner.cxx:265
 TTreeCloner.cxx:266
 TTreeCloner.cxx:267
 TTreeCloner.cxx:268
 TTreeCloner.cxx:269
 TTreeCloner.cxx:270
 TTreeCloner.cxx:271
 TTreeCloner.cxx:272
 TTreeCloner.cxx:273
 TTreeCloner.cxx:274
 TTreeCloner.cxx:275
 TTreeCloner.cxx:276
 TTreeCloner.cxx:277
 TTreeCloner.cxx:278
 TTreeCloner.cxx:279
 TTreeCloner.cxx:280
 TTreeCloner.cxx:281
 TTreeCloner.cxx:282
 TTreeCloner.cxx:283
 TTreeCloner.cxx:284
 TTreeCloner.cxx:285
 TTreeCloner.cxx:286
 TTreeCloner.cxx:287
 TTreeCloner.cxx:288
 TTreeCloner.cxx:289
 TTreeCloner.cxx:290
 TTreeCloner.cxx:291
 TTreeCloner.cxx:292
 TTreeCloner.cxx:293
 TTreeCloner.cxx:294
 TTreeCloner.cxx:295
 TTreeCloner.cxx:296
 TTreeCloner.cxx:297
 TTreeCloner.cxx:298
 TTreeCloner.cxx:299
 TTreeCloner.cxx:300
 TTreeCloner.cxx:301
 TTreeCloner.cxx:302
 TTreeCloner.cxx:303
 TTreeCloner.cxx:304
 TTreeCloner.cxx:305
 TTreeCloner.cxx:306
 TTreeCloner.cxx:307
 TTreeCloner.cxx:308
 TTreeCloner.cxx:309
 TTreeCloner.cxx:310
 TTreeCloner.cxx:311
 TTreeCloner.cxx:312
 TTreeCloner.cxx:313
 TTreeCloner.cxx:314
 TTreeCloner.cxx:315
 TTreeCloner.cxx:316
 TTreeCloner.cxx:317
 TTreeCloner.cxx:318
 TTreeCloner.cxx:319
 TTreeCloner.cxx:320
 TTreeCloner.cxx:321
 TTreeCloner.cxx:322
 TTreeCloner.cxx:323
 TTreeCloner.cxx:324
 TTreeCloner.cxx:325
 TTreeCloner.cxx:326
 TTreeCloner.cxx:327
 TTreeCloner.cxx:328
 TTreeCloner.cxx:329
 TTreeCloner.cxx:330
 TTreeCloner.cxx:331
 TTreeCloner.cxx:332
 TTreeCloner.cxx:333
 TTreeCloner.cxx:334
 TTreeCloner.cxx:335
 TTreeCloner.cxx:336
 TTreeCloner.cxx:337
 TTreeCloner.cxx:338
 TTreeCloner.cxx:339
 TTreeCloner.cxx:340
 TTreeCloner.cxx:341
 TTreeCloner.cxx:342
 TTreeCloner.cxx:343
 TTreeCloner.cxx:344
 TTreeCloner.cxx:345
 TTreeCloner.cxx:346
 TTreeCloner.cxx:347
 TTreeCloner.cxx:348
 TTreeCloner.cxx:349
 TTreeCloner.cxx:350
 TTreeCloner.cxx:351
 TTreeCloner.cxx:352
 TTreeCloner.cxx:353
 TTreeCloner.cxx:354
 TTreeCloner.cxx:355
 TTreeCloner.cxx:356
 TTreeCloner.cxx:357
 TTreeCloner.cxx:358
 TTreeCloner.cxx:359
 TTreeCloner.cxx:360
 TTreeCloner.cxx:361
 TTreeCloner.cxx:362
 TTreeCloner.cxx:363
 TTreeCloner.cxx:364
 TTreeCloner.cxx:365
 TTreeCloner.cxx:366
 TTreeCloner.cxx:367
 TTreeCloner.cxx:368
 TTreeCloner.cxx:369
 TTreeCloner.cxx:370
 TTreeCloner.cxx:371
 TTreeCloner.cxx:372
 TTreeCloner.cxx:373
 TTreeCloner.cxx:374
 TTreeCloner.cxx:375
 TTreeCloner.cxx:376
 TTreeCloner.cxx:377
 TTreeCloner.cxx:378
 TTreeCloner.cxx:379
 TTreeCloner.cxx:380
 TTreeCloner.cxx:381
 TTreeCloner.cxx:382
 TTreeCloner.cxx:383
 TTreeCloner.cxx:384
 TTreeCloner.cxx:385
 TTreeCloner.cxx:386
 TTreeCloner.cxx:387
 TTreeCloner.cxx:388
 TTreeCloner.cxx:389
 TTreeCloner.cxx:390
 TTreeCloner.cxx:391
 TTreeCloner.cxx:392
 TTreeCloner.cxx:393
 TTreeCloner.cxx:394
 TTreeCloner.cxx:395
 TTreeCloner.cxx:396
 TTreeCloner.cxx:397
 TTreeCloner.cxx:398
 TTreeCloner.cxx:399
 TTreeCloner.cxx:400
 TTreeCloner.cxx:401
 TTreeCloner.cxx:402
 TTreeCloner.cxx:403
 TTreeCloner.cxx:404
 TTreeCloner.cxx:405
 TTreeCloner.cxx:406
 TTreeCloner.cxx:407
 TTreeCloner.cxx:408
 TTreeCloner.cxx:409
 TTreeCloner.cxx:410
 TTreeCloner.cxx:411
 TTreeCloner.cxx:412
 TTreeCloner.cxx:413
 TTreeCloner.cxx:414
 TTreeCloner.cxx:415
 TTreeCloner.cxx:416
 TTreeCloner.cxx:417
 TTreeCloner.cxx:418
 TTreeCloner.cxx:419
 TTreeCloner.cxx:420
 TTreeCloner.cxx:421
 TTreeCloner.cxx:422
 TTreeCloner.cxx:423
 TTreeCloner.cxx:424
 TTreeCloner.cxx:425
 TTreeCloner.cxx:426
 TTreeCloner.cxx:427
 TTreeCloner.cxx:428
 TTreeCloner.cxx:429
 TTreeCloner.cxx:430
 TTreeCloner.cxx:431
 TTreeCloner.cxx:432
 TTreeCloner.cxx:433
 TTreeCloner.cxx:434
 TTreeCloner.cxx:435
 TTreeCloner.cxx:436
 TTreeCloner.cxx:437
 TTreeCloner.cxx:438
 TTreeCloner.cxx:439
 TTreeCloner.cxx:440
 TTreeCloner.cxx:441
 TTreeCloner.cxx:442
 TTreeCloner.cxx:443
 TTreeCloner.cxx:444
 TTreeCloner.cxx:445
 TTreeCloner.cxx:446
 TTreeCloner.cxx:447
 TTreeCloner.cxx:448
 TTreeCloner.cxx:449
 TTreeCloner.cxx:450
 TTreeCloner.cxx:451
 TTreeCloner.cxx:452
 TTreeCloner.cxx:453
 TTreeCloner.cxx:454
 TTreeCloner.cxx:455
 TTreeCloner.cxx:456
 TTreeCloner.cxx:457
 TTreeCloner.cxx:458
 TTreeCloner.cxx:459
 TTreeCloner.cxx:460
 TTreeCloner.cxx:461
 TTreeCloner.cxx:462
 TTreeCloner.cxx:463
 TTreeCloner.cxx:464
 TTreeCloner.cxx:465
 TTreeCloner.cxx:466
 TTreeCloner.cxx:467
 TTreeCloner.cxx:468
 TTreeCloner.cxx:469
 TTreeCloner.cxx:470
 TTreeCloner.cxx:471
 TTreeCloner.cxx:472
 TTreeCloner.cxx:473
 TTreeCloner.cxx:474
 TTreeCloner.cxx:475
 TTreeCloner.cxx:476
 TTreeCloner.cxx:477