/*****************************************************************************
 * Project: RooFit                                                           *
 * Package: RooFitCore                                                       *
 * @(#)root/roofitcore:$Id$
 * Author:                                                                   *
 * Tristan du Pree, Nikhef, Amsterdam, tdupree@nikhef.nl                     * 
 *                                                                           *
 * 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
// RooMultiBinomial is an efficiency function which makes all combinations of 
// efficiencies given as input different effiency functions for different categories.
// 
// Given a dataset with a category C that determines if a given
// event is accepted (1) or rejected (0) for the efficiency to be measured,
// this class evaluates as F if C is 'accept' and as (1-F) if
// C is 'reject'. Values of F below 0 and above 1 are clipped.
// F may have an arbitrary number of dependents and parameters
//
// The combination only 'reject' can be chosen to be visible or not visible
// (and hence this efficiency is then equal to zero).
// END_HTML
//

#include "RooFit.h"

#include "RooMultiBinomial.h"
#include "RooStreamParser.h"
#include "RooArgList.h"
#include "RooAbsCategory.h"
#include "RooMsgService.h"
#include <string>
#include <vector>

using namespace std ;

ClassImp(RooMultiBinomial)
  ;


//_____________________________________________________________________________
RooMultiBinomial::RooMultiBinomial(const char *name, const char *title, 
				   const RooArgList& effFuncList, 
				   const RooArgList& catList,
				   Bool_t ignoreNonVisible) :
  RooAbsReal(name,title),
  _catList("catList","list of cats", this),
  _effFuncList("effFuncList","list of eff funcs",this),
  _ignoreNonVisible(ignoreNonVisible)
{  
  // Construct the efficiency functions from a list of efficiency functions
  // and a list of categories cat with two states (0,1) that indicate if a given
  // event should be counted as rejected or accepted respectively

  _catList.add(catList);
  _effFuncList.add(effFuncList);

  if (_catList.getSize() != effFuncList.getSize()) {
    coutE(InputArguments) << "RooMultiBinomial::ctor(" << GetName() << ") ERROR: Wrong input, should have equal number of categories and efficiencies." << endl;
    throw string("RooMultiBinomial::ctor() ERROR: Wrong input, should have equal number of categories and efficiencies") ;
  }

}



//_____________________________________________________________________________
RooMultiBinomial::RooMultiBinomial(const RooMultiBinomial& other, const char* name) : 
  RooAbsReal(other, name),
  _catList("catList",this,other._catList),
  _effFuncList("effFuncList",this,other._effFuncList),
  _ignoreNonVisible(other._ignoreNonVisible)
{
  // Copy constructor
}



//_____________________________________________________________________________
RooMultiBinomial::~RooMultiBinomial() 
{
  // Destructor
}



//_____________________________________________________________________________
Double_t RooMultiBinomial::evaluate() const
{
  // Calculate the raw value of the function which is the effFunc
  // value if cat==1 and it is (1-effFunc) if cat==0

  Int_t effFuncListSize = _effFuncList.getSize();

  // Get efficiency function for category i

  vector<Double_t> effFuncVal(effFuncListSize);
  for (int i=0; i<effFuncListSize; ++i) {
    effFuncVal[i] = ((RooAbsReal&)_effFuncList[i]).getVal() ;
  }

  // Truncate efficiency functions in range 0.0-1.0

  for (int i=0; i<effFuncListSize; ++i) {
    if (effFuncVal[i]>1) {
      coutW(Eval) << "WARNING: Efficency >1 (equal to " << effFuncVal[i] 
		  << " ), for i = " << i << "...TRUNCATED" << endl;
      effFuncVal[i] = 1.0 ;
    } else if (effFuncVal[i]<0) {
      effFuncVal[i] = 0.0 ;
      coutW(Eval) << "WARNING: Efficency <0 (equal to " << effFuncVal[i] 
		  << " ), for i = " << i << "...TRUNCATED" << endl;
    }
  }

  vector<Double_t> effValue(effFuncListSize);
  Bool_t notVisible = true;

  // Calculate efficiency per accept/reject decision

  for (int i=0; i<effFuncListSize; ++i) {
    if ( ((RooAbsCategory&)_catList[i]).getIndex() == 1) {
      // Accept case
      effValue[i] = effFuncVal[i] ;
      notVisible = false;
    } else if ( ((RooAbsCategory&)_catList[i]).getIndex() == 0){
      // Reject case
      effValue[i] = 1 - effFuncVal[i] ;
    } else {
      coutW(Eval) << "WARNING: WRONG CATEGORY NAMES GIVEN!, label = " << ((RooAbsCategory&)_catList[i]).getIndex() << endl;
      effValue[i] = 0;
    }
  }

  Double_t _effVal = 1.;

  // Calculate efficiency for combination of accept/reject categories
  // put equal to zero if combination of only zeros AND chosen to be invisible

  for (int i=0; i<effFuncListSize; ++i) {
    _effVal=_effVal*effValue[i];
    if (notVisible && _ignoreNonVisible){
      _effVal=0;
    }
  }

  return _effVal;

}



 RooMultiBinomial.cxx:1
 RooMultiBinomial.cxx:2
 RooMultiBinomial.cxx:3
 RooMultiBinomial.cxx:4
 RooMultiBinomial.cxx:5
 RooMultiBinomial.cxx:6
 RooMultiBinomial.cxx:7
 RooMultiBinomial.cxx:8
 RooMultiBinomial.cxx:9
 RooMultiBinomial.cxx:10
 RooMultiBinomial.cxx:11
 RooMultiBinomial.cxx:12
 RooMultiBinomial.cxx:13
 RooMultiBinomial.cxx:14
 RooMultiBinomial.cxx:15
 RooMultiBinomial.cxx:16
 RooMultiBinomial.cxx:17
 RooMultiBinomial.cxx:18
 RooMultiBinomial.cxx:19
 RooMultiBinomial.cxx:20
 RooMultiBinomial.cxx:21
 RooMultiBinomial.cxx:22
 RooMultiBinomial.cxx:23
 RooMultiBinomial.cxx:24
 RooMultiBinomial.cxx:25
 RooMultiBinomial.cxx:26
 RooMultiBinomial.cxx:27
 RooMultiBinomial.cxx:28
 RooMultiBinomial.cxx:29
 RooMultiBinomial.cxx:30
 RooMultiBinomial.cxx:31
 RooMultiBinomial.cxx:32
 RooMultiBinomial.cxx:33
 RooMultiBinomial.cxx:34
 RooMultiBinomial.cxx:35
 RooMultiBinomial.cxx:36
 RooMultiBinomial.cxx:37
 RooMultiBinomial.cxx:38
 RooMultiBinomial.cxx:39
 RooMultiBinomial.cxx:40
 RooMultiBinomial.cxx:41
 RooMultiBinomial.cxx:42
 RooMultiBinomial.cxx:43
 RooMultiBinomial.cxx:44
 RooMultiBinomial.cxx:45
 RooMultiBinomial.cxx:46
 RooMultiBinomial.cxx:47
 RooMultiBinomial.cxx:48
 RooMultiBinomial.cxx:49
 RooMultiBinomial.cxx:50
 RooMultiBinomial.cxx:51
 RooMultiBinomial.cxx:52
 RooMultiBinomial.cxx:53
 RooMultiBinomial.cxx:54
 RooMultiBinomial.cxx:55
 RooMultiBinomial.cxx:56
 RooMultiBinomial.cxx:57
 RooMultiBinomial.cxx:58
 RooMultiBinomial.cxx:59
 RooMultiBinomial.cxx:60
 RooMultiBinomial.cxx:61
 RooMultiBinomial.cxx:62
 RooMultiBinomial.cxx:63
 RooMultiBinomial.cxx:64
 RooMultiBinomial.cxx:65
 RooMultiBinomial.cxx:66
 RooMultiBinomial.cxx:67
 RooMultiBinomial.cxx:68
 RooMultiBinomial.cxx:69
 RooMultiBinomial.cxx:70
 RooMultiBinomial.cxx:71
 RooMultiBinomial.cxx:72
 RooMultiBinomial.cxx:73
 RooMultiBinomial.cxx:74
 RooMultiBinomial.cxx:75
 RooMultiBinomial.cxx:76
 RooMultiBinomial.cxx:77
 RooMultiBinomial.cxx:78
 RooMultiBinomial.cxx:79
 RooMultiBinomial.cxx:80
 RooMultiBinomial.cxx:81
 RooMultiBinomial.cxx:82
 RooMultiBinomial.cxx:83
 RooMultiBinomial.cxx:84
 RooMultiBinomial.cxx:85
 RooMultiBinomial.cxx:86
 RooMultiBinomial.cxx:87
 RooMultiBinomial.cxx:88
 RooMultiBinomial.cxx:89
 RooMultiBinomial.cxx:90
 RooMultiBinomial.cxx:91
 RooMultiBinomial.cxx:92
 RooMultiBinomial.cxx:93
 RooMultiBinomial.cxx:94
 RooMultiBinomial.cxx:95
 RooMultiBinomial.cxx:96
 RooMultiBinomial.cxx:97
 RooMultiBinomial.cxx:98
 RooMultiBinomial.cxx:99
 RooMultiBinomial.cxx:100
 RooMultiBinomial.cxx:101
 RooMultiBinomial.cxx:102
 RooMultiBinomial.cxx:103
 RooMultiBinomial.cxx:104
 RooMultiBinomial.cxx:105
 RooMultiBinomial.cxx:106
 RooMultiBinomial.cxx:107
 RooMultiBinomial.cxx:108
 RooMultiBinomial.cxx:109
 RooMultiBinomial.cxx:110
 RooMultiBinomial.cxx:111
 RooMultiBinomial.cxx:112
 RooMultiBinomial.cxx:113
 RooMultiBinomial.cxx:114
 RooMultiBinomial.cxx:115
 RooMultiBinomial.cxx:116
 RooMultiBinomial.cxx:117
 RooMultiBinomial.cxx:118
 RooMultiBinomial.cxx:119
 RooMultiBinomial.cxx:120
 RooMultiBinomial.cxx:121
 RooMultiBinomial.cxx:122
 RooMultiBinomial.cxx:123
 RooMultiBinomial.cxx:124
 RooMultiBinomial.cxx:125
 RooMultiBinomial.cxx:126
 RooMultiBinomial.cxx:127
 RooMultiBinomial.cxx:128
 RooMultiBinomial.cxx:129
 RooMultiBinomial.cxx:130
 RooMultiBinomial.cxx:131
 RooMultiBinomial.cxx:132
 RooMultiBinomial.cxx:133
 RooMultiBinomial.cxx:134
 RooMultiBinomial.cxx:135
 RooMultiBinomial.cxx:136
 RooMultiBinomial.cxx:137
 RooMultiBinomial.cxx:138
 RooMultiBinomial.cxx:139
 RooMultiBinomial.cxx:140
 RooMultiBinomial.cxx:141
 RooMultiBinomial.cxx:142
 RooMultiBinomial.cxx:143
 RooMultiBinomial.cxx:144
 RooMultiBinomial.cxx:145
 RooMultiBinomial.cxx:146
 RooMultiBinomial.cxx:147
 RooMultiBinomial.cxx:148
 RooMultiBinomial.cxx:149
 RooMultiBinomial.cxx:150
 RooMultiBinomial.cxx:151
 RooMultiBinomial.cxx:152
 RooMultiBinomial.cxx:153
 RooMultiBinomial.cxx:154
 RooMultiBinomial.cxx:155
 RooMultiBinomial.cxx:156
 RooMultiBinomial.cxx:157
 RooMultiBinomial.cxx:158