/*****************************************************************************
 * Project: RooFit                                                           *
 * Package: RooFitBabar                                                      *
 * @(#)root/roofit:$Id$
 * Authors:                                                                  *
 *    Aaron Roodman, Stanford Linear Accelerator Center, Stanford University *
 *                                                                           *
 * Copyright (c) 2004, 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)             *
 *****************************************************************************/

//////////////////////////////////////////////////////////////////////////////
//
// The Parametric Step Function PDF is a binned distribution whose parameters 
// are the heights of each bin.  This PDF was first used in BaBar's B0->pi0pi0
// paper BABAR Collaboration (B. Aubert et al.) Phys.Rev.Lett.91:241801,2003.
// 
// This PDF may be used to describe oddly shaped distributions.  It differs
// from a RooKeysPdf or a RooHistPdf in that a RooParametricStepFunction
// has free parameters.  In particular, any statistical uncertainty in 
// sample used to model this PDF may be understood with these free parameters;
// this is not possible with non-parametric PDFs.
//
// The RooParametricStepFunction has Nbins-1 free parameters. Note that
// the limits of the dependent varaible must match the low and hi bin limits.
//
// An example of usage is:
//
// Int_t nbins(10);
// TArrayD limits(nbins+1);
// limits[0] = 0.0; //etc...
// RooArgList* list = new RooArgList("list");
// RooRealVar* binHeight0 = new RooRealVar("binHeight0","bin 0 Value",0.1,0.0,1.0);
// list->add(binHeight0); // up to binHeight8, ie. 9 parameters
//
// RooParametricStepFunction  aPdf = ("aPdf","PSF",*x,
//                                    *list,limits,nbins);
//
				

#include "RooFit.h"

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

#include "RooParametricStepFunction.h"
#include "RooAbsReal.h"
#include "RooRealVar.h"
#include "RooArgList.h"

#include "TError.h"

using namespace std;

ClassImp(RooParametricStepFunction)
;


//_____________________________________________________________________________
RooParametricStepFunction::RooParametricStepFunction(const char* name, const char* title, 
			     RooAbsReal& x, const RooArgList& coefList, TArrayD& limits, Int_t nBins) :
  RooAbsPdf(name, title),
  _x("x", "Dependent", this, x),
  _coefList("coefList","List of coefficients",this),
  _nBins(nBins)
{
  // Constructor
  _coefIter = _coefList.createIterator() ;

  // Check lowest order
  if (_nBins<0) {
    cout << "RooParametricStepFunction::ctor(" << GetName() 
	 << ") WARNING: nBins must be >=0, setting value to 0" << endl ;
    _nBins=0 ;
  }

  TIterator* coefIter = coefList.createIterator() ;
  RooAbsArg* coef ;
  while((coef = (RooAbsArg*)coefIter->Next())) {
    if (!dynamic_cast<RooAbsReal*>(coef)) {
      cout << "RooParametricStepFunction::ctor(" << GetName() << ") ERROR: coefficient " << coef->GetName() 
	   << " is not of type RooAbsReal" << endl ;
      R__ASSERT(0) ;
    }
    _coefList.add(*coef) ;
  }
  delete coefIter ;

  // Bin limits  
  limits.Copy(_limits);

}



//_____________________________________________________________________________
RooParametricStepFunction::RooParametricStepFunction(const RooParametricStepFunction& other, const char* name) :
  RooAbsPdf(other, name), 
  _x("x", this, other._x), 
  _coefList("coefList",this,other._coefList),
  _nBins(other._nBins)
{
  // Copy constructor
  _coefIter = _coefList.createIterator();
  (other._limits).Copy(_limits);
}



//_____________________________________________________________________________
RooParametricStepFunction::~RooParametricStepFunction()
{
  // Destructor
  delete _coefIter ;
}



//_____________________________________________________________________________
Int_t RooParametricStepFunction::getAnalyticalIntegral(RooArgSet& allVars, RooArgSet& analVars, const char* /*rangeName*/) const 
{
  if (matchArgs(allVars, analVars, _x)) return 1;
  return 0;
}



//_____________________________________________________________________________
Double_t RooParametricStepFunction::analyticalIntegral(Int_t code, const char* rangeName) const 
{
  R__ASSERT(code==1) ;
  
  // Case without range is trivial: p.d.f is by construction normalized 
  if (!rangeName) {
    return 1.0 ;
  }

  // Case with ranges, calculate integral explicitly 
  Double_t xmin = _x.min(rangeName) ;
  Double_t xmax = _x.max(rangeName) ;

  Double_t sum=0 ;
  Int_t i ;
  for (i=1 ; i<=_nBins ; i++) {
    Double_t binVal = (i<_nBins) ? (static_cast<RooRealVar*>(_coefList.at(i-1))->getVal()) : lastBinValue() ;      
    if (_limits[i-1]>=xmin && _limits[i]<=xmax) {
      // Bin fully in the integration domain
      sum += (_limits[i]-_limits[i-1])*binVal ;
    } else if (_limits[i-1]<xmin && _limits[i]>xmax) {
      // Domain is fully contained in this bin
      sum += (xmax-xmin)*binVal ;
      // Exit here, this is the last bin to be processed by construction
      return sum ;
    } else if (_limits[i-1]<xmin && _limits[i]<=xmax && _limits[i]>xmin) {
      // Lower domain boundary is in bin
      sum +=  (_limits[i]-xmin)*binVal ;
    } else if (_limits[i-1]>=xmin && _limits[i]>xmax && _limits[i-1]<xmax) {
      sum +=  (xmax-_limits[i-1])*binVal ;      
      // Upper domain boundary is in bin
      // Exit here, this is the last bin to be processed by construction
      return sum ;
    }
  }

  return sum;  
}



//_____________________________________________________________________________
Double_t RooParametricStepFunction::lastBinValue() const
{
  Double_t sum(0.);
  Double_t binSize(0.);
  for (Int_t j=1;j<_nBins;j++){
    RooRealVar* tmp = (RooRealVar*) _coefList.at(j-1);
    binSize = _limits[j] - _limits[j-1];
    sum = sum + tmp->getVal()*binSize;
  }
  binSize = _limits[_nBins] - _limits[_nBins-1];
  return (1.0 - sum)/binSize;
}



//_____________________________________________________________________________
Double_t RooParametricStepFunction::evaluate() const 
{
  Double_t value(0.);
  if (_x >= _limits[0] && _x < _limits[_nBins]){

    for (Int_t i=1;i<=_nBins;i++){
      if (_x < _limits[i]){
	// in Bin i-1 (starting with Bin 0)
	if (i<_nBins) {
	  // not in last Bin
	  RooRealVar* tmp = (RooRealVar*) _coefList.at(i-1);
	  value =  tmp->getVal();
	  break;
	} else {
	  // in last Bin
	  Double_t sum(0.);
	  Double_t binSize(0.);
	  for (Int_t j=1;j<_nBins;j++){
	    RooRealVar* tmp = (RooRealVar*) _coefList.at(j-1);
	    binSize = _limits[j] - _limits[j-1];
	    sum = sum + tmp->getVal()*binSize;
	  }
	  binSize = _limits[_nBins] - _limits[_nBins-1];
	  value = (1.0 - sum)/binSize;
	  if (value<=0.0){
	    value = 0.000001;
	    //	    cout << "RooParametricStepFunction: sum of values gt 1.0 -- beware!!" <<endl;
	  }
	  break;
	}
      } 
    }

  } 
  return value;

}


//_____________________________________________________________________________
Int_t RooParametricStepFunction::getnBins(){
  return _nBins;
}


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