// RooAddition calculates the sum of a set of RooAbsReal terms, or
// when constructed with two sets, it sums the product of the terms
// in the two sets. This class does not (yet) do any smart handling of integrals,
// i.e. all integrals of the product are handled numerically
// END_HTML
#include "RooFit.h"
#include "Riostream.h"
#include <math.h>
#include <memory>
#include "RooAddition.h"
#include "RooProduct.h"
#include "RooAbsReal.h"
#include "RooErrorHandler.h"
#include "RooArgSet.h"
#include "RooNameReg.h"
#include "RooNLLVar.h"
#include "RooChi2Var.h"
#include "RooMsgService.h"
ClassImp(RooAddition)
;
RooAddition::RooAddition()
: _setIter( _set.createIterator() )
{
}
RooAddition::RooAddition(const char* name, const char* title, const RooArgSet& sumSet, Bool_t takeOwnership)
: RooAbsReal(name, title)
, _set("!set","set of components",this)
, _setIter( _set.createIterator() )
, _cacheMgr(this,10)
{
std::auto_ptr<TIterator> inputIter( sumSet.createIterator() );
RooAbsArg* comp ;
while((comp = (RooAbsArg*)inputIter->Next())) {
if (!dynamic_cast<RooAbsReal*>(comp)) {
coutE(InputArguments) << "RooAddition::ctor(" << GetName() << ") ERROR: component " << comp->GetName()
<< " is not of type RooAbsReal" << endl ;
RooErrorHandler::softAbort() ;
}
_set.add(*comp) ;
if (takeOwnership) _ownedList.addOwned(*comp) ;
}
}
RooAddition::RooAddition(const char* name, const char* title, const RooArgList& sumSet1, const RooArgList& sumSet2, Bool_t takeOwnership)
: RooAbsReal(name, title)
, _set("!set","set of components",this)
, _setIter( _set.createIterator() )
, _cacheMgr(this,10)
{
if (sumSet1.getSize() != sumSet2.getSize()) {
coutE(InputArguments) << "RooAddition::ctor(" << GetName() << ") ERROR: input lists should be of equal length" << endl ;
RooErrorHandler::softAbort() ;
}
std::auto_ptr<TIterator> inputIter1( sumSet1.createIterator() );
std::auto_ptr<TIterator> inputIter2( sumSet2.createIterator() );
RooAbsArg *comp1(0),*comp2(0) ;
while((comp1 = (RooAbsArg*)inputIter1->Next())) {
if (!dynamic_cast<RooAbsReal*>(comp1)) {
coutE(InputArguments) << "RooAddition::ctor(" << GetName() << ") ERROR: component " << comp1->GetName()
<< " in first list is not of type RooAbsReal" << endl ;
RooErrorHandler::softAbort() ;
}
comp2 = (RooAbsArg*)inputIter2->Next();
if (!dynamic_cast<RooAbsReal*>(comp2)) {
coutE(InputArguments) << "RooAddition::ctor(" << GetName() << ") ERROR: component " << comp2->GetName()
<< " in first list is not of type RooAbsReal" << endl ;
RooErrorHandler::softAbort() ;
}
TString _name(name);
_name.Append( "_[");
_name.Append(comp1->GetName());
_name.Append( "_x_");
_name.Append(comp2->GetName());
_name.Append( "]");
RooProduct *prod = new RooProduct( _name, _name , RooArgSet(*comp1, *comp2) ) ;
_set.add(*prod);
_ownedList.addOwned(*prod) ;
if (takeOwnership) {
_ownedList.addOwned(*comp1) ;
_ownedList.addOwned(*comp2) ;
}
}
}
RooAddition::RooAddition(const RooAddition& other, const char* name)
: RooAbsReal(other, name)
, _set("!set",this,other._set)
, _setIter( _set.createIterator() )
, _cacheMgr(other._cacheMgr,this)
{
}
RooAddition::~RooAddition()
{
delete _setIter ;
}
Double_t RooAddition::evaluate() const
{
Double_t sum(0);
const RooArgSet* nset = _set.nset() ;
_setIter->Reset() ;
RooAbsReal* comp ;
while((comp=(RooAbsReal*)_setIter->Next())) {
sum += comp->getVal(nset) ;
}
return sum ;
}
Double_t RooAddition::defaultErrorLevel() const
{
RooAbsReal* nllArg(0) ;
RooAbsReal* chi2Arg(0) ;
RooAbsArg* arg ;
_setIter->Reset() ;
while((arg=(RooAbsArg*)_setIter->Next())) {
if (dynamic_cast<RooNLLVar*>(arg)) {
nllArg = (RooAbsReal*)arg ;
}
if (dynamic_cast<RooChi2Var*>(arg)) {
chi2Arg = (RooAbsReal*)arg ;
}
}
if (nllArg && !chi2Arg) {
coutI(Fitting) << "RooAddition::defaultErrorLevel(" << GetName()
<< ") Summation contains a RooNLLVar, using its error level" << endl ;
return nllArg->defaultErrorLevel() ;
} else if (chi2Arg && !nllArg) {
coutI(Fitting) << "RooAddition::defaultErrorLevel(" << GetName()
<< ") Summation contains a RooChi2Var, using its error level" << endl ;
return chi2Arg->defaultErrorLevel() ;
} else if (!nllArg && !chi2Arg) {
coutI(Fitting) << "RooAddition::defaultErrorLevel(" << GetName() << ") WARNING: "
<< "Summation contains neither RooNLLVar nor RooChi2Var server, using default level of 1.0" << endl ;
} else {
coutI(Fitting) << "RooAddition::defaultErrorLevel(" << GetName() << ") WARNING: "
<< "Summation contains BOTH RooNLLVar and RooChi2Var server, using default level of 1.0" << endl ;
}
return 1.0 ;
}
void RooAddition::printMetaArgs(ostream& os) const
{
_setIter->Reset() ;
Bool_t first(kTRUE) ;
RooAbsArg* arg;
while((arg=(RooAbsArg*)_setIter->Next())) {
if (!first) { os << " + " ;
} else { first = kFALSE ;
}
os << arg->GetName() ;
}
os << " " ;
}
Int_t RooAddition::getAnalyticalIntegral(RooArgSet& allVars, RooArgSet& analVars, const char* rangeName) const
{
analVars.add(allVars);
Int_t sterileIndex(-1);
CacheElem* cache = (CacheElem*) _cacheMgr.getObj(&analVars,&analVars,&sterileIndex,RooNameReg::ptr(rangeName));
if (cache!=0) {
Int_t code = _cacheMgr.lastIndex();
return code+1;
}
cache = new CacheElem;
_setIter->Reset();
RooAbsReal *arg(0);
while( (arg=(RooAbsReal*)_setIter->Next())!=0 ) {
RooAbsReal *I = arg->createIntegral(analVars,rangeName);
cache->_I.addOwned(*I);
}
Int_t code = _cacheMgr.setObj(&analVars,&analVars,(RooAbsCacheElement*)cache,RooNameReg::ptr(rangeName));
return 1+code;
}
Double_t RooAddition::analyticalIntegral(Int_t code, const char* rangeName) const
{
CacheElem *cache = (CacheElem*) _cacheMgr.getObjByIndex(code-1);
if (cache==0) {
std::auto_ptr<RooArgSet> vars( getParameters(RooArgSet()) );
std::auto_ptr<RooArgSet> iset( _cacheMgr.nameSet2ByIndex(code-1)->select(*vars) );
RooArgSet dummy;
Int_t code2 = getAnalyticalIntegral(*iset,dummy,rangeName);
assert(code==code2);
return analyticalIntegral(code2,rangeName);
}
assert(cache!=0);
std::auto_ptr<TIterator> iter( cache->_I.createIterator() );
RooAbsReal *I;
double result(0);
while ( ( I=(RooAbsReal*)iter->Next() ) != 0 ) result += I->getVal();
return result;
}
RooArgList RooAddition::CacheElem::containedArgs(Action)
{
RooArgList ret(_I) ;
return ret ;
}
RooAddition::CacheElem::~CacheElem()
{
}