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)
153 par1->add(par2,
true) ;
154 par1->remove(
x.
arg(),
true,
true) ;
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.
RooFit::OwningPtr< RooArgSet > getParameters(const RooAbsData *data, bool stripDisconnected=true) const
Create a list of leaf nodes in the arg tree starting with ourself as top node that don't match any of...
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.
const T & arg() const
Return reference to object held in proxy.
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...