RooProdPdf.cxx

Go to the documentation of this file.
00001 /*****************************************************************************
00002  * Project: RooFit                                                           *
00003  * Package: RooFitCore                                                       *
00004  * @(#)root/roofitcore:$Id: RooProdPdf.cxx 36845 2010-11-22 15:44:57Z wouter $
00005  * Authors:                                                                  *
00006  *   WV, Wouter Verkerke, UC Santa Barbara, verkerke@slac.stanford.edu       *
00007  *   DK, David Kirkby,    UC Irvine,         dkirkby@uci.edu                 *
00008  *                                                                           *
00009  * Copyright (c) 2000-2005, Regents of the University of California          *
00010  *                          and Stanford University. All rights reserved.    *
00011  *                                                                           *
00012  * Redistribution and use in source and binary forms,                        *
00013  * with or without modification, are permitted according to the terms        *
00014  * listed in LICENSE (http://roofit.sourceforge.net/license.txt)             *
00015  *****************************************************************************/
00016 
00017 //////////////////////////////////////////////////////////////////////////////
00018 //
00019 // BEGIN_HTML
00020 // RooProdPdf is an efficient implementation of a product of PDFs of the form 
00021 //
00022 //  PDF_1 * PDF_2 * ... * PDF_N
00023 //
00024 // PDFs may share observables. If that is the case any irreducable subset
00025 // of PDFS that share observables will be normalized with explicit numeric
00026 // integration as any built-in normalization will no longer be valid.
00027 //
00028 // Alternatively, products using conditional PDFs can be defined, e.g.
00029 //
00030 //    F(x|y) * G(y)
00031 //
00032 // meaning a pdf F(x) _given_ y and a PDF G(y). In this contruction F is only
00033 // normalized w.r.t x and G is normalized w.r.t y. The product in this construction
00034 // is properly normalized.
00035 //
00036 // If exactly one of the component PDFs supports extended likelihood fits, the
00037 // product will also be usable in extended mode, returning the number of expected
00038 // events from the extendable component PDF. The extendable component does not
00039 // have to appear in any specific place in the list.
00040 // 
00041 // END_HTML
00042 //
00043 
00044 #include "RooFit.h"
00045 #include "Riostream.h"
00046 #include "TClass.h"
00047 
00048 #include "TIterator.h"
00049 #include "RooProdPdf.h"
00050 #include "RooRealProxy.h"
00051 #include "RooProdGenContext.h"
00052 #include "RooGenProdProj.h"
00053 #include "RooProduct.h"
00054 #include "RooNameReg.h"
00055 #include "RooMsgService.h"
00056 #include "RooFormulaVar.h"
00057 #include "RooRealVar.h"
00058 #include "RooAddition.h"
00059 #include "RooGlobalFunc.h"
00060 #include "RooConstVar.h"
00061 #include "RooWorkspace.h"
00062 #include "RooRangeBoolean.h"
00063 #include "RooCustomizer.h"
00064 #include "RooRealIntegral.h"
00065 
00066 #include <string.h>
00067 #include <sstream>
00068 
00069 #ifndef _WIN32
00070 #include <strings.h>
00071 #else
00072 
00073 static char *strtok_r(char *s1, const char *s2, char **lasts)
00074 {
00075   char *ret;
00076   
00077   if (s1 == NULL)
00078     s1 = *lasts;
00079   while(*s1 && strchr(s2, *s1))
00080     ++s1;
00081   if(*s1 == '\0')
00082     return NULL;
00083   ret = s1;
00084   while(*s1 && !strchr(s2, *s1))
00085     ++s1;
00086   if(*s1)
00087     *s1++ = '\0';
00088   *lasts = s1;
00089   return ret;
00090 }
00091 
00092 #endif
00093 
00094 
00095 #include "TSystem.h"
00096 
00097 ClassImp(RooProdPdf)
00098 ;
00099 
00100 
00101 
00102 //_____________________________________________________________________________
00103 RooProdPdf::RooProdPdf() :
00104   _curNormSet(0),
00105   _cutOff(0),
00106   _extendedIndex(-1),
00107   _useDefaultGen(kFALSE),
00108   _refRangeName(0),
00109   _selfNorm(kTRUE)
00110 {
00111   // Default constructor
00112   _pdfIter = _pdfList.createIterator() ;  
00113 }
00114 
00115 
00116 
00117 //_____________________________________________________________________________
00118 RooProdPdf::RooProdPdf(const char *name, const char *title, Double_t cutOff) :
00119   RooAbsPdf(name,title), 
00120   _cacheMgr(this,10),
00121   _genCode(10),
00122   _cutOff(cutOff),
00123   _pdfList("!pdfs","List of PDFs",this),
00124   _extendedIndex(-1),
00125   _useDefaultGen(kFALSE),
00126   _refRangeName(0),
00127   _selfNorm(kTRUE)
00128 {
00129   // Dummy constructor
00130   _pdfIter = _pdfList.createIterator() ;
00131 }
00132 
00133 
00134 
00135 //_____________________________________________________________________________
00136 RooProdPdf::RooProdPdf(const char *name, const char *title,
00137                        RooAbsPdf& pdf1, RooAbsPdf& pdf2, Double_t cutOff) : 
00138   RooAbsPdf(name,title), 
00139   _cacheMgr(this,10),
00140   _genCode(10),
00141   _cutOff(cutOff),
00142   _pdfList("!pdfs","List of PDFs",this),
00143   _pdfIter(_pdfList.createIterator()), 
00144   _extendedIndex(-1),
00145   _useDefaultGen(kFALSE),
00146   _refRangeName(0),
00147   _selfNorm(kTRUE)
00148 {
00149   // Constructor with 2 PDFs (most frequent use case).
00150   // 
00151   // The optional cutOff parameter can be used as a speed optimization if
00152   // one or more of the PDF have sizable regions with very small values,
00153   // which would pull the entire product of PDFs to zero in those regions.
00154   //
00155   // After each PDF multiplication, the running product is compared with
00156   // the cutOff parameter. If the running product is smaller than the
00157   // cutOff value, the product series is terminated and remaining PDFs
00158   // are not evaluated.
00159   //
00160   // There is no magic value of the cutOff, the user should experiment
00161   // to find the appropriate balance between speed and precision.
00162   // If a cutoff is specified, the PDFs most likely to be small should
00163   // be put first in the product. The default cutOff value is zero.
00164   //
00165 
00166   _pdfList.add(pdf1) ;
00167   RooArgSet* nset1 = new RooArgSet("nset") ;
00168   _pdfNSetList.Add(nset1) ;
00169   if (pdf1.canBeExtended()) {
00170     _extendedIndex = _pdfList.index(&pdf1) ;
00171   }
00172 
00173   _pdfList.add(pdf2) ;
00174   RooArgSet* nset2 = new RooArgSet("nset") ;
00175   _pdfNSetList.Add(nset2) ;
00176 
00177   if (pdf2.canBeExtended()) {
00178     if (_extendedIndex>=0) {
00179       // Protect against multiple extended terms
00180       coutW(InputArguments) << "RooProdPdf::RooProdPdf(" << GetName() 
00181                             << ") multiple components with extended terms detected,"
00182                             << " product will not be extendible." << endl ;
00183       _extendedIndex=-1 ;
00184     } else {
00185       _extendedIndex=_pdfList.index(&pdf2) ;
00186     }
00187   }
00188 }
00189 
00190 
00191 
00192 //_____________________________________________________________________________
00193 RooProdPdf::RooProdPdf(const char* name, const char* title, const RooArgList& inPdfList, Double_t cutOff) :
00194   RooAbsPdf(name,title), 
00195   _cacheMgr(this,10),
00196   _genCode(10),
00197   _cutOff(cutOff),
00198   _pdfList("!pdfs","List of PDFs",this),
00199   _pdfIter(_pdfList.createIterator()), 
00200   _extendedIndex(-1),
00201   _useDefaultGen(kFALSE),
00202   _refRangeName(0),
00203   _selfNorm(kTRUE)
00204 {
00205   // Constructor from a list of PDFs
00206   // 
00207   // The optional cutOff parameter can be used as a speed optimization if
00208   // one or more of the PDF have sizable regions with very small values,
00209   // which would pull the entire product of PDFs to zero in those regions.
00210   //
00211   // After each PDF multiplication, the running product is compared with
00212   // the cutOff parameter. If the running product is smaller than the
00213   // cutOff value, the product series is terminated and remaining PDFs
00214   // are not evaluated.
00215   //
00216   // There is no magic value of the cutOff, the user should experiment
00217   // to find the appropriate balance between speed and precision.
00218   // If a cutoff is specified, the PDFs most likely to be small should
00219   // be put first in the product. The default cutOff value is zero.
00220 
00221   TIterator* iter = inPdfList.createIterator() ;
00222   RooAbsArg* arg ;
00223   Int_t numExtended(0) ;
00224   while((arg=(RooAbsArg*)iter->Next())) {
00225     RooAbsPdf* pdf = dynamic_cast<RooAbsPdf*>(arg) ;
00226     if (!pdf) {
00227       coutW(InputArguments) << "RooProdPdf::RooProdPdf(" << GetName() << ") list arg " 
00228                             << pdf->GetName() << " is not a PDF, ignored" << endl ;
00229       continue ;
00230     }
00231     _pdfList.add(*pdf) ;
00232 
00233     RooArgSet* nset = new RooArgSet("nset") ;
00234     _pdfNSetList.Add(nset) ;
00235 
00236     if (pdf->canBeExtended()) {
00237       _extendedIndex = _pdfList.index(pdf) ;
00238       numExtended++ ;
00239     }
00240   }
00241 
00242   // Protect against multiple extended terms
00243   if (numExtended>1) {
00244     coutW(InputArguments) << "RooProdPdf::RooProdPdf(" << GetName() 
00245                           << ") WARNING: multiple components with extended terms detected,"
00246                           << " product will not be extendible." << endl ;
00247     _extendedIndex = -1 ;
00248   }
00249 
00250   delete iter ;
00251 }
00252 
00253 
00254 
00255 //_____________________________________________________________________________
00256 RooProdPdf::RooProdPdf(const char* name, const char* title, const RooArgSet& fullPdfSet,
00257                        const RooCmdArg& arg1, const RooCmdArg& arg2,
00258                        const RooCmdArg& arg3, const RooCmdArg& arg4,
00259                        const RooCmdArg& arg5, const RooCmdArg& arg6,
00260                        const RooCmdArg& arg7, const RooCmdArg& arg8) :
00261   RooAbsPdf(name,title), 
00262   _cacheMgr(this,10),
00263   _genCode(10),
00264   _cutOff(0),
00265   _pdfList("!pdfs","List of PDFs",this),
00266   _pdfIter(_pdfList.createIterator()), 
00267   _extendedIndex(-1),
00268   _useDefaultGen(kFALSE),
00269   _refRangeName(0),
00270   _selfNorm(kTRUE)
00271 {
00272   // Constructor from named argument list
00273   //
00274   // fullPdf -- Set of 'regular' PDFS that are normalized over all their observables
00275   // Conditional(pdfSet,depSet) -- Add PDF to product with condition that it
00276   //                               only be normalized over specified observables
00277   //                               any remaining observables will be conditional
00278   //                               observables
00279   //                               
00280   //
00281   // For example, given a PDF F(x,y) and G(y)
00282   //
00283   // RooProdPdf("P","P",G,Conditional(F,x)) will construct a 2-dimensional PDF as follows:
00284   // 
00285   //   P(x,y) = G(y)/Int[y]G(y) * F(x,y)/Int[x]G(x,y)
00286   //
00287   // which is a well normalized and properly defined PDF, but different from the
00288   //  
00289   //  P'(x,y) = F(x,y)*G(y) / Int[x,y] F(x,y)*G(y)
00290   //
00291   // In the former case the y distribution of P is identical to that of G, while
00292   // F only is used to determine the correlation between X and Y. In the latter
00293   // case the Y distribution is defined by the product of F and G.
00294   //
00295   // This P(x,y) construction is analoguous to generating events from F(x,y) with
00296   // a prototype dataset sampled from G(y)
00297   
00298   RooLinkedList l ;
00299   l.Add((TObject*)&arg1) ;  l.Add((TObject*)&arg2) ;  
00300   l.Add((TObject*)&arg3) ;  l.Add((TObject*)&arg4) ;
00301   l.Add((TObject*)&arg5) ;  l.Add((TObject*)&arg6) ;  
00302   l.Add((TObject*)&arg7) ;  l.Add((TObject*)&arg8) ;
00303 
00304   initializeFromCmdArgList(fullPdfSet,l) ;
00305 }
00306 
00307 
00308 
00309 //_____________________________________________________________________________
00310 RooProdPdf::RooProdPdf(const char* name, const char* title,
00311                        const RooCmdArg& arg1, const RooCmdArg& arg2,
00312                        const RooCmdArg& arg3, const RooCmdArg& arg4,
00313                        const RooCmdArg& arg5, const RooCmdArg& arg6,
00314                        const RooCmdArg& arg7, const RooCmdArg& arg8) :
00315   RooAbsPdf(name,title), 
00316   _cacheMgr(this,10),
00317   _genCode(10),
00318   _cutOff(0),
00319   _pdfList("!pdfList","List of PDFs",this),
00320   _pdfIter(_pdfList.createIterator()), 
00321   _extendedIndex(-1),
00322   _useDefaultGen(kFALSE),
00323   _refRangeName(0),
00324   _selfNorm(kTRUE)
00325 {
00326   // Constructor from named argument list
00327   //
00328   // fullPdf -- Set of 'regular' PDFS that are normalized over all their observables
00329   // Conditional(pdfSet,depSet) -- Add PDF to product with condition that it
00330   //                               only be normalized over specified observables
00331   //                               any remaining observables will be conditional
00332   //                               observables
00333   //                               
00334   //
00335   // For example, given a PDF F(x,y) and G(y)
00336   //
00337   // RooProdPdf("P","P",G,Conditional(F,x)) will construct a 2-dimensional PDF as follows:
00338   // 
00339   //   P(x,y) = G(y)/Int[y]G(y) * F(x,y)/Int[x]G(x,y)
00340   //
00341   // which is a well normalized and properly defined PDF, but different from the
00342   //  
00343   //  P'(x,y) = F(x,y)*G(y) / Int[x,y] F(x,y)*G(y)
00344   //
00345   // In the former case the y distribution of P is identical to that of G, while
00346   // F only is used to determine the correlation between X and Y. In the latter
00347   // case the Y distribution is defined by the product of F and G.
00348   //
00349   // This P(x,y) construction is analoguous to generating events from F(x,y) with
00350   // a prototype dataset sampled from G(y)
00351   
00352   RooLinkedList l ;
00353   l.Add((TObject*)&arg1) ;  l.Add((TObject*)&arg2) ;  
00354   l.Add((TObject*)&arg3) ;  l.Add((TObject*)&arg4) ;
00355   l.Add((TObject*)&arg5) ;  l.Add((TObject*)&arg6) ;  
00356   l.Add((TObject*)&arg7) ;  l.Add((TObject*)&arg8) ;
00357 
00358   initializeFromCmdArgList(RooArgSet(),l) ;
00359 }
00360 
00361 
00362 
00363 //_____________________________________________________________________________
00364 RooProdPdf::RooProdPdf(const char* name, const char* title, const RooArgSet& fullPdfSet, const RooLinkedList& cmdArgList) :
00365   RooAbsPdf(name,title), 
00366   _cacheMgr(this,10),
00367   _genCode(10),
00368   _cutOff(0),
00369   _pdfList("!pdfs","List of PDFs",this),
00370   _pdfIter(_pdfList.createIterator()), 
00371   _extendedIndex(-1),
00372   _useDefaultGen(kFALSE),
00373   _refRangeName(0),
00374   _selfNorm(kTRUE)
00375 {
00376   // Internal constructor from list of named arguments  
00377   initializeFromCmdArgList(fullPdfSet, cmdArgList) ;
00378 }
00379 
00380 
00381 
00382 //_____________________________________________________________________________
00383 RooProdPdf::RooProdPdf(const RooProdPdf& other, const char* name) :
00384   RooAbsPdf(other,name), 
00385   _cacheMgr(other._cacheMgr,this),
00386   _genCode(other._genCode),
00387   _cutOff(other._cutOff),
00388   _pdfList("!pdfs",this,other._pdfList),
00389   _pdfIter(_pdfList.createIterator()), 
00390   _extendedIndex(other._extendedIndex),
00391   _useDefaultGen(other._useDefaultGen),
00392   _refRangeName(other._refRangeName),
00393   _selfNorm(other._selfNorm),
00394   _defNormSet(other._defNormSet)
00395 {
00396   // Copy constructor
00397 
00398   // Clone contents of normalizarion set list
00399   TIterator* iter = other._pdfNSetList.MakeIterator() ;
00400   RooArgSet* nset ;
00401   while((nset=(RooArgSet*)iter->Next())) {
00402     RooArgSet* tmp = (RooArgSet*) nset->snapshot() ;
00403     tmp->setName(nset->GetName()) ;
00404     _pdfNSetList.Add(tmp) ;
00405   }
00406   delete iter ;
00407 
00408 }
00409 
00410 
00411 
00412 //_____________________________________________________________________________
00413 void RooProdPdf::initializeFromCmdArgList(const RooArgSet& fullPdfSet, const RooLinkedList& l)
00414 {
00415   // Initialize RooProdPdf configuration from given list of RooCmdArg configuration arguments
00416   // and set of 'regular' p.d.f.s in product
00417 
00418   Int_t numExtended(0) ;
00419 
00420   // Process set of full PDFS
00421   TIterator* siter = fullPdfSet.createIterator() ;
00422   RooAbsPdf* pdf ;
00423   while((pdf=(RooAbsPdf*)siter->Next())) {
00424     _pdfList.add(*pdf) ;
00425     RooArgSet* nset1 = new RooArgSet("nset") ;
00426     _pdfNSetList.Add(nset1) ;       
00427 
00428     if (pdf->canBeExtended()) {
00429       _extendedIndex = _pdfList.index(pdf) ;
00430       numExtended++ ;
00431     }
00432 
00433   }
00434   delete siter ;
00435 
00436   // Process list of conditional PDFs
00437   TIterator* iter = l.MakeIterator() ;
00438   RooCmdArg* carg ;
00439   while((carg=(RooCmdArg*)iter->Next())) {
00440 
00441     if (!TString(carg->GetName()).CompareTo("Conditional")) {
00442 
00443       Int_t argType = carg->getInt(0) ;
00444       RooArgSet* pdfSet = (RooArgSet*) carg->getSet(0) ;
00445       RooArgSet* normSet = (RooArgSet*) carg->getSet(1) ;
00446 
00447       TIterator* siter2 = pdfSet->createIterator() ;
00448       RooAbsPdf* thePdf ;
00449       while((thePdf=(RooAbsPdf*)siter2->Next())) {
00450         _pdfList.add(*thePdf) ;
00451 
00452         if (argType==0) {
00453           RooArgSet* tmp = (RooArgSet*) normSet->snapshot() ;
00454           tmp->setName("nset") ;
00455           _pdfNSetList.Add(tmp) ;                 
00456         } else {
00457           RooArgSet* tmp = (RooArgSet*) normSet->snapshot() ;
00458           tmp->setName("cset") ;
00459           _pdfNSetList.Add(tmp) ;                 
00460         }
00461 
00462         if (thePdf->canBeExtended()) {
00463           _extendedIndex = _pdfList.index(thePdf) ;
00464           numExtended++ ;
00465         }
00466 
00467       }
00468       delete siter2 ;
00469 
00470 
00471     } else if (TString(carg->GetName()).CompareTo("")) {
00472       coutW(InputArguments) << "Unknown arg: " << carg->GetName() << endl ;
00473     }
00474   }
00475 
00476   // Protect against multiple extended terms
00477   if (numExtended>1) {
00478     coutW(InputArguments) << "RooProdPdf::RooProdPdf(" << GetName() 
00479                           << ") WARNING: multiple components with extended terms detected,"
00480                           << " product will not be extendible." << endl ;
00481     _extendedIndex = -1 ;
00482   }
00483 
00484 
00485   delete iter ;
00486 }
00487 
00488 
00489 
00490 //_____________________________________________________________________________
00491 RooProdPdf::~RooProdPdf()
00492 {
00493   // Destructor
00494 
00495   _pdfNSetList.Delete() ;
00496   delete _pdfIter ;
00497 }
00498 
00499 
00500 
00501 //_____________________________________________________________________________
00502 Double_t RooProdPdf::getVal(const RooArgSet* set) const 
00503 {
00504   // Overload getVal() to intercept normalization set for use in evaluate()
00505   _curNormSet = (RooArgSet*)set ;
00506   return RooAbsPdf::getVal(set) ;
00507 }
00508 
00509 
00510 
00511 //_____________________________________________________________________________
00512 Double_t RooProdPdf::evaluate() const 
00513 {
00514   // Calculate current value of object
00515 
00516   Int_t code ;
00517   RooArgList *plist(0) ;
00518   RooLinkedList *nlist(0) ;
00519   getPartIntList(_curNormSet,0,plist,nlist,code) ;
00520 
00521   // preceding call to getPartIntList guarantees non-null return
00522   // coverity[NULL_RETURNS]
00523   CacheElem* cache = (CacheElem*) _cacheMgr.getObj(_curNormSet,0,&code,0) ;
00524   Double_t ret =  calculate(*cache) ;
00525 
00526   return ret ;
00527 }
00528 
00529 
00530 
00531 //_____________________________________________________________________________
00532 Double_t RooProdPdf::calculate(const RooArgList* partIntList, const RooLinkedList* normSetList) const
00533 {
00534   // Calculate running product of pdfs terms, using the supplied
00535   // normalization set in 'normSetList' for each component
00536 
00537   RooAbsReal* partInt ;
00538   RooArgSet* normSet ;
00539   Double_t value(1.0) ;
00540   Int_t n = partIntList->getSize() ;
00541 
00542   Int_t i ;
00543   for (i=0 ; i<n ; i++) {
00544     partInt = ((RooAbsReal*)partIntList->at(i)) ;
00545     normSet = ((RooArgSet*)normSetList->At(i)) ;    
00546     Double_t piVal = partInt->getVal(normSet->getSize()>0 ? normSet : 0) ;
00547 //     cout << "partInt(" << partInt->GetName() << ") = " << piVal << " normSet = " << normSet << " " << (normSet->getSize()>0 ? *normSet : RooArgSet()) << endl ;
00548     value *= piVal ;
00549     if (value<_cutOff) {
00550       break ;
00551     }
00552   }
00553 
00554   return value ;
00555 }
00556 
00557 
00558 
00559 //_____________________________________________________________________________
00560 Double_t RooProdPdf::calculate(const RooProdPdf::CacheElem& cache, Bool_t /*verbose*/) const
00561 {
00562   // Calculate running product of pdfs terms, using the supplied
00563   // normalization set in 'normSetList' for each component
00564 
00565   //cout << "RooProdPdf::calculate from cache" << endl ;
00566 
00567   Double_t value(1.0) ;
00568 
00569   if (cache._isRearranged) {
00570 
00571     if (dologD(Eval)) {
00572       cxcoutD(Eval) << "RooProdPdf::calculate(" << GetName() << ") rearranged product calculation" 
00573                     << " calculate: num = " << cache._rearrangedNum->GetName() << " = " << cache._rearrangedNum->getVal() << endl ;
00574 //       cache._rearrangedNum->printComponentTree("",0,5) ;    
00575       cxcoutD(Eval) << "calculate: den = " << cache._rearrangedDen->GetName() << " = " << cache._rearrangedDen->getVal() << endl ;      
00576 //       cache._rearrangedDen->printComponentTree("",0,5) ;    
00577     }
00578 
00579     value = cache._rearrangedNum->getVal() / cache._rearrangedDen->getVal() ;
00580     
00581   } else {
00582     
00583     cxcoutD(Eval) << "RooProdPdf::calculate(" << GetName() << ") regular product chain calculation" << endl ;
00584     
00585     RooAbsReal* partInt ;
00586     RooArgSet* normSet ;
00587     Int_t n = cache._partList.getSize() ;
00588     
00589     Int_t i ;
00590     for (i=0 ; i<n ; i++) {
00591       partInt = ((RooAbsReal*)cache._partList.at(i)) ;
00592       normSet = ((RooArgSet*)cache._normList.At(i)) ;    
00593       Double_t piVal = partInt->getVal(normSet->getSize()>0 ? normSet : 0) ;
00594       //cout << "partInt " << partInt->GetName() << " is of type " << partInt->IsA()->GetName() << endl ;
00595       if (dynamic_cast<RooAbsPdf*>(partInt)) {
00596         cxcoutD(Eval) << "product term " << partInt->GetName() << " normalized over " << (normSet?*normSet:RooArgSet())  
00597                       << " = " << partInt->getVal() << " / " << ((RooAbsPdf*)partInt)->getNorm(normSet) << " = " << piVal << endl ;
00598       } else {
00599         cxcoutD(Eval) << "product term " << partInt->GetName() << " normalized over " << (normSet?*normSet:RooArgSet()) << " = " << piVal << endl ;
00600       }
00601       value *= piVal ;
00602       if (value<_cutOff) {
00603         break ;
00604       }
00605     }
00606   }
00607 
00608   cxcoutD(Eval) << "return value = " << value << endl ;
00609   return value ;
00610 }
00611 
00612 
00613 
00614 //_____________________________________________________________________________
00615 void RooProdPdf::factorizeProduct(const RooArgSet& normSet, const RooArgSet& intSet,
00616                                   RooLinkedList& termList, RooLinkedList& normList, 
00617                                   RooLinkedList& impDepList, RooLinkedList& crossDepList,
00618                                   RooLinkedList& intList) const 
00619 {
00620   // Factorize product in irreducible terms for given choice of integration/normalization
00621  
00622   _pdfIter->Reset() ;
00623   RooAbsPdf* pdf ;
00624 
00625   // List of all term dependents: normalization and imported
00626   RooLinkedList depAllList ;
00627   RooLinkedList depIntNoNormList ;
00628 
00629   // Setup lists for factorization terms and their dependents
00630   RooArgSet* term(0) ;
00631   RooArgSet* termNormDeps(0) ;
00632   RooArgSet* termAllDeps(0) ;
00633   RooArgSet* termIntDeps(0) ;
00634   RooArgSet* termIntNoNormDeps(0) ;
00635   TIterator* lIter = termList.MakeIterator() ;
00636   TIterator* ldIter = normList.MakeIterator() ;
00637   TIterator* laIter = depAllList.MakeIterator() ;
00638   TIterator* nIter = _pdfNSetList.MakeIterator() ;
00639   RooArgSet* pdfNSet, *pdfNSetOrig, *pdfCSet ;
00640 
00641   // Loop over the PDFs
00642   while((pdf=(RooAbsPdf*)_pdfIter->Next())) {    
00643     pdfNSetOrig = (RooArgSet*) nIter->Next() ;
00644     lIter->Reset() ;
00645     ldIter->Reset() ;
00646     laIter->Reset() ;
00647 
00648     // Reduce pdfNSet to actual dependents
00649     if (string("nset")==pdfNSetOrig->GetName()) {
00650       pdfNSet = pdf->getObservables(*pdfNSetOrig) ;
00651       pdfCSet = new RooArgSet ;
00652     } else if (string("cset") == pdfNSetOrig->GetName()) {
00653       RooArgSet* tmp = pdf->getObservables(normSet) ;
00654       tmp->remove(*pdfNSetOrig,kTRUE,kTRUE) ;
00655       pdfCSet = pdfNSetOrig ;
00656       pdfNSet = tmp ;
00657     } else {
00658       // Legacy mode. Interpret at NSet for backward compatibility
00659       pdfNSet = pdf->getObservables(*pdfNSetOrig) ;
00660       pdfCSet = new RooArgSet ;
00661     }
00662 
00663 
00664     RooArgSet pdfNormDeps ; // Dependents to be normalized for the PDF
00665     RooArgSet pdfAllDeps ; // All dependents of this PDF ;
00666 
00667     // Make list of all dependents of this PDF
00668     RooArgSet* tmp = pdf->getObservables(normSet) ;
00669     pdfAllDeps.add(*tmp) ;
00670     delete tmp ;
00671 
00672     
00673 //     cout << GetName() << ": pdf = " << pdf->GetName() << " pdfAllDeps = " << pdfAllDeps << " pdfNSet = " << *pdfNSet << " pdfCSet = " << *pdfCSet << endl ;
00674 
00675     // Make list of normalization dependents for this PDF ;
00676     if (pdfNSet->getSize()>0) {
00677       // PDF is conditional
00678       RooArgSet* tmp2 = (RooArgSet*) pdfAllDeps.selectCommon(*pdfNSet) ;
00679       pdfNormDeps.add(*tmp2) ;
00680       delete tmp2 ;
00681     } else {
00682       // PDF is regular
00683       pdfNormDeps.add(pdfAllDeps) ;
00684     }
00685 
00686 //     cout << GetName() << ": pdfNormDeps for " << pdf->GetName() << " = " << pdfNormDeps << endl ;
00687 
00688     RooArgSet* pdfIntSet = pdf->getObservables(intSet) ;
00689 
00690     // WVE if we have no norm deps, conditional observables should be taken out of pdfIntSet
00691     if (pdfNormDeps.getSize()==0 && pdfCSet->getSize()>0) {
00692       pdfIntSet->remove(*pdfCSet,kTRUE,kTRUE) ;
00693 //       cout << GetName() << ": have no norm deps, removing conditional observables from intset" << endl ;
00694     }
00695 
00696     RooArgSet pdfIntNoNormDeps(*pdfIntSet) ;
00697     pdfIntNoNormDeps.remove(pdfNormDeps,kTRUE,kTRUE) ;
00698 
00699 
00700 //     cout << GetName() << ": pdf = " << pdf->GetName() << " intset = " << *pdfIntSet << " pdfIntNoNormDeps = " << pdfIntNoNormDeps << endl ;
00701 
00702     // Check if this PDF has dependents overlapping with one of the existing terms
00703     Bool_t done(kFALSE) ;
00704     while((term=(RooArgSet*)lIter->Next())) {      
00705       termNormDeps=(RooArgSet*)ldIter->Next() ;
00706       termAllDeps=(RooArgSet*)laIter->Next() ;
00707 
00708       // PDF should be added to existing term if 
00709       // 1) It has overlapping normalization dependents with any other PDF in existing term
00710       // 2) It has overlapping dependents of any class for which integration is requested
00711       // 3) If normalization happens over multiple ranges, and those ranges are both defined
00712       //    in either observable
00713 
00714       Bool_t normOverlap = pdfNormDeps.overlaps(*termNormDeps)  ;
00715       //Bool_t intOverlap =  pdfIntSet->overlaps(*termAllDeps) ;
00716 
00717       if (normOverlap) {
00718 //      cout << GetName() << ": this term overlaps with term " << (*term) << " in normalization observables" << endl ;
00719 
00720         term->add(*pdf) ;
00721         termNormDeps->add(pdfNormDeps,kFALSE) ;
00722         termAllDeps->add(pdfAllDeps,kFALSE) ;
00723         if (!termIntDeps) {
00724           termIntDeps = new RooArgSet("termIntDeps") ;
00725         }
00726         termIntDeps->add(*pdfIntSet,kFALSE) ;
00727         if (!termIntNoNormDeps) {
00728           termIntNoNormDeps = new RooArgSet("termIntNoNormDeps") ;
00729         }
00730         termIntNoNormDeps->add(pdfIntNoNormDeps,kFALSE) ;
00731         done = kTRUE ;
00732       }
00733     }
00734 
00735     // If not, create a new term
00736     if (!done) {
00737       if (!(pdfNormDeps.getSize()==0&&pdfAllDeps.getSize()==0&&pdfIntSet->getSize()==0) || normSet.getSize()==0) {
00738 //      cout << GetName() << ": creating new term" << endl ;
00739         term = new RooArgSet("term") ;
00740         termNormDeps = new RooArgSet("termNormDeps") ;
00741         termAllDeps = new RooArgSet("termAllDeps") ;
00742         termIntDeps = new RooArgSet("termIntDeps") ;
00743         termIntNoNormDeps = new RooArgSet("termIntNoNormDeps") ;
00744         
00745         term->add(*pdf) ;
00746         termNormDeps->add(pdfNormDeps,kFALSE) ;
00747         termAllDeps->add(pdfAllDeps,kFALSE) ;
00748         termIntDeps->add(*pdfIntSet,kFALSE) ;
00749         termIntNoNormDeps->add(pdfIntNoNormDeps,kFALSE) ;
00750         
00751         termList.Add(term) ;
00752         normList.Add(termNormDeps) ;
00753         depAllList.Add(termAllDeps) ;
00754         intList.Add(termIntDeps) ;
00755         depIntNoNormList.Add(termIntNoNormDeps) ;
00756       }
00757     }
00758 
00759     // We own the reduced version of pdfNSet
00760     delete pdfNSet ;
00761     delete pdfIntSet ;
00762     if (pdfCSet != pdfNSetOrig) {
00763       delete pdfCSet ;
00764     }
00765   }
00766 
00767   // Loop over list of terms again to determine 'imported' observables
00768   lIter->Reset() ;
00769   ldIter->Reset() ;
00770   laIter->Reset() ;
00771   TIterator* innIter = depIntNoNormList.MakeIterator() ;
00772 
00773 //   cout << "now making second loop over terms" << endl ;
00774   // coverity[UNUSED_VALUE]
00775   while((term=(RooArgSet*)lIter->Next())) {
00776     RooArgSet* normDeps = (RooArgSet*) ldIter->Next() ;
00777     RooArgSet* allDeps = (RooArgSet*) laIter->Next() ;
00778     RooArgSet* intNoNormDeps = (RooArgSet*) innIter->Next() ;
00779 
00780     // Make list of wholly imported dependents
00781     RooArgSet impDeps(*allDeps) ;
00782     impDeps.remove(*normDeps,kTRUE,kTRUE) ;
00783     impDepList.Add(impDeps.snapshot()) ;
00784 //     cout << GetName() << ": list of imported dependents for term " << (*term) << " set to " << impDeps << endl ;
00785 
00786     // Make list of cross dependents (term is self contained for these dependents, 
00787     // but components import dependents from other components)
00788     RooArgSet* crossDeps = (RooArgSet*) intNoNormDeps->selectCommon(*normDeps) ;
00789     crossDepList.Add(crossDeps->snapshot()) ;
00790 //     cout << GetName() << ": list of cross dependents for term " << (*term) << " set to " << *crossDeps << endl ;
00791     delete crossDeps ;
00792   }
00793 
00794 
00795   depAllList.Delete() ;
00796   depIntNoNormList.Delete() ;
00797 
00798   delete nIter ;
00799   delete lIter ;
00800   delete ldIter ;
00801   delete laIter ;
00802   delete innIter ;
00803 
00804   return ;
00805 }
00806 
00807 
00808 
00809 
00810 //_____________________________________________________________________________
00811 void RooProdPdf::getPartIntList(const RooArgSet* nset, const RooArgSet* iset, 
00812                                 pRooArgList& partList, pRooLinkedList& nsetList, 
00813                                 Int_t& code, const char* isetRangeName) const 
00814 {
00815   // Return list of (partial) integrals of product terms for integration
00816   // of p.d.f over observables iset while normalization over observables nset.
00817   // Also return list of normalization sets to be used to evaluate 
00818   // each component in the list correctly.
00819 
00820   RooArgList* partListPointer=(RooArgList*)partList ;
00821   RooLinkedList* nsetListPointer=(RooLinkedList*)nsetList ;
00822 
00823 //   cout << "   FOLKERT::RooProdPdf::getPartIntList(" << GetName() <<")  nset = " << (nset?*nset:RooArgSet()) << endl 
00824 //        << "   _normRange = " << _normRange << endl 
00825 //        << "   iset = " << (iset?*iset:RooArgSet()) << endl 
00826 //        << "   isetRangeName = " << (isetRangeName?isetRangeName:"<null>") << endl ;
00827 
00828   // Check if this configuration was created before
00829   Int_t sterileIdx(-1) ;
00830 
00831   CacheElem* cache = (CacheElem*) _cacheMgr.getObj(nset,iset,&sterileIdx,RooNameReg::ptr(isetRangeName)) ;
00832   if (cache) {
00833     code = _cacheMgr.lastIndex() ;
00834     partList = &cache->_partList ;
00835     nsetList = &cache->_normList ;
00836 
00837     return ;
00838   }
00839 
00840   // Create containers for partial integral components to be generated
00841   cache = new CacheElem ;
00842 
00843   // Factorize the product in irreducible terms for this nset
00844   RooLinkedList terms, norms, imp, ints, cross ;
00845 //   cout << "RooProdPdf::getPIL -- now calling factorizeProduct()" << endl ;
00846 
00847 
00848   // Normalization set used for factorization  
00849   RooArgSet factNset(nset ? (*nset) : _defNormSet) ;
00850 //   cout << GetName() << "factNset = " << factNset << endl ;
00851 
00852   factorizeProduct(factNset,iset?(*iset):RooArgSet(),terms,norms,imp,cross,ints) ;
00853 
00854   RooArgSet *norm, *integ, *xdeps, *imps ;
00855   
00856   // Group irriducible terms that need to be (partially) integrated together
00857   RooLinkedList groupedList ; 
00858   RooArgSet outerIntDeps ;
00859 //   cout << "RooProdPdf::getPIL -- now calling groupProductTerms()" << endl ;
00860   groupProductTerms(groupedList,outerIntDeps,terms,norms,imp,ints,cross) ;
00861   TIterator* gIter = groupedList.MakeIterator() ;
00862   RooLinkedList* group ;
00863 
00864   // Loop over groups
00865 //   cout<<"FK: pdf("<<GetName()<<") Starting selecting F(x|y)!"<<endl;
00866   // Find groups of type F(x|y), i.e. termImpSet!=0, construct ratio object
00867   map<string,RooArgSet> ratioTerms ;
00868   while((group=(RooLinkedList*)gIter->Next())) {    
00869     if (group->GetSize()==1) {
00870 //       cout<<"FK: Starting Single Term"<<endl;
00871 
00872       RooArgSet* term = (RooArgSet*) group->At(0) ;
00873           
00874       Int_t termIdx = terms.IndexOf(term) ;
00875       norm=(RooArgSet*) norms.At(termIdx) ;
00876       imps=(RooArgSet*)imp.At(termIdx) ;      
00877       RooArgSet termNSet(*norm), termImpSet(*imps) ;      
00878 
00879 //       cout<<"FK: termImpSet.getSize()  = "<<termImpSet.getSize()<< " " << termImpSet << endl;
00880 //       cout<<"FK: _refRangeName = "<<_refRangeName<<endl;
00881 
00882       if (termImpSet.getSize()>0 && _refRangeName!=0) {   
00883 
00884 //      cout << "WVE now here" << endl ;
00885 
00886         // WVE we can skip this if the ref range is equal to the normalization range
00887         Bool_t rangeIdentical(kTRUE) ;
00888         TIterator* niter = termNSet.createIterator() ;
00889         RooRealVar* normObs ;
00890 //      cout << "_normRange = " << _normRange << " _refRangeName = " << RooNameReg::str(_refRangeName) << endl ;
00891         while((normObs=(RooRealVar*)niter->Next())) {
00892           //FK: Here the refRange should be compared to _normRange, if it's set, and to the normObs range if it's not set
00893           if(_normRange.Length()>0){        
00894             if (normObs->getMin(_normRange.Data())!=normObs->getMin(RooNameReg::str(_refRangeName))) rangeIdentical=kFALSE ;
00895             if (normObs->getMax(_normRange.Data())!=normObs->getMax(RooNameReg::str(_refRangeName))) rangeIdentical=kFALSE ;        
00896           }
00897           else{
00898             if (normObs->getMin()!=normObs->getMin(RooNameReg::str(_refRangeName))) rangeIdentical=kFALSE ;
00899             if (normObs->getMax()!=normObs->getMax(RooNameReg::str(_refRangeName))) rangeIdentical=kFALSE ;
00900           }
00901         }
00902         delete niter ;
00903 //      cout<<"FK: rangeIdentical Single = "<<(rangeIdentical ? 'T':'F')<<endl;
00904         // coverity[CONSTANT_EXPRESSION_RESULT]
00905         if (!rangeIdentical || 1) {
00906 //        cout << "PREPARING RATIO HERE (SINGLE TERM)" << endl ;          
00907           RooAbsReal* ratio = makeCondPdfRatioCorr(*(RooAbsReal*)term->first(),termNSet,termImpSet,normRange(),RooNameReg::str(_refRangeName)) ;          
00908           ostringstream str ; termImpSet.printValue(str) ;
00909           ratioTerms[str.str()].add(*ratio) ;
00910         }       
00911       }
00912         
00913     } else {
00914 //       cout<<"FK: Starting Composite Term"<<endl;
00915       
00916       RooArgSet compTermSet, compTermNorm ;
00917       TIterator* tIter = group->MakeIterator() ;
00918       RooArgSet* term ;
00919       while((term=(RooArgSet*)tIter->Next())) {
00920         
00921         Int_t termIdx = terms.IndexOf(term) ;
00922         norm=(RooArgSet*) norms.At(termIdx) ;
00923         imps=(RooArgSet*)imp.At(termIdx) ;        
00924         RooArgSet termNSet(*norm), termImpSet(*imps) ;
00925         
00926         if (termImpSet.getSize()>0 && _refRangeName!=0) {         
00927 
00928           // WVE we can skip this if the ref range is equal to the normalization range
00929           Bool_t rangeIdentical(kTRUE) ;
00930           TIterator* niter = termNSet.createIterator() ;
00931           RooRealVar* normObs ;
00932           //FK: Here the refRange should be compared to _normRange, if it's set, and to the normObs range if it's not set
00933           if(_normRange.Length()>0){
00934             while((normObs=(RooRealVar*)niter->Next())) {
00935               if (normObs->getMin(_normRange.Data())!=normObs->getMin(RooNameReg::str(_refRangeName))) rangeIdentical=kFALSE ;
00936               if (normObs->getMax(_normRange.Data())!=normObs->getMax(RooNameReg::str(_refRangeName))) rangeIdentical=kFALSE ;
00937             }
00938           }
00939           else{
00940             while((normObs=(RooRealVar*)niter->Next())) {
00941               if (normObs->getMin()!=normObs->getMin(RooNameReg::str(_refRangeName))) rangeIdentical=kFALSE ;
00942               if (normObs->getMax()!=normObs->getMax(RooNameReg::str(_refRangeName))) rangeIdentical=kFALSE ;
00943             }
00944           }
00945 //        cout<<"FK: rangeIdentical Composite = "<<(rangeIdentical ? 'T':'F') <<endl;
00946           delete niter ;
00947           if (!rangeIdentical || 1) {       
00948 //          cout << "PREPARING RATIO HERE (COMPOSITE TERM)" << endl ;       
00949             RooAbsReal* ratio = makeCondPdfRatioCorr(*(RooAbsReal*)term->first(),termNSet,termImpSet,normRange(),RooNameReg::str(_refRangeName)) ;
00950             ostringstream str ; termImpSet.printValue(str) ;
00951             ratioTerms[str.str()].add(*ratio) ;
00952           }
00953         }      
00954       }
00955       delete tIter ;
00956     }
00957 
00958   }
00959   gIter->Reset() ;
00960 
00961   // Find groups with y as termNSet
00962   // Replace G(y) with (G(y),ratio)
00963   while((group=(RooLinkedList*)gIter->Next())) {    
00964     if (group->GetSize()==1) {
00965       RooArgSet* term = (RooArgSet*) group->At(0) ;
00966       
00967       Int_t termIdx = terms.IndexOf(term) ;
00968       norm=(RooArgSet*) norms.At(termIdx) ;
00969       imps=(RooArgSet*)imp.At(termIdx) ;      
00970       RooArgSet termNSet(*norm), termImpSet(*imps) ;      
00971 
00972       // If termNset matches index of ratioTerms, insert ratio here
00973       ostringstream str ; termNSet.printValue(str) ;
00974       if (ratioTerms[str.str()].getSize()>0) {
00975 //      cout << "MUST INSERT RATIO OBJECT IN TERM (SINGLE) " << *term << endl ;
00976         term->add(ratioTerms[str.str()]) ;
00977       }
00978       
00979     } else {
00980       
00981       RooArgSet compTermSet, compTermNorm ;
00982       TIterator* tIter = group->MakeIterator() ;
00983       RooArgSet* term ;
00984       while((term=(RooArgSet*)tIter->Next())) {
00985         
00986         Int_t termIdx = terms.IndexOf(term) ;
00987         norm=(RooArgSet*) norms.At(termIdx) ;
00988         imps=(RooArgSet*)imp.At(termIdx) ;        
00989         RooArgSet termNSet(*norm), termImpSet(*imps) ;
00990         
00991         // If termNset matches index of ratioTerms, insert ratio here
00992         ostringstream str ; termNSet.printValue(str) ;
00993         if (ratioTerms[str.str()].getSize()>0) {
00994 //        cout << "MUST INSERT RATIO OBJECT IN TERM (COMPOSITE)" << *term << endl ;
00995           term->add(ratioTerms[str.str()]) ;
00996         }
00997         
00998       }      
00999       delete tIter ;
01000     }
01001   }
01002   gIter->Reset() ;
01003   
01004   
01005   while((group=(RooLinkedList*)gIter->Next())) {
01006     
01007 //     cout << GetName() << ":now processing group" << endl ;
01008 //      group->Print("1") ;
01009     
01010     if (group->GetSize()==1) {
01011 //       cout << "processing atomic item" << endl ;
01012       RooArgSet* term = (RooArgSet*) group->At(0) ;
01013 
01014       Int_t termIdx = terms.IndexOf(term) ;
01015       norm=(RooArgSet*) norms.At(termIdx) ;
01016       integ=(RooArgSet*) ints.At(termIdx) ;
01017       xdeps=(RooArgSet*)cross.At(termIdx) ;
01018       imps=(RooArgSet*)imp.At(termIdx) ;
01019         
01020       RooArgSet termNSet, termISet, termXSet, termImpSet ;
01021       
01022       // Take list of normalization, integrated dependents from factorization algorithm
01023       termISet.add(*integ) ;
01024       termNSet.add(*norm) ;
01025       
01026       // Cross-imported integrated dependents
01027       termXSet.add(*xdeps) ;
01028       termImpSet.add(*imps) ;
01029       
01030 //       cout << GetName() << ": termISet = " << termISet << endl ;
01031 //       cout << GetName() << ": termNSet = " << termNSet << endl ;
01032 //       cout << GetName() << ": termXSet = " << termXSet << endl ;
01033 //       cout << GetName() << ": termImpSet = " << termImpSet << endl ;
01034       
01035       // Add prefab term to partIntList. 
01036       Bool_t isOwned ;
01037       vector<RooAbsReal*> func = processProductTerm(nset,iset,isetRangeName,term,termNSet,termISet,isOwned) ;
01038       if (func[0]) {
01039         cache->_partList.add(*func[0]) ;
01040         if (isOwned) cache->_ownedList.addOwned(*func[0]) ;
01041         
01042         cache->_normList.Add(norm->snapshot(kFALSE)) ;
01043 
01044         cache->_numList.addOwned(*func[1]) ;
01045         cache->_denList.addOwned(*func[2]) ;
01046 //      cout << "func[0]=" << func[0]->IsA()->GetName() << "::" << func[0]->GetName() << endl ;
01047 //      cout << "func[1]=" << func[1]->IsA()->GetName() << "::" << func[1]->GetName() << endl ;
01048 //      cout << "func[2]=" << func[2]->IsA()->GetName() << "::" << func[2]->GetName() << endl ;
01049       }
01050     } else {
01051 
01052 //        cout << "processing composite item" << endl ;
01053       RooArgSet compTermSet, compTermNorm, compTermNum, compTermDen ;
01054       TIterator* tIter = group->MakeIterator() ;
01055       RooArgSet* term ;
01056       while((term=(RooArgSet*)tIter->Next())) {
01057 
01058 //      cout << GetName() << ": processing term " << (*term) << " of composite item" << endl ;
01059         
01060         Int_t termIdx = terms.IndexOf(term) ;
01061         norm=(RooArgSet*) norms.At(termIdx) ;
01062         integ=(RooArgSet*) ints.At(termIdx) ;
01063         xdeps=(RooArgSet*)cross.At(termIdx) ;
01064         imps=(RooArgSet*)imp.At(termIdx) ;
01065         
01066         RooArgSet termNSet, termISet, termXSet, termImpSet ;
01067         termISet.add(*integ) ;
01068         termNSet.add(*norm) ;
01069         termXSet.add(*xdeps) ;
01070         termImpSet.add(*imps) ;
01071 
01072         // Remove outer integration dependents from termISet
01073         termISet.remove(outerIntDeps,kTRUE,kTRUE) ;
01074 //      cout << "termISet = " ; termISet.Print("1") ;
01075 
01076 //      cout << GetName() << ": termISet = " << termISet << endl ;
01077 //      cout << GetName() << ": termNSet = " << termNSet << endl ;
01078 //      cout << GetName() << ": termXSet = " << termXSet << endl ;
01079 //      cout << GetName() << ": termImpSet = " << termImpSet << endl ;
01080 
01081         Bool_t isOwned ;
01082         vector<RooAbsReal*> func = processProductTerm(nset,iset,isetRangeName,term,termNSet,termISet,isOwned,kTRUE) ;
01083 //      cout << GetName() << ": created composite term component " << func[0]->GetName() << endl ;
01084         if (func[0]) {
01085           compTermSet.add(*func[0]) ;
01086           if (isOwned) cache->_ownedList.addOwned(*func[0]) ;
01087           compTermNorm.add(*norm,kFALSE) ;
01088 
01089           compTermNum.add(*func[1]) ;
01090           compTermDen.add(*func[2]) ;
01091           //cache->_numList.add(*func[1]) ;
01092           //cache->_denList.add(*func[2]) ;
01093 
01094 //        cout << "func[0]=" << func[0]->IsA()->GetName() << "::" << func[0]->GetName() << endl ;
01095 //        cout << "func[1]=" << func[1]->IsA()->GetName() << "::" << func[1]->GetName() << endl ;
01096 //        cout << "func[2]=" << func[2]->IsA()->GetName() << "::" << func[2]->GetName() << endl ;
01097         }      
01098       }
01099 
01100 //       cout << GetName() << ": constructing special composite product" << endl ;
01101 //       cout << GetName() << ": compTermSet = " ; compTermSet.Print("1") ;
01102       
01103       // WVE THIS NEEDS TO BE REARRANGED
01104 
01105       // compTermset is set van partial integrals to be multiplied
01106       // prodtmp = product (compTermSet)
01107       // inttmp = int ( prodtmp ) d (outerIntDeps) _range_isetRangeName
01108 
01109       const char* prodname = makeRGPPName("SPECPROD",compTermSet,outerIntDeps,RooArgSet(),isetRangeName) ;
01110       RooProduct* prodtmp = new RooProduct(prodname,prodname,compTermSet) ;
01111       cache->_ownedList.addOwned(*prodtmp) ;
01112 
01113       const char* intname = makeRGPPName("SPECINT",compTermSet,outerIntDeps,RooArgSet(),isetRangeName) ;
01114       RooRealIntegral* inttmp = new RooRealIntegral(intname,intname,*prodtmp,outerIntDeps,0,0,isetRangeName) ;
01115       inttmp->setStringAttribute("PROD_TERM_TYPE","SPECINT") ;
01116 
01117       cache->_ownedList.addOwned(*inttmp) ;
01118       cache->_partList.add(*inttmp);
01119 
01120       // Product of numerator terms
01121       string prodname_num = makeRGPPName("SPECPROD_NUM",compTermNum,RooArgSet(),RooArgSet(),0) ;
01122       RooProduct* prodtmp_num = new RooProduct(prodname_num.c_str(),prodname_num.c_str(),compTermNum) ;
01123       prodtmp_num->addOwnedComponents(compTermNum) ;
01124       cache->_ownedList.addOwned(*prodtmp_num) ;
01125       
01126       // Product of denominator terms
01127       string prodname_den = makeRGPPName("SPECPROD_DEN",compTermDen,RooArgSet(),RooArgSet(),0) ;
01128       RooProduct* prodtmp_den = new RooProduct(prodname_den.c_str(),prodname_den.c_str(),compTermDen) ;
01129       prodtmp_den->addOwnedComponents(compTermDen) ;
01130       cache->_ownedList.addOwned(*prodtmp_den) ;
01131 
01132       // Ratio
01133       string name = Form("SPEC_RATIO(%s,%s)",prodname_num.c_str(),prodname_den.c_str()) ;
01134       RooFormulaVar* ndr = new RooFormulaVar(name.c_str(),"@0/@1",RooArgList(*prodtmp_num,*prodtmp_den)) ;
01135 
01136       // Integral of ratio
01137       RooAbsReal* numtmp = ndr->createIntegral(outerIntDeps,isetRangeName) ;      
01138       numtmp->addOwnedComponents(*ndr) ;
01139 
01140       cache->_numList.addOwned(*numtmp) ;
01141       cache->_denList.addOwned(*(RooAbsArg*)RooFit::RooConst(1).clone("1")) ;                
01142       cache->_normList.Add(compTermNorm.snapshot(kFALSE)) ;
01143 
01144       delete tIter ;      
01145     }
01146   }
01147   delete gIter ;
01148 
01149   // Store the partial integral list and return the assigned code ;
01150   code = _cacheMgr.setObj(nset,iset,(RooAbsCacheElement*)cache,RooNameReg::ptr(isetRangeName)) ;
01151 
01152   // Fill references to be returned
01153   partList = &cache->_partList ;
01154   nsetList = &cache->_normList; 
01155 
01156   // WVE DEBUG PRINTING
01157 //   cout << "RooProdPdf::getPartIntList(" << GetName() << ") made cache " << cache << " with the following nset pointers " ;
01158 //   TIterator* nliter = nsetList->MakeIterator() ;
01159 //   RooArgSet* ns ;
01160 //   while((ns=(RooArgSet*)nliter->Next())) {
01161 //     cout << ns << " " ;
01162 //   }
01163 //   cout << endl ;
01164 //   delete nliter ;
01165 
01166   partListPointer=(RooArgList*)partList ;
01167   nsetListPointer=(RooLinkedList*)nsetList ;
01168 
01169 //   cout << "   FOLKERT::RooProdPdf::getPartIntList END(" << GetName() <<")  nset = " << (nset?*nset:RooArgSet()) << endl 
01170 //        << "   _normRange = " << _normRange << endl 
01171 //        << "   iset = " << (iset?*iset:RooArgSet()) << endl 
01172 //        << "   partList = " ; 
01173 //   if(partListPointer) partListPointer->Print() ;
01174 //   cout << "   nsetList = " ;
01175 //   if(nsetListPointer) nsetListPointer->Print("") ;
01176 //   cout << "   code = " << code << endl
01177 //        << "   isetRangeName = " << (isetRangeName?isetRangeName:"<null>") << endl ;
01178 
01179 
01180   // Need to rearrange product in case of multiple ranges
01181   if (_normRange.Contains(",")) {
01182     rearrangeProduct(*cache) ;
01183   }
01184 
01185   // We own contents of all lists filled by factorizeProduct() 
01186   groupedList.Delete() ;
01187   terms.Delete() ;
01188   ints.Delete() ;
01189   imp.Delete() ;
01190   norms.Delete() ;
01191   cross.Delete() ;
01192 }
01193 
01194 
01195 
01196 
01197 //_____________________________________________________________________________
01198 RooAbsReal* RooProdPdf::makeCondPdfRatioCorr(RooAbsReal& pdf, const RooArgSet& termNset, const RooArgSet& /*termImpSet*/, const char* normRangeTmp, const char* refRange) const
01199 {
01200   // For single normalization ranges
01201   RooAbsReal* ratio_num = pdf.createIntegral(termNset,normRangeTmp) ;
01202   RooAbsReal* ratio_den = pdf.createIntegral(termNset,refRange) ;
01203   RooFormulaVar* ratio = new RooFormulaVar(Form("ratio(%s,%s)",ratio_num->GetName(),ratio_den->GetName()),"@0/@1",
01204                                            RooArgList(*ratio_num,*ratio_den)) ;
01205   
01206   ratio->addOwnedComponents(RooArgSet(*ratio_num,*ratio_den)) ;       
01207   ratio->setAttribute("RATIO_TERM") ;
01208   return ratio ;
01209 }
01210 
01211 
01212 
01213 
01214 //_____________________________________________________________________________
01215 void RooProdPdf::rearrangeProduct(RooProdPdf::CacheElem& cache) const
01216 {
01217   TIterator* iterp = cache._partList.createIterator() ;
01218   TIterator* iter1 = cache._numList.createIterator() ;
01219   TIterator* iter2 = cache._denList.createIterator() ;
01220   TIterator* itern = cache._normList.MakeIterator() ;
01221   RooAbsReal* part, *num, *den ;
01222   RooArgSet* nset ;
01223   RooArgSet nomList ;
01224 
01225   list<string> rangeComps ;
01226   char buf[1024] ;  
01227   strlcpy(buf,_normRange.Data(),1024) ;
01228   char* save(0) ;
01229   char* token = strtok_r(buf,",",&save) ;
01230   while(token) {
01231     rangeComps.push_back(token) ;
01232     token = strtok_r(0,",",&save) ;
01233   }
01234 
01235 
01236   map<string,RooArgSet> denListList ; 
01237   RooArgSet specIntDeps ;
01238   string specIntRange ;
01239 
01240 //   cout << "THIS IS REARRANGEPRODUCT" << endl ;
01241 
01242   while((part=(RooAbsReal*)iterp->Next())) {
01243 
01244     // coverity[UNUSED_VALUE]
01245     nset = (RooArgSet*) itern->Next() ;
01246     num = (RooAbsReal*) iter1->Next() ;
01247     den = (RooAbsReal*) iter2->Next() ;
01248     
01249 //     cout << "now processing part " << part->GetName() << " of type " << part->getStringAttribute("PROD_TERM_TYPE") << endl ;
01250 //     cout << "corresponding numerator = " << num->GetName() << endl ;
01251 //     cout << "corresponding denominator = " << den->GetName() << endl ;
01252     
01253 
01254     RooFormulaVar* ratio(0) ;
01255     RooArgSet origNumTerm ;
01256     
01257     if (string("SPECINT")==part->getStringAttribute("PROD_TERM_TYPE")) {
01258 
01259         RooRealIntegral* orig = (RooRealIntegral*) num;
01260         RooFormulaVar* specratio = (RooFormulaVar*) &orig->integrand() ;
01261         RooProduct* func = (RooProduct*) specratio->getParameter(0) ;
01262 
01263         RooArgSet* comps = orig->getComponents() ;
01264         TIterator* iter = comps->createIterator() ;
01265         RooAbsArg* carg ;
01266         while((carg=(RooAbsArg*)iter->Next())) {
01267           if (carg->getAttribute("RATIO_TERM")) {
01268             ratio = (RooFormulaVar*)carg ;
01269             break ;
01270           }
01271         }
01272         delete iter ;
01273         delete comps ;
01274 
01275         if (ratio) {
01276           RooCustomizer cust(*func,"blah") ;
01277           cust.replaceArg(*ratio,RooFit::RooConst(1)) ;
01278           RooAbsArg* funcCust = cust.build() ;
01279 //        cout << "customized function = " << endl ;
01280 //        funcCust->printComponentTree() ;
01281           nomList.add(*funcCust) ;
01282         } else {        
01283           nomList.add(*func) ;    
01284         }
01285 
01286 
01287     } else {
01288 
01289       // Find the ratio term
01290       RooAbsReal* func = num;
01291       // If top level object is integral, navigate to integrand
01292       if (func->InheritsFrom(RooRealIntegral::Class())) {
01293         func = (RooAbsReal*) &((RooRealIntegral*)(func))->integrand();
01294       }
01295       if (func->InheritsFrom(RooProduct::Class())) {
01296 //      cout << "product term found: " ; func->Print() ;
01297         RooArgSet comps(((RooProduct*)(func))->components()) ;
01298         TIterator* iter = comps.createIterator() ;
01299         RooAbsArg* arg ;
01300         while((arg=(RooAbsArg*)iter->Next())) {
01301           if (arg->getAttribute("RATIO_TERM")) {
01302             ratio = (RooFormulaVar*)(arg) ;
01303           } else {
01304             origNumTerm.add(*arg) ;
01305           }
01306         }
01307         delete iter ;
01308       }
01309 
01310       if (ratio) {
01311 //      cout << "Found ratio term in numerator: " << ratio->GetName() << endl ;
01312 //      cout << "Adding only original term to numerator: " << origNumTerm << endl ;
01313         nomList.add(origNumTerm) ;
01314       } else {
01315         nomList.add(*num) ;    
01316       }
01317       
01318     }
01319 
01320     for (list<string>::iterator iter = rangeComps.begin() ; iter != rangeComps.end() ; ++iter) {
01321       // If denominator is an integral, make a clone with the integration range adjusted to
01322       // the selected component of the normalization integral
01323 //       cout << "NOW PROCESSING DENOMINATOR " << den->IsA()->GetName() << "::" << den->GetName() << endl ;
01324 
01325       if (string("SPECINT")==part->getStringAttribute("PROD_TERM_TYPE")) {
01326 
01327 //      cout << "create integral: SPECINT case" << endl ;
01328         RooRealIntegral* orig = (RooRealIntegral*) num;
01329         RooFormulaVar* specRatio = (RooFormulaVar*) &orig->integrand() ;
01330         specIntDeps.add(orig->intVars()) ;
01331         if (orig->intRange()) {
01332           specIntRange = orig->intRange() ;
01333         }
01334         //RooProduct* numtmp = (RooProduct*) specRatio->getParameter(0) ;
01335         RooProduct* dentmp = (RooProduct*) specRatio->getParameter(1) ;
01336 
01337 //      cout << "numtmp = " << numtmp->IsA()->GetName() << "::" << numtmp->GetName() << endl ;
01338 //      cout << "dentmp = " << dentmp->IsA()->GetName() << "::" << dentmp->GetName() << endl ;
01339 
01340 //      cout << "denominator components are " << dentmp->components() << endl ;
01341         RooArgSet comps(dentmp->components()) ;
01342         TIterator* piter = comps.createIterator() ;
01343         RooAbsReal* parg ;
01344         while((parg=(RooAbsReal*)piter->Next())) {
01345 //        cout << "now processing denominator component " << parg->IsA()->GetName() << "::" << parg->GetName() << endl ;
01346 
01347           if (ratio && parg->dependsOn(*ratio)) {
01348 //          cout << "depends in value of ratio" << endl ;
01349 
01350             // Make specialize ratio instance
01351             RooAbsReal* specializedRatio = specializeRatio(*(RooFormulaVar*)ratio,iter->c_str()) ;
01352             
01353 //          cout << "specRatio = " << endl ;
01354 //          specializedRatio->printComponentTree() ;
01355             
01356             // Replace generic ratio with specialized ratio
01357             RooAbsArg *partCust(0) ;
01358             if (parg->InheritsFrom(RooAddition::Class())) {
01359               
01360 
01361 
01362               RooAddition* tmpadd = (RooAddition*)(parg) ;          
01363 
01364               RooCustomizer cust(*tmpadd->list1().first(),Form("blah_%s",iter->c_str())) ;        
01365               cust.replaceArg(*ratio,*specializedRatio) ;         
01366               partCust = cust.build() ;
01367               
01368             } else {
01369               RooCustomizer cust(*parg,Form("blah_%s",iter->c_str())) ;   
01370               cust.replaceArg(*ratio,*specializedRatio) ;         
01371               partCust = cust.build() ;
01372             }
01373             
01374             // Print customized denominator
01375 //          cout << "customized function = " << endl ;
01376 //          partCust->printComponentTree() ;
01377             
01378             RooAbsReal* specializedPartCust = specializeIntegral(*(RooAbsReal*)partCust,iter->c_str()) ;
01379 
01380             // Finally divide again by ratio
01381             string name = Form("%s_divided_by_ratio",specializedPartCust->GetName()) ;
01382             RooFormulaVar* specIntFinal = new RooFormulaVar(name.c_str(),"@0/@1",RooArgList(*specializedPartCust,*specializedRatio)) ;
01383             
01384             denListList[*iter].add(*specIntFinal) ;               
01385           } else {
01386 
01387 //          cout << "does NOT depend on value of ratio" << endl ;
01388 //          parg->Print("t") ;
01389 
01390             denListList[*iter].add(*specializeIntegral(*parg,iter->c_str())) ;            
01391 
01392           }
01393         }
01394 //      cout << "end iteration over denominator components" << endl ;
01395         delete piter ;
01396               
01397 
01398       } else {
01399 
01400         if (ratio) {
01401 
01402           RooAbsReal* specRatio = specializeRatio(*(RooFormulaVar*)ratio,iter->c_str()) ;
01403 
01404           // If integral is 'Int r(y)*g(y) dy ' then divide a posteriori by r(y)
01405 //        cout << "have ratio, orig den = " << den->GetName() << endl ;
01406 
01407           RooArgSet tmp(origNumTerm) ;
01408           tmp.add(*specRatio) ;
01409           string pname = makeRGPPName("PROD",tmp,RooArgSet(),RooArgSet(),0) ;
01410           RooProduct* specDenProd = new RooProduct(pname.c_str(),pname.c_str(),tmp) ;
01411           RooAbsReal* specInt(0) ;
01412 
01413           if (den->InheritsFrom(RooRealIntegral::Class())) {
01414             specInt = specDenProd->createIntegral(((RooRealIntegral*)den)->intVars(),iter->c_str()) ;
01415           } else if (den->InheritsFrom(RooAddition::Class())) {     
01416             RooAddition* orig = (RooAddition*)den ;
01417             RooRealIntegral* origInt = (RooRealIntegral*) orig->list1().first() ;
01418             specInt = specDenProd->createIntegral(origInt->intVars(),iter->c_str()) ;
01419           } else {
01420             throw string("this should not happen") ;
01421           }
01422           
01423           //RooAbsReal* specInt = specializeIntegral(*den,iter->c_str()) ;
01424           string name = Form("%s_divided_by_ratio",specInt->GetName()) ;
01425           RooFormulaVar* specIntFinal = new RooFormulaVar(name.c_str(),"@0/@1",RooArgList(*specInt,*specRatio)) ;
01426           denListList[*iter].add(*specIntFinal) ;
01427         } else {
01428           denListList[*iter].add(*specializeIntegral(*den,iter->c_str())) ;
01429         }
01430         
01431       }
01432     }
01433     
01434   }
01435 
01436   // Do not rearrage terms if numerator and denominator are effectively empty
01437   if (nomList.getSize()==0) {
01438     delete iter1 ;
01439     delete iter2 ;
01440     delete itern ;
01441     return ;
01442   }
01443 
01444   string name = Form("%s_numerator",GetName()) ;
01445   // WVE FIX THIS (2)
01446 
01447   RooAbsReal* numerator = new RooProduct(name.c_str(),name.c_str(),nomList) ;
01448 
01449   RooArgSet products ;
01450 //   cout << "nomList = " << nomList << endl ;
01451   for (map<string,RooArgSet>::iterator iter = denListList.begin() ; iter != denListList.end() ; ++iter) {
01452 //     cout << "denList[" << iter->first << "] = " << iter->second << endl ;
01453     name = Form("%s_denominator_comp_%s",GetName(),iter->first.c_str()) ;
01454     // WVE FIX THIS (2)
01455     RooProduct* prod_comp = new RooProduct(name.c_str(),name.c_str(),iter->second) ;
01456     products.add(*prod_comp) ;
01457   }  
01458   name = Form("%s_denominator_sum",GetName()) ;
01459   RooAbsReal* norm = new RooAddition(name.c_str(),name.c_str(),products) ;
01460   norm->addOwnedComponents(products) ;
01461 
01462   if (specIntDeps.getSize()>0) {
01463     // Apply posterior integration required for SPECINT case
01464     
01465     string namesr = Form("SPEC_RATIO(%s,%s)",numerator->GetName(),norm->GetName()) ;
01466     RooFormulaVar* ndr = new RooFormulaVar(namesr.c_str(),"@0/@1",RooArgList(*numerator,*norm)) ;
01467     
01468     // Integral of ratio
01469     RooAbsReal* numtmp = ndr->createIntegral(specIntDeps,specIntRange.c_str()) ;      
01470     
01471     numerator = numtmp ;
01472     norm = (RooAbsReal*) RooFit::RooConst(1).Clone() ;
01473   }
01474 
01475 
01476 //   cout << "numerator" << endl ;
01477 //   numerator->printComponentTree("",0,5) ;
01478 //   cout << "denominator" << endl ;
01479 //   norm->printComponentTree("",0,5) ;
01480 
01481 
01482   // WVE DEBUG
01483   //RooMsgService::instance().debugWorkspace()->import(RooArgSet(*numerator,*norm)) ;
01484   
01485   cache._rearrangedNum = numerator ;
01486   cache._rearrangedDen = norm ;
01487   cache._isRearranged = kTRUE ;
01488 
01489   delete iter1 ;
01490   delete iter2 ;
01491   delete iterp ;
01492   delete itern ;
01493   
01494 }
01495 
01496 
01497 //_____________________________________________________________________________
01498 RooAbsReal* RooProdPdf::specializeRatio(RooFormulaVar& input, const char* targetRangeName) const
01499 {  
01500   RooRealIntegral* numint = (RooRealIntegral*) input.getParameter(0) ;
01501   RooRealIntegral* denint = (RooRealIntegral*) input.getParameter(1) ;
01502   
01503   RooAbsReal* numint_spec = specializeIntegral(*numint,targetRangeName) ;
01504   
01505   RooAbsReal* ret =  new RooFormulaVar(Form("ratio(%s,%s)",numint_spec->GetName(),denint->GetName()),"@0/@1",RooArgList(*numint_spec,*denint)) ;
01506   ret->addOwnedComponents(*numint_spec) ;
01507   
01508   return ret ;
01509 }
01510 
01511 
01512 
01513 //_____________________________________________________________________________
01514 RooAbsReal* RooProdPdf::specializeIntegral(RooAbsReal& input, const char* targetRangeName) const
01515 {
01516   if (input.InheritsFrom(RooRealIntegral::Class())) {
01517     
01518     // If input is integral, recreate integral but override integration range to be targetRangeName
01519     RooRealIntegral* orig = (RooRealIntegral*)&input ;
01520 //     cout << "creating integral: integrand =  " << orig->integrand().GetName() << " vars = " << orig->intVars() << " range = " << targetRangeName << endl ;
01521     return orig->integrand().createIntegral(orig->intVars(),targetRangeName) ;
01522     
01523   } else if (input.InheritsFrom(RooAddition::Class())) {
01524 
01525     // If input is sum of integrals, recreate integral from first component of set, but override integration range to be targetRangeName
01526     RooAddition* orig = (RooAddition*)&input ;
01527     RooRealIntegral* origInt = (RooRealIntegral*) orig->list1().first() ;
01528 //     cout << "creating integral from addition: integrand =  " << origInt->integrand().GetName() << " vars = " << origInt->intVars() << " range = " << targetRangeName << endl ;
01529     return origInt->integrand().createIntegral(origInt->intVars(),targetRangeName) ;
01530 
01531   } else {
01532 
01533 //     cout << "specializeIntegral: unknown input type " << input.IsA()->GetName() << "::" << input.GetName() << endl ;
01534   }
01535 
01536   return &input ;
01537 }
01538 
01539 
01540 //_____________________________________________________________________________
01541 void RooProdPdf::groupProductTerms(RooLinkedList& groupedTerms, RooArgSet& outerIntDeps, 
01542                                    const RooLinkedList& terms, const RooLinkedList& norms, 
01543                                    const RooLinkedList& imps, const RooLinkedList& ints, const RooLinkedList& /*cross*/) const
01544 {
01545   // Group product into terms that can be calculated independently
01546 
01547   // Start out with each term in its own group
01548   TIterator* tIter = terms.MakeIterator() ;
01549   RooArgSet* term ;
01550   while((term=(RooArgSet*)tIter->Next())) {
01551     RooLinkedList* group = new RooLinkedList ;
01552     group->Add(term) ;
01553     groupedTerms.Add(group) ;
01554   }
01555   delete tIter ;
01556 
01557   // Make list of imported dependents that occur in any term
01558   RooArgSet allImpDeps ;
01559   TIterator* iIter = imps.MakeIterator() ;
01560   RooArgSet *impDeps ;
01561   while((impDeps=(RooArgSet*)iIter->Next())) {
01562     allImpDeps.add(*impDeps,kFALSE) ;
01563   }
01564   delete iIter ;
01565 
01566   // Make list of integrated dependents that occur in any term
01567   RooArgSet allIntDeps ;
01568   iIter = ints.MakeIterator() ;
01569   RooArgSet *intDeps ;
01570   while((intDeps=(RooArgSet*)iIter->Next())) {
01571     allIntDeps.add(*intDeps,kFALSE) ;
01572   }
01573   delete iIter ;
01574   
01575   RooArgSet* tmp = (RooArgSet*) allIntDeps.selectCommon(allImpDeps) ;
01576   outerIntDeps.removeAll() ;
01577   outerIntDeps.add(*tmp) ;
01578   delete tmp ;
01579 
01580   // Now iteratively merge groups that should be (partially) integrated together
01581   TIterator* oidIter = outerIntDeps.createIterator() ;
01582   TIterator* glIter = groupedTerms.MakeIterator() ;
01583   RooAbsArg* outerIntDep ;
01584   while ((outerIntDep =(RooAbsArg*)oidIter->Next())) {
01585     
01586     // Collect groups that feature this dependent
01587     RooLinkedList* newGroup = 0 ;
01588 
01589     // Loop over groups
01590     RooLinkedList* group ;
01591     glIter->Reset() ;    
01592     Bool_t needMerge = kFALSE ;
01593     while((group=(RooLinkedList*)glIter->Next())) {
01594 
01595       // See if any term in this group depends in any ay on outerDepInt
01596       RooArgSet* term2 ;
01597       TIterator* tIter2 = group->MakeIterator() ;
01598       while((term2=(RooArgSet*)tIter2->Next())) {
01599 
01600         Int_t termIdx = terms.IndexOf(term2) ;
01601         RooArgSet* termNormDeps = (RooArgSet*) norms.At(termIdx) ;
01602         RooArgSet* termIntDeps = (RooArgSet*) ints.At(termIdx) ;
01603         RooArgSet* termImpDeps = (RooArgSet*) imps.At(termIdx) ;
01604 
01605         if (termNormDeps->contains(*outerIntDep) || 
01606             termIntDeps->contains(*outerIntDep) || 
01607             termImpDeps->contains(*outerIntDep)) {
01608           needMerge = kTRUE ;
01609         }
01610         
01611       }
01612 
01613       if (needMerge) {
01614         // Create composite group if not yet existing
01615         if (newGroup==0) {
01616           newGroup = new RooLinkedList ;
01617         }
01618         
01619         // Add terms of this group to new term      
01620         tIter2->Reset() ;
01621         while((term2=(RooArgSet*)tIter2->Next())) {
01622           newGroup->Add(term2) ;          
01623         }
01624 
01625         // Remove this group from list and delete it (but not its contents)
01626         groupedTerms.Remove(group) ;
01627         delete group ;
01628       }
01629       delete tIter2 ;
01630     }
01631     // If a new group has been created to merge terms dependent on current outerIntDep, add it to group list
01632     if (newGroup) {
01633       groupedTerms.Add(newGroup) ;
01634     }
01635 
01636   }
01637 
01638   delete glIter ;
01639   delete oidIter ;
01640 }
01641 
01642 
01643 
01644 //_____________________________________________________________________________
01645 std::vector<RooAbsReal*> RooProdPdf::processProductTerm(const RooArgSet* nset, const RooArgSet* iset, const char* isetRangeName,
01646                                                         const RooArgSet* term,const RooArgSet& termNSet, const RooArgSet& termISet,
01647                                                         Bool_t& isOwned, Bool_t forceWrap) const
01648 {
01649   // Calculate integrals of factorized product terms over observables iset while normalized
01650   // to observables in nset.
01651 
01652 //   cout << "   FOLKERT::RooProdPdf(" << GetName() <<") processProductTerm nset = " << (nset?*nset:RooArgSet()) << endl 
01653 //         << "   _normRange = " << _normRange << endl 
01654 //         << "   iset = " << (iset?*iset:RooArgSet()) << endl 
01655 //         << "   isetRangeName = " << (isetRangeName?isetRangeName:"<null>") << endl 
01656 //         << "   term = " << (term?*term:RooArgSet()) << endl 
01657 //         << "   termNSet = " << termNSet << endl 
01658 //         << "   termISet = " << termISet << endl 
01659 //         << "   isOwned = " << isOwned << endl 
01660 //         << "   forceWrap = " << forceWrap << endl ;
01661 
01662   vector<RooAbsReal*> ret(3) ; ret[0] = 0 ; ret[1] = 0 ; ret[2] = 0 ;
01663 
01664   // CASE I: factorizing term: term is integrated over all normalizing observables
01665   // -----------------------------------------------------------------------------
01666   // Check if all observbales of this term are integrated. If so the term cancels
01667   if (termNSet.getSize()>0 && termNSet.getSize()==termISet.getSize() && isetRangeName==0) {
01668 
01669     
01670 //     cout << "processProductTerm(" << GetName() << ") case I " << endl ;
01671 
01672     // Term factorizes    
01673     return ret ;
01674   }
01675   
01676   // CASE II: Dropped terms: if term is entirely unnormalized, it should be dropped
01677   // ------------------------------------------------------------------------------
01678   if (nset && termNSet.getSize()==0) {
01679 
01680 //     cout << "processProductTerm(" << GetName() << ") case II " << endl ;
01681     
01682     // Drop terms that are not asked to be normalized  
01683     return ret ;
01684   }
01685   
01686   if (iset && termISet.getSize()>0) {
01687     if (term->getSize()==1) {
01688       
01689       // CASE IIIa: Normalized and partially integrated single PDF term
01690       //---------------------------------------------------------------
01691 
01692       TIterator* pIter = term->createIterator() ;
01693       RooAbsPdf* pdf = (RooAbsPdf*) pIter->Next() ;
01694       delete pIter ;
01695       
01696       RooAbsReal* partInt = pdf->createIntegral(termISet,termNSet,isetRangeName) ;
01697       //partInt->setOperMode(operMode()) ;
01698       partInt->setStringAttribute("PROD_TERM_TYPE","IIIa") ;
01699 
01700       isOwned=kTRUE ;
01701 
01702 //       cout << "processProductTerm(" << GetName() << ") case IIIa func = " << partInt->GetName() << endl ;
01703 
01704       ret[0] = partInt ;
01705 
01706       // Split mode results 
01707       ret[1] = pdf->createIntegral(termISet,isetRangeName) ;
01708       ret[2] = pdf->createIntegral(termNSet,normRange()) ;      
01709 
01710       return ret ;
01711 
01712       
01713     } else {
01714       
01715       // CASE IIIb: Normalized and partially integrated composite PDF term
01716       //---------------------------------------------------------------
01717 
01718       // Use auxiliary class RooGenProdProj to calculate this term
01719       const char* name = makeRGPPName("GENPROJ_",*term,termISet,termNSet,isetRangeName) ;
01720       RooAbsReal* partInt = new RooGenProdProj(name,name,*term,termISet,termNSet,isetRangeName) ;
01721       partInt->setStringAttribute("PROD_TERM_TYPE","IIIb") ;
01722       //partInt->setOperMode(operMode()) ;
01723 
01724 //       cout << "processProductTerm(" << GetName() << ") case IIIb func = " << partInt->GetName() << endl ;
01725       
01726       isOwned=kTRUE ;
01727       ret[0] = partInt ;
01728       
01729       const char* name1 = makeRGPPName("PROD",*term,RooArgSet(),RooArgSet(),0) ;
01730 
01731       // WVE FIX THIS
01732       RooProduct* tmp_prod = new RooProduct(name1,name1,*term) ;
01733       
01734       ret[1] = tmp_prod->createIntegral(termISet,isetRangeName) ;
01735       ret[2] = tmp_prod->createIntegral(termNSet,normRange()) ;
01736 
01737       return ret ;
01738     }      
01739   }
01740   
01741   // CASE IVa: Normalized non-integrated composite PDF term
01742   // -------------------------------------------------------
01743   if (nset && nset->getSize()>0 && term->getSize()>1) {
01744     // Composite term needs normalized integration
01745 
01746     const char* name = makeRGPPName("GENPROJ_",*term,termISet,termNSet,isetRangeName) ;
01747     RooAbsReal* partInt = new RooGenProdProj(name,name,*term,termISet,termNSet,isetRangeName,normRange()) ;
01748     partInt->setStringAttribute("PROD_TERM_TYPE","IVa") ;
01749     //partInt->setOperMode(operMode()) ;
01750 
01751 //     cout << "processProductTerm(" << GetName() << ") case IVa func = " << partInt->GetName() << endl ;
01752 
01753     isOwned=kTRUE ;
01754     ret[0] = partInt ;
01755 
01756     const char* name1 = makeRGPPName("PROD",*term,RooArgSet(),RooArgSet(),0) ;
01757 
01758     // WVE FIX THIS
01759     RooProduct* tmp_prod = new RooProduct(name1,name1,*term) ;
01760 
01761     ret[1] = tmp_prod->createIntegral(termISet,isetRangeName) ;
01762     ret[2] = tmp_prod->createIntegral(termNSet,normRange()) ;
01763 
01764     return ret ;
01765   }
01766   
01767   // CASE IVb: Normalized, non-integrated single PDF term 
01768   // -----------------------------------------------------
01769   TIterator* pIter = term->createIterator() ;
01770   RooAbsPdf* pdf ;
01771   while((pdf=(RooAbsPdf*)pIter->Next())) {
01772 
01773     if (forceWrap) {
01774 
01775       // Construct representative name of normalization wrapper
01776       TString name(pdf->GetName()) ;
01777       name.Append("_NORM[") ;
01778       TIterator* nIter = termNSet.createIterator() ;
01779       RooAbsArg* arg ;
01780       Bool_t first(kTRUE) ;
01781       while((arg=(RooAbsArg*)nIter->Next())) {
01782         if (!first) {
01783           name.Append(",") ;
01784         } else {
01785           first=kFALSE ;
01786         }                  
01787         name.Append(arg->GetName()) ;
01788       }      
01789       if (normRange()) {
01790         name.Append("|") ;
01791         name.Append(normRange()) ;
01792       }
01793       name.Append("]") ;
01794       delete nIter ;
01795 
01796       
01797       RooAbsReal* partInt = new RooRealIntegral(name.Data(),name.Data(),*pdf,RooArgSet(),&termNSet) ;
01798       partInt->setStringAttribute("PROD_TERM_TYPE","IVb") ;
01799       isOwned=kTRUE ;      
01800 
01801 //       cout << "processProductTerm(" << GetName() << ") case IVb func = " << partInt->GetName() << endl ;
01802 
01803       delete pIter ;
01804       ret[0] = partInt ;
01805 
01806       ret[1] = pdf->createIntegral(RooArgSet()) ;
01807       ret[2] = pdf->createIntegral(termNSet,normRange()) ;
01808       
01809       return ret ;
01810 
01811 
01812     } else {
01813       isOwned=kFALSE ;
01814 
01815       delete pIter ;
01816 //       cout << "processProductTerm(" << GetName() << ") case IVb func = " << pdf->GetName() << endl ;
01817       pdf->setStringAttribute("PROD_TERM_TYPE","IVb") ;
01818       ret[0] = pdf ;
01819 
01820       ret[1] = pdf->createIntegral(RooArgSet()) ;
01821       ret[2] = termNSet.getSize()>0 ? pdf->createIntegral(termNSet,normRange()) : ((RooAbsReal*)RooFit::RooConst(1).clone("1")) ;
01822       return ret  ;
01823     }
01824   }
01825   delete pIter ;
01826 
01827   coutE(Eval) << "RooProdPdf::processProductTerm(" << GetName() << ") unidentified term!!!" << endl ;
01828   return ret ;
01829 }
01830 
01831 
01832 
01833 
01834 //_____________________________________________________________________________
01835 const char* RooProdPdf::makeRGPPName(const char* pfx, const RooArgSet& term, const RooArgSet& iset, 
01836                                      const RooArgSet& nset, const char* isetRangeName) const
01837 {
01838   // Make an appropriate automatic name for a RooGenProdProj object in getPartIntList() 
01839 
01840   static TString pname ;
01841   pname = pfx ;
01842   pname.Append("[") ;
01843 
01844   TIterator* pIter = term.createIterator() ;
01845   
01846   // Encode component names
01847   Bool_t first(kTRUE) ;
01848   RooAbsPdf* pdf ;
01849   while((pdf=(RooAbsPdf*)pIter->Next())) {
01850     if (first) {
01851       first = kFALSE ;
01852     } else {
01853       pname.Append("_X_") ;
01854     }
01855     pname.Append(pdf->GetName()) ;
01856   }
01857   delete pIter ;
01858   pname.Append("]") ;
01859 
01860   pname.Append(integralNameSuffix(iset,&nset,isetRangeName,kTRUE)) ;  
01861 
01862   return pname.Data() ;
01863 }
01864 
01865 
01866 
01867 //_____________________________________________________________________________
01868 Bool_t RooProdPdf::forceAnalyticalInt(const RooAbsArg& /*dep*/) const 
01869 {
01870   // Force RooRealIntegral to offer all observables for internal integration
01871   return kTRUE ;
01872 }
01873 
01874 
01875 
01876 //_____________________________________________________________________________
01877 Int_t RooProdPdf::getAnalyticalIntegralWN(RooArgSet& allVars, RooArgSet& analVars, 
01878                                           const RooArgSet* normSet, const char* rangeName) const 
01879 {
01880   // Determine which part (if any) of given integral can be performed analytically.
01881   // If any analytical integration is possible, return integration scenario code.
01882   //
01883   // RooProdPdf implements two strategies in implementing analytical integrals
01884   //
01885   // First, PDF components whose entire set of dependents are requested to be integrated
01886   // can be dropped from the product, as they will integrate out to 1 by construction
01887   //
01888   // Second, RooProdPdf queries each remaining component PDF for its analytical integration 
01889   // capability of the requested set ('allVars'). It finds the largest common set of variables 
01890   // that can be integrated by all remaining components. If such a set exists, it reconfirms that 
01891   // each component is capable of analytically integrating the common set, and combines the components 
01892   // individual integration codes into a single integration code valid for RooProdPdf.
01893 
01894   if (_forceNumInt) return 0 ;
01895 
01896   // Declare that we can analytically integrate all requested observables
01897   analVars.add(allVars) ;
01898 
01899   // Retrieve (or create) the required partial integral list
01900   Int_t code ;
01901   RooArgList *plist(0) ;
01902   RooLinkedList *nlist(0) ;
01903   getPartIntList(normSet,&allVars,plist,nlist,code,rangeName) ;
01904 //   cout << "RooProdPdf::getAIWN(" << GetName() << ") allVars = " << allVars << " rangeName = " << (rangeName?rangeName:"<none>") << " code = " << code << endl ;
01905   
01906   return code+1 ;
01907 }
01908 
01909 
01910 
01911 
01912 //_____________________________________________________________________________
01913 Double_t RooProdPdf::analyticalIntegralWN(Int_t code, const RooArgSet* normSet, const char* rangeName) const 
01914 {
01915   // Return analytical integral defined by given scenario code
01916 
01917   // No integration scenario
01918   if (code==0) {
01919     return getVal(normSet) ;
01920   }
01921 
01922   // WVE needs adaptation for rangename feature
01923 
01924   // Partial integration scenarios
01925   CacheElem* cache = (CacheElem*) _cacheMgr.getObjByIndex(code-1) ;
01926   
01927   RooArgList* partIntList(0) ;
01928   RooLinkedList* normList(0) ;
01929 
01930   // If cache has been sterilized, revive this slot
01931   if (cache==0) {
01932     RooArgSet* vars = getParameters(RooArgSet()) ;
01933     RooArgSet* nset = _cacheMgr.nameSet1ByIndex(code-1)->select(*vars) ;
01934     RooArgSet* iset = _cacheMgr.nameSet2ByIndex(code-1)->select(*vars) ;
01935 
01936     Int_t code2(-1) ;
01937     getPartIntList(nset,iset,partIntList,normList,code2,rangeName) ;
01938 
01939     delete vars ;
01940     delete nset ;
01941     delete iset ;
01942 
01943     // preceding call to getPartIntList guarantees non-null return
01944     // coverity[NULL_RETURNS]
01945     cache = (CacheElem*) _cacheMgr.getObj(nset,iset,&code2,RooNameReg::ptr(rangeName)) ;
01946 
01947 
01948   } else {
01949 
01950     partIntList = &cache->_partList ;
01951     normList = &cache->_normList ;
01952 
01953   }
01954 
01955 //   Double_t val = calculate(partIntList,normList) ;
01956   
01957   Double_t val = calculate(*cache,kTRUE) ;
01958 //   cout << "RPP::aIWN(" << GetName() << ") ,code = " << code-1 << ", value = " << val << endl ;
01959 
01960   return val ;
01961 }
01962 
01963 
01964 
01965 //_____________________________________________________________________________
01966 Bool_t RooProdPdf::checkObservables(const RooArgSet* /*nset*/) const 
01967 {
01968   // Obsolete
01969   return kFALSE ;
01970   
01971 }
01972 
01973 
01974 
01975 
01976 //_____________________________________________________________________________
01977 RooAbsPdf::ExtendMode RooProdPdf::extendMode() const
01978 {
01979   // If this product contains exactly one extendable p.d.f return the extension abilities of
01980   // that p.d.f, otherwise return CanNotBeExtended
01981   return (_extendedIndex>=0) ? ((RooAbsPdf*)_pdfList.at(_extendedIndex))->extendMode() : CanNotBeExtended ;
01982 }
01983 
01984 
01985 
01986 //_____________________________________________________________________________
01987 Double_t RooProdPdf::expectedEvents(const RooArgSet* nset) const 
01988 {
01989   // Return the expected number of events associated with the extentable input p.d.f
01990   // in the product. If there is no extendable term, return zero and issue and error
01991 
01992   if (_extendedIndex<0) {
01993     coutE(Generation) << "ERROR: Requesting expected number of events from a RooProdPdf that does not contain an extended p.d.f" << endl ;
01994   }
01995   assert(_extendedIndex>=0) ;
01996   return ((RooAbsPdf*)_pdfList.at(_extendedIndex))->expectedEvents(nset) ;
01997 }
01998 
01999 
02000 
02001 
02002 //_____________________________________________________________________________
02003 RooAbsGenContext* RooProdPdf::genContext(const RooArgSet &vars, const RooDataSet *prototype, 
02004                                          const RooArgSet* auxProto, Bool_t verbose) const 
02005 {
02006   // Return generator context optimized for generating events from product p.d.f.s
02007 
02008   if (_useDefaultGen) return RooAbsPdf::genContext(vars,prototype,auxProto,verbose) ;
02009   return new RooProdGenContext(*this,vars,prototype,auxProto,verbose) ;
02010 }
02011 
02012 
02013 
02014 //_____________________________________________________________________________
02015 Int_t RooProdPdf::getGenerator(const RooArgSet& directVars, RooArgSet &generateVars, Bool_t staticInitOK) const
02016 {
02017   // Query internal generation capabilities of component p.d.f.s and aggregate capabilities
02018   // into master configuration passed to the generator context
02019 
02020   if (!_useDefaultGen) return 0 ;
02021 
02022   // Find the subset directVars that only depend on a single PDF in the product
02023   RooArgSet directSafe ;
02024   TIterator* dIter = directVars.createIterator() ;
02025   RooAbsArg* arg ;
02026   while((arg=(RooAbsArg*)dIter->Next())) {
02027     if (isDirectGenSafe(*arg)) directSafe.add(*arg) ;
02028   }
02029   delete dIter ;
02030 
02031 
02032   // Now find direct integrator for relevant components ;
02033   _pdfIter->Reset() ;
02034   RooAbsPdf* pdf ;
02035   Int_t code[64], n(0) ;
02036   while((pdf=(RooAbsPdf*)_pdfIter->Next())) {
02037     RooArgSet pdfDirect ;
02038     code[n] = pdf->getGenerator(directSafe,pdfDirect,staticInitOK) ;
02039     if (code[n]!=0) {
02040       generateVars.add(pdfDirect) ;
02041     }
02042     n++ ;
02043   }
02044 
02045 
02046   if (generateVars.getSize()>0) {
02047     Int_t masterCode = _genCode.store(code,n) ;
02048     return masterCode+1 ;    
02049   } else {
02050     return 0 ;
02051   }
02052 }
02053 
02054 
02055 
02056 //_____________________________________________________________________________
02057 void RooProdPdf::initGenerator(Int_t code)
02058 {
02059   // Forward one-time initialization call to component generation initialization
02060   // methods.
02061 
02062   if (!_useDefaultGen) return ;
02063 
02064   const Int_t* codeList = _genCode.retrieve(code-1) ;
02065   _pdfIter->Reset() ;
02066   RooAbsPdf* pdf ;
02067   Int_t i(0) ;
02068   while((pdf=(RooAbsPdf*)_pdfIter->Next())) {
02069     if (codeList[i]!=0) {
02070       pdf->initGenerator(codeList[i]) ;
02071     }
02072     i++ ;
02073   }
02074 }
02075 
02076 
02077 
02078 //_____________________________________________________________________________
02079 void RooProdPdf::generateEvent(Int_t code)
02080 {  
02081   // Generate a single event with configuration specified by 'code'
02082   // Defer internal generation to components as encoded in the _genCode
02083   // registry for given generator code.
02084 
02085   if (!_useDefaultGen) return ;
02086 
02087   const Int_t* codeList = _genCode.retrieve(code-1) ;
02088   _pdfIter->Reset() ;
02089   RooAbsPdf* pdf ;
02090   Int_t i(0) ;
02091   while((pdf=(RooAbsPdf*)_pdfIter->Next())) {
02092     if (codeList[i]!=0) {
02093       pdf->generateEvent(codeList[i]) ;
02094     }
02095     i++ ;
02096   }
02097 
02098 }
02099 
02100 
02101 
02102 //_____________________________________________________________________________
02103 RooProdPdf::CacheElem::~CacheElem() 
02104 {
02105   // Destructor
02106   //_normList.Delete() ; //WVE THIS IS AN INTENTIAL LEAK -- MUST FIX LATER
02107   if (_rearrangedNum) delete _rearrangedNum ;
02108   if (_rearrangedDen) delete _rearrangedDen ;
02109 //   cout << "RooProdPdf::CacheElem dtor, this = " << this << endl ;
02110 }
02111 
02112 
02113 
02114 //_____________________________________________________________________________
02115 RooArgList RooProdPdf::CacheElem::containedArgs(Action) 
02116 {
02117   // Return RooAbsArg components contained in the cache
02118   RooArgList ret ;
02119   ret.add(_partList) ;
02120   ret.add(_numList) ;
02121   ret.add(_denList) ;
02122   if (_rearrangedNum) ret.add(*_rearrangedNum) ;
02123   if (_rearrangedDen) ret.add(*_rearrangedDen) ;
02124   return ret ;
02125 
02126 }
02127 
02128 
02129 
02130 //_____________________________________________________________________________
02131 void RooProdPdf::CacheElem::printCompactTreeHook(ostream& os, const char* indent, Int_t curElem, Int_t maxElem) 
02132 {
02133   // Hook function to print cache contents in tree printing of RooProdPdf
02134 
02135    if (curElem==0) {
02136      os << indent << "RooProdPdf begin partial integral cache" << endl ;
02137    }
02138 
02139    TIterator* iter = _partList.createIterator() ;
02140    RooAbsArg* arg ;
02141    TString indent2(indent) ;
02142    indent2 += Form("[%d] ",curElem) ;
02143    while((arg=(RooAbsArg*)iter->Next())) {      
02144      arg->printCompactTree(os,indent2) ;
02145    }
02146    delete iter ;
02147 
02148    if (curElem==maxElem) {
02149      os << indent << "RooProdPdf end partial integral cache" << endl ;
02150    }
02151 }
02152 
02153 
02154 
02155 //_____________________________________________________________________________
02156 Bool_t RooProdPdf::isDirectGenSafe(const RooAbsArg& arg) const 
02157 {
02158   // Forward determination of safety of internal generator code to
02159   // component p.d.f that would generate the given observable
02160 
02161   // Only override base class behaviour if default generator method is enabled
02162   if (!_useDefaultGen) return RooAbsPdf::isDirectGenSafe(arg) ;
02163 
02164   // Argument may appear in only one PDF component
02165   _pdfIter->Reset() ;
02166   RooAbsPdf* pdf, *thePdf(0) ;  
02167   while((pdf=(RooAbsPdf*)_pdfIter->Next())) {
02168 
02169     if (pdf->dependsOn(arg)) {
02170       // Found PDF depending on arg
02171 
02172       // If multiple PDFs depend on arg directGen is not safe
02173       if (thePdf) return kFALSE ;
02174 
02175       thePdf = pdf ;
02176     }
02177   }
02178   // Forward call to relevant component PDF
02179   return thePdf?(thePdf->isDirectGenSafe(arg)):kFALSE ;
02180 }
02181 
02182 
02183 
02184 //_____________________________________________________________________________
02185 RooArgSet* RooProdPdf::findPdfNSet(RooAbsPdf& pdf) const 
02186 {
02187   // Look up user specified normalization set for given input PDF component
02188 
02189   Int_t idx = _pdfList.index(&pdf) ;
02190   if (idx<0) return 0 ;
02191   return (RooArgSet*) _pdfNSetList.At(idx) ;
02192 }
02193 
02194 
02195 
02196 //_____________________________________________________________________________
02197 RooArgSet* RooProdPdf::getConstraints(const RooArgSet& observables, RooArgSet& constrainedParams, Bool_t stripDisconnected) const
02198 {
02199   // Return all parameter constraint p.d.f.s on parameters listed in constrainedParams
02200   // The observables set is required to distinguish unambiguously p.d.f in terms 
02201   // of observables and parameters, which are not constraints, and p.d.fs in terms
02202   // of parameters only, which can serve as constraints p.d.f.s
02203 
02204   RooArgSet constraints ;
02205   RooArgSet pdfParams, conParams ;
02206 
02207   // Loop over p.d.f. components
02208   TIterator* piter = _pdfList.createIterator() ;
02209   RooAbsPdf* pdf ;
02210   while((pdf=(RooAbsPdf*)piter->Next())) {
02211     // A constraint term is a p.d.f that does not depend on any of the listed observables
02212     // but does depends on any of the parameters that should be constrained
02213     if (!pdf->dependsOnValue(observables) && pdf->dependsOnValue(constrainedParams)) {
02214       constraints.add(*pdf) ;
02215       RooArgSet* tmp = pdf->getParameters(observables) ;
02216       conParams.add(*tmp,kTRUE) ;
02217       delete tmp ;      
02218     } else {
02219       RooArgSet* tmp = pdf->getParameters(observables) ;
02220       pdfParams.add(*tmp,kTRUE) ;
02221       delete tmp ;
02222     }
02223   }
02224 
02225   // Strip any constraints that are completely decoupled from the other product terms
02226   RooArgSet* finalConstraints = new RooArgSet("constraints") ;
02227   TIterator* citer = constraints.createIterator() ;
02228   while((pdf=(RooAbsPdf*)citer->Next())) {
02229     if (pdf->dependsOnValue(pdfParams) || !stripDisconnected) {
02230       finalConstraints->add(*pdf) ;
02231     } else {
02232       coutI(Minimization) << "RooProdPdf::getConstraints(" << GetName() << ") omitting term " << pdf->GetName() 
02233                           << " as constraint term as it does not share any parameters with the other pdfs in product. "
02234                           << "To force inclusion in likelihood, add an explicit Constrain() argument for the target parameter" << endl ;
02235     }
02236   }
02237   delete citer ;
02238   delete piter ;
02239   
02240   // Now remove from constrainedParams all parameters that occur exclusively in constraint term and not in regular pdf term
02241 
02242   RooArgSet* cexl = (RooArgSet*) conParams.selectCommon(constrainedParams) ;
02243   cexl->remove(pdfParams,kTRUE,kTRUE) ;
02244   constrainedParams.remove(*cexl,kTRUE,kTRUE) ;
02245   delete cexl ;
02246 
02247   return finalConstraints ;
02248 }
02249 
02250 
02251 
02252 
02253 //_____________________________________________________________________________
02254 void RooProdPdf::getParametersHook(const RooArgSet* nset, RooArgSet* params, Bool_t stripDisconnected) const 
02255 {
02256   if (!stripDisconnected) return ;
02257   if (!nset || nset->getSize()==0) return ;
02258 
02259   // Get/create appropriate term list for this normalization set
02260   RooArgList *plist(0) ;
02261   RooLinkedList *nlist(0) ;
02262   Int_t code ;
02263   getPartIntList(nset,0,plist,nlist,code) ;
02264 
02265   // Strip any terms from params that do not depend on any term
02266   TIterator* titer = plist->createIterator() ;
02267   TIterator* piter = params->createIterator() ;
02268   RooAbsReal* term, *param ;
02269   RooArgSet tostrip ;
02270   while((param=(RooAbsReal*)piter->Next())) {
02271     Bool_t anyDep(kFALSE) ;
02272     titer->Reset() ;
02273     while((term=(RooAbsReal*)titer->Next())) {    
02274       if (term->dependsOnValue(*param)) {
02275         anyDep=kTRUE ;
02276       }
02277     }
02278     if (!anyDep) {
02279       tostrip.add(*param) ;
02280     }
02281   }
02282   delete piter ;
02283   delete titer ;
02284 
02285   if (tostrip.getSize()>0) {
02286     params->remove(tostrip,kTRUE,kTRUE);
02287   }
02288  
02289 }
02290 
02291 
02292 
02293 //_____________________________________________________________________________
02294 void RooProdPdf::selectNormalizationRange(const char* rangeName, Bool_t force) 
02295 {
02296   // Interface function used by test statistics to freeze choice of range
02297   // for interpretation of conditional product terms
02298 
02299   if (!force && _refRangeName) {
02300     return ;
02301   }
02302 
02303   fixRefRange(rangeName) ;
02304 }
02305 
02306 
02307 
02308 
02309 //_____________________________________________________________________________
02310 void RooProdPdf::fixRefRange(const char* rangeName)
02311 {
02312   _refRangeName = (TNamed*)RooNameReg::ptr(rangeName) ;
02313 }
02314 
02315 
02316 
02317 //_____________________________________________________________________________
02318 std::list<Double_t>* RooProdPdf::plotSamplingHint(RooAbsRealLValue& obs, Double_t xlo, Double_t xhi) const 
02319 {
02320   // Forward the plot sampling hint from the p.d.f. that defines the observable obs  
02321   _pdfIter->Reset() ;
02322   RooAbsPdf* pdf ;
02323   while((pdf=(RooAbsPdf*)_pdfIter->Next())) {
02324     list<Double_t>* hint = pdf->plotSamplingHint(obs,xlo,xhi) ;      
02325     if (hint) {
02326       return hint ;
02327     }
02328   }
02329   
02330   return 0 ;
02331 }
02332 
02333 
02334 
02335 //_____________________________________________________________________________
02336 void RooProdPdf::printMetaArgs(ostream& os) const 
02337 {
02338   // Customized printing of arguments of a RooProdPdf to more intuitively reflect the contents of the
02339   // product operator construction
02340 
02341   TIterator* niter = _pdfNSetList.MakeIterator() ;
02342   for (int i=0 ; i<_pdfList.getSize() ; i++) {
02343     if (i>0) os << " * " ;
02344     RooArgSet* ncset = (RooArgSet*) niter->Next() ;
02345     os << _pdfList.at(i)->GetName() ;
02346     if (ncset->getSize()>0) {
02347       if (string("nset")==ncset->GetName()) {
02348         os << *ncset  ;
02349       } else {
02350         os << "|" ;
02351         TIterator* nciter = ncset->createIterator() ;
02352         RooAbsArg* arg ;
02353         Bool_t first(kTRUE) ;
02354         while((arg=(RooAbsArg*)nciter->Next())) {
02355           if (!first) {
02356             os << "," ;
02357           } else {
02358             first = kFALSE ;
02359           }       
02360           os << arg->GetName() ;          
02361         }
02362       }
02363     }
02364   }
02365   os << " " ;    
02366   delete niter ;
02367 }

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