TTreePlayer.cxx

Go to the documentation of this file.
00001 // @(#)root/treeplayer:$Id: TTreePlayer.cxx 37409 2010-12-08 17:18:21Z pcanal $
00002 // Author: Rene Brun   12/01/96
00003 
00004 /*************************************************************************
00005  * Copyright (C) 1995-2000, Rene Brun and Fons Rademakers.               *
00006  * All rights reserved.                                                  *
00007  *                                                                       *
00008  * For the licensing terms see $ROOTSYS/LICENSE.                         *
00009  * For the list of contributors see $ROOTSYS/README/CREDITS.             *
00010  *************************************************************************/
00011 
00012 //////////////////////////////////////////////////////////////////////////
00013 //                                                                      //
00014 // TTree                                                                //
00015 //                                                                      //
00016 //  a TTree object has a header with a name and a title.
00017 //  It consists of a list of independent branches (TBranch). Each branch
00018 //  has its own definition and list of buffers. Branch buffers may be
00019 //  automatically written to disk or kept in memory until the Tree attribute
00020 //  fMaxVirtualSize is reached.
00021 //  Variables of one branch are written to the same buffer.
00022 //  A branch buffer is automatically compressed if the file compression
00023 //  attribute is set (default).
00024 //
00025 //  Branches may be written to different files (see TBranch::SetFile).
00026 //
00027 //  The ROOT user can decide to make one single branch and serialize one
00028 //  object into one single I/O buffer or to make several branches.
00029 //  Making one single branch and one single buffer can be the right choice
00030 //  when one wants to process only a subset of all entries in the tree.
00031 //  (you know for example the list of entry numbers you want to process).
00032 //  Making several branches is particularly interesting in the data analysis
00033 //  phase, when one wants to histogram some attributes of an object (entry)
00034 //  without reading all the attributes.
00035 //Begin_Html
00036 /*
00037 <img src="gif/ttree_classtree.gif">
00038 */
00039 //End_Html
00040 //
00041 //  ==> TTree *tree = new TTree(name, title, maxvirtualsize)
00042 //     Creates a Tree with name and title. Maxvirtualsize is by default 64Mbytes,
00043 //     maxvirtualsize = 64000000(default) means: Keeps as many buffers in memory until
00044 //     the sum of all buffers is greater than 64 Megabyte. When this happens,
00045 //     memory buffers are written to disk and deleted until the size of all
00046 //     buffers is again below the threshold.
00047 //     maxvirtualsize = 0 means: keep only one buffer in memory.
00048 //
00049 //     Various kinds of branches can be added to a tree:
00050 //       A - simple structures or list of variables. (may be for C or Fortran structures)
00051 //       B - any object (inheriting from TObject). (we expect this option be the most frequent)
00052 //       C - a ClonesArray. (a specialized object for collections of same class objects)
00053 //
00054 //  ==> Case A
00055 //      ======
00056 //     TBranch *branch = tree->Branch(branchname,address, leaflist, bufsize)
00057 //       * address is the address of the first item of a structure
00058 //       * leaflist is the concatenation of all the variable names and types
00059 //         separated by a colon character :
00060 //         The variable name and the variable type are separated by a slash (/).
00061 //         The variable type may be 0,1 or 2 characters. If no type is given,
00062 //         the type of the variable is assumed to be the same as the previous
00063 //         variable. If the first variable does not have a type, it is assumed
00064 //         of type F by default. The list of currently supported types is given below:
00065 //            - C : a character string terminated by the 0 character
00066 //            - B : an 8 bit signed integer (Char_t)
00067 //            - b : an 8 bit unsigned integer (UChar_t)
00068 //            - S : a 16 bit signed integer (Short_t)
00069 //            - s : a 16 bit unsigned integer (UShort_t)
00070 //            - I : a 32 bit signed integer (Int_t)
00071 //            - i : a 32 bit unsigned integer (UInt_t)
00072 //            - F : a 32 bit floating point (Float_t)
00073 //            - D : a 64 bit floating point (Double_t)
00074 //
00075 //  ==> Case B
00076 //      ======
00077 //     TBranch *branch = tree->Branch(branchname,className,object, bufsize, splitlevel)
00078 //          object is the address of a pointer to an existing object (derived from TObject).
00079 //        if splitlevel=1 (default), this branch will automatically be split
00080 //          into subbranches, with one subbranch for each data member or object
00081 //          of the object itself. In case the object member is a TClonesArray,
00082 //          the mechanism described in case C is applied to this array.
00083 //        if splitlevel=0, the object is serialized in the branch buffer.
00084 //
00085 //  ==> Case C
00086 //      ======
00087 //     TBranch *branch = tree->Branch(branchname,clonesarray, bufsize, splitlevel)
00088 //         clonesarray is the address of a pointer to a TClonesArray.
00089 //         The TClonesArray is a direct access list of objects of the same class.
00090 //         For example, if the TClonesArray is an array of TTrack objects,
00091 //         this function will create one subbranch for each data member of
00092 //         the object TTrack.
00093 //
00094 //
00095 //  ==> branch->SetAddress(Void *address)
00096 //      In case of dynamic structures changing with each entry for example, one must
00097 //      redefine the branch address before filling the branch again.
00098 //      This is done via the TBranch::SetAddress member function.
00099 //
00100 //  ==> tree->Fill()
00101 //      loops on all defined branches and for each branch invokes the Fill function.
00102 //
00103 //         See also the class TNtuple (a simple Tree with only one branch)
00104 //Begin_Html
00105 /*
00106 <img src="gif/tree_layout.gif">
00107 */
00108 //End_Html
00109 //  =============================================================================
00110 //______________________________________________________________________________
00111 //*-*-*-*-*-*-*A simple example with histograms and a tree*-*-*-*-*-*-*-*-*-*
00112 //*-*          ===========================================
00113 //
00114 //  This program creates :
00115 //    - a one dimensional histogram
00116 //    - a two dimensional histogram
00117 //    - a profile histogram
00118 //    - a tree
00119 //
00120 //  These objects are filled with some random numbers and saved on a file.
00121 //
00122 //-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
00123 //
00124 // #include "TFile.h"
00125 // #include "TH1.h"
00126 // #include "TH2.h"
00127 // #include "TProfile.h"
00128 // #include "TRandom.h"
00129 // #include "TTree.h"
00130 //
00131 //
00132 // //______________________________________________________________________________
00133 // main(int argc, char **argv)
00134 // {
00135 // // Create a new ROOT binary machine independent file.
00136 // // Note that this file may contain any kind of ROOT objects, histograms,trees
00137 // // pictures, graphics objects, detector geometries, tracks, events, etc..
00138 // // This file is now becoming the current directory.
00139 //   TFile hfile("htree.root","RECREATE","Demo ROOT file with histograms & trees");
00140 //
00141 // // Create some histograms and a profile histogram
00142 //   TH1F *hpx   = new TH1F("hpx","This is the px distribution",100,-4,4);
00143 //   TH2F *hpxpy = new TH2F("hpxpy","py ps px",40,-4,4,40,-4,4);
00144 //   TProfile *hprof = new TProfile("hprof","Profile of pz versus px",100,-4,4,0,20);
00145 //
00146 // // Define some simple structures
00147 //   typedef struct {Float_t x,y,z;} POINT;
00148 //   typedef struct {
00149 //      Int_t ntrack,nseg,nvertex;
00150 //      UInt_t flag;
00151 //      Float_t temperature;
00152 //   } EVENTN;
00153 //   static POINT point;
00154 //   static EVENTN eventn;
00155 //
00156 // // Create a ROOT Tree
00157 //   TTree *tree = new TTree("T","An example of ROOT tree with a few branches");
00158 //   tree->Branch("point",&point,"x:y:z");
00159 //   tree->Branch("eventn",&eventn,"ntrack/I:nseg:nvertex:flag/i:temperature/F");
00160 //   tree->Branch("hpx","TH1F",&hpx,128000,0);
00161 //
00162 //   Float_t px,py,pz;
00163 //   static Float_t p[3];
00164 //
00165 // //--------------------Here we start a loop on 1000 events
00166 //   for ( Int_t i=0; i<1000; i++) {
00167 //      gRandom->Rannor(px,py);
00168 //      pz = px*px + py*py;
00169 //      Float_t random = gRandom->::Rndm(1);
00170 //
00171 // //         Fill histograms
00172 //      hpx->Fill(px);
00173 //      hpxpy->Fill(px,py,1);
00174 //      hprof->Fill(px,pz,1);
00175 //
00176 // //         Fill structures
00177 //      p[0] = px;
00178 //      p[1] = py;
00179 //      p[2] = pz;
00180 //      point.x = 10*(random-1);;
00181 //      point.y = 5*random;
00182 //      point.z = 20*random;
00183 //      eventn.ntrack  = Int_t(100*random);
00184 //      eventn.nseg    = Int_t(2*eventn.ntrack);
00185 //      eventn.nvertex = 1;
00186 //      eventn.flag    = Int_t(random+0.5);
00187 //      eventn.temperature = 20+random;
00188 //
00189 // //        Fill the tree. For each event, save the 2 structures and 3 objects
00190 // //      In this simple example, the objects hpx, hprof and hpxpy are slightly
00191 // //      different from event to event. We expect a big compression factor!
00192 //      tree->Fill();
00193 //   }
00194 //  //--------------End of the loop
00195 //
00196 //   tree->Print();
00197 //
00198 // // Save all objects in this file
00199 //   hfile.Write();
00200 //
00201 // // Close the file. Note that this is automatically done when you leave
00202 // // the application.
00203 //   hfile.Close();
00204 //
00205 //   return 0;
00206 // }
00207 //                                                                      //
00208 //////////////////////////////////////////////////////////////////////////
00209 
00210 #include <string.h>
00211 #include <stdio.h>
00212 
00213 #include "Riostream.h"
00214 #include "TTreePlayer.h"
00215 #include "TROOT.h"
00216 #include "TSystem.h"
00217 #include "TFile.h"
00218 #include "TEventList.h"
00219 #include "TEntryList.h"
00220 #include "TBranchObject.h"
00221 #include "TBranchElement.h"
00222 #include "TStreamerInfo.h"
00223 #include "TStreamerElement.h"
00224 #include "TLeafObject.h"
00225 #include "TLeafF.h"
00226 #include "TLeafD.h"
00227 #include "TLeafC.h"
00228 #include "TLeafB.h"
00229 #include "TLeafI.h"
00230 #include "TLeafS.h"
00231 #include "TMath.h"
00232 #include "TH2.h"
00233 #include "TH3.h"
00234 #include "TPolyMarker.h"
00235 #include "TPolyMarker3D.h"
00236 #include "TDirectory.h"
00237 #include "TClonesArray.h"
00238 #include "TClass.h"
00239 #include "TVirtualPad.h"
00240 #include "TProfile.h"
00241 #include "TProfile2D.h"
00242 #include "TTreeFormula.h"
00243 #include "TTreeFormulaManager.h"
00244 #include "TStyle.h"
00245 #include "Foption.h"
00246 #include "TTreeResult.h"
00247 #include "TTreeRow.h"
00248 #include "TPrincipal.h"
00249 #include "TChain.h"
00250 #include "TChainElement.h"
00251 #include "TF1.h"
00252 #include "TH1.h"
00253 #include "TVirtualFitter.h"
00254 #include "TEnv.h"
00255 #include "THLimitsFinder.h"
00256 #include "TSelectorDraw.h"
00257 #include "TSelectorEntries.h"
00258 #include "TPluginManager.h"
00259 #include "TObjString.h"
00260 #include "TTreeProxyGenerator.h"
00261 #include "TTreeIndex.h"
00262 #include "TChainIndex.h"
00263 #include "TRefProxy.h"
00264 #include "TRefArrayProxy.h"
00265 #include "TVirtualMonitoring.h"
00266 #include "TTreeCache.h"
00267 #include "TStyle.h"
00268 
00269 #include "HFitInterface.h"
00270 #include "Foption.h"
00271 #include "Fit/UnBinData.h"
00272 #include "Math/MinimizerOptions.h"
00273 
00274 R__EXTERN Foption_t Foption;
00275 R__EXTERN  TTree *gTree;
00276 
00277 TVirtualFitter *tFitter=0;
00278 
00279 extern void TreeUnbinnedFitLikelihood(Int_t &npar, Double_t *gin, Double_t &f, Double_t *u, Int_t flag);
00280 
00281 ClassImp(TTreePlayer)
00282 
00283 //______________________________________________________________________________
00284 TTreePlayer::TTreePlayer()
00285 {
00286 //*-*-*-*-*-*-*-*-*-*-*Default Tree constructor*-*-*-*-*-*-*-*-*-*-*-*-*-*
00287 //*-*                  ========================
00288    fTree           = 0;
00289    fScanFileName   = 0;
00290    fScanRedirect   = kFALSE;
00291    fSelectedRows   = 0;
00292    fDimension      = 0;
00293    fHistogram      = 0;
00294    fFormulaList    = new TList();
00295    fFormulaList->SetOwner(kTRUE);
00296    fSelector         = new TSelectorDraw();
00297    fSelectorFromFile = 0;
00298    fSelectorClass    = 0;
00299    fSelectorUpdate   = 0;
00300    fInput            = new TList();
00301    fInput->Add(new TNamed("varexp",""));
00302    fInput->Add(new TNamed("selection",""));
00303    fSelector->SetInputList(fInput);
00304    gROOT->GetListOfCleanups()->Add(this);
00305    TClass::GetClass("TRef")->AdoptReferenceProxy(new TRefProxy());
00306    TClass::GetClass("TRefArray")->AdoptReferenceProxy(new TRefArrayProxy());
00307 }
00308 
00309 //______________________________________________________________________________
00310 TTreePlayer::~TTreePlayer()
00311 {
00312 //*-*-*-*-*-*-*-*-*-*-*Tree destructor*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
00313 //*-*                  =================
00314 
00315    delete fFormulaList;
00316    delete fSelector;
00317    DeleteSelectorFromFile();
00318    fInput->Delete();
00319    delete fInput;
00320    gROOT->GetListOfCleanups()->Remove(this);
00321 }
00322 
00323 //______________________________________________________________________________
00324 TVirtualIndex *TTreePlayer::BuildIndex(const TTree *T, const char *majorname, const char *minorname)
00325 {
00326    // Build the index for the tree (see TTree::BuildIndex)
00327 
00328    TVirtualIndex *index;
00329    if (dynamic_cast<const TChain*>(T)) {
00330       index = new TChainIndex(T, majorname, minorname);
00331       if (index->IsZombie()) {
00332          delete index;
00333          Error("BuildIndex", "Creating a TChainIndex unsuccessfull - switching to TTreeIndex");
00334       }
00335       else
00336          return index;
00337    }
00338    return new TTreeIndex(T,majorname,minorname);
00339 }
00340 
00341 //______________________________________________________________________________
00342 TTree *TTreePlayer::CopyTree(const char *selection, Option_t *, Long64_t nentries,
00343                              Long64_t firstentry)
00344 {
00345    // copy a Tree with selection
00346    // make a clone of this Tree header.
00347    // then copy the selected entries
00348    //
00349    // selection is a standard selection expression (see TTreePlayer::Draw)
00350    // option is reserved for possible future use
00351    // nentries is the number of entries to process (default is all)
00352    // first is the first entry to process (default is 0)
00353    //
00354    // IMPORTANT: The copied tree stays connected with this tree until this tree
00355    //            is deleted.  In particular, any changes in branch addresses
00356    //            in this tree are forwarded to the clone trees.  Any changes
00357    //            made to the branch addresses of the copied trees are over-ridden
00358    //            anytime this tree changes its branch addresses.
00359    //            Once this tree is deleted, all the addresses of the copied tree
00360    //            are reset to their default values.
00361    //
00362    // The following example illustrates how to copy some events from the Tree
00363    // generated in $ROOTSYS/test/Event
00364    //
00365    //   gSystem->Load("libEvent");
00366    //   TFile f("Event.root");
00367    //   TTree *T = (TTree*)f.Get("T");
00368    //   Event *event = new Event();
00369    //   T->SetBranchAddress("event",&event);
00370    //   TFile f2("Event2.root","recreate");
00371    //   TTree *T2 = T->CopyTree("fNtrack<595");
00372    //   T2->Write();
00373 
00374 
00375    // we make a copy of the tree header
00376    TTree *tree = fTree->CloneTree(0);
00377    if (tree == 0) return 0;
00378 
00379    // The clone should not delete any shared i/o buffers.
00380    TObjArray* branches = tree->GetListOfBranches();
00381    Int_t nb = branches->GetEntriesFast();
00382    for (Int_t i = 0; i < nb; ++i) {
00383       TBranch* br = (TBranch*) branches->UncheckedAt(i);
00384       if (br->InheritsFrom(TBranchElement::Class())) {
00385          ((TBranchElement*) br)->ResetDeleteObject();
00386       }
00387    }
00388 
00389    Long64_t entry,entryNumber;
00390    nentries = GetEntriesToProcess(firstentry, nentries);
00391 
00392    // Compile selection expression if there is one
00393    TTreeFormula *select = 0; // no need to interfere with fSelect since we
00394                              // handle the loop explicitly below and can call
00395                              // UpdateFormulaLeaves ourselves.
00396    if (strlen(selection)) {
00397       select = new TTreeFormula("Selection",selection,fTree);
00398       if (!select || !select->GetNdim()) {
00399          delete select;
00400          delete tree;
00401          return 0;
00402       }
00403       fFormulaList->Add(select);
00404    }
00405 
00406    //loop on the specified entries
00407    Int_t tnumber = -1;
00408    for (entry=firstentry;entry<firstentry+nentries;entry++) {
00409       entryNumber = fTree->GetEntryNumber(entry);
00410       if (entryNumber < 0) break;
00411       Long64_t localEntry = fTree->LoadTree(entryNumber);
00412       if (localEntry < 0) break;
00413       if (tnumber != fTree->GetTreeNumber()) {
00414          tnumber = fTree->GetTreeNumber();
00415          if (select) select->UpdateFormulaLeaves();
00416       }
00417       if (select) {
00418          Int_t ndata = select->GetNdata();
00419          Bool_t keep = kFALSE;
00420          for(Int_t current = 0; current<ndata && !keep; current++) {
00421             keep |= (select->EvalInstance(current) != 0);
00422          }
00423          if (!keep) continue;
00424       }
00425       fTree->GetEntry(entryNumber);
00426       tree->Fill();
00427    }
00428    fFormulaList->Clear();
00429    return tree;
00430 }
00431 
00432 //______________________________________________________________________________
00433 void TTreePlayer::DeleteSelectorFromFile()
00434 {
00435 // Delete any selector created by this object.
00436 // The selector has been created using TSelector::GetSelector(file)
00437 
00438    if (fSelectorFromFile && fSelectorClass) {
00439       if (fSelectorClass->IsLoaded()) {
00440          delete fSelectorFromFile;
00441       }
00442    }
00443    fSelectorFromFile = 0;
00444    fSelectorClass = 0;
00445 }
00446 
00447 //______________________________________________________________________________
00448 Long64_t TTreePlayer::DrawScript(const char* wrapperPrefix,
00449                                  const char *macrofilename, const char *cutfilename,
00450                                  Option_t *option, Long64_t nentries, Long64_t firstentry)
00451 {
00452    // Draw the result of a C++ script.
00453    //
00454    // The macrofilename and optionally cutfilename are assumed to contain
00455    // at least a method with the same name as the file.  The method
00456    // should return a value that can be automatically cast to
00457    // respectively a double and a boolean.
00458    //
00459    // Both methods will be executed in a context such that the
00460    // branch names can be used as C++ variables. This is
00461    // accomplished by generating a TTreeProxy (see MakeProxy)
00462    // and including the files in the proper location.
00463    //
00464    // If the branch name can not be used a proper C++ symbol name,
00465    // it will be modified as follow:
00466    //    - white spaces are removed
00467    //    - if the leading character is not a letter, an underscore is inserted
00468    //    - < and > are replace by underscores
00469    //    - * is replaced by st
00470    //    - & is replaced by rf
00471    //
00472    // If a cutfilename is specified, for each entry, we execute
00473    //   if (cutfilename()) htemp->Fill(macrofilename());
00474    // If no cutfilename is specified, for each entry we execute
00475    //   htemp(macrofilename());
00476    //
00477    // The default for the histogram are the same as for
00478    // TTreePlayer::DrawSelect
00479 
00480    if (!macrofilename || strlen(macrofilename)==0) return 0;
00481 
00482    TString aclicMode;
00483    TString arguments;
00484    TString io;
00485    TString realcutname;
00486    if (cutfilename && strlen(cutfilename))
00487       realcutname =  gSystem->SplitAclicMode(cutfilename, aclicMode, arguments, io);
00488 
00489    // we ignore the aclicMode for the cutfilename!
00490    TString realname = gSystem->SplitAclicMode(macrofilename, aclicMode, arguments, io);
00491 
00492    TString selname = wrapperPrefix;
00493 
00494    TTreeProxyGenerator gp(fTree,realname,realcutname,selname,option,3);
00495 
00496    selname = gp.GetFileName();
00497    if (aclicMode.Length()==0) {
00498       Warning("DrawScript","TTreeProxy does not work in interpreted mode yet. The script will be compiled.");
00499       aclicMode = "+";
00500    }
00501    selname.Append(aclicMode);
00502 
00503    Info("DrawScript","%s",Form("Will process tree/chain using %s",selname.Data()));
00504    Long64_t result = fTree->Process(selname,option,nentries,firstentry);
00505    fTree->SetNotify(0);
00506 
00507    // could delete the file selname+".h"
00508    // However this would remove the optimization of avoiding a useless
00509    // recompilation if the user ask for the same thing twice!
00510 
00511    return result;
00512 }
00513 
00514 //______________________________________________________________________________
00515 Long64_t TTreePlayer::DrawSelect(const char *varexp0, const char *selection, Option_t *option,Long64_t nentries, Long64_t firstentry)
00516 {
00517 // Draw expression varexp for specified entries
00518 // Returns -1 in case of error or number of selected events in case of success.
00519 //
00520 //  varexp is an expression of the general form
00521 //   - "e1"           produces a 1-d histogram of expression "e1"
00522 //   - "e1:e2"        produces a 2-d histogram (or profile) of "e1" versus "e2"
00523 //   - "e1:e2:e3"     produces a 3-d scatter-plot of "e1" versus "e2" versus "e3"
00524 //   - "e1:e2:e3:e4"  produces a 3-d scatter-plot of "e1" versus "e2" versus "e3"
00525 //                    and "e4" mapped on the color number.
00526 //
00527 //  Example:
00528 //     varexp = x     simplest case: draw a 1-Dim distribution of column named x
00529 //            = sqrt(x)            : draw distribution of sqrt(x)
00530 //            = x*y/z
00531 //            = y:sqrt(x) 2-Dim distribution of y versus sqrt(x)
00532 //            = px:py:pz:2.5*E  produces a 3-d scatter-plot of px vs py ps pz
00533 //              and the color number of each marker will be 2.5*E.
00534 //              If the color number is negative it is set to 0.
00535 //              If the color number is greater than the current number of colors
00536 //                 it is set to the highest color number.
00537 //              The default number of colors is 50.
00538 //              see TStyle::SetPalette for setting a new color palette.
00539 //
00540 //  Note that the variables e1, e2 or e3 may contain a selection.
00541 //  example, if e1= x*(y<0), the value histogrammed will be x if y<0
00542 //  and will be 0 otherwise.
00543 //
00544 //  The expressions can use all the operations and build-in functions
00545 //  supported by TFormula (See TFormula::Analyze), including free
00546 //  standing function taking numerical arguments (TMath::Bessel).
00547 //  In addition, you can call member functions taking numerical
00548 //  arguments. For example:
00549 //      - "TMath::BreitWigner(fPx,3,2)"
00550 //      - "event.GetHistogram().GetXaxis().GetXmax()"
00551 //  Note: You can only pass expression that depend on the TTree's data
00552 //  to static functions and you can only call non-static member function
00553 //  with 'fixed' parameters.
00554 //
00555 //  The selection is an expression with a combination of the columns.
00556 //  In a selection all the C++ operators are authorized.
00557 //  The value corresponding to the selection expression is used as a weight
00558 //  to fill the histogram.
00559 //  If the expression includes only boolean operations, the result
00560 //  is 0 or 1. If the result is 0, the histogram is not filled.
00561 //  In general, the expression may be of the form:
00562 //      value*(boolean expression)
00563 //  if boolean expression is true, the histogram is filled with
00564 //  a weight = value.
00565 //  Examples:
00566 //      selection1 = "x<y && sqrt(z)>3.2"
00567 //      selection2 = "(x+y)*(sqrt(z)>3.2"
00568 //  selection1 returns a weight = 0 or 1
00569 //  selection2 returns a weight = x+y if sqrt(z)>3.2
00570 //             returns a weight = 0 otherwise.
00571 //
00572 //  option is the drawing option
00573 //      see TH1::Draw for the list of all drawing options.
00574 //      If option contains the string "goff", no graphics is generated.
00575 //
00576 //  nentries is the number of entries to process (default is all)
00577 //  first is the first entry to process (default is 0)
00578 //
00579 //     Drawing expressions using arrays and array elements
00580 //     ===================================================
00581 // Let assume, a leaf fMatrix, on the branch fEvent, which is a 3 by 3 array,
00582 // or a TClonesArray.
00583 // In a TTree::Draw expression you can now access fMatrix using the following
00584 // syntaxes:
00585 //
00586 //   String passed    What is used for each entry of the tree
00587 //
00588 //   "fMatrix"       the 9 elements of fMatrix
00589 //   "fMatrix[][]"   the 9 elements of fMatrix
00590 //   "fMatrix[2][2]" only the elements fMatrix[2][2]
00591 //   "fMatrix[1]"    the 3 elements fMatrix[1][0], fMatrix[1][1] and fMatrix[1][2]
00592 //   "fMatrix[1][]"  the 3 elements fMatrix[1][0], fMatrix[1][1] and fMatrix[1][2]
00593 //   "fMatrix[][0]"  the 3 elements fMatrix[0][0], fMatrix[1][0] and fMatrix[2][0]
00594 //
00595 //   "fEvent.fMatrix...." same as "fMatrix..." (unless there is more than one leaf named fMatrix!).
00596 //
00597 // In summary, if a specific index is not specified for a dimension, TTree::Draw
00598 // will loop through all the indices along this dimension.  Leaving off the
00599 // last (right most) dimension of specifying then with the two characters '[]'
00600 // is equivalent.  For variable size arrays (and TClonesArray) the range
00601 // of the first dimension is recalculated for each entry of the tree.
00602 // You can also specify the index as an expression of any other variables from the
00603 // tree.
00604 //
00605 // TTree::Draw now also properly handles operations involving 2 or more arrays.
00606 //
00607 // Let assume a second matrix fResults[5][2], here are a sample of some
00608 // of the possible combinations, the number of elements they produce and
00609 // the loop used:
00610 //
00611 //  expression                       element(s)  Loop
00612 //
00613 //  "fMatrix[2][1] - fResults[5][2]"   one     no loop
00614 //  "fMatrix[2][]  - fResults[5][2]"   three   on 2nd dim fMatrix
00615 //  "fMatrix[2][]  - fResults[5][]"    two     on both 2nd dimensions
00616 //  "fMatrix[][2]  - fResults[][1]"    three   on both 1st dimensions
00617 //  "fMatrix[][2]  - fResults[][]"     six     on both 1st and 2nd dimensions of
00618 //                                             fResults
00619 //  "fMatrix[][2]  - fResults[3][]"    two     on 1st dim of fMatrix and 2nd of
00620 //                                             fResults (at the same time)
00621 //  "fMatrix[][]   - fResults[][]"     six     on 1st dim then on  2nd dim
00622 //
00623 //  "fMatrix[][fResult[][]]"           30      on 1st dim of fMatrix then on both
00624 //                                             dimensions of fResults.  The value
00625 //                                             if fResults[j][k] is used as the second
00626 //                                             index of fMatrix.
00627 //
00628 // In summary, TTree::Draw loops through all un-specified dimensions.  To
00629 // figure out the range of each loop, we match each unspecified dimension
00630 // from left to right (ignoring ALL dimensions for which an index has been
00631 // specified), in the equivalent loop matched dimensions use the same index
00632 // and are restricted to the smallest range (of only the matched dimensions).
00633 // When involving variable arrays, the range can of course be different
00634 // for each entry of the tree.
00635 //
00636 // So the loop equivalent to "fMatrix[][2] - fResults[3][]" is:
00637 //
00638 //    for (Int_t i0; i0 < min(3,2); i0++) {
00639 //       use the value of (fMatrix[i0][2] - fMatrix[3][i0])
00640 //    }
00641 //
00642 // So the loop equivalent to "fMatrix[][2] - fResults[][]" is:
00643 //
00644 //    for (Int_t i0; i0 < min(3,5); i0++) {
00645 //       for (Int_t i1; i1 < 2; i1++) {
00646 //          use the value of (fMatrix[i0][2] - fMatrix[i0][i1])
00647 //       }
00648 //    }
00649 //
00650 // So the loop equivalent to "fMatrix[][] - fResults[][]" is:
00651 //
00652 //    for (Int_t i0; i0 < min(3,5); i0++) {
00653 //       for (Int_t i1; i1 < min(3,2); i1++) {
00654 //          use the value of (fMatrix[i0][i1] - fResults[i0][i1])
00655 //       }
00656 //    }
00657 //
00658 // So the loop equivalent to "fMatrix[][fResults[][]]" is:
00659 //
00660 //    for (Int_t i0; i0 < 3; i0++) {
00661 //       for (Int_t j2; j2 < 5; j2++) {
00662 //          for (Int_t j3; j3 < 2; j3++) {
00663 //             i1 = fResults[j2][j3];
00664 //             use the value of fMatrix[i0][i1]
00665 //       }
00666 //    }
00667 //
00668 //     Saving the result of Draw to an histogram
00669 //     =========================================
00670 //  By default the temporary histogram created is called htemp.
00671 //  One can retrieve a pointer to this histogram with:
00672 //    TH1F *htemp = (TH1F*)gPad->GetPrimitive("htemp");
00673 //
00674 //  If varexp0 contains >>hnew (following the variable(s) name(s),
00675 //  the new histogram created is called hnew and it is kept in the current
00676 //  directory (and also the current pad).
00677 //  Example:
00678 //    tree.Draw("sqrt(x)>>hsqrt","y>0")
00679 //    will draw sqrt(x) and save the histogram as "hsqrt" in the current
00680 //    directory.  To retrieve it do:
00681 //    TH1F *hsqrt = (TH1F*)gDirectory->Get("hsqrt");
00682 //
00683 //  The binning information is taken from the environment variables
00684 //
00685 //     Hist.Binning.?D.?
00686 //
00687 //  In addition, the name of the histogram can be followed by up to 9
00688 //  numbers between '(' and ')', where the numbers describe the
00689 //  following:
00690 //
00691 //   1 - bins in x-direction
00692 //   2 - lower limit in x-direction
00693 //   3 - upper limit in x-direction
00694 //   4-6 same for y-direction
00695 //   7-9 same for z-direction
00696 //
00697 //   When a new binning is used the new value will become the default.
00698 //   Values can be skipped.
00699 //  Example:
00700 //    tree.Draw("sqrt(x)>>hsqrt(500,10,20)"
00701 //          // plot sqrt(x) between 10 and 20 using 500 bins
00702 //    tree.Draw("sqrt(x):sin(y)>>hsqrt(100,10,60,50,.1,.5)"
00703 //          // plot sqrt(x) against sin(y)
00704 //          // 100 bins in x-direction; lower limit on x-axis is 10; upper limit is 60
00705 //          //  50 bins in y-direction; lower limit on y-axis is .1; upper limit is .5
00706 //
00707 //  By default, the specified histogram is reset.
00708 //  To continue to append data to an existing histogram, use "+" in front
00709 //  of the histogram name.
00710 //  A '+' in front of the histogram name is ignored, when the name is followed by
00711 //  binning information as described in the previous paragraph.
00712 //    tree.Draw("sqrt(x)>>+hsqrt","y>0")
00713 //      will not reset hsqrt, but will continue filling.
00714 //  This works for 1-D, 2-D and 3-D histograms.
00715 //
00716 //     Accessing collection objects
00717 //     ============================
00718 //
00719 //  TTree::Draw default's handling of collections is to assume that any
00720 //  request on a collection pertain to it content.  For example, if fTracks
00721 //  is a collection of Track objects, the following:
00722 //      tree->Draw("event.fTracks.fPx");
00723 //  will plot the value of fPx for each Track objects inside the collection.
00724 //  Also
00725 //     tree->Draw("event.fTracks.size()");
00726 //  would plot the result of the member function Track::size() for each
00727 //  Track object inside the collection.
00728 //  To access information about the collection itself, TTree::Draw support
00729 //  the '@' notation.  If a variable which points to a collection is prefixed
00730 //  or postfixed with '@', the next part of the expression will pertain to
00731 //  the collection object.  For example:
00732 //     tree->Draw("event.@fTracks.size()");
00733 //  will plot the size of the collection refered to by fTracks (i.e the number
00734 //  of Track objects).
00735 //
00736 //     Drawing 'objects'
00737 //     =================
00738 //
00739 //  When a class has a member function named AsDouble or AsString, requesting
00740 //  to directly draw the object will imply a call to one of the 2 functions.
00741 //  If both AsDouble and AsString are present, AsDouble will be used.
00742 //  AsString can return either a char*, a std::string or a TString.s
00743 //  For example, the following
00744 //     tree->Draw("event.myTTimeStamp");
00745 //  will draw the same histogram as
00746 //     tree->Draw("event.myTTimeStamp.AsDouble()");
00747 //  In addition, when the object is a type TString or std::string, TTree::Draw
00748 //  will call respectively TString::Data and std::string::c_str()
00749 //
00750 //  If the object is a TBits, the histogram will contain the index of the bit
00751 //  that are turned on.
00752 //
00753 //     Retrieving  information about the tree itself.
00754 //     ============================================
00755 //
00756 //  You can refer to the tree (or chain) containing the data by using the
00757 //  string 'This'.
00758 //  You can then could any TTree methods.  For example:
00759 //     tree->Draw("This->GetReadEntry()");
00760 //  will display the local entry numbers be read.
00761 //     tree->Draw("This->GetUserInfo()->At(0)->GetName()");
00762 //  will display the name of the first 'user info' object.
00763 //
00764 //     Special functions and variables
00765 //     ===============================
00766 //
00767 //  Entry$:  A TTree::Draw formula can use the special variable Entry$
00768 //  to access the entry number being read.  For example to draw every
00769 //  other entry use:
00770 //    tree.Draw("myvar","Entry$%2==0");
00771 //
00772 //  Entry$      : return the current entry number (== TTree::GetReadEntry())
00773 //  LocalEntry$ : return the current entry number in the current tree of a chain (== GetTree()->GetReadEntry())
00774 //  Entries$    : return the total number of entries (== TTree::GetEntries())
00775 //  Length$     : return the total number of element of this formula for this
00776 //              entry (==TTreeFormula::GetNdata())
00777 //  Iteration$:   return the current iteration over this formula for this
00778 //                 entry (i.e. varies from 0 to Length$).
00779 //
00780 //  Length$(formula): return the total number of element of the formula given as a
00781 //                    parameter.
00782 //  Sum$(formula): return the sum of the value of the elements of the formula given
00783 //                    as a parameter.  For example the mean for all the elements in
00784 //                    one entry can be calculated with:
00785 //                Sum$(formula)/Length$(formula)
00786 //  Min$(formula): return the minimun (within one TTree entry) of the value of the
00787 //                    elements of the formula given as a parameter.
00788 //  Max$(formula): return the maximum (within one TTree entry) of the value of the
00789 //                    elements of the formula given as a parameter.
00790 //  MinIf$(formula,condition)
00791 //  MaxIf$(formula,condition): return the minimum (maximum) (within one TTree entry)
00792 //                    of the value of the elements of the formula given as a parameter
00793 //                    if they match the condition. If not element match the condition, the result is zero.  To avoid the
00794 //                    the result is zero.  To avoid the consequent peak a zero, use the
00795 //                    pattern:
00796 //    tree->Draw("MinIf$(formula,condition)","condition");
00797 //                    which will avoid calculation MinIf$ for the entries that have no match
00798 //                    for the condition.
00799 //
00800 //  Alt$(primary,alternate) : return the value of "primary" if it is available
00801 //                 for the current iteration otherwise return the value of "alternate".
00802 //                 For example, with arr1[3] and arr2[2]
00803 //    tree->Draw("arr1+Alt$(arr2,0)");
00804 //                 will draw arr[0]+arr2[0] ; arr[1]+arr2[1] and arr[1]+0
00805 //                 Or with a variable size array arr3
00806 //    tree->Draw("Alt$(arr3[0],0)+Alt$(arr3[1],0)+Alt$(arr3[2],0)");
00807 //                 will draw the sum arr3 for the index 0 to min(2,actual_size_of_arr3-1)
00808 //                 As a comparison
00809 //    tree->Draw("arr3[0]+arr3[1]+arr3[2]");
00810 //                 will draw the sum arr3 for the index 0 to 2 only if the
00811 //                 actual_size_of_arr3 is greater or equal to 3.
00812 //                 Note that the array in 'primary' is flattened/linearized thus using
00813 //                 Alt$ with multi-dimensional arrays of different dimensions in unlikely
00814 //                 to yield the expected results.  To visualize a bit more what elements
00815 //                 would be matched by TTree::Draw, TTree::Scan can be used:
00816 //    tree->Scan("arr1:Alt$(arr2,0)");
00817 //                 will print on one line the value of arr1 and (arr2,0) that will be
00818 //                 matched by
00819 //    tree->Draw("arr1-Alt$(arr2,0)");
00820 //
00821 //     Drawing a user function accessing the TTree data directly
00822 //     =========================================================
00823 //
00824 //  If the formula contains  a file name, TTree::MakeProxy will be used
00825 //  to load and execute this file.   In particular it will draw the
00826 //  result of a function with the same name as the file.  The function
00827 //  will be executed in a context where the name of the branches can
00828 //  be used as a C++ variable.
00829 //
00830 //  For example draw px using the file hsimple.root (generated by the
00831 //  hsimple.C tutorial), we need a file named hsimple.cxx:
00832 //
00833 //     double hsimple() {
00834 //        return px;
00835 //     }
00836 //
00837 //  MakeProxy can then be used indirectly via the TTree::Draw interface
00838 //  as follow:
00839 //     new TFile("hsimple.root")
00840 //     ntuple->Draw("hsimple.cxx");
00841 //
00842 //  A more complete example is available in the tutorials directory:
00843 //    h1analysisProxy.cxx , h1analysProxy.h and h1analysisProxyCut.C
00844 //  which reimplement the selector found in h1analysis.C
00845 //
00846 //  The main features of this facility are:
00847 //
00848 //    * on-demand loading of branches
00849 //    * ability to use the 'branchname' as if it was a data member
00850 //    * protection against array out-of-bound
00851 //    * ability to use the branch data as object (when the user code is available)
00852 //
00853 //  See TTree::MakeProxy for more details.
00854 //
00855 //     Making a Profile histogram
00856 //     ==========================
00857 //  In case of a 2-Dim expression, one can generate a TProfile histogram
00858 //  instead of a TH2F histogram by specifying option=prof or option=profs.
00859 //  The option=prof is automatically selected in case of y:x>>pf
00860 //  where pf is an existing TProfile histogram.
00861 //
00862 //     Making a 2D Profile histogram
00863 //     ==========================
00864 //  In case of a 3-Dim expression, one can generate a TProfile2D histogram
00865 //  instead of a TH3F histogram by specifying option=prof or option=profs.
00866 //  The option=prof is automatically selected in case of z:y:x>>pf
00867 //  where pf is an existing TProfile2D histogram.
00868 //
00869 //     Making a 5-D plot with GL
00870 //     =========================
00871 //  When the option "gl5d" is specified and the dimension of the query is 5
00872 //  a 5-d plot is created using GL, eg
00873 //      T->Draw("x:y:z:u:w","","gl5d")
00874 //
00875 //     Making a parallel coordinates plot.
00876 //     ===========================
00877 //  In case of a 2-Dim or more expression with the option=para, one can generate
00878 //  a parallel coordinates plot. With that option, the number of dimensions is
00879 //  arbitrary. Giving more than 4 variables without the option=para or
00880 //  option=candle or option=goff will produce an error.
00881 //
00882 //     Making a candle sticks chart.
00883 //     ===========================
00884 //  In case of a 2-Dim or more expression with the option=candle, one can generate
00885 //  a candle sticks chart. With that option, the number of dimensions is
00886 //  arbitrary. Giving more than 4 variables without the option=para or
00887 //  option=candle or option=goff will produce an error.
00888 //
00889 //     Normalizing the ouput histogram to 1
00890 //     ====================================
00891 //  When option contains "norm" the output histogram is normalized to 1.
00892 //
00893 //     Saving the result of Draw to a TEventList or a TEntryList
00894 //     =========================================================
00895 //  TTree::Draw can be used to fill a TEventList object (list of entry numbers)
00896 //  instead of histogramming one variable.
00897 //  If varexp0 has the form >>elist , a TEventList object named "elist"
00898 //  is created in the current directory. elist will contain the list
00899 //  of entry numbers satisfying the current selection.
00900 //  If option "entrylist" is used, a TEntryList object is created
00901 //  Example:
00902 //    tree.Draw(">>yplus","y>0")
00903 //    will create a TEventList object named "yplus" in the current directory.
00904 //    In an interactive session, one can type (after TTree::Draw)
00905 //       yplus.Print("all")
00906 //    to print the list of entry numbers in the list.
00907 //    tree.Draw(">>yplus", "y>0", "entrylist")
00908 //    will create a TEntryList object names "yplus" in the current directory
00909 //
00910 //  By default, the specified entry list is reset.
00911 //  To continue to append data to an existing list, use "+" in front
00912 //  of the list name;
00913 //    tree.Draw(">>+yplus","y>0")
00914 //      will not reset yplus, but will enter the selected entries at the end
00915 //      of the existing list.
00916 //
00917 //      Using a TEventList or a TEntryList as Input
00918 //      ===========================
00919 //  Once a TEventList or a TEntryList object has been generated, it can be used as input
00920 //  for TTree::Draw. Use TTree::SetEventList or TTree::SetEntryList to set the
00921 //  current event list
00922 //  Example1:
00923 //     TEventList *elist = (TEventList*)gDirectory->Get("yplus");
00924 //     tree->SetEventList(elist);
00925 //     tree->Draw("py");
00926 //  Example2:
00927 //     TEntryList *elist = (TEntryList*)gDirectory->Get("yplus");
00928 //     tree->SetEntryList(elist);
00929 //     tree->Draw("py");
00930 //  If a TEventList object is used as input, a new TEntryList object is created
00931 //  inside the SetEventList function. In case of a TChain, all tree headers are loaded
00932 //  for this transformation. This new object is owned by the chain and is deleted
00933 //  with it, unless the user extracts it by calling GetEntryList() function.
00934 //  See also comments to SetEventList() function of TTree and TChain.
00935 //
00936 //  If arrays are used in the selection critera, the event entered in the
00937 //  list are all the event that have at least one element of the array that
00938 //  satisfy the selection.
00939 //  Example:
00940 //      tree.Draw(">>pyplus","fTracks.fPy>0");
00941 //      tree->SetEventList(pyplus);
00942 //      tree->Draw("fTracks.fPy");
00943 //  will draw the fPy of ALL tracks in event with at least one track with
00944 //  a positive fPy.
00945 //
00946 //  To select only the elements that did match the original selection
00947 //  use TEventList::SetReapplyCut.
00948 //  Example:
00949 //      tree.Draw(">>pyplus","fTracks.fPy>0");
00950 //      pyplus->SetReapplyCut(kTRUE);
00951 //      tree->SetEventList(pyplus);
00952 //      tree->Draw("fTracks.fPy");
00953 //  will draw the fPy of only the tracks that have a positive fPy.
00954 //
00955 //  Note: Use tree->SetEventList(0) if you do not want use the list as input.
00956 //
00957 //      How to obtain more info from TTree::Draw
00958 //      ========================================
00959 //
00960 //  Once TTree::Draw has been called, it is possible to access useful
00961 //  information still stored in the TTree object via the following functions:
00962 //    -GetSelectedRows()    // return the number of entries accepted by the
00963 //                          //selection expression. In case where no selection
00964 //                          //was specified, returns the number of entries processed.
00965 //    -GetV1()              //returns a pointer to the double array of V1
00966 //    -GetV2()              //returns a pointer to the double array of V2
00967 //    -GetV3()              //returns a pointer to the double array of V3
00968 //    -GetW()               //returns a pointer to the double array of Weights
00969 //                          //where weight equal the result of the selection expression.
00970 //   where V1,V2,V3 correspond to the expressions in
00971 //   TTree::Draw("V1:V2:V3",selection);
00972 //
00973 //   Example:
00974 //    Root > ntuple->Draw("py:px","pz>4");
00975 //    Root > TGraph *gr = new TGraph(ntuple->GetSelectedRows(),
00976 //                                   ntuple->GetV2(), ntuple->GetV1());
00977 //    Root > gr->Draw("ap"); //draw graph in current pad
00978 //    creates a TGraph object with a number of points corresponding to the
00979 //    number of entries selected by the expression "pz>4", the x points of the graph
00980 //    being the px values of the Tree and the y points the py values.
00981 //
00982 //   Important note: By default TTree::Draw creates the arrays obtained
00983 //    with GetV1, GetV2, GetV3, GetW with a length corresponding to the
00984 //    parameter fEstimate. By default fEstimate=10000 and can be modified
00985 //    via TTree::SetEstimate. A possible recipee is to do
00986 //       tree->SetEstimate(tree->GetEntries());
00987 //    You must call SetEstimate if the expected number of selected rows
00988 //    is greater than 10000.
00989 //
00990 //    You can use the option "goff" to turn off the graphics output
00991 //    of TTree::Draw in the above example.
00992 //
00993 //           Automatic interface to TTree::Draw via the TTreeViewer
00994 //           ======================================================
00995 //
00996 //    A complete graphical interface to this function is implemented
00997 //    in the class TTreeViewer.
00998 //    To start the TTreeViewer, three possibilities:
00999 //       - select TTree context menu item "StartViewer"
01000 //       - type the command  "TTreeViewer TV(treeName)"
01001 //       - execute statement "tree->StartViewer();"
01002 //
01003    if (fTree->GetEntriesFriend() == 0) return 0;
01004 
01005    // Let's see if we have a filename as arguments instead of
01006    // a TTreeFormula expression.
01007 
01008    TString possibleFilename = varexp0;
01009    Ssiz_t dot_pos = possibleFilename.Last('.');
01010    if ( dot_pos != kNPOS
01011        && possibleFilename.Index("Alt$")<0 && possibleFilename.Index("Entries$")<0
01012        && possibleFilename.Index("Length$")<0  && possibleFilename.Index("Entry$")<0
01013        && possibleFilename.Index("LocalEntry$")<0
01014        && possibleFilename.Index("Min$")<0 && possibleFilename.Index("Max$")<0
01015        && possibleFilename.Index("MinIf$")<0 && possibleFilename.Index("MaxIf$")<0
01016        && possibleFilename.Index("Iteration$")<0 && possibleFilename.Index("Sum$")<0
01017        && possibleFilename.Index(">")<0 && possibleFilename.Index("<")<0
01018        && gSystem->IsFileInIncludePath(possibleFilename.Data())) {
01019 
01020       if (selection && strlen(selection) && !gSystem->IsFileInIncludePath(selection)) {
01021          Error("DrawSelect",
01022                "Drawing using a C++ file currently requires that both the expression and the selection are files\n\t\"%s\" is not a file",
01023                selection);
01024          return 0;
01025       }
01026       return DrawScript("generatedSel",varexp0,selection,option,nentries,firstentry);
01027 
01028    } else {
01029       possibleFilename = selection;
01030       if (possibleFilename.Index("Alt$")<0 && possibleFilename.Index("Entries$")<0
01031           && possibleFilename.Index("Length$")<0  && possibleFilename.Index("Entry$")<0
01032           && possibleFilename.Index("LocalEntry$")<0
01033           && possibleFilename.Index("Min$")<0 && possibleFilename.Index("Max$")<0
01034           && possibleFilename.Index("MinIf$")<0 && possibleFilename.Index("MaxIf$")<0
01035           && possibleFilename.Index("Iteration$")<0 && possibleFilename.Index("Sum$")<0
01036           && possibleFilename.Index(">")<0 && possibleFilename.Index("<")<0
01037           && gSystem->IsFileInIncludePath(possibleFilename.Data())) {
01038 
01039          Error("DrawSelect",
01040                "Drawing using a C++ file currently requires that both the expression and the selection are files\n\t\"%s\" is not a file",
01041                varexp0);
01042          return 0;
01043       }
01044    }
01045 
01046    Long64_t oldEstimate  = fTree->GetEstimate();
01047    TEventList *evlist  = fTree->GetEventList();
01048    TEntryList *elist = fTree->GetEntryList();
01049    if (evlist && elist){
01050       elist->SetBit(kCanDelete, kTRUE);
01051    }
01052    TNamed *cvarexp    = (TNamed*)fInput->FindObject("varexp");
01053    TNamed *cselection = (TNamed*)fInput->FindObject("selection");
01054    if (cvarexp) cvarexp->SetTitle(varexp0);
01055    if (cselection) cselection->SetTitle(selection);
01056 
01057    TString opt = option;
01058    opt.ToLower();
01059    Bool_t optpara   = kFALSE;
01060    Bool_t optcandle = kFALSE;
01061    Bool_t optgl5d   = kFALSE;
01062    Bool_t optnorm   = kFALSE;
01063    if (opt.Contains("norm")) {optnorm = kTRUE; opt.ReplaceAll("norm",""); opt.ReplaceAll(" ","");}
01064    if (opt.Contains("para")) optpara = kTRUE;
01065    if (opt.Contains("candle")) optcandle = kTRUE;
01066    if (opt.Contains("gl5d")) optgl5d = kTRUE;
01067    Bool_t pgl = gStyle->GetCanvasPreferGL();
01068    if (optgl5d) {
01069       fTree->SetEstimate(fTree->GetEntries());
01070       if (!gPad) {
01071          if (pgl == kFALSE) gStyle->SetCanvasPreferGL(kTRUE);
01072          gROOT->ProcessLineFast("new TCanvas();");
01073       }
01074    }
01075 
01076 
01077    // Do not process more than fMaxEntryLoop entries
01078    if (nentries > fTree->GetMaxEntryLoop()) nentries = fTree->GetMaxEntryLoop();
01079 
01080    // invoke the selector
01081    Long64_t nrows = Process(fSelector,option,nentries,firstentry);
01082    fSelectedRows = nrows;
01083    fDimension = fSelector->GetDimension();
01084 
01085    //*-* an Event List
01086    if (fDimension <= 0) {
01087       fTree->SetEstimate(oldEstimate);
01088       if (fSelector->GetCleanElist()) {
01089          // We are in the case where the input list was reset!
01090          fTree->SetEntryList(elist);
01091          delete fSelector->GetObject();
01092       }
01093       return nrows;
01094    }
01095 
01096    // Draw generated histogram
01097    Long64_t drawflag = fSelector->GetDrawFlag();
01098    Int_t action   = fSelector->GetAction();
01099    Bool_t draw = kFALSE;
01100    if (!drawflag && !opt.Contains("goff")) draw = kTRUE;
01101    if (!optcandle && !optpara) fHistogram = (TH1*)fSelector->GetObject();
01102    if (optnorm) {
01103       Double_t sumh= fHistogram->GetSumOfWeights();
01104       if (sumh != 0) fHistogram->Scale(1./sumh);
01105    }
01106    
01107    //if (!nrows && draw && drawflag && !opt.Contains("same")) {
01108    //   if (gPad) gPad->Clear();
01109    //   return 0;
01110    //}
01111 
01112    //*-*- 1-D distribution
01113    if (fDimension == 1) {
01114       if (fSelector->GetVar1()->IsInteger()) fHistogram->LabelsDeflate("X");
01115       if (draw) fHistogram->Draw(opt.Data());
01116 
01117    //*-*- 2-D distribution
01118    } else if (fDimension == 2 && !(optpara||optcandle)) {
01119       if (fSelector->GetVar1()->IsInteger()) fHistogram->LabelsDeflate("Y");
01120       if (fSelector->GetVar2()->IsInteger()) fHistogram->LabelsDeflate("X");
01121       if (action == 4) {
01122          if (draw) fHistogram->Draw(opt.Data());
01123       } else {
01124          Bool_t graph = kFALSE;
01125          Int_t l = opt.Length();
01126          if (l == 0 || opt == "same") graph = kTRUE;
01127          if (opt.Contains("p")     || opt.Contains("*")    || opt.Contains("l"))    graph = kTRUE;
01128          if (opt.Contains("surf")  || opt.Contains("lego") || opt.Contains("cont")) graph = kFALSE;
01129          if (opt.Contains("col")   || opt.Contains("hist") || opt.Contains("scat")) graph = kFALSE;
01130          if (!graph) {
01131             if (draw) fHistogram->Draw(opt.Data());
01132          } else {
01133             if (fSelector->GetOldHistogram() && draw) fHistogram->Draw(opt.Data());
01134          }
01135       }
01136    //*-*- 3-D distribution
01137    } else if (fDimension == 3 && !(optpara||optcandle)) {
01138       if (fSelector->GetVar1()->IsInteger()) fHistogram->LabelsDeflate("Z");
01139       if (fSelector->GetVar2()->IsInteger()) fHistogram->LabelsDeflate("Y");
01140       if (fSelector->GetVar3()->IsInteger()) fHistogram->LabelsDeflate("X");
01141       if (action == 23) {
01142          if (draw) fHistogram->Draw(opt.Data());
01143       } else {
01144          Int_t noscat = opt.Length();
01145          if (opt.Contains("same")) noscat -= 4;
01146          if (noscat) {
01147             if (draw) fHistogram->Draw(opt.Data());
01148          } else {
01149             if (fSelector->GetOldHistogram() && draw) fHistogram->Draw(opt.Data());
01150          }
01151       }
01152    //*-*- 4-D distribution
01153    } else if (fDimension == 4 && !(optpara||optcandle)) {
01154       if (fSelector->GetVar1()->IsInteger()) fHistogram->LabelsDeflate("Z");
01155       if (fSelector->GetVar2()->IsInteger()) fHistogram->LabelsDeflate("Y");
01156       if (fSelector->GetVar3()->IsInteger()) fHistogram->LabelsDeflate("X");
01157       if (draw) fHistogram->Draw(opt.Data());
01158       Int_t ncolors  = gStyle->GetNumberOfColors();
01159       TObjArray *pms = (TObjArray*)fHistogram->GetListOfFunctions()->FindObject("polymarkers");
01160       for (Int_t col=0;col<ncolors;col++) {
01161          if (!pms) continue;
01162          TPolyMarker3D *pm3d = (TPolyMarker3D*)pms->UncheckedAt(col);
01163          if (draw) pm3d->Draw();
01164       }
01165    //*-*- Parallel Coordinates or Candle chart.
01166    } else if (optpara || optcandle) {
01167       if (draw) {
01168          TObject* para = fSelector->GetObject();
01169          TObject *enlist = gDirectory->FindObject("enlist");
01170          fTree->Draw(">>enlist",selection,"entrylist",nentries,firstentry);
01171          gROOT->ProcessLineFast(Form("TParallelCoord::SetEntryList((TParallelCoord*)0x%lx,(TEntryList*)0x%lx)",
01172                                      (ULong_t)para, (ULong_t)enlist));
01173       }
01174    //*-*- 5d with gl
01175    } else if (optgl5d) {
01176       gROOT->ProcessLineFast(Form("(new TGL5DDataSet((TTree *)0x%lx))->Draw(\"%s\");", (ULong_t)fTree, opt.Data()));
01177       gStyle->SetCanvasPreferGL(pgl);
01178    }
01179 
01180    if (fHistogram) fHistogram->ResetBit(TH1::kCanRebin);
01181    return fSelectedRows;
01182 }
01183 
01184 //______________________________________________________________________________
01185 Int_t TTreePlayer::Fit(const char *formula ,const char *varexp, const char *selection,Option_t *option ,Option_t *goption,Long64_t nentries, Long64_t firstentry)
01186 {
01187 // Fit  a projected item(s) from a Tree.
01188 // Returns -1 in case of error or number of selected events in case of success.
01189 //
01190 //  The formula is a TF1 expression.
01191 //
01192 //  See TTree::Draw for explanations of the other parameters.
01193 //
01194 //  By default the temporary histogram created is called htemp.
01195 //  If varexp contains >>hnew , the new histogram created is called hnew
01196 //  and it is kept in the current directory.
01197 //  Example:
01198 //    tree.Fit("pol4","sqrt(x)>>hsqrt","y>0")
01199 //    will fit sqrt(x) and save the histogram as "hsqrt" in the current
01200 //    directory.
01201 //
01202 //   Return status
01203 //   =============
01204 // The function returns the status of the histogram fit (see TH1::Fit)
01205 // If no entries were selected, the function returns -1;
01206 //   (i.e. fitResult is null if the fit is OK)
01207 
01208    Int_t nch = option ? strlen(option) + 10 : 10;
01209    char *opt = new char[nch];
01210    if (option) strlcpy(opt,option,nch-1);
01211    else        strlcpy(opt,"goff",5);
01212    
01213    Long64_t nsel = DrawSelect(varexp,selection,opt,nentries,firstentry);
01214 
01215    delete [] opt;
01216    Int_t fitResult = -1;
01217 
01218    if (fHistogram && nsel > 0) {
01219       fitResult = fHistogram->Fit(formula,option,goption);
01220    }
01221    return fitResult;
01222 }
01223 
01224 //______________________________________________________________________________
01225 Long64_t TTreePlayer::GetEntries(const char *selection)
01226 {
01227    // Return the number of entries matching the selection.
01228    // Return -1 in case of errors.
01229    //
01230    // If the selection uses any arrays or containers, we return the number
01231    // of entries where at least one element match the selection.
01232    // GetEntries is implemented using the selector class TSelectorEntries,
01233    // which can be used directly (see code in TTreePlayer::GetEntries) for
01234    // additional option.
01235    // If SetEventList was used on the TTree or TChain, only that subset
01236    // of entries will be considered.
01237 
01238    TSelectorEntries s(selection);
01239    fTree->Process(&s);
01240    fTree->SetNotify(0);
01241    return s.GetSelectedRows();
01242 }
01243 
01244 //______________________________________________________________________________
01245 Long64_t TTreePlayer::GetEntriesToProcess(Long64_t firstentry, Long64_t nentries) const
01246 {
01247    // return the number of entries to be processed
01248    // this function checks that nentries is not bigger than the number
01249    // of entries in the Tree or in the associated TEventlist
01250 
01251    Long64_t lastentry = firstentry + nentries - 1;
01252    if (lastentry > fTree->GetEntriesFriend()-1) {
01253       lastentry  = fTree->GetEntriesFriend() - 1;
01254       nentries   = lastentry - firstentry + 1;
01255    }
01256    //TEventList *elist = fTree->GetEventList();
01257    //if (elist && elist->GetN() < nentries) nentries = elist->GetN();
01258    TEntryList *elist = fTree->GetEntryList();
01259    if (elist && elist->GetN() < nentries) nentries = elist->GetN();
01260    return nentries;
01261 }
01262 
01263 //______________________________________________________________________________
01264 const char *TTreePlayer::GetNameByIndex(TString &varexp, Int_t *index,Int_t colindex)
01265 {
01266 //*-*-*-*-*-*-*-*-*Return name corresponding to colindex in varexp*-*-*-*-*-*
01267 //*-*              ===============================================
01268 //
01269 //   varexp is a string of names separated by :
01270 //   index is an array with pointers to the start of name[i] in varexp
01271 //
01272 
01273    Int_t i1,n;
01274    static TString column;
01275    if (colindex<0 ) return "";
01276    i1 = index[colindex] + 1;
01277    n  = index[colindex+1] - i1;
01278    column = varexp(i1,n);
01279    //  return (const char*)Form((const char*)column);
01280    return column.Data();
01281 }
01282 
01283 //______________________________________________________________________________
01284 static TString R__GetBranchPointerName(TLeaf *leaf)
01285 {
01286    // Return the name of the branch pointer needed by MakeClass/MakeSelector
01287 
01288    TLeaf *leafcount = leaf->GetLeafCount();
01289    TBranch *branch = leaf->GetBranch();
01290 
01291    TString branchname( branch->GetName() );
01292 
01293    if ( branch->GetNleaves() <= 1 ) {
01294        if (branch->IsA() != TBranchObject::Class()) {
01295          if (!leafcount) {
01296             TBranch *mother = branch->GetMother();
01297             const char* ltitle = leaf->GetTitle();
01298             if (mother && mother!=branch) {
01299                branchname = mother->GetName();
01300                if (branchname[branchname.Length()-1]!='.') {
01301                   branchname += ".";
01302                }
01303                if (strncmp(branchname.Data(),ltitle,branchname.Length())==0) {
01304                   branchname = "";
01305                }
01306             } else {
01307                branchname = "";
01308             }
01309             branchname += ltitle;
01310          }
01311       }
01312    }
01313    char *bname = (char*)branchname.Data();
01314    char *twodim = (char*)strstr(bname,"[");
01315    if (twodim) *twodim = 0;
01316    while (*bname) {
01317       if (*bname == '.') *bname='_';
01318       if (*bname == ',') *bname='_';
01319       if (*bname == ':') *bname='_';
01320       if (*bname == '<') *bname='_';
01321       if (*bname == '>') *bname='_';
01322       bname++;
01323    }
01324    return branchname;
01325 }
01326 
01327 //______________________________________________________________________________
01328 Int_t TTreePlayer::MakeClass(const char *classname, const char *option)
01329 {
01330 // Generate skeleton analysis class for this Tree.
01331 //
01332 // The following files are produced: classname.h and classname.C
01333 // If classname is 0, classname will be called "nameoftree.
01334 //
01335 // The generated code in classname.h includes the following:
01336 //    - Identification of the original Tree and Input file name
01337 //    - Definition of analysis class (data and functions)
01338 //    - the following class functions:
01339 //       - constructor (connecting by default the Tree file)
01340 //       - GetEntry(Long64_t entry)
01341 //       - Init(TTree *tree) to initialize a new TTree
01342 //       - Show(Long64_t entry) to read and Dump entry
01343 //
01344 // The generated code in classname.C includes only the main
01345 // analysis function Loop.
01346 //
01347 // To use this function:
01348 //    - connect your Tree file (eg: TFile f("myfile.root");)
01349 //    - T->MakeClass("MyClass");
01350 // where T is the name of the Tree in file myfile.root
01351 // and MyClass.h, MyClass.C the name of the files created by this function.
01352 // In a ROOT session, you can do:
01353 //    root > .L MyClass.C
01354 //    root > MyClass t
01355 //    root > t.GetEntry(12); // Fill t data members with entry number 12
01356 //    root > t.Show();       // Show values of entry 12
01357 //    root > t.Show(16);     // Read and show values of entry 16
01358 //    root > t.Loop();       // Loop on all entries
01359 //
01360 //  NOTE: Do not use the code generated for one Tree in case of a TChain.
01361 //        Maximum dimensions calculated on the basis of one TTree only
01362 //        might be too small when processing all the TTrees in one TChain.
01363 //        Instead of myTree.MakeClass(..,  use myChain.MakeClass(..
01364 
01365    TString opt = option;
01366    opt.ToLower();
01367 
01368    // Connect output files
01369    if (!classname) classname = fTree->GetName();
01370 
01371    TString thead;
01372    thead.Form("%s.h", classname);
01373    FILE *fp = fopen(thead, "w");
01374    if (!fp) {
01375       Error("MakeClass","cannot open output file %s", thead.Data());
01376       return 3;
01377    }
01378    TString tcimp;
01379    tcimp.Form("%s.C", classname);
01380    FILE *fpc = fopen(tcimp, "w");
01381    if (!fpc) {
01382       Error("MakeClass","cannot open output file %s", tcimp.Data());
01383       fclose(fp);
01384       return 3;
01385    }
01386    TString treefile;
01387    if (fTree->GetDirectory() && fTree->GetDirectory()->GetFile()) {
01388       treefile = fTree->GetDirectory()->GetFile()->GetName();
01389    } else {
01390       treefile = "Memory Directory";
01391    }
01392    // In the case of a chain, the GetDirectory information usually does
01393    // pertain to the Chain itself but to the currently loaded tree.
01394    // So we can not rely on it.
01395    Bool_t ischain = fTree->InheritsFrom(TChain::Class());
01396    Bool_t isHbook = fTree->InheritsFrom("THbookTree");
01397    if (isHbook)
01398       treefile = fTree->GetTitle();
01399 
01400 //======================Generate classname.h=====================
01401    // Print header
01402    TObjArray *leaves = fTree->GetListOfLeaves();
01403    Int_t nleaves = leaves ? leaves->GetEntriesFast() : 0;
01404    TDatime td;
01405    fprintf(fp,"//////////////////////////////////////////////////////////\n");
01406    fprintf(fp,"// This class has been automatically generated on\n");
01407    fprintf(fp,"// %s by ROOT version %s\n",td.AsString(),gROOT->GetVersion());
01408    if (!ischain) {
01409       fprintf(fp,"// from TTree %s/%s\n",fTree->GetName(),fTree->GetTitle());
01410       fprintf(fp,"// found on file: %s\n",treefile.Data());
01411    } else {
01412       fprintf(fp,"// from TChain %s/%s\n",fTree->GetName(),fTree->GetTitle());
01413    }
01414    fprintf(fp,"//////////////////////////////////////////////////////////\n");
01415    fprintf(fp,"\n");
01416    fprintf(fp,"#ifndef %s_h\n",classname);
01417    fprintf(fp,"#define %s_h\n",classname);
01418    fprintf(fp,"\n");
01419    fprintf(fp,"#include <TROOT.h>\n");
01420    fprintf(fp,"#include <TChain.h>\n");
01421    fprintf(fp,"#include <TFile.h>\n");
01422    if (isHbook) fprintf(fp,"#include <THbookFile.h>\n");
01423    if (opt.Contains("selector")) fprintf(fp,"#include <TSelector.h>\n");
01424 
01425 // First loop on all leaves to generate dimension declarations
01426    Int_t len, lenb,l;
01427    char blen[1024];
01428    char *bname;
01429    Int_t *leaflen = new Int_t[nleaves];
01430    TObjArray *leafs = new TObjArray(nleaves);
01431    for (l=0;l<nleaves;l++) {
01432       TLeaf *leaf = (TLeaf*)leaves->UncheckedAt(l);
01433       leafs->AddAt(new TObjString(leaf->GetName()),l);
01434       leaflen[l] = leaf->GetMaximum();
01435    }
01436    if (ischain) {
01437       // In case of a chain, one must find the maximum dimension of each leaf
01438       // One must be careful and not assume that all Trees in the chain
01439       // have the same leaves and in the same order!
01440       TChain *chain = (TChain*)fTree;
01441       Int_t ntrees = chain->GetNtrees();
01442       for (Int_t file=0;file<ntrees;file++) {
01443          Long64_t first = chain->GetTreeOffset()[file];
01444          chain->LoadTree(first);
01445          for (l=0;l<nleaves;l++) {
01446             TObjString *obj = (TObjString*)leafs->At(l);
01447             TLeaf *leaf = chain->GetLeaf(obj->GetName());
01448             if (leaf) {
01449                leaflen[l] = TMath::Max(leaflen[l],leaf->GetMaximum());
01450             }
01451          }
01452       }
01453       chain->LoadTree(0);
01454    }
01455 
01456    leaves = fTree->GetListOfLeaves();
01457    for (l=0;l<nleaves;l++) {
01458       TLeaf *leaf = (TLeaf*)leaves->UncheckedAt(l);
01459       strlcpy(blen,leaf->GetName(),sizeof(blen)); 
01460       bname = &blen[0];
01461       while (*bname) {
01462          if (*bname == '.') *bname='_';
01463          if (*bname == ',') *bname='_';
01464          if (*bname == ':') *bname='_';
01465          if (*bname == '<') *bname='_';
01466          if (*bname == '>') *bname='_';
01467          bname++;
01468       }
01469       lenb = strlen(blen);
01470       if (blen[lenb-1] == '_') {
01471          blen[lenb-1] = 0;
01472          len = leaflen[l];
01473          if (len <= 0) len = 1;
01474          fprintf(fp,"   const Int_t kMax%s = %d;\n",blen,len);
01475       }
01476    }
01477    delete [] leaflen;
01478    leafs->Delete();
01479    delete leafs;
01480 
01481 // second loop on all leaves to generate type declarations
01482    fprintf(fp,"\n");
01483    if (opt.Contains("selector")) {
01484       fprintf(fp,"class %s : public TSelector {\n",classname);
01485       fprintf(fp,"public :\n");
01486       fprintf(fp,"   TTree          *fChain;   //!pointer to the analyzed TTree or TChain\n");
01487    } else {
01488       fprintf(fp,"class %s {\n",classname);
01489       fprintf(fp,"public :\n");
01490       fprintf(fp,"   TTree          *fChain;   //!pointer to the analyzed TTree or TChain\n");
01491       fprintf(fp,"   Int_t           fCurrent; //!current Tree number in a TChain\n");
01492    }
01493    fprintf(fp,"\n   // Declaration of leaf types\n");
01494    TLeaf *leafcount;
01495    TLeafObject *leafobj;
01496    TBranchElement *bre=0;
01497    const char *headOK  = "   ";
01498    const char *headcom = " //";
01499    const char *head;
01500    char branchname[1024];
01501    char aprefix[1024];
01502    TObjArray branches(100);
01503    TObjArray mustInit(100);
01504    TObjArray mustInitArr(100);
01505    mustInitArr.SetOwner(kFALSE);
01506    Int_t *leafStatus = new Int_t[nleaves];
01507    for (l=0;l<nleaves;l++) {
01508       Int_t kmax = 0;
01509       head = headOK;
01510       leafStatus[l] = 0;
01511       TLeaf *leaf = (TLeaf*)leaves->UncheckedAt(l);
01512       len = leaf->GetLen(); if (len<=0) len = 1;
01513       leafcount =leaf->GetLeafCount();
01514       TBranch *branch = leaf->GetBranch();
01515       branchname[0] = 0;
01516       strlcpy(branchname,branch->GetName(),sizeof(branchname)); 
01517       strlcpy(aprefix,branch->GetName(),sizeof(aprefix)); 
01518       if (!branches.FindObject(branch)) branches.Add(branch);
01519       else leafStatus[l] = 1;
01520       if ( branch->GetNleaves() > 1) {
01521          // More than one leaf for the branch we need to distinguish them
01522          strlcat(branchname,".",sizeof(branchname));
01523          strlcat(branchname,leaf->GetTitle(),sizeof(branchname));
01524          if (leafcount) {
01525             // remove any dimension in title
01526             char *dim =  (char*)strstr(branchname,"["); if (dim) dim[0] = 0;
01527          }
01528       } else {
01529          strlcpy(branchname,branch->GetName(),sizeof(branchname)); 
01530       }
01531       char *twodim = (char*)strstr(leaf->GetTitle(),"][");
01532       bname = branchname;
01533       while (*bname) {
01534          if (*bname == '.') *bname='_';
01535          if (*bname == ',') *bname='_';
01536          if (*bname == ':') *bname='_';
01537          if (*bname == '<') *bname='_';
01538          if (*bname == '>') *bname='_';
01539          bname++;
01540       }
01541       if (branch->IsA() == TBranchObject::Class()) {
01542          if (branch->GetListOfBranches()->GetEntriesFast()) {leafStatus[l] = 1; continue;}
01543          leafobj = (TLeafObject*)leaf;
01544          if (!leafobj->GetClass()) {leafStatus[l] = 1; head = headcom;}
01545          fprintf(fp,"%s%-15s *%s;\n",head,leafobj->GetTypeName(), leafobj->GetName());
01546          if (leafStatus[l] == 0) mustInit.Add(leafobj);
01547          continue;
01548       }
01549       if (leafcount) {
01550          len = leafcount->GetMaximum();
01551          if (len<=0) len = 1;
01552          strlcpy(blen,leafcount->GetName(),sizeof(blen)); 
01553          bname = &blen[0];
01554          while (*bname) {
01555             if (*bname == '.') *bname='_';
01556             if (*bname == ',') *bname='_';
01557             if (*bname == ':') *bname='_';
01558             if (*bname == '<') *bname='_';
01559             if (*bname == '>') *bname='_';
01560             bname++;
01561          }
01562          lenb = strlen(blen);
01563          if (blen[lenb-1] == '_') {blen[lenb-1] = 0; kmax = 1;}
01564          else                     snprintf(blen,sizeof(blen),"%d",len);
01565       }
01566       if (branch->IsA() == TBranchElement::Class()) {
01567          bre = (TBranchElement*)branch;
01568          if (bre->GetType() != 3 && bre->GetType() != 4
01569              && bre->GetStreamerType() <= 0 && bre->GetListOfBranches()->GetEntriesFast()) {
01570             leafStatus[l] = 0;
01571          }
01572          if (bre->GetType() == 3 || bre->GetType() == 4) {
01573             fprintf(fp,"   %-15s %s_;\n","Int_t", branchname);
01574             continue;
01575          }
01576          if (bre->IsBranchFolder()) {
01577             fprintf(fp,"   %-15s *%s;\n",bre->GetClassName(), branchname);
01578             mustInit.Add(bre);
01579             continue;
01580          } else {
01581             if (branch->GetListOfBranches()->GetEntriesFast()) {leafStatus[l] = 1;}
01582          }
01583          if (bre->GetStreamerType() < 0) {
01584             if (branch->GetListOfBranches()->GetEntriesFast()) {
01585                fprintf(fp,"%s%-15s *%s;\n",headcom,bre->GetClassName(), branchname);
01586             } else {
01587                fprintf(fp,"%s%-15s *%s;\n",head,bre->GetClassName(), branchname);
01588                mustInit.Add(bre);
01589             }
01590             continue;
01591          }
01592          if (bre->GetStreamerType() == 0) {
01593             if (!TClass::GetClass(bre->GetClassName())->GetClassInfo()) {leafStatus[l] = 1; head = headcom;}
01594             fprintf(fp,"%s%-15s *%s;\n",head,bre->GetClassName(), branchname);
01595             if (leafStatus[l] == 0) mustInit.Add(bre);
01596             continue;
01597          }
01598          if (bre->GetStreamerType() > 60) {
01599             TClass *cle = TClass::GetClass(bre->GetClassName());
01600             if (!cle) {leafStatus[l] = 1; continue;}
01601             if (bre->GetStreamerType() == 66) leafStatus[l] = 0;
01602             char brename[256];
01603             strlcpy(brename,bre->GetName(),255); 
01604             char *bren = brename;
01605             char *adot = strrchr(bren,'.');
01606             if (adot) bren = adot+1;
01607             char *brack = strchr(bren,'[');
01608             if (brack) *brack = 0;
01609             TStreamerElement *elem = (TStreamerElement*)cle->GetStreamerInfo()->GetElements()->FindObject(bren);
01610             if (elem) {
01611                if (elem->IsA() == TStreamerBase::Class()) {leafStatus[l] = 1; continue;}
01612                if (!TClass::GetClass(elem->GetTypeName())) {leafStatus[l] = 1; continue;}
01613                if (!TClass::GetClass(elem->GetTypeName())->GetClassInfo()) {leafStatus[l] = 1; head = headcom;}
01614                if (leafcount) fprintf(fp,"%s%-15s %s[kMax%s];\n",head,elem->GetTypeName(), branchname,blen);
01615                else           fprintf(fp,"%s%-15s %s;\n",head,elem->GetTypeName(), branchname);
01616             } else {
01617                if (!TClass::GetClass(bre->GetClassName())->GetClassInfo()) {leafStatus[l] = 1; head = headcom;}
01618                fprintf(fp,"%s%-15s %s;\n",head,bre->GetClassName(), branchname);
01619             }
01620             continue;
01621          }
01622       }
01623       if (strlen(leaf->GetTypeName()) == 0) {leafStatus[l] = 1; continue;}
01624       if (leafcount) {
01625          //len = leafcount->GetMaximum();
01626          //strlcpy(blen,leafcount->GetName(),sizeof(blen));
01627          //bname = &blen[0];
01628          //while (*bname) {if (*bname == '.') *bname='_'; bname++;}
01629          //lenb = strlen(blen);
01630          //Int_t kmax = 0;
01631          //if (blen[lenb-1] == '_') {blen[lenb-1] = 0; kmax = 1;}
01632          //else                     sprintf(blen,"%d",len);
01633 
01634          const char *stars = " ";
01635          if (bre && bre->GetBranchCount2()) {
01636             stars = "*";
01637          }
01638          // Dimensions can be in the branchname for a split Object with a fix length C array.
01639          // Theses dimensions HAVE TO be placed after the dimension explicited by leafcount
01640          TString dimensions;
01641          char *dimInName = (char*) strstr(branchname,"[");
01642          if ( twodim || dimInName ) {
01643             if (dimInName) {
01644                dimensions = dimInName; 
01645                dimInName[0] = 0; // terminate branchname before the array dimensions.
01646             }
01647             if (twodim) dimensions += (char*)(twodim+1);
01648          }
01649          const char* leafcountName = leafcount->GetName();
01650          char b2len[1024];
01651          if (bre && bre->GetBranchCount2()) {
01652             TLeaf * l2 = (TLeaf*)bre->GetBranchCount2()->GetListOfLeaves()->At(0);
01653             strlcpy(b2len,l2->GetName(),sizeof(b2len)); 
01654             bname = &b2len[0];
01655             while (*bname) {
01656                if (*bname == '.') *bname='_';
01657                if (*bname == ',') *bname='_';
01658                if (*bname == ':') *bname='_';
01659                if (*bname == '<') *bname='_';
01660                if (*bname == '>') *bname='_';
01661                bname++;
01662             }
01663             leafcountName = b2len;
01664          }
01665          if (dimensions.Length()) {
01666             if (kmax) fprintf(fp,"   %-14s %s%s[kMax%s]%s;   //[%s]\n",leaf->GetTypeName(), stars,
01667                               branchname,blen,dimensions.Data(),leafcountName);
01668             else      fprintf(fp,"   %-14s %s%s[%d]%s;   //[%s]\n",leaf->GetTypeName(), stars,
01669                               branchname,len,dimensions.Data(),leafcountName);
01670          } else {
01671             if (kmax) fprintf(fp,"   %-14s %s%s[kMax%s];   //[%s]\n",leaf->GetTypeName(), stars, branchname,blen,leafcountName);
01672             else      fprintf(fp,"   %-14s %s%s[%d];   //[%s]\n",leaf->GetTypeName(), stars, branchname,len,leafcountName);
01673          }
01674          if (stars[0]=='*') {
01675             TNamed *n;
01676             if (kmax) n = new TNamed(branchname, Form("kMax%s",blen));
01677             else n = new TNamed(branchname, Form("%d",len));
01678             mustInitArr.Add(n);
01679          }
01680       } else {
01681          if (strstr(branchname,"[")) len = 1;
01682          if (len < 2) fprintf(fp,"   %-15s %s;\n",leaf->GetTypeName(), branchname);
01683          else {
01684             if (twodim) fprintf(fp,"   %-15s %s%s;\n",leaf->GetTypeName(), branchname,(char*)strstr(leaf->GetTitle(),"["));
01685             else        fprintf(fp,"   %-15s %s[%d];\n",leaf->GetTypeName(), branchname,len);
01686          }
01687       }
01688    }
01689 
01690 // generate list of branches
01691    fprintf(fp,"\n");
01692    fprintf(fp,"   // List of branches\n");
01693    for (l=0;l<nleaves;l++) {
01694       if (leafStatus[l]) continue;
01695       TLeaf *leaf = (TLeaf*)leaves->UncheckedAt(l);
01696       fprintf(fp,"   TBranch        *b_%s;   //!\n",R__GetBranchPointerName(leaf).Data());
01697    }
01698 
01699 // generate class member functions prototypes
01700    if (opt.Contains("selector")) {
01701       fprintf(fp,"\n");
01702       fprintf(fp,"   %s(TTree * /*tree*/ =0) { }\n",classname) ;
01703       fprintf(fp,"   virtual ~%s() { }\n",classname);
01704       fprintf(fp,"   virtual Int_t   Version() const { return 2; }\n");
01705       fprintf(fp,"   virtual void    Begin(TTree *tree);\n");
01706       fprintf(fp,"   virtual void    SlaveBegin(TTree *tree);\n");
01707       fprintf(fp,"   virtual void    Init(TTree *tree);\n");
01708       fprintf(fp,"   virtual Bool_t  Notify();\n");
01709       fprintf(fp,"   virtual Bool_t  Process(Long64_t entry);\n");
01710       fprintf(fp,"   virtual Int_t   GetEntry(Long64_t entry, Int_t getall = 0) { return fChain ? fChain->GetTree()->GetEntry(entry, getall) : 0; }\n");
01711       fprintf(fp,"   virtual void    SetOption(const char *option) { fOption = option; }\n");
01712       fprintf(fp,"   virtual void    SetObject(TObject *obj) { fObject = obj; }\n");
01713       fprintf(fp,"   virtual void    SetInputList(TList *input) { fInput = input; }\n");
01714       fprintf(fp,"   virtual TList  *GetOutputList() const { return fOutput; }\n");
01715       fprintf(fp,"   virtual void    SlaveTerminate();\n");
01716       fprintf(fp,"   virtual void    Terminate();\n\n");
01717       fprintf(fp,"   ClassDef(%s,0);\n",classname);
01718       fprintf(fp,"};\n");
01719       fprintf(fp,"\n");
01720       fprintf(fp,"#endif\n");
01721       fprintf(fp,"\n");
01722    } else {
01723       fprintf(fp,"\n");
01724       fprintf(fp,"   %s(TTree *tree=0);\n",classname);
01725       fprintf(fp,"   virtual ~%s();\n",classname);
01726       fprintf(fp,"   virtual Int_t    Cut(Long64_t entry);\n");
01727       fprintf(fp,"   virtual Int_t    GetEntry(Long64_t entry);\n");
01728       fprintf(fp,"   virtual Long64_t LoadTree(Long64_t entry);\n");
01729       fprintf(fp,"   virtual void     Init(TTree *tree);\n");
01730       fprintf(fp,"   virtual void     Loop();\n");
01731       fprintf(fp,"   virtual Bool_t   Notify();\n");
01732       fprintf(fp,"   virtual void     Show(Long64_t entry = -1);\n");
01733       fprintf(fp,"};\n");
01734       fprintf(fp,"\n");
01735       fprintf(fp,"#endif\n");
01736       fprintf(fp,"\n");
01737    }
01738 // generate code for class constructor
01739    fprintf(fp,"#ifdef %s_cxx\n",classname);
01740    if (!opt.Contains("selector")) {
01741       fprintf(fp,"%s::%s(TTree *tree)\n",classname,classname);
01742       fprintf(fp,"{\n");
01743       fprintf(fp,"// if parameter tree is not specified (or zero), connect the file\n");
01744       fprintf(fp,"// used to generate this class and read the Tree.\n");
01745       fprintf(fp,"   if (tree == 0) {\n");
01746       if (ischain) {
01747          fprintf(fp,"\n#ifdef SINGLE_TREE\n");
01748          fprintf(fp,"      // The following code should be used if you want this class to access\n");
01749          fprintf(fp,"      // a single tree instead of a chain\n");
01750       }
01751       if (isHbook) {
01752          fprintf(fp,"      THbookFile *f = (THbookFile*)gROOT->GetListOfBrowsables()->FindObject(\"%s\");\n",
01753                     treefile.Data());
01754          fprintf(fp,"      if (!f) {\n");
01755          fprintf(fp,"         f = new THbookFile(\"%s\");\n",treefile.Data());
01756          fprintf(fp,"      }\n");
01757          Int_t hid;
01758          sscanf(fTree->GetName(),"h%d",&hid);
01759          fprintf(fp,"      tree = (TTree*)f->Get(%d);\n\n",hid);
01760       } else {
01761          fprintf(fp,"      TFile *f = (TFile*)gROOT->GetListOfFiles()->FindObject(\"%s\");\n",treefile.Data());
01762          fprintf(fp,"      if (!f) {\n");
01763          fprintf(fp,"         f = new TFile(\"%s\");\n",treefile.Data());
01764          if (gDirectory != gFile) {
01765             fprintf(fp,"         f->cd(\"%s\");\n",gDirectory->GetPath());
01766          }
01767          fprintf(fp,"      }\n");
01768          fprintf(fp,"      tree = (TTree*)gDirectory->Get(\"%s\");\n\n",fTree->GetName());
01769       }
01770       if (ischain) {
01771          fprintf(fp,"#else // SINGLE_TREE\n\n");
01772          fprintf(fp,"      // The following code should be used if you want this class to access a chain\n");
01773          fprintf(fp,"      // of trees.\n");
01774          fprintf(fp,"      TChain * chain = new TChain(\"%s\",\"%s\");\n",
01775                  fTree->GetName(),fTree->GetTitle());
01776          TIter next(((TChain*)fTree)->GetListOfFiles());
01777          TChainElement *element;
01778          while ((element = (TChainElement*)next())) {
01779             fprintf(fp,"      chain->Add(\"%s/%s\");\n",element->GetTitle(),element->GetName());
01780          }
01781          fprintf(fp,"      tree = chain;\n");
01782          fprintf(fp,"#endif // SINGLE_TREE\n\n");
01783       }
01784       fprintf(fp,"   }\n");
01785       fprintf(fp,"   Init(tree);\n");
01786       fprintf(fp,"}\n");
01787       fprintf(fp,"\n");
01788    }
01789 
01790 // generate code for class destructor()
01791    if (!opt.Contains("selector")) {
01792       fprintf(fp,"%s::~%s()\n",classname,classname);
01793       fprintf(fp,"{\n");
01794       fprintf(fp,"   if (!fChain) return;\n");
01795       if (isHbook) {
01796          //fprintf(fp,"   delete fChain->GetCurrentFile();\n");
01797       } else {
01798          fprintf(fp,"   delete fChain->GetCurrentFile();\n");
01799       }
01800       fprintf(fp,"}\n");
01801       fprintf(fp,"\n");
01802    }
01803 // generate code for class member function GetEntry()
01804    if (!opt.Contains("selector")) {
01805       fprintf(fp,"Int_t %s::GetEntry(Long64_t entry)\n",classname);
01806       fprintf(fp,"{\n");
01807       fprintf(fp,"// Read contents of entry.\n");
01808 
01809       fprintf(fp,"   if (!fChain) return 0;\n");
01810       fprintf(fp,"   return fChain->GetEntry(entry);\n");
01811       fprintf(fp,"}\n");
01812    }
01813 // generate code for class member function LoadTree()
01814    if (!opt.Contains("selector")) {
01815       fprintf(fp,"Long64_t %s::LoadTree(Long64_t entry)\n",classname);
01816       fprintf(fp,"{\n");
01817       fprintf(fp,"// Set the environment to read one entry\n");
01818       fprintf(fp,"   if (!fChain) return -5;\n");
01819       fprintf(fp,"   Long64_t centry = fChain->LoadTree(entry);\n");
01820       fprintf(fp,"   if (centry < 0) return centry;\n");
01821       fprintf(fp,"   if (!fChain->InheritsFrom(TChain::Class()))  return centry;\n");
01822       fprintf(fp,"   TChain *chain = (TChain*)fChain;\n");
01823       fprintf(fp,"   if (chain->GetTreeNumber() != fCurrent) {\n");
01824       fprintf(fp,"      fCurrent = chain->GetTreeNumber();\n");
01825       fprintf(fp,"      Notify();\n");
01826       fprintf(fp,"   }\n");
01827       fprintf(fp,"   return centry;\n");
01828       fprintf(fp,"}\n");
01829       fprintf(fp,"\n");
01830    }
01831 
01832 // generate code for class member function Init(), first pass = get branch pointer
01833    fprintf(fp,"void %s::Init(TTree *tree)\n",classname);
01834    fprintf(fp,"{\n");
01835    fprintf(fp,"   // The Init() function is called when the selector needs to initialize\n"
01836               "   // a new tree or chain. Typically here the branch addresses and branch\n"
01837               "   // pointers of the tree will be set.\n"
01838               "   // It is normally not necessary to make changes to the generated\n"
01839               "   // code, but the routine can be extended by the user if needed.\n"
01840               "   // Init() will be called many times when running on PROOF\n"
01841               "   // (once per file to be processed).\n\n");
01842    if (mustInit.Last()) {
01843       TIter next(&mustInit);
01844       TObject *obj;
01845       fprintf(fp,"   // Set object pointer\n");
01846       while( (obj = next()) ) {
01847          if (obj->InheritsFrom(TBranch::Class())) {
01848             strlcpy(branchname,((TBranch*)obj)->GetName(),sizeof(branchname));
01849          } else if (obj->InheritsFrom(TLeaf::Class())) {
01850             strlcpy(branchname,((TLeaf*)obj)->GetName(),sizeof(branchname)); 
01851          }
01852          branchname[1023]=0;
01853          bname = branchname;
01854          while (*bname) {
01855             if (*bname == '.') *bname='_';
01856             if (*bname == ',') *bname='_';
01857             if (*bname == ':') *bname='_';
01858             if (*bname == '<') *bname='_';
01859             if (*bname == '>') *bname='_';
01860             bname++;
01861          }
01862          fprintf(fp,"   %s = 0;\n",branchname );
01863       }
01864    }
01865    if (mustInitArr.Last()) {
01866       TIter next(&mustInitArr);
01867       TNamed *info;
01868       fprintf(fp,"   // Set array pointer\n");
01869       while( (info = (TNamed*)next()) ) {
01870          fprintf(fp,"   for(int i=0; i<%s; ++i) %s[i] = 0;\n",info->GetTitle(),info->GetName());
01871       }
01872       fprintf(fp,"\n");
01873    }
01874    fprintf(fp,"   // Set branch addresses and branch pointers\n");
01875    fprintf(fp,"   if (!tree) return;\n");
01876    fprintf(fp,"   fChain = tree;\n");
01877    if (!opt.Contains("selector")) fprintf(fp,"   fCurrent = -1;\n");
01878    fprintf(fp,"   fChain->SetMakeClass(1);\n");
01879    fprintf(fp,"\n");
01880    for (l=0;l<nleaves;l++) {
01881       if (leafStatus[l]) continue;
01882       TLeaf *leaf = (TLeaf*)leaves->UncheckedAt(l);
01883       len = leaf->GetLen();
01884       leafcount =leaf->GetLeafCount();
01885       TBranch *branch = leaf->GetBranch();
01886       strlcpy(aprefix,branch->GetName(),sizeof(aprefix)); 
01887 
01888       if ( branch->GetNleaves() > 1) {
01889          // More than one leaf for the branch we need to distinguish them
01890          strlcpy(branchname,branch->GetName(),sizeof(branchname)); 
01891          strlcat(branchname,".",sizeof(branchname));
01892          strlcat(branchname,leaf->GetTitle(),sizeof(branchname));
01893          if (leafcount) {
01894             // remove any dimension in title
01895             char *dim =  (char*)strstr(branchname,"["); if (dim) dim[0] = 0;
01896          }
01897       } else {
01898          strlcpy(branchname,branch->GetName(),sizeof(branchname)); 
01899          if (branch->IsA() == TBranchElement::Class()) {
01900             bre = (TBranchElement*)branch;
01901             if (bre->GetType() == 3 || bre->GetType()==4) strlcat(branchname,"_",sizeof(branchname));
01902          }
01903       }
01904       bname = branchname;
01905       char *brak = strstr(branchname,"[");     if (brak) *brak = 0;
01906       char *twodim = (char*)strstr(bname,"["); if (twodim) *twodim = 0;
01907       while (*bname) {
01908          if (*bname == '.') *bname='_';
01909          if (*bname == ',') *bname='_';
01910          if (*bname == ':') *bname='_';
01911          if (*bname == '<') *bname='_';
01912          if (*bname == '>') *bname='_';
01913          bname++;
01914       }
01915       if (branch->IsA() == TBranchObject::Class()) {
01916          if (branch->GetListOfBranches()->GetEntriesFast()) {
01917             fprintf(fp,"   fChain->SetBranchAddress(\"%s\",(void*)-1,&b_%s);\n",branch->GetName(),R__GetBranchPointerName(leaf).Data());
01918             continue;
01919          }
01920          strlcpy(branchname,branch->GetName(),sizeof(branchname)); 
01921       }
01922       if (branch->IsA() == TBranchElement::Class()) {
01923          if (((TBranchElement*)branch)->GetType() == 3) len =1;
01924          if (((TBranchElement*)branch)->GetType() == 4) len =1;
01925       }
01926       if (leafcount) len = leafcount->GetMaximum()+1;
01927       if (len > 1) fprintf(fp,"   fChain->SetBranchAddress(\"%s\", %s, &b_%s);\n",
01928                            branch->GetName(), branchname, R__GetBranchPointerName(leaf).Data());
01929       else         fprintf(fp,"   fChain->SetBranchAddress(\"%s\", &%s, &b_%s);\n",
01930                            branch->GetName(), branchname, R__GetBranchPointerName(leaf).Data());
01931    }
01932    //must call Notify in case of MakeClass
01933    if (!opt.Contains("selector")) {
01934       fprintf(fp,"   Notify();\n");
01935    }
01936 
01937    fprintf(fp,"}\n");
01938    fprintf(fp,"\n");
01939 
01940 // generate code for class member function Notify()
01941    fprintf(fp,"Bool_t %s::Notify()\n",classname);
01942    fprintf(fp,"{\n");
01943    fprintf(fp,"   // The Notify() function is called when a new file is opened. This\n"
01944               "   // can be either for a new TTree in a TChain or when when a new TTree\n"
01945               "   // is started when using PROOF. It is normally not necessary to make changes\n"
01946               "   // to the generated code, but the routine can be extended by the\n"
01947               "   // user if needed. The return value is currently not used.\n\n");
01948    fprintf(fp,"   return kTRUE;\n");
01949    fprintf(fp,"}\n");
01950    fprintf(fp,"\n");
01951 
01952 // generate code for class member function Show()
01953    if (!opt.Contains("selector")) {
01954       fprintf(fp,"void %s::Show(Long64_t entry)\n",classname);
01955       fprintf(fp,"{\n");
01956       fprintf(fp,"// Print contents of entry.\n");
01957       fprintf(fp,"// If entry is not specified, print current entry\n");
01958 
01959       fprintf(fp,"   if (!fChain) return;\n");
01960       fprintf(fp,"   fChain->Show(entry);\n");
01961       fprintf(fp,"}\n");
01962    }
01963 // generate code for class member function Cut()
01964    if (!opt.Contains("selector")) {
01965       fprintf(fp,"Int_t %s::Cut(Long64_t entry)\n",classname);
01966       fprintf(fp,"{\n");
01967       fprintf(fp,"// This function may be called from Loop.\n");
01968       fprintf(fp,"// returns  1 if entry is accepted.\n");
01969       fprintf(fp,"// returns -1 otherwise.\n");
01970 
01971       fprintf(fp,"   return 1;\n");
01972       fprintf(fp,"}\n");
01973    }
01974    fprintf(fp,"#endif // #ifdef %s_cxx\n",classname);
01975 
01976 //======================Generate classname.C=====================
01977    if (!opt.Contains("selector")) {
01978       // generate code for class member function Loop()
01979       fprintf(fpc,"#define %s_cxx\n",classname);
01980       fprintf(fpc,"#include \"%s\"\n",thead.Data());
01981       fprintf(fpc,"#include <TH2.h>\n");
01982       fprintf(fpc,"#include <TStyle.h>\n");
01983       fprintf(fpc,"#include <TCanvas.h>\n");
01984       fprintf(fpc,"\n");
01985       fprintf(fpc,"void %s::Loop()\n",classname);
01986       fprintf(fpc,"{\n");
01987       fprintf(fpc,"//   In a ROOT session, you can do:\n");
01988       fprintf(fpc,"//      Root > .L %s.C\n",classname);
01989       fprintf(fpc,"//      Root > %s t\n",classname);
01990       fprintf(fpc,"//      Root > t.GetEntry(12); // Fill t data members with entry number 12\n");
01991       fprintf(fpc,"//      Root > t.Show();       // Show values of entry 12\n");
01992       fprintf(fpc,"//      Root > t.Show(16);     // Read and show values of entry 16\n");
01993       fprintf(fpc,"//      Root > t.Loop();       // Loop on all entries\n");
01994       fprintf(fpc,"//\n");
01995       fprintf(fpc,"\n//     This is the loop skeleton where:\n");
01996       fprintf(fpc,"//    jentry is the global entry number in the chain\n");
01997       fprintf(fpc,"//    ientry is the entry number in the current Tree\n");
01998       fprintf(fpc,"//  Note that the argument to GetEntry must be:\n");
01999       fprintf(fpc,"//    jentry for TChain::GetEntry\n");
02000       fprintf(fpc,"//    ientry for TTree::GetEntry and TBranch::GetEntry\n");
02001       fprintf(fpc,"//\n");
02002       fprintf(fpc,"//       To read only selected branches, Insert statements like:\n");
02003       fprintf(fpc,"// METHOD1:\n");
02004       fprintf(fpc,"//    fChain->SetBranchStatus(\"*\",0);  // disable all branches\n");
02005       fprintf(fpc,"//    fChain->SetBranchStatus(\"branchname\",1);  // activate branchname\n");
02006       fprintf(fpc,"// METHOD2: replace line\n");
02007       fprintf(fpc,"//    fChain->GetEntry(jentry);       //read all branches\n");
02008       fprintf(fpc,"//by  b_branchname->GetEntry(ientry); //read only this branch\n");
02009       fprintf(fpc,"   if (fChain == 0) return;\n");
02010       fprintf(fpc,"\n   Long64_t nentries = fChain->GetEntriesFast();\n");
02011       fprintf(fpc,"\n   Long64_t nbytes = 0, nb = 0;\n");
02012       fprintf(fpc,"   for (Long64_t jentry=0; jentry<nentries;jentry++) {\n");
02013       fprintf(fpc,"      Long64_t ientry = LoadTree(jentry);\n");
02014       fprintf(fpc,"      if (ientry < 0) break;\n");
02015       fprintf(fpc,"      nb = fChain->GetEntry(jentry);   nbytes += nb;\n");
02016       fprintf(fpc,"      // if (Cut(ientry) < 0) continue;\n");
02017       fprintf(fpc,"   }\n");
02018       fprintf(fpc,"}\n");
02019    }
02020    if (opt.Contains("selector")) {
02021       // generate usage comments and list of includes
02022       fprintf(fpc,"#define %s_cxx\n",classname);
02023       fprintf(fpc,"// The class definition in %s.h has been generated automatically\n",classname);
02024       fprintf(fpc,"// by the ROOT utility TTree::MakeSelector(). This class is derived\n");
02025       fprintf(fpc,"// from the ROOT class TSelector. For more information on the TSelector\n"
02026                   "// framework see $ROOTSYS/README/README.SELECTOR or the ROOT User Manual.\n\n");
02027       fprintf(fpc,"// The following methods are defined in this file:\n");
02028       fprintf(fpc,"//    Begin():        called every time a loop on the tree starts,\n");
02029       fprintf(fpc,"//                    a convenient place to create your histograms.\n");
02030       fprintf(fpc,"//    SlaveBegin():   called after Begin(), when on PROOF called only on the\n"
02031                   "//                    slave servers.\n");
02032       fprintf(fpc,"//    Process():      called for each event, in this function you decide what\n");
02033       fprintf(fpc,"//                    to read and fill your histograms.\n");
02034       fprintf(fpc,"//    SlaveTerminate: called at the end of the loop on the tree, when on PROOF\n"
02035                   "//                    called only on the slave servers.\n");
02036       fprintf(fpc,"//    Terminate():    called at the end of the loop on the tree,\n");
02037       fprintf(fpc,"//                    a convenient place to draw/fit your histograms.\n");
02038       fprintf(fpc,"//\n");
02039       fprintf(fpc,"// To use this file, try the following session on your Tree T:\n");
02040       fprintf(fpc,"//\n");
02041       fprintf(fpc,"// Root > T->Process(\"%s.C\")\n",classname);
02042       fprintf(fpc,"// Root > T->Process(\"%s.C\",\"some options\")\n",classname);
02043       fprintf(fpc,"// Root > T->Process(\"%s.C+\")\n",classname);
02044       fprintf(fpc,"//\n\n");
02045       fprintf(fpc,"#include \"%s\"\n",thead.Data());
02046       fprintf(fpc,"#include <TH2.h>\n");
02047       fprintf(fpc,"#include <TStyle.h>\n");
02048       fprintf(fpc,"\n");
02049       // generate code for class member function Begin
02050       fprintf(fpc,"\n");
02051       fprintf(fpc,"void %s::Begin(TTree * /*tree*/)\n",classname);
02052       fprintf(fpc,"{\n");
02053       fprintf(fpc,"   // The Begin() function is called at the start of the query.\n");
02054       fprintf(fpc,"   // When running with PROOF Begin() is only called on the client.\n");
02055       fprintf(fpc,"   // The tree argument is deprecated (on PROOF 0 is passed).\n");
02056       fprintf(fpc,"\n");
02057       fprintf(fpc,"   TString option = GetOption();\n");
02058       fprintf(fpc,"\n");
02059       fprintf(fpc,"}\n");
02060       // generate code for class member function SlaveBegin
02061       fprintf(fpc,"\n");
02062       fprintf(fpc,"void %s::SlaveBegin(TTree * /*tree*/)\n",classname);
02063       fprintf(fpc,"{\n");
02064       fprintf(fpc,"   // The SlaveBegin() function is called after the Begin() function.\n");
02065       fprintf(fpc,"   // When running with PROOF SlaveBegin() is called on each slave server.\n");
02066       fprintf(fpc,"   // The tree argument is deprecated (on PROOF 0 is passed).\n");
02067       fprintf(fpc,"\n");
02068       fprintf(fpc,"   TString option = GetOption();\n");
02069       fprintf(fpc,"\n");
02070       fprintf(fpc,"}\n");
02071       // generate code for class member function Process
02072       fprintf(fpc,"\n");
02073       fprintf(fpc,"Bool_t %s::Process(Long64_t entry)\n",classname);
02074       fprintf(fpc,"{\n");
02075       fprintf(fpc,"   // The Process() function is called for each entry in the tree (or possibly\n"
02076                   "   // keyed object in the case of PROOF) to be processed. The entry argument\n"
02077                   "   // specifies which entry in the currently loaded tree is to be processed.\n"
02078                   "   // It can be passed to either %s::GetEntry() or TBranch::GetEntry()\n"
02079                   "   // to read either all or the required parts of the data. When processing\n"
02080                   "   // keyed objects with PROOF, the object is already loaded and is available\n"
02081                   "   // via the fObject pointer.\n"
02082                   "   //\n"
02083                   "   // This function should contain the \"body\" of the analysis. It can contain\n"
02084                   "   // simple or elaborate selection criteria, run algorithms on the data\n"
02085                   "   // of the event and typically fill histograms.\n"
02086                   "   //\n"
02087                   "   // The processing can be stopped by calling Abort().\n"
02088                   "   //\n"
02089                   "   // Use fStatus to set the return value of TTree::Process().\n"
02090                   "   //\n"
02091                   "   // The return value is currently not used.\n\n", classname);
02092       fprintf(fpc,"\n");
02093       fprintf(fpc,"   return kTRUE;\n");
02094       fprintf(fpc,"}\n");
02095       // generate code for class member function SlaveTerminate
02096       fprintf(fpc,"\n");
02097       fprintf(fpc,"void %s::SlaveTerminate()\n",classname);
02098       fprintf(fpc,"{\n");
02099       fprintf(fpc,"   // The SlaveTerminate() function is called after all entries or objects\n"
02100                   "   // have been processed. When running with PROOF SlaveTerminate() is called\n"
02101                   "   // on each slave server.");
02102       fprintf(fpc,"\n");
02103       fprintf(fpc,"\n");
02104       fprintf(fpc,"}\n");
02105       // generate code for class member function Terminate
02106       fprintf(fpc,"\n");
02107       fprintf(fpc,"void %s::Terminate()\n",classname);
02108       fprintf(fpc,"{\n");
02109       fprintf(fpc,"   // The Terminate() function is the last function to be called during\n"
02110                   "   // a query. It always runs on the client, it can be used to present\n"
02111                   "   // the results graphically or save the results to file.");
02112       fprintf(fpc,"\n");
02113       fprintf(fpc,"\n");
02114       fprintf(fpc,"}\n");
02115    }
02116    Info("MakeClass","Files: %s and %s generated from TTree: %s",thead.Data(),tcimp.Data(),fTree->GetName());
02117    delete [] leafStatus;
02118    fclose(fp);
02119    fclose(fpc);
02120 
02121    return 0;
02122 }
02123 
02124 
02125 //______________________________________________________________________________
02126 Int_t TTreePlayer::MakeCode(const char *filename)
02127 {
02128 // Generate skeleton function for this Tree
02129 //
02130 // The function code is written on filename.
02131 // If filename is 0, filename will be called nameoftree.C
02132 //
02133 // The generated code includes the following:
02134 //    - Identification of the original Tree and Input file name
02135 //    - Connection of the Tree file
02136 //    - Declaration of Tree variables
02137 //    - Setting of branches addresses
02138 //    - A skeleton for the entry loop
02139 //
02140 // To use this function:
02141 //    - connect your Tree file (eg: TFile f("myfile.root");)
02142 //    - T->MakeCode("anal.C");
02143 // where T is the name of the Tree in file myfile.root
02144 // and anal.C the name of the file created by this function.
02145 //
02146 // NOTE: Since the implementation of this function, a new and better
02147 //       function TTree::MakeClass() has been developed.
02148 
02149 // Connect output file
02150    TString tfile;
02151    if (filename)
02152       tfile = filename;
02153    else
02154       tfile.Form("%s.C", fTree->GetName());
02155    FILE *fp = fopen(tfile, "w");
02156    if (!fp) {
02157       Error("MakeCode","cannot open output file %s", tfile.Data());
02158       return 3;
02159    }
02160    TString treefile;
02161    if (fTree->GetDirectory() && fTree->GetDirectory()->GetFile()) {
02162       treefile = fTree->GetDirectory()->GetFile()->GetName();
02163    } else {
02164       treefile = "Memory Directory";
02165    }
02166    // In the case of a chain, the GetDirectory information usually does
02167    // pertain to the Chain itself but to the currently loaded tree.
02168    // So we can not rely on it.
02169    Bool_t ischain = fTree->InheritsFrom(TChain::Class());
02170 
02171 // Print header
02172    TObjArray *leaves = fTree->GetListOfLeaves();
02173    Int_t nleaves = leaves ? leaves->GetEntriesFast() : 0;
02174    TDatime td;
02175    fprintf(fp,"{\n");
02176    fprintf(fp,"//////////////////////////////////////////////////////////\n");
02177    fprintf(fp,"//   This file has been automatically generated \n");
02178    fprintf(fp,"//     (%s by ROOT version%s)\n",td.AsString(),gROOT->GetVersion());
02179    if (!ischain) {
02180       fprintf(fp,"//   from TTree %s/%s\n",fTree->GetName(),fTree->GetTitle());
02181       fprintf(fp,"//   found on file: %s\n",treefile.Data());
02182    } else {
02183       fprintf(fp,"//   from TChain %s/%s\n",fTree->GetName(),fTree->GetTitle());
02184    }
02185    fprintf(fp,"//////////////////////////////////////////////////////////\n");
02186    fprintf(fp,"\n");
02187    fprintf(fp,"\n");
02188 
02189 
02190 // Reset and file connect
02191    fprintf(fp,"//Reset ROOT and connect tree file\n");
02192    fprintf(fp,"   gROOT->Reset();\n");
02193    if (ischain) {
02194       fprintf(fp,"\n#ifdef SINGLE_TREE\n");
02195       fprintf(fp,"   // The following code should be used if you want this code to access\n");
02196       fprintf(fp,"   // a single tree instead of a chain\n");
02197    }
02198    fprintf(fp,"   TFile *f = (TFile*)gROOT->GetListOfFiles()->FindObject(\"%s\");\n",treefile.Data());
02199    fprintf(fp,"   if (!f) {\n");
02200    fprintf(fp,"      f = new TFile(\"%s\");\n",treefile.Data());
02201    if (gDirectory != gFile) {
02202       fprintf(fp,"      f->cd(\"%s\");\n",gDirectory->GetPath());
02203    }
02204    fprintf(fp,"   }\n");
02205    fprintf(fp,"   TTree *%s = (TTree*)gDirectory->Get(\"%s\");\n\n",fTree->GetName(),fTree->GetName());
02206    if (ischain) {
02207       fprintf(fp,"#else // SINGLE_TREE\n\n");
02208       fprintf(fp,"   // The following code should be used if you want this code to access a chain\n");
02209       fprintf(fp,"   // of trees.\n");
02210       fprintf(fp,"   TChain *%s = new TChain(\"%s\",\"%s\");\n",
02211                  fTree->GetName(),fTree->GetName(),fTree->GetTitle());
02212       TIter next(((TChain*)fTree)->GetListOfFiles());
02213       TChainElement *element;
02214       while ((element = (TChainElement*)next())) {
02215          fprintf(fp,"   %s->Add(\"%s/%s\");\n",fTree->GetName(),element->GetTitle(),element->GetName());
02216       }
02217       fprintf(fp,"#endif // SINGLE_TREE\n\n");
02218    }
02219 
02220 // First loop on all leaves to generate type declarations
02221    fprintf(fp,"//Declaration of leaves types\n");
02222    Int_t len, l;
02223    TLeaf *leafcount;
02224    TLeafObject *leafobj;
02225    char *bname;
02226    const char *headOK  = "   ";
02227    const char *headcom = " //";
02228    const char *head;
02229    char branchname[1024];
02230    for (l=0;l<nleaves;l++) {
02231       TLeaf *leaf = (TLeaf*)leaves->UncheckedAt(l);
02232       len = leaf->GetLen();
02233       leafcount =leaf->GetLeafCount();
02234       TBranch *branch = leaf->GetBranch();
02235       if (branch->GetListOfBranches()->GetEntriesFast() > 0) continue;
02236 
02237       if ( branch->GetNleaves() > 1) {
02238          // More than one leaf for the branch we need to distinguish them
02239          strlcpy(branchname,branch->GetName(),sizeof(branchname)); 
02240          strlcat(branchname,".",sizeof(branchname));
02241          strlcat(branchname,leaf->GetTitle(),sizeof(branchname));
02242          if (leafcount) {
02243             // remove any dimension in title
02244             char *dim =  (char*)strstr(branchname,"[");
02245             dim[0] = 0;
02246          }
02247       } else {
02248          if (leafcount) strlcpy(branchname,branch->GetName(),sizeof(branchname));
02249          else           strlcpy(branchname,leaf->GetTitle(),sizeof(branchname));
02250       }
02251       char *twodim = (char*)strstr(leaf->GetTitle(),"][");
02252       bname = branchname;
02253       while (*bname) {
02254          if (*bname == '.') *bname='_';
02255          if (*bname == ',') *bname='_';
02256          if (*bname == ':') *bname='_';
02257          if (*bname == '<') *bname='_';
02258          if (*bname == '>') *bname='_';
02259          bname++;
02260       }
02261       if (branch->IsA() == TBranchObject::Class()) {
02262          leafobj = (TLeafObject*)leaf;
02263          if (leafobj->GetClass()) head = headOK;
02264          else                     head = headcom;
02265          fprintf(fp,"%s%-15s *%s = 0;\n",head,leafobj->GetTypeName(), leafobj->GetName());
02266          continue;
02267       }
02268       if (leafcount) {
02269          len = leafcount->GetMaximum();
02270          // Dimensions can be in the branchname for a split Object with a fix length C array.
02271          // Theses dimensions HAVE TO be placed after the dimension explicited by leafcount
02272          char *dimInName = (char*) strstr(branchname,"[");
02273          TString dimensions;
02274          if ( twodim || dimInName ) {
02275             if (dimInName) {
02276                dimensions = dimInName; 
02277                dimInName[0] = 0; // terminate branchname before the array dimensions.
02278             }
02279             if (twodim) dimensions += (char*)(twodim+1);
02280          }
02281          if (dimensions.Length()) {
02282             fprintf(fp,"   %-15s %s[%d]%s;\n",leaf->GetTypeName(), branchname,len,dimensions.Data());
02283          } else {
02284             fprintf(fp,"   %-15s %s[%d];\n",leaf->GetTypeName(), branchname,len);
02285          }
02286       } else {
02287          if (strstr(branchname,"[")) len = 1;
02288          if (len < 2) fprintf(fp,"   %-15s %s;\n",leaf->GetTypeName(), branchname);
02289          else         fprintf(fp,"   %-15s %s[%d];\n",leaf->GetTypeName(), branchname,len);
02290       }
02291    }
02292 
02293 // Second loop on all leaves to set the corresponding branch address
02294    fprintf(fp,"\n   // Set branch addresses.\n");
02295    for (l=0;l<nleaves;l++) {
02296       TLeaf *leaf = (TLeaf*)leaves->UncheckedAt(l);
02297       len = leaf->GetLen();
02298       leafcount =leaf->GetLeafCount();
02299       TBranch *branch = leaf->GetBranch();
02300 
02301       if ( branch->GetNleaves() > 1) {
02302          // More than one leaf for the branch we need to distinguish them
02303          strlcpy(branchname,branch->GetName(),sizeof(branchname)); 
02304          strlcat(branchname,".",sizeof(branchname));
02305          strlcat(branchname,leaf->GetTitle(),sizeof(branchname));
02306          if (leafcount) {
02307             // remove any dimension in title
02308             char *dim =  (char*)strstr(branchname,"[");
02309             dim[0] = 0;
02310          }
02311       } else {
02312          if (leafcount) strlcpy(branchname,branch->GetName(),sizeof(branchname));
02313          else           strlcpy(branchname,leaf->GetTitle(),sizeof(branchname));
02314       }
02315       bname = branchname;
02316       while (*bname) {
02317          if (*bname == '.') *bname='_';
02318          if (*bname == ',') *bname='_';
02319          if (*bname == ':') *bname='_';
02320          if (*bname == '<') *bname='_';
02321          if (*bname == '>') *bname='_';
02322          bname++;
02323       }
02324       char *brak = strstr(branchname,"[");
02325       if (brak) *brak = 0;
02326       head = headOK;
02327       if (branch->IsA() == TBranchObject::Class()) {
02328          strlcpy(branchname,branch->GetName(),sizeof(branchname));
02329          leafobj = (TLeafObject*)leaf;
02330          if (!leafobj->GetClass()) head = headcom;
02331       }
02332       if (leafcount) len = leafcount->GetMaximum()+1;
02333       if (len > 1 || brak) fprintf(fp,"%s%s->SetBranchAddress(\"%s\",%s);\n",head,fTree->GetName(),branch->GetName(),branchname);
02334       else                 fprintf(fp,"%s%s->SetBranchAddress(\"%s\",&%s);\n",head,fTree->GetName(),branch->GetName(),branchname);
02335    }
02336 
02337 //Generate instructions to make the loop on entries
02338    fprintf(fp,"\n//     This is the loop skeleton\n");
02339    fprintf(fp,"//       To read only selected branches, Insert statements like:\n");
02340    fprintf(fp,"// %s->SetBranchStatus(\"*\",0);  // disable all branches\n",fTree->GetName());
02341    fprintf(fp,"// %s->SetBranchStatus(\"branchname\",1);  // activate branchname\n",GetName());
02342    fprintf(fp,"\n   Long64_t nentries = %s->GetEntries();\n",fTree->GetName());
02343    fprintf(fp,"\n   Long64_t nbytes = 0;\n");
02344    fprintf(fp,"//   for (Long64_t i=0; i<nentries;i++) {\n");
02345    fprintf(fp,"//      nbytes += %s->GetEntry(i);\n",fTree->GetName());
02346    fprintf(fp,"//   }\n");
02347    fprintf(fp,"}\n");
02348 
02349    printf("Macro: %s generated from Tree: %s\n",tfile.Data(), fTree->GetName());
02350    fclose(fp);
02351 
02352    return 0;
02353 }
02354 
02355 //______________________________________________________________________________
02356 Int_t TTreePlayer::MakeProxy(const char *proxyClassname,
02357                              const char *macrofilename, const char *cutfilename,
02358                              const char *option, Int_t maxUnrolling)
02359 {
02360    // Generate a skeleton analysis class for this Tree using TBranchProxy.
02361    // TBranchProxy is the base of a class hierarchy implementing an
02362    // indirect access to the content of the branches of a TTree.
02363    //
02364    // "proxyClassname" is expected to be of the form:
02365    //    [path/]fileprefix
02366    // The skeleton will then be generated in the file:
02367    //    fileprefix.h
02368    // located in the current directory or in 'path/' if it is specified.
02369    // The class generated will be named 'fileprefix'
02370    //
02371    // "macrofilename" and optionally "cutfilename" are expected to point
02372    // to source file which will be included in by the generated skeletong.
02373    // Method of the same name as the file(minus the extension and path)
02374    // will be called by the generated skeleton's Process method as follow:
02375    //    [if (cutfilename())] htemp->Fill(macrofilename());
02376    //
02377    // "option" can be used select some of the optional features during
02378    // the code generation.  The possible options are:
02379    //    nohist : indicates that the generated ProcessFill should not
02380    //             fill the histogram.
02381    //
02382    // 'maxUnrolling' controls how deep in the class hierarchy does the
02383    // system 'unroll' class that are not split.  'unrolling' a class
02384    // will allow direct access to its data members a class (this
02385    // emulates the behavior of TTreeFormula).
02386    //
02387    // The main features of this skeleton are:
02388    //
02389    //    * on-demand loading of branches
02390    //    * ability to use the 'branchname' as if it was a data member
02391    //    * protection against array out-of-bound
02392    //    * ability to use the branch data as object (when the user code is available)
02393    //
02394    // For example with Event.root, if
02395    //    Double_t somepx = fTracks.fPx[2];
02396    // is executed by one of the method of the skeleton,
02397    // somepx will be updated with the current value of fPx of the 3rd track.
02398    //
02399    // Both macrofilename and the optional cutfilename are expected to be
02400    // the name of source files which contain at least a free standing
02401    // function with the signature:
02402    //     x_t macrofilename(); // i.e function with the same name as the file
02403    // and
02404    //     y_t cutfilename();   // i.e function with the same name as the file
02405    //
02406    // x_t and y_t needs to be types that can convert respectively to a double
02407    // and a bool (because the skeleton uses:
02408    //     if (cutfilename()) htemp->Fill(macrofilename());
02409    //
02410    // This 2 functions are run in a context such that the branch names are
02411    // available as local variables of the correct (read-only) type.
02412    //
02413    // Note that if you use the same 'variable' twice, it is more efficient
02414    // to 'cache' the value. For example
02415    //   Int_t n = fEventNumber; // Read fEventNumber
02416    //   if (n<10 || n>10) { ... }
02417    // is more efficient than
02418    //   if (fEventNumber<10 || fEventNumber>10)
02419    //
02420    // Access to TClonesArray.
02421    //
02422    // If a branch (or member) is a TClonesArray (let's say fTracks), you
02423    // can access the TClonesArray itself by using ->:
02424    //    fTracks->GetLast();
02425    // However this will load the full TClonesArray object and its content.
02426    // To quickly read the size of the TClonesArray use (note the dot):
02427    //    fTracks.GetEntries();
02428    // This will read only the size from disk if the TClonesArray has been
02429    // split.
02430    // To access the content of the TClonesArray, use the [] operator:
02431    //    float px = fTracks[i].fPx; // fPx of the i-th track
02432    //
02433    // Warning:
02434    //    The variable actually use for access are 'wrapper' around the
02435    // real data type (to add autoload for example) and hence getting to
02436    // the data involves the implicit call to a C++ conversion operator.
02437    // This conversion is automatic in most case.  However it is not invoked
02438    // in a few cases, in particular in variadic function (like printf).
02439    // So when using printf you should either explicitly cast the value or
02440    // use any intermediary variable:
02441    //      fprintf(stdout,"trs[%d].a = %d\n",i,(int)trs.a[i]);
02442    //
02443    // Also, optionally, the generated selector will also call methods named
02444    // macrofilename_methodname in each of 6 main selector methods if the method
02445    // macrofilename_methodname exist (Where macrofilename is stripped of its
02446    // extension).
02447    //
02448    // Concretely, with the script named h1analysisProxy.C,
02449    //
02450    // The method         calls the method (if it exist)
02451    // Begin           -> void h1analysisProxy_Begin(TTree*);
02452    // SlaveBegin      -> void h1analysisProxy_SlaveBegin(TTree*);
02453    // Notify          -> Bool_t h1analysisProxy_Notify();
02454    // Process         -> Bool_t h1analysisProxy_Process(Long64_t);
02455    // SlaveTerminate  -> void h1analysisProxy_SlaveTerminate();
02456    // Terminate       -> void h1analysisProxy_Terminate();
02457    //
02458    // If a file name macrofilename.h (or .hh, .hpp, .hxx, .hPP, .hXX) exist
02459    // it is included before the declaration of the proxy class.  This can
02460    // be used in particular to insure that the include files needed by
02461    // the macro file are properly loaded.
02462    //
02463    // The default histogram is accessible via the variable named 'htemp'.
02464    //
02465    // If the library of the classes describing the data in the branch is
02466    // loaded, the skeleton will add the needed #include statements and
02467    // give the ability to access the object stored in the branches.
02468    //
02469    // To draw px using the file hsimple.root (generated by the
02470    // hsimple.C tutorial), we need a file named hsimple.cxx:
02471    //
02472    //     double hsimple() {
02473    //        return px;
02474    //     }
02475    //
02476    // MakeProxy can then be used indirectly via the TTree::Draw interface
02477    // as follow:
02478    //     new TFile("hsimple.root")
02479    //     ntuple->Draw("hsimple.cxx");
02480    //
02481    // A more complete example is available in the tutorials directory:
02482    //   h1analysisProxy.cxx , h1analysProxy.h and h1analysisProxyCut.C
02483    // which reimplement the selector found in h1analysis.C
02484 
02485    if (macrofilename==0 || strlen(macrofilename)==0 ) {
02486       // We currently require a file name for the script
02487       Error("MakeProxy","A file name for the user script is required");
02488       return 0;
02489    }
02490 
02491    TTreeProxyGenerator gp(fTree,macrofilename,cutfilename,proxyClassname,option,maxUnrolling);
02492 
02493    return 0;
02494 }
02495 
02496 //______________________________________________________________________________
02497 TPrincipal *TTreePlayer::Principal(const char *varexp, const char *selection, Option_t *option, Long64_t nentries, Long64_t firstentry)
02498 {
02499 // Interface to the Principal Components Analysis class.
02500 //
02501 //   Create an instance of TPrincipal
02502 //   Fill it with the selected variables
02503 //   if option "n" is specified, the TPrincipal object is filled with
02504 //                 normalized variables.
02505 //   If option "p" is specified, compute the principal components
02506 //   If option "p" and "d" print results of analysis
02507 //   If option "p" and "h" generate standard histograms
02508 //   If option "p" and "c" generate code of conversion functions
02509 //   return a pointer to the TPrincipal object. It is the user responsibility
02510 //   to delete this object.
02511 //   The option default value is "np"
02512 //
02513 //   See TTreePlayer::DrawSelect for explanation of the other parameters.
02514 
02515    TTreeFormula **var;
02516    std::vector<TString> cnames;
02517    TString opt = option;
02518    opt.ToLower();
02519    TPrincipal *principal = 0;
02520    Long64_t entry,entryNumber;
02521    Int_t i,nch;
02522    Int_t ncols = 8;   // by default first 8 columns are printed only
02523    TObjArray *leaves = fTree->GetListOfLeaves();
02524    Int_t nleaves = leaves->GetEntriesFast();
02525    if (nleaves < ncols) ncols = nleaves;
02526    nch = varexp ? strlen(varexp) : 0;
02527 
02528    nentries = GetEntriesToProcess(firstentry, nentries);
02529 
02530 //*-*- Compile selection expression if there is one
02531    TTreeFormula *select = 0;
02532    if (strlen(selection)) {
02533       select = new TTreeFormula("Selection",selection,fTree);
02534       if (!select) return principal;
02535       if (!select->GetNdim()) { delete select; return principal; }
02536       fFormulaList->Add(select);
02537    }
02538 //*-*- if varexp is empty, take first 8 columns by default
02539    int allvar = 0;
02540    if (varexp && !strcmp(varexp, "*")) { ncols = nleaves; allvar = 1; }
02541    if (nch == 0 || allvar) {
02542       for (i=0;i<ncols;i++) {
02543          cnames.push_back( ((TLeaf*)leaves->At(i))->GetName() );
02544       }
02545 //*-*- otherwise select only the specified columns
02546    } else {
02547       ncols = fSelector->SplitNames(varexp,cnames);
02548    }
02549    var = new TTreeFormula* [ncols];
02550    Double_t *xvars = new Double_t[ncols];
02551 
02552 //*-*- Create the TreeFormula objects corresponding to each column
02553    for (i=0;i<ncols;i++) {
02554       var[i] = new TTreeFormula("Var1",cnames[i].Data(),fTree);
02555       fFormulaList->Add(var[i]);
02556    }
02557 
02558 //*-*- Create a TreeFormulaManager to coordinate the formulas
02559    TTreeFormulaManager *manager=0;
02560    if (fFormulaList->LastIndex()>=0) {
02561       manager = new TTreeFormulaManager;
02562       for(i=0;i<=fFormulaList->LastIndex();i++) {
02563          manager->Add((TTreeFormula*)fFormulaList->At(i));
02564       }
02565       manager->Sync();
02566    }
02567 
02568 //*-* Build the TPrincipal object
02569    if (opt.Contains("n")) principal = new TPrincipal(ncols, "n");
02570    else                   principal = new TPrincipal(ncols);
02571 
02572 //*-*- loop on all selected entries
02573    fSelectedRows = 0;
02574    Int_t tnumber = -1;
02575    for (entry=firstentry;entry<firstentry+nentries;entry++) {
02576       entryNumber = fTree->GetEntryNumber(entry);
02577       if (entryNumber < 0) break;
02578       Long64_t localEntry = fTree->LoadTree(entryNumber);
02579       if (localEntry < 0) break;
02580       if (tnumber != fTree->GetTreeNumber()) {
02581          tnumber = fTree->GetTreeNumber();
02582          if (manager) manager->UpdateFormulaLeaves();
02583       }
02584       int ndata = 1;
02585       if (manager && manager->GetMultiplicity()) {
02586          ndata = manager->GetNdata();
02587       }
02588 
02589       for(int inst=0;inst<ndata;inst++) {
02590          Bool_t loaded = kFALSE;
02591          if (select) {
02592             if (select->EvalInstance(inst) == 0) {
02593                continue;
02594             }
02595          }
02596 
02597          if (inst==0) loaded = kTRUE;
02598          else if (!loaded) {
02599             // EvalInstance(0) always needs to be called so that
02600             // the proper branches are loaded.
02601             for (i=0;i<ncols;i++) {
02602                var[i]->EvalInstance(0);
02603             }
02604             loaded = kTRUE;
02605          }
02606 
02607          for (i=0;i<ncols;i++) {
02608             xvars[i] = var[i]->EvalInstance(inst);
02609          }
02610          principal->AddRow(xvars);
02611       }
02612    }
02613 
02614    //*-* some actions with principal ?
02615    if (opt.Contains("p")) {
02616       principal->MakePrincipals(); // Do the actual analysis
02617       if (opt.Contains("d")) principal->Print();
02618       if (opt.Contains("h")) principal->MakeHistograms();
02619       if (opt.Contains("c")) principal->MakeCode();
02620    }
02621 
02622 //*-*- delete temporary objects
02623    fFormulaList->Clear();
02624    delete [] var;
02625    delete [] xvars;
02626 
02627    return principal;
02628 }
02629 
02630 //______________________________________________________________________________
02631 Long64_t TTreePlayer::Process(const char *filename,Option_t *option, Long64_t nentries, Long64_t firstentry)
02632 {
02633    // Process this tree executing the TSelector code in the specified filename.
02634    // The return value is -1 in case of error and TSelector::GetStatus() in
02635    // in case of success.
02636    //
02637    // The code in filename is loaded (interpreted or compiled, see below),
02638    // filename must contain a valid class implementation derived from TSelector,
02639    // where TSelector has the following member functions:
02640    //
02641    //    Begin():        called every time a loop on the tree starts,
02642    //                    a convenient place to create your histograms.
02643    //    SlaveBegin():   called after Begin(), when on PROOF called only on the
02644    //                    slave servers.
02645    //    Process():      called for each event, in this function you decide what
02646    //                    to read and fill your histograms.
02647    //    SlaveTerminate: called at the end of the loop on the tree, when on PROOF
02648    //                    called only on the slave servers.
02649    //    Terminate():    called at the end of the loop on the tree,
02650    //                    a convenient place to draw/fit your histograms.
02651    //
02652    // If filename is of the form file.C, the file will be interpreted.
02653    // If filename is of the form file.C++, the file file.C will be compiled
02654    // and dynamically loaded.
02655    // If filename is of the form file.C+, the file file.C will be compiled
02656    // and dynamically loaded. At next call, if file.C is older than file.o
02657    // and file.so, the file.C is not compiled, only file.so is loaded.
02658    //
02659    //  NOTE1
02660    //  It may be more interesting to invoke directly the other Process function
02661    //  accepting a TSelector* as argument.eg
02662    //     MySelector *selector = (MySelector*)TSelector::GetSelector(filename);
02663    //     selector->CallSomeFunction(..);
02664    //     mytree.Process(selector,..);
02665    //
02666    //  NOTE2
02667    //  One should not call this function twice with the same selector file
02668    //  in the same script. If this is required, proceed as indicated in NOTE1,
02669    //  by getting a pointer to the corresponding TSelector,eg
02670    //    workaround 1
02671    //    ------------
02672    //void stubs1() {
02673    //   TSelector *selector = TSelector::GetSelector("h1test.C");
02674    //   TFile *f1 = new TFile("stubs_nood_le1.root");
02675    //   TTree *h1 = (TTree*)f1->Get("h1");
02676    //   h1->Process(selector);
02677    //   TFile *f2 = new TFile("stubs_nood_le1_coarse.root");
02678    //   TTree *h2 = (TTree*)f2->Get("h1");
02679    //   h2->Process(selector);
02680    //}
02681    //  or use ACLIC to compile the selector
02682    //   workaround 2
02683    //   ------------
02684    //void stubs2() {
02685    //   TFile *f1 = new TFile("stubs_nood_le1.root");
02686    //   TTree *h1 = (TTree*)f1->Get("h1");
02687    //   h1->Process("h1test.C+");
02688    //   TFile *f2 = new TFile("stubs_nood_le1_coarse.root");
02689    //   TTree *h2 = (TTree*)f2->Get("h1");
02690    //   h2->Process("h1test.C+");
02691    //}
02692 
02693    DeleteSelectorFromFile(); //delete previous selector if any
02694 
02695    // This might reloads the script and delete your option
02696    // string! so let copy it first:
02697    TString opt(option);
02698    TString file(filename);
02699    TSelector *selector = TSelector::GetSelector(file);
02700    if (!selector) return -1;
02701 
02702    fSelectorFromFile = selector;
02703    fSelectorClass    = selector->IsA();
02704 
02705    Long64_t nsel = Process(selector,opt,nentries,firstentry);
02706    return nsel;
02707 }
02708 
02709 //______________________________________________________________________________
02710 Long64_t TTreePlayer::Process(TSelector *selector,Option_t *option, Long64_t nentries, Long64_t firstentry)
02711 {
02712    // Process this tree executing the code in the specified selector.
02713    // The return value is -1 in case of error and TSelector::GetStatus() in
02714    // in case of success.
02715    //
02716    //   The TSelector class has the following member functions:
02717    //
02718    //    Begin():        called every time a loop on the tree starts,
02719    //                    a convenient place to create your histograms.
02720    //    SlaveBegin():   called after Begin(), when on PROOF called only on the
02721    //                    slave servers.
02722    //    Process():      called for each event, in this function you decide what
02723    //                    to read and fill your histograms.
02724    //    SlaveTerminate: called at the end of the loop on the tree, when on PROOF
02725    //                    called only on the slave servers.
02726    //    Terminate():    called at the end of the loop on the tree,
02727    //                    a convenient place to draw/fit your histograms.
02728    //
02729    //  If the Tree (Chain) has an associated EventList, the loop is on the nentries
02730    //  of the EventList, starting at firstentry, otherwise the loop is on the
02731    //  specified Tree entries.
02732 
02733    nentries = GetEntriesToProcess(firstentry, nentries);
02734 
02735    TDirectory::TContext ctxt(0);
02736 
02737    fTree->SetNotify(selector);
02738 
02739    selector->SetOption(option);
02740 
02741    selector->Begin(fTree);       //<===call user initialization function
02742    selector->SlaveBegin(fTree);  //<===call user initialization function
02743    if (selector->Version() >= 2)
02744       selector->Init(fTree);
02745    selector->Notify();
02746 
02747    if (gMonitoringWriter)
02748       gMonitoringWriter->SendProcessingStatus("STARTED",kTRUE);
02749 
02750    if (selector->GetAbort() != TSelector::kAbortProcess
02751        && (selector->Version() != 0 || selector->GetStatus() != -1)) {
02752 
02753       Long64_t readbytesatstart = 0;
02754       readbytesatstart = TFile::GetFileBytesRead();
02755 
02756       //set the file cache
02757       TTreeCache *tpf = 0;
02758       TFile *curfile = fTree->GetCurrentFile();
02759       if (curfile && fTree->GetCacheSize() > 0) {
02760          tpf = (TTreeCache*)curfile->GetCacheRead();
02761          if (tpf)
02762             tpf->SetEntryRange(firstentry,firstentry+nentries);
02763          else {
02764             fTree->SetCacheSize(fTree->GetCacheSize());
02765             tpf = (TTreeCache*)curfile->GetCacheRead();
02766             if (tpf) tpf->SetEntryRange(firstentry,firstentry+nentries);
02767          }
02768       }
02769 
02770       //Create a timer to get control in the entry loop(s)
02771       TProcessEventTimer *timer = 0;
02772       Int_t interval = fTree->GetTimerInterval();
02773       if (!gROOT->IsBatch() && interval)
02774          timer = new TProcessEventTimer(interval);
02775 
02776       //loop on entries (elist or all entries)
02777       Long64_t entry, entryNumber, localEntry;
02778 
02779       Bool_t useCutFill = selector->Version() == 0;
02780 
02781       // force the first monitoring info
02782       if (gMonitoringWriter)
02783          gMonitoringWriter->SendProcessingProgress(0,0,kTRUE);
02784 
02785       //trying to set the first tree, because in the Draw function
02786       //the tree corresponding to firstentry has already been loaded,
02787       //so it is not set in the entry list
02788       fSelectorUpdate = selector;
02789       UpdateFormulaLeaves();
02790 
02791       for (entry=firstentry;entry<firstentry+nentries;entry++) {
02792          entryNumber = fTree->GetEntryNumber(entry);
02793          if (entryNumber < 0) break;
02794          if (timer && timer->ProcessEvents()) break;
02795          if (gROOT->IsInterrupted()) break;
02796          localEntry = fTree->LoadTree(entryNumber);
02797          if (localEntry < 0) break;
02798          if(useCutFill) {
02799             if (selector->ProcessCut(localEntry))
02800                selector->ProcessFill(localEntry); //<==call user analysis function
02801          } else {
02802             selector->Process(localEntry);        //<==call user analysis function
02803          }
02804          if (gMonitoringWriter)
02805             gMonitoringWriter->SendProcessingProgress((entry-firstentry),TFile::GetFileBytesRead()-readbytesatstart,kTRUE);
02806          if (selector->GetAbort() == TSelector::kAbortProcess) break;
02807       }
02808       delete timer;
02809       //we must reset the cache
02810       {
02811          TFile *curfile2 = fTree->GetCurrentFile();
02812          if (curfile2 && fTree->GetCacheSize() > 0) {
02813             tpf = (TTreeCache*)curfile2->GetCacheRead();
02814             if (tpf) tpf->SetEntryRange(0,0);
02815          }
02816       }
02817    }
02818 
02819    if (selector->Version() != 0 || selector->GetStatus() != -1) {
02820       selector->SlaveTerminate();   //<==call user termination function
02821       selector->Terminate();        //<==call user termination function
02822    }
02823    fSelectorUpdate = 0;
02824    if (gMonitoringWriter)
02825       gMonitoringWriter->SendProcessingStatus("DONE");
02826 
02827    return selector->GetStatus();
02828 }
02829 
02830 //______________________________________________________________________________
02831 void TTreePlayer::RecursiveRemove(TObject *obj)
02832 {
02833 // cleanup pointers in the player pointing to obj
02834 
02835    if (fHistogram == obj) fHistogram = 0;
02836 }
02837 
02838 //______________________________________________________________________________
02839 Long64_t TTreePlayer::Scan(const char *varexp, const char *selection,
02840                            Option_t * option,
02841                            Long64_t nentries, Long64_t firstentry)
02842 {
02843    // Loop on Tree and print entries passing selection. If varexp is 0 (or "")
02844    // then print only first 8 columns. If varexp = "*" print all columns.
02845    // Otherwise a columns selection can be made using "var1:var2:var3".
02846    // The function returns the number of entries passing the selection.
02847    //
02848    // By default 50 rows are shown and you are asked for <CR>
02849    // to see the next 50 rows.
02850    // You can change the default number of rows to be shown before <CR>
02851    // via  mytree->SetScanField(maxrows) where maxrows is 50 by default.
02852    // if maxrows is set to 0 all rows of the Tree are shown.
02853    // This option is interesting when dumping the contents of a Tree to
02854    // an ascii file, eg from the command line
02855    //   tree->SetScanField(0);
02856    //   tree->Scan("*"); >tree.log
02857    //  will create a file tree.log
02858    //
02859    // Arrays (within an entry) are printed in their linear forms.
02860    // If several arrays with multiple dimensions are printed together,
02861    // they will NOT be synchronized.  For example print
02862    //   arr1[4][2] and arr2[2][3] will results in a printing similar to:
02863    // ***********************************************
02864    // *    Row   * Instance *      arr1 *      arr2 *
02865    // ***********************************************
02866    // *        x *        0 * arr1[0][0]* arr2[0][0]*
02867    // *        x *        1 * arr1[0][1]* arr2[0][1]*
02868    // *        x *        2 * arr1[1][0]* arr2[0][2]*
02869    // *        x *        3 * arr1[1][1]* arr2[1][0]*
02870    // *        x *        4 * arr1[2][0]* arr2[1][1]*
02871    // *        x *        5 * arr1[2][1]* arr2[1][2]*
02872    // *        x *        6 * arr1[3][0]*           *
02873    // *        x *        7 * arr1[3][1]*           *
02874    //
02875    // However, if there is a selection criterion which is an array, then
02876    // all the formulas will be synchronized with the selection criterion
02877    // (see TTreePlayer::DrawSelect for more information).
02878    //
02879    // The options string can contains the following parameters:
02880    //    lenmax=dd
02881    //       Where 'dd' is the maximum number of elements per array that should
02882    //       be printed.  If 'dd' is 0, all elements are printed (this is the
02883    //       default)
02884    //    colsize=ss
02885    //       Where 'ss' will be used as the default size for all the column
02886    //       If this options is not specified, the default column size is 9
02887    //    precision=pp
02888    //       Where 'pp' will be used as the default 'precision' for the
02889    //       printing format.
02890    //    col=xxx
02891    //       Where 'xxx' is colon (:) delimited list of printing format for
02892    //       each column. The format string should follow the printf format
02893    //       specification.  The value given will be prefixed by % and, if no
02894    //       conversion specifier is given, will be suffixed by the letter g.
02895    //       before being passed to fprintf.  If no format is specified for a
02896    //       column, the default is used  (aka ${colsize}.${precision}g )
02897    // For example:
02898    //   tree->Scan("a:b:c","","colsize=30 precision=3 col=::20.10:#x:5ld");
02899    // Will print 3 columns, the first 2 columns will be 30 characters long,
02900    // the third columns will be 20 characters long.  The printing format used
02901    // for the columns (assuming they are numbers) will be respectively:
02902    //   %30.3g %30.3g %20.10g %#x %5ld
02903 
02904 
02905    TString opt = option;
02906    opt.ToLower();
02907    UInt_t ui;
02908    UInt_t lenmax = 0;
02909    UInt_t colDefaultSize = 9;
02910    UInt_t colPrecision = 9;
02911    vector<TString> colFormats;
02912    vector<Int_t> colSizes;
02913 
02914    if (opt.Contains("lenmax=")) {
02915       int start = opt.Index("lenmax=");
02916       int numpos = start + strlen("lenmax=");
02917       int numlen = 0;
02918       int len = opt.Length();
02919       while( (numpos+numlen<len) && isdigit(opt[numpos+numlen]) ) numlen++;
02920       TString num = opt(numpos,numlen);
02921       opt.Remove(start,strlen("lenmax")+numlen);
02922 
02923       lenmax = atoi(num.Data());
02924    }
02925    if (opt.Contains("colsize=")) {
02926       int start = opt.Index("colsize=");
02927       int numpos = start + strlen("colsize=");
02928       int numlen = 0;
02929       int len = opt.Length();
02930       while( (numpos+numlen<len) && isdigit(opt[numpos+numlen]) ) numlen++;
02931       TString num = opt(numpos,numlen);
02932       opt.Remove(start,strlen("size")+numlen);
02933 
02934       colDefaultSize = atoi(num.Data());
02935       colPrecision = colDefaultSize;
02936       if (colPrecision>18) colPrecision = 18;
02937    }
02938    if (opt.Contains("precision=")) {
02939       int start = opt.Index("precision=");
02940       int numpos = start + strlen("precision=");
02941       int numlen = 0;
02942       int len = opt.Length();
02943       while( (numpos+numlen<len) && isdigit(opt[numpos+numlen]) ) numlen++;
02944       TString num = opt(numpos,numlen);
02945       opt.Remove(start,strlen("precision")+numlen);
02946 
02947       colPrecision = atoi(num.Data());
02948    }
02949    TString defFormat = Form("%d.%d",colDefaultSize,colPrecision);
02950    if (opt.Contains("col=")) {
02951       int start = opt.Index("col=");
02952       int numpos = start + strlen("col=");
02953       int numlen = 0;
02954       int len = opt.Length();
02955       while( (numpos+numlen<len) &&
02956              (isdigit(opt[numpos+numlen])
02957               || opt[numpos+numlen] == 'c'
02958               || opt[numpos+numlen] == 'd'
02959               || opt[numpos+numlen] == 'i'
02960               || opt[numpos+numlen] == 'o'
02961               || opt[numpos+numlen] == 'x'
02962               || opt[numpos+numlen] == 'X'
02963               || opt[numpos+numlen] == 'u'
02964               || opt[numpos+numlen] == 'f'
02965               || opt[numpos+numlen] == 'e'
02966               || opt[numpos+numlen] == 'E'
02967               || opt[numpos+numlen] == 'g'
02968               || opt[numpos+numlen] == 'G'
02969               || opt[numpos+numlen] == 'l'
02970               || opt[numpos+numlen] == 'L'
02971               || opt[numpos+numlen] == 'h'
02972               || opt[numpos+numlen] == '#'
02973               || opt[numpos+numlen]=='.'
02974               || opt[numpos+numlen]==':')) numlen++;
02975       TString flist = opt(numpos,numlen);
02976       opt.Remove(start,strlen("col")+numlen);
02977 
02978       int i = 0;
02979       while(i<flist.Length() && flist[i]==':') {
02980          colFormats.push_back(defFormat);
02981          colSizes.push_back(colDefaultSize);
02982          ++i;
02983       }
02984       for(; i<flist.Length(); ++i) {
02985          int next = flist.Index(":",i);
02986          if (next==i) {
02987             colFormats.push_back(defFormat);
02988          } else if (next==kNPOS) {
02989             colFormats.push_back(flist(i,flist.Length()-i));
02990             i = flist.Length();
02991          } else {
02992             colFormats.push_back(flist(i,next-i));
02993             i = next;
02994          }
02995          UInt_t siz = atoi(colFormats[colFormats.size()-1].Data());
02996          colSizes.push_back( siz ? siz : colDefaultSize );
02997       }
02998    }
02999 
03000    TTreeFormula **var;
03001    std::vector<TString> cnames;
03002    TString onerow;
03003    Long64_t entry,entryNumber;
03004    Int_t i,nch;
03005    UInt_t ncols = 8;   // by default first 8 columns are printed only
03006    ofstream out;
03007    Int_t lenfile = 0;
03008    char * fname = 0;
03009    if (fScanRedirect) {
03010       fTree->SetScanField(0);  // no page break if Scan is redirected
03011       fname = (char *) fScanFileName;
03012       if (!fname) fname = (char*)"";
03013       lenfile = strlen(fname);
03014       if (!lenfile) {
03015          Int_t nch2 = strlen(fTree->GetName());
03016          fname = new char[nch2+10];
03017          strlcpy(fname, fTree->GetName(),nch2+10);
03018          strlcat(fname, "-scan.dat",nch2+10);
03019       }
03020       out.open(fname, ios::out);
03021       if (!out.good ()) {
03022          if (!lenfile) delete [] fname;
03023          Error("Scan","Can not open file for redirection");
03024          return 0;
03025       }
03026    }
03027    TObjArray *leaves = fTree->GetListOfLeaves();
03028    if (leaves==0) return 0;
03029    UInt_t nleaves = leaves->GetEntriesFast();
03030    if (nleaves < ncols) ncols = nleaves;
03031    nch = varexp ? strlen(varexp) : 0;
03032 
03033    nentries = GetEntriesToProcess(firstentry, nentries);
03034 
03035 //*-*- Compile selection expression if there is one
03036    TTreeFormula        *select  = 0;
03037    if (selection && strlen(selection)) {
03038       select = new TTreeFormula("Selection",selection,fTree);
03039       if (!select) return -1;
03040       if (!select->GetNdim()) { delete select; return -1; }
03041       fFormulaList->Add(select);
03042    }
03043 //*-*- if varexp is empty, take first 8 columns by default
03044    int allvar = 0;
03045    if (varexp && !strcmp(varexp, "*")) { ncols = nleaves; allvar = 1; }
03046    if (nch == 0 || allvar) {
03047       UInt_t ncs = ncols;
03048       ncols = 0;
03049       for (ui=0;ui<ncs;++ui) {
03050          TLeaf *lf = (TLeaf*)leaves->At(ui);
03051          if (lf->GetBranch()->GetListOfBranches()->GetEntries() > 0) continue;
03052          cnames.push_back( lf->GetBranch()->GetMother()->GetName() );
03053          if (cnames[ncols] == lf->GetName() ) {
03054             // Already complete, let move on.
03055          } else if (cnames[ncols][cnames[ncols].Length()-1]=='.') {
03056             cnames[ncols] = lf->GetBranch()->GetName(); // name of branch already include mother's name
03057          } else {
03058             if (lf->GetBranch()->GetMother()->IsA()->InheritsFrom(TBranchElement::Class())) {
03059                TBranchElement *mother = (TBranchElement*)lf->GetBranch()->GetMother();
03060                if (mother->GetType() == 3 || mother->GetType() == 4) {
03061                   // The name of the mother branch is embedded in the sub-branch names.
03062                   cnames[ncols] = lf->GetBranch()->GetName();
03063                   ++ncols;
03064                   continue;
03065                }
03066             }
03067             if (!strchr(lf->GetBranch()->GetName() ,'[') ) {
03068                cnames[ncols].Append('.');
03069                cnames[ncols].Append( lf->GetBranch()->GetName() );
03070             }
03071          }
03072          if (strcmp( lf->GetBranch()->GetName(), lf->GetName() ) != 0 ) {
03073             cnames[ncols].Append('.');
03074             cnames[ncols].Append( lf->GetName() );
03075          }
03076          ++ncols;
03077       }
03078 //*-*- otherwise select only the specified columns
03079    } else {
03080 
03081       ncols = fSelector->SplitNames(varexp, cnames);
03082 
03083    }
03084    var = new TTreeFormula* [ncols];
03085 
03086    for(ui=colFormats.size();ui<ncols;++ui) {
03087       colFormats.push_back(defFormat);
03088       colSizes.push_back(colDefaultSize);
03089    }
03090 
03091 //*-*- Create the TreeFormula objects corresponding to each column
03092    for (ui=0;ui<ncols;ui++) {
03093       var[ui] = new TTreeFormula("Var1",cnames[ui].Data(),fTree);
03094       fFormulaList->Add(var[ui]);
03095    }
03096 
03097 //*-*- Create a TreeFormulaManager to coordinate the formulas
03098    TTreeFormulaManager *manager=0;
03099    Bool_t hasArray = kFALSE;
03100    Bool_t forceDim = kFALSE;
03101    if (fFormulaList->LastIndex()>=0) {
03102       if (select) {
03103          if (select->GetManager()->GetMultiplicity() > 0 ) {
03104             manager = new TTreeFormulaManager;
03105             for(i=0;i<=fFormulaList->LastIndex();i++) {
03106                manager->Add((TTreeFormula*)fFormulaList->At(i));
03107             }
03108             manager->Sync();
03109          }
03110       }
03111       for(i=0;i<=fFormulaList->LastIndex();i++) {
03112          TTreeFormula *form = ((TTreeFormula*)fFormulaList->At(i));
03113          switch( form->GetManager()->GetMultiplicity() ) {
03114             case  1:
03115             case  2:
03116                hasArray = kTRUE;
03117                forceDim = kTRUE;
03118                break;
03119             case -1:
03120                forceDim = kTRUE;
03121                break;
03122             case  0:
03123                break;
03124          }
03125 
03126       }
03127    }
03128 
03129 //*-*- Print header
03130    onerow = "***********";
03131    if (hasArray) onerow += "***********";
03132 
03133    for (ui=0;ui<ncols;ui++) {
03134       TString starFormat = Form("*%%%d.%ds",colSizes[ui]+2,colSizes[ui]+2);
03135       onerow += Form(starFormat.Data(),var[ui]->PrintValue(-2));
03136    }
03137    if (fScanRedirect)
03138       out<<onerow.Data()<<"*"<<endl;
03139    else
03140       printf("%s*\n",onerow.Data());
03141    onerow = "*    Row   ";
03142    if (hasArray) onerow += "* Instance ";
03143    for (ui=0;ui<ncols;ui++) {
03144       TString numbFormat = Form("* %%%d.%ds ",colSizes[ui],colSizes[ui]);
03145       onerow += Form(numbFormat.Data(),var[ui]->PrintValue(-1));
03146    }
03147    if (fScanRedirect)
03148       out<<onerow.Data()<<"*"<<endl;
03149    else
03150       printf("%s*\n",onerow.Data());
03151    onerow = "***********";
03152    if (hasArray) onerow += "***********";
03153    for (ui=0;ui<ncols;ui++) {
03154       TString starFormat = Form("*%%%d.%ds",colSizes[ui]+2,colSizes[ui]+2);
03155       onerow += Form(starFormat.Data(),var[ui]->PrintValue(-2));
03156    }
03157    if (fScanRedirect)
03158       out<<onerow.Data()<<"*"<<endl;
03159    else
03160       printf("%s*\n",onerow.Data());
03161 //*-*- loop on all selected entries
03162    fSelectedRows = 0;
03163    Int_t tnumber = -1;
03164    Bool_t exitloop = kFALSE;
03165    for (entry=firstentry;
03166         entry<(firstentry+nentries) && !exitloop;
03167         entry++) {
03168       entryNumber = fTree->GetEntryNumber(entry);
03169       if (entryNumber < 0) break;
03170       Long64_t localEntry = fTree->LoadTree(entryNumber);
03171       if (localEntry < 0) break;
03172       if (tnumber != fTree->GetTreeNumber()) {
03173          tnumber = fTree->GetTreeNumber();
03174          if (manager) manager->UpdateFormulaLeaves();
03175          else {
03176             for(i=0;i<=fFormulaList->LastIndex();i++) {
03177                ((TTreeFormula*)fFormulaList->At(i))->UpdateFormulaLeaves();
03178             }
03179          }
03180       }
03181 
03182       int ndata = 1;
03183       if (forceDim) {
03184 
03185          if (manager) {
03186 
03187             ndata = manager->GetNdata(kTRUE);
03188 
03189          } else {
03190 
03191             // let's print the max number of column
03192             for (ui=0;ui<ncols;ui++) {
03193                if (ndata < var[ui]->GetNdata() ) {
03194                   ndata = var[ui]->GetNdata();
03195                }
03196             }
03197             if (select && select->GetNdata()==0) ndata = 0;
03198          }
03199 
03200       }
03201 
03202       if (lenmax && ndata>(int)lenmax) ndata = lenmax;
03203       Bool_t loaded = kFALSE;
03204       for(int inst=0;inst<ndata;inst++) {
03205          if (select) {
03206             if (select->EvalInstance(inst) == 0) {
03207                continue;
03208             }
03209          }
03210          if (inst==0) loaded = kTRUE;
03211          else if (!loaded) {
03212             // EvalInstance(0) always needs to be called so that
03213             // the proper branches are loaded.
03214             for (ui=0;ui<ncols;ui++) {
03215                var[ui]->EvalInstance(0);
03216             }
03217             loaded = kTRUE;
03218          }
03219          onerow = Form("* %8lld ",entryNumber);
03220          if (hasArray) {
03221             onerow += Form("* %8d ",inst);
03222          }
03223          for (ui=0;ui<ncols;++ui) {
03224             TString numbFormat = Form("* %%%d.%ds ",colSizes[ui],colSizes[ui]);
03225             if (var[ui]->GetNdim()) onerow += Form(numbFormat.Data(),var[ui]->PrintValue(0,inst,colFormats[ui].Data()));
03226             else {
03227                TString emptyForm = Form("* %%%dc ",colSizes[ui]);
03228                onerow += Form(emptyForm.Data(),' ');
03229             }
03230          }
03231          fSelectedRows++;
03232          if (fScanRedirect)
03233             out<<onerow.Data()<<"*"<<endl;
03234          else
03235             printf("%s*\n",onerow.Data());
03236          if (fTree->GetScanField() > 0 && fSelectedRows > 0) {
03237             if (fSelectedRows%fTree->GetScanField() == 0) {
03238                fprintf(stderr,"Type <CR> to continue or q to quit ==> ");
03239                int answer, readch;
03240                readch = getchar();
03241                answer = readch;
03242                while (readch != '\n' && readch != EOF) readch = getchar();
03243                if (answer == 'q' || answer == 'Q') {
03244                   exitloop = kTRUE;
03245                   break;
03246                }
03247             }
03248          }
03249       }
03250    }
03251    onerow = "***********";
03252    if (hasArray) onerow += "***********";
03253    for (ui=0;ui<ncols;ui++) {
03254       TString starFormat = Form("*%%%d.%ds",colSizes[ui]+2,colSizes[ui]+2);
03255       onerow += Form(starFormat.Data(),var[ui]->PrintValue(-2));
03256    }
03257    if (fScanRedirect)
03258       out<<onerow.Data()<<"*"<<endl;
03259    else
03260       printf("%s*\n",onerow.Data());
03261    if (select) Printf("==> %lld selected %s", fSelectedRows,
03262                       fSelectedRows == 1 ? "entry" : "entries");
03263    if (fScanRedirect) printf("File <%s> created\n", fname);
03264 
03265 //*-*- delete temporary objects
03266    fFormulaList->Clear();
03267    // The TTreeFormulaManager is deleted by the last TTreeFormula.
03268    delete [] var;
03269    return fSelectedRows;
03270 }
03271 
03272 //______________________________________________________________________________
03273 TSQLResult *TTreePlayer::Query(const char *varexp, const char *selection,
03274                                Option_t *, Long64_t nentries, Long64_t firstentry)
03275 {
03276    // Loop on Tree and return TSQLResult object containing entries passing
03277    // selection. If varexp is 0 (or "") then print only first 8 columns.
03278    // If varexp = "*" print all columns. Otherwise a columns selection can
03279    // be made using "var1:var2:var3". In case of error 0 is returned otherwise
03280    // a TSQLResult object which must be deleted by the user.
03281 
03282    TTreeFormula **var;
03283    std::vector<TString> cnames;
03284    TString onerow;
03285    Long64_t entry,entryNumber;
03286    Int_t i,nch;
03287    Int_t ncols = 8;   // by default first 8 columns are printed only
03288    TObjArray *leaves = fTree->GetListOfLeaves();
03289    Int_t nleaves = leaves->GetEntriesFast();
03290    if (nleaves < ncols) ncols = nleaves;
03291    nch = varexp ? strlen(varexp) : 0;
03292 
03293    nentries = GetEntriesToProcess(firstentry, nentries);
03294 
03295    // compile selection expression if there is one
03296    TTreeFormula *select = 0;
03297    if (strlen(selection)) {
03298       select = new TTreeFormula("Selection",selection,fTree);
03299       if (!select) return 0;
03300       if (!select->GetNdim()) { delete select; return 0; }
03301       fFormulaList->Add(select);
03302    }
03303 
03304    // if varexp is empty, take first 8 columns by default
03305    int allvar = 0;
03306    if (varexp && !strcmp(varexp, "*")) { ncols = nleaves; allvar = 1; }
03307    if (nch == 0 || allvar) {
03308       for (i=0;i<ncols;i++) {
03309          cnames.push_back( ((TLeaf*)leaves->At(i))->GetName() );
03310       }
03311    } else {
03312       // otherwise select only the specified columns
03313       ncols = fSelector->SplitNames(varexp,cnames);
03314    }
03315    var = new TTreeFormula* [ncols];
03316 
03317    // create the TreeFormula objects corresponding to each column
03318    for (i=0;i<ncols;i++) {
03319       var[i] = new TTreeFormula("Var1",cnames[i].Data(),fTree);
03320       fFormulaList->Add(var[i]);
03321    }
03322 
03323    // fill header info into result object
03324    TTreeResult *res = new TTreeResult(ncols);
03325    for (i = 0; i < ncols; i++) {
03326       res->AddField(i, var[i]->PrintValue(-1));
03327    }
03328 
03329    //*-*- Create a TreeFormulaManager to coordinate the formulas
03330    TTreeFormulaManager *manager=0;
03331    if (fFormulaList->LastIndex()>=0) {
03332       manager = new TTreeFormulaManager;
03333       for(i=0;i<=fFormulaList->LastIndex();i++) {
03334          manager->Add((TTreeFormula*)fFormulaList->At(i));
03335       }
03336       manager->Sync();
03337    }
03338 
03339    // loop on all selected entries
03340    const char *aresult;
03341    Int_t len;
03342    char *arow = new char[ncols*50];
03343    fSelectedRows = 0;
03344    Int_t tnumber = -1;
03345    Int_t *fields = new Int_t[ncols];
03346    for (entry=firstentry;entry<firstentry+nentries;entry++) {
03347       entryNumber = fTree->GetEntryNumber(entry);
03348       if (entryNumber < 0) break;
03349       Long64_t localEntry = fTree->LoadTree(entryNumber);
03350       if (localEntry < 0) break;
03351       if (tnumber != fTree->GetTreeNumber()) {
03352          tnumber = fTree->GetTreeNumber();
03353          for (i=0;i<ncols;i++) var[i]->UpdateFormulaLeaves();
03354       }
03355 
03356       Int_t ndata = 1;
03357       if (manager && manager->GetMultiplicity()) {
03358          ndata = manager->GetNdata();
03359       }
03360 
03361       if (select) {
03362          select->GetNdata();
03363          if (select->EvalInstance(0) == 0) continue;
03364       }
03365 
03366       Bool_t loaded = kFALSE;
03367       for(int inst=0;inst<ndata;inst++) {
03368          if (select) {
03369             if (select->EvalInstance(inst) == 0) {
03370                continue;
03371             }
03372          }
03373 
03374          if (inst==0) loaded = kTRUE;
03375          else if (!loaded) {
03376             // EvalInstance(0) always needs to be called so that
03377             // the proper branches are loaded.
03378             for (i=0;i<ncols;i++) {
03379                var[i]->EvalInstance(0);
03380             }
03381             loaded = kTRUE;
03382          }
03383          for (i=0;i<ncols;i++) {
03384             aresult = var[i]->PrintValue(0,inst);
03385             len = strlen(aresult)+1;
03386             if (i == 0) {
03387                memcpy(arow,aresult,len);
03388                fields[i] = len;
03389             } else {
03390                memcpy(arow+fields[i-1],aresult,len);
03391                fields[i] = fields[i-1] + len;
03392             }
03393          }
03394          res->AddRow(new TTreeRow(ncols,fields,arow));
03395          fSelectedRows++;
03396       }
03397    }
03398 
03399    // delete temporary objects
03400    fFormulaList->Clear();
03401    // The TTreeFormulaManager is deleted by the last TTreeFormula.
03402    delete [] fields;
03403    delete [] arow;
03404    delete [] var;
03405 
03406    return res;
03407 }
03408 
03409 //_______________________________________________________________________
03410 void TTreePlayer::SetEstimate(Long64_t n)
03411 {
03412 //*-*-*-*-*-*-*-*-*Set number of entries to estimate variable limits*-*-*-*
03413 //*-*              ================================================
03414 //
03415    fSelector->SetEstimate(n);
03416 }
03417 
03418 //_______________________________________________________________________
03419 void TTreePlayer::StartViewer(Int_t ww, Int_t wh)
03420 {
03421 //*-*-*-*-*-*-*-*-*Start the TTreeViewer on this TTree*-*-*-*-*-*-*-*-*-*
03422 //*-*              ===================================
03423 //
03424 //  ww is the width of the canvas in pixels
03425 //  wh is the height of the canvas in pixels
03426 
03427    if (gROOT->IsBatch()) {
03428       Warning("StartViewer", "viewer cannot run in batch mode");
03429       return;
03430    }
03431 
03432    if (ww || wh) { }   // use unused variables
03433    TPluginHandler *h;
03434    if ((h = gROOT->GetPluginManager()->FindHandler("TVirtualTreeViewer"))) {
03435       if (h->LoadPlugin() == -1)
03436          return;
03437       h->ExecPlugin(1,fTree);
03438    }
03439 }
03440 
03441 //______________________________________________________________________________
03442 void TreeUnbinnedFitLikelihood(Int_t & /*npar*/, Double_t * /*gin*/,
03443                                Double_t &r, Double_t *par, Int_t /*flag*/)
03444 {
03445    // The fit function used by the unbinned likelihood fit.
03446 
03447    Double_t x[3];
03448    TF1 *fitfunc = (TF1*)tFitter->GetObjectFit();
03449    fitfunc->InitArgs(x,par);
03450 
03451    Long64_t n = gTree->GetSelectedRows();
03452    Double_t  *data1 = gTree->GetV1();
03453    Double_t  *data2 = gTree->GetV2();
03454    Double_t  *data3 = gTree->GetV3();
03455    Double_t *weight = gTree->GetW();
03456    Double_t logEpsilon = -230;   // protect against negative probabilities
03457    Double_t logL = 0.0, prob;
03458    //printf("n=%lld, data1=%x, weight=%x\n",n,data1,weight);
03459 
03460    for(Long64_t i = 0; i < n; i++) {
03461       if (weight[i] <= 0) continue;
03462       x[0] = data1[i];
03463       if (data2) x[1] = data2[i];
03464       if (data3) x[2] = data3[i];
03465       prob = fitfunc->EvalPar(x,par);
03466       //printf("i=%lld, x=%g, w=%g, prob=%g, logL=%g\n",i,x[0],weight[i],prob,logL);
03467       if(prob > 0) logL += TMath::Log(prob) * weight[i];
03468       else         logL += logEpsilon * weight[i];
03469    }
03470 
03471    r = -2*logL;
03472 }
03473 
03474 
03475 //______________________________________________________________________________
03476 Int_t TTreePlayer::UnbinnedFit(const char *funcname ,const char *varexp, const char *selection,Option_t *option ,Long64_t nentries, Long64_t firstentry)
03477 {
03478 //*-*-*-*-*-*Unbinned fit of one or more variable(s) from a Tree*-*-*-*-*-*
03479 //*-*        ===================================================
03480 //
03481 //  funcname is a TF1 function.
03482 //
03483 //  See TTree::Draw for explanations of the other parameters.
03484 //
03485 //   Fit the variable varexp using the function funcname using the
03486 //   selection cuts given by selection.
03487 //
03488 //   The list of fit options is given in parameter option.
03489 //      option = "Q" Quiet mode (minimum printing)
03490 //             = "V" Verbose mode (default is between Q and V)
03491 //             = "E" Perform better Errors estimation using Minos technique
03492 //             = "M" More. Improve fit results
03493 //             = "D" Draw the projected histogram with the fitted function
03494 //                   normalized to the number of selected rows
03495 //                   and multiplied by the bin width
03496 //
03497 //   You can specify boundary limits for some or all parameters via
03498 //        func->SetParLimits(p_number, parmin, parmax);
03499 //   if parmin>=parmax, the parameter is fixed
03500 //   Note that you are not forced to fix the limits for all parameters.
03501 //   For example, if you fit a function with 6 parameters, you can do:
03502 //     func->SetParameters(0,3.1,1.e-6,0.1,-8,100);
03503 //     func->SetParLimits(4,-10,-4);
03504 //     func->SetParLimits(5, 1,1);
03505 //   With this setup, parameters 0->3 can vary freely
03506 //   Parameter 4 has boundaries [-10,-4] with initial value -8
03507 //   Parameter 5 is fixed to 100.
03508 //
03509 //   For the fit to be meaningful, the function must be self-normalized.
03510 //
03511 //   i.e. It must have the same integral regardless of the parameter
03512 //   settings.  Otherwise the fit will effectively just maximize the
03513 //   area.
03514 //
03515 //   It is mandatory to have a normalization variable
03516 //   which is fixed for the fit.  e.g.
03517 //
03518 //     TF1* f1 = new TF1("f1", "gaus(0)/sqrt(2*3.14159)/[2]", 0, 5);
03519 //     f1->SetParameters(1, 3.1, 0.01);
03520 //     f1->SetParLimits(0, 1, 1); // fix the normalization parameter to 1
03521 //     data->UnbinnedFit("f1", "jpsimass", "jpsipt>3.0");
03522 //   //
03523 //
03524 //   1, 2 and 3 Dimensional fits are supported.
03525 //   See also TTree::Fit
03526 //
03527 //    Return status
03528 //    =============
03529 //   The function return the status of the fit in the following form
03530 //     fitResult = migradResult + 10*minosResult + 100*hesseResult + 1000*improveResult
03531 //   The fitResult is 0 is the fit is OK.
03532 //   The fitResult is negative in case of an error not connected with the fit.
03533 //   The number of entries used in the fit can be obtained via
03534 //     mytree.GetSelectedRows();
03535 //   If the number of selected entries is null the function returns -1
03536 
03537 
03538 // new implementation using new Fitter classes
03539 
03540    gTree = fTree; // not sure if this is still needed
03541 
03542    // function is given by name, find it in gROOT
03543    TF1* fitfunc = (TF1*)gROOT->GetFunction(funcname);
03544    if (!fitfunc) { Error("UnbinnedFit", "Unknown function: %s",funcname); return 0; }
03545 
03546    Int_t npar = fitfunc->GetNpar();
03547    if (npar <=0) { Error("UnbinnedFit", "Illegal number of parameters = %d",npar); return 0; }
03548 
03549    // Spin through the data to select out the events of interest
03550    // Make sure that the arrays V1,etc are created large enough to accommodate
03551    // all entries
03552    Long64_t oldEstimate = fTree->GetEstimate();
03553    Long64_t nent = fTree->GetEntriesFriend();
03554    fTree->SetEstimate(TMath::Min(nent,nentries));
03555 
03556    // build FitOptions
03557    TString opt = option;
03558    opt.ToUpper();
03559    Foption_t fitOption;
03560    if (opt.Contains("Q")) fitOption.Quiet   = 1;
03561    if (opt.Contains("V")){fitOption.Verbose = 1; fitOption.Quiet   = 0;}
03562    if (opt.Contains("E")) fitOption.Errors  = 1;
03563    if (opt.Contains("M")) fitOption.More    = 1;
03564    if (!opt.Contains("D")) fitOption.Nograph    = 1;  // what about 0
03565    // could add range and automatic normalization of functions and gradient
03566 
03567    TString drawOpt = "goff para";
03568    if (!fitOption.Nograph) drawOpt = "";
03569    Long64_t nsel = DrawSelect(varexp, selection,drawOpt, nentries, firstentry);
03570 
03571    if (!fitOption.Nograph  && GetSelectedRows() <= 0 && GetDimension() > 4) {
03572       Info("UnbinnedFit","Ignore option D with more than 4 variables");
03573       nsel = DrawSelect(varexp, selection,"goff para", nentries, firstentry);
03574    }
03575 
03576    //if no selected entries return
03577    Long64_t nrows = GetSelectedRows();
03578 
03579    if (nrows <= 0) {
03580       Error("UnbinnedFit", "Cannot fit: no entries selected");
03581       return -1;
03582    }
03583 
03584    // Check that function has same dimension as number of variables
03585    Int_t ndim = GetDimension();
03586    // do not check with TF1::GetNdim() since it returns 1 for TF1 classes created with
03587    // a C function with larger dimension
03588 
03589 
03590    // use pointer stored in the tree (not copy the data in)
03591    std::vector<double *> vlist(ndim);
03592    for (int i = 0; i < ndim; ++i)
03593       vlist[i] = fSelector->GetVal(i);
03594 
03595    // fill the data
03596    ROOT::Fit::UnBinData * fitdata = new ROOT::Fit::UnBinData(nrows, ndim, vlist.begin());
03597 
03598 
03599 
03600    ROOT::Math::MinimizerOptions minOption;
03601    TFitResultPtr ret = ROOT::Fit::UnBinFit(fitdata,fitfunc, fitOption, minOption);
03602 
03603    //reset estimate
03604    fTree->SetEstimate(oldEstimate);
03605 
03606    //if option "D" is specified, draw the projected histogram
03607    //with the fitted function normalized to the number of selected rows
03608    //and multiplied by the bin width
03609    if (!fitOption.Nograph && fHistogram) {
03610       if (fHistogram->GetDimension() < 2) {
03611          TH1 *hf = (TH1*)fHistogram->Clone("unbinnedFit");
03612          hf->SetLineWidth(3);
03613          hf->Reset();
03614          Int_t nbins = fHistogram->GetXaxis()->GetNbins();
03615          Double_t norm = ((Double_t)nsel)*fHistogram->GetXaxis()->GetBinWidth(1);
03616          for (Int_t bin=1;bin<=nbins;bin++) {
03617             Double_t func = norm*fitfunc->Eval(hf->GetBinCenter(bin));
03618             hf->SetBinContent(bin,func);
03619          }
03620          fHistogram->GetListOfFunctions()->Add(hf,"lsame");
03621       }
03622       fHistogram->Draw();
03623    }
03624 
03625 
03626    return int(ret);
03627 
03628 }
03629 
03630 //______________________________________________________________________________
03631 void TTreePlayer::UpdateFormulaLeaves()
03632 {
03633    // this function is called by TChain::LoadTree when a new Tree is loaded.
03634    // Because Trees in a TChain may have a different list of leaves, one
03635    // must update the leaves numbers in the TTreeFormula used by the TreePlayer.
03636 
03637    if (fSelector)  fSelector->Notify();
03638    if (fSelectorUpdate){
03639       //If the selector is writing into a TEntryList, the entry list's
03640       //sublists need to be changed according to the loaded tree
03641       if (fSelector==fSelectorUpdate) {
03642          //FIXME: should be more consistent with selector from file
03643          TObject *obj = fSelector->GetObject();
03644          if (obj){
03645             if (fSelector->GetObject()->InheritsFrom(TEntryList::Class())){
03646                ((TEntryList*)fSelector->GetObject())->SetTree(fTree->GetTree());
03647             }
03648          }
03649       }
03650       if (fSelectorFromFile==fSelectorUpdate) {
03651          TIter next(fSelectorFromFile->GetOutputList());
03652          TEntryList *elist=0;
03653          while ((elist=(TEntryList*)next())){
03654             if (elist->InheritsFrom(TEntryList::Class())){
03655                elist->SetTree(fTree->GetTree());
03656             }
03657          }
03658       }
03659    }
03660 
03661    if (fFormulaList->GetSize()) {
03662       TObjLink *lnk = fFormulaList->FirstLink();
03663       while (lnk) {
03664          lnk->GetObject()->Notify();
03665          lnk = lnk->Next();
03666       }
03667    }
03668 }

Generated on Tue Jul 5 15:43:10 2011 for ROOT_528-00b_version by  doxygen 1.5.1