Logo ROOT  
Reference Guide
RooNDKeysPdf.cxx
Go to the documentation of this file.
1/*****************************************************************************
2 * Project: RooFit *
3 * Package: RooFitModels *
4 * File: $Id: RooNDKeysPdf.cxx 31258 2009-11-17 22:41:06Z wouter $
5 * Authors: *
6 * Max Baak, CERN, mbaak@cern.ch *
7 * *
8 * Redistribution and use in source and binary forms, *
9 * with or without modification, are permitted according to the terms *
10 * listed in LICENSE (http://roofit.sourceforge.net/license.txt) *
11 *****************************************************************************/
12
13/** \class RooNDKeysPdf
14 \ingroup Roofit
15
16Generic N-dimensional implementation of a kernel estimation p.d.f. This p.d.f. models the distribution
17of an arbitrary input dataset as a superposition of Gaussian kernels, one for each data point,
18each contributing 1/N to the total integral of the p.d.f.
19If the 'adaptive mode' is enabled, the width of the Gaussian is adaptively calculated from the
20local density of events, i.e. narrow for regions with high event density to preserve details and
21wide for regions with log event density to promote smoothness. The details of the general algorithm
22are described in the following paper:
23Cranmer KS, Kernel Estimation in High-Energy Physics.
24 Computer Physics Communications 136:198-207,2001 - e-Print Archive: hep ex/0011057
25For multi-dimensional datasets, the kernels are modeled by multidimensional Gaussians. The kernels are
26constructed such that they reflect the correlation coefficients between the observables
27in the input dataset.
28**/
29
30#include <iostream>
31#include <algorithm>
32#include <string>
33
34#include "TMath.h"
35#include "TMatrixDSymEigen.h"
36#include "RooNDKeysPdf.h"
37#include "RooAbsReal.h"
38#include "RooRealVar.h"
39#include "RooRandom.h"
40#include "RooHist.h"
41#include "RooMsgService.h"
42#include "RooChangeTracker.h"
43
44#include "TError.h"
45
46using namespace std;
47
49
50////////////////////////////////////////////////////////////////////////////////
51/// Construct N-dimensional kernel estimation p.d.f. in observables 'varList'
52/// from dataset 'data'. Options can be
53///
54/// - 'a' = Use adaptive kernels (width varies with local event density)
55/// - 'm' = Mirror data points over observable boundaries. Improves modeling
56/// behavior at edges for distributions that are not close to zero
57/// at edge
58/// - 'd' = Debug flag
59/// - 'v' = Verbose flag
60///
61/// The parameter rho (default = 1) provides an overall scale factor that can
62/// be applied to the bandwith calculated for each kernel. The nSigma parameter
63/// determines the size of the box that is used to search for contributing kernels
64/// around a given point in observable space. The nSigma parameters is used
65/// in case of non-adaptive bandwidths and for the 1st non-adaptive pass for
66/// the calculation of adaptive keys p.d.f.s.
67///
68/// The optional weight arguments allows to specify an observable or function
69/// expression in observables that specifies the weight of each event.
70
71RooNDKeysPdf::RooNDKeysPdf(const char *name, const char *title, const RooArgList &varList, const RooDataSet &data,
72 TString options, Double_t rho, Double_t nSigma, Bool_t rotate, Bool_t sortInput)
73 : RooAbsPdf(name, title), _varList("varList", "List of variables", this),
74 _rhoList("rhoList", "List of rho parameters", this), _data(&data), _options(options), _widthFactor(rho),
75 _nSigma(nSigma), _weights(&_weights0), _rotate(rotate), _sortInput(sortInput), _nAdpt(1), _tracker(0)
76{
77 // Constructor
78
79 for (const auto var : varList) {
80 if (!dynamic_cast<const RooAbsReal*>(var)) {
81 coutE(InputArguments) << "RooNDKeysPdf::ctor(" << GetName() << ") ERROR: variable " << var->GetName()
82 << " is not of type RooAbsReal" << endl ;
83 R__ASSERT(0) ;
84 }
85 _varList.add(*var) ;
86 _varName.push_back(var->GetName());
87 }
88
89 createPdf();
90}
91
92////////////////////////////////////////////////////////////////////////////////
93/// Constructor
94
95RooNDKeysPdf::RooNDKeysPdf(const char *name, const char *title, const RooArgList &varList, const TH1 &hist,
96 TString options, Double_t rho, Double_t nSigma, Bool_t rotate, Bool_t sortInput)
97 : RooAbsPdf(name, title), _varList("varList", "List of variables", this),
98 _rhoList("rhoList", "List of rho parameters", this), _ownedData(createDatasetFromHist(varList, hist)), _data(_ownedData.get()),
99 _options(options), _widthFactor(rho), _nSigma(nSigma), _weights(&_weights0), _rotate(rotate),
100 _sortInput(sortInput), _nAdpt(1), _tracker(0)
101{
102 for (const auto var : varList) {
103 if (!dynamic_cast<const RooAbsReal *>(var)) {
104 coutE(InputArguments) << "RooNDKeysPdf::ctor(" << GetName() << ") ERROR: variable " << var->GetName()
105 << " is not of type RooAbsReal" << endl;
106 assert(0);
107 }
108 _varList.add(*var);
109 _varName.push_back(var->GetName());
110 }
111
112 createPdf();
113}
114
115////////////////////////////////////////////////////////////////////////////////
116/// Constructor
117
118RooNDKeysPdf::RooNDKeysPdf(const char *name, const char *title, const RooArgList &varList, const RooDataSet &data,
119 const TVectorD &rho, TString options, Double_t nSigma, Bool_t rotate, Bool_t sortInput)
120 : RooAbsPdf(name, title), _varList("varList", "List of variables", this),
121 _rhoList("rhoList", "List of rho parameters", this), _data(&data), _options(options), _widthFactor(-1.0),
122 _nSigma(nSigma), _weights(&_weights0), _rotate(rotate), _sortInput(sortInput), _nAdpt(1), _tracker(0)
123{
124 for (const auto var : varList) {
125 if (!dynamic_cast<const RooAbsReal*>(var)) {
126 coutE(InputArguments) << "RooNDKeysPdf::ctor(" << GetName() << ") ERROR: variable " << var->GetName()
127 << " is not of type RooAbsReal" << endl;
128 R__ASSERT(0);
129 }
130 _varList.add(*var) ;
131 _varName.push_back(var->GetName());
132 }
133
134 // copy rho widths
135 if( _varList.getSize() != rho.GetNrows() ) {
137 << "ERROR: RooNDKeysPdf::RooNDKeysPdf() : The vector-size of rho is different from that of varList."
138 << "Unable to create the PDF." << endl;
140 }
141
142 // negative width factor will serve as a switch in initialize()
143 // negative value means that a vector has been provided as input,
144 // and that _rho has already been set ...
145 _rho.resize( rho.GetNrows() );
146 for (Int_t j = 0; j < rho.GetNrows(); j++) {
147 _rho[j] = rho[j]; /*cout<<"RooNDKeysPdf ctor, _rho["<<j<<"]="<<_rho[j]<<endl;*/
148 }
149
150 createPdf(); // calls initialize ...
151}
152
153////////////////////////////////////////////////////////////////////////////////
154/// Backward compatibility constructor for (1-dim) RooKeysPdf. If you are a new user,
155/// please use the first constructor form.
156
157RooNDKeysPdf::RooNDKeysPdf(const char *name, const char *title, const RooArgList &varList, const RooDataSet &data,
158 const RooArgList &rhoList, TString options, Double_t nSigma, Bool_t rotate, Bool_t sortInput)
159 : RooAbsPdf(name, title), _varList("varList", "List of variables", this),
160 _rhoList("rhoList", "List of rho parameters", this), _data(&data), _options(options), _widthFactor(-1.0),
161 _nSigma(nSigma), _weights(&_weights0), _rotate(rotate), _sortInput(sortInput), _nAdpt(1)
162{
163 for (const auto var : varList) {
164 if (!dynamic_cast<RooAbsReal *>(var)) {
165 coutE(InputArguments) << "RooNDKeysPdf::ctor(" << GetName() << ") ERROR: variable " << var->GetName()
166 << " is not of type RooAbsReal" << endl;
167 assert(0);
168 }
169 _varList.add(*var);
170 _varName.push_back(var->GetName());
171 }
172
173 _rho.resize(rhoList.getSize(), 1.0);
174
175 for (unsigned int i=0; i < rhoList.size(); ++i) {
176 const auto rho = rhoList.at(i);
177 if (!dynamic_cast<const RooAbsReal *>(rho)) {
178 coutE(InputArguments) << "RooNDKeysPdf::ctor(" << GetName() << ") ERROR: parameter " << rho->GetName()
179 << " is not of type RooRealVar" << endl;
180 assert(0);
181 }
182 _rhoList.add(*rho);
183 _rho[i] = (dynamic_cast<RooAbsReal *>(rho))->getVal();
184 }
185
186 // copy rho widths
187 if ((_varList.getSize() != _rhoList.getSize())) {
188 coutE(InputArguments) << "ERROR: RooNDKeysPdf::RooNDKeysPdf() : The size of rhoList is different from varList."
189 << "Unable to create the PDF." << endl;
190 assert(_varList.getSize() == _rhoList.getSize());
191 }
192
193 // keep track of changes in rho parameters
194 _tracker = new RooChangeTracker("tracker", "track rho parameters", _rhoList, true); // check for value updates
195 (void)_tracker->hasChanged(true); // first evaluation always true for new parameters (?)
196
197 createPdf();
198}
199
200////////////////////////////////////////////////////////////////////////////////
201/// Constructor
202
203RooNDKeysPdf::RooNDKeysPdf(const char *name, const char *title, const RooArgList &varList, const TH1 &hist,
204 const RooArgList &rhoList, TString options, Double_t nSigma, Bool_t rotate, Bool_t sortInput)
205 : RooAbsPdf(name, title), _varList("varList", "List of variables", this),
206 _rhoList("rhoList", "List of rho parameters", this), _ownedData(createDatasetFromHist(varList, hist)), _data(_ownedData.get()),
207 _options(options), _widthFactor(-1), _nSigma(nSigma), _weights(&_weights0), _rotate(rotate), _sortInput(sortInput),
208 _nAdpt(1)
209{
210 for (const auto var : varList) {
211 if (!dynamic_cast<RooAbsReal *>(var)) {
212 coutE(InputArguments) << "RooNDKeysPdf::ctor(" << GetName() << ") ERROR: variable " << var->GetName()
213 << " is not of type RooAbsReal" << endl;
214 assert(0);
215 }
216 _varList.add(*var);
217 _varName.push_back(var->GetName());
218 }
219
220 // copy rho widths
221 _rho.resize(rhoList.getSize(), 1.0);
222
223 for (unsigned int i=0; i < rhoList.size(); ++i) {
224 const auto rho = rhoList.at(i);
225 if (!dynamic_cast<RooAbsReal *>(rho)) {
226 coutE(InputArguments) << "RooNDKeysPdf::ctor(" << GetName() << ") ERROR: parameter " << rho->GetName()
227 << " is not of type RooRealVar" << endl;
228 assert(0);
229 }
230 _rhoList.add(*rho);
231 _rho[i] = (dynamic_cast<RooAbsReal *>(rho))->getVal();
232 }
233
234 if ((_varList.getSize() != _rhoList.getSize())) {
235 coutE(InputArguments) << "ERROR: RooNDKeysPdf::RooNDKeysPdf() : The size of rhoList is different from varList."
236 << "Unable to create the PDF." << endl;
237 assert(_varList.getSize() == _rhoList.getSize());
238 }
239
240 // keep track of changes in rho parameters
241 _tracker = new RooChangeTracker("tracker", "track rho parameters", _rhoList, true); // check for value updates
242 (void)_tracker->hasChanged(true); // first evaluation always true for new parameters (?)
243
244 createPdf();
245}
246
247////////////////////////////////////////////////////////////////////////////////
248/// Constructor
249
250RooNDKeysPdf::RooNDKeysPdf(const char *name, const char *title, RooAbsReal &x, const RooDataSet &data, Mirror mirror,
251 Double_t rho, Double_t nSigma, Bool_t rotate, Bool_t sortInput)
252 : RooAbsPdf(name, title), _varList("varList", "List of variables", this),
253 _rhoList("rhoList", "List of rho parameters", this), _data(&data), _options("a"), _widthFactor(rho),
254 _nSigma(nSigma), _weights(&_weights0), _rotate(rotate), _sortInput(sortInput), _nAdpt(1), _tracker(0)
255{
256 _varList.add(x);
257 _varName.push_back(x.GetName());
258
259 if (mirror != NoMirror) {
260 if (mirror != MirrorBoth)
261 coutW(InputArguments) << "RooNDKeysPdf::RooNDKeysPdf() : Warning : asymmetric mirror(s) no longer supported."
262 << endl;
263 _options = "m";
264 }
265
266 createPdf();
267}
268
269////////////////////////////////////////////////////////////////////////////////
270/// Backward compatibility constructor for Roo2DKeysPdf. If you are a new user,
271/// please use the first constructor form.
272
273RooNDKeysPdf::RooNDKeysPdf(const char *name, const char *title, RooAbsReal &x, RooAbsReal &y, const RooDataSet &data,
274 TString options, Double_t rho, Double_t nSigma, Bool_t rotate, Bool_t sortInput)
275 : RooAbsPdf(name, title), _varList("varList", "List of variables", this),
276 _rhoList("rhoList", "List of rho parameters", this), _data(&data), _options(options), _widthFactor(rho),
277 _nSigma(nSigma), _weights(&_weights0), _rotate(rotate), _sortInput(sortInput), _nAdpt(1), _tracker(0)
278{
280 _varName.push_back(x.GetName());
281 _varName.push_back(y.GetName());
282
283 createPdf();
284}
285
286////////////////////////////////////////////////////////////////////////////////
287/// Constructor
288
290 : RooAbsPdf(other, name), _varList("varList", this, other._varList), _rhoList("rhoList", this, other._rhoList),
291 _ownedData(other._ownedData ? new RooDataSet(*other._ownedData) : nullptr),
292 _data(_ownedData ? _ownedData.get() : other._data), _options(other._options), _widthFactor(other._widthFactor),
293 _nSigma(other._nSigma), _weights(&_weights0), _rotate(other._rotate), _sortInput(other._sortInput),
294 _nAdpt(other._nAdpt)
295{
296 _tracker = (other._tracker != NULL ? new RooChangeTracker(*other._tracker) : NULL);
297 // if (_tracker!=NULL) { _tracker->hasChanged(true); }
298
299 _fixedShape = other._fixedShape;
300 _mirror = other._mirror;
301 _debug = other._debug;
302 _verbose = other._verbose;
303 _nDim = other._nDim;
304 _nEvents = other._nEvents;
305 _nEventsM = other._nEventsM;
306 _nEventsW = other._nEventsW;
307 _d = other._d;
308 _n = other._n;
309 _dataPts = other._dataPts;
310 _dataPtsR = other._dataPtsR;
311 _weights0 = other._weights0;
312 _weights1 = other._weights1;
313 if (_options.Contains("a")) {
315 }
316 _sortTVIdcs = other._sortTVIdcs;
317 _varName = other._varName;
318 _rho = other._rho;
319 _x = other._x;
320 _x0 = other._x0;
321 _x1 = other._x1;
322 _x2 = other._x2;
323 _xDatLo = other._xDatLo;
324 _xDatHi = other._xDatHi;
325 _xDatLo3s = other._xDatLo3s;
326 _xDatHi3s = other._xDatHi3s;
327 _mean = other._mean;
328 _sigma = other._sigma;
329
330 // BoxInfo
331 _netFluxZ = other._netFluxZ;
332 _nEventsBW = other._nEventsBW;
334 _xVarLo = other._xVarLo;
335 _xVarHi = other._xVarHi;
336 _xVarLoM3s = other._xVarLoM3s;
337 _xVarLoP3s = other._xVarLoP3s;
338 _xVarHiM3s = other._xVarHiM3s;
339 _xVarHiP3s = other._xVarHiP3s;
340 _bpsIdcs = other._bpsIdcs;
341 _ibNoSort = other._ibNoSort;
342 _sIdcs = other._sIdcs;
343 _bIdcs = other._bIdcs;
344 _bmsIdcs = other._bmsIdcs;
345
348
349 _idx = other._idx;
350 _minWeight = other._minWeight;
351 _maxWeight = other._maxWeight;
352 _wMap = other._wMap;
353
354 _covMat = new TMatrixDSym(*other._covMat);
355 _corrMat = new TMatrixDSym(*other._corrMat);
356 _rotMat = new TMatrixD(*other._rotMat);
357 _sigmaR = new TVectorD(*other._sigmaR);
358 _dx = new TVectorD(*other._dx);
359 _sigmaAvgR = other._sigmaAvgR;
360}
361
362////////////////////////////////////////////////////////////////////////////////
363
365{
366 if (_covMat) delete _covMat;
367 if (_corrMat) delete _corrMat;
368 if (_rotMat) delete _rotMat;
369 if (_sigmaR) delete _sigmaR;
370 if (_dx) delete _dx;
371 if (_tracker)
372 delete _tracker;
373
374 // delete all the boxinfos map
375 while ( !_rangeBoxInfo.empty() ) {
376 map<pair<string,int>,BoxInfo*>::iterator iter = _rangeBoxInfo.begin();
377 BoxInfo* box= (*iter).second;
378 _rangeBoxInfo.erase(iter);
379 delete box;
380 }
381}
382
383////////////////////////////////////////////////////////////////////////////////
384/// evaluation order of constructor.
385
387{
388 if (firstCall) {
389 // set options
390 setOptions();
391 // initialization
392 initialize();
393 }
394
395
396 // copy dataset, calculate sigma_i's, determine min and max event weight
397 loadDataSet(firstCall);
398
399 // mirror dataset around dataset boundaries -- does not depend on event weights
400 if (_mirror) mirrorDataSet();
401
402 // store indices and weights of events with high enough weights
404
405 // store indices of events in variable boundaries and box shell.
406//calculateShell(&_fullBoxInfo);
407 // calculate normalization needed in analyticalIntegral()
408//calculatePreNorm(&_fullBoxInfo);
409
410 // lookup table for determining which events contribute to a certain coordinate
411 const_cast<RooNDKeysPdf*>(this)->sortDataIndices();
412
413 // determine static and/or adaptive bandwidth
415}
416
417////////////////////////////////////////////////////////////////////////////////
418/// set the configuration
419
421{
423
424 if( _options.Contains("a") ) { _weights = &_weights1; }
425 else { _weights = &_weights0; }
426 if( _options.Contains("m") ) _mirror = true;
427 else _mirror = false;
428 if( _options.Contains("d") ) _debug = true;
429 else _debug = false;
430 if( _options.Contains("v") ) { _debug = true; _verbose = true; }
431 else { _debug = false; _verbose = false; }
432
433 cxcoutD(InputArguments) << "RooNDKeysPdf::setOptions() options = " << _options
434 << "\n\tbandWidthType = " << _options.Contains("a")
435 << "\n\tmirror = " << _mirror
436 << "\n\tdebug = " << _debug
437 << "\n\tverbose = " << _verbose
438 << endl;
439
440 if (_nSigma<2.0) {
441 coutW(InputArguments) << "RooNDKeysPdf::setOptions() : Warning : nSigma = " << _nSigma << " < 2.0. "
442 << "Calculated normalization could be too large."
443 << endl;
444 }
445
446 // number of adaptive width iterations. Default is 1.
447 if (_options.Contains("a")) {
448 if (!sscanf(_options.Data(), "%d%*s", &_nAdpt)) {
449 _nAdpt = 1;
450 }
451 }
452}
453
454////////////////////////////////////////////////////////////////////////////////
455/// initialization
456
458{
463
465 _nEventsBW = 0;
466 _nEventsBMSW = 0;
467
468 if(_nDim==0) {
469 coutE(InputArguments) << "ERROR: RooNDKeysPdf::initialize() : The observable list is empty. "
470 << "Unable to begin generating the PDF." << endl;
471 R__ASSERT (_nDim!=0);
472 }
473
474 if(_nEvents==0) {
475 coutE(InputArguments) << "ERROR: RooNDKeysPdf::initialize() : The input data set is empty. "
476 << "Unable to begin generating the PDF." << endl;
477 R__ASSERT (_nEvents!=0);
478 }
479
480 _d = static_cast<Double_t>(_nDim);
481
482 vector<Double_t> dummy(_nDim,0.);
483 _dataPts.resize(_nEvents,dummy);
484 _weights0.resize(_nEvents,dummy);
485
486 //rdh _rho.resize(_nDim,_widthFactor);
487
488 if (_widthFactor>0) { _rho.resize(_nDim,_widthFactor); }
489 // else: _rho has been provided as external input
490
491 _x.resize(_nDim,0.);
492 _x0.resize(_nDim,0.);
493 _x1.resize(_nDim,0.);
494 _x2.resize(_nDim,0.);
495
496 _mean.resize(_nDim,0.);
497 _sigma.resize(_nDim,0.);
498
499 _xDatLo.resize(_nDim,0.);
500 _xDatHi.resize(_nDim,0.);
501 _xDatLo3s.resize(_nDim,0.);
502 _xDatHi3s.resize(_nDim,0.);
503
504 boxInfoInit(&_fullBoxInfo,0,0xFFFF);
505
506 _minWeight=0;
507 _maxWeight=0;
508 _wMap.clear();
509
510 _covMat = 0;
511 _corrMat= 0;
512 _rotMat = 0;
513 _sigmaR = 0;
514 _dx = new TVectorD(_nDim); _dx->Zero();
515 _dataPtsR.resize(_nEvents,*_dx);
516
517 for(unsigned int j=0; j < _varList.size(); ++j) {
518 auto& var = static_cast<const RooRealVar&>(_varList[j]);
519 _xDatLo[j] = var.getMin();
520 _xDatHi[j] = var.getMax();
521 }
522}
523
524////////////////////////////////////////////////////////////////////////////////
525/// copy the dataset and calculate some useful variables
526
528{
529 // first some initialization
530 _nEventsW=0.;
531
532 TMatrixD mat(_nDim,_nDim);
533 if (!_covMat) _covMat = new TMatrixDSym(_nDim);
535 if (!_rotMat) _rotMat = new TMatrixD(_nDim,_nDim);
536 if (!_sigmaR) _sigmaR = new TVectorD(_nDim);
537
538 mat.Zero();
539 _covMat->Zero();
540 _corrMat->Zero();
541 _rotMat->Zero();
542 _sigmaR->Zero();
543
544 const RooArgSet* values= _data->get();
545 vector<RooRealVar*> dVars(_nDim);
546 for (Int_t j=0; j<_nDim; j++) {
547 dVars[j] = (RooRealVar*)values->find(_varName[j].c_str());
548 _x0[j]=_x1[j]=_x2[j]=0.;
549 }
550
551 _idx.clear();
552 for (Int_t i=0; i<_nEvents; i++) {
553
554 _data->get(i); // fills dVars
555 _idx.push_back(i);
556 vector<Double_t>& point = _dataPts[i];
557 TVectorD& pointV = _dataPtsR[i];
558
559 Double_t myweight = _data->weight(); // default is one?
560 if ( TMath::Abs(myweight)>_maxWeight ) { _maxWeight = TMath::Abs(myweight); }
561 _nEventsW += myweight;
562
563 for (Int_t j=0; j<_nDim; j++) {
564 for (Int_t k=0; k<_nDim; k++) {
565 mat(j,k) += dVars[j]->getVal() * dVars[k]->getVal() * myweight;
566 }
567 // only need to do once
568 if (firstCall)
569 point[j] = pointV[j] = dVars[j]->getVal();
570
571 _x0[j] += 1. * myweight;
572 _x1[j] += point[j] * myweight ;
573 _x2[j] += point[j] * point[j] * myweight ;
574 if (_x2[j]!=_x2[j]) exit(3);
575
576 // only need to do once
577 if (firstCall) {
578 if (point[j]<_xDatLo[j]) { _xDatLo[j]=point[j]; }
579 if (point[j]>_xDatHi[j]) { _xDatHi[j]=point[j]; }
580 }
581 }
582 }
583
584 _n = TMath::Power(4./(_nEventsW*(_d+2.)), 1./(_d+4.)) ;
585 // = (4/[n(dim(R) + 2)])^1/(dim(R)+4); dim(R) = 2
586 _minWeight = (0.5 - TMath::Erf(_nSigma/sqrt(2.))/2.) * _maxWeight;
587
588 for (Int_t j=0; j<_nDim; j++) {
589 _mean[j] = _x1[j]/_x0[j];
590 _sigma[j] = sqrt(_x2[j]/_x0[j]-_mean[j]*_mean[j]);
591 }
592
593 for (Int_t j=0; j<_nDim; j++) {
594 for (Int_t k=0; k<_nDim; k++) {
595 (*_covMat)(j,k) = mat(j,k)/_x0[j] - _mean[j]*_mean[k];
596 }
597 }
598
599 for (Int_t j=0; j<_nDim; j++) {
600 for (Int_t k=0; k<_nDim; k++)
601 (*_corrMat)(j,k) = (*_covMat)(j,k)/(_sigma[j]*_sigma[k]) ;
602 }
603
604 // use raw sigmas (without rho) for sigmaAvgR
605 TMatrixDSymEigen evCalculator(*_covMat);
606 TVectorD sigmaRraw = evCalculator.GetEigenValues();
607 for (Int_t j=0; j<_nDim; j++) { sigmaRraw[j] = sqrt(sigmaRraw[j]); }
608
609 _sigmaAvgR=1.;
610 for (Int_t j=0; j<_nDim; j++) { _sigmaAvgR *= sigmaRraw[j]; }
612
613 // find decorrelation matrix and eigenvalues (R)
614 if (_nDim > 1 && _rotate) {
615 // new: rotation matrix now independent of rho evaluation
616 *_rotMat = evCalculator.GetEigenVectors();
617 *_rotMat = _rotMat->T(); // transpose
618 } else {
619 TMatrixD haar(_nDim, _nDim);
620 TMatrixD unit(TMatrixD::kUnit, haar);
621 *_rotMat = unit;
622 }
623
624 // update sigmas (rho dependent)
625 updateRho();
626
627 //// rho no longer used after this.
628 //// Now set rho = 1 because sigmaR now contains rho
629 // for (Int_t j=0; j<_nDim; j++) { _rho[j] = 1.; } // reset: important!
630
631 if (_verbose) {
632 //_covMat->Print();
633 _rotMat->Print();
634 _corrMat->Print();
635 _sigmaR->Print();
636 }
637
638 if (_nDim > 1 && _rotate) {
639 // apply rotation
640 for (Int_t i = 0; i < _nEvents; i++) {
641 TVectorD &pointR = _dataPtsR[i];
642 pointR *= *_rotMat;
643 }
644 }
645
646 coutI(Contents) << "RooNDKeysPdf::loadDataSet(" << this << ")"
647 << "\n Number of events in dataset: " << _nEvents
648 << "\n Weighted number of events in dataset: " << _nEventsW << endl;
649}
650
651////////////////////////////////////////////////////////////////////////////////
652/// determine mirror dataset.
653/// mirror points are added around the physical boundaries of the dataset
654/// Two steps:
655/// 1. For each entry, determine if it should be mirrored (the mirror configuration).
656/// 2. For each mirror configuration, make the mirror points.
657
659{
660 for (Int_t j=0; j<_nDim; j++) {
661 _xDatLo3s[j] = _xDatLo[j] + _nSigma * (_n * _sigma[j]);
662 _xDatHi3s[j] = _xDatHi[j] - _nSigma * (_n * _sigma[j]);
663
664 // cout<<"xDatLo3s["<<j<<"]="<<_xDatLo3s[j]<<endl;
665 // cout<<"xDatHi3s["<<j<<"]="<<_xDatHi3s[j]<<endl;
666 }
667
668 vector<Double_t> dummy(_nDim,0.);
669
670 // 1.
671 for (Int_t i=0; i<_nEvents; i++) {
672 vector<Double_t>& x = _dataPts[i];
673
674 Int_t size = 1;
675 vector<vector<Double_t> > mpoints(size,dummy);
676 vector<vector<Int_t> > mjdcs(size);
677
678 // create all mirror configurations for event i
679 for (Int_t j=0; j<_nDim; j++) {
680
681 vector<Int_t>& mjdxK = mjdcs[0];
682 vector<Double_t>& mpointK = mpoints[0];
683
684 // single mirror *at physical boundaries*
685 if ((x[j]>_xDatLo[j] && x[j]<_xDatLo3s[j]) && x[j]<(_xDatLo[j]+_xDatHi[j])/2.) {
686 mpointK[j] = 2.*_xDatLo[j]-x[j];
687 mjdxK.push_back(j);
688 } else if ((x[j]<_xDatHi[j] && x[j]>_xDatHi3s[j]) && x[j]>(_xDatLo[j]+_xDatHi[j])/2.) {
689 mpointK[j] = 2.*_xDatHi[j]-x[j];
690 mjdxK.push_back(j);
691 }
692 }
693
694 vector<Int_t>& mjdx0 = mjdcs[0];
695 // no mirror point(s) for this event
696 if (size==1 && mjdx0.size()==0) continue;
697
698 // 2.
699 // generate all mirror points for event i
700 vector<Int_t>& mjdx = mjdcs[0];
701 vector<Double_t>& mpoint = mpoints[0];
702
703 // number of mirror points for this mirror configuration
704 Int_t eMir = 1 << mjdx.size();
705 vector<vector<Double_t> > epoints(eMir,x);
706
707 for (Int_t m=0; m<Int_t(mjdx.size()); m++) {
708 Int_t size1 = 1 << m;
709 Int_t size2 = 1 << (m+1);
710 // copy all previous mirror points
711 for (Int_t l=size1; l<size2; ++l) {
712 epoints[l] = epoints[l-size1];
713 // fill high mirror points
714 vector<Double_t>& epoint = epoints[l];
715 epoint[mjdx[Int_t(mjdx.size()-1)-m]] = mpoint[mjdx[Int_t(mjdx.size()-1)-m]];
716 }
717 }
718
719 // remove duplicate mirror points
720 // note that: first epoint == x
721 epoints.erase(epoints.begin());
722
723 // add mirror points of event i to total dataset
724 TVectorD pointR(_nDim);
725
726 for (Int_t m=0; m<Int_t(epoints.size()); m++) {
727 _idx.push_back(i);
728 _dataPts.push_back(epoints[m]);
729 //_weights0.push_back(_weights0[i]);
730 for (Int_t j=0; j<_nDim; j++) { pointR[j] = (epoints[m])[j]; }
731 if (_nDim > 1 && _rotate) {
732 pointR *= *_rotMat;
733 }
734 _dataPtsR.push_back(pointR);
735 }
736
737 epoints.clear();
738 mpoints.clear();
739 mjdcs.clear();
740 } // end of event loop
741
742 _nEventsM = Int_t(_dataPts.size());
743}
744
745////////////////////////////////////////////////////////////////////////////////
746
748{
749 _wMap.clear();
750
751 for (Int_t i=0; i<_nEventsM; i++) {
752 _data->get(_idx[i]);
753 Double_t myweight = _data->weight();
754 //if ( TMath::Abs(myweight)>_minWeight ) {
755 _wMap[i] = myweight;
756 //}
757 }
758
759 coutI(Contents) << "RooNDKeysPdf::loadWeightSet(" << this << ") : Number of weighted events : " << _wMap.size() << endl;
760}
761
762////////////////////////////////////////////////////////////////////////////////
763/// determine points in +/- nSigma shell around the box determined by the variable
764/// ranges. These points are needed in the normalization, to determine probability
765/// leakage in and out of the box.
766
768{
769 for (Int_t j=0; j<_nDim; j++) {
770 if (bi->xVarLo[j]==_xDatLo[j] && bi->xVarHi[j]==_xDatHi[j]) {
771 bi->netFluxZ = bi->netFluxZ && kTRUE;
772 } else { bi->netFluxZ = kFALSE; }
773
774 bi->xVarLoM3s[j] = bi->xVarLo[j] - _nSigma * (_n * _sigma[j]);
775 bi->xVarLoP3s[j] = bi->xVarLo[j] + _nSigma * (_n * _sigma[j]);
776 bi->xVarHiM3s[j] = bi->xVarHi[j] - _nSigma * (_n * _sigma[j]);
777 bi->xVarHiP3s[j] = bi->xVarHi[j] + _nSigma * (_n * _sigma[j]);
778
779 //cout<<"bi->xVarLoM3s["<<j<<"]="<<bi->xVarLoM3s[j]<<endl;
780 //cout<<"bi->xVarLoP3s["<<j<<"]="<<bi->xVarLoP3s[j]<<endl;
781 //cout<<"bi->xVarHiM3s["<<j<<"]="<<bi->xVarHiM3s[j]<<endl;
782 //cout<<"bi->xVarHiM3s["<<j<<"]="<<bi->xVarHiM3s[j]<<endl;
783 }
784
785 map<Int_t,Double_t>::iterator wMapItr = _wMap.begin();
786
787 //for (Int_t i=0; i<_nEventsM; i++) {
788 for (; wMapItr!=_wMap.end(); ++wMapItr) {
789 Int_t i = (*wMapItr).first;
790
791 const vector<Double_t>& x = _dataPts[i];
792 Bool_t inVarRange(kTRUE);
793 Bool_t inVarRangePlusShell(kTRUE);
794
795 for (Int_t j=0; j<_nDim; j++) {
796
797 if (x[j]>bi->xVarLo[j] && x[j]<bi->xVarHi[j]) {
798 inVarRange = inVarRange && kTRUE;
799 } else { inVarRange = inVarRange && kFALSE; }
800
801 if (x[j]>bi->xVarLoM3s[j] && x[j]<bi->xVarHiP3s[j]) {
802 inVarRangePlusShell = inVarRangePlusShell && kTRUE;
803 } else { inVarRangePlusShell = inVarRangePlusShell && kFALSE; }
804 }
805
806 // event in range?
807 if (inVarRange) {
808 bi->bIdcs.push_back(i);
809 }
810
811 // event in shell?
812 if (inVarRangePlusShell) {
813 bi->bpsIdcs[i] = kTRUE;
814 Bool_t inShell(kFALSE);
815 for (Int_t j=0; j<_nDim; j++) {
816 if ((x[j]>bi->xVarLoM3s[j] && x[j]<bi->xVarLoP3s[j]) && x[j]<(bi->xVarLo[j]+bi->xVarHi[j])/2.) {
817 inShell = kTRUE;
818 } else if ((x[j]>bi->xVarHiM3s[j] && x[j]<bi->xVarHiP3s[j]) && x[j]>(bi->xVarLo[j]+bi->xVarHi[j])/2.) {
819 inShell = kTRUE;
820 }
821 }
822 if (inShell) bi->sIdcs.push_back(i); // needed for normalization
823 else {
824 bi->bmsIdcs.push_back(i); // idem
825 }
826 }
827 }
828
829 coutI(Contents) << "RooNDKeysPdf::calculateShell() : "
830 << "\n Events in shell " << bi->sIdcs.size()
831 << "\n Events in box " << bi->bIdcs.size()
832 << "\n Events in box and shell " << bi->bpsIdcs.size()
833 << endl;
834}
835
836////////////////////////////////////////////////////////////////////////////////
837///bi->nEventsBMSW=0.;
838///bi->nEventsBW=0.;
839
841{
842 // box minus shell
843 for (Int_t i=0; i<Int_t(bi->bmsIdcs.size()); i++)
844 bi->nEventsBMSW += _wMap[bi->bmsIdcs[i]];
845
846 // box
847 for (Int_t i=0; i<Int_t(bi->bIdcs.size()); i++)
848 bi->nEventsBW += _wMap[bi->bIdcs[i]];
849
850 cxcoutD(Eval) << "RooNDKeysPdf::calculatePreNorm() : "
851 << "\n nEventsBMSW " << bi->nEventsBMSW
852 << "\n nEventsBW " << bi->nEventsBW
853 << endl;
854}
855
856////////////////////////////////////////////////////////////////////////////////
857/// sort entries, as needed for loopRange()
858
860{
861 // will loop over all events by default
862 if (!_sortInput) {
863 _ibNoSort.clear();
864 for (unsigned int i = 0; i < _dataPtsR.size(); ++i) {
865 _ibNoSort[i] = kTRUE;
866 }
867 return;
868 }
869
870 itVec itrVecR;
871 vector<TVectorD>::iterator dpRItr = _dataPtsR.begin();
872 for (Int_t i = 0; dpRItr != _dataPtsR.end(); ++dpRItr, ++i) {
873 if (bi) {
874 if (bi->bpsIdcs.find(i) != bi->bpsIdcs.end())
875 // if (_wMap.find(i)!=_wMap.end())
876 itrVecR.push_back(itPair(i, dpRItr));
877 } else
878 itrVecR.push_back(itPair(i, dpRItr));
879 }
880
881 _sortTVIdcs.resize(_nDim);
882 for (Int_t j=0; j<_nDim; j++) {
883 _sortTVIdcs[j].clear();
884 sort(itrVecR.begin(), itrVecR.end(), [=](const itPair& a, const itPair& b) {
885 return (*a.second)[j] < (*b.second)[j];
886 });
887 _sortTVIdcs[j] = itrVecR;
888 }
889
890 for (Int_t j=0; j<_nDim; j++) {
891 cxcoutD(Eval) << "RooNDKeysPdf::sortDataIndices() : Number of sorted events : " << _sortTVIdcs[j].size() << endl;
892 }
893}
894
895////////////////////////////////////////////////////////////////////////////////
896
898{
899 cxcoutD(Eval) << "RooNDKeysPdf::calculateBandWidth()" << endl;
900
901 // non-adaptive bandwidth
902 // (default, and needed to calculate adaptive bandwidth)
903
904 if(!_options.Contains("a")) {
905 cxcoutD(Eval) << "RooNDKeysPdf::calculateBandWidth() Using static bandwidth." << endl;
906 }
907
908 // fixed width approximation
909 for (Int_t i=0; i<_nEvents; i++) {
910 vector<Double_t>& weight = _weights0[i];
911 for (Int_t j = 0; j < _nDim; j++) {
912 weight[j] = _n * (*_sigmaR)[j];
913 // cout<<"j: "<<j<<", _n: "<<_n<<", sigmaR="<<(*_sigmaR)[j]<<", weight="<<weight[j]<<endl;
914 }
915 }
916
917 // adaptive width
918 if (_options.Contains("a")) {
919 cxcoutD(Eval) << "RooNDKeysPdf::calculateBandWidth() Using adaptive bandwidth." << endl;
920
921 double sqrt12 = sqrt(12.);
922 double sqrtSigmaAvgR = sqrt(_sigmaAvgR);
923
924 vector<Double_t> dummy(_nDim, 0.);
925 _weights1.resize(_nEvents, dummy);
926
927 std::vector<std::vector<Double_t>> *weights_prev(0);
928 std::vector<std::vector<Double_t>> *weights_new(0);
929
930 // cout << "Number of adaptive iterations: " << _nAdpt << endl;
931
932 for (Int_t k = 1; k <= _nAdpt; ++k) {
933
934 // cout << " Cycle: " << k << endl;
935
936 // if multiple adaptive iterations, need to swap weight sets
937 if (k % 2) {
938 weights_prev = &_weights0;
939 weights_new = &_weights1;
940 } else {
941 weights_prev = &_weights1;
942 weights_new = &_weights0;
943 }
944
945 for (Int_t i = 0; i < _nEvents; ++i) {
946 vector<Double_t> &x = _dataPts[i];
947 Double_t f = TMath::Power(gauss(x, *weights_prev) / _nEventsW, -1. / (2. * _d));
948
949 vector<Double_t> &weight = (*weights_new)[i];
950 for (Int_t j = 0; j < _nDim; j++) {
951 Double_t norm = (_n * (*_sigmaR)[j]) / sqrtSigmaAvgR;
952 weight[j] = norm * f / sqrt12; // note additional factor of sqrt(12) compared with HEP-EX/0011057
953 }
954 }
955 }
956 // this is the latest updated weights set
957 _weights = weights_new;
958 }
959}
960
961////////////////////////////////////////////////////////////////////////////////
962/// loop over all closest point to x, as determined by loopRange()
963
964Double_t RooNDKeysPdf::gauss(vector<Double_t>& x, vector<vector<Double_t> >& weights) const
965{
966 if(_nEvents==0) return 0.;
967
968 const double sqrt2pi = std::sqrt(TMath::TwoPi());
969
970 Double_t z=0.;
971 map<Int_t,Bool_t> ibMap;
972
973 // determine input loop range for event x
974 if (_sortInput) {
975 if (_sortTVIdcs.empty())
976 const_cast<RooNDKeysPdf*>(this)->sortDataIndices();
977
978 loopRange(x, ibMap);
979 }
980
981 map<Int_t, Bool_t>::iterator ibMapItr, ibMapEnd;
982 ibMapItr = (_sortInput ? ibMap.begin() : _ibNoSort.begin());
983 ibMapEnd = (_sortInput ? ibMap.end() : _ibNoSort.end());
984
985 for (; ibMapItr != ibMapEnd; ++ibMapItr) {
986 Int_t i = (*ibMapItr).first;
987
988 Double_t g(1.);
989
990 if (i >= (Int_t)_idx.size()) {
991 continue;
992 } //---> 1.myline
993
994 const vector<Double_t> &point = _dataPts[i];
995 const vector<Double_t> &weight = weights[_idx[i]];
996
997 for (Int_t j = 0; j < _nDim; j++) {
998 (*_dx)[j] = x[j] - point[j];
999 }
1000
1001 if (_nDim > 1 && _rotate) {
1002 *_dx *= *_rotMat; // rotate to decorrelated frame!
1003 }
1004
1005 for (Int_t j = 0; j < _nDim; j++) {
1006 Double_t r = (*_dx)[j]; // x[j] - point[j];
1007 Double_t c = 1. / (2. * weight[j] * weight[j]);
1008
1009 // cout << "j = " << j << " x[j] = " << point[j] << " w = " << weight[j] << endl;
1010
1011 g *= exp(-c * r * r);
1012 g *= 1. / (sqrt2pi * weight[j]);
1013 }
1014 z += (g * _wMap[_idx[i]]);
1015 }
1016 return z;
1017}
1018
1019////////////////////////////////////////////////////////////////////////////////
1020/// determine closest points to x, to loop over in evaluate()
1021
1022void RooNDKeysPdf::loopRange(vector<Double_t>& x, map<Int_t,Bool_t>& ibMap) const
1023{
1024 ibMap.clear();
1025 TVectorD xRm(_nDim);
1026 TVectorD xRp(_nDim);
1027
1028 for (Int_t j = 0; j < _nDim; j++) {
1029 xRm[j] = xRp[j] = x[j];
1030 }
1031
1032 if (_nDim > 1 && _rotate) {
1033 xRm *= *_rotMat;
1034 xRp *= *_rotMat;
1035 }
1036 for (Int_t j = 0; j < _nDim; j++) {
1037 xRm[j] -= _nSigma * (_n * (*_sigmaR)[j]);
1038 xRp[j] += _nSigma * (_n * (*_sigmaR)[j]);
1039 // cout<<"xRm["<<j<<"]="<<xRm[j]<<endl;
1040 // cout<<"xRp["<<j<<"]="<<xRp[j]<<endl;
1041 }
1042
1043 vector<TVectorD> xvecRm(1,xRm);
1044 vector<TVectorD> xvecRp(1,xRp);
1045
1046 map<Int_t,Bool_t> ibMapRT;
1047
1048 for (Int_t j=0; j<_nDim; j++) {
1049 ibMap.clear();
1050 auto comp = [=](const itPair& a, const itPair& b) {
1051 return (*a.second)[j] < (*b.second)[j];
1052 };
1053
1054 auto lo = lower_bound(_sortTVIdcs[j].begin(), _sortTVIdcs[j].end(), itPair(0, xvecRm.begin()), comp);
1055 auto hi = upper_bound(_sortTVIdcs[j].begin(), _sortTVIdcs[j].end(), itPair(0, xvecRp.begin()), comp);
1056 auto it = lo;
1057
1058 if (j==0) {
1059 if (_nDim==1) { for (it=lo; it!=hi; ++it) ibMap[(*it).first] = kTRUE; }
1060 else { for (it=lo; it!=hi; ++it) ibMapRT[(*it).first] = kTRUE; }
1061 continue;
1062 }
1063
1064 for (it=lo; it!=hi; ++it)
1065 if (ibMapRT.find((*it).first)!=ibMapRT.end()) { ibMap[(*it).first] = kTRUE; }
1066
1067 ibMapRT.clear();
1068 if (j!=_nDim-1) { ibMapRT = ibMap; }
1069 }
1070}
1071
1072////////////////////////////////////////////////////////////////////////////////
1073
1074void RooNDKeysPdf::boxInfoInit(BoxInfo* bi, const char* rangeName, Int_t /*code*/) const
1075{
1076 vector<Bool_t> doInt(_nDim,kTRUE);
1077
1078 bi->filled = kFALSE;
1079
1080 bi->xVarLo.resize(_nDim,0.);
1081 bi->xVarHi.resize(_nDim,0.);
1082 bi->xVarLoM3s.resize(_nDim,0.);
1083 bi->xVarLoP3s.resize(_nDim,0.);
1084 bi->xVarHiM3s.resize(_nDim,0.);
1085 bi->xVarHiP3s.resize(_nDim,0.);
1086
1087 bi->netFluxZ = kTRUE;
1088 bi->bpsIdcs.clear();
1089 bi->bIdcs.clear();
1090 bi->sIdcs.clear();
1091 bi->bmsIdcs.clear();
1092
1093 bi->nEventsBMSW=0.;
1094 bi->nEventsBW=0.;
1095
1096 for (unsigned int j=0; j < _varList.size(); ++j) {
1097 auto var = static_cast<const RooAbsRealLValue*>(_varList.at(j));
1098 if (doInt[j]) {
1099 bi->xVarLo[j] = var->getMin(rangeName);
1100 bi->xVarHi[j] = var->getMax(rangeName);
1101 } else {
1102 bi->xVarLo[j] = var->getVal() ;
1103 bi->xVarHi[j] = var->getVal() ;
1104 }
1105 }
1106}
1107
1108////////////////////////////////////////////////////////////////////////////////
1109
1111{
1112 if (_tracker != NULL && _tracker->hasChanged(kTRUE)) {
1113 updateRho(); // update internal rho parameters
1114 // redetermine static and/or adaptive bandwidth
1116 }
1117
1118 const RooArgSet *nset = _varList.nset();
1119 for (unsigned int j=0; j < _varList.size(); ++j) {
1120 auto var = static_cast<const RooAbsReal*>(_varList.at(j));
1121 _x[j] = var->getVal(nset);
1122 }
1123
1124 Double_t val = gauss(_x,*_weights);
1125 //cout<<"returning "<<val<<endl;
1126
1127 if (val>=1E-20)
1128 return val ;
1129 else
1130 return (1E-20) ;
1131}
1132
1133////////////////////////////////////////////////////////////////////////////////
1134
1135Int_t RooNDKeysPdf::getAnalyticalIntegral(RooArgSet& allVars, RooArgSet& analVars, const char* rangeName) const
1136{
1137 if (rangeName) return 0 ;
1138
1139 Int_t code=0;
1140 if (matchArgs(allVars,analVars,RooArgSet(_varList))) { code=1; }
1141
1142 return code;
1143
1144}
1145
1146////////////////////////////////////////////////////////////////////////////////
1147
1148Double_t RooNDKeysPdf::analyticalIntegral(Int_t code, const char* rangeName) const
1149{
1150 cxcoutD(Eval) << "Calling RooNDKeysPdf::analyticalIntegral(" << GetName() << ") with code " << code
1151 << " and rangeName " << (rangeName?rangeName:"<none>") << endl;
1152
1153 // determine which observables need to be integrated over ...
1154 Int_t nComb = 1 << (_nDim);
1155 R__ASSERT(code>=1 && code<nComb) ;
1156
1157 vector<Bool_t> doInt(_nDim,kTRUE);
1158
1159 // get BoxInfo
1160 BoxInfo* bi(0);
1161
1162 if (rangeName) {
1163 string rangeNameStr(rangeName) ;
1164 bi = _rangeBoxInfo[make_pair(rangeNameStr,code)] ;
1165 if (!bi) {
1166 bi = new BoxInfo ;
1167 _rangeBoxInfo[make_pair(rangeNameStr,code)] = bi ;
1168 boxInfoInit(bi,rangeName,code);
1169 }
1170 } else bi= &_fullBoxInfo ;
1171
1172 // have boundaries changed?
1173 Bool_t newBounds(kFALSE);
1174 for (unsigned int j=0; j < _varList.size(); ++j) {
1175 auto var = static_cast<const RooAbsRealLValue*>(_varList.at(j));
1176 if ((var->getMin(rangeName)-bi->xVarLo[j]!=0) ||
1177 (var->getMax(rangeName)-bi->xVarHi[j]!=0)) {
1178 newBounds = kTRUE;
1179 }
1180 }
1181
1182 // reset
1183 if (newBounds) {
1184 cxcoutD(Eval) << "RooNDKeysPdf::analyticalIntegral() : Found new boundaries ... " << (rangeName?rangeName:"<none>") << endl;
1185 boxInfoInit(bi,rangeName,code);
1186 }
1187
1188 // recalculates netFluxZero and nEventsIR
1189 if (!bi->filled || newBounds) {
1190 // Fill box info with contents
1191 calculateShell(bi);
1192 calculatePreNorm(bi);
1193 bi->filled = kTRUE;
1194 const_cast<RooNDKeysPdf*>(this)->sortDataIndices(bi);
1195 }
1196
1197 // first guess
1198 Double_t norm=bi->nEventsBW;
1199
1200 if (_mirror && bi->netFluxZ) {
1201 // KEYS expression is self-normalized
1202 cxcoutD(Eval) << "RooNDKeysPdf::analyticalIntegral() : Using mirrored normalization : " << bi->nEventsBW << endl;
1203 return bi->nEventsBW;
1204 }
1205 // calculate leakage in and out of variable range box
1206 else
1207 {
1208 norm = bi->nEventsBMSW;
1209 if (norm<0.) norm=0.;
1210
1211 for (Int_t i=0; i<Int_t(bi->sIdcs.size()); ++i) {
1212 Double_t prob=1.;
1213 const vector<Double_t>& x = _dataPts[bi->sIdcs[i]];
1214 const vector<Double_t>& weight = (*_weights)[_idx[bi->sIdcs[i]]];
1215
1216 vector<Double_t> chi(_nDim,100.);
1217
1218 for (Int_t j=0; j<_nDim; j++) {
1219 if(!doInt[j]) continue;
1220
1221 if ((x[j]>bi->xVarLoM3s[j] && x[j]<bi->xVarLoP3s[j]) && x[j]<(bi->xVarLo[j]+bi->xVarHi[j])/2.)
1222 chi[j] = (x[j]-bi->xVarLo[j])/weight[j];
1223 else if ((x[j]>bi->xVarHiM3s[j] && x[j]<bi->xVarHiP3s[j]) && x[j]>(bi->xVarLo[j]+bi->xVarHi[j])/2.)
1224 chi[j] = (bi->xVarHi[j]-x[j])/weight[j];
1225
1226 if (chi[j]>0) // inVarRange
1227 prob *= (0.5 + TMath::Erf(fabs(chi[j])/sqrt(2.))/2.);
1228 else // outside Var range
1229 prob *= (0.5 - TMath::Erf(fabs(chi[j])/sqrt(2.))/2.);
1230 }
1231
1232 norm += prob * _wMap[_idx[bi->sIdcs[i]]];
1233 }
1234
1235 cxcoutD(Eval) << "RooNDKeysPdf::analyticalIntegral() : Final normalization : " << norm << " " << bi->nEventsBW << endl;
1236 return norm;
1237 }
1238}
1239
1240
1241////////////////////////////////////////////////////////////////////////////////
1242
1244{
1245 std::vector<RooRealVar *> varVec;
1246 RooArgSet varsAndWeightSet;
1247
1248 for (const auto var : varList) {
1249 if (!dynamic_cast<RooRealVar *>(var)) {
1250 coutE(InputArguments) << "RooNDKeysPdf::createDatasetFromHist(" << GetName() << ") WARNING: variable "
1251 << var->GetName() << " is not of type RooRealVar. Skip." << endl;
1252 continue;
1253 }
1254 varsAndWeightSet.add(*var); // used for dataset creation
1255 varVec.push_back(static_cast<RooRealVar *>(var)); // used for setting the variables.
1256 }
1257
1258 /// Add weight
1259 RooRealVar weight("weight", "event weight", 0);
1260 varsAndWeightSet.add(weight);
1261
1262 /// determine histogram dimensionality
1263 unsigned int histndim(0);
1264 std::string classname = hist.ClassName();
1265 if (classname.find("TH1") == 0) {
1266 histndim = 1;
1267 } else if (classname.find("TH2") == 0) {
1268 histndim = 2;
1269 } else if (classname.find("TH3") == 0) {
1270 histndim = 3;
1271 }
1272 assert(histndim == varVec.size());
1273
1274 if (histndim > 3 || histndim <= 0) {
1275 coutE(InputArguments) << "RooNDKeysPdf::createDatasetFromHist(" << GetName()
1276 << ") ERROR: input histogram dimension not between [1-3]: " << histndim << endl;
1277 assert(0);
1278 }
1279
1280 /// dataset creation
1281 RooDataSet *dataFromHist = new RooDataSet("datasetFromHist", "datasetFromHist", varsAndWeightSet, weight.GetName());
1282
1283 /// dataset filling
1284 for (int i = 1; i <= hist.GetXaxis()->GetNbins(); ++i) {
1285 // 1 or more dimension
1286
1287 Double_t xval = hist.GetXaxis()->GetBinCenter(i);
1288 varVec[0]->setVal(xval);
1289
1290 if (varVec.size() == 1) {
1291 Double_t fval = hist.GetBinContent(i);
1292 weight.setVal(fval);
1293 dataFromHist->add(varsAndWeightSet, fval);
1294 } else { // 2 or more dimensions
1295
1296 for (int j = 1; j <= hist.GetYaxis()->GetNbins(); ++j) {
1297 Double_t yval = hist.GetYaxis()->GetBinCenter(j);
1298 varVec[1]->setVal(yval);
1299
1300 if (varVec.size() == 2) {
1301 Double_t fval = hist.GetBinContent(i, j);
1302 weight.setVal(fval);
1303 dataFromHist->add(varsAndWeightSet, fval);
1304 } else { // 3 dimensions
1305
1306 for (int k = 1; k <= hist.GetZaxis()->GetNbins(); ++k) {
1307 Double_t zval = hist.GetZaxis()->GetBinCenter(k);
1308 varVec[2]->setVal(zval);
1309
1310 Double_t fval = hist.GetBinContent(i, j, k);
1311 weight.setVal(fval);
1312 dataFromHist->add(varsAndWeightSet, fval);
1313 }
1314 }
1315 }
1316 }
1317 }
1318
1319 return dataFromHist;
1320}
1321
1322
1323 ////////////////////////////////////////////////////////////////////////////////
1324 /// Return evaluated weights
1325
1327{
1328 TMatrixD mref(_nEvents, _nDim + 1);
1329
1330 cxcoutD(Eval) << "RooNDKeysPdf::getWeights() Return evaluated weights." << endl;
1331
1332 for (Int_t i = 0; i < _nEvents; ++i) {
1333 vector<Double_t> &x = _dataPts[i];
1334 for (Int_t j = 0; j < _nDim; j++) {
1335 mref(i, j) = x[j];
1336 }
1337
1338 vector<Double_t> &weight = (*_weights)[i];
1339 mref(i, _nDim) = weight[k];
1340 }
1341
1342 return mref;
1343}
1344
1345 ////////////////////////////////////////////////////////////////////////////////
1347{
1348 for (unsigned int j = 0; j < _rhoList.size(); ++j) {
1349 auto rho = static_cast<const RooAbsReal*>(_rhoList.at(j));
1350 _rho[j] = rho->getVal();
1351 }
1352
1353 if (_nDim > 1 && _rotate) {
1354 TMatrixDSym covMatRho(_nDim); // covariance matrix times rho parameters
1355 for (Int_t j = 0; j < _nDim; j++) {
1356 for (Int_t k = 0; k < _nDim; k++) {
1357 covMatRho(j, k) = (*_covMat)(j, k) * _rho[j] * _rho[k];
1358 }
1359 }
1360 // find decorrelation matrix and eigenvalues (R)
1361 TMatrixDSymEigen evCalculatorRho(covMatRho);
1362 *_sigmaR = evCalculatorRho.GetEigenValues();
1363 for (Int_t j = 0; j < _nDim; j++) {
1364 (*_sigmaR)[j] = sqrt((*_sigmaR)[j]);
1365 }
1366 } else {
1367 for (Int_t j = 0; j < _nDim; j++) {
1368 (*_sigmaR)[j] = (_sigma[j] * _rho[j]);
1369 } // * rho
1370 }
1371}
ROOT::R::TRInterface & r
Definition: Object.C:4
#define b(i)
Definition: RSha256.hxx:100
#define f(i)
Definition: RSha256.hxx:104
#define c(i)
Definition: RSha256.hxx:101
#define g(i)
Definition: RSha256.hxx:105
static RooMathCoreReg dummy
#define coutI(a)
Definition: RooMsgService.h:31
#define cxcoutD(a)
Definition: RooMsgService.h:82
#define coutW(a)
Definition: RooMsgService.h:33
#define coutE(a)
Definition: RooMsgService.h:34
std::vector< itPair > itVec
Definition: RooNDKeysPdf.h:43
std::pair< Int_t, VecTVecDouble::iterator > itPair
Definition: RooNDKeysPdf.h:42
int Int_t
Definition: RtypesCore.h:41
const Bool_t kFALSE
Definition: RtypesCore.h:88
bool Bool_t
Definition: RtypesCore.h:59
double Double_t
Definition: RtypesCore.h:55
const Bool_t kTRUE
Definition: RtypesCore.h:87
#define ClassImp(name)
Definition: Rtypes.h:365
#define R__ASSERT(e)
Definition: TError.h:96
char name[80]
Definition: TGX11.cxx:109
float type_of_call hi(const int &, const int &)
double sqrt(double)
double exp(double)
TMatrixTSym< Double_t > TMatrixDSym
TMatrixT< Double_t > TMatrixD
Definition: TMatrixDfwd.h:22
typedef void((*Func_t)())
TVectorT< Double_t > TVectorD
Definition: TVectorDfwd.h:22
friend class RooDataSet
Definition: RooAbsArg.h:599
friend class RooArgSet
Definition: RooAbsArg.h:551
TIterator end() or range-based loops.")
Definition: RooAbsArg.h:113
Int_t getSize() const
Storage_t::size_type size() const
RooAbsArg * find(const char *name) const
Find object with given name in list.
virtual Int_t numEntries() const
Definition: RooAbsData.cxx:307
const RooArgSet * nset() const
Definition: RooAbsProxy.h:46
RooAbsRealLValue is the common abstract base class for objects that represent a real value that may a...
RooAbsReal is the common abstract base class for objects that represent a real value and implements f...
Definition: RooAbsReal.h:59
Bool_t matchArgs(const RooArgSet &allDeps, RooArgSet &numDeps, const RooArgProxy &a) const
Utility function for use in getAnalyticalIntegral().
RooArgList is a container object that can hold multiple RooAbsArg objects.
Definition: RooArgList.h:21
RooAbsArg * at(Int_t idx) const
Return object at given index, or nullptr if index is out of range.
Definition: RooArgList.h:74
RooArgSet is a container object that can hold multiple RooAbsArg objects.
Definition: RooArgSet.h:28
virtual Bool_t add(const RooAbsCollection &col, Bool_t silent=kFALSE)
Add a collection of arguments to this collection by calling add() for each element in the source coll...
Definition: RooArgSet.h:88
RooChangeTracker is a meta object that tracks value changes in a given set of RooAbsArgs by registeri...
Bool_t hasChanged(Bool_t clearState)
Returns true if state has changed since last call with clearState=kTRUE.
RooDataSet is a container class to hold unbinned data.
Definition: RooDataSet.h:31
virtual const RooArgSet * get(Int_t index) const override
Return RooArgSet with coordinates of event 'index'.
virtual void add(const RooArgSet &row, Double_t weight=1.0, Double_t weightError=0) override
Add a data point, with its coordinates specified in the 'data' argset, to the data set.
virtual Double_t weight() const override
Return event weight of current event.
Definition: RooDataSet.cxx:979
virtual Bool_t add(const RooAbsArg &var, Bool_t silent=kFALSE)
Reimplementation of standard RooArgList::add()
Generic N-dimensional implementation of a kernel estimation p.d.f.
Definition: RooNDKeysPdf.h:48
BoxInfo _fullBoxInfo
Definition: RooNDKeysPdf.h:185
RooListProxy _rhoList
Definition: RooNDKeysPdf.h:116
Double_t _nSigma
Definition: RooNDKeysPdf.h:140
TVectorD * _dx
Definition: RooNDKeysPdf.h:196
Double_t _minWeight
Definition: RooNDKeysPdf.h:188
std::vector< Int_t > _sIdcs
Definition: RooNDKeysPdf.h:180
void initialize()
initialization
std::vector< Double_t > _xVarLo
Definition: RooNDKeysPdf.h:176
void calculatePreNorm(BoxInfo *bi) const
bi->nEventsBMSW=0.
Double_t analyticalIntegral(Int_t code, const char *rangeName=0) const
Implements the actual analytical integral(s) advertised by getAnalyticalIntegral.
TVectorD * _sigmaR
Definition: RooNDKeysPdf.h:195
std::vector< Double_t > _xDatLo3s
Definition: RooNDKeysPdf.h:171
Double_t _nEventsBW
Definition: RooNDKeysPdf.h:174
std::vector< Double_t > _x0
Definition: RooNDKeysPdf.h:168
virtual ~RooNDKeysPdf()
std::vector< Double_t > _xVarLoP3s
Definition: RooNDKeysPdf.h:177
void loadWeightSet() const
Bool_t _fixedShape
Definition: RooNDKeysPdf.h:142
Bool_t _sortInput
Definition: RooNDKeysPdf.h:200
Bool_t _verbose
Definition: RooNDKeysPdf.h:145
std::vector< Double_t > _xDatHi3s
Definition: RooNDKeysPdf.h:171
const RooDataSet * _data
Definition: RooNDKeysPdf.h:137
std::vector< Int_t > _bIdcs
Definition: RooNDKeysPdf.h:181
std::vector< TVectorD > _dataPtsR
Definition: RooNDKeysPdf.h:157
void loopRange(std::vector< Double_t > &x, std::map< Int_t, Bool_t > &ibMap) const
determine closest points to x, to loop over in evaluate()
std::vector< Double_t > _xVarHi
Definition: RooNDKeysPdf.h:176
void createPdf(Bool_t firstCall=kTRUE)
evaluation order of constructor.
Double_t _nEventsBMSW
Definition: RooNDKeysPdf.h:175
void updateRho() const
Double_t _nEventsW
Definition: RooNDKeysPdf.h:150
void calculateShell(BoxInfo *bi) const
determine points in +/- nSigma shell around the box determined by the variable ranges.
std::vector< Double_t > _x1
Definition: RooNDKeysPdf.h:168
Bool_t _netFluxZ
Definition: RooNDKeysPdf.h:173
Double_t _maxWeight
Definition: RooNDKeysPdf.h:189
std::vector< Double_t > _mean
Definition: RooNDKeysPdf.h:169
Bool_t _rotate
Definition: RooNDKeysPdf.h:199
RooListProxy _varList
Definition: RooNDKeysPdf.h:115
TMatrixDSym * _corrMat
Definition: RooNDKeysPdf.h:193
std::vector< Int_t > _bmsIdcs
Definition: RooNDKeysPdf.h:182
std::vector< Double_t > _rho
Definition: RooNDKeysPdf.h:165
std::vector< Double_t > _xDatHi
Definition: RooNDKeysPdf.h:170
std::vector< Double_t > _x
Definition: RooNDKeysPdf.h:167
std::vector< itVec > _sortTVIdcs
Definition: RooNDKeysPdf.h:162
void boxInfoInit(BoxInfo *bi, const char *rangeName, Int_t code) const
std::map< std::pair< std::string, int >, BoxInfo * > _rangeBoxInfo
Definition: RooNDKeysPdf.h:184
std::vector< Double_t > _xVarLoM3s
Definition: RooNDKeysPdf.h:177
Double_t _d
Definition: RooNDKeysPdf.h:151
Double_t _sigmaAvgR
Definition: RooNDKeysPdf.h:197
Double_t _widthFactor
Definition: RooNDKeysPdf.h:139
std::vector< Int_t > _idx
Definition: RooNDKeysPdf.h:187
std::vector< Double_t > _xDatLo
Definition: RooNDKeysPdf.h:170
void sortDataIndices(BoxInfo *bi=0)
sort entries, as needed for loopRange()
Int_t getAnalyticalIntegral(RooArgSet &allVars, RooArgSet &analVars, const char *rangeName=0) const
Interface function getAnalyticalIntergral advertises the analytical integrals that are supported.
TString _options
do not persist
Definition: RooNDKeysPdf.h:138
std::vector< std::vector< Double_t > > * _weights
Definition: RooNDKeysPdf.h:160
TMatrixD getWeights(const int &k) const
Return evaluated weights.
std::vector< Double_t > _xVarHiM3s
Definition: RooNDKeysPdf.h:177
Double_t evaluate() const
Evaluate this PDF / function / constant. Needs to be overridden by all derived classes.
std::map< Int_t, Bool_t > _ibNoSort
Definition: RooNDKeysPdf.h:179
std::vector< std::vector< Double_t > > _weights0
Definition: RooNDKeysPdf.h:158
void mirrorDataSet() const
determine mirror dataset.
void setOptions()
set the configuration
std::vector< std::vector< Double_t > > _dataPts
Definition: RooNDKeysPdf.h:156
RooDataSet * createDatasetFromHist(const RooArgList &varList, const TH1 &hist) const
RooNDKeysPdf()=default
std::vector< Double_t > _sigma
Definition: RooNDKeysPdf.h:169
std::vector< std::string > _varName
Definition: RooNDKeysPdf.h:164
Double_t gauss(std::vector< Double_t > &x, std::vector< std::vector< Double_t > > &weights) const
loop over all closest point to x, as determined by loopRange()
Double_t _n
Definition: RooNDKeysPdf.h:152
std::map< Int_t, Double_t > _wMap
Definition: RooNDKeysPdf.h:190
std::vector< std::vector< Double_t > > _weights1
Definition: RooNDKeysPdf.h:159
TMatrixD * _rotMat
Definition: RooNDKeysPdf.h:194
Bool_t _mirror
Definition: RooNDKeysPdf.h:143
std::vector< Double_t > _x2
Definition: RooNDKeysPdf.h:168
void loadDataSet(Bool_t firstCall) const
copy the dataset and calculate some useful variables
TMatrixDSym * _covMat
Definition: RooNDKeysPdf.h:192
std::vector< Double_t > _xVarHiP3s
Definition: RooNDKeysPdf.h:177
std::map< Int_t, Bool_t > _bpsIdcs
Definition: RooNDKeysPdf.h:178
RooChangeTracker * _tracker
Definition: RooNDKeysPdf.h:203
void calculateBandWidth() const
RooRealVar represents a variable that can be changed from the outside.
Definition: RooRealVar.h:35
virtual void setVal(Double_t value)
Set value of variable to 'value'.
Definition: RooRealVar.cxx:278
virtual Double_t GetBinCenter(Int_t bin) const
Return center of bin.
Definition: TAxis.cxx:464
The TH1 histogram class.
Definition: TH1.h:56
TAxis * GetZaxis()
Definition: TH1.h:318
TAxis * GetXaxis()
Get the behaviour adopted by the object about the statoverflows. See EStatOverflows for more informat...
Definition: TH1.h:316
TAxis * GetYaxis()
Definition: TH1.h:317
virtual Double_t GetBinContent(Int_t bin) const
Return content of bin number bin.
Definition: TH1.cxx:4899
TMatrixDSymEigen.
const TVectorD & GetEigenValues() const
const TMatrixD & GetEigenVectors() const
void Print(Option_t *name="") const
Print the matrix as a table of elements.
virtual TMatrixTBase< Element > & Zero()
Set matrix elements to zero.
TMatrixT< Element > & T()
Definition: TMatrixT.h:150
virtual const char * GetName() const
Returns name of object.
Definition: TNamed.h:47
virtual const char * ClassName() const
Returns name of class to which the object belongs.
Definition: TObject.cxx:128
Basic string class.
Definition: TString.h:131
void ToLower()
Change string to lower-case.
Definition: TString.cxx:1125
const char * Data() const
Definition: TString.h:364
Bool_t Contains(const char *pat, ECaseCompare cmp=kExact) const
Definition: TString.h:619
TVectorT< Element > & Zero()
Set vector elements to zero.
Definition: TVectorT.cxx:451
Int_t GetNrows() const
Definition: TVectorT.h:75
void Print(Option_t *option="") const
Print the vector as a list of elements.
Definition: TVectorT.cxx:1361
void box(Int_t pat, Double_t x1, Double_t y1, Double_t x2, Double_t y2)
Definition: fillpatterns.C:1
Double_t y[n]
Definition: legend1.C:17
Double_t x[n]
Definition: legend1.C:17
for(Int_t i=0;i< n;i++)
Definition: legend1.C:18
VecExpr< UnaryOp< Fabs< T >, VecExpr< A, T, D >, T >, T, D > fabs(const VecExpr< A, T, D > &rhs)
@ InputArguments
Definition: RooGlobalFunc.h:68
Double_t Erf(Double_t x)
Computation of the error function erf(x).
Definition: TMath.cxx:184
constexpr Double_t E()
Base of natural log:
Definition: TMath.h:97
LongDouble_t Power(LongDouble_t x, LongDouble_t y)
Definition: TMath.h:725
Short_t Abs(Short_t d)
Definition: TMathBase.h:120
constexpr Double_t TwoPi()
Definition: TMath.h:45
std::vector< Double_t > xVarHiP3s
Definition: RooNDKeysPdf.h:106
std::vector< Double_t > xVarHi
Definition: RooNDKeysPdf.h:105
std::map< Int_t, Bool_t > bpsIdcs
Definition: RooNDKeysPdf.h:107
std::vector< Int_t > bIdcs
Definition: RooNDKeysPdf.h:109
std::vector< Double_t > xVarLoM3s
Definition: RooNDKeysPdf.h:106
std::vector< Double_t > xVarHiM3s
Definition: RooNDKeysPdf.h:106
std::vector< Double_t > xVarLoP3s
Definition: RooNDKeysPdf.h:106
std::vector< Double_t > xVarLo
Definition: RooNDKeysPdf.h:105
std::vector< Int_t > sIdcs
Definition: RooNDKeysPdf.h:108
std::vector< Int_t > bmsIdcs
Definition: RooNDKeysPdf.h:110
auto * m
Definition: textangle.C:8
auto * l
Definition: textangle.C:4
auto * a
Definition: textangle.C:12