91 using std::flush, std::endl;
108 pdf1(
"pdf1",
"pdf1",this,_pdf1),
109 pdf2(
"pdf2",
"pdf2",this,_pdf2),
111 alpha(
"alpha",
"alpha",this,_alpha),
112 _cacheAlpha(doCacheAlpha)
121 pdf1(
"pdf1",this,other.pdf1),
122 pdf2(
"pdf2",this,other.pdf2),
124 alpha(
"alpha",this,other.alpha),
125 _cacheAlpha(other._cacheAlpha)
150 std::unique_ptr<RooArgSet> par1{
pdf1->getParameters(
static_cast<RooArgSet*
>(
nullptr))};
152 pdf2->getParameters(
nullptr, par2);
153 par1->add(par2,
true) ;
154 par1->remove(
x.arg(),
true,
true) ;
156 par1->add(
alpha.arg()) ;
170 name.Append(
"_MORPH_") ;
192 double alphaSave =
alpha ;
194 coutP(Eval) <<
"RooIntegralMorph::fillCacheObject(" <<
GetName() <<
") filling multi-dimensional cache" ;
195 while(slIter->Next()) {
199 ccoutP(Eval) <<
"." << flush;
201 ccoutP(Eval) << std::endl;
221 ret.
add(PdfCacheElem::containedArgs(action)) ;
252 _nset = std::make_unique<RooArgSet>(*
_x);
256 _cb1 = std::unique_ptr<RooAbsFunc>{
_c1->bindVars(*
_x,
_nset.get())};
257 _cb2 = std::unique_ptr<RooAbsFunc>{
_c2->bindVars(*
_x,
_nset.get())};
259 _rf1 = std::make_unique<RooBrentRootFinder>(*
_cb1);
260 _rf2 = std::make_unique<RooBrentRootFinder>(*
_cb2);
262 _rf1->setTol(1
e-12) ;
263 _rf2->setTol(1
e-12) ;
286 oocoutW(_self,Eval) <<
"RooIntegralMorph::MorphCacheElem::calcX() WARNING: requested root finding for unphysical CDF value " <<
y << endl ;
291 double xmax = _x->getMax(
"cache") ;
292 double xmin = _x->getMin(
"cache") ;
300 return _alpha->getVal()*
x1 + (1-_alpha->getVal())*
x2 ;
308 double xmax = _x->getMax(
"cache") ;
309 double xmin = _x->getMin(
"cache") ;
319 double xsave = _self->x ;
326 _yatX.resize(_x->numBins(
"cache")+1);
327 _calcX.resize(_x->numBins(
"cache")+1);
332 Int_t nbins = _x->numBins(
"cache") ;
335 for (
int i=0 ; i<nbins ; i++) {
344 for (
int i=0 ; i<10 ; i++) {
347 double offset = _yatX[_yatXmin] ;
348 double delta = (_yatX[_yatXmax] - _yatX[_yatXmin])/10 ;
353 double X = calcX(
y,ok) ;
362 Int_t igapLow = _yatXmin+1 ;
365 Int_t igapHigh = igapLow+1 ;
366 while(igapHigh<(_yatXmax) && _yatX[igapHigh]<0) igapHigh++ ;
369 fillGap(igapLow-1,igapHigh) ;
372 if (igapHigh>=_yatXmax-1) break ;
373 igapLow = igapHigh+1 ;
377 double xmax = _x->getMax(
"cache") ;
378 double xmin = _x->getMin(
"cache") ;
379 double binw = (
xmax-
xmin)/_x->numBins(
"cache") ;
380 for (
int i=_yatXmin+1 ; i<_yatXmax-1 ; i++) {
383 double xBinC =
xmin + (i+0.5)*binw ;
384 double xOffset = xBinC-_calcX[i] ;
385 if (std::abs(xOffset/binw)>1
e-3) {
386 double slope = (_yatX[i+1]-_yatX[i-1])/(_calcX[i+1]-_calcX[i-1]) ;
387 double newY = _yatX[i] + slope*xOffset ;
394 for (
int i=0; i<_yatXmin ; i++) {
400 double x1 = _x->getMin(
"cache");
401 double x2 = _x->getMin(
"cache");
403 double xMax = _x->getMax(
"cache");
406 for (
int i=_yatXmin ; i<_yatXmax ; i++) {
408 double y = _yatX[i] ;
414 _rf1->findRoot(
x1,
x1,xMax,
y) ;
415 _rf2->findRoot(
x2,
x2,xMax,
y) ;
418 double f1x1 = _pdf1->getVal(_nset.get());
420 double f2x2 = _pdf2->getVal(_nset.get());
421 double fbarX = f1x1*f2x2 / ( _alpha->getVal()*f2x2 + (1-_alpha->getVal())*f1x1 ) ;
428 for (
int i=_yatXmax+1 ; i<nbins ; i++) {
434 pdf()->setUnitNorm(
true) ;
437 oocxcoutD(_self,Eval) <<
"RooIntegralMorph::MorphCacheElem::calculate(" << _self->GetName() <<
") calculation required " << _ccounter <<
" samplings of cdfs" << endl ;
452 oocoutE(_self,Eval) <<
"RooIntegralMorph::MorphCacheElme::fillGap(" << _self->GetName() <<
"): ERROR in fillgap " << ixlo <<
" = " << ixhi
453 <<
" splitPoint= " << splitPoint <<
" _yatX[ixlo] = " << _yatX[ixlo] << endl ;
456 oocoutE(_self,Eval) <<
"RooIntegralMorph::MorphCacheElme::fillGap(" << _self->GetName() <<
"): ERROR in fillgap " << ixlo <<
" = " << ixhi
457 <<
" splitPoint " << splitPoint <<
" _yatX[ixhi] = " << _yatX[ixhi] << endl ;
461 double ymid = _yatX[ixlo]*splitPoint + _yatX[ixhi]*(1-splitPoint) ;
463 double Xmid = calcX(ymid,ok) ;
465 oocoutW(_self,Eval) <<
"RooIntegralMorph::MorphCacheElem::fillGap(" << _self->GetName() <<
") unable to calculate midpoint in gap ["
466 << ixlo <<
"," << ixhi <<
"], resorting to interpolation" << endl ;
467 interpolateGap(ixlo,ixhi) ;
470 Int_t iX = binX(Xmid) ;
471 double cq = (Xmid-_calcX[ixlo])/(_calcX[ixhi]-_calcX[ixlo])-0.5 ;
479 if (std::abs(cq)<0.01 || std::abs(cq*(ixhi-ixlo))<0.1 || ymid<_ycutoff ) {
483 interpolateGap(ixlo,iX) ;
486 interpolateGap(iX,ixhi) ;
493 if (splitPoint<0.95) {
495 double newSplit = splitPoint + 0.5*(1-splitPoint) ;
496 fillGap(ixlo,ixhi,newSplit) ;
499 interpolateGap(ixlo,ixhi) ;
502 }
else if (iX==ixhi) {
505 if (splitPoint>0.05) {
506 double newSplit = splitPoint/2 ;
507 fillGap(ixlo,ixhi,newSplit) ;
510 interpolateGap(ixlo,ixhi) ;
534 double xmax = _x->getMax(
"cache") ;
535 double xmin = _x->getMin(
"cache") ;
536 double binw = (
xmax-
xmin)/_x->numBins(
"cache") ;
539 double deltaY = (_yatX[ixhi]-_yatX[ixlo])/((_calcX[ixhi]-_calcX[ixlo])/binw) ;
542 double xBinC =
xmin + (ixlo+0.5)*binw ;
543 double xOffset = xBinC-_calcX[ixlo] ;
545 for (
int j=ixlo+1 ; j<ixhi ; j++) {
546 _yatX[j] = _yatX[ixlo]+(xOffset+(j-ixlo))*deltaY ;
547 _calcX[j] =
xmin + (j+0.5)*binw ;
561 double xmin = _x->getMin(
"cache") ;
562 double xmax = _x->getMax(
"cache") ;
563 Int_t nbins = _x->numBins(
"cache") ;
578 oocxcoutD(_self,Eval) <<
"RooIntegralMorph::MorphCacheElem::findRange(" << _self->GetName() <<
") findMin: x1 = " <<
x1 <<
" x2 = " <<
x2 <<
" ok = " << (ok?
"T":
"F") << endl ;
584 double X = _alpha->getVal()*
x1 + (1-_alpha->getVal())*
x2 ;
585 if (std::abs(
X-Xlast)/(
xmax-
xmin)<0.0001) {
592 _yatX[_yatXmin] =
ymin ;
593 _calcX[_yatXmin] =
X ;
601 if (
ymin<_ycutoff) break ;
603 _yatX[_yatXmin] = yminSave ;
604 _calcX[_yatXmin] = Xsave ;
609 double deltaymax = 0.1;
610 double deltaymaxSave(-1);
613 ok &= _rf1->findRoot(
x1,
xmin,
xmax,1-deltaymax) ;
614 ok &= _rf2->findRoot(
x2,
xmin,
xmax,1-deltaymax) ;
616 oocxcoutD(_self,Eval) <<
"RooIntegralMorph::MorphCacheElem::findRange(" << _self->GetName() <<
") findMax: x1 = " <<
x1 <<
" x2 = " <<
x2 <<
" ok = " << (ok?
"T":
"F") << endl ;
622 double X = _alpha->getVal()*
x1 + (1-_alpha->getVal())*
x2 ;
623 if (std::abs(
X-Xlast)/(
xmax-
xmin)<0.0001) {
630 _yatX[_yatXmax] = 1-deltaymax ;
631 _calcX[_yatXmax] =
X ;
632 deltaymaxSave = deltaymax ;
636 deltaymax /=sqrt(10.) ;
639 if (deltaymax<_ycutoff) break ;
642 _yatX[_yatXmax] = 1-deltaymaxSave ;
643 _calcX[_yatXmax] = Xsave ;
647 for (
int i=0 ; i<_yatXmin ; i++) _yatX[i] = -2 ;
648 for (
int i=_yatXmax+1 ; i<nbins; i++) _yatX[i] = -2 ;
649 oocxcoutD(_self,Eval) <<
"RooIntegralMorph::findRange(" << _self->GetName() <<
"): ymin = " << _yatX[_yatXmin] <<
" ymax = " << _yatX[_yatXmax] << endl;
650 oocxcoutD(_self,Eval) <<
"RooIntegralMorph::findRange(" << _self->GetName() <<
"): xmin = " << _calcX[_yatXmin] <<
" xmax = " << _calcX[_yatXmax] << endl;
671 orderedObs.
add(obs) ;
674 orderedObs.
remove(*obsX) ;
675 orderedObs.
add(*obsX) ;
Option_t Option_t TPoint TPoint const char x2
Option_t Option_t TPoint TPoint const char x1
Common abstract base class for objects that represent a value and a "shape" in RooFit.
Abstract base class for p.d.f.s that need or want to cache their evaluate() output in a RooHistPdf de...
virtual void removeAll()
Remove all arguments from our set, deleting them if we own them.
virtual bool remove(const RooAbsArg &var, bool silent=false, bool matchByNameOnly=false)
Remove the specified argument from our list.
virtual bool add(const RooAbsArg &var, bool silent=false)
Add the specified argument to list.
void assign(const RooAbsCollection &other) const
Sets the value, cache and constant attribute of any argument in our set that also appears in the othe...
RooAbsArg * find(const char *name) const
Find object with given name in list.
Abstract interface for all probability density functions.
RooFit::OwningPtr< RooAbsReal > createCdf(const RooArgSet &iset, const RooArgSet &nset=RooArgSet())
Create a cumulative distribution function of this p.d.f in terms of the observables listed in iset.
Abstract base class for objects that represent a real value and implements functionality common to al...
virtual double offset() const
RooArgList is a container object that can hold multiple RooAbsArg objects.
RooArgSet is a container object that can hold multiple RooAbsArg objects.
TIterator * sliceIterator(RooAbsArg &sliceArg, const RooArgSet &otherArgs)
Create an iterator over all bins in a slice defined by the subset of observables listed in sliceArg.
const RooArgSet * get() const override
Get bin centre of current bin.
void setUnitNorm(bool flag)
~MorphCacheElem() override
Destructor.
std::unique_ptr< RooBrentRootFinder > _rf1
std::unique_ptr< RooAbsReal > _c1
void calculate(TIterator *iter)
Calculate shape of p.d.f for x,alpha values defined by dIter iterator over cache histogram.
void interpolateGap(Int_t ixlo, Int_t ixhi)
Fill empty histogram bins between ixlo and ixhi with values obtained from linear interpolation of ixl...
MorphCacheElem(RooIntegralMorph &self, const RooArgSet *nset)
Construct of cache element, copy relevant input from RooIntegralMorph, create the cdfs from the input...
std::unique_ptr< RooAbsFunc > _cb2
void fillGap(Int_t ixlo, Int_t ixhi, double splitPoint=0.5)
Fill all empty histogram bins between bins ixlo and ixhi.
std::unique_ptr< RooArgSet > _nset
void findRange()
Determine which range of y values can be mapped to x values from the numeric inversion of the input c...
std::unique_ptr< RooAbsFunc > _cb1
std::unique_ptr< RooBrentRootFinder > _rf2
RooArgList containedArgs(Action) override
Return all RooAbsArg components contained in this cache.
std::unique_ptr< RooAbsReal > _c2
double calcX(double y, bool &ok)
Calculate the x value of the output p.d.f at the given cdf value y.
Int_t binX(double x)
Return the bin number enclosing the given x value.
Class RooIntegralMorph is an implementation of the histogram interpolation technique described by Ale...
RooIntegralMorph()=default
RooFit::OwningPtr< RooArgSet > actualObservables(const RooArgSet &nset) const override
Observable to be cached for given choice of normalization.
PdfCacheElem * createCache(const RooArgSet *nset) const override
Create and return a derived MorphCacheElem.
const char * inputBaseName() const override
Return base name component for cache components in this case a string encoding the names of both end ...
void preferredObservableScanOrder(const RooArgSet &obs, RooArgSet &orderedObs) const override
Indicate to the RooAbsCachedPdf base class that for the filling of the cache the traversal of the x s...
void fillCacheObject(PdfCacheElem &cache) const override
Fill the cache with the interpolated shape.
double evaluate() const override
Dummy.
RooFit::OwningPtr< RooArgSet > actualParameters(const RooArgSet &nset) const override
Parameters of the cache.
Variable that can be changed from the outside.
Iterator abstract base class.
virtual TObject * Next()=0
const char * GetName() const override
Returns name of object.
OwningPtr< T > makeOwningPtr(std::unique_ptr< T > &&ptr)
Internal helper to turn a std::unique_ptr<T> into an OwningPtr.
T * OwningPtr
An alias for raw pointers for indicating that the return type of a RooFit function is an owning point...