40 ClassImp(Roo2DKeysPdf);
53 Roo2DKeysPdf::Roo2DKeysPdf(
const char *name,
const char *title,
54 RooAbsReal& xx, RooAbsReal & yy, RooDataSet& data, TString options, Double_t widthScaleFactor):
55 RooAbsPdf(name,title),
56 x(
"x",
"x dimension",this, xx),
57 y(
"y",
"y dimension",this, yy)
59 setWidthScaleFactor(widthScaleFactor);
60 loadDataSet(data, options);
69 Roo2DKeysPdf::Roo2DKeysPdf(
const Roo2DKeysPdf & other,
const char* name) :
70 RooAbsPdf(other,name),
71 x(
"x", this, other.x),
74 if(_verbosedebug) { cout <<
"Roo2DKeysPdf::Roo2DKeysPdf copy ctor" << endl; }
76 _xMean = other._xMean;
77 _xSigma = other._xSigma;
78 _yMean = other._yMean;
79 _ySigma = other._ySigma;
82 _BandWidthType = other._BandWidthType;
83 _MirrorAtBoundary = other._MirrorAtBoundary;
84 _widthScaleFactor = other._widthScaleFactor;
87 _sqrt2pi = other._sqrt2pi;
88 _nEvents = other._nEvents;
90 _debug = other._debug;
91 _verbosedebug = other._verbosedebug;
92 _vverbosedebug = other._vverbosedebug;
98 _xoffset = other._xoffset;
99 _yoffset = other._yoffset;
101 _x =
new Double_t[_nEvents];
102 _y =
new Double_t[_nEvents];
103 _hx =
new Double_t[_nEvents];
104 _hy =
new Double_t[_nEvents];
107 for(Int_t iEvt = 0; iEvt< _nEvents; iEvt++)
109 _x[iEvt] = other._x[iEvt];
110 _y[iEvt] = other._y[iEvt];
111 _hx[iEvt] = other._hx[iEvt];
112 _hy[iEvt] = other._hy[iEvt];
120 Roo2DKeysPdf::~Roo2DKeysPdf() {
121 if(_verbosedebug) { cout <<
"Roo2DKeysPdf::Roo2KeysPdf dtor" << endl; }
135 Int_t Roo2DKeysPdf::loadDataSet(RooDataSet& data, TString options)
137 if(_verbosedebug) { cout <<
"Roo2DKeysPdf::loadDataSet" << endl; }
141 if(_verbosedebug) { cout <<
"Roo2DKeysPdf::loadDataSet(RooDataSet& data, TString options)" << endl; }
143 _2pi = 2.0*TMath::Pi() ;
144 _sqrt2pi = sqrt(_2pi);
145 _nEvents = (Int_t)data.numEntries();
148 cout <<
"ERROR: Roo2DKeysPdf::loadDataSet The input data set is empty. Unable to begin generating the PDF" << endl;
151 _n16 = TMath::Power(_nEvents, -0.166666666);
158 _x =
new Double_t[_nEvents];
159 _y =
new Double_t[_nEvents];
160 _hx =
new Double_t[_nEvents];
161 _hy =
new Double_t[_nEvents];
172 const RooAbsReal & xx = x.arg();
173 const RooAbsReal & yy = y.arg();
174 if(! (RooRealVar*)( (RooArgSet*)data.get(0) )->find( xx.GetName() ) )
176 cout <<
"Roo2DKeysPdf::Roo2DKeysPdf invalid RooAbsReal name: "<<xx.GetName()<<
" not in the data set" <<endl;
179 if(! (RooRealVar*)( (RooArgSet*)data.get(0) )->find( yy.GetName() ) )
181 cout <<
"Roo2DKeysPdf::Roo2DKeysPdf invalid RooAbsReal name: "<<yy.GetName()<<
" not in the data set" << endl;
186 cout <<
"Roo2DKeysPdf::Roo2DKeysPdf Unable to initilize object; incompatible RooDataSet doesn't contain"<<endl;
187 cout <<
" all of the RooAbsReal arguments"<<endl;
192 const RooArgSet * values = data.get();
193 const RooRealVar* X = ((RooRealVar*)(values->find(xx.GetName())) ) ;
194 const RooRealVar* Y = ((RooRealVar*)(values->find(yy.GetName())) ) ;
196 for (Int_t j=0;j<_nEvents;++j)
200 _x[j] = X->getVal() ;
201 _y[j] = Y->getVal() ;
203 x0+=1; x1+=_x[j]; x_2+=_x[j]*_x[j];
204 y0+=1; y1+=_y[j]; y_2+=_y[j]*_y[j];
212 cout <<
"Roo2DKeysPdf::Roo2DKeysPdf Empty data set was used; can't generate a PDF"<<endl;
216 _xSigma = sqrt(x_2/_nEvents-_xMean*_xMean);
219 _ySigma = sqrt(y_2/_nEvents-_yMean*_yMean);
221 _n = Double_t(1)/(_2pi*_nEvents*_xSigma*_ySigma);
224 return calculateBandWidth(_BandWidthType);
230 void Roo2DKeysPdf::setOptions(TString options)
232 if(_verbosedebug) { cout <<
"Roo2DKeysPdf::setOptions" << endl; }
235 if( options.Contains(
"a") ) _BandWidthType = 0;
236 else _BandWidthType = 1;
237 if( options.Contains(
"n") ) _BandWidthType = 1;
238 else _BandWidthType = 0;
239 if( options.Contains(
"m") ) _MirrorAtBoundary = 1;
240 else _MirrorAtBoundary = 0;
241 if( options.Contains(
"d") ) _debug = 1;
243 if( options.Contains(
"v") ) { _debug = 1; _verbosedebug = 1; }
244 else _verbosedebug = 0;
245 if( options.Contains(
"vv") ) { _vverbosedebug = 1; }
246 else _vverbosedebug = 0;
250 cout <<
"Roo2DKeysPdf::setOptions(TString options) options = "<< options << endl;
251 cout <<
"\t_BandWidthType = " << _BandWidthType << endl;
252 cout <<
"\t_MirrorAtBoundary = " << _MirrorAtBoundary << endl;
253 cout <<
"\t_debug = " << _debug << endl;
254 cout <<
"\t_verbosedebug = " << _verbosedebug << endl;
255 cout <<
"\t_vverbosedebug = " << _vverbosedebug << endl;
262 void Roo2DKeysPdf::getOptions(
void)
const
264 cout <<
"Roo2DKeysPdf::getOptions(void)" << endl;
265 cout <<
"\t_BandWidthType = " << _BandWidthType << endl;
266 cout <<
"\t_MirrorAtBoundary = " << _MirrorAtBoundary << endl;
267 cout <<
"\t_debug = " << _debug << endl;
268 cout <<
"\t_verbosedebug = " << _verbosedebug << endl;
269 cout <<
"\t_vverbosedebug = " << _vverbosedebug << endl;
277 Int_t Roo2DKeysPdf::calculateBandWidth(Int_t kernel)
279 if(_verbosedebug) { cout <<
"Roo2DKeysPdf::calculateBandWidth(Int_t kernel)" << endl; }
282 _BandWidthType = kernel;
287 Double_t sigSum = _xSigma*_xSigma + _ySigma*_ySigma;
288 Double_t sqrtSum = sqrt( sigSum );
289 Double_t sigProd = _ySigma*_xSigma;
290 if(sigProd != 0.0) h = _n16*sqrt( sigSum/sigProd );
293 cout <<
"Roo2DKeysPdf::calculateBandWidth The sqr(variance sum) == 0.0. " <<
" Your dataset represents a delta function."<<endl;
297 Double_t hXSigma = h * _xSigma;
298 Double_t hYSigma = h * _ySigma;
299 Double_t xhmin = hXSigma * sqrt(2.)/10;
300 Double_t yhmin = hYSigma * sqrt(2.)/10;
305 if(_BandWidthType == 1)
307 cout <<
"Roo2DKeysPdf::calculateBandWidth Using a normal bandwidth (same for a given dimension) based on"<<endl;
308 cout <<
" h_j = n^{-1/6}*sigma_j for the j^th dimension and n events * "<<_widthScaleFactor<<endl;
309 Double_t hxGaussian = _n16 * _xSigma * _widthScaleFactor;
310 Double_t hyGaussian = _n16 * _ySigma * _widthScaleFactor;
311 for(Int_t j=0;j<_nEvents;++j)
315 if(_hx[j]<xhmin) _hx[j] = xhmin;
316 if(_hy[j]<yhmin) _hy[j] = yhmin;
321 cout <<
"Roo2DKeysPdf::calculateBandWidth Using an adaptive bandwidth (in general different for all events) [default]"<<endl;
322 cout <<
" scaled by a factor of "<<_widthScaleFactor<<endl;
323 Double_t xnorm = h * TMath::Power(_xSigma/sqrtSum, 1.5) * _widthScaleFactor;
324 Double_t ynorm = h * TMath::Power(_ySigma/sqrtSum, 1.5) * _widthScaleFactor;
325 for(Int_t j=0;j<_nEvents;++j)
327 Double_t f_ti = TMath::Power( g(_x[j], _x, hXSigma, _y[j], _y, hYSigma), -0.25 ) ;
328 _hx[j] = xnorm * f_ti;
329 _hy[j] = ynorm * f_ti;
330 if(_hx[j]<xhmin) _hx[j] = xhmin;
331 if(_hy[j]<yhmin) _hy[j] = yhmin;
346 Double_t Roo2DKeysPdf::evaluate()
const
348 if(_vverbosedebug) { cout <<
"Roo2DKeysPdf::evaluate()" << endl; }
349 return evaluateFull(x,y);
362 Double_t Roo2DKeysPdf::evaluateFull(Double_t thisX, Double_t thisY)
const
364 if( _vverbosedebug ) { cout <<
"Roo2DKeysPdf::evaluateFull()" << endl; }
368 Double_t rx2, ry2, zx, zy;
369 if( _MirrorAtBoundary )
371 for (Int_t j = 0; j < _nEvents; ++j)
373 rx2 = 0.0; ry2 = 0.0; zx = 0.0; zy = 0.0;
374 if(_hx[j] != 0.0) rx2 = (thisX - _x[j])/_hx[j];
375 if(_hy[j] != 0.0) ry2 = (thisY - _y[j])/_hy[j];
377 if(_hx[j] != 0.0) zx = exp(-0.5*rx2*rx2)/_hx[j];
378 if(_hy[j] != 0.0) zy = exp(-0.5*ry2*ry2)/_hy[j];
380 zx += highBoundaryCorrection(thisX, _hx[j], x.max(), _x[j])
381 + lowBoundaryCorrection(thisX, _hx[j], x.min(), _x[j]);
382 zy += highBoundaryCorrection(thisY, _hy[j], y.max(), _y[j])
383 + lowBoundaryCorrection(thisY, _hy[j], y.min(), _y[j]);
390 for (Int_t j = 0; j < _nEvents; ++j)
392 rx2 = 0.0; ry2 = 0.0; zx = 0.0; zy = 0.0;
393 if(_hx[j] != 0.0) rx2 = (thisX - _x[j])/_hx[j];
394 if(_hy[j] != 0.0) ry2 = (thisY - _y[j])/_hy[j];
396 if(_hx[j] != 0.0) zx = exp(-0.5*rx2*rx2)/_hx[j];
397 if(_hy[j] != 0.0) zy = exp(-0.5*ry2*ry2)/_hy[j];
415 Double_t Roo2DKeysPdf::highBoundaryCorrection(Double_t thisVar, Double_t thisH, Double_t high, Double_t tVar)
const
417 if(_vverbosedebug) { cout <<
"Roo2DKeysPdf::highBoundaryCorrection" << endl; }
419 if(thisH == 0.0)
return 0.0;
420 Double_t correction = (thisVar + tVar - 2.0* high )/thisH;
421 return exp(-0.5*correction*correction)/thisH;
427 Double_t Roo2DKeysPdf::lowBoundaryCorrection(Double_t thisVar, Double_t thisH, Double_t low, Double_t tVar)
const
429 if(_vverbosedebug) { cout <<
"Roo2DKeysPdf::lowBoundaryCorrection" << endl; }
431 if(thisH == 0.0)
return 0.0;
432 Double_t correction = (thisVar + tVar - 2.0* low )/thisH;
433 return exp(-0.5*correction*correction)/thisH;
447 Double_t Roo2DKeysPdf::g(Double_t varMean1, Double_t * _var1, Double_t sigma1, Double_t varMean2, Double_t * _var2, Double_t sigma2)
const
449 if((_nEvents == 0.0) || (sigma1 == 0.0) || (sigma2 == 0))
return 0.0;
451 Double_t c1 = -1.0/(2.0*sigma1*sigma1);
452 Double_t c2 = -1.0/(2.0*sigma2*sigma2);
453 Double_t d = 4.0*c1*c2 /(_sqrt2pi*_nEvents);
456 for (Int_t i = 0; i < _nEvents; ++i)
458 Double_t r1 = _var1[i] - varMean1;
459 Double_t r2 = _var2[i] - varMean2;
460 z += exp( c1 * r1*r1 ) * exp( c2 * r2*r2 );
469 Int_t Roo2DKeysPdf::getBandWidthType()
const
471 if(_BandWidthType == 1) cout <<
"The Bandwidth Type selected is Trivial" << endl;
472 else cout <<
"The Bandwidth Type selected is Adaptive" << endl;
474 return _BandWidthType;
480 Double_t Roo2DKeysPdf::getMean(
const char * axis)
const
482 if(!strcmp(axis,x.GetName()) || !strcmp(axis,
"x") || !strcmp(axis,
"X"))
return _xMean;
483 else if(!strcmp(axis,y.GetName()) || !strcmp(axis,
"y") || !strcmp(axis,
"Y"))
return _yMean;
486 cout <<
"Roo2DKeysPdf::getMean unknown axis "<<axis<<endl;
494 Double_t Roo2DKeysPdf::getSigma(
const char * axis)
const
496 if(!strcmp(axis,x.GetName()) || !strcmp(axis,
"x") || !strcmp(axis,
"X"))
return _xSigma;
497 else if(!strcmp(axis,y.GetName()) || !strcmp(axis,
"y") || !strcmp(axis,
"Y"))
return _ySigma;
500 cout <<
"Roo2DKeysPdf::getSigma unknown axis "<<axis<<endl;
509 void Roo2DKeysPdf::writeToFile(
char * outputFile,
const char * name)
const
511 TString histName = name;
513 TString nName = name;
515 writeHistToFile( outputFile, histName);
516 writeNTupleToFile( outputFile, nName);
526 void Roo2DKeysPdf::writeHistToFile(
char * outputFile,
const char * histName)
const
529 cout <<
"Roo2DKeysPdf::writeHistToFile This member function is temporarily disabled" <<endl;
531 file =
new TFile(outputFile,
"UPDATE");
534 cout <<
"Roo2DKeysPdf::writeHistToFile unable to open file "<< outputFile <<endl;
539 const RooAbsReal & xx = x.arg();
540 const RooAbsReal & yy = y.arg();
541 RooArgSet values( RooArgList( xx, yy ));
542 RooRealVar * xArg = ((RooRealVar*)(values.find(xx.GetName())) ) ;
543 RooRealVar * yArg = ((RooRealVar*)(values.find(yy.GetName())) ) ;
545 TH2F * hist = (TH2F*)xArg->createHistogram(
"hist", *yArg);
546 hist = (TH2F*)this->fillHistogram(hist, RooArgList(*xArg, *yArg) );
547 hist->SetName(histName);
561 void Roo2DKeysPdf::writeNTupleToFile(
char * outputFile,
const char * name)
const
566 file =
new TFile(outputFile,
"UPDATE");
569 cout <<
"Roo2DKeysPdf::writeNTupleToFile unable to open file "<< outputFile <<endl;
572 RooAbsReal & xArg = (RooAbsReal&)x.arg();
573 RooAbsReal & yArg = (RooAbsReal&)y.arg();
575 Double_t theX, theY, hx;
576 TString label = name;
577 label +=
" the source data for 2D Keys PDF";
578 TTree * _theTree =
new TTree(name, label);
579 if(!_theTree) { cout <<
"Unable to get a TTree for output" << endl;
return; }
580 _theTree->SetAutoSave(1000000000);
583 const char * xname = xArg.GetName();
584 const char * yname = yArg.GetName();
585 if (!strcmp(xname,
"")) xname =
"x";
586 if (!strcmp(yname,
"")) yname =
"y";
588 _theTree->Branch(xname, &theX,
" x/D");
589 _theTree->Branch(yname, &theY,
" y/D");
590 _theTree->Branch(
"hx", &hx,
" hx/D");
591 _theTree->Branch(
"hy", &hx,
" hy/D");
593 for(Int_t iEvt = 0; iEvt < _nEvents; iEvt++)
610 void Roo2DKeysPdf::PrintInfo(ostream & out)
const
612 out <<
"Roo2DKeysPDF instance domain information:"<<endl;
613 out <<
"\tX_min = " << _lox <<endl;
614 out <<
"\tX_max = " << _hix <<endl;
615 out <<
"\tY_min = " << _loy <<endl;
616 out <<
"\tY_max = " << _hiy <<endl;
618 out <<
"Data information:" << endl;
619 out <<
"\t<x> = " << _xMean <<endl;
620 out <<
"\tsigma(x) = " << _xSigma <<endl;
621 out <<
"\t<y> = " << _yMean <<endl;
622 out <<
"\tsigma(y) = " << _ySigma <<endl;
624 out <<
"END of info for Roo2DKeys pdf instance"<< endl;