#include "Riostream.h"
#include "RooLinearMorph.h"
#include "RooAbsReal.h"
#include "RooAbsCategory.h"
#include "RooBrentRootFinder.h"
#include "RooAbsFunc.h"
#include "RooRealVar.h"
#include "RooDataHist.h"
#include "TH1.h"
ClassImp(RooLinearMorph)
RooLinearMorph::RooLinearMorph(const char *name, const char *title,
RooAbsReal& _pdf1,
RooAbsReal& _pdf2,
RooAbsReal& _x,
RooAbsReal& _alpha,
Bool_t doCacheAlpha) :
RooAbsCachedPdf(name,title,2),
pdf1("pdf1","pdf1",this,_pdf1),
pdf2("pdf2","pdf2",this,_pdf2),
x("x","x",this,_x),
alpha("alpha","alpha",this,_alpha),
_cacheAlpha(doCacheAlpha),
_cache(0)
{
}
RooLinearMorph::RooLinearMorph(const RooLinearMorph& other, const char* name) :
RooAbsCachedPdf(other,name),
pdf1("pdf1",this,other.pdf1),
pdf2("pdf2",this,other.pdf2),
x("x",this,other.x),
alpha("alpha",this,other.alpha),
_cacheAlpha(other._cacheAlpha),
_cache(0)
{
}
RooArgSet* RooLinearMorph::actualObservables(const RooArgSet& ) const
{
RooArgSet* obs = new RooArgSet ;
if (_cacheAlpha) {
obs->add(alpha.arg()) ;
}
obs->add(x.arg()) ;
return obs ;
}
RooArgSet* RooLinearMorph::actualParameters(const RooArgSet& ) const
{
RooArgSet* par1 = pdf1.arg().getParameters(RooArgSet()) ;
RooArgSet* par2 = pdf2.arg().getParameters(RooArgSet()) ;
par1->add(*par2,kTRUE) ;
par1->remove(x.arg(),kTRUE,kTRUE) ;
if (!_cacheAlpha) {
par1->add(alpha.arg()) ;
}
delete par2 ;
return par1 ;
}
const char* RooLinearMorph::inputBaseName() const
{
static TString name ;
name = pdf1.arg().GetName() ;
name.Append("_MORPH_") ;
name.Append(pdf2.arg().GetName()) ;
return name.Data() ;
}
void RooLinearMorph::fillCacheObject(PdfCacheElem& cache) const
{
MorphCacheElem& mcache = static_cast<MorphCacheElem&>(cache) ;
if (!_cacheAlpha) {
TIterator* dIter = cache.hist()->sliceIterator((RooAbsArg&)x.arg(),RooArgSet()) ;
mcache.calculate(dIter) ;
delete dIter ;
} else {
TIterator* slIter = cache.hist()->sliceIterator((RooAbsArg&)alpha.arg(),RooArgSet()) ;
Double_t alphaSave = alpha ;
RooArgSet alphaSet(alpha.arg()) ;
coutP(Eval) << "RooLinearMorph::fillCacheObject(" << GetName() << ") filling multi-dimensional cache" ;
while(slIter->Next()) {
alphaSet = (*cache.hist()->get()) ;
TIterator* dIter = cache.hist()->sliceIterator((RooAbsArg&)x.arg(),RooArgSet(alpha.arg())) ;
mcache.calculate(dIter) ;
ccoutP(Eval) << "." << flush;
delete dIter ;
}
ccoutP(Eval) << endl ;
delete slIter ;
const_cast<RooLinearMorph*>(this)->alpha = alphaSave ;
}
}
RooAbsCachedPdf::PdfCacheElem* RooLinearMorph::createCache(const RooArgSet* nset) const
{
return new MorphCacheElem(const_cast<RooLinearMorph&>(*this),nset) ;
}
RooArgList RooLinearMorph::MorphCacheElem::containedArgs(Action action)
{
RooArgList ret ;
ret.add(PdfCacheElem::containedArgs(action)) ;
ret.add(*_self) ;
ret.add(*_pdf1) ;
ret.add(*_pdf2) ;
ret.add(*_x ) ;
ret.add(*_alpha) ;
ret.add(*_c1) ;
ret.add(*_c2) ;
return ret ;
}
RooLinearMorph::MorphCacheElem::MorphCacheElem(RooLinearMorph& self, const RooArgSet* nsetIn) : PdfCacheElem(self,nsetIn)
{
_x = (RooRealVar*)self.x.absArg() ;
_nset = new RooArgSet(*_x) ;
_alpha = (RooAbsReal*)self.alpha.absArg() ;
_pdf1 = (RooAbsPdf*)(self.pdf1.absArg()) ;
_pdf2 = (RooAbsPdf*)(self.pdf2.absArg()) ;
_c1 = _pdf1->createCdf(*_x);
_c2 = _pdf2->createCdf(*_x) ;
_cb1 = _c1->bindVars(*_x,_nset) ;
_cb2 = _c2->bindVars(*_x,_nset) ;
_self = &self ;
_rf1 = new RooBrentRootFinder(*_cb1) ;
_rf2 = new RooBrentRootFinder(*_cb2) ;
_ccounter = 0 ;
_rf1->setTol(1e-12) ;
_rf2->setTol(1e-12) ;
_ycutoff = 1e-7 ;
_yatX = 0 ;
_calcX = 0 ;
}
RooLinearMorph::MorphCacheElem::~MorphCacheElem()
{
delete[] _yatX ;
delete[] _calcX ;
}
Double_t RooLinearMorph::MorphCacheElem::calcX(Double_t y, Bool_t& ok)
{
if (y<0 || y>1) {
oocoutW(_self,Eval) << "RooLinearMorph::MorphCacheElem::calcX() WARNING: requested root finding for unphysical CDF value " << y << endl ;
}
Double_t x1,x2 ;
Double_t xmax = _x->getMax("cache") ;
Double_t xmin = _x->getMin("cache") ;
ok=kTRUE ;
ok &= _rf1->findRoot(x1,xmin,xmax,y) ;
ok &= _rf2->findRoot(x2,xmin,xmax,y) ;
if (!ok) return 0 ;
_ccounter++ ;
return _alpha->getVal()*x1 + (1-_alpha->getVal())*x2 ;
}
Int_t RooLinearMorph::MorphCacheElem::binX(Double_t X)
{
Double_t xmax = _x->getMax("cache") ;
Double_t xmin = _x->getMin("cache") ;
return (Int_t)(_x->numBins("cache")*(X-xmin)/(xmax-xmin)) ;
}
void RooLinearMorph::MorphCacheElem::calculate(TIterator* dIter)
{
Double_t xsave = _self->x ;
if (!_yatX) {
_yatX = new Double_t[_x->numBins("cache")+1] ;
_calcX = new Double_t[_x->numBins("cache")+1] ;
}
RooArgSet nsetTmp(*_x) ;
_ccounter = 0 ;
Int_t nbins = _x->numBins("cache") ;
for (int i=0 ; i<nbins ; i++) {
_yatX[i] = -1 ;
_calcX[i] = 0 ;
}
findRange() ;
for (int i=0 ; i<10 ; i++) {
Double_t offset = _yatX[_yatXmin] ;
Double_t delta = (_yatX[_yatXmax] - _yatX[_yatXmin])/10 ;
Double_t y = offset + i*delta ;
Bool_t ok ;
Double_t X = calcX(y,ok) ;
if (ok) {
Int_t iX = binX(X) ;
_yatX[iX] = y ;
_calcX[iX] = X ;
}
}
Int_t igapLow = _yatXmin+1 ;
while(true) {
Int_t igapHigh = igapLow+1 ;
while(_yatX[igapHigh]<0 && igapHigh<(_yatXmax)) igapHigh++ ;
fillGap(igapLow-1,igapHigh) ;
if (igapHigh>=_yatXmax-1) break ;
igapLow = igapHigh+1 ;
}
Double_t xmax = _x->getMax("cache") ;
Double_t xmin = _x->getMin("cache") ;
Double_t binw = (xmax-xmin)/_x->numBins("cache") ;
for (int i=_yatXmin+1 ; i<_yatXmax-1 ; i++) {
Double_t xBinC = xmin + (i+0.5)*binw ;
Double_t xOffset = xBinC-_calcX[i] ;
if (fabs(xOffset/binw)>1e-3) {
Double_t slope = (_yatX[i+1]-_yatX[i-1])/(_calcX[i+1]-_calcX[i-1]) ;
Double_t newY = _yatX[i] + slope*xOffset ;
_yatX[i] = newY ;
}
}
for (int i=0; i<_yatXmin ; i++) {
dIter->Next() ;
hist()->set(0) ;
}
for (int i=_yatXmin ; i<_yatXmax ; i++) {
Double_t y = _yatX[i] ;
Double_t x1,x2 ;
Double_t xMin = _x->getMin("cache") ;
Double_t xMax = _x->getMax("cache") ;
_rf1->findRoot(x1,xMin,xMax,y) ;
_rf2->findRoot(x2,xMin,xMax,y) ;
_x->setVal(x1) ; Double_t f1x1 = _pdf1->getVal(&nsetTmp) ;
_x->setVal(x2) ; Double_t f2x2 = _pdf2->getVal(&nsetTmp) ;
Double_t fbarX = f1x1*f2x2 / ( _alpha->getVal()*f2x2 + (1-_alpha->getVal())*f1x1 ) ;
dIter->Next() ;
hist()->set(fbarX) ;
}
for (int i=_yatXmax+1 ; i<nbins ; i++) {
dIter->Next() ;
hist()->set(0) ;
}
pdf()->setUnitNorm(kTRUE) ;
_self->x = xsave ;
oocxcoutD(_self,Eval) << "RooLinearMorph::MorphCacheElem::calculate(" << _self->GetName() << ") calculation required " << _ccounter << " samplings of cdfs" << endl ;
}
void RooLinearMorph::MorphCacheElem::fillGap(Int_t ixlo, Int_t ixhi, Double_t splitPoint)
{
if (_yatX[ixlo]<0) {
oocoutE(_self,Eval) << "RooLinearMorph::MorphCacheElme::fillGap(" << _self->GetName() << "): ERROR in fillgap " << ixlo << " = " << ixhi
<< " splitPoint= " << splitPoint << " _yatX[ixlo] = " << _yatX[ixlo] << endl ;
}
if (_yatX[ixhi]<0) {
oocoutE(_self,Eval) << "RooLinearMorph::MorphCacheElme::fillGap(" << _self->GetName() << "): ERROR in fillgap " << ixlo << " = " << ixhi
<< " splitPoint " << splitPoint << " _yatX[ixhi] = " << _yatX[ixhi] << endl ;
}
Double_t ymid = _yatX[ixlo]*splitPoint + _yatX[ixhi]*(1-splitPoint) ;
Bool_t ok ;
Double_t Xmid = calcX(ymid,ok) ;
if (!ok) {
oocoutW(_self,Eval) << "RooLinearMorph::MorphCacheElem::fillGap(" << _self->GetName() << ") unable to calculate midpoint in gap ["
<< ixlo << "," << ixhi << "], resorting to interpolation" << endl ;
interpolateGap(ixlo,ixhi) ;
}
Int_t iX = binX(Xmid) ;
Double_t cq = (Xmid-_calcX[ixlo])/(_calcX[ixhi]-_calcX[ixlo])-0.5 ;
_yatX[iX] = ymid ;
_calcX[iX] = Xmid ;
if (fabs(cq)<0.01 || fabs(cq*(ixhi-ixlo))<0.1 || ymid<_ycutoff ) {
if (iX-ixlo>1) {
interpolateGap(ixlo,iX) ;
}
if (ixhi-iX>1) {
interpolateGap(iX,ixhi) ;
}
} else {
if (iX==ixlo) {
if (splitPoint<0.95) {
Double_t newSplit = splitPoint + 0.5*(1-splitPoint) ;
fillGap(ixlo,ixhi,newSplit) ;
} else {
interpolateGap(ixlo,ixhi) ;
}
} else if (iX==ixhi) {
if (splitPoint>0.05) {
Double_t newSplit = splitPoint/2 ;
fillGap(ixlo,ixhi,newSplit) ;
} else {
interpolateGap(ixlo,ixhi) ;
}
} else {
if (iX-ixlo>1) {
fillGap(ixlo,iX) ;
}
if (ixhi-iX>1) {
fillGap(iX,ixhi) ;
}
}
}
}
void RooLinearMorph::MorphCacheElem::interpolateGap(Int_t ixlo, Int_t ixhi)
{
Double_t xmax = _x->getMax("cache") ;
Double_t xmin = _x->getMin("cache") ;
Double_t binw = (xmax-xmin)/_x->numBins("cache") ;
Double_t deltaY = (_yatX[ixhi]-_yatX[ixlo])/((_calcX[ixhi]-_calcX[ixlo])/binw) ;
Double_t xBinC = xmin + (ixlo+0.5)*binw ;
Double_t xOffset = xBinC-_calcX[ixlo] ;
for (int j=ixlo+1 ; j<ixhi ; j++) {
_yatX[j] = _yatX[ixlo]+(xOffset+(j-ixlo))*deltaY ;
_calcX[j] = xmin + (j+0.5)*binw ;
}
}
void RooLinearMorph::MorphCacheElem::findRange()
{
Double_t xmin = _x->getMin("cache") ;
Double_t xmax = _x->getMax("cache") ;
Int_t nbins = _x->numBins("cache") ;
Double_t x1,x2 ;
Bool_t ok = kTRUE ;
Double_t ymin=0.1,yminSave(-1) ;
Double_t Xsave(-1),Xlast=xmax ;
while(true) {
ok &= _rf1->findRoot(x1,xmin,xmax,ymin) ;
ok &= _rf2->findRoot(x2,xmin,xmax,ymin) ;
oocxcoutD(_self,Eval) << "RooLinearMorph::MorphCacheElem::findRange(" << _self->GetName() << ") findMin: x1 = " << x1 << " x2 = " << x2 << " ok = " << (ok?"T":"F") << endl ;
if (!ok) break ;
Double_t X = _alpha->getVal()*x1 + (1-_alpha->getVal())*x2 ;
if (fabs(X-Xlast)/(xmax-xmin)<0.0001) {
break ;
}
Xlast=X ;
_yatXmin = (Int_t)(nbins*(X-xmin)/(xmax-xmin)) ;
_yatX[_yatXmin] = ymin ;
_calcX[_yatXmin] = X ;
yminSave = ymin ;
Xsave=X ;
ymin /=sqrt(10.) ;
if (ymin<_ycutoff) break ;
}
_yatX[_yatXmin] = yminSave ;
_calcX[_yatXmin] = Xsave ;
ok = kTRUE ;
Double_t deltaymax=0.1, deltaymaxSave(-1) ;
Xlast=xmin ;
while(true) {
ok &= _rf1->findRoot(x1,xmin,xmax,1-deltaymax) ;
ok &= _rf2->findRoot(x2,xmin,xmax,1-deltaymax) ;
oocxcoutD(_self,Eval) << "RooLinearMorph::MorphCacheElem::findRange(" << _self->GetName() << ") findMax: x1 = " << x1 << " x2 = " << x2 << " ok = " << (ok?"T":"F") << endl ;
if (!ok) break ;
Double_t X = _alpha->getVal()*x1 + (1-_alpha->getVal())*x2 ;
if (fabs(X-Xlast)/(xmax-xmin)<0.0001) {
break ;
}
Xlast=X ;
_yatXmax = (Int_t)(nbins*(X-xmin)/(xmax-xmin)) ;
_yatX[_yatXmax] = 1-deltaymax ;
_calcX[_yatXmax] = X ;
deltaymaxSave = deltaymax ;
Xsave=X ;
deltaymax /=sqrt(10.) ;
if (deltaymax<_ycutoff) break ;
}
_yatX[_yatXmax] = 1-deltaymaxSave ;
_calcX[_yatXmax] = Xsave ;
for (int i=0 ; i<_yatXmin ; i++) _yatX[i] = -2 ;
for (int i=_yatXmax+1 ; i<nbins; i++) _yatX[i] = -2 ;
oocxcoutD(_self,Eval) << "RooLinearMorph::findRange(" << _self->GetName() << "): ymin = " << _yatX[_yatXmin] << " ymax = " << _yatX[_yatXmax] << endl;
oocxcoutD(_self,Eval) << "RooLinearMorph::findRange(" << _self->GetName() << "): xmin = " << _calcX[_yatXmin] << " xmax = " << _calcX[_yatXmax] << endl;
}
Double_t RooLinearMorph::evaluate() const
{
return 0 ;
}
void RooLinearMorph::preferredObservableScanOrder(const RooArgSet& obs, RooArgSet& orderedObs) const
{
orderedObs.removeAll() ;
orderedObs.add(obs) ;
RooAbsArg* obsX = obs.find(x.arg().GetName()) ;
if (obsX) {
orderedObs.remove(*obsX) ;
orderedObs.add(*obsX) ;
}
}
Last change: Wed Jun 25 08:33:19 2008
Last generated: 2008-06-25 08:33
This page has been automatically generated. If you have any comments or suggestions about the page layout send a mail to ROOT support, or contact the developers with any questions or problems regarding ROOT.