89using std::flush, std::endl;
100 pdf1(
"pdf1",
"pdf1", this, _pdf1),
101 pdf2(
"pdf2",
"pdf2", this, _pdf2),
102 x(
"x",
"x", this, _x),
103 alpha(
"alpha",
"alpha", this, _alpha),
104 _cacheAlpha(doCacheAlpha)
113 pdf1(
"pdf1", this, other.pdf1),
114 pdf2(
"pdf2", this, other.pdf2),
115 x(
"x", this, other.
x),
116 alpha(
"alpha", this, other.alpha),
117 _cacheAlpha(other._cacheAlpha)
145 par1->add(par2,
true);
146 par1->remove(
x.
arg(),
true,
true);
162 name.Append(
"_MORPH_");
182 std::unique_ptr<TIterator> slIter{
185 double alphaSave =
alpha;
187 coutP(Eval) <<
"RooIntegralMorph::fillCacheObject(" <<
GetName() <<
") filling multi-dimensional cache";
188 while (slIter->Next()) {
190 std::unique_ptr<TIterator> dIter{
193 ccoutP(Eval) <<
"." << flush;
195 ccoutP(Eval) << std::endl;
215 ret.
add(PdfCacheElem::containedArgs(action));
246 _nset = std::make_unique<RooArgSet>(*
_x);
250 _cb1 = std::unique_ptr<RooAbsFunc>{
_c1->bindVars(*
_x,
_nset.get())};
251 _cb2 = std::unique_ptr<RooAbsFunc>{
_c2->bindVars(*
_x,
_nset.get())};
253 _rf1 = std::make_unique<RooBrentRootFinder>(*
_cb1);
254 _rf2 = std::make_unique<RooBrentRootFinder>(*
_cb2);
277 if (y < 0 || y > 1) {
279 <<
"RooIntegralMorph::MorphCacheElem::calcX() WARNING: requested root finding for unphysical CDF value " <<
y
285 double xmax = _x->getMax(
"cache");
286 double xmin = _x->getMin(
"cache");
295 return _alpha->getVal() *
x1 + (1 - _alpha->getVal()) *
x2;
303 double xmax = _x->getMax(
"cache");
304 double xmin = _x->getMin(
"cache");
314 double xsave = _self->x;
321 _yatX.resize(_x->numBins(
"cache") + 1);
322 _calcX.resize(_x->numBins(
"cache") + 1);
327 Int_t nbins = _x->numBins(
"cache");
329 oocoutE(_self, Eval) <<
"RooIntegralMorph::MorphCacheElem::calculate(" << _self->GetName()
330 <<
") ERROR: observable " << _x->GetName()
331 <<
" has an empty binning for the cache histogram."
332 <<
" Define one with RooRealVar::setBins(nbins, \"cache\")." << std::endl;
337 for (
int i = 0; i < nbins; i++) {
346 for (
int i = 0; i < 10; i++) {
349 double offset = _yatX[_yatXmin];
350 double delta = (_yatX[_yatXmax] - _yatX[_yatXmin]) / 10;
355 double X = calcX(
y, ok);
364 Int_t igapLow = _yatXmin + 1;
367 Int_t igapHigh = igapLow + 1;
368 while (igapHigh < (_yatXmax) && _yatX[igapHigh] < 0)
372 fillGap(igapLow - 1, igapHigh);
375 if (igapHigh >= _yatXmax - 1)
377 igapLow = igapHigh + 1;
381 double xmax = _x->getMax(
"cache");
382 double xmin = _x->getMin(
"cache");
383 double binw = (
xmax -
xmin) / _x->numBins(
"cache");
384 for (
int i = _yatXmin + 1; i < _yatXmax - 1; i++) {
387 double xBinC =
xmin + (i + 0.5) * binw;
388 double xOffset = xBinC - _calcX[i];
389 if (std::abs(xOffset / binw) > 1
e-3) {
390 double slope = (_yatX[i + 1] - _yatX[i - 1]) / (_calcX[i + 1] - _calcX[i - 1]);
391 double newY = _yatX[i] + slope * xOffset;
399 for (
int i = 0; i < _yatXmin; i++) {
401 const std::size_t binIdx = hist()->getIndex(*hist()->get(),
true);
402 hist()->set(binIdx, 0, -1);
405 double xMax = _x->getMax(
"cache");
406 const double aval = _alpha->getVal();
412 double x1lo = _x->getMin(
"cache");
413 double x2lo = _x->getMin(
"cache");
416 for (
int i = _yatXmin; i <= _yatXmax; i++) {
419 const double xBinC =
xmin + (i + 0.5) * binw;
431 for (
int iter = 0; iter < 10; iter++) {
432 bool ok = _rf1->findRoot(
x1, x1lo, xMax,
y);
433 ok &= _rf2->findRoot(
x2, x2lo, xMax,
y);
435 f1x1 = _pdf1->getVal(_nset.get());
437 f2x2 = _pdf2->getVal(_nset.get());
438 if (!ok || f1x1 <= 0 || f2x2 <= 0)
440 const double X = aval *
x1 + (1 - aval) *
x2;
441 if (std::abs(
X - xBinC) < 1
e-12 * (xMax -
xmin))
443 const double dXdy = aval / f1x1 + (1 - aval) / f2x2;
444 const double yNew =
y + (xBinC -
X) / dXdy;
445 if (!(yNew > 0.) || !(yNew < 1.) || yNew ==
y)
451 double fbarX = f1x1 * f2x2 / (aval * f2x2 + (1 - aval) * f1x1);
455 const std::size_t binIdx = hist()->getIndex(*hist()->get(),
true);
456 hist()->set(binIdx, fbarX, -1);
463 for (
int i = _yatXmax + 1; i < nbins; i++) {
465 const std::size_t binIdx = hist()->getIndex(*hist()->get(),
true);
466 hist()->set(binIdx, 0, -1);
469 pdf()->setUnitNorm(
true);
472 oocxcoutD(_self, Eval) <<
"RooIntegralMorph::MorphCacheElem::calculate(" << _self->GetName()
473 <<
") calculation required " << _ccounter <<
" samplings of cdfs" << std::endl;
488 if (_yatX[ixlo] < 0) {
489 oocoutE(_self, Eval) <<
"RooIntegralMorph::MorphCacheElme::fillGap(" << _self->GetName() <<
"): ERROR in fillgap "
490 << ixlo <<
" = " << ixhi <<
" splitPoint= " << splitPoint <<
" _yatX[ixlo] = " << _yatX[ixlo]
493 if (_yatX[ixhi] < 0) {
494 oocoutE(_self, Eval) <<
"RooIntegralMorph::MorphCacheElme::fillGap(" << _self->GetName() <<
"): ERROR in fillgap "
495 << ixlo <<
" = " << ixhi <<
" splitPoint " << splitPoint <<
" _yatX[ixhi] = " << _yatX[ixhi]
500 double ymid = _yatX[ixlo] * splitPoint + _yatX[ixhi] * (1 - splitPoint);
502 double Xmid = calcX(ymid, ok);
504 oocoutW(_self, Eval) <<
"RooIntegralMorph::MorphCacheElem::fillGap(" << _self->GetName()
505 <<
") unable to calculate midpoint in gap [" << ixlo <<
"," << ixhi
506 <<
"], resorting to interpolation" << std::endl;
507 interpolateGap(ixlo, ixhi);
510 Int_t iX = binX(Xmid);
511 double cq = (Xmid - _calcX[ixlo]) / (_calcX[ixhi] - _calcX[ixlo]) - 0.5;
519 if (std::abs(cq) < 0.01 || std::abs(cq * (ixhi - ixlo)) < 0.1 || ymid < _ycutoff) {
523 interpolateGap(ixlo, iX);
526 interpolateGap(iX, ixhi);
533 if (splitPoint < 0.95) {
535 double newSplit = splitPoint + 0.5 * (1 - splitPoint);
536 fillGap(ixlo, ixhi, newSplit);
539 interpolateGap(ixlo, ixhi);
542 }
else if (iX == ixhi) {
545 if (splitPoint > 0.05) {
546 double newSplit = splitPoint / 2;
547 fillGap(ixlo, ixhi, newSplit);
550 interpolateGap(ixlo, ixhi);
574 double xmax = _x->getMax(
"cache");
575 double xmin = _x->getMin(
"cache");
576 double binw = (
xmax -
xmin) / _x->numBins(
"cache");
579 double deltaY = (_yatX[ixhi] - _yatX[ixlo]) / ((_calcX[ixhi] - _calcX[ixlo]) / binw);
582 double xBinC =
xmin + (ixlo + 0.5) * binw;
583 double xOffset = xBinC - _calcX[ixlo];
585 for (
int j = ixlo + 1; j < ixhi; j++) {
586 _yatX[j] = _yatX[ixlo] + (xOffset / binw + (j - ixlo)) * deltaY;
587 _calcX[j] =
xmin + (j + 0.5) * binw;
600 double xmin = _x->getMin(
"cache");
601 double xmax = _x->getMax(
"cache");
602 Int_t nbins = _x->numBins(
"cache");
617 oocxcoutD(_self, Eval) <<
"RooIntegralMorph::MorphCacheElem::findRange(" << _self->GetName()
618 <<
") findMin: x1 = " <<
x1 <<
" x2 = " <<
x2 <<
" ok = " << (ok ?
"T" :
"F") << std::endl;
625 double X = _alpha->getVal() *
x1 + (1 - _alpha->getVal()) *
x2;
626 if (std::abs(
X - Xlast) / (
xmax -
xmin) < 0.0001) {
633 _yatX[_yatXmin] =
ymin;
634 _calcX[_yatXmin] =
X;
645 _yatX[_yatXmin] = yminSave;
646 _calcX[_yatXmin] = Xsave;
651 double deltaymax = 0.1;
652 double deltaymaxSave(-1);
655 ok &= _rf1->findRoot(
x1,
xmin,
xmax, 1 - deltaymax);
656 ok &= _rf2->findRoot(
x2,
xmin,
xmax, 1 - deltaymax);
658 oocxcoutD(_self, Eval) <<
"RooIntegralMorph::MorphCacheElem::findRange(" << _self->GetName()
659 <<
") findMax: x1 = " <<
x1 <<
" x2 = " <<
x2 <<
" ok = " << (ok ?
"T" :
"F") << std::endl;
666 double X = _alpha->getVal() *
x1 + (1 - _alpha->getVal()) *
x2;
667 if (std::abs(
X - Xlast) / (
xmax -
xmin) < 0.0001) {
674 _yatX[_yatXmax] = 1 - deltaymax;
675 _calcX[_yatXmax] =
X;
676 deltaymaxSave = deltaymax;
680 deltaymax /= sqrt(10.);
683 if (deltaymax < _ycutoff)
687 _yatX[_yatXmax] = 1 - deltaymaxSave;
688 _calcX[_yatXmax] = Xsave;
691 for (
int i = 0; i < _yatXmin; i++)
693 for (
int i = _yatXmax + 1; i < nbins; i++)
695 oocxcoutD(_self, Eval) <<
"RooIntegralMorph::findRange(" << _self->GetName() <<
"): ymin = " << _yatX[_yatXmin]
696 <<
" ymax = " << _yatX[_yatXmax] << std::endl;
697 oocxcoutD(_self, Eval) <<
"RooIntegralMorph::findRange(" << _self->GetName() <<
"): xmin = " << _calcX[_yatXmin]
698 <<
" xmax = " << _calcX[_yatXmax] << std::endl;
723 orderedObs.
add(*obsX);
int Int_t
Signed integer 4 bytes (int)
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.
friend class MorphCacheElem
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.
T * OwningPtr
An alias for raw pointers for indicating that the return type of a RooFit function is an owning point...
OwningPtr< T > makeOwningPtr(std::unique_ptr< T > &&ptr)
Internal helper to turn a std::unique_ptr<T> into an OwningPtr.