00001 // @(#)root/treeplayer:$Id: TTreeFormulaManager.cxx 35756 2010-09-27 01:30:22Z pcanal $ 00002 // Author: Philippe Canal 20/03/02 00003 00004 /************************************************************************* 00005 * Copyright (C) 1995-2000, Rene Brun and Fons Rademakers and al. * 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 #include "TTreeFormulaManager.h" 00014 00015 #include "TArrayI.h" 00016 #include "TError.h" 00017 #include "TLeafElement.h" 00018 00019 00020 ClassImp(TTreeFormulaManager) 00021 00022 //________________________________________________________________________________ 00023 // 00024 // A TreeFormulaManager is used to coordinate one or more TTreeFormula objecs 00025 // 00026 // In particular it makes sure that the dimensions and size of all the formulas 00027 // is properly coordinated. 00028 // 00029 00030 00031 //______________________________________________________________________________ 00032 TTreeFormulaManager::TTreeFormulaManager() : TObject() 00033 { 00034 //*-*-*-*-*-*-*-*-*-*-*Tree FormulaManger default constructor*-*-*-*-*-*-*-*-*-* 00035 //*-* ====================================== 00036 00037 fMultiplicity = 0; 00038 fMultiVarDim = kFALSE; 00039 fNeedSync = kFALSE; 00040 fNdata = 1; 00041 00042 for(Int_t i=0; i<kMAXFORMDIM+1; i++) { 00043 fVarDims[i] = 0; 00044 fCumulUsedSizes[i] = 1; 00045 fUsedSizes[i] = 1; 00046 fVirtUsedSizes[i] = 1; 00047 } 00048 fCumulUsedVarDims = 0; 00049 } 00050 00051 00052 //______________________________________________________________________________ 00053 TTreeFormulaManager::~TTreeFormulaManager() 00054 { 00055 //*-*-*-*-*-*-*-*-*-*-*Tree FormulaManager default destructor*-*-*-*-*-*-*-*-*-* 00056 //*-* ====================================== 00057 00058 for (int l = 0; l<kMAXFORMDIM; l++) { 00059 if (fVarDims[l]) delete fVarDims[l]; 00060 fVarDims[l] = 0; 00061 } 00062 if (fCumulUsedVarDims) delete fCumulUsedVarDims; 00063 } 00064 00065 //______________________________________________________________________________ 00066 void TTreeFormulaManager::Remove(TTreeFormula* adding) 00067 { 00068 // Remove a formula from this manager 00069 00070 fFormulas.Remove(adding); 00071 } 00072 00073 //______________________________________________________________________________ 00074 void TTreeFormulaManager::Add(TTreeFormula* adding) 00075 { 00076 // Add a new formula to the list of formulas managed 00077 // The manager of the formula will be changed and the old one will be deleted 00078 // if it is empty. 00079 00080 TTreeFormulaManager * old = adding->fManager; 00081 00082 if (old) { 00083 if (old==this) { 00084 if (fFormulas.FindObject(adding)) return; 00085 } else { 00086 old->fFormulas.Remove(adding); 00087 if (old->fFormulas.GetLast()==-1) delete adding->fManager; 00088 } 00089 } 00090 00091 if (adding->TestBit(TTreeFormula::kNeedEntries)) { 00092 SetBit(TTreeFormula::kNeedEntries); 00093 } 00094 00095 fFormulas.Add(adding); 00096 adding->fManager = this; 00097 fNeedSync = kTRUE; 00098 } 00099 00100 //______________________________________________________________________________ 00101 void TTreeFormulaManager::AddVarDims(Int_t virt_dim) 00102 { 00103 // Add a variable dimension 00104 00105 if (!fVarDims[virt_dim]) fVarDims[virt_dim] = new TArrayI; 00106 } 00107 00108 //______________________________________________________________________________ 00109 void TTreeFormulaManager::CancelDimension(Int_t virt_dim) 00110 { 00111 // Cancel a dimension. This is usually called when an out-of-bounds index 00112 // is used. 00113 00114 fCumulUsedSizes[virt_dim] = 0; 00115 00116 } 00117 00118 //______________________________________________________________________________ 00119 void TTreeFormulaManager::EnableMultiVarDims() 00120 { 00121 // Set the manager as handling a formula with multiple variable dimensions 00122 00123 fMultiVarDim = kTRUE; 00124 if (!fCumulUsedVarDims) fCumulUsedVarDims = new TArrayI; 00125 00126 } 00127 00128 //______________________________________________________________________________ 00129 Int_t TTreeFormulaManager::GetNdata(Bool_t forceLoadDim) 00130 { 00131 //*-*-*-*-*-*-*-*Return number of available instances in the formulas*-*-*-*-*-* 00132 //*-* ==================================================== 00133 // 00134 00135 Int_t k; 00136 00137 // new version of GetNData: 00138 // Possible problem: we only allow one variable dimension so far. 00139 if (fMultiplicity==0) return fNdata; 00140 00141 if (fMultiplicity==2) return fNdata; // CumulUsedSizes[0]; 00142 00143 // We have at least one leaf with a variable size: 00144 00145 // Reset the registers. 00146 for(k=0; k<=kMAXFORMDIM; k++) { 00147 fUsedSizes[k] = TMath::Abs(fVirtUsedSizes[k]); 00148 if (fVarDims[k]) { 00149 for(Int_t i0=0;i0<fVarDims[k]->GetSize();i0++) { 00150 fVarDims[k]->AddAt(0,i0); 00151 } 00152 } 00153 } 00154 if (fCumulUsedVarDims) { 00155 for(Int_t i0=0;i0<fCumulUsedVarDims->GetSize();++i0) { 00156 fCumulUsedVarDims->AddAt(0,i0); 00157 } 00158 } 00159 00160 TTreeFormula* current = 0; 00161 00162 Int_t size = fFormulas.GetLast()+1; 00163 00164 for(Int_t i=0; i<size; i++) { 00165 00166 current = (TTreeFormula*)fFormulas.UncheckedAt(i); 00167 if (current->fMultiplicity!=1 && !current->fHasCast) continue; 00168 if (!current->LoadCurrentDim() ) { 00169 if (forceLoadDim) { 00170 for(Int_t j=i+1; j<size; j++) { 00171 current = (TTreeFormula*)fFormulas.UncheckedAt(j); 00172 if (current->fMultiplicity!=1 && !current->fHasCast) continue; 00173 current->LoadCurrentDim(); 00174 } 00175 } 00176 fNdata = 0; 00177 return 0; 00178 } 00179 } 00180 00181 if (fMultiplicity==-1) { fNdata = 1; return fCumulUsedSizes[0]; } 00182 00183 Int_t overall = 1; 00184 if (!fMultiVarDim) { 00185 for (k = kMAXFORMDIM; (k >= 0) ; k--) { 00186 if (fUsedSizes[k]>=0) { 00187 overall *= fUsedSizes[k]; 00188 fCumulUsedSizes[k] = overall; 00189 } else { 00190 Error("GetNdata","a dimension is still negative!"); 00191 } 00192 } 00193 } else { 00194 overall = 0; // Since we work with additions in this section 00195 if (fCumulUsedVarDims && fUsedSizes[0]>fCumulUsedVarDims->GetSize()) fCumulUsedVarDims->Set(fUsedSizes[0]); 00196 for(Int_t i = 0; i < fUsedSizes[0]; i++) { 00197 Int_t local_overall = 1; 00198 for (k = kMAXFORMDIM; (k > 0) ; k--) { 00199 if (fVarDims[k]) { 00200 Int_t index = fVarDims[k]->At(i); 00201 if (fCumulUsedVarDims && fCumulUsedVarDims->At(i)==1 && index) index = 1; 00202 if (fUsedSizes[k]==1 || (index!=1 && index<fUsedSizes[k])) 00203 local_overall *= index; 00204 else local_overall *= fUsedSizes[k]; 00205 } else { 00206 local_overall *= fUsedSizes[k]; 00207 } 00208 } 00209 // a negative value indicates that this value of the primary index 00210 // will lead to an invalid index; So we skip it. 00211 if (fCumulUsedVarDims->At(i)<0) fCumulUsedVarDims->AddAt(0,i); 00212 else { 00213 fCumulUsedVarDims->AddAt(local_overall,i); 00214 overall += local_overall; 00215 } 00216 } 00217 } 00218 fNdata = overall; 00219 return overall; 00220 00221 } 00222 00223 //______________________________________________________________________________ 00224 Bool_t TTreeFormulaManager::Sync() 00225 { 00226 // Synchronize all the formulae. 00227 00228 if (!fNeedSync) return true; 00229 00230 TTreeFormula* current = 0; 00231 Bool_t hasCast = kFALSE; 00232 00233 fMultiplicity = 0; 00234 // We do not use an intermediary variable because ResetDimensions 00235 // might add more formulas (TCutG). 00236 for(Int_t i=0; i<fFormulas.GetLast()+1; i++) { 00237 current = (TTreeFormula*)fFormulas.UncheckedAt(i); 00238 00239 hasCast |= current->fHasCast; 00240 00241 // We probably need to reset the formula's dimension 00242 00243 current->ResetDimensions(); 00244 switch (current->GetMultiplicity()) { 00245 case 0: 00246 // nothing to do 00247 break; 00248 case 1: 00249 fMultiplicity = 1; 00250 break; 00251 case 2: 00252 if (fMultiplicity!=1) fMultiplicity = 2; 00253 break; 00254 default: 00255 Error("Sync","Unexpected case!"); 00256 } 00257 00258 00259 } // end of for each formulas 00260 00261 // For now we keep fCumulUsedSizes sign aware. 00262 // This will be reset properly (if needed) by GetNdata. 00263 fCumulUsedSizes[kMAXFORMDIM] = fUsedSizes[kMAXFORMDIM]; 00264 for (Int_t k = kMAXFORMDIM; (k > 0) ; k--) { 00265 if (fUsedSizes[k-1]>=0) { 00266 fCumulUsedSizes[k-1] = fUsedSizes[k-1] * fCumulUsedSizes[k]; 00267 } else { 00268 fCumulUsedSizes[k-1] = - TMath::Abs(fCumulUsedSizes[k]); 00269 } 00270 } 00271 00272 // Now that we know the virtual dimension we know if a loop over EvalInstance 00273 // is needed or not. 00274 if (fCumulUsedSizes[0]==1 && fMultiplicity>0) { 00275 // Case where even though we have an array. We know that they will always 00276 // only be one element. 00277 fMultiplicity -= 2; 00278 } else if (fCumulUsedSizes[0]<0 && fMultiplicity==2) { 00279 // Case of a fixed length array that have one of its indices given 00280 // by a variable. 00281 fMultiplicity = 1; 00282 } else if (fMultiplicity==0 && hasCast) { 00283 fMultiplicity = -1; 00284 } 00285 00286 switch(fMultiplicity) { 00287 case 0: fNdata = 1; break; 00288 case 2: fNdata = fCumulUsedSizes[0]; break; 00289 default: fNdata = 0; 00290 } 00291 fNeedSync = kFALSE; 00292 00293 return true; 00294 } 00295 00296 //______________________________________________________________________________ 00297 void TTreeFormulaManager::UpdateFormulaLeaves() 00298 { 00299 // this function could be called TTreePlayer::UpdateFormulaLeaves, itself 00300 // called by TChain::LoadTree when a new Tree is loaded. 00301 // Because Trees in a TChain may have a different list of leaves, one 00302 // must update the leaves numbers in the TTreeFormula used by the TreePlayer. 00303 00304 // A safer alternative would be to recompile the whole thing .... However 00305 // currently compile HAS TO be called from the constructor! 00306 00307 Int_t size = fFormulas.GetLast()+1; 00308 00309 for(Int_t i=0; i<size; i++) { 00310 00311 TTreeFormula *current = (TTreeFormula*)fFormulas.UncheckedAt(i); 00312 current->UpdateFormulaLeaves(); 00313 00314 } 00315 00316 } 00317 00318 //______________________________________________________________________________ 00319 void TTreeFormulaManager::UpdateUsedSize(Int_t &virt_dim, Int_t vsize) 00320 { 00321 // Reload the array sizes 00322 00323 if (vsize<0) 00324 fVirtUsedSizes[virt_dim] = -1 * TMath::Abs(fVirtUsedSizes[virt_dim]); 00325 else 00326 if ( TMath::Abs(fVirtUsedSizes[virt_dim])==1 00327 || (vsize < TMath::Abs(fVirtUsedSizes[virt_dim]) ) ) { 00328 // Absolute values represent the min of all real dimensions 00329 // that are known. The fact that it is negatif indicates 00330 // that one of the leaf has a variable size for this 00331 // dimensions. 00332 if (fVirtUsedSizes[virt_dim] < 0) { 00333 fVirtUsedSizes[virt_dim] = -1 * vsize; 00334 } else { 00335 fVirtUsedSizes[virt_dim] = vsize; 00336 } 00337 } 00338 fUsedSizes[virt_dim] = fVirtUsedSizes[virt_dim]; 00339 virt_dim++; 00340 00341 }