ROOT logo
/*****************************************************************************
 * Project: RooFit                                                           *
 * Package: RooFitModels                                                     *
 * @(#)root/roofit:$Id: RooKeysPdf.cxx 30333 2009-09-21 15:39:17Z wouter $
 * Authors:                                                                  *
 *   GR, Gerhard Raven,   UC San Diego,        raven@slac.stanford.edu       *
 *   DK, David Kirkby,    UC Irvine,         dkirkby@uci.edu                 *
 *   WV, Wouter Verkerke, UC Santa Barbara, verkerke@slac.stanford.edu       *
 *                                                                           *
 * Copyright (c) 2000-2005, Regents of the University of California          *
 *                          and Stanford University. All rights reserved.    *
 *                                                                           *
 * Redistribution and use in source and binary forms,                        *
 * with or without modification, are permitted according to the terms        *
 * listed in LICENSE (http://roofit.sourceforge.net/license.txt)             *
 *****************************************************************************/
#include "RooFit.h"

#include <math.h>
#include "Riostream.h"
#include "TMath.h"

#include "RooKeysPdf.h"
#include "RooAbsReal.h"
#include "RooRealVar.h"
#include "RooRandom.h"
#include "RooDataSet.h"

ClassImp(RooKeysPdf)


//////////////////////////////////////////////////////////////////////////////
//
// BEGIN_HTML
// Class RooKeysPdf implements a one-dimensional kernel estimation p.d.f which model the distribution
// of an arbitrary input dataset as a superposition of Gaussian kernels, one for each data point,
// each contributing 1/N to the total integral of the p.d.f.
// <p>
// If the 'adaptive mode' is enabled, the width of the Gaussian is adaptively calculated from the
// local density of events, i.e. narrow for regions with high event density to preserve details and
// wide for regions with log event density to promote smoothness. The details of the general algorithm
// are described in the following paper: 
// <p>
// Cranmer KS, Kernel Estimation in High-Energy Physics.  
//             Computer Physics Communications 136:198-207,2001 - e-Print Archive: hep ex/0011057
// <p>
// END_HTML
//


//_____________________________________________________________________________
RooKeysPdf::RooKeysPdf() : _dataPts(0), _weights(0)
{
}


//_____________________________________________________________________________
RooKeysPdf::RooKeysPdf(const char *name, const char *title,
                       RooAbsReal& x, RooDataSet& data,
                       Mirror mirror, Double_t rho) :
  RooAbsPdf(name,title),
  _x("x","Dependent",this,x),
  _nEvents(0),
  _dataPts(0),
  _weights(0),
  _mirrorLeft(mirror==MirrorLeft || mirror==MirrorBoth || mirror==MirrorLeftAsymRight),
  _mirrorRight(mirror==MirrorRight || mirror==MirrorBoth || mirror==MirrorAsymLeftRight),
  _asymLeft(mirror==MirrorAsymLeft || mirror==MirrorAsymLeftRight || mirror==MirrorAsymBoth),
  _asymRight(mirror==MirrorAsymRight || mirror==MirrorLeftAsymRight || mirror==MirrorAsymBoth),
  _rho(rho)
{
  // cache stuff about x
  sprintf(_varName, "%s", x.GetName());
  RooRealVar real= (RooRealVar&)(_x.arg());
  _lo = real.getMin();
  _hi = real.getMax();
  _binWidth = (_hi-_lo)/(_nPoints-1);

  // form the lookup table
  LoadDataSet(data);
}



//_____________________________________________________________________________
RooKeysPdf::RooKeysPdf(const RooKeysPdf& other, const char* name):
  RooAbsPdf(other,name), _x("x",this,other._x), _nEvents(other._nEvents),
  _dataPts(0), _weights(0),
  _mirrorLeft( other._mirrorLeft ), _mirrorRight( other._mirrorRight ),
  _asymLeft(other._asymLeft), _asymRight(other._asymRight),
  _rho( other._rho ) {

  // cache stuff about x
  sprintf(_varName, "%s", other._varName );
  _lo = other._lo;
  _hi = other._hi;
  _binWidth = other._binWidth;

  // copy over data and weights... not necessary, commented out for speed
//    _dataPts = new Double_t[_nEvents];
//    _weights = new Double_t[_nEvents];  
//    for (Int_t i= 0; i<_nEvents; i++) {
//      _dataPts[i]= other._dataPts[i];
//      _weights[i]= other._weights[i];
//    }

  // copy over the lookup table
  for (Int_t i= 0; i<_nPoints+1; i++)
    _lookupTable[i]= other._lookupTable[i];
  
}


//_____________________________________________________________________________
RooKeysPdf::~RooKeysPdf() {
  delete[] _dataPts;
  delete[] _weights;
}


void

//_____________________________________________________________________________
RooKeysPdf::LoadDataSet( RooDataSet& data) {
  delete[] _dataPts;
  delete[] _weights;

  // make new arrays for data and weights to fill
  _nEvents= (Int_t)data.numEntries();
  if (_mirrorLeft) _nEvents += data.numEntries();
  if (_mirrorRight) _nEvents += data.numEntries();

  _dataPts = new Double_t[_nEvents];
  _weights = new Double_t[_nEvents];

  Double_t x0(0);
  Double_t x1(0);
  Double_t x2(0);

  Int_t i, idata=0;
  for (i=0; i<data.numEntries(); i++) {
    const RooArgSet *values= data.get(i);
    RooRealVar real= (RooRealVar&)(values->operator[](_varName));

    _dataPts[idata]= real.getVal();
    x0++; x1+=_dataPts[idata]; x2+=_dataPts[idata]*_dataPts[idata];
    idata++;

    if (_mirrorLeft) {
      _dataPts[idata]= 2*_lo - real.getVal();
      idata++;
    }

    if (_mirrorRight) {
      _dataPts[idata]= 2*_hi - real.getVal();
      idata++;
    }
  }

  Double_t meanv=x1/x0;
  Double_t sigmav=sqrt(x2/x0-meanv*meanv);
  Double_t h=TMath::Power(Double_t(4)/Double_t(3),0.2)*TMath::Power(_nEvents,-0.2)*_rho;
  Double_t hmin=h*sigmav*sqrt(2.)/10;
  Double_t norm=h*sqrt(sigmav)/(2.0*sqrt(3.0));

  _weights=new Double_t[_nEvents];
  for(Int_t j=0;j<_nEvents;++j) {
    _weights[j]=norm/sqrt(g(_dataPts[j],h*sigmav));
    if (_weights[j]<hmin) _weights[j]=hmin;
  }
  
  for (i=0;i<_nPoints+1;++i) 
    _lookupTable[i]=evaluateFull( _lo+Double_t(i)*_binWidth );

  
}



//_____________________________________________________________________________
Double_t RooKeysPdf::evaluate() const {
  Int_t i = (Int_t)floor((Double_t(_x)-_lo)/_binWidth);
  if (i<0) {
    cerr << "got point below lower bound:"
	 << Double_t(_x) << " < " << _lo
	 << " -- performing linear extrapolation..." << endl;
    i=0;
  }
  if (i>_nPoints-1) {
    cerr << "got point above upper bound:"
	 << Double_t(_x) << " > " << _hi
	 << " -- performing linear extrapolation..." << endl;
    i=_nPoints-1;
  }
  Double_t dx = (Double_t(_x)-(_lo+i*_binWidth))/_binWidth;
  
  // for now do simple linear interpolation.
  // one day replace by splines...
  return (_lookupTable[i]+dx*(_lookupTable[i+1]-_lookupTable[i]));
}


//_____________________________________________________________________________
Double_t RooKeysPdf::evaluateFull( Double_t x ) const {
  Double_t y=0;

  for (Int_t i=0;i<_nEvents;++i) {
    Double_t chi=(x-_dataPts[i])/_weights[i];
    y+=exp(-0.5*chi*chi)/_weights[i];

    // if mirroring the distribution across either edge of
    // the range ("Boundary Kernels"), pick up the additional
    // contributions
//      if (_mirrorLeft) {
//        chi=(x-(2*_lo-_dataPts[i]))/_weights[i];
//        y+=exp(-0.5*chi*chi)/_weights[i];
//      }
    if (_asymLeft) {
      chi=(x-(2*_lo-_dataPts[i]))/_weights[i];
      y-=exp(-0.5*chi*chi)/_weights[i];
    }
//      if (_mirrorRight) {
//        chi=(x-(2*_hi-_dataPts[i]))/_weights[i];
//        y+=exp(-0.5*chi*chi)/_weights[i];
//      }
    if (_asymRight) {
      chi=(x-(2*_hi-_dataPts[i]))/_weights[i];
      y-=exp(-0.5*chi*chi)/_weights[i];
    }
  }
  
  static const Double_t sqrt2pi(sqrt(2*TMath::Pi()));  
  return y/(sqrt2pi*_nEvents);
}


//_____________________________________________________________________________
Double_t RooKeysPdf::g(Double_t x,Double_t sigmav) const {
  
  Double_t c=Double_t(1)/(2*sigmav*sigmav);

  Double_t y=0;
  for (Int_t i=0;i<_nEvents;++i) {
    Double_t r=x-_dataPts[i];
    y+=exp(-c*r*r);
  }
  
  static const Double_t sqrt2pi(sqrt(2*TMath::Pi()));  
  return y/(sigmav*sqrt2pi*_nEvents);
}
 RooKeysPdf.cxx:1
 RooKeysPdf.cxx:2
 RooKeysPdf.cxx:3
 RooKeysPdf.cxx:4
 RooKeysPdf.cxx:5
 RooKeysPdf.cxx:6
 RooKeysPdf.cxx:7
 RooKeysPdf.cxx:8
 RooKeysPdf.cxx:9
 RooKeysPdf.cxx:10
 RooKeysPdf.cxx:11
 RooKeysPdf.cxx:12
 RooKeysPdf.cxx:13
 RooKeysPdf.cxx:14
 RooKeysPdf.cxx:15
 RooKeysPdf.cxx:16
 RooKeysPdf.cxx:17
 RooKeysPdf.cxx:18
 RooKeysPdf.cxx:19
 RooKeysPdf.cxx:20
 RooKeysPdf.cxx:21
 RooKeysPdf.cxx:22
 RooKeysPdf.cxx:23
 RooKeysPdf.cxx:24
 RooKeysPdf.cxx:25
 RooKeysPdf.cxx:26
 RooKeysPdf.cxx:27
 RooKeysPdf.cxx:28
 RooKeysPdf.cxx:29
 RooKeysPdf.cxx:30
 RooKeysPdf.cxx:31
 RooKeysPdf.cxx:32
 RooKeysPdf.cxx:33
 RooKeysPdf.cxx:34
 RooKeysPdf.cxx:35
 RooKeysPdf.cxx:36
 RooKeysPdf.cxx:37
 RooKeysPdf.cxx:38
 RooKeysPdf.cxx:39
 RooKeysPdf.cxx:40
 RooKeysPdf.cxx:41
 RooKeysPdf.cxx:42
 RooKeysPdf.cxx:43
 RooKeysPdf.cxx:44
 RooKeysPdf.cxx:45
 RooKeysPdf.cxx:46
 RooKeysPdf.cxx:47
 RooKeysPdf.cxx:48
 RooKeysPdf.cxx:49
 RooKeysPdf.cxx:50
 RooKeysPdf.cxx:51
 RooKeysPdf.cxx:52
 RooKeysPdf.cxx:53
 RooKeysPdf.cxx:54
 RooKeysPdf.cxx:55
 RooKeysPdf.cxx:56
 RooKeysPdf.cxx:57
 RooKeysPdf.cxx:58
 RooKeysPdf.cxx:59
 RooKeysPdf.cxx:60
 RooKeysPdf.cxx:61
 RooKeysPdf.cxx:62
 RooKeysPdf.cxx:63
 RooKeysPdf.cxx:64
 RooKeysPdf.cxx:65
 RooKeysPdf.cxx:66
 RooKeysPdf.cxx:67
 RooKeysPdf.cxx:68
 RooKeysPdf.cxx:69
 RooKeysPdf.cxx:70
 RooKeysPdf.cxx:71
 RooKeysPdf.cxx:72
 RooKeysPdf.cxx:73
 RooKeysPdf.cxx:74
 RooKeysPdf.cxx:75
 RooKeysPdf.cxx:76
 RooKeysPdf.cxx:77
 RooKeysPdf.cxx:78
 RooKeysPdf.cxx:79
 RooKeysPdf.cxx:80
 RooKeysPdf.cxx:81
 RooKeysPdf.cxx:82
 RooKeysPdf.cxx:83
 RooKeysPdf.cxx:84
 RooKeysPdf.cxx:85
 RooKeysPdf.cxx:86
 RooKeysPdf.cxx:87
 RooKeysPdf.cxx:88
 RooKeysPdf.cxx:89
 RooKeysPdf.cxx:90
 RooKeysPdf.cxx:91
 RooKeysPdf.cxx:92
 RooKeysPdf.cxx:93
 RooKeysPdf.cxx:94
 RooKeysPdf.cxx:95
 RooKeysPdf.cxx:96
 RooKeysPdf.cxx:97
 RooKeysPdf.cxx:98
 RooKeysPdf.cxx:99
 RooKeysPdf.cxx:100
 RooKeysPdf.cxx:101
 RooKeysPdf.cxx:102
 RooKeysPdf.cxx:103
 RooKeysPdf.cxx:104
 RooKeysPdf.cxx:105
 RooKeysPdf.cxx:106
 RooKeysPdf.cxx:107
 RooKeysPdf.cxx:108
 RooKeysPdf.cxx:109
 RooKeysPdf.cxx:110
 RooKeysPdf.cxx:111
 RooKeysPdf.cxx:112
 RooKeysPdf.cxx:113
 RooKeysPdf.cxx:114
 RooKeysPdf.cxx:115
 RooKeysPdf.cxx:116
 RooKeysPdf.cxx:117
 RooKeysPdf.cxx:118
 RooKeysPdf.cxx:119
 RooKeysPdf.cxx:120
 RooKeysPdf.cxx:121
 RooKeysPdf.cxx:122
 RooKeysPdf.cxx:123
 RooKeysPdf.cxx:124
 RooKeysPdf.cxx:125
 RooKeysPdf.cxx:126
 RooKeysPdf.cxx:127
 RooKeysPdf.cxx:128
 RooKeysPdf.cxx:129
 RooKeysPdf.cxx:130
 RooKeysPdf.cxx:131
 RooKeysPdf.cxx:132
 RooKeysPdf.cxx:133
 RooKeysPdf.cxx:134
 RooKeysPdf.cxx:135
 RooKeysPdf.cxx:136
 RooKeysPdf.cxx:137
 RooKeysPdf.cxx:138
 RooKeysPdf.cxx:139
 RooKeysPdf.cxx:140
 RooKeysPdf.cxx:141
 RooKeysPdf.cxx:142
 RooKeysPdf.cxx:143
 RooKeysPdf.cxx:144
 RooKeysPdf.cxx:145
 RooKeysPdf.cxx:146
 RooKeysPdf.cxx:147
 RooKeysPdf.cxx:148
 RooKeysPdf.cxx:149
 RooKeysPdf.cxx:150
 RooKeysPdf.cxx:151
 RooKeysPdf.cxx:152
 RooKeysPdf.cxx:153
 RooKeysPdf.cxx:154
 RooKeysPdf.cxx:155
 RooKeysPdf.cxx:156
 RooKeysPdf.cxx:157
 RooKeysPdf.cxx:158
 RooKeysPdf.cxx:159
 RooKeysPdf.cxx:160
 RooKeysPdf.cxx:161
 RooKeysPdf.cxx:162
 RooKeysPdf.cxx:163
 RooKeysPdf.cxx:164
 RooKeysPdf.cxx:165
 RooKeysPdf.cxx:166
 RooKeysPdf.cxx:167
 RooKeysPdf.cxx:168
 RooKeysPdf.cxx:169
 RooKeysPdf.cxx:170
 RooKeysPdf.cxx:171
 RooKeysPdf.cxx:172
 RooKeysPdf.cxx:173
 RooKeysPdf.cxx:174
 RooKeysPdf.cxx:175
 RooKeysPdf.cxx:176
 RooKeysPdf.cxx:177
 RooKeysPdf.cxx:178
 RooKeysPdf.cxx:179
 RooKeysPdf.cxx:180
 RooKeysPdf.cxx:181
 RooKeysPdf.cxx:182
 RooKeysPdf.cxx:183
 RooKeysPdf.cxx:184
 RooKeysPdf.cxx:185
 RooKeysPdf.cxx:186
 RooKeysPdf.cxx:187
 RooKeysPdf.cxx:188
 RooKeysPdf.cxx:189
 RooKeysPdf.cxx:190
 RooKeysPdf.cxx:191
 RooKeysPdf.cxx:192
 RooKeysPdf.cxx:193
 RooKeysPdf.cxx:194
 RooKeysPdf.cxx:195
 RooKeysPdf.cxx:196
 RooKeysPdf.cxx:197
 RooKeysPdf.cxx:198
 RooKeysPdf.cxx:199
 RooKeysPdf.cxx:200
 RooKeysPdf.cxx:201
 RooKeysPdf.cxx:202
 RooKeysPdf.cxx:203
 RooKeysPdf.cxx:204
 RooKeysPdf.cxx:205
 RooKeysPdf.cxx:206
 RooKeysPdf.cxx:207
 RooKeysPdf.cxx:208
 RooKeysPdf.cxx:209
 RooKeysPdf.cxx:210
 RooKeysPdf.cxx:211
 RooKeysPdf.cxx:212
 RooKeysPdf.cxx:213
 RooKeysPdf.cxx:214
 RooKeysPdf.cxx:215
 RooKeysPdf.cxx:216
 RooKeysPdf.cxx:217
 RooKeysPdf.cxx:218
 RooKeysPdf.cxx:219
 RooKeysPdf.cxx:220
 RooKeysPdf.cxx:221
 RooKeysPdf.cxx:222
 RooKeysPdf.cxx:223
 RooKeysPdf.cxx:224
 RooKeysPdf.cxx:225
 RooKeysPdf.cxx:226
 RooKeysPdf.cxx:227
 RooKeysPdf.cxx:228
 RooKeysPdf.cxx:229
 RooKeysPdf.cxx:230
 RooKeysPdf.cxx:231
 RooKeysPdf.cxx:232
 RooKeysPdf.cxx:233
 RooKeysPdf.cxx:234
 RooKeysPdf.cxx:235
 RooKeysPdf.cxx:236
 RooKeysPdf.cxx:237
 RooKeysPdf.cxx:238
 RooKeysPdf.cxx:239
 RooKeysPdf.cxx:240
 RooKeysPdf.cxx:241
 RooKeysPdf.cxx:242
 RooKeysPdf.cxx:243
 RooKeysPdf.cxx:244
 RooKeysPdf.cxx:245
 RooKeysPdf.cxx:246
 RooKeysPdf.cxx:247
 RooKeysPdf.cxx:248
 RooKeysPdf.cxx:249
 RooKeysPdf.cxx:250