94 ClassImp(RooIntegralMorph);
102 RooIntegralMorph::RooIntegralMorph(
const char *name,
const char *title,
107 Bool_t doCacheAlpha) :
108 RooAbsCachedPdf(name,title,2),
109 pdf1(
"pdf1",
"pdf1",this,_pdf1),
110 pdf2(
"pdf2",
"pdf2",this,_pdf2),
112 alpha(
"alpha",
"alpha",this,_alpha),
113 _cacheAlpha(doCacheAlpha),
121 RooIntegralMorph::RooIntegralMorph(
const RooIntegralMorph& other,
const char* name) :
122 RooAbsCachedPdf(other,name),
123 pdf1(
"pdf1",this,other.pdf1),
124 pdf2(
"pdf2",this,other.pdf2),
126 alpha(
"alpha",this,other.alpha),
127 _cacheAlpha(other._cacheAlpha),
137 RooArgSet* RooIntegralMorph::actualObservables(
const RooArgSet& )
const
139 RooArgSet* obs =
new RooArgSet ;
141 obs->add(alpha.arg()) ;
151 RooArgSet* RooIntegralMorph::actualParameters(
const RooArgSet& )
const
153 RooArgSet* par1 = pdf1.arg().getParameters(RooArgSet()) ;
154 RooArgSet* par2 = pdf2.arg().getParameters(RooArgSet()) ;
155 par1->add(*par2,kTRUE) ;
156 par1->remove(x.arg(),kTRUE,kTRUE) ;
158 par1->add(alpha.arg()) ;
168 const char* RooIntegralMorph::inputBaseName()
const
170 static TString name ;
172 name = pdf1.arg().GetName() ;
173 name.Append(
"_MORPH_") ;
174 name.Append(pdf2.arg().GetName()) ;
181 void RooIntegralMorph::fillCacheObject(PdfCacheElem& cache)
const
183 MorphCacheElem& mcache =
static_cast<MorphCacheElem&
>(cache) ;
189 TIterator* dIter = cache.hist()->sliceIterator((RooAbsArg&)x.arg(),RooArgSet()) ;
190 mcache.calculate(dIter) ;
194 TIterator* slIter = cache.hist()->sliceIterator((RooAbsArg&)alpha.arg(),RooArgSet()) ;
196 Double_t alphaSave = alpha ;
197 RooArgSet alphaSet(alpha.arg()) ;
198 coutP(Eval) <<
"RooIntegralMorph::fillCacheObject(" << GetName() <<
") filling multi-dimensional cache" ;
199 while(slIter->Next()) {
200 alphaSet = (*cache.hist()->get()) ;
201 TIterator* dIter = cache.hist()->sliceIterator((RooAbsArg&)x.arg(),RooArgSet(alpha.arg())) ;
202 mcache.calculate(dIter) ;
203 ccoutP(Eval) <<
"." << flush;
206 ccoutP(Eval) << endl ;
209 const_cast<RooIntegralMorph*
>(
this)->alpha = alphaSave ;
216 RooAbsCachedPdf::PdfCacheElem* RooIntegralMorph::createCache(
const RooArgSet* nset)
const
218 return new MorphCacheElem(const_cast<RooIntegralMorph&>(*
this),nset) ;
224 RooArgList RooIntegralMorph::MorphCacheElem::containedArgs(Action action)
227 ret.add(PdfCacheElem::containedArgs(action)) ;
244 RooIntegralMorph::MorphCacheElem::MorphCacheElem(RooIntegralMorph&
self,
const RooArgSet* nsetIn) : PdfCacheElem(self,nsetIn)
247 _x = (RooRealVar*)
self.x.absArg() ;
248 _nset =
new RooArgSet(*_x) ;
250 _alpha = (RooAbsReal*)
self.alpha.absArg() ;
251 _pdf1 = (RooAbsPdf*)(
self.pdf1.absArg()) ;
252 _pdf2 = (RooAbsPdf*)(
self.pdf2.absArg()) ;
253 _c1 = _pdf1->createCdf(*_x);
254 _c2 = _pdf2->createCdf(*_x) ;
255 _cb1 = _c1->bindVars(*_x,_nset) ;
256 _cb2 = _c2->bindVars(*_x,_nset) ;
259 _rf1 =
new RooBrentRootFinder(*_cb1) ;
260 _rf2 =
new RooBrentRootFinder(*_cb2) ;
263 _rf1->setTol(1e-12) ;
264 _rf2->setTol(1e-12) ;
271 pdf()->setUnitNorm(kTRUE) ;
280 RooIntegralMorph::MorphCacheElem::~MorphCacheElem()
292 Double_t RooIntegralMorph::MorphCacheElem::calcX(Double_t y, Bool_t& ok)
295 oocoutW(_self,Eval) <<
"RooIntegralMorph::MorphCacheElem::calcX() WARNING: requested root finding for unphysical CDF value " << y << endl ;
299 Double_t xmax = _x->getMax(
"cache") ;
300 Double_t xmin = _x->getMin(
"cache") ;
303 ok &= _rf1->findRoot(x1,xmin,xmax,y) ;
304 ok &= _rf2->findRoot(x2,xmin,xmax,y) ;
308 return _alpha->getVal()*x1 + (1-_alpha->getVal())*x2 ;
314 Int_t RooIntegralMorph::MorphCacheElem::binX(Double_t X)
316 Double_t xmax = _x->getMax(
"cache") ;
317 Double_t xmin = _x->getMin(
"cache") ;
318 return (Int_t)(_x->numBins(
"cache")*(X-xmin)/(xmax-xmin)) ;
325 void RooIntegralMorph::MorphCacheElem::calculate(TIterator* dIter)
327 Double_t xsave = _self->x ;
334 _yatX.resize(_x->numBins(
"cache")+1);
335 _calcX.resize(_x->numBins(
"cache")+1);
337 RooArgSet nsetTmp(*_x) ;
341 Int_t nbins = _x->numBins(
"cache") ;
344 for (
int i=0 ; i<nbins ; i++) {
353 for (
int i=0 ; i<10 ; i++) {
356 Double_t offset = _yatX[_yatXmin] ;
357 Double_t delta = (_yatX[_yatXmax] - _yatX[_yatXmin])/10 ;
358 Double_t y = offset + i*delta ;
362 Double_t X = calcX(y,ok) ;
371 Int_t igapLow = _yatXmin+1 ;
374 Int_t igapHigh = igapLow+1 ;
375 while(igapHigh<(_yatXmax) && _yatX[igapHigh]<0) igapHigh++ ;
378 fillGap(igapLow-1,igapHigh) ;
381 if (igapHigh>=_yatXmax-1) break ;
382 igapLow = igapHigh+1 ;
386 Double_t xmax = _x->getMax(
"cache") ;
387 Double_t xmin = _x->getMin(
"cache") ;
388 Double_t binw = (xmax-xmin)/_x->numBins(
"cache") ;
389 for (
int i=_yatXmin+1 ; i<_yatXmax-1 ; i++) {
392 Double_t xBinC = xmin + (i+0.5)*binw ;
393 Double_t xOffset = xBinC-_calcX[i] ;
394 if (fabs(xOffset/binw)>1e-3) {
395 Double_t slope = (_yatX[i+1]-_yatX[i-1])/(_calcX[i+1]-_calcX[i-1]) ;
396 Double_t newY = _yatX[i] + slope*xOffset ;
403 for (
int i=0; i<_yatXmin ; i++) {
409 for (
int i=_yatXmin ; i<_yatXmax ; i++) {
411 Double_t y = _yatX[i] ;
415 Double_t xMin = _x->getMin(
"cache") ;
416 Double_t xMax = _x->getMax(
"cache") ;
417 _rf1->findRoot(x1,xMin,xMax,y) ;
418 _rf2->findRoot(x2,xMin,xMax,y) ;
420 _x->setVal(x1) ; Double_t f1x1 = _pdf1->getVal(&nsetTmp) ;
421 _x->setVal(x2) ; Double_t f2x2 = _pdf2->getVal(&nsetTmp) ;
422 Double_t fbarX = f1x1*f2x2 / ( _alpha->getVal()*f2x2 + (1-_alpha->getVal())*f1x1 ) ;
429 for (
int i=_yatXmax+1 ; i<nbins ; i++) {
435 pdf()->setUnitNorm(kTRUE) ;
438 oocxcoutD(_self,Eval) <<
"RooIntegralMorph::MorphCacheElem::calculate(" << _self->GetName() <<
") calculation required " << _ccounter <<
" samplings of cdfs" << endl ;
447 void RooIntegralMorph::MorphCacheElem::fillGap(Int_t ixlo, Int_t ixhi, Double_t splitPoint)
453 oocoutE(_self,Eval) <<
"RooIntegralMorph::MorphCacheElme::fillGap(" << _self->GetName() <<
"): ERROR in fillgap " << ixlo <<
" = " << ixhi
454 <<
" splitPoint= " << splitPoint <<
" _yatX[ixlo] = " << _yatX[ixlo] << endl ;
457 oocoutE(_self,Eval) <<
"RooIntegralMorph::MorphCacheElme::fillGap(" << _self->GetName() <<
"): ERROR in fillgap " << ixlo <<
" = " << ixhi
458 <<
" splitPoint " << splitPoint <<
" _yatX[ixhi] = " << _yatX[ixhi] << endl ;
462 Double_t ymid = _yatX[ixlo]*splitPoint + _yatX[ixhi]*(1-splitPoint) ;
464 Double_t Xmid = calcX(ymid,ok) ;
466 oocoutW(_self,Eval) <<
"RooIntegralMorph::MorphCacheElem::fillGap(" << _self->GetName() <<
") unable to calculate midpoint in gap ["
467 << ixlo <<
"," << ixhi <<
"], resorting to interpolation" << endl ;
468 interpolateGap(ixlo,ixhi) ;
471 Int_t iX = binX(Xmid) ;
472 Double_t cq = (Xmid-_calcX[ixlo])/(_calcX[ixhi]-_calcX[ixlo])-0.5 ;
480 if (fabs(cq)<0.01 || fabs(cq*(ixhi-ixlo))<0.1 || ymid<_ycutoff ) {
484 interpolateGap(ixlo,iX) ;
487 interpolateGap(iX,ixhi) ;
494 if (splitPoint<0.95) {
496 Double_t newSplit = splitPoint + 0.5*(1-splitPoint) ;
497 fillGap(ixlo,ixhi,newSplit) ;
500 interpolateGap(ixlo,ixhi) ;
503 }
else if (iX==ixhi) {
506 if (splitPoint>0.05) {
507 Double_t newSplit = splitPoint/2 ;
508 fillGap(ixlo,ixhi,newSplit) ;
511 interpolateGap(ixlo,ixhi) ;
531 void RooIntegralMorph::MorphCacheElem::interpolateGap(Int_t ixlo, Int_t ixhi)
535 Double_t xmax = _x->getMax(
"cache") ;
536 Double_t xmin = _x->getMin(
"cache") ;
537 Double_t binw = (xmax-xmin)/_x->numBins(
"cache") ;
540 Double_t deltaY = (_yatX[ixhi]-_yatX[ixlo])/((_calcX[ixhi]-_calcX[ixlo])/binw) ;
543 Double_t xBinC = xmin + (ixlo+0.5)*binw ;
544 Double_t xOffset = xBinC-_calcX[ixlo] ;
546 for (
int j=ixlo+1 ; j<ixhi ; j++) {
547 _yatX[j] = _yatX[ixlo]+(xOffset+(j-ixlo))*deltaY ;
548 _calcX[j] = xmin + (j+0.5)*binw ;
560 void RooIntegralMorph::MorphCacheElem::findRange()
562 Double_t xmin = _x->getMin(
"cache") ;
563 Double_t xmax = _x->getMax(
"cache") ;
564 Int_t nbins = _x->numBins(
"cache") ;
568 Double_t ymin=0.1,yminSave(-1) ;
569 Double_t Xsave(-1),Xlast=xmax ;
574 ok &= _rf1->findRoot(x1,xmin,xmax,ymin) ;
575 ok &= _rf2->findRoot(x2,xmin,xmax,ymin) ;
576 oocxcoutD(_self,Eval) <<
"RooIntegralMorph::MorphCacheElem::findRange(" << _self->GetName() <<
") findMin: x1 = " << x1 <<
" x2 = " << x2 <<
" ok = " << (ok?
"T":
"F") << endl ;
582 Double_t X = _alpha->getVal()*x1 + (1-_alpha->getVal())*x2 ;
583 if (fabs(X-Xlast)/(xmax-xmin)<0.0001) {
589 _yatXmin = (Int_t)(nbins*(X-xmin)/(xmax-xmin)) ;
590 _yatX[_yatXmin] = ymin ;
591 _calcX[_yatXmin] = X ;
599 if (ymin<_ycutoff) break ;
601 _yatX[_yatXmin] = yminSave ;
602 _calcX[_yatXmin] = Xsave ;
607 Double_t deltaymax=0.1, deltaymaxSave(-1) ;
610 ok &= _rf1->findRoot(x1,xmin,xmax,1-deltaymax) ;
611 ok &= _rf2->findRoot(x2,xmin,xmax,1-deltaymax) ;
613 oocxcoutD(_self,Eval) <<
"RooIntegralMorph::MorphCacheElem::findRange(" << _self->GetName() <<
") findMax: x1 = " << x1 <<
" x2 = " << x2 <<
" ok = " << (ok?
"T":
"F") << endl ;
619 Double_t X = _alpha->getVal()*x1 + (1-_alpha->getVal())*x2 ;
620 if (fabs(X-Xlast)/(xmax-xmin)<0.0001) {
626 _yatXmax = (Int_t)(nbins*(X-xmin)/(xmax-xmin)) ;
627 _yatX[_yatXmax] = 1-deltaymax ;
628 _calcX[_yatXmax] = X ;
629 deltaymaxSave = deltaymax ;
633 deltaymax /=sqrt(10.) ;
636 if (deltaymax<_ycutoff) break ;
639 _yatX[_yatXmax] = 1-deltaymaxSave ;
640 _calcX[_yatXmax] = Xsave ;
644 for (
int i=0 ; i<_yatXmin ; i++) _yatX[i] = -2 ;
645 for (
int i=_yatXmax+1 ; i<nbins; i++) _yatX[i] = -2 ;
646 oocxcoutD(_self,Eval) <<
"RooIntegralMorph::findRange(" << _self->GetName() <<
"): ymin = " << _yatX[_yatXmin] <<
" ymax = " << _yatX[_yatXmax] << endl;
647 oocxcoutD(_self,Eval) <<
"RooIntegralMorph::findRange(" << _self->GetName() <<
"): xmin = " << _calcX[_yatXmin] <<
" xmax = " << _calcX[_yatXmax] << endl;
653 Double_t RooIntegralMorph::evaluate()
const
663 void RooIntegralMorph::preferredObservableScanOrder(
const RooArgSet& obs, RooArgSet& orderedObs)
const
666 orderedObs.removeAll() ;
668 orderedObs.add(obs) ;
669 RooAbsArg* obsX = obs.find(x.arg().GetName()) ;
671 orderedObs.remove(*obsX) ;
672 orderedObs.add(*obsX) ;