/***************************************************************************** 
 * Project: RooFit                                                           * 
 *                                                                           * 
 * This code was autogenerated by RooClassFactory                            * 
 *****************************************************************************/ 

// Your description goes here... 

#include "Riostream.h" 

#include "RooHistConstraint.h" 
#include "RooAbsReal.h" 
#include "RooAbsCategory.h" 
#include "RooParamHistFunc.h"
#include "RooRealVar.h"
#include <math.h> 
#include "TMath.h" 

using namespace std;

ClassImp(RooHistConstraint) 
  
RooHistConstraint::RooHistConstraint(const char *name, const char *title, const RooArgSet& phfSet, Int_t threshold) :
  RooAbsPdf(name,title), 
  _gamma("gamma","gamma",this),
  _nominal("nominal","nominal",this),
  _nominalErr("nominalErr","nominalErr",this),
  _relParam(kTRUE)
{ 
  // Implementing constraint on sum of RooParamHists
  //
  // Step 1 - Create new gamma parameters for sum
  // Step 2 - Replace entries in gamma listproxy of components with new sum components
  // Step 3 - Implement constraints in terms of gamma sum parameters
  
  
  if (phfSet.getSize()==1) {

    RooParamHistFunc* phf = dynamic_cast<RooParamHistFunc*>(phfSet.first()) ;
    
    if (!phf) {
      coutE(InputArguments) << "RooHistConstraint::ctor(" << GetName() 
			    << ") ERROR: input object must be a RooParamHistFunc" << endl ;
      throw std::string("RoohistConstraint::ctor ERROR incongruent input arguments") ;
    }
    
    // Now populate nominal with parameters 
    RooArgSet allVars ;
    for (Int_t i=0 ; i<phf->_dh.numEntries() ; i++) {
      phf->_dh.get(i) ;
      if (phf->_dh.weight()<threshold) {
	const char* vname = Form("%s_nominal_bin_%i",GetName(),i) ;
	RooRealVar* var = new RooRealVar(vname,vname,0,1000) ;    
	var->setVal(phf->_dh.weight()) ;
	var->setConstant(kTRUE) ;
	allVars.add(*var) ;
	_nominal.add(*var) ;
	RooRealVar* gam = (RooRealVar*) phf->_p.at(i) ;
	if (var->getVal()>0) {
	  gam->setConstant(kFALSE) ;
	}
	_gamma.add(*gam) ;
      }
    }
    addOwnedComponents(allVars) ;  

    return ;
  }



  RooFIter phiter = phfSet.fwdIterator() ;
  RooAbsArg* arg ;
  Int_t nbins(-1) ;
  vector<RooParamHistFunc*> phvec ;
  RooArgSet gammaSet ;
  string bin0_name ;
  while((arg=phiter.next())) {

    RooParamHistFunc* phfComp = dynamic_cast<RooParamHistFunc*>(arg) ;
    if (phfComp) {
      phvec.push_back(phfComp) ;
      if (nbins==-1) {
	nbins = phfComp->_p.getSize() ;
	bin0_name = phfComp->_p.at(0)->GetName() ;
	gammaSet.add(phfComp->_p) ;
      } else {
	if (phfComp->_p.getSize()!=nbins) {
	  coutE(InputArguments) << "RooHistConstraint::ctor(" << GetName() 
				<< ") ERROR: incongruent input arguments: all input RooParamHistFuncs should have same #bins" << endl ;
	  throw std::string("RoohistConstraint::ctor ERROR incongruent input arguments") ;
	}
	if (bin0_name != phfComp->_p.at(0)->GetName()) {
	  coutE(InputArguments) << "RooHistConstraint::ctor(" << GetName() 
				<< ") ERROR: incongruent input arguments: all input RooParamHistFuncs should have the same bin parameters" << endl ;
	  throw std::string("RoohistConstraint::ctor ERROR incongruent input arguments") ;	  
	}
	
      }
    } else {
      coutW(InputArguments) << "RooHistConstraint::ctor(" << GetName() 
			    << ") WARNING: ignoring input argument " << arg->GetName() << " which is not of type RooParamHistFunc" << endl;
    }
  }

  _gamma.add(gammaSet) ;

  // Now populate nominal and nominalErr with parameters 
  RooArgSet allVars ;
  for (Int_t i=0 ; i<nbins ; i++) {

    Double_t sumVal(0) ;
    for (vector<RooParamHistFunc*>::iterator iter = phvec.begin() ; iter != phvec.end() ; ++iter) {
      sumVal += (*iter)->getNominal(i) ;
    }      
    
    if (sumVal<threshold) {
      
      const char* vname = Form("%s_nominal_bin_%i",GetName(),i) ;
      RooRealVar* var = new RooRealVar(vname,vname,0,1000) ;    

      Double_t sumVal2(0) ;
      for (vector<RooParamHistFunc*>::iterator iter = phvec.begin() ; iter != phvec.end() ; ++iter) {
	sumVal2 += (*iter)->getNominal(i) ;
      }      
      var->setVal(sumVal2) ;
      var->setConstant(kTRUE) ;

      vname = Form("%s_nominal_error_bin_%i",GetName(),i) ;
      RooRealVar* vare = new RooRealVar(vname,vname,0,1000) ;    

      Double_t sumErr2(0) ;
      for (vector<RooParamHistFunc*>::iterator iter = phvec.begin() ; iter != phvec.end() ; ++iter) {
	sumErr2 += pow((*iter)->getNominalError(i),2) ;
      }      
      vare->setVal(sqrt(sumErr2)) ;
      vare->setConstant(kTRUE) ;

      allVars.add(RooArgSet(*var,*vare)) ;
      _nominal.add(*var) ;
      _nominalErr.add(*vare) ;
      
      ((RooRealVar*)_gamma.at(i))->setConstant(kFALSE) ;

    }
  }
  addOwnedComponents(allVars) ;  
} 


 RooHistConstraint::RooHistConstraint(const RooHistConstraint& other, const char* name) :  
   RooAbsPdf(other,name), 
   _gamma("gamma",this,other._gamma),
   _nominal("nominal",this,other._nominal),
   _nominalErr("nominalErr",this,other._nominalErr),
   _relParam(other._relParam)
 { 
 } 


 Double_t RooHistConstraint::evaluate() const 
 { 
   Double_t prod(1) ;
   RooFIter niter = _nominal.fwdIterator() ;
   RooFIter giter = _gamma.fwdIterator() ;
   RooAbsReal *gam, *nom ;
   while ((gam = (RooAbsReal*) giter.next())) {
     nom = (RooAbsReal*) niter.next() ;
     Double_t gamVal = gam->getVal() ;
     if (_relParam) gamVal *= nom->getVal() ;
     Double_t pois = TMath::Poisson(nom->getVal(),gamVal) ;
     prod *= pois ;
   }   
   return prod ;
 } 


Double_t RooHistConstraint::getLogVal(const RooArgSet* /*set*/) const 
{
   Double_t sum(0) ;
   RooFIter niter = _nominal.fwdIterator() ;
   RooFIter giter = _gamma.fwdIterator() ;
   RooAbsReal *gamv, *nomv ;
   while ((gamv = (RooAbsReal*) giter.next())) {
     nomv = (RooAbsReal*) niter.next() ;
     Double_t gam = gamv->getVal() ; 
     Int_t    nom = (Int_t) nomv->getVal() ;
     if (_relParam) gam *= nom ;
     if (gam>0) {       
       Double_t logPoisson = nom*log(gam) - gam - logSum(nom) ;          
       sum += logPoisson ;
     } else if (nom>0) {
       cout << "ERROR gam=0 and nom>0" << endl ;
     }
   }   
   return sum ;
}


Double_t RooHistConstraint::logSum(Int_t i) const
{
  static Double_t* _lut = 0 ;
  if (!_lut) {
    _lut = new Double_t[5000] ;
    for (Int_t ii=0 ; ii<5000 ; ii++) _lut[ii] = 0 ;

    for (Int_t j=1 ; j<=5000 ; j++) {
      Double_t logj = log((Double_t)j) ;
      for (Int_t ii=j ; ii<=5000 ; ii++) {
	_lut[ii-1] += logj ;	
      }
    }
  }

  if (i<5000) {    
    return _lut[i-1] ;
  } else {
    Double_t ret = _lut[4999] ;
    cout << "logSum i=" << i << endl ;
    for (Int_t j=5000 ; j<=i ; j++) {
      ret += log((Double_t)j) ;
    }
    return ret ;
  }
  
}

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