/*****************************************************************************
 * Project: RooFit                                                           *
 * Package: RooFitCore                                                       *
 * @(#)root/roofitcore:$Id$
 * Authors:                                                                  *
 *   WV, Wouter Verkerke, UC Santa Barbara, verkerke@slac.stanford.edu       *
 *   DK, David Kirkby,    UC Irvine,         dkirkby@uci.edu                 *
 *                                                                           *
 * Copyright (c) 2000-2005, Regents of the University of California          *
 *                          and Stanford University. All rights reserved.    *
 *                                                                           *
 * Redistribution and use in source and binary forms,                        *
 * with or without modification, are permitted according to the terms        *
 * listed in LICENSE (http://roofit.sourceforge.net/license.txt)             *
 *****************************************************************************/

//////////////////////////////////////////////////////////////////////////////
//
// BEGIN_HTML
//
// RooGenProdProj is an auxiliary class for RooProdPdf that calculates
// a general normalized projection of a product of non-factorizing PDFs, e.g.
//
//            Int ( P1 * P2 * ....) dx
//  P_x_xy = -------------------------------
//            Int (P1 * P2 * ... ) dx dy
//
// Partial integrals that factorize that can be calculated are calculated
// analytically. Remaining non-factorizing observables are integrated numerically.
// END_HTML
//


#include "RooFit.h"

#include "Riostream.h"
#include "Riostream.h"
#include <math.h>

#include "RooGenProdProj.h"
#include "RooAbsReal.h"
#include "RooAbsPdf.h"
#include "RooErrorHandler.h"
#include "RooProduct.h"

using namespace std;

ClassImp(RooGenProdProj)
;


//_____________________________________________________________________________
RooGenProdProj::RooGenProdProj() :
  _compSetOwnedN(0), 
  _compSetOwnedD(0),
  _haveD(kFALSE)
{
  // Default constructor
}


//_____________________________________________________________________________
RooGenProdProj::RooGenProdProj(const char *name, const char *title, const RooArgSet& _prodSet, const RooArgSet& _intSet, 
			       const RooArgSet& _normSet, const char* isetRangeName, const char* normRangeName, Bool_t doFactorize) :
  RooAbsReal(name, title),
  _compSetOwnedN(0), 
  _compSetOwnedD(0),
  _compSetN("compSetN","Set of integral components owned by numerator",this,kFALSE),
  _compSetD("compSetD","Set of integral components owned by denominator",this,kFALSE),
  _intList("intList","List of integrals",this,kTRUE),
  _haveD(kFALSE)
{
  // Constructor for a normalization projection of the product of p.d.f.s _prodSet
  // integrated over _intSet in range isetRangeName while normalized over _normSet

  // Set expensive object cache to that of first item in prodSet
  setExpensiveObjectCache(_prodSet.first()->expensiveObjectCache()) ;

  // Create owners of components created in ctor
  _compSetOwnedN = new RooArgSet ;
  _compSetOwnedD = new RooArgSet ;

  RooAbsReal* numerator = makeIntegral("numerator",_prodSet,_intSet,*_compSetOwnedN,isetRangeName,doFactorize) ;
  RooAbsReal* denominator = makeIntegral("denominator",_prodSet,_normSet,*_compSetOwnedD,normRangeName,doFactorize) ;

//   cout << "RooGenProdPdf::ctor(" << GetName() << ") numerator = " << numerator->GetName() << endl ;
//   numerator->printComponentTree() ;
//   cout << "RooGenProdPdf::ctor(" << GetName() << ") denominator = " << denominator->GetName() << endl ;
//   denominator->printComponentTree() ;

  // Copy all components in (non-owning) set proxy
  _compSetN.add(*_compSetOwnedN) ;
  _compSetD.add(*_compSetOwnedD) ;
  
  _intList.add(*numerator) ;
  if (denominator) {
    _intList.add(*denominator) ;
    _haveD = kTRUE ;
  }
}



//_____________________________________________________________________________
RooGenProdProj::RooGenProdProj(const RooGenProdProj& other, const char* name) :
  RooAbsReal(other, name), 
  _compSetOwnedN(0), 
  _compSetOwnedD(0),
  _compSetN("compSetN","Set of integral components owned by numerator",this),
  _compSetD("compSetD","Set of integral components owned by denominator",this),
  _intList("intList","List of integrals",this)
{
  // Copy constructor

  // Explicitly remove all server links at this point
  TIterator* iter = serverIterator() ;
  RooAbsArg* server ;
  while((server=(RooAbsArg*)iter->Next())) {
    removeServer(*server,kTRUE) ;
  }
  delete iter ;

  // Copy constructor
  _compSetOwnedN = (RooArgSet*) other._compSetN.snapshot() ;
  _compSetN.add(*_compSetOwnedN) ;

  _compSetOwnedD = (RooArgSet*) other._compSetD.snapshot() ;
  _compSetD.add(*_compSetOwnedD) ;

  RooAbsArg* arg ;
  TIterator* nIter = _compSetOwnedN->createIterator() ;  
  while((arg=(RooAbsArg*)nIter->Next())) {
//     cout << "ownedN elem " << arg->GetName() << "(" << arg << ")" << endl ;
    arg->setOperMode(_operMode) ;
  }
  delete nIter ;
  TIterator* dIter = _compSetOwnedD->createIterator() ;
  while((arg=(RooAbsArg*)dIter->Next())) {
//     cout << "ownedD elem " << arg->GetName() << "(" << arg << ")" << endl ;
    arg->setOperMode(_operMode) ;
  }
  delete dIter ;

  // Fill _intList
  _haveD = other._haveD ;
  _intList.add(*_compSetN.find(other._intList.at(0)->GetName())) ;
  if (other._haveD) {
    _intList.add(*_compSetD.find(other._intList.at(1)->GetName())) ;
  }
}



//_____________________________________________________________________________
RooGenProdProj::~RooGenProdProj()
{
  // Destructor

  if (_compSetOwnedN) delete _compSetOwnedN ;
  if (_compSetOwnedD) delete _compSetOwnedD ;
}



//_____________________________________________________________________________
RooAbsReal* RooGenProdProj::makeIntegral(const char* name, const RooArgSet& compSet, const RooArgSet& intSet, 
					 RooArgSet& saveSet, const char* isetRangeName, Bool_t doFactorize) 
{
  // Utility function to create integral over observables intSet in range isetRangeName over product of p.d.fs in compSet.
  // The integration is factorized into components as much as possible and done analytically as far as possible.
  // All component object needed to represent product integral are added as owned members to saveSet.
  // The return value is a RooAbsReal object representing the requested integral

  RooArgSet anaIntSet, numIntSet ;

  // First determine subset of observables in intSet that are factorizable
  TIterator* compIter = compSet.createIterator() ;
  TIterator* intIter = intSet.createIterator() ;
  RooAbsPdf* pdf ;
  RooAbsArg* arg ;
  while((arg=(RooAbsArg*)intIter->Next())) {
    Int_t count(0) ;
    compIter->Reset() ;
    while((pdf=(RooAbsPdf*)compIter->Next())) {
      if (pdf->dependsOn(*arg)) count++ ;
    }

    if (count==0) {
    } else if (count==1) {
      anaIntSet.add(*arg) ;
    } else {
    }    
  }

  // Determine which of the factorizable integrals can be done analytically
  RooArgSet prodSet ;
  numIntSet.add(intSet) ;
  
  compIter->Reset() ;
  while((pdf=(RooAbsPdf*)compIter->Next())) {
    if (doFactorize && pdf->dependsOn(anaIntSet)) {
      RooArgSet anaSet ;
      Int_t code = pdf->getAnalyticalIntegralWN(anaIntSet,anaSet,0,isetRangeName) ;
      if (code!=0) {
	// Analytical integral, create integral object
	RooAbsReal* pai = pdf->createIntegral(anaSet,isetRangeName) ;
	pai->setOperMode(_operMode) ;
	
	// Add to integral to product
	prodSet.add(*pai) ;
	
	// Remove analytically integratable observables from numeric integration list
	numIntSet.remove(anaSet) ;
	
	// Declare ownership of integral
	saveSet.addOwned(*pai) ;
      } else {
	// Analytic integration of factorizable observable not possible, add straight pdf to product
	prodSet.add(*pdf) ;
      }      
    } else {
      // Non-factorizable observables, add straight pdf to product
      prodSet.add(*pdf) ;
    }
  }

  //cout << "RooGenProdProj::makeIntegral(" << GetName() << ") prodset = " << prodSet << endl ;

  // Create product of (partial) analytical integrals
  TString prodName ;
  if (isetRangeName) {
    prodName = Form("%s_%s_Range[%s]",GetName(),name,isetRangeName) ;
  } else {
    prodName = Form("%s_%s",GetName(),name) ;
  }
  RooProduct* prod = new RooProduct(prodName,"product",prodSet) ;
  prod->setExpensiveObjectCache(expensiveObjectCache()) ;
  prod->setOperMode(_operMode) ;

  // Declare owndership of product
  saveSet.addOwned(*prod) ;

  // Create integral performing remaining numeric integration over (partial) analytic product
  RooAbsReal* ret = prod->createIntegral(numIntSet,isetRangeName) ;
//   cout << "verbose print of integral object" << endl ;
//   ret->Print("v") ;
  ret->setOperMode(_operMode) ;
  saveSet.addOwned(*ret) ;

  delete compIter ;
  delete intIter ;

  // Caller owners returned master integral object
  return ret ;
}



//_____________________________________________________________________________
Double_t RooGenProdProj::evaluate() const 
{  
  // Calculate and return value of normalization projection

  Double_t nom = ((RooAbsReal*)_intList.at(0))->getVal() ;

  if (!_haveD) return nom ;

  Double_t den = ((RooAbsReal*)_intList.at(1))->getVal() ;

  //cout << "RooGenProdProj::eval(" << GetName() << ") nom = " << nom << " den = " << den << endl ;

  return nom / den ;
}



//_____________________________________________________________________________
void RooGenProdProj::operModeHook() 
{
  // Intercept cache mode operation changes and propagate them to the components

  // WVE use cache manager here!

  RooAbsArg* arg ;
  TIterator* nIter = _compSetOwnedN->createIterator() ;  
  while((arg=(RooAbsArg*)nIter->Next())) {
    arg->setOperMode(_operMode) ;
  }
  delete nIter ;

  TIterator* dIter = _compSetOwnedD->createIterator() ;
  while((arg=(RooAbsArg*)dIter->Next())) {
    arg->setOperMode(_operMode) ;
  }
  delete dIter ;

  _intList.at(0)->setOperMode(_operMode) ;
  if (_haveD) _intList.at(1)->setOperMode(Auto) ; // Denominator always stays in Auto mode (normalization integral)
}







 RooGenProdProj.cxx:1
 RooGenProdProj.cxx:2
 RooGenProdProj.cxx:3
 RooGenProdProj.cxx:4
 RooGenProdProj.cxx:5
 RooGenProdProj.cxx:6
 RooGenProdProj.cxx:7
 RooGenProdProj.cxx:8
 RooGenProdProj.cxx:9
 RooGenProdProj.cxx:10
 RooGenProdProj.cxx:11
 RooGenProdProj.cxx:12
 RooGenProdProj.cxx:13
 RooGenProdProj.cxx:14
 RooGenProdProj.cxx:15
 RooGenProdProj.cxx:16
 RooGenProdProj.cxx:17
 RooGenProdProj.cxx:18
 RooGenProdProj.cxx:19
 RooGenProdProj.cxx:20
 RooGenProdProj.cxx:21
 RooGenProdProj.cxx:22
 RooGenProdProj.cxx:23
 RooGenProdProj.cxx:24
 RooGenProdProj.cxx:25
 RooGenProdProj.cxx:26
 RooGenProdProj.cxx:27
 RooGenProdProj.cxx:28
 RooGenProdProj.cxx:29
 RooGenProdProj.cxx:30
 RooGenProdProj.cxx:31
 RooGenProdProj.cxx:32
 RooGenProdProj.cxx:33
 RooGenProdProj.cxx:34
 RooGenProdProj.cxx:35
 RooGenProdProj.cxx:36
 RooGenProdProj.cxx:37
 RooGenProdProj.cxx:38
 RooGenProdProj.cxx:39
 RooGenProdProj.cxx:40
 RooGenProdProj.cxx:41
 RooGenProdProj.cxx:42
 RooGenProdProj.cxx:43
 RooGenProdProj.cxx:44
 RooGenProdProj.cxx:45
 RooGenProdProj.cxx:46
 RooGenProdProj.cxx:47
 RooGenProdProj.cxx:48
 RooGenProdProj.cxx:49
 RooGenProdProj.cxx:50
 RooGenProdProj.cxx:51
 RooGenProdProj.cxx:52
 RooGenProdProj.cxx:53
 RooGenProdProj.cxx:54
 RooGenProdProj.cxx:55
 RooGenProdProj.cxx:56
 RooGenProdProj.cxx:57
 RooGenProdProj.cxx:58
 RooGenProdProj.cxx:59
 RooGenProdProj.cxx:60
 RooGenProdProj.cxx:61
 RooGenProdProj.cxx:62
 RooGenProdProj.cxx:63
 RooGenProdProj.cxx:64
 RooGenProdProj.cxx:65
 RooGenProdProj.cxx:66
 RooGenProdProj.cxx:67
 RooGenProdProj.cxx:68
 RooGenProdProj.cxx:69
 RooGenProdProj.cxx:70
 RooGenProdProj.cxx:71
 RooGenProdProj.cxx:72
 RooGenProdProj.cxx:73
 RooGenProdProj.cxx:74
 RooGenProdProj.cxx:75
 RooGenProdProj.cxx:76
 RooGenProdProj.cxx:77
 RooGenProdProj.cxx:78
 RooGenProdProj.cxx:79
 RooGenProdProj.cxx:80
 RooGenProdProj.cxx:81
 RooGenProdProj.cxx:82
 RooGenProdProj.cxx:83
 RooGenProdProj.cxx:84
 RooGenProdProj.cxx:85
 RooGenProdProj.cxx:86
 RooGenProdProj.cxx:87
 RooGenProdProj.cxx:88
 RooGenProdProj.cxx:89
 RooGenProdProj.cxx:90
 RooGenProdProj.cxx:91
 RooGenProdProj.cxx:92
 RooGenProdProj.cxx:93
 RooGenProdProj.cxx:94
 RooGenProdProj.cxx:95
 RooGenProdProj.cxx:96
 RooGenProdProj.cxx:97
 RooGenProdProj.cxx:98
 RooGenProdProj.cxx:99
 RooGenProdProj.cxx:100
 RooGenProdProj.cxx:101
 RooGenProdProj.cxx:102
 RooGenProdProj.cxx:103
 RooGenProdProj.cxx:104
 RooGenProdProj.cxx:105
 RooGenProdProj.cxx:106
 RooGenProdProj.cxx:107
 RooGenProdProj.cxx:108
 RooGenProdProj.cxx:109
 RooGenProdProj.cxx:110
 RooGenProdProj.cxx:111
 RooGenProdProj.cxx:112
 RooGenProdProj.cxx:113
 RooGenProdProj.cxx:114
 RooGenProdProj.cxx:115
 RooGenProdProj.cxx:116
 RooGenProdProj.cxx:117
 RooGenProdProj.cxx:118
 RooGenProdProj.cxx:119
 RooGenProdProj.cxx:120
 RooGenProdProj.cxx:121
 RooGenProdProj.cxx:122
 RooGenProdProj.cxx:123
 RooGenProdProj.cxx:124
 RooGenProdProj.cxx:125
 RooGenProdProj.cxx:126
 RooGenProdProj.cxx:127
 RooGenProdProj.cxx:128
 RooGenProdProj.cxx:129
 RooGenProdProj.cxx:130
 RooGenProdProj.cxx:131
 RooGenProdProj.cxx:132
 RooGenProdProj.cxx:133
 RooGenProdProj.cxx:134
 RooGenProdProj.cxx:135
 RooGenProdProj.cxx:136
 RooGenProdProj.cxx:137
 RooGenProdProj.cxx:138
 RooGenProdProj.cxx:139
 RooGenProdProj.cxx:140
 RooGenProdProj.cxx:141
 RooGenProdProj.cxx:142
 RooGenProdProj.cxx:143
 RooGenProdProj.cxx:144
 RooGenProdProj.cxx:145
 RooGenProdProj.cxx:146
 RooGenProdProj.cxx:147
 RooGenProdProj.cxx:148
 RooGenProdProj.cxx:149
 RooGenProdProj.cxx:150
 RooGenProdProj.cxx:151
 RooGenProdProj.cxx:152
 RooGenProdProj.cxx:153
 RooGenProdProj.cxx:154
 RooGenProdProj.cxx:155
 RooGenProdProj.cxx:156
 RooGenProdProj.cxx:157
 RooGenProdProj.cxx:158
 RooGenProdProj.cxx:159
 RooGenProdProj.cxx:160
 RooGenProdProj.cxx:161
 RooGenProdProj.cxx:162
 RooGenProdProj.cxx:163
 RooGenProdProj.cxx:164
 RooGenProdProj.cxx:165
 RooGenProdProj.cxx:166
 RooGenProdProj.cxx:167
 RooGenProdProj.cxx:168
 RooGenProdProj.cxx:169
 RooGenProdProj.cxx:170
 RooGenProdProj.cxx:171
 RooGenProdProj.cxx:172
 RooGenProdProj.cxx:173
 RooGenProdProj.cxx:174
 RooGenProdProj.cxx:175
 RooGenProdProj.cxx:176
 RooGenProdProj.cxx:177
 RooGenProdProj.cxx:178
 RooGenProdProj.cxx:179
 RooGenProdProj.cxx:180
 RooGenProdProj.cxx:181
 RooGenProdProj.cxx:182
 RooGenProdProj.cxx:183
 RooGenProdProj.cxx:184
 RooGenProdProj.cxx:185
 RooGenProdProj.cxx:186
 RooGenProdProj.cxx:187
 RooGenProdProj.cxx:188
 RooGenProdProj.cxx:189
 RooGenProdProj.cxx:190
 RooGenProdProj.cxx:191
 RooGenProdProj.cxx:192
 RooGenProdProj.cxx:193
 RooGenProdProj.cxx:194
 RooGenProdProj.cxx:195
 RooGenProdProj.cxx:196
 RooGenProdProj.cxx:197
 RooGenProdProj.cxx:198
 RooGenProdProj.cxx:199
 RooGenProdProj.cxx:200
 RooGenProdProj.cxx:201
 RooGenProdProj.cxx:202
 RooGenProdProj.cxx:203
 RooGenProdProj.cxx:204
 RooGenProdProj.cxx:205
 RooGenProdProj.cxx:206
 RooGenProdProj.cxx:207
 RooGenProdProj.cxx:208
 RooGenProdProj.cxx:209
 RooGenProdProj.cxx:210
 RooGenProdProj.cxx:211
 RooGenProdProj.cxx:212
 RooGenProdProj.cxx:213
 RooGenProdProj.cxx:214
 RooGenProdProj.cxx:215
 RooGenProdProj.cxx:216
 RooGenProdProj.cxx:217
 RooGenProdProj.cxx:218
 RooGenProdProj.cxx:219
 RooGenProdProj.cxx:220
 RooGenProdProj.cxx:221
 RooGenProdProj.cxx:222
 RooGenProdProj.cxx:223
 RooGenProdProj.cxx:224
 RooGenProdProj.cxx:225
 RooGenProdProj.cxx:226
 RooGenProdProj.cxx:227
 RooGenProdProj.cxx:228
 RooGenProdProj.cxx:229
 RooGenProdProj.cxx:230
 RooGenProdProj.cxx:231
 RooGenProdProj.cxx:232
 RooGenProdProj.cxx:233
 RooGenProdProj.cxx:234
 RooGenProdProj.cxx:235
 RooGenProdProj.cxx:236
 RooGenProdProj.cxx:237
 RooGenProdProj.cxx:238
 RooGenProdProj.cxx:239
 RooGenProdProj.cxx:240
 RooGenProdProj.cxx:241
 RooGenProdProj.cxx:242
 RooGenProdProj.cxx:243
 RooGenProdProj.cxx:244
 RooGenProdProj.cxx:245
 RooGenProdProj.cxx:246
 RooGenProdProj.cxx:247
 RooGenProdProj.cxx:248
 RooGenProdProj.cxx:249
 RooGenProdProj.cxx:250
 RooGenProdProj.cxx:251
 RooGenProdProj.cxx:252
 RooGenProdProj.cxx:253
 RooGenProdProj.cxx:254
 RooGenProdProj.cxx:255
 RooGenProdProj.cxx:256
 RooGenProdProj.cxx:257
 RooGenProdProj.cxx:258
 RooGenProdProj.cxx:259
 RooGenProdProj.cxx:260
 RooGenProdProj.cxx:261
 RooGenProdProj.cxx:262
 RooGenProdProj.cxx:263
 RooGenProdProj.cxx:264
 RooGenProdProj.cxx:265
 RooGenProdProj.cxx:266
 RooGenProdProj.cxx:267
 RooGenProdProj.cxx:268
 RooGenProdProj.cxx:269
 RooGenProdProj.cxx:270
 RooGenProdProj.cxx:271
 RooGenProdProj.cxx:272
 RooGenProdProj.cxx:273
 RooGenProdProj.cxx:274
 RooGenProdProj.cxx:275
 RooGenProdProj.cxx:276
 RooGenProdProj.cxx:277
 RooGenProdProj.cxx:278
 RooGenProdProj.cxx:279
 RooGenProdProj.cxx:280
 RooGenProdProj.cxx:281
 RooGenProdProj.cxx:282
 RooGenProdProj.cxx:283
 RooGenProdProj.cxx:284
 RooGenProdProj.cxx:285
 RooGenProdProj.cxx:286
 RooGenProdProj.cxx:287
 RooGenProdProj.cxx:288
 RooGenProdProj.cxx:289
 RooGenProdProj.cxx:290
 RooGenProdProj.cxx:291
 RooGenProdProj.cxx:292
 RooGenProdProj.cxx:293
 RooGenProdProj.cxx:294
 RooGenProdProj.cxx:295
 RooGenProdProj.cxx:296
 RooGenProdProj.cxx:297
 RooGenProdProj.cxx:298
 RooGenProdProj.cxx:299
 RooGenProdProj.cxx:300
 RooGenProdProj.cxx:301
 RooGenProdProj.cxx:302
 RooGenProdProj.cxx:303
 RooGenProdProj.cxx:304
 RooGenProdProj.cxx:305
 RooGenProdProj.cxx:306