/*****************************************************************************
 * 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
// Numeric 1-dimensional convolution operator PDF. This class can convolve any PDF
// with any other PDF using a straightforward numeric calculation of the
// convolution integral
// <p>
// This class should be used as last resort as numeric convolution calculated
// this way is computationally intensive and prone to stability fitting problems. 
// <b>The preferred way to compute numeric convolutions is RooFFTConvPdf</b>,
// which calculates convolutions using Fourier Transforms (requires external free
// FFTW3 package)
// <p>
// RooNumConvPdf implements reasonable defaults that should convolve most
// functions reasonably well, but results strongly depend on the shape of your
// input PDFS so always check your result.
// <p>
// The default integration engine for the numeric convolution is the
// adaptive Gauss-Kronrod method, which empirically seems the most robust
// for this task. You can override the convolution integration settings via
// the RooNumIntConfig object reference returned by the convIntConfig() member
// function
// <p>
// By default the numeric convolution is integrated from -infinity to
// +infinity through a <pre>x -> 1/x</pre> coordinate transformation of the
// tails. For convolution with a very small bandwidth it may be
// advantageous (for both CPU consumption and stability) if the
// integration domain is limited to a finite range. The function
// setConvolutionWindow(mean,width,scale) allows to set a sliding
// window around the x value to be calculated taking a RooAbsReal
// expression for an offset and a width to be taken around the x
// value. These input expression can be RooFormulaVars or other
// function objects although the 3d 'scale' argument 'scale'
// multiplies the width RooAbsReal expression given in the 2nd
// argument, allowing for an appropriate window definition for most
// cases without need for a RooFormulaVar object: e.g. a Gaussian
// resolution PDF do setConvolutionWindow(gaussMean,gaussSigma,5)
// Note that for a 'wide' Gaussian the -inf to +inf integration
// may converge more quickly than that over a finite range!
// <p>
// The default numeric precision is 1e-7, i.e. the global default for
// numeric integration but you should experiment with this value to
// see if it is sufficient for example by studying the number of function
// calls that MINUIT needs to fit your function as function of the
// convolution precision. 
// END_HTML
//

#include "RooFit.h"

#include "Riostream.h"
#include "Riostream.h"
#include "TH2F.h"
#include "RooNumConvPdf.h"
#include "RooArgList.h"
#include "RooRealVar.h"
#include "RooFormulaVar.h"
#include "RooCustomizer.h"
#include "RooConvIntegrandBinding.h"
#include "RooNumIntFactory.h"
#include "RooGenContext.h"
#include "RooConvGenContext.h"



using namespace std;

ClassImp(RooNumConvPdf)
;



//_____________________________________________________________________________
RooNumConvPdf::RooNumConvPdf() :
  _init(kFALSE),
  _conv(0)
{  
}




//_____________________________________________________________________________R
RooNumConvPdf::RooNumConvPdf(const char *name, const char *title, RooRealVar& convVar, RooAbsPdf& inPdf, RooAbsPdf& resmodel) : 
  RooAbsPdf(name,title), 
  _init(kFALSE),
  _conv(0),
  _origVar("!origVar","Original Convolution variable",this,convVar),
  _origPdf("!origPdf","Original Input PDF",this,inPdf),
  _origModel("!origModel","Original Resolution model",this,resmodel)
{
  // Constructor of convolution operator PDF
  // 
  // convVar  :  convolution variable (on which both pdf and resmodel should depend)
  // pdf      :  input 'physics' pdf
  // resmodel :  input 'resultion' pdf
  //
  // output is pdf(x) (X) resmodel(x) = Int [ pdf(x') resmodel (x-x') ] dx'
  //
}



//_____________________________________________________________________________
RooNumConvPdf::RooNumConvPdf(const RooNumConvPdf& other, const char* name) :
  RooAbsPdf(other,name), 
  _init(kFALSE),
  _origVar("!origVar",this,other._origVar),
  _origPdf("!origPdf",this,other._origPdf),
  _origModel("!origModel",this,other._origModel)
{
  // Copy constructor

  // Make temporary clone of original convolution to preserve configuration information
  // This information will be propagated to a newly create convolution in a subsequent
  // call to initialize() 
  if (other._conv) {
    _conv = new RooNumConvolution(*other._conv,Form("%s_CONV",name?name:GetName())) ;
  } else {
    _conv = 0 ;
  }
}



//_____________________________________________________________________________
RooNumConvPdf::~RooNumConvPdf() 
{
  // Destructor
  if (_init) {
    delete _conv ;
  }
}



//_____________________________________________________________________________
Double_t RooNumConvPdf::evaluate() const
{
  // Calculate and return value of p.d.f

  if (!_init) initialize() ;

  return _conv->evaluate() ;
}



//_____________________________________________________________________________
void RooNumConvPdf::initialize() const
{
  // One-time initialization of object

  // Save pointer to any prototype convolution object (only present if this object is made through
  // a copy constructor) 
  RooNumConvolution* protoConv = _conv ;

  // Optionally pass along configuration data from prototype object
  _conv = new RooNumConvolution(Form("%s_CONV",GetName()),GetTitle(),var(),pdf(),model(),protoConv) ;

  // Delete prototype object now
  if (protoConv) {
    delete protoConv ;  
  }

  _init = kTRUE ;
}



//_____________________________________________________________________________
RooAbsGenContext* RooNumConvPdf::genContext(const RooArgSet &vars, const RooDataSet *prototype, 
					    const RooArgSet* auxProto, Bool_t verbose) const 
{
  // Return appropriate generator context for this convolved p.d.f. If both pdf and resolution
  // model support internal generation return and optimization convolution generation context
  // that uses a smearing algorithm. Otherwise return a standard accept/reject sampling
  // context on the convoluted shape.

  if (!_init) initialize() ;

  // Check if physics PDF and resolution model can both directly generate the convolution variable
  RooArgSet* modelDep = _conv->model().getObservables(&vars) ;
  modelDep->remove(_conv->var(),kTRUE,kTRUE) ;
  Int_t numAddDep = modelDep->getSize() ;
  delete modelDep ;

  RooArgSet dummy ;
  Bool_t pdfCanDir = (((RooAbsPdf&)_conv->pdf()).getGenerator(_conv->var(),dummy) != 0 && \
		      ((RooAbsPdf&)_conv->pdf()).isDirectGenSafe(_conv->var())) ;
  Bool_t resCanDir = (((RooAbsPdf&)_conv->model()).getGenerator(_conv->var(),dummy) !=0  && 
		      ((RooAbsPdf&)_conv->model()).isDirectGenSafe(_conv->var())) ;

  if (numAddDep>0 || !pdfCanDir || !resCanDir) {
    // Any resolution model with more dependents than the convolution variable
    // or pdf or resmodel do not support direct generation
    return new RooGenContext(*this,vars,prototype,auxProto,verbose) ;
  } 
  
  // Any other resolution model: use specialized generator context
  return new RooConvGenContext(*this,vars,prototype,auxProto,verbose) ;
}



//_____________________________________________________________________________
void RooNumConvPdf::printMetaArgs(ostream& os) const 
{
  // Customized printing of arguments of a RooNumConvPdf to more intuitively reflect the contents of the
  // product operator construction

  os << _origPdf.arg().GetName() << "(" << _origVar.arg().GetName() << ") (*) " << _origModel.arg().GetName() << "(" << _origVar.arg().GetName() << ") " ;
}
 RooNumConvPdf.cxx:1
 RooNumConvPdf.cxx:2
 RooNumConvPdf.cxx:3
 RooNumConvPdf.cxx:4
 RooNumConvPdf.cxx:5
 RooNumConvPdf.cxx:6
 RooNumConvPdf.cxx:7
 RooNumConvPdf.cxx:8
 RooNumConvPdf.cxx:9
 RooNumConvPdf.cxx:10
 RooNumConvPdf.cxx:11
 RooNumConvPdf.cxx:12
 RooNumConvPdf.cxx:13
 RooNumConvPdf.cxx:14
 RooNumConvPdf.cxx:15
 RooNumConvPdf.cxx:16
 RooNumConvPdf.cxx:17
 RooNumConvPdf.cxx:18
 RooNumConvPdf.cxx:19
 RooNumConvPdf.cxx:20
 RooNumConvPdf.cxx:21
 RooNumConvPdf.cxx:22
 RooNumConvPdf.cxx:23
 RooNumConvPdf.cxx:24
 RooNumConvPdf.cxx:25
 RooNumConvPdf.cxx:26
 RooNumConvPdf.cxx:27
 RooNumConvPdf.cxx:28
 RooNumConvPdf.cxx:29
 RooNumConvPdf.cxx:30
 RooNumConvPdf.cxx:31
 RooNumConvPdf.cxx:32
 RooNumConvPdf.cxx:33
 RooNumConvPdf.cxx:34
 RooNumConvPdf.cxx:35
 RooNumConvPdf.cxx:36
 RooNumConvPdf.cxx:37
 RooNumConvPdf.cxx:38
 RooNumConvPdf.cxx:39
 RooNumConvPdf.cxx:40
 RooNumConvPdf.cxx:41
 RooNumConvPdf.cxx:42
 RooNumConvPdf.cxx:43
 RooNumConvPdf.cxx:44
 RooNumConvPdf.cxx:45
 RooNumConvPdf.cxx:46
 RooNumConvPdf.cxx:47
 RooNumConvPdf.cxx:48
 RooNumConvPdf.cxx:49
 RooNumConvPdf.cxx:50
 RooNumConvPdf.cxx:51
 RooNumConvPdf.cxx:52
 RooNumConvPdf.cxx:53
 RooNumConvPdf.cxx:54
 RooNumConvPdf.cxx:55
 RooNumConvPdf.cxx:56
 RooNumConvPdf.cxx:57
 RooNumConvPdf.cxx:58
 RooNumConvPdf.cxx:59
 RooNumConvPdf.cxx:60
 RooNumConvPdf.cxx:61
 RooNumConvPdf.cxx:62
 RooNumConvPdf.cxx:63
 RooNumConvPdf.cxx:64
 RooNumConvPdf.cxx:65
 RooNumConvPdf.cxx:66
 RooNumConvPdf.cxx:67
 RooNumConvPdf.cxx:68
 RooNumConvPdf.cxx:69
 RooNumConvPdf.cxx:70
 RooNumConvPdf.cxx:71
 RooNumConvPdf.cxx:72
 RooNumConvPdf.cxx:73
 RooNumConvPdf.cxx:74
 RooNumConvPdf.cxx:75
 RooNumConvPdf.cxx:76
 RooNumConvPdf.cxx:77
 RooNumConvPdf.cxx:78
 RooNumConvPdf.cxx:79
 RooNumConvPdf.cxx:80
 RooNumConvPdf.cxx:81
 RooNumConvPdf.cxx:82
 RooNumConvPdf.cxx:83
 RooNumConvPdf.cxx:84
 RooNumConvPdf.cxx:85
 RooNumConvPdf.cxx:86
 RooNumConvPdf.cxx:87
 RooNumConvPdf.cxx:88
 RooNumConvPdf.cxx:89
 RooNumConvPdf.cxx:90
 RooNumConvPdf.cxx:91
 RooNumConvPdf.cxx:92
 RooNumConvPdf.cxx:93
 RooNumConvPdf.cxx:94
 RooNumConvPdf.cxx:95
 RooNumConvPdf.cxx:96
 RooNumConvPdf.cxx:97
 RooNumConvPdf.cxx:98
 RooNumConvPdf.cxx:99
 RooNumConvPdf.cxx:100
 RooNumConvPdf.cxx:101
 RooNumConvPdf.cxx:102
 RooNumConvPdf.cxx:103
 RooNumConvPdf.cxx:104
 RooNumConvPdf.cxx:105
 RooNumConvPdf.cxx:106
 RooNumConvPdf.cxx:107
 RooNumConvPdf.cxx:108
 RooNumConvPdf.cxx:109
 RooNumConvPdf.cxx:110
 RooNumConvPdf.cxx:111
 RooNumConvPdf.cxx:112
 RooNumConvPdf.cxx:113
 RooNumConvPdf.cxx:114
 RooNumConvPdf.cxx:115
 RooNumConvPdf.cxx:116
 RooNumConvPdf.cxx:117
 RooNumConvPdf.cxx:118
 RooNumConvPdf.cxx:119
 RooNumConvPdf.cxx:120
 RooNumConvPdf.cxx:121
 RooNumConvPdf.cxx:122
 RooNumConvPdf.cxx:123
 RooNumConvPdf.cxx:124
 RooNumConvPdf.cxx:125
 RooNumConvPdf.cxx:126
 RooNumConvPdf.cxx:127
 RooNumConvPdf.cxx:128
 RooNumConvPdf.cxx:129
 RooNumConvPdf.cxx:130
 RooNumConvPdf.cxx:131
 RooNumConvPdf.cxx:132
 RooNumConvPdf.cxx:133
 RooNumConvPdf.cxx:134
 RooNumConvPdf.cxx:135
 RooNumConvPdf.cxx:136
 RooNumConvPdf.cxx:137
 RooNumConvPdf.cxx:138
 RooNumConvPdf.cxx:139
 RooNumConvPdf.cxx:140
 RooNumConvPdf.cxx:141
 RooNumConvPdf.cxx:142
 RooNumConvPdf.cxx:143
 RooNumConvPdf.cxx:144
 RooNumConvPdf.cxx:145
 RooNumConvPdf.cxx:146
 RooNumConvPdf.cxx:147
 RooNumConvPdf.cxx:148
 RooNumConvPdf.cxx:149
 RooNumConvPdf.cxx:150
 RooNumConvPdf.cxx:151
 RooNumConvPdf.cxx:152
 RooNumConvPdf.cxx:153
 RooNumConvPdf.cxx:154
 RooNumConvPdf.cxx:155
 RooNumConvPdf.cxx:156
 RooNumConvPdf.cxx:157
 RooNumConvPdf.cxx:158
 RooNumConvPdf.cxx:159
 RooNumConvPdf.cxx:160
 RooNumConvPdf.cxx:161
 RooNumConvPdf.cxx:162
 RooNumConvPdf.cxx:163
 RooNumConvPdf.cxx:164
 RooNumConvPdf.cxx:165
 RooNumConvPdf.cxx:166
 RooNumConvPdf.cxx:167
 RooNumConvPdf.cxx:168
 RooNumConvPdf.cxx:169
 RooNumConvPdf.cxx:170
 RooNumConvPdf.cxx:171
 RooNumConvPdf.cxx:172
 RooNumConvPdf.cxx:173
 RooNumConvPdf.cxx:174
 RooNumConvPdf.cxx:175
 RooNumConvPdf.cxx:176
 RooNumConvPdf.cxx:177
 RooNumConvPdf.cxx:178
 RooNumConvPdf.cxx:179
 RooNumConvPdf.cxx:180
 RooNumConvPdf.cxx:181
 RooNumConvPdf.cxx:182
 RooNumConvPdf.cxx:183
 RooNumConvPdf.cxx:184
 RooNumConvPdf.cxx:185
 RooNumConvPdf.cxx:186
 RooNumConvPdf.cxx:187
 RooNumConvPdf.cxx:188
 RooNumConvPdf.cxx:189
 RooNumConvPdf.cxx:190
 RooNumConvPdf.cxx:191
 RooNumConvPdf.cxx:192
 RooNumConvPdf.cxx:193
 RooNumConvPdf.cxx:194
 RooNumConvPdf.cxx:195
 RooNumConvPdf.cxx:196
 RooNumConvPdf.cxx:197
 RooNumConvPdf.cxx:198
 RooNumConvPdf.cxx:199
 RooNumConvPdf.cxx:200
 RooNumConvPdf.cxx:201
 RooNumConvPdf.cxx:202
 RooNumConvPdf.cxx:203
 RooNumConvPdf.cxx:204
 RooNumConvPdf.cxx:205
 RooNumConvPdf.cxx:206
 RooNumConvPdf.cxx:207
 RooNumConvPdf.cxx:208
 RooNumConvPdf.cxx:209
 RooNumConvPdf.cxx:210
 RooNumConvPdf.cxx:211
 RooNumConvPdf.cxx:212
 RooNumConvPdf.cxx:213
 RooNumConvPdf.cxx:214
 RooNumConvPdf.cxx:215
 RooNumConvPdf.cxx:216
 RooNumConvPdf.cxx:217
 RooNumConvPdf.cxx:218
 RooNumConvPdf.cxx:219
 RooNumConvPdf.cxx:220
 RooNumConvPdf.cxx:221
 RooNumConvPdf.cxx:222
 RooNumConvPdf.cxx:223
 RooNumConvPdf.cxx:224
 RooNumConvPdf.cxx:225
 RooNumConvPdf.cxx:226
 RooNumConvPdf.cxx:227
 RooNumConvPdf.cxx:228
 RooNumConvPdf.cxx:229