/*****************************************************************************
 * Project: RooFit                                                           *
 * Package: RooFitModels                                                     *
 * @(#)root/roofit:$Id$
 * 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 <limits>
#include <algorithm>
#include <cmath>
#include "Riostream.h"
#include "TMath.h"

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

#include "TError.h"

using namespace std;

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
//

const Double_t RooKeysPdf::_nSigma = std::sqrt(-2. *
    std::log(std::numeric_limits<Double_t>::epsilon()));

//_____________________________________________________________________________
  RooKeysPdf::RooKeysPdf() : _nEvents(0), _dataPts(0), _dataWgts(0), _weights(0), _sumWgt(0),
			     _mirrorLeft(kFALSE), _mirrorRight(kFALSE), 
			     _asymLeft(kFALSE), _asymRight(kFALSE)
{ 
  // coverity[UNINIT_CTOR]
  TRACE_CREATE
}


//_____________________________________________________________________________
RooKeysPdf::RooKeysPdf(const char *name, const char *title,
                       RooAbsReal& x, RooDataSet& data,
                       Mirror mirror, Double_t rho) :
  RooAbsPdf(name,title),
  _x("x","observable",this,x),
  _nEvents(0),
  _dataPts(0),
  _dataWgts(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
  snprintf(_varName, 128,"%s", x.GetName());
  RooAbsRealLValue& real= (RooRealVar&)(_x.arg());
  _lo = real.getMin();
  _hi = real.getMax();
  _binWidth = (_hi-_lo)/(_nPoints-1);

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



//_____________________________________________________________________________
RooKeysPdf::RooKeysPdf(const char *name, const char *title,
                       RooAbsReal& xpdf, RooRealVar& xdata, RooDataSet& data,
                       Mirror mirror, Double_t rho) :
  RooAbsPdf(name,title),
  _x("x","Observable",this,xpdf),
  _nEvents(0),
  _dataPts(0),
  _dataWgts(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
  snprintf(_varName, 128,"%s", xdata.GetName());
  RooAbsRealLValue& real= (RooRealVar&)(xdata);
  _lo = real.getMin();
  _hi = real.getMax();
  _binWidth = (_hi-_lo)/(_nPoints-1);

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



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

  // cache stuff about x
  snprintf(_varName, 128, "%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];
  
  TRACE_CREATE
}


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

  TRACE_DESTROY
}



//_____________________________________________________________________________
namespace {
  // small helper structure
  struct Data {
    Double_t x;
    Double_t w;
  };
  // helper to order two Data structures
  struct cmp {
    inline bool operator()(const struct Data& a, const struct Data& b) const
    { return a.x < b.x; }
  };
}
void RooKeysPdf::LoadDataSet( RooDataSet& data) {
  delete[] _dataPts;
  delete[] _dataWgts;
  delete[] _weights;

  std::vector<Data> tmp;
  tmp.reserve((1 + _mirrorLeft + _mirrorRight) * data.numEntries());
  Double_t x0 = 0., x1 = 0., x2 = 0.;
  _sumWgt = 0.;
  // read the data set into tmp and accumulate some statistics
  RooRealVar& real = (RooRealVar&)(data.get()->operator[](_varName));
  for (Int_t i = 0; i < data.numEntries(); ++i) {
    data.get(i);
    const Double_t x = real.getVal();
    const Double_t w = data.weight();
    x0 += w;
    x1 += w * x;
    x2 += w * x * x;
    _sumWgt += Double_t(1 + _mirrorLeft + _mirrorRight) * w;

    Data p;
    p.x = x, p.w = w;
    tmp.push_back(p);
    if (_mirrorLeft) {
      p.x = 2. * _lo - x;
      tmp.push_back(p);
    }
    if (_mirrorRight) {
      p.x = 2. * _hi - x;
      tmp.push_back(p);
    }
  }
  // sort the entire data set so that values of x are increasing
  std::sort(tmp.begin(), tmp.end(), cmp());

  // copy the sorted data set to its final destination
  _nEvents = tmp.size();
  _dataPts  = new Double_t[_nEvents];
  _dataWgts = new Double_t[_nEvents];
  for (unsigned i = 0; i < tmp.size(); ++i) {
    _dataPts[i] = tmp[i].x;
    _dataWgts[i] = tmp[i].w;
  }
  {
    // free tmp
    std::vector<Data> tmp2;
    tmp2.swap(tmp);
  }

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

  _weights=new Double_t[_nEvents];
  for(Int_t j=0;j<_nEvents;++j) {
    _weights[j]=norm/std::sqrt(g(_dataPts[j],h*sigmav));
    if (_weights[j]<hmin) _weights[j]=hmin;
  }
  
  // The idea below is that beyond nSigma sigma, the value of the exponential
  // in the Gaussian is well below the machine precision of a double, so it
  // does not contribute any more. That way, we can limit how many bins of the
  // binned approximation in _lookupTable we have to touch when filling it.
  for (Int_t i=0;i<_nPoints+1;++i) _lookupTable[i] = 0.;
  for(Int_t j=0;j<_nEvents;++j) {
      const Double_t xlo = std::min(_hi,
	      std::max(_lo, _dataPts[j] - _nSigma * _weights[j]));
      const Double_t xhi = std::max(_lo,
	      std::min(_hi, _dataPts[j] + _nSigma * _weights[j]));
      if (xlo >= xhi) continue;
      const Double_t chi2incr = _binWidth / _weights[j] / std::sqrt(2.);
      const Double_t weightratio = _dataWgts[j] / _weights[j];
      const Int_t binlo = static_cast<Int_t>(std::floor((xlo - _lo) / _binWidth));
      const Int_t binhi = static_cast<Int_t>(_nPoints - std::floor((_hi - xhi) / _binWidth));
      const Double_t x = (Double_t(_nPoints - binlo) * _lo +
	      Double_t(binlo) * _hi) / Double_t(_nPoints);
      Double_t chi = (x - _dataPts[j]) / _weights[j] / std::sqrt(2.);
      for (Int_t k = binlo; k <= binhi; ++k, chi += chi2incr) {
	  _lookupTable[k] += weightratio * std::exp(- chi * chi);
      }
  }
  if (_asymLeft) {
      for(Int_t j=0;j<_nEvents;++j) {
	  const Double_t xlo = std::min(_hi,
		  std::max(_lo, 2. * _lo - _dataPts[j] + _nSigma * _weights[j]));
	  const Double_t xhi = std::max(_lo,
		  std::min(_hi, 2. * _lo - _dataPts[j] - _nSigma * _weights[j]));
	  if (xlo >= xhi) continue;
	  const Double_t chi2incr = _binWidth / _weights[j] / std::sqrt(2.);
	  const Double_t weightratio = _dataWgts[j] / _weights[j];
	  const Int_t binlo = static_cast<Int_t>(std::floor((xlo - _lo) / _binWidth));
	  const Int_t binhi = static_cast<Int_t>(_nPoints - std::floor((_hi - xhi) / _binWidth));
	  const Double_t x = (Double_t(_nPoints - binlo) * _lo +
		  Double_t(binlo) * _hi) / Double_t(_nPoints);
	  Double_t chi = (x - (2. * _lo - _dataPts[j])) / _weights[j] / std::sqrt(2.);
	  for (Int_t k = binlo; k <= binhi; ++k, chi += chi2incr) {
	      _lookupTable[k] -= weightratio * std::exp(- chi * chi);
	  }
      }
  }
  if (_asymRight) {
      for(Int_t j=0;j<_nEvents;++j) {
	  const Double_t xlo = std::min(_hi,
		  std::max(_lo, 2. * _hi - _dataPts[j] + _nSigma * _weights[j]));
	  const Double_t xhi = std::max(_lo,
		  std::min(_hi, 2. * _hi - _dataPts[j] - _nSigma * _weights[j]));
	  if (xlo >= xhi) continue;
	  const Double_t chi2incr = _binWidth / _weights[j] / std::sqrt(2.);
	  const Double_t weightratio = _dataWgts[j] / _weights[j];
	  const Int_t binlo = static_cast<Int_t>(std::floor((xlo - _lo) / _binWidth));
	  const Int_t binhi = static_cast<Int_t>(_nPoints - std::floor((_hi - xhi) / _binWidth));
	  const Double_t x = (Double_t(_nPoints - binlo) * _lo +
		  Double_t(binlo) * _hi) / Double_t(_nPoints);
	  Double_t chi = (x - (2. * _hi - _dataPts[j])) / _weights[j] / std::sqrt(2.);
	  for (Int_t k = binlo; k <= binhi; ++k, chi += chi2incr) {
	      _lookupTable[k] -= weightratio * std::exp(- chi * chi);
	  }
      }
  }
  static const Double_t sqrt2pi(std::sqrt(2*TMath::Pi()));  
  for (Int_t i=0;i<_nPoints+1;++i) 
    _lookupTable[i] /= sqrt2pi * _sumWgt;
}

//_____________________________________________________________________________
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...
  Double_t ret = (_lookupTable[i]+dx*(_lookupTable[i+1]-_lookupTable[i]));
  if (ret<0) ret=0 ;
  return ret ;
}

Int_t RooKeysPdf::getAnalyticalIntegral(
	RooArgSet& allVars, RooArgSet& analVars, const char* /* rangeName */) const
{
  if (matchArgs(allVars, analVars, _x)) return 1;
  return 0;
}

Double_t RooKeysPdf::analyticalIntegral(Int_t code, const char* rangeName) const
{
  R__ASSERT(1 == code);
  // this code is based on _lookupTable and uses linear interpolation, just as
  // evaluate(); integration is done using the trapez rule
  const Double_t xmin = std::max(_lo, _x.min(rangeName));
  const Double_t xmax = std::min(_hi, _x.max(rangeName));
  const Int_t imin = (Int_t)floor((xmin - _lo) / _binWidth);
  const Int_t imax = std::min((Int_t)floor((xmax - _lo) / _binWidth),
      _nPoints - 1);
  Double_t sum = 0.;
  // sum up complete bins in middle
  if (imin + 1 < imax)
    sum += _lookupTable[imin + 1] + _lookupTable[imax];
  for (Int_t i = imin + 2; i < imax; ++i)
    sum += 2. * _lookupTable[i];
  sum *= _binWidth * 0.5;
  // treat incomplete bins
  const Double_t dxmin = (xmin - (_lo + imin * _binWidth)) / _binWidth;
  const Double_t dxmax = (xmax - (_lo + imax * _binWidth)) / _binWidth;
  if (imin < imax) {
    // first bin
    sum += _binWidth * (1. - dxmin) * 0.5 * (_lookupTable[imin + 1] +
	_lookupTable[imin] + dxmin *
	(_lookupTable[imin + 1] - _lookupTable[imin]));
    // last bin
    sum += _binWidth * dxmax * 0.5 * (_lookupTable[imax] +
	_lookupTable[imax] + dxmax *
	(_lookupTable[imax + 1] - _lookupTable[imax]));
  } else if (imin == imax) {
    // first bin == last bin
    sum += _binWidth * (dxmax - dxmin) * 0.5 * (
	_lookupTable[imin] + dxmin *
	(_lookupTable[imin + 1] - _lookupTable[imin]) +
	_lookupTable[imax] + dxmax *
	(_lookupTable[imax + 1] - _lookupTable[imax]));
  }
  return sum;
}

Int_t RooKeysPdf::getMaxVal(const RooArgSet& vars) const
{
  if (vars.contains(*_x.absArg())) return 1;
  return 0;
}

Double_t RooKeysPdf::maxVal(Int_t code) const
{
  R__ASSERT(1 == code);
  Double_t max = -std::numeric_limits<Double_t>::max();
  for (Int_t i = 0; i <= _nPoints; ++i)
    if (max < _lookupTable[i]) max = _lookupTable[i];
  return max;
}


//_____________________________________________________________________________
Double_t RooKeysPdf::g(Double_t x,Double_t sigmav) const {
  
  Double_t y=0;
  // since data is sorted, we can be a little faster because we know which data
  // points contribute
  Double_t* it = std::lower_bound(_dataPts, _dataPts + _nEvents,
      x - _nSigma * sigmav);
  if (it >= (_dataPts + _nEvents)) return 0.;
  Double_t* iend = std::upper_bound(it, _dataPts + _nEvents,
      x + _nSigma * sigmav);
  for ( ; it < iend; ++it) {
    const Double_t r = (x - *it) / sigmav;
    y += std::exp(-0.5 * r * r);
  }
  
  static const Double_t sqrt2pi(std::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
 RooKeysPdf.cxx:251
 RooKeysPdf.cxx:252
 RooKeysPdf.cxx:253
 RooKeysPdf.cxx:254
 RooKeysPdf.cxx:255
 RooKeysPdf.cxx:256
 RooKeysPdf.cxx:257
 RooKeysPdf.cxx:258
 RooKeysPdf.cxx:259
 RooKeysPdf.cxx:260
 RooKeysPdf.cxx:261
 RooKeysPdf.cxx:262
 RooKeysPdf.cxx:263
 RooKeysPdf.cxx:264
 RooKeysPdf.cxx:265
 RooKeysPdf.cxx:266
 RooKeysPdf.cxx:267
 RooKeysPdf.cxx:268
 RooKeysPdf.cxx:269
 RooKeysPdf.cxx:270
 RooKeysPdf.cxx:271
 RooKeysPdf.cxx:272
 RooKeysPdf.cxx:273
 RooKeysPdf.cxx:274
 RooKeysPdf.cxx:275
 RooKeysPdf.cxx:276
 RooKeysPdf.cxx:277
 RooKeysPdf.cxx:278
 RooKeysPdf.cxx:279
 RooKeysPdf.cxx:280
 RooKeysPdf.cxx:281
 RooKeysPdf.cxx:282
 RooKeysPdf.cxx:283
 RooKeysPdf.cxx:284
 RooKeysPdf.cxx:285
 RooKeysPdf.cxx:286
 RooKeysPdf.cxx:287
 RooKeysPdf.cxx:288
 RooKeysPdf.cxx:289
 RooKeysPdf.cxx:290
 RooKeysPdf.cxx:291
 RooKeysPdf.cxx:292
 RooKeysPdf.cxx:293
 RooKeysPdf.cxx:294
 RooKeysPdf.cxx:295
 RooKeysPdf.cxx:296
 RooKeysPdf.cxx:297
 RooKeysPdf.cxx:298
 RooKeysPdf.cxx:299
 RooKeysPdf.cxx:300
 RooKeysPdf.cxx:301
 RooKeysPdf.cxx:302
 RooKeysPdf.cxx:303
 RooKeysPdf.cxx:304
 RooKeysPdf.cxx:305
 RooKeysPdf.cxx:306
 RooKeysPdf.cxx:307
 RooKeysPdf.cxx:308
 RooKeysPdf.cxx:309
 RooKeysPdf.cxx:310
 RooKeysPdf.cxx:311
 RooKeysPdf.cxx:312
 RooKeysPdf.cxx:313
 RooKeysPdf.cxx:314
 RooKeysPdf.cxx:315
 RooKeysPdf.cxx:316
 RooKeysPdf.cxx:317
 RooKeysPdf.cxx:318
 RooKeysPdf.cxx:319
 RooKeysPdf.cxx:320
 RooKeysPdf.cxx:321
 RooKeysPdf.cxx:322
 RooKeysPdf.cxx:323
 RooKeysPdf.cxx:324
 RooKeysPdf.cxx:325
 RooKeysPdf.cxx:326
 RooKeysPdf.cxx:327
 RooKeysPdf.cxx:328
 RooKeysPdf.cxx:329
 RooKeysPdf.cxx:330
 RooKeysPdf.cxx:331
 RooKeysPdf.cxx:332
 RooKeysPdf.cxx:333
 RooKeysPdf.cxx:334
 RooKeysPdf.cxx:335
 RooKeysPdf.cxx:336
 RooKeysPdf.cxx:337
 RooKeysPdf.cxx:338
 RooKeysPdf.cxx:339
 RooKeysPdf.cxx:340
 RooKeysPdf.cxx:341
 RooKeysPdf.cxx:342
 RooKeysPdf.cxx:343
 RooKeysPdf.cxx:344
 RooKeysPdf.cxx:345
 RooKeysPdf.cxx:346
 RooKeysPdf.cxx:347
 RooKeysPdf.cxx:348
 RooKeysPdf.cxx:349
 RooKeysPdf.cxx:350
 RooKeysPdf.cxx:351
 RooKeysPdf.cxx:352
 RooKeysPdf.cxx:353
 RooKeysPdf.cxx:354
 RooKeysPdf.cxx:355
 RooKeysPdf.cxx:356
 RooKeysPdf.cxx:357
 RooKeysPdf.cxx:358
 RooKeysPdf.cxx:359
 RooKeysPdf.cxx:360
 RooKeysPdf.cxx:361
 RooKeysPdf.cxx:362
 RooKeysPdf.cxx:363
 RooKeysPdf.cxx:364
 RooKeysPdf.cxx:365
 RooKeysPdf.cxx:366
 RooKeysPdf.cxx:367
 RooKeysPdf.cxx:368
 RooKeysPdf.cxx:369
 RooKeysPdf.cxx:370
 RooKeysPdf.cxx:371
 RooKeysPdf.cxx:372
 RooKeysPdf.cxx:373
 RooKeysPdf.cxx:374
 RooKeysPdf.cxx:375
 RooKeysPdf.cxx:376
 RooKeysPdf.cxx:377
 RooKeysPdf.cxx:378
 RooKeysPdf.cxx:379
 RooKeysPdf.cxx:380
 RooKeysPdf.cxx:381
 RooKeysPdf.cxx:382
 RooKeysPdf.cxx:383
 RooKeysPdf.cxx:384
 RooKeysPdf.cxx:385
 RooKeysPdf.cxx:386
 RooKeysPdf.cxx:387
 RooKeysPdf.cxx:388
 RooKeysPdf.cxx:389
 RooKeysPdf.cxx:390
 RooKeysPdf.cxx:391
 RooKeysPdf.cxx:392
 RooKeysPdf.cxx:393
 RooKeysPdf.cxx:394
 RooKeysPdf.cxx:395
 RooKeysPdf.cxx:396
 RooKeysPdf.cxx:397
 RooKeysPdf.cxx:398
 RooKeysPdf.cxx:399
 RooKeysPdf.cxx:400
 RooKeysPdf.cxx:401
 RooKeysPdf.cxx:402
 RooKeysPdf.cxx:403
 RooKeysPdf.cxx:404
 RooKeysPdf.cxx:405
 RooKeysPdf.cxx:406
 RooKeysPdf.cxx:407
 RooKeysPdf.cxx:408
 RooKeysPdf.cxx:409
 RooKeysPdf.cxx:410
 RooKeysPdf.cxx:411
 RooKeysPdf.cxx:412
 RooKeysPdf.cxx:413
 RooKeysPdf.cxx:414
 RooKeysPdf.cxx:415