/*****************************************************************************
 * 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 
// RooAddGenContext is an efficient implementation of the
// generator context specific for RooAddPdf PDFs. The strategy
// of RooAddGenContext is to defer generation of each component
// to a dedicated generator context for that component and to
// randomly choose one of those context to generate an event,
// with a probability proportional to its associated coefficient
// END_HTML
//


#include "RooFit.h"

#include "Riostream.h"


#include "RooMsgService.h"
#include "RooAddGenContext.h"
#include "RooAddGenContext.h"
#include "RooAddPdf.h"
#include "RooDataSet.h"
#include "RooRandom.h"
#include "RooAddModel.h"

using namespace std;

ClassImp(RooAddGenContext)
;
  

//_____________________________________________________________________________
RooAddGenContext::RooAddGenContext(const RooAddPdf &model, const RooArgSet &vars, 
				   const RooDataSet *prototype, const RooArgSet* auxProto,
				   Bool_t verbose) :
  RooAbsGenContext(model,vars,prototype,auxProto,verbose), _isModel(kFALSE)
{
  // Constructor

  cxcoutI(Generation) << "RooAddGenContext::ctor() setting up event special generator context for sum p.d.f. " << model.GetName() 
			<< " for generation of observable(s) " << vars ;
  if (prototype) ccxcoutI(Generation) << " with prototype data for " << *prototype->get() ;
  if (auxProto && auxProto->getSize()>0)  ccxcoutI(Generation) << " with auxiliary prototypes " << *auxProto ;
  ccxcoutI(Generation) << endl ;

  // Constructor. Build an array of generator contexts for each product component PDF
  _pdfSet = (RooArgSet*) RooArgSet(model).snapshot(kTRUE) ;
  _pdf = (RooAddPdf*) _pdfSet->find(model.GetName()) ;
  _pdf->setOperMode(RooAbsArg::ADirty,kTRUE) ;

  // Fix normalization set of this RooAddPdf
  if (prototype) 
    {
      RooArgSet coefNSet(vars) ;
      coefNSet.add(*prototype->get()) ;
      _pdf->fixAddCoefNormalization(coefNSet,kFALSE) ;
    }

  model._pdfIter->Reset() ;
  RooAbsPdf* pdf ;
  _nComp = model._pdfList.getSize() ;
  _coefThresh = new Double_t[_nComp+1] ;
  _vars = (RooArgSet*) vars.snapshot(kFALSE) ;

  while((pdf=(RooAbsPdf*)model._pdfIter->Next())) {
    RooAbsGenContext* cx = pdf->genContext(vars,prototype,auxProto,verbose) ;
    _gcList.push_back(cx) ;
  }  

  ((RooAddPdf*)_pdf)->getProjCache(_vars) ;
  _pdf->recursiveRedirectServers(*_theEvent) ;

  _mcache = 0 ;
  _pcache = 0 ;
}



//_____________________________________________________________________________
RooAddGenContext::RooAddGenContext(const RooAddModel &model, const RooArgSet &vars, 
				   const RooDataSet *prototype, const RooArgSet* auxProto,
				   Bool_t verbose) :
  RooAbsGenContext(model,vars,prototype,auxProto,verbose), _isModel(kTRUE)
{
  // Constructor

  cxcoutI(Generation) << "RooAddGenContext::ctor() setting up event special generator context for sum resolution model " << model.GetName() 
			<< " for generation of observable(s) " << vars ;
  if (prototype) ccxcoutI(Generation) << " with prototype data for " << *prototype->get() ;
  if (auxProto && auxProto->getSize()>0)  ccxcoutI(Generation) << " with auxiliary prototypes " << *auxProto ;
  ccxcoutI(Generation) << endl ;

  // Constructor. Build an array of generator contexts for each product component PDF
  _pdfSet = (RooArgSet*) RooArgSet(model).snapshot(kTRUE) ;
  _pdf = (RooAbsPdf*) _pdfSet->find(model.GetName()) ;


  model._pdfIter->Reset() ;
  RooAbsPdf* pdf ;
  _nComp = model._pdfList.getSize() ;
  _coefThresh = new Double_t[_nComp+1] ;
  _vars = (RooArgSet*) vars.snapshot(kFALSE) ;

  while((pdf=(RooAbsPdf*)model._pdfIter->Next())) {
    RooAbsGenContext* cx = pdf->genContext(vars,prototype,auxProto,verbose) ;
    _gcList.push_back(cx) ;
  }  

  ((RooAddModel*)_pdf)->getProjCache(_vars) ;
  _pdf->recursiveRedirectServers(*_theEvent) ;

  _mcache = 0 ;
  _pcache = 0 ;
}



//_____________________________________________________________________________
RooAddGenContext::~RooAddGenContext()
{
  // Destructor. Delete all owned subgenerator contexts

  delete[] _coefThresh ;
  for (vector<RooAbsGenContext*>::iterator iter=_gcList.begin() ; iter!=_gcList.end() ; ++iter) {
    delete *iter ;
  }
  delete _vars ;
  delete _pdfSet ;
}



//_____________________________________________________________________________
void RooAddGenContext::attach(const RooArgSet& args) 
{
  // Attach given set of variables to internal p.d.f. clone

  _pdf->recursiveRedirectServers(args) ;

  // Forward initGenerator call to all components
  for (vector<RooAbsGenContext*>::iterator iter=_gcList.begin() ; iter!=_gcList.end() ; ++iter) {
    (*iter)->attach(args) ;
  }
}



//_____________________________________________________________________________
void RooAddGenContext::initGenerator(const RooArgSet &theEvent)
{
  // One-time initialization of generator contex. Attach theEvent
  // to internal p.d.f clone and forward initialization call to 
  // the component generators

  _pdf->recursiveRedirectServers(theEvent) ;

  if (_isModel) {    
    RooAddModel* amod = (RooAddModel*) _pdf ;
    _mcache = amod->getProjCache(_vars) ;
  } else {
    RooAddPdf* apdf = (RooAddPdf*) _pdf ;
    _pcache = apdf->getProjCache(_vars,0,"FULL_RANGE_ADDGENCONTEXT") ;
  }
  
  // Forward initGenerator call to all components
  for (vector<RooAbsGenContext*>::iterator iter=_gcList.begin() ; iter!=_gcList.end() ; ++iter) {
    (*iter)->initGenerator(theEvent) ;
  }
}


//_____________________________________________________________________________
void RooAddGenContext::generateEvent(RooArgSet &theEvent, Int_t remaining)
{
  // Randomly choose one of the component contexts to generate this event,
  // with a probability proportional to its coefficient

  // Throw a random number to determin which component to generate
  updateThresholds() ;
  Double_t rand = RooRandom::uniform() ;
  Int_t i=0 ;
  for (i=0 ; i<_nComp ; i++) {
    if (rand>_coefThresh[i] && rand<_coefThresh[i+1]) {
      _gcList[i]->generateEvent(theEvent,remaining) ;
      return ;
    }
  }
}


//_____________________________________________________________________________
void RooAddGenContext::updateThresholds()
{
  // Update the cumulative threshold table from the current coefficient
  // values

  if (_isModel) {
    
    RooAddModel* amod = (RooAddModel*) _pdf ;
    amod->updateCoefficients(*_mcache,_vars) ;

    _coefThresh[0] = 0. ;
    Int_t i ;
    for (i=0 ; i<_nComp ; i++) {
      _coefThresh[i+1] = amod->_coefCache[i] ;
      _coefThresh[i+1] += _coefThresh[i] ;
    }

  } else {

    RooAddPdf* apdf = (RooAddPdf*) _pdf ;
    
    apdf->updateCoefficients(*_pcache,_vars) ;
    
    _coefThresh[0] = 0. ;
    Int_t i ;
    for (i=0 ; i<_nComp ; i++) {
      _coefThresh[i+1] = apdf->_coefCache[i] ;
      _coefThresh[i+1] += _coefThresh[i] ;
//       cout << "RooAddGenContext::updateThresholds(" << GetName() << ") _coefThresh[" << i+1 << "] = " << _coefThresh[i+1] << endl ;
    }
    
  }

}


//_____________________________________________________________________________
void RooAddGenContext::setProtoDataOrder(Int_t* lut)
{
  // Forward the setProtoDataOrder call to the component generator contexts

  RooAbsGenContext::setProtoDataOrder(lut) ;
  for (vector<RooAbsGenContext*>::iterator iter=_gcList.begin() ; iter!=_gcList.end() ; ++iter) {
    (*iter)->setProtoDataOrder(lut) ;
  }
}



//_____________________________________________________________________________
void RooAddGenContext::printMultiline(ostream &os, Int_t content, Bool_t verbose, TString indent) const 
{
  // Print the details of the context

  RooAbsGenContext::printMultiline(os,content,verbose,indent) ;
  os << indent << "--- RooAddGenContext ---" << endl ;
  os << indent << "Using PDF ";
  _pdf->printStream(os,kName|kArgs|kClassName,kSingleLine,indent);
  
  os << indent << "List of component generators" << endl ;
  TString indent2(indent) ;
  indent2.Append("    ") ;
  for (vector<RooAbsGenContext*>::const_iterator iter=_gcList.begin() ; iter!=_gcList.end() ; ++iter) {
    (*iter)->printMultiline(os,content,verbose,indent2) ;
  }
}
 RooAddGenContext.cxx:1
 RooAddGenContext.cxx:2
 RooAddGenContext.cxx:3
 RooAddGenContext.cxx:4
 RooAddGenContext.cxx:5
 RooAddGenContext.cxx:6
 RooAddGenContext.cxx:7
 RooAddGenContext.cxx:8
 RooAddGenContext.cxx:9
 RooAddGenContext.cxx:10
 RooAddGenContext.cxx:11
 RooAddGenContext.cxx:12
 RooAddGenContext.cxx:13
 RooAddGenContext.cxx:14
 RooAddGenContext.cxx:15
 RooAddGenContext.cxx:16
 RooAddGenContext.cxx:17
 RooAddGenContext.cxx:18
 RooAddGenContext.cxx:19
 RooAddGenContext.cxx:20
 RooAddGenContext.cxx:21
 RooAddGenContext.cxx:22
 RooAddGenContext.cxx:23
 RooAddGenContext.cxx:24
 RooAddGenContext.cxx:25
 RooAddGenContext.cxx:26
 RooAddGenContext.cxx:27
 RooAddGenContext.cxx:28
 RooAddGenContext.cxx:29
 RooAddGenContext.cxx:30
 RooAddGenContext.cxx:31
 RooAddGenContext.cxx:32
 RooAddGenContext.cxx:33
 RooAddGenContext.cxx:34
 RooAddGenContext.cxx:35
 RooAddGenContext.cxx:36
 RooAddGenContext.cxx:37
 RooAddGenContext.cxx:38
 RooAddGenContext.cxx:39
 RooAddGenContext.cxx:40
 RooAddGenContext.cxx:41
 RooAddGenContext.cxx:42
 RooAddGenContext.cxx:43
 RooAddGenContext.cxx:44
 RooAddGenContext.cxx:45
 RooAddGenContext.cxx:46
 RooAddGenContext.cxx:47
 RooAddGenContext.cxx:48
 RooAddGenContext.cxx:49
 RooAddGenContext.cxx:50
 RooAddGenContext.cxx:51
 RooAddGenContext.cxx:52
 RooAddGenContext.cxx:53
 RooAddGenContext.cxx:54
 RooAddGenContext.cxx:55
 RooAddGenContext.cxx:56
 RooAddGenContext.cxx:57
 RooAddGenContext.cxx:58
 RooAddGenContext.cxx:59
 RooAddGenContext.cxx:60
 RooAddGenContext.cxx:61
 RooAddGenContext.cxx:62
 RooAddGenContext.cxx:63
 RooAddGenContext.cxx:64
 RooAddGenContext.cxx:65
 RooAddGenContext.cxx:66
 RooAddGenContext.cxx:67
 RooAddGenContext.cxx:68
 RooAddGenContext.cxx:69
 RooAddGenContext.cxx:70
 RooAddGenContext.cxx:71
 RooAddGenContext.cxx:72
 RooAddGenContext.cxx:73
 RooAddGenContext.cxx:74
 RooAddGenContext.cxx:75
 RooAddGenContext.cxx:76
 RooAddGenContext.cxx:77
 RooAddGenContext.cxx:78
 RooAddGenContext.cxx:79
 RooAddGenContext.cxx:80
 RooAddGenContext.cxx:81
 RooAddGenContext.cxx:82
 RooAddGenContext.cxx:83
 RooAddGenContext.cxx:84
 RooAddGenContext.cxx:85
 RooAddGenContext.cxx:86
 RooAddGenContext.cxx:87
 RooAddGenContext.cxx:88
 RooAddGenContext.cxx:89
 RooAddGenContext.cxx:90
 RooAddGenContext.cxx:91
 RooAddGenContext.cxx:92
 RooAddGenContext.cxx:93
 RooAddGenContext.cxx:94
 RooAddGenContext.cxx:95
 RooAddGenContext.cxx:96
 RooAddGenContext.cxx:97
 RooAddGenContext.cxx:98
 RooAddGenContext.cxx:99
 RooAddGenContext.cxx:100
 RooAddGenContext.cxx:101
 RooAddGenContext.cxx:102
 RooAddGenContext.cxx:103
 RooAddGenContext.cxx:104
 RooAddGenContext.cxx:105
 RooAddGenContext.cxx:106
 RooAddGenContext.cxx:107
 RooAddGenContext.cxx:108
 RooAddGenContext.cxx:109
 RooAddGenContext.cxx:110
 RooAddGenContext.cxx:111
 RooAddGenContext.cxx:112
 RooAddGenContext.cxx:113
 RooAddGenContext.cxx:114
 RooAddGenContext.cxx:115
 RooAddGenContext.cxx:116
 RooAddGenContext.cxx:117
 RooAddGenContext.cxx:118
 RooAddGenContext.cxx:119
 RooAddGenContext.cxx:120
 RooAddGenContext.cxx:121
 RooAddGenContext.cxx:122
 RooAddGenContext.cxx:123
 RooAddGenContext.cxx:124
 RooAddGenContext.cxx:125
 RooAddGenContext.cxx:126
 RooAddGenContext.cxx:127
 RooAddGenContext.cxx:128
 RooAddGenContext.cxx:129
 RooAddGenContext.cxx:130
 RooAddGenContext.cxx:131
 RooAddGenContext.cxx:132
 RooAddGenContext.cxx:133
 RooAddGenContext.cxx:134
 RooAddGenContext.cxx:135
 RooAddGenContext.cxx:136
 RooAddGenContext.cxx:137
 RooAddGenContext.cxx:138
 RooAddGenContext.cxx:139
 RooAddGenContext.cxx:140
 RooAddGenContext.cxx:141
 RooAddGenContext.cxx:142
 RooAddGenContext.cxx:143
 RooAddGenContext.cxx:144
 RooAddGenContext.cxx:145
 RooAddGenContext.cxx:146
 RooAddGenContext.cxx:147
 RooAddGenContext.cxx:148
 RooAddGenContext.cxx:149
 RooAddGenContext.cxx:150
 RooAddGenContext.cxx:151
 RooAddGenContext.cxx:152
 RooAddGenContext.cxx:153
 RooAddGenContext.cxx:154
 RooAddGenContext.cxx:155
 RooAddGenContext.cxx:156
 RooAddGenContext.cxx:157
 RooAddGenContext.cxx:158
 RooAddGenContext.cxx:159
 RooAddGenContext.cxx:160
 RooAddGenContext.cxx:161
 RooAddGenContext.cxx:162
 RooAddGenContext.cxx:163
 RooAddGenContext.cxx:164
 RooAddGenContext.cxx:165
 RooAddGenContext.cxx:166
 RooAddGenContext.cxx:167
 RooAddGenContext.cxx:168
 RooAddGenContext.cxx:169
 RooAddGenContext.cxx:170
 RooAddGenContext.cxx:171
 RooAddGenContext.cxx:172
 RooAddGenContext.cxx:173
 RooAddGenContext.cxx:174
 RooAddGenContext.cxx:175
 RooAddGenContext.cxx:176
 RooAddGenContext.cxx:177
 RooAddGenContext.cxx:178
 RooAddGenContext.cxx:179
 RooAddGenContext.cxx:180
 RooAddGenContext.cxx:181
 RooAddGenContext.cxx:182
 RooAddGenContext.cxx:183
 RooAddGenContext.cxx:184
 RooAddGenContext.cxx:185
 RooAddGenContext.cxx:186
 RooAddGenContext.cxx:187
 RooAddGenContext.cxx:188
 RooAddGenContext.cxx:189
 RooAddGenContext.cxx:190
 RooAddGenContext.cxx:191
 RooAddGenContext.cxx:192
 RooAddGenContext.cxx:193
 RooAddGenContext.cxx:194
 RooAddGenContext.cxx:195
 RooAddGenContext.cxx:196
 RooAddGenContext.cxx:197
 RooAddGenContext.cxx:198
 RooAddGenContext.cxx:199
 RooAddGenContext.cxx:200
 RooAddGenContext.cxx:201
 RooAddGenContext.cxx:202
 RooAddGenContext.cxx:203
 RooAddGenContext.cxx:204
 RooAddGenContext.cxx:205
 RooAddGenContext.cxx:206
 RooAddGenContext.cxx:207
 RooAddGenContext.cxx:208
 RooAddGenContext.cxx:209
 RooAddGenContext.cxx:210
 RooAddGenContext.cxx:211
 RooAddGenContext.cxx:212
 RooAddGenContext.cxx:213
 RooAddGenContext.cxx:214
 RooAddGenContext.cxx:215
 RooAddGenContext.cxx:216
 RooAddGenContext.cxx:217
 RooAddGenContext.cxx:218
 RooAddGenContext.cxx:219
 RooAddGenContext.cxx:220
 RooAddGenContext.cxx:221
 RooAddGenContext.cxx:222
 RooAddGenContext.cxx:223
 RooAddGenContext.cxx:224
 RooAddGenContext.cxx:225
 RooAddGenContext.cxx:226
 RooAddGenContext.cxx:227
 RooAddGenContext.cxx:228
 RooAddGenContext.cxx:229
 RooAddGenContext.cxx:230
 RooAddGenContext.cxx:231
 RooAddGenContext.cxx:232
 RooAddGenContext.cxx:233
 RooAddGenContext.cxx:234
 RooAddGenContext.cxx:235
 RooAddGenContext.cxx:236
 RooAddGenContext.cxx:237
 RooAddGenContext.cxx:238
 RooAddGenContext.cxx:239
 RooAddGenContext.cxx:240
 RooAddGenContext.cxx:241
 RooAddGenContext.cxx:242
 RooAddGenContext.cxx:243
 RooAddGenContext.cxx:244
 RooAddGenContext.cxx:245
 RooAddGenContext.cxx:246
 RooAddGenContext.cxx:247
 RooAddGenContext.cxx:248
 RooAddGenContext.cxx:249
 RooAddGenContext.cxx:250
 RooAddGenContext.cxx:251
 RooAddGenContext.cxx:252
 RooAddGenContext.cxx:253
 RooAddGenContext.cxx:254
 RooAddGenContext.cxx:255
 RooAddGenContext.cxx:256
 RooAddGenContext.cxx:257
 RooAddGenContext.cxx:258
 RooAddGenContext.cxx:259
 RooAddGenContext.cxx:260
 RooAddGenContext.cxx:261
 RooAddGenContext.cxx:262
 RooAddGenContext.cxx:263
 RooAddGenContext.cxx:264
 RooAddGenContext.cxx:265
 RooAddGenContext.cxx:266
 RooAddGenContext.cxx:267
 RooAddGenContext.cxx:268
 RooAddGenContext.cxx:269
 RooAddGenContext.cxx:270
 RooAddGenContext.cxx:271
 RooAddGenContext.cxx:272
 RooAddGenContext.cxx:273
 RooAddGenContext.cxx:274