Logo ROOT  
Reference Guide
 
Loading...
Searching...
No Matches
RooMomentMorph.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 RooMomentMorph
12 \ingroup Roofit
13
14**/
15
16#include "RooMomentMorph.h"
17#include "RooRealConstant.h"
18#include "RooRealVar.h"
19#include "RooFormulaVar.h"
20#include "RooCustomizer.h"
21#include "RooAddPdf.h"
22#include "RooAddition.h"
23#include "RooMoment.h"
24#include "RooLinearVar.h"
25#include "RooChangeTracker.h"
26
27#include "TMath.h"
28
29////////////////////////////////////////////////////////////////////////////////
30/// coverity[UNINIT_CTOR]
31
33 : _cacheMgr(this, 10, true, true)
34{
35}
36
37////////////////////////////////////////////////////////////////////////////////
38/// CTOR
39
40RooMomentMorph::RooMomentMorph(const char *name, const char *title, RooAbsReal &_m, const RooArgList &varList,
41 const RooArgList &pdfList, const TVectorD &mrefpoints, Setting setting)
42 : RooAbsPdf(name, title),
43 _cacheMgr(this, 10, true, true),
44 m("m", "m", this, _m),
45 _varList("varList", "List of variables", this),
46 _pdfList("pdfList", "List of pdfs", this),
47 _mref(new TVectorD(mrefpoints)),
48 _setting(setting),
49 _useHorizMorph(true)
50{
51 // observables
53
54 // reference p.d.f.s
55 _pdfList.addTyped<RooAbsPdf>(pdfList);
56
57 // initialization
58 initialize();
59}
60
61////////////////////////////////////////////////////////////////////////////////
62/// CTOR
63
64RooMomentMorph::RooMomentMorph(const char *name, const char *title, RooAbsReal &_m, const RooArgList &varList,
65 const RooArgList &pdfList, const RooArgList &mrefList, Setting setting)
66 : RooAbsPdf(name, title),
67 _cacheMgr(this, 10, true, true),
68 m("m", "m", this, _m),
69 _varList("varList", "List of variables", this),
70 _pdfList("pdfList", "List of pdfs", this),
71 _mref(new TVectorD(mrefList.size())),
72 _setting(setting),
73 _useHorizMorph(true)
74{
75 // observables
77
78 // reference p.d.f.s
79 _pdfList.addTyped<RooAbsPdf>(pdfList);
80
81 // reference points in m
82
83 Int_t i = 0;
84 for (auto *mref : mrefList) {
85 if (!dynamic_cast<RooAbsReal*>(mref)) {
86 coutE(InputArguments) << "RooMomentMorph::ctor(" << GetName() << ") ERROR: mref " << mref->GetName() << " is not of type RooAbsReal" << std::endl ;
87 throw std::string("RooPolyMorh::ctor() ERROR mref is not of type RooAbsReal") ;
88 }
89 if (!dynamic_cast<RooConstVar*>(mref)) {
90 coutW(InputArguments) << "RooMomentMorph::ctor(" << GetName() << ") WARNING mref point " << i << " is not a constant, taking a snapshot of its value" << std::endl ;
91 }
92 (*_mref)[i] = static_cast<RooAbsReal*>(mref)->getVal() ;
93 i++;
94 }
95
96 // initialization
97 initialize();
98}
99
100////////////////////////////////////////////////////////////////////////////////
101
103 : RooAbsPdf(other, name),
104 _cacheMgr(other._cacheMgr, this),
105 m("m", this, other.m),
106 _varList("varList", this, other._varList),
107 _pdfList("pdfList", this, other._pdfList),
108 _mref(new TVectorD(*other._mref)),
109 _setting(other._setting),
110 _useHorizMorph(other._useHorizMorph)
111{
112
113 // initialization
114 initialize();
115}
116
117////////////////////////////////////////////////////////////////////////////////
118
120{
121 if (_mref) delete _mref;
122 if (_M) delete _M;
123}
124
125////////////////////////////////////////////////////////////////////////////////
126
128{
130
131 // other quantities needed
132 if (nPdf!=_mref->GetNrows()) {
133 coutE(InputArguments) << "RooMomentMorph::initialize(" << GetName() << ") ERROR: nPdf != nRefPoints" << std::endl ;
134 assert(0) ;
135 }
136
137 TVectorD dm{nPdf};
138 _M = new TMatrixD(nPdf,nPdf);
139
140 // transformation matrix for non-linear extrapolation, needed in evaluate()
141 TMatrixD M(nPdf,nPdf);
142 for (Int_t i=0; i<_mref->GetNrows(); ++i) {
143 dm[i] = (*_mref)[i]-(*_mref)[0];
144 M(i,0) = 1.;
145 if (i>0) M(0,i) = 0.;
146 }
147 for (Int_t i=1; i<_mref->GetNrows(); ++i) {
148 for (Int_t j=1; j<_mref->GetNrows(); ++j) {
149 M(i,j) = std::pow(dm[i],(double)j);
150 }
151 }
152 (*_M) = M.Invert();
153}
154
155////////////////////////////////////////////////////////////////////////////////
156
157RooMomentMorph::CacheElem::CacheElem(std::unique_ptr<RooAbsPdf> && sumPdf,
158 std::unique_ptr<RooChangeTracker> && tracker,
159 const RooArgList& flist)
160 : _sumPdf(std::move(sumPdf)), _tracker(std::move(tracker)) {
161 _frac.add(flist);
162}
163
164////////////////////////////////////////////////////////////////////////////////
165
167{
168 if (auto* cache = static_cast<CacheElem*>(_cacheMgr.getObj(nullptr,static_cast<RooArgSet*>(nullptr)))) {
169 return cache ;
170 }
173
174 RooAbsReal* null = nullptr;
175 std::vector<RooAbsReal*> meanrv(nPdf*nVar,null);
176 std::vector<RooAbsReal*> sigmarv(nPdf*nVar,null);
177 std::vector<RooAbsReal*> myrms(nVar,null);
178 std::vector<RooAbsReal*> mypos(nVar,null);
179 std::vector<RooAbsReal*> slope(nPdf*nVar,null);
180 std::vector<RooAbsReal*> offs(nPdf*nVar,null);
181 std::vector<RooAbsReal*> transVar(nPdf*nVar,null);
182 std::vector<RooAbsReal*> transPdf(nPdf,null);
183
185
187
188 // fraction parameters
189 RooArgList coefList("coefList");
190 RooArgList coefList2("coefList2");
191 for (Int_t i=0; i<2*nPdf; ++i) {
192 std::string fracName = "frac_" + std::to_string(i);
193
194 RooRealVar* frac = new RooRealVar(fracName.c_str(),fracName.c_str(),1.) ;
195
196 fracl.add(*frac); // to be set later
197 if (i<nPdf) coefList.add(*frac);
198 else coefList2.add(*frac);
199 ownedComps.add(*frac);
200 }
201
202 std::unique_ptr<RooAddPdf> theSumPdf;
203 std::string sumpdfName = Form("%s_sumpdf",GetName());
204
205 if (_useHorizMorph) {
206 // mean and sigma
208 for (Int_t i=0; i<nPdf; ++i) {
209 for (Int_t j=0; j<nVar; ++j) {
210
211 std::string meanName = Form("%s_mean_%d_%d",GetName(),i,j);
212 std::string sigmaName = Form("%s_sigma_%d_%d",GetName(),i,j);
213
214 RooAbsMoment* mom = nVar==1 ?
215 (static_cast<RooAbsPdf*>(_pdfList.at(i)))->sigma(static_cast<RooRealVar&>(*varList.at(j))) :
216 (static_cast<RooAbsPdf*>(_pdfList.at(i)))->sigma(static_cast<RooRealVar&>(*varList.at(j)),varList) ;
217
218 mom->setLocalNoDirtyInhibit(true) ;
219 mom->mean()->setLocalNoDirtyInhibit(true) ;
220
221 sigmarv[ij(i,j)] = mom ;
222 meanrv[ij(i,j)] = mom->mean() ;
223
224 ownedComps.add(*sigmarv[ij(i,j)]) ;
225 }
226 }
227
228 // slope and offset (to be set later, depend on m)
229 for (Int_t j=0; j<nVar; ++j) {
230 RooArgList meanList("meanList");
231 RooArgList rmsList("rmsList");
232 for (Int_t i=0; i<nPdf; ++i) {
233 meanList.add(*meanrv[ij(i,j)]);
234 rmsList.add(*sigmarv[ij(i,j)]);
235 }
236 std::string myrmsName = Form("%s_rms_%d",GetName(),j);
237 std::string myposName = Form("%s_pos_%d",GetName(),j);
238 myrms[j] = new RooAddition(myrmsName.c_str(),myrmsName.c_str(),rmsList,coefList2);
239 mypos[j] = new RooAddition(myposName.c_str(),myposName.c_str(),meanList,coefList2);
240 ownedComps.add(RooArgSet(*myrms[j],*mypos[j])) ;
241 }
242
243 // construction of unit pdfs
245
246 for (Int_t i=0; i<nPdf; ++i) {
247
248 auto& pdf = static_cast<RooAbsPdf&>(_pdfList[i]);
249 std::string pdfName = "pdf_" + std::to_string(i);
250 RooCustomizer cust(pdf,pdfName.c_str());
251
252 for (Int_t j=0; j<nVar; ++j) {
253 // slope and offset formulas
254 std::string slopeName = Form("%s_slope_%d_%d",GetName(),i,j);
255 std::string offsetName = Form("%s_offset_%d_%d",GetName(),i,j);
256 slope[ij(i,j)] = new RooFormulaVar(slopeName.c_str(),"@0/@1", {*sigmarv[ij(i,j)],*myrms[j]});
257 offs[ij(i,j)] = new RooFormulaVar(offsetName.c_str(),"@0-(@1*@2)", {*meanrv[ij(i,j)],*mypos[j],*slope[ij(i,j)]});
258 ownedComps.add(RooArgSet(*slope[ij(i,j)],*offs[ij(i,j)])) ;
259 // linear transformations, so pdf can be renormalized
260 auto* var = static_cast<RooRealVar*>(_varList[j]);
261 std::string transVarName = Form("%s_transVar_%d_%d",GetName(),i,j);
262 //transVar[ij(i,j)] = new RooFormulaVar(transVarName.c_str(),transVarName.c_str(),"@0*@1+@2",RooArgList(*var,*slope[ij(i,j)],*offs[ij(i,j)]));
263
264 transVar[ij(i,j)] = new RooLinearVar(transVarName.c_str(),transVarName.c_str(),*var,*slope[ij(i,j)],*offs[ij(i,j)]);
265
266 // *** WVE this is important *** this declares that frac effectively depends on the morphing parameters
267 // This will prevent the likelihood optimizers from erroneously declaring terms constant
268 transVar[ij(i,j)]->addServer(const_cast<RooAbsReal&>(m.arg()));
269
270 ownedComps.add(*transVar[ij(i,j)]) ;
271 cust.replaceArg(*var,*transVar[ij(i,j)]);
272 }
273 transPdf[i] = static_cast<RooAbsPdf*>(cust.build()) ;
274 transPdfList.add(*transPdf[i]);
275 ownedComps.add(*transPdf[i]) ;
276 }
277 // sum pdf
278 theSumPdf = std::make_unique<RooAddPdf>(sumpdfName.c_str(),sumpdfName.c_str(),transPdfList,coefList);
279 }
280 else {
281 theSumPdf = std::make_unique<RooAddPdf>(sumpdfName.c_str(),sumpdfName.c_str(),_pdfList,coefList);
282 }
283 theSumPdf->fixCoefNormalization(*nset);
284
285 // *** WVE this is important *** this declares that frac effectively depends on the morphing parameters
286 // This will prevent the likelihood optimizers from erroneously declaring terms constant
287 theSumPdf->addServer(const_cast<RooAbsReal&>(m.arg()));
288 theSumPdf->addOwnedComponents(ownedComps) ;
289
290 // change tracker for fraction parameters
291 std::string trackerName = Form("%s_frac_tracker",GetName()) ;
292 auto tracker = std::make_unique<RooChangeTracker>(trackerName.c_str(),trackerName.c_str(),m.arg(),true) ;
293
294 // Store it in the cache
295 auto cache = new CacheElem(std::move(theSumPdf),std::move(tracker),fracl) ;
296 _cacheMgr.setObj(nullptr,nullptr,cache,nullptr);
297
298 cache->calculateFractions(*this, false);
299 return cache ;
300}
301
302////////////////////////////////////////////////////////////////////////////////
303
305{
306 return RooArgList(*_sumPdf,*_tracker) ;
307}
308
309////////////////////////////////////////////////////////////////////////////////
310
312
313////////////////////////////////////////////////////////////////////////////////
314/// Special version of getVal() overrides RooAbsReal::getVal() to save value of current normalization set
315
316double RooMomentMorph::getValV(const RooArgSet* set) const
317{
318 _curNormSet = set ? const_cast<RooArgSet*>(set) : const_cast<RooArgSet*>(static_cast<RooArgSet const*>(&_varList));
319 return RooAbsPdf::getValV(set) ;
320}
321
322////////////////////////////////////////////////////////////////////////////////
323
325{
326 CacheElem* cache = getCache(nset ? nset : _curNormSet) ;
327
328 if (cache->_tracker->hasChanged(true)) {
329 cache->calculateFractions(*this,false); // verbose turned off
330 }
331
332 return cache->_sumPdf.get();
333}
334
335////////////////////////////////////////////////////////////////////////////////
336
338{
339 CacheElem* cache = getCache(_curNormSet) ;
340
341 if (cache->_tracker->hasChanged(true)) {
342 cache->calculateFractions(*this,false); // verbose turned off
343 }
344
345 return cache->_sumPdf->getVal(_pdfList.nset());
346}
347
348////////////////////////////////////////////////////////////////////////////////
349
351{
352 return static_cast<RooRealVar*>(_frac.at(i)) ;
353}
354
355////////////////////////////////////////////////////////////////////////////////
356
358{
359 return static_cast<RooRealVar*>(_frac.at(i)) ;
360}
361
362////////////////////////////////////////////////////////////////////////////////
363
365{
366 Int_t nPdf = self._pdfList.size();
367
368 double dm = self.m - (*self._mref)[0];
369
370 // fully non-linear
371 double sumposfrac=0.;
372 for (Int_t i=0; i<nPdf; ++i) {
373 double ffrac=0.;
374 for (Int_t j=0; j<nPdf; ++j) { ffrac += (*self._M)(j,i) * (j==0?1.:std::pow(dm,(double)j)); }
375 if (ffrac>=0) sumposfrac+=ffrac;
376 // fractions for pdf
377 const_cast<RooRealVar*>(frac(i))->setVal(ffrac);
378 // fractions for rms and mean
379 const_cast<RooRealVar*>(frac(nPdf+i))->setVal(ffrac);
380 if (verbose) { std::cout << ffrac << std::endl; }
381 }
382
383 // various mode settings
384 int imin = self.idxmin(self.m);
385 int imax = self.idxmax(self.m);
386 double mfrac = (self.m-(*self._mref)[imin])/((*self._mref)[imax]-(*self._mref)[imin]);
387 switch (self._setting) {
388 case NonLinear:
389 // default already set above
390 break;
391
392 case SineLinear:
393 mfrac = std::sin( TMath::PiOver2()*mfrac ); // this gives a continuous differentiable transition between grid points.
394
395 // now fall through to Linear case
396
397 case Linear:
398 for (Int_t i=0; i<2*nPdf; ++i)
399 const_cast<RooRealVar*>(frac(i))->setVal(0.);
400 if (imax>imin) { // m in between mmin and mmax
401 const_cast<RooRealVar*>(frac(imin))->setVal(1.-mfrac);
402 const_cast<RooRealVar*>(frac(nPdf+imin))->setVal(1.-mfrac);
403 const_cast<RooRealVar*>(frac(imax))->setVal(mfrac);
404 const_cast<RooRealVar*>(frac(nPdf+imax))->setVal(mfrac);
405 } else if (imax==imin) { // m outside mmin and mmax
406 const_cast<RooRealVar*>(frac(imin))->setVal(1.);
407 const_cast<RooRealVar*>(frac(nPdf+imin))->setVal(1.);
408 }
409 break;
411 for (Int_t i=0; i<nPdf; ++i)
412 const_cast<RooRealVar*>(frac(i))->setVal(0.);
413 if (imax>imin) { // m in between mmin and mmax
414 const_cast<RooRealVar*>(frac(imin))->setVal(1.-mfrac);
415 const_cast<RooRealVar*>(frac(imax))->setVal(mfrac);
416 } else if (imax==imin) { // m outside mmin and mmax
417 const_cast<RooRealVar*>(frac(imin))->setVal(1.);
418 }
419 break;
421 for (Int_t i = 0; i < nPdf; ++i) {
422 if (frac(i)->getVal() < 0)
423 const_cast<RooRealVar *>(frac(i))->setVal(0.);
424 const_cast<RooRealVar *>(frac(i))->setVal(frac(i)->getVal() / sumposfrac);
425 }
426 break;
427 }
428
429}
430
431////////////////////////////////////////////////////////////////////////////////
432
433int RooMomentMorph::idxmin(const double& mval) const
434{
435 int imin(0);
437 double mmin=-DBL_MAX;
438 for (Int_t i=0; i<nPdf; ++i)
439 if ( (*_mref)[i]>mmin && (*_mref)[i]<=mval ) { mmin=(*_mref)[i]; imin=i; }
440 return imin;
441}
442
443
444////////////////////////////////////////////////////////////////////////////////
445
446int RooMomentMorph::idxmax(const double& mval) const
447{
448 int imax(0);
450 double mmax=DBL_MAX;
451 for (Int_t i=0; i<nPdf; ++i)
452 if ( (*_mref)[i]<mmax && (*_mref)[i]>=mval ) { mmax=(*_mref)[i]; imax=i; }
453 return imax;
454}
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
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
double getValV(const RooArgSet *set=nullptr) const override
Return current value, normalized by integrating over the observables in nset.
const RooArgSet * nset() const
Definition RooAbsProxy.h:52
Abstract base class for objects that represent a real value and implements functionality common to al...
Definition RooAbsReal.h:63
double getVal(const RooArgSet *normalisationSet=nullptr) const
Evaluate object.
Definition RooAbsReal.h:107
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.
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...
RooArgList containedArgs(Action) override
CacheElem(std::unique_ptr< RooAbsPdf > &&sumPdf, std::unique_ptr< RooChangeTracker > &&tracker, const RooArgList &flist)
RooRealVar * frac(Int_t i)
void calculateFractions(const RooMomentMorph &self, bool verbose=true) const
std::unique_ptr< RooAbsPdf > _sumPdf
std::unique_ptr< RooChangeTracker > _tracker
RooObjCacheManager _cacheMgr
! The cache manager
friend class CacheElem
~RooMomentMorph() override
RooSetProxy _varList
double evaluate() const override
Evaluate this PDF / function / constant. Needs to be overridden by all derived classes.
RooMomentMorph()
coverity[UNINIT_CTOR]
RooRealProxy m
RooAbsPdf * sumPdf(const RooArgSet *nset)
Int_t ij(const Int_t &i, const Int_t &j) const
RooArgSet * _curNormSet
! Current normalization set
RooListProxy _pdfList
int idxmin(const double &m) const
int idxmax(const double &m) const
double getValV(const RooArgSet *set=nullptr) const override
Special version of getVal() overrides RooAbsReal::getVal() to save value of current normalization set...
CacheElem * getCache(const RooArgSet *nset) const
TVectorD * _mref
Variable that can be changed from the outside.
Definition RooRealVar.h:37
void setVal(double value) override
Set value of variable to 'value'.
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