Logo ROOT  
Reference Guide
 
Loading...
Searching...
No Matches
RooMomentMorphFunc.cxx
Go to the documentation of this file.
1/*
2 * Project: RooFit
3 *
4 * Copyright (c) 2023, CERN
5 *
6 * Redistribution and use in source and binary forms,
7 * with or without modification, are permitted according to the terms
8 * listed in LICENSE (http://roofit.sourceforge.net/license.txt)
9 */
10
11/** \class RooMomentMorphFunc
12 \ingroup Roofit
13
14**/
15
16#include "RooMomentMorphFunc.h"
17#include "RooRealConstant.h"
18#include "RooRealVar.h"
19#include "RooFormulaVar.h"
20#include "RooCustomizer.h"
21#include "RooRealSumFunc.h"
22#include "RooAddition.h"
23#include "RooMoment.h"
24#include "RooLinearVar.h"
25#include "RooChangeTracker.h"
26
27#include "TMath.h"
28
29using std::string, std::vector;
30
31
32//_____________________________________________________________________________
34 : _cacheMgr(this, 10, true, true)
35{
36}
37
38//_____________________________________________________________________________
40 const RooArgList &pdfList, const TVectorD &mrefpoints, Setting setting)
41 : RooAbsReal(name, title),
42 _cacheMgr(this, 10, true, true),
43 m("m", "m", this, _m),
44 _varList("varList", "List of variables", this),
45 _pdfList("pdfList", "List of pdfs", this),
46 _mref(new TVectorD(mrefpoints)),
47 _setting(setting)
48{
49 // observables
51
52 // reference p.d.f.s
53 _pdfList.addTyped<RooAbsPdf>(pdfList);
54
55 // initialization
56 initialize();
57}
58
59//_____________________________________________________________________________
61 const RooArgList &pdfList, const RooArgList &mrefList, Setting setting)
62 : RooAbsReal(name, title),
63 _cacheMgr(this, 10, true, true),
64 m("m", "m", this, _m),
65 _varList("varList", "List of variables", this),
66 _pdfList("pdfList", "List of pdfs", this),
67 _mref(new TVectorD(mrefList.size())),
68 _setting(setting)
69{
70 // observables
72
73 // reference p.d.f.s
74 _pdfList.addTyped<RooAbsPdf>(pdfList);
75
76 // reference points in m
77
78 Int_t i = 0;
79 for (auto *mref : mrefList) {
80 if (!dynamic_cast<RooAbsReal *>(mref)) {
81 coutE(InputArguments) << "RooMomentMorphFunc::ctor(" << GetName() << ") ERROR: mref " << mref->GetName()
82 << " is not of type RooAbsReal" << std::endl;
83 throw string("RooPolyMorh::ctor() ERROR mref is not of type RooAbsReal");
84 }
85 if (!dynamic_cast<RooConstVar *>(mref)) {
86 coutW(InputArguments) << "RooMomentMorphFunc::ctor(" << GetName() << ") WARNING mref point " << i
87 << " is not a constant, taking a snapshot of its value" << std::endl;
88 }
89 (*_mref)[i] = static_cast<RooAbsReal *>(mref)->getVal();
90 ++i;
91 }
92
93 // initialization
94 initialize();
95}
96
97//_____________________________________________________________________________
100 _cacheMgr(other._cacheMgr, this),
101 m("m", this, other.m),
102 _varList("varList", this, other._varList),
103 _pdfList("pdfList", this, other._pdfList),
104 _mref(new TVectorD(*other._mref)),
105 _setting(other._setting),
106 _useHorizMorph(other._useHorizMorph)
107{
108
109 // initialization
110 initialize();
111}
112
113//_____________________________________________________________________________
115{
116 if (_mref)
117 delete _mref;
118 if (_M)
119 delete _M;
120}
121
122//_____________________________________________________________________________
124{
125
127
128 // other quantities needed
129 if (nPdf != _mref->GetNrows()) {
130 coutE(InputArguments) << "RooMomentMorphFunc::initialize(" << GetName() << ") ERROR: nPdf != nRefPoints" << std::endl;
131 assert(0);
132 }
133
134 TVectorD *dm = new TVectorD(nPdf);
135 _M = new TMatrixD(nPdf, nPdf);
136
137 // transformation matrix for non-linear extrapolation, needed in evaluate()
138 TMatrixD M(nPdf, nPdf);
139 for (Int_t i = 0; i < _mref->GetNrows(); ++i) {
140 (*dm)[i] = (*_mref)[i] - (*_mref)[0];
141 M(i, 0) = 1.;
142 if (i > 0)
143 M(0, i) = 0.;
144 }
145 for (Int_t i = 1; i < _mref->GetNrows(); ++i) {
146 for (Int_t j = 1; j < _mref->GetNrows(); ++j) {
147 M(i, j) = std::pow((*dm)[i], (double)j);
148 }
149 }
150 (*_M) = M.Invert();
151
152 delete dm;
153}
154
155//_____________________________________________________________________________
157{
158 auto cache = static_cast<CacheElem *>(_cacheMgr.getObj(nullptr, static_cast<RooArgSet const*>(nullptr)));
159 if (cache) {
160 return cache;
161 }
164
165 RooAbsReal *null = nullptr;
174
176
178
179 // fraction parameters
180 RooArgList coefList("coefList");
181 RooArgList coefList2("coefList2");
182 for (Int_t i = 0; i < 2 * nPdf; ++i) {
183 std::string fracName = Form("frac_%d", i);
184
185 RooRealVar *frac = new RooRealVar(fracName.c_str(), fracName.c_str(), 1.);
186
187 fracl.add(*frac); // to be set later
188 if (i < nPdf) {
189 coefList.add(*static_cast<RooRealVar *>(fracl.at(i)));
190 } else {
191 coefList2.add(*static_cast<RooRealVar *>(fracl.at(i)));
192 }
193 ownedComps.add(*static_cast<RooRealVar *>(fracl.at(i)));
194 }
195
196 RooRealSumFunc *theSumFunc = nullptr;
197 std::string sumfuncName = Form("%s_sumfunc", GetName());
198
199 if (_useHorizMorph) {
200 // mean and sigma
202 for (Int_t i = 0; i < nPdf; ++i) {
203 for (Int_t j = 0; j < nVar; ++j) {
204
205 std::string meanName = Form("%s_mean_%d_%d", GetName(), i, j);
206 std::string sigmaName = Form("%s_sigma_%d_%d", GetName(), i, j);
207
208 RooAbsMoment *mom = nVar == 1 ? (static_cast<RooAbsPdf *>(_pdfList.at(i)))->sigma(static_cast<RooRealVar &>(*varList.at(j)))
209 : (static_cast<RooAbsPdf *>(_pdfList.at(i)))->sigma(static_cast<RooRealVar &>(*varList.at(j)), varList);
210
211 mom->setLocalNoDirtyInhibit(true);
212 mom->mean()->setLocalNoDirtyInhibit(true);
213
214 sigmarv[ij(i, j)] = mom;
215 meanrv[ij(i, j)] = mom->mean();
216
217 ownedComps.add(*sigmarv[ij(i, j)]);
218 }
219 }
220
221 // slope and offset (to be set later, depend on m)
222 for (Int_t j = 0; j < nVar; ++j) {
223 RooArgList meanList("meanList");
224 RooArgList rmsList("rmsList");
225 for (Int_t i = 0; i < nPdf; ++i) {
226 meanList.add(*meanrv[ij(i, j)]);
227 rmsList.add(*sigmarv[ij(i, j)]);
228 }
229 std::string myrmsName = Form("%s_rms_%d", GetName(), j);
230 std::string myposName = Form("%s_pos_%d", GetName(), j);
231 myrms[j] = new RooAddition(myrmsName.c_str(), myrmsName.c_str(), rmsList, coefList2);
232 mypos[j] = new RooAddition(myposName.c_str(), myposName.c_str(), meanList, coefList2);
233 ownedComps.add(RooArgSet(*myrms[j], *mypos[j]));
234 }
235
236 // construction of unit pdfs
238
239 for (Int_t i = 0; i < nPdf; ++i) {
240 auto& pdf = static_cast<RooAbsPdf&>(_pdfList[i]);
241 std::string pdfName = Form("pdf_%d", i);
242 RooCustomizer cust(pdf, pdfName.c_str());
243
244 for (Int_t j = 0; j < nVar; ++j) {
245 // slope and offset formulas
246 std::string slopeName = Form("%s_slope_%d_%d", GetName(), i, j);
247 std::string offsetName = Form("%s_offset_%d_%d", GetName(), i, j);
248 slope[ij(i, j)] = new RooFormulaVar(slopeName.c_str(), "@0/@1", RooArgList(*sigmarv[ij(i, j)], *myrms[j]));
249 offs[ij(i, j)] = new RooFormulaVar(offsetName.c_str(), "@0-(@1*@2)",
250 RooArgList(*meanrv[ij(i, j)], *mypos[j], *slope[ij(i, j)]));
251 ownedComps.add(RooArgSet(*slope[ij(i, j)], *offs[ij(i, j)]));
252 // linear transformations, so pdf can be renormalized
253 auto& var = static_cast<RooRealVar&>(*_varList[j]);
254 std::string transVarName = Form("%s_transVar_%d_%d", GetName(), i, j);
255 // transVar[ij(i,j)] = new
256 // RooFormulaVar(transVarName.c_str(),transVarName.c_str(),"@0*@1+@2",RooArgList(*var,*slope[ij(i,j)],*offs[ij(i,j)]));
257
258 transVar[ij(i, j)] =
259 new RooLinearVar(transVarName.c_str(), transVarName.c_str(), var, *slope[ij(i, j)], *offs[ij(i, j)]);
260
261 // *** WVE this is important *** this declares that frac effectively depends on the morphing parameters
262 // This will prevent the likelihood optimizers from erroneously declaring terms constant
263 transVar[ij(i, j)]->addServer((RooAbsArg &)m.arg());
264
265 ownedComps.add(*transVar[ij(i, j)]);
266 cust.replaceArg(var, *transVar[ij(i, j)]);
267 }
268 transPdf[i] = static_cast<RooAbsPdf *>(cust.build());
269 transPdfList.add(*transPdf[i]);
270 ownedComps.add(*transPdf[i]);
271 }
272 // sum pdf
273 theSumFunc = new RooRealSumFunc(sumfuncName.c_str(), sumfuncName.c_str(), transPdfList, coefList);
274 } else {
275 theSumFunc = new RooRealSumFunc(sumfuncName.c_str(), sumfuncName.c_str(), _pdfList, coefList);
276 }
277
278 // *** WVE this is important *** this declares that frac effectively depends on the morphing parameters
279 // This will prevent the likelihood optimizers from erroneously declaring terms constant
280 theSumFunc->addServer((RooAbsArg &)m.arg());
281 theSumFunc->addOwnedComponents(ownedComps);
282
283 // change tracker for fraction parameters
284 std::string trackerName = Form("%s_frac_tracker", GetName());
285 RooChangeTracker *tracker = new RooChangeTracker(trackerName.c_str(), trackerName.c_str(), m.arg(), true);
286
287 // Store it in the cache
288 cache = new CacheElem(*theSumFunc, *tracker, fracl);
289 _cacheMgr.setObj(nullptr, nullptr, cache, nullptr);
290
291 return cache;
292}
293
294//_____________________________________________________________________________
299
300//_____________________________________________________________________________
302{
303 delete _sumFunc;
304 delete _tracker;
305}
306
307//_____________________________________________________________________________
309{
310 // Special version of getValV() overrides RooAbsReal::getVal() to save value of current normalization set
311 _curNormSet = set ? const_cast<RooArgSet *>(set) : const_cast<RooArgSet *>(static_cast<RooArgSet const*>(&_varList));
312 return RooAbsReal::getValV(set);
313}
314
315//_____________________________________________________________________________
317{
318 CacheElem *cache = getCache(nset ? nset : _curNormSet);
319
320 if (cache->_tracker->hasChanged(true)) {
321 cache->calculateFractions(*this, false); // verbose turned off
322 }
323
324 return cache->_sumFunc;
325}
326
327//_____________________________________________________________________________
329{
330 CacheElem *cache = getCache(nset ? nset : _curNormSet);
331
332 if (cache->_tracker->hasChanged(true)) {
333 cache->calculateFractions(*this, false); // verbose turned off
334 }
335
336 return cache->_sumFunc;
337}
338
339//_____________________________________________________________________________
341{
343
344 if (cache->_tracker->hasChanged(true)) {
345 cache->calculateFractions(*this, false); // verbose turned off
346 }
347
348 double ret = cache->_sumFunc->getVal(_pdfList.nset());
349 return ret;
350}
351
352//_____________________________________________________________________________
354{
355 return static_cast<RooRealVar *>(_frac.at(i));
356}
357
358//_____________________________________________________________________________
360{
361 return static_cast<RooRealVar *>(_frac.at(i));
362}
363
364//_____________________________________________________________________________
366{
367 Int_t nPdf = self._pdfList.size();
368
369 double dm = self.m - (*self._mref)[0];
370
371 // fully non-linear
372 double sumposfrac = 0.;
373 for (Int_t i = 0; i < nPdf; ++i) {
374 double ffrac = 0.;
375 for (Int_t j = 0; j < nPdf; ++j) {
376 ffrac += (*self._M)(j, i) * (j == 0 ? 1. : std::pow(dm, (double)j));
377 }
378 if (ffrac >= 0)
379 sumposfrac += ffrac;
380 // fractions for pdf
381 const_cast<RooRealVar *>(frac(i))->setVal(ffrac);
382 // fractions for rms and mean
383 const_cast<RooRealVar *>(frac(nPdf + i))->setVal(ffrac);
384 if (verbose) {
385 std::cout << ffrac << std::endl;
386 }
387 }
388
389 // various mode settings
390 int imin = self.idxmin(self.m);
391 int imax = self.idxmax(self.m);
392 double mfrac = (self.m - (*self._mref)[imin]) / ((*self._mref)[imax] - (*self._mref)[imin]);
393 switch (self._setting) {
394 case NonLinear:
395 // default already set above
396 break;
397
398 case SineLinear:
399 mfrac =
400 std::sin(TMath::PiOver2() * mfrac); // this gives a continuous differentiable transition between grid points.
401
402 // now fall through to Linear case
403
404 case Linear:
405 for (Int_t i = 0; i < 2 * nPdf; ++i) const_cast<RooRealVar *>(frac(i))->setVal(0.);
406 if (imax > imin) { // m in between mmin and mmax
407 const_cast<RooRealVar *>(frac(imin))->setVal(1. - mfrac);
408 const_cast<RooRealVar *>(frac(nPdf + imin))->setVal(1. - mfrac);
409 const_cast<RooRealVar *>(frac(imax))->setVal(mfrac);
410 const_cast<RooRealVar *>(frac(nPdf + imax))->setVal(mfrac);
411 } else if (imax == imin) { // m outside mmin and mmax
412 const_cast<RooRealVar *>(frac(imin))->setVal(1.);
413 const_cast<RooRealVar *>(frac(nPdf + imin))->setVal(1.);
414 }
415 break;
417 for (Int_t i = 0; i < nPdf; ++i) const_cast<RooRealVar *>(frac(i))->setVal(0.);
418 if (imax > imin) { // m in between mmin and mmax
419 const_cast<RooRealVar *>(frac(imin))->setVal(1. - mfrac);
420 const_cast<RooRealVar *>(frac(imax))->setVal(mfrac);
421 } else if (imax == imin) { // m outside mmin and mmax
422 const_cast<RooRealVar *>(frac(imin))->setVal(1.);
423 }
424 break;
426 for (Int_t i = 0; i < nPdf; ++i) {
427 if (frac(i)->getVal() < 0)
428 const_cast<RooRealVar *>(frac(i))->setVal(0.);
429 const_cast<RooRealVar *>(frac(i))->setVal(frac(i)->getVal() / sumposfrac);
430 }
431 break;
432 }
433}
434
435//_____________________________________________________________________________
436int RooMomentMorphFunc::idxmin(const double &mval) const
437{
438 int imin(0);
440 double mmin = -DBL_MAX;
441 for (Int_t i = 0; i < nPdf; ++i) {
442 if ((*_mref)[i] > mmin && (*_mref)[i] <= mval) {
443 mmin = (*_mref)[i];
444 imin = i;
445 }
446 }
447 return imin;
448}
449
450//_____________________________________________________________________________
451int RooMomentMorphFunc::idxmax(const double &mval) const
452{
453 int imax(0);
455 double mmax = DBL_MAX;
456 for (Int_t i = 0; i < nPdf; ++i) {
457 if ((*_mref)[i] < mmax && (*_mref)[i] >= mval) {
458 mmax = (*_mref)[i];
459 imax = i;
460 }
461 }
462 return imax;
463}
464
465//_____________________________________________________________________________
466std::list<double> *RooMomentMorphFunc::plotSamplingHint(RooAbsRealLValue &obs, double xlo, double xhi) const
467{
468 return sumFunc(nullptr)->plotSamplingHint(obs, xlo, xhi);
469}
470
471//_____________________________________________________________________________
472std::list<double> *RooMomentMorphFunc::binBoundaries(RooAbsRealLValue &obs, double xlo, double xhi) const
473{
474 return sumFunc(nullptr)->binBoundaries(obs, xlo, xhi);
475}
476
477//_____________________________________________________________________________
479{
480 return sumFunc(nullptr)->isBinnedDistribution(obs);
481}
size_t size(const MatrixT &matrix)
retrieve the size of a square matrix
#define coutW(a)
#define coutE(a)
ROOT::Detail::TRangeCast< T, true > TRangeDynCast
TRangeDynCast is an adapter class that allows the typed iteration through a TCollection.
char name[80]
Definition TGX11.cxx:142
TMatrixT< Double_t > TMatrixD
Definition TMatrixDfwd.h:23
char * Form(const char *fmt,...)
Formats a string in a circular formatting buffer.
Definition TString.cxx:2570
TVectorT< Double_t > TVectorD
Definition TVectorDfwd.h:23
Common abstract base class for objects that represent a value and a "shape" in RooFit.
Definition RooAbsArg.h:76
virtual bool add(const RooAbsArg &var, bool silent=false)
Add the specified argument to list.
Storage_t::size_type size() const
bool addTyped(const RooAbsCollection &list, bool silent=false)
Adds elements of a given RooAbsCollection to the container if they match the specified type.
Abstract interface for all probability density functions.
Definition RooAbsPdf.h:32
const RooArgSet * nset() const
Definition RooAbsProxy.h:52
Abstract base class for objects that represent a real value that may appear on the left hand side of ...
Abstract base class for objects that represent a real value and implements functionality common to al...
Definition RooAbsReal.h:63
virtual std::list< double > * binBoundaries(RooAbsRealLValue &obs, double xlo, double xhi) const
Retrieve bin boundaries if this distribution is binned in obs.
double getVal(const RooArgSet *normalisationSet=nullptr) const
Evaluate object.
Definition RooAbsReal.h:107
virtual double getValV(const RooArgSet *normalisationSet=nullptr) const
Return value of object.
friend class RooRealSumFunc
Definition RooAbsReal.h:403
virtual bool isBinnedDistribution(const RooArgSet &) const
Tests if the distribution is binned. Unless overridden by derived classes, this always returns false.
Definition RooAbsReal.h:343
virtual std::list< double > * plotSamplingHint(RooAbsRealLValue &obs, double xlo, double xhi) const
Interface for returning an optional hint for initial sampling points when constructing a curve projec...
Calculates the sum of a set of RooAbsReal terms, or when constructed with two sets,...
Definition RooAddition.h:27
RooArgList is a container object that can hold multiple RooAbsArg objects.
Definition RooArgList.h:22
RooAbsArg * at(Int_t idx) const
Return object at given index, or nullptr if index is out of range.
Definition RooArgList.h:110
RooArgSet is a container object that can hold multiple RooAbsArg objects.
Definition RooArgSet.h:24
Int_t setObj(const RooArgSet *nset, T *obj, const TNamed *isetRangeName=nullptr)
Setter function without integration set.
T * getObj(const RooArgSet *nset, Int_t *sterileIndex=nullptr, const TNamed *isetRangeName=nullptr)
Getter function without integration set.
Meta object that tracks value changes in a given set of RooAbsArgs by registering itself as value cli...
bool hasChanged(bool clearState)
Returns true if state has changed since last call with clearState=true.
Represents a constant real-valued object.
Definition RooConstVar.h:23
RooCustomizer is a factory class to produce clones of a prototype composite PDF object with the same ...
A RooFormulaVar is a generic implementation of a real-valued object, which takes a RooArgList of serv...
RooLinearVar is the most general form of a derived real-valued object that can be used by RooRealInte...
void calculateFractions(const RooMomentMorphFunc &self, bool verbose=true) const
RooArgList containedArgs(Action) override
double getValV(const RooArgSet *set=nullptr) const override
Return value of object.
RooArgSet * _curNormSet
! Current normalization set
bool isBinnedDistribution(const RooArgSet &obs) const override
Tests if the distribution is binned. Unless overridden by derived classes, this always returns false.
RooObjCacheManager _cacheMgr
! The cache manager
CacheElem * getCache(const RooArgSet *nset) const
double evaluate() const override
Evaluate this PDF / function / constant. Needs to be overridden by all derived classes.
RooAbsReal * sumFunc(const RooArgSet *nset)
int idxmin(const double &m) const
std::list< double > * binBoundaries(RooAbsRealLValue &, double, double) const override
Retrieve bin boundaries if this distribution is binned in obs.
std::list< double > * plotSamplingHint(RooAbsRealLValue &obs, double xlo, double xhi) const override
Interface for returning an optional hint for initial sampling points when constructing a curve projec...
Int_t ij(const Int_t &i, const Int_t &j) const
int idxmax(const double &m) const
Variable that can be changed from the outside.
Definition RooRealVar.h:37
const T & arg() const
Return reference to object held in proxy.
const char * GetName() const override
Returns name of object.
Definition TNamed.h:49
Int_t GetNrows() const
Definition TVectorT.h:75
constexpr Double_t PiOver2()
Definition TMath.h:54
TMarker m
Definition textangle.C:8