diff --git a/roofit/inc/RooKeysPdf.h b/roofit/inc/RooKeysPdf.h
index aed0a3d8778ae01c21c30d29b2f522f2f8f133f2..2489af58a923dbfc2dcfc05984a6cc826a7dc17b 100644
--- a/roofit/inc/RooKeysPdf.h
+++ b/roofit/inc/RooKeysPdf.h
@@ -1,7 +1,7 @@
 /*****************************************************************************
  * Project: RooFit                                                           *
  * Package: RooFitModels                                                     *
- *    File: $Id: RooKeysPdf.rdl,v 1.1 2007/03/01 15:23:18 hellas Exp $
+ *    File: $Id: RooKeysPdf.h,v 1.10 2007/05/11 09:13:07 verkerke Exp $
  * Authors:                                                                  *
  *   GR, Gerhard Raven,   UC San Diego,        raven@slac.stanford.edu       *
  *   DK, David Kirkby,    UC Irvine,         dkirkby@uci.edu                 *
@@ -14,201 +14,55 @@
  * with or without modification, are permitted according to the terms        *
  * listed in LICENSE (http://roofit.sourceforge.net/license.txt)             *
  *****************************************************************************/
-#ifndef ROO_KEYS_PDF
-#define ROO_KEYS_PDF
+#ifndef ROO_KEYS
+#define ROO_KEYS
 
 #include "RooAbsPdf.h"
 #include "RooRealProxy.h"
-#include "RooSetProxy.h"
-#include "RooRealConstant.h"
-#include "TVectorD.h"
-#include "TMatrixD.h"
-#include "TMatrixDSym.h"
-#include <map>
-#include <vector>
-#include <string>
 
 class RooRealVar;
-class RooArgList;
-class RooArgSet;
-
-using namespace std;
-
-typedef std::pair<Int_t, vector<vector<Double_t> >::iterator > iiPair;
-typedef std::vector< iiPair > iiVec;
-
-typedef std::pair<Int_t, vector<TVectorD>::iterator > itPair;
-typedef std::vector< itPair > itVec;
 
 class RooKeysPdf : public RooAbsPdf {
-
 public:
-
-  enum Mirror {NoMirror, MirrorLeft, MirrorRight, MirrorBoth,
-               MirrorAsymLeft, MirrorAsymLeftRight,
-               MirrorAsymRight, MirrorLeftAsymRight,
-               MirrorAsymBoth };
-
-  RooKeysPdf(const char *name, const char *title,
-               const RooArgList& varList, RooDataSet& data, 
-	       TString options="a", Double_t rho=1, Double_t nSigma=3,
-	       RooAbsReal& weight=RooRealConstant::value(1));
-
+  enum Mirror { NoMirror, MirrorLeft, MirrorRight, MirrorBoth,
+		MirrorAsymLeft, MirrorAsymLeftRight,
+		MirrorAsymRight, MirrorLeftAsymRight,
+		MirrorAsymBoth };
   RooKeysPdf(const char *name, const char *title,
-               RooAbsReal& x, RooDataSet& data, 
-               Mirror mirror= NoMirror, Double_t rho=1, Double_t nSigma=3,
-	       RooAbsReal& weight=RooRealConstant::value(1));
-
-  RooKeysPdf(const char *name, const char *title,
-               RooAbsReal& x, RooAbsReal &y, RooDataSet& data, 
-               TString options="a", Double_t rho = 1.0, Double_t nSigma=3,
-	       RooAbsReal& weight=RooRealConstant::value(1));
-
+             RooAbsReal& x, RooDataSet& data, Mirror mirror= NoMirror,
+	     Double_t rho=1);
   RooKeysPdf(const RooKeysPdf& other, const char* name=0);
+  virtual TObject* clone(const char* newname) const {return new RooKeysPdf(*this,newname); }
   virtual ~RooKeysPdf();
-
-  virtual TObject* clone(const char* newname) const { return new RooKeysPdf(*this,newname); }
   
-  Int_t getAnalyticalIntegral(RooArgSet& allVars, RooArgSet& analVars, const char* rangeName=0) const ;
-  Double_t analyticalIntegral(Int_t code, const char* rangeName=0) const ;
-
-  inline void fixShape(Bool_t fix) { 
-    createPdf(kFALSE);
-    _fixedShape=fix; 
-  }
+  void LoadDataSet( RooDataSet& data);
 
 protected:
   
-  RooListProxy _varList ;
-  TIterator* _varItr ;   //! do not persist
-  TIterator* _weightItr; //!
-
+  RooRealProxy _x ;
   Double_t evaluate() const;
 
 private:
-
-  struct BoxInfo {
-    Bool_t filled;
-    Bool_t netFluxZ;
-    Double_t nEventsBW;
-    Double_t nEventsBMSW;
-    vector<Double_t> xVarLo, xVarHi;
-    vector<Double_t> xVarLoM3s, xVarLoP3s, xVarHiM3s, xVarHiP3s;
-    map<Int_t,Bool_t> bpsIdcs;
-    vector<Int_t> sIdcs;	
-    vector<Int_t> bIdcs;
-    vector<Int_t> bmsIdcs;
-  } ;
-
-  void     createPdf(Bool_t firstCall=kTRUE) const;  
-  void     setOptions() const;
-  void     initialize() const; 
-  void     loadDataSet(Bool_t firstCall) const;
-  void     mirrorDataSet() const;
-  void     loadWeightSet() const;
-  void     calculateShell(BoxInfo* bi) const;
-  void     calculatePreNorm(BoxInfo* bi) const;
-  void     sortDataIndices(BoxInfo* bi=0) const;
-  void     calculateBandWidth() const;
-  Double_t gauss(vector<Double_t>& x, vector<vector<Double_t> >& weights) const;
-  void     loopRange(vector<Double_t>& x, map<Int_t,Bool_t>& ibMap) const;
-  void     boxInfoInit(BoxInfo* bi, const char* rangeName, Int_t code) const;
-
-  virtual  Bool_t redirectServersHook(const RooAbsCollection& /*newServerList*/, Bool_t /*mustReplaceAll*/, 
-  	                              Bool_t /*nameChange*/, Bool_t /*isRecursive*/) ;
-
-  mutable RooDataSet& _data;
-  mutable TString _options;
-  mutable Double_t _widthFactor;
-  mutable Double_t _nSigma;
-
-  mutable RooRealProxy _weight ;
-  mutable RooSetProxy  _weightParams ;
-  mutable RooAbsReal*  _weightDep ;
-
-  mutable Bool_t _fixedShape;
-  mutable Bool_t _mirror;
-  mutable Bool_t _debug;
-  mutable Bool_t _verbose;
-
-  mutable Double_t _sqrt2pi;
-  mutable Int_t _nDim;
-  mutable Int_t _nEvents;
-  mutable Int_t _nEventsM;
-  mutable Double_t _nEventsW;
-  mutable Double_t _d;
-  mutable Double_t _n;
   
-  // cached info on variable
-
-  mutable vector<vector<Double_t> > _dataPts;
-  mutable vector<TVectorD> _dataPtsR;
-  mutable vector<vector<Double_t> > _weights0;
-  mutable vector<vector<Double_t> > _weights1;
-  mutable vector<vector<Double_t> >* _weights; //!
-  mutable vector<iiVec> _sortIdcs;
-  mutable vector<itVec> _sortTVIdcs;
-
-  mutable vector<string> _varName;
-  mutable vector<Double_t> _rho;
-  mutable RooArgSet _dataVars;
-  mutable vector<Double_t> _x;
-  mutable vector<Double_t> _x0, _x1, _x2;
-  mutable vector<Double_t> _mean, _sigma;
-  mutable vector<Double_t> _xDatLo, _xDatHi;
-  mutable vector<Double_t> _xDatLo3s, _xDatHi3s;
+  Double_t evaluateFull(Double_t x) const;
 
-  mutable Bool_t _netFluxZ;
-  mutable Double_t _nEventsBW;
-  mutable Double_t _nEventsBMSW;
-  mutable vector<Double_t> _xVarLo, _xVarHi;
-  mutable vector<Double_t> _xVarLoM3s, _xVarLoP3s, _xVarHiM3s, _xVarHiP3s;
-  mutable map<Int_t,Bool_t> _bpsIdcs;
-  mutable vector<Int_t>	_sIdcs;	
-  mutable vector<Int_t> _bIdcs;
-  mutable vector<Int_t> _bmsIdcs;
-
-  mutable map<pair<string,int>,BoxInfo*> _rangeBoxInfo ;
-  mutable BoxInfo _fullBoxInfo ;
-
-  mutable vector<Int_t> _idx;
-  mutable Double_t _minWeight;
-  mutable Double_t _maxWeight;
-  mutable map<Int_t,Double_t> _wMap;
-
-  mutable TMatrixDSym* _covMat; 
-  mutable TMatrixDSym* _corrMat; 
-  mutable TMatrixD* _rotMat; 
-  mutable TVectorD* _sigmaR; 
-  mutable TVectorD* _dx;
-  mutable Double_t _sigmaAvgR;
-
-/*
-  /// sorter function
-  struct SorterL2H {
-    Int_t idx;
-    
-    SorterL2H (Int_t index) : idx(index) {}
-    bool operator() (const iiPair& a, const iiPair& b) {
-      const vector<Double_t>& aVec = *(a.second); 
-      const vector<Double_t>& bVec = *(b.second); 
-      return (aVec[idx]<bVec[idx]);
-    }
-  };
-*/
+  Int_t _nEvents;
+  Double_t *_dataPts; //!
+  Double_t *_weights; //!
+  
+  enum { _nPoints = 1000 };
+  Double_t _lookupTable[_nPoints+1];
+  
+  Double_t g(Double_t x,Double_t sigma) const;
 
-  /// sorter function
-  struct SorterTV_L2H {
-    Int_t idx;
-    
-    SorterTV_L2H (Int_t index) : idx(index) {}
-    bool operator() (const itPair& a, const itPair& b) {
-      const TVectorD& aVec = *(a.second); 
-      const TVectorD& bVec = *(b.second); 
-      return (aVec[idx]<bVec[idx]);
-    }
-  };
+  Bool_t _mirrorLeft, _mirrorRight;
+  Bool_t _asymLeft, _asymRight;
 
+  // cached info on variable
+  Char_t _varName[128];
+  Double_t _lo, _hi, _binWidth;
+  Double_t _rho;
+  
   ClassDef(RooKeysPdf,1) // Non-Parametric KEYS PDF
 };
 
diff --git a/roofit/src/RooKeysPdf.cxx b/roofit/src/RooKeysPdf.cxx
index 87948110377b497c2713d6d000c74f303bcd6c2a..3cc9a94f86f82839d1d03d9b6b1cddf9a5ebedd0 100644
--- a/roofit/src/RooKeysPdf.cxx
+++ b/roofit/src/RooKeysPdf.cxx
@@ -1,1147 +1,211 @@
 /*****************************************************************************
  * Project: RooFit                                                           *
  * Package: RooFitModels                                                     *
- *    File: $Id$
+ * @(#)root/roofit:$Name:  $:$Id$
  * Authors:                                                                  *
- *   MB, Max Baak,   Nikhef,        mbaak@nikhef.nl                          *
+ *   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 <iostream>
+#include "RooFit.h"
 
+#include <math.h>
+#include "Riostream.h"
 #include "TMath.h"
-#include "TMatrixDSymEigen.h"
+
 #include "RooKeysPdf.h"
 #include "RooAbsReal.h"
 #include "RooRealVar.h"
 #include "RooRandom.h"
 #include "RooDataSet.h"
-#include "RooHist.h"
-
-using namespace std;
 
 ClassImp(RooKeysPdf)
 
-
-RooKeysPdf::RooKeysPdf(const char *name, const char *title,
-			   const RooArgList& varList, RooDataSet& data,
-			   TString options, Double_t rho, Double_t nSigma,
-			   RooAbsReal& weight) :
-  RooAbsPdf(name,title),
-  _varList("varList","List of variables",this),
-  _data(data),
-  _options(options),
-  _widthFactor(rho),
-  _nSigma(nSigma),
-  _weight("weight","weight formula",this,weight,kFALSE,kFALSE),
-  _weightParams("weightParams","weight parameters",this),
-  _weightDep(0),
-  _weights(&_weights0)
-{
-
-  // Constructor
-  _varItr    = _varList.createIterator() ;
-  _weightItr = _weightParams.createIterator() ;
-
-  TIterator* varItr = varList.createIterator() ;
-  RooAbsArg* var ;
-  for (Int_t i=0; (var = (RooAbsArg*)varItr->Next()); ++i) {
-    if (!dynamic_cast<RooAbsReal*>(var)) {
-      cout << "RooKeysPdf::ctor(" << GetName() << ") ERROR: variable " << var->GetName() 
-           << " is not of type RooAbsReal" << endl ;
-      assert(0) ;
-    }
-    _varList.add(*var) ;
-    _varName.push_back(var->GetName());
-  }
-  delete varItr ;
-
-  // Add parameters of weight function to weightParams 
-  RooArgSet* wgtParams = (RooArgSet*) weight.getParameters(_data) ;
-  _weightParams.add(*wgtParams) ;
-  delete wgtParams ;
-
-  createPdf();
-}
-
-
 RooKeysPdf::RooKeysPdf(const char *name, const char *title,
-                           RooAbsReal& x, RooDataSet& data,
-                           Mirror mirror, Double_t rho, Double_t nSigma,
-			   RooAbsReal& weight) :
+                       RooAbsReal& x, RooDataSet& data,
+                       Mirror mirror, Double_t rho) :
   RooAbsPdf(name,title),
-  _varList("varList","List of variables",this),
-  _data(data),
-  _widthFactor(rho),
-  _nSigma(nSigma), 
-  _weight("weight","weight formula",this,weight,kFALSE,kFALSE),
-  _weightParams("weightParams","weight parameters",this),
-  _weightDep(0),
-  _weights(&_weights0)
-{ 
-  // Constructor
-  _varItr = _varList.createIterator() ;
-  _weightItr = _weightParams.createIterator() ;
+  _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];
   
-  _varList.add(x) ;
-  _varName.push_back(x.GetName());
-
-  if (mirror!=NoMirror) {
-    if (mirror!=MirrorBoth) 
-      cout << "RooKeysPdf::RooKeysPdf() : Warning : asymmetric mirror(s) no longer supported." 
-	   << endl;
-    _options="m";
-  }
-
-  // Add parameters of weight function to weightParams 
-  RooArgSet* wgtParams = (RooArgSet*) weight.getParameters(_data) ;
-  _weightParams.add(*wgtParams) ;
-  delete wgtParams ;
-
-  createPdf();
-}
-
-
-RooKeysPdf::RooKeysPdf(const char *name, const char *title, RooAbsReal& x, RooAbsReal & y,
-                           RooDataSet& data, TString options, Double_t rho, Double_t nSigma,
-			   RooAbsReal& weight) :
-  RooAbsPdf(name,title),
-  _varList("varList","List of variables",this),
-  _data(data),
-  _options(options),
-  _widthFactor(rho),
-  _nSigma(nSigma),
-  _weight("weight","weight formula",this,weight,kFALSE,kFALSE),
-  _weightParams("weightParams","weight parameters",this),
-  _weightDep(0),
-  _weights(&_weights0)
-{ 
-  // Constructor
-  _varItr = _varList.createIterator() ;
-  _weightItr = _weightParams.createIterator() ;
-
-  _varList.add(RooArgSet(x,y)) ;
-  _varName.push_back(x.GetName());
-  _varName.push_back(y.GetName());
-
-  // Add parameters of weight function to weightParams 
-  RooArgSet* wgtParams = (RooArgSet*) weight.getParameters(_data) ;
-  _weightParams.add(*wgtParams) ;
-  delete wgtParams ;
-
-  createPdf();
-}
-
-
-RooKeysPdf::RooKeysPdf(const RooKeysPdf& other, const char* name) :
-  RooAbsPdf(other,name), 
-  _varList("varList",this,other._varList),
-  _data(other._data),
-  _options(other._options),
-  _widthFactor(other._widthFactor),
-  _nSigma(other._nSigma),
-  _weight("weight",this,other._weight),
-  _weightParams("weightParams",this,other._weightParams),
-  _weightDep(0),
-  _weights(&_weights0)
-{
-  // Constructor
-  _varItr      = _varList.createIterator() ;
-  _weightItr   = _weightParams.createIterator() ;
-
-  _fixedShape  = other._fixedShape;
-  _mirror      = other._mirror;
-  _debug       = other._debug;
-  _verbose     = other._verbose;
-  _sqrt2pi     = other._sqrt2pi;
-  _nDim        = other._nDim;
-  _nEvents     = other._nEvents;
-  _nEventsM    = other._nEventsM;
-  _nEventsW    = other._nEventsW;
-  _d           = other._d;
-  _n           = other._n;
-  _dataPts     = other._dataPts;
-  _dataPtsR    = other._dataPtsR;
-  _weights0    = other._weights0;
-  _weights1    = other._weights1;
-  if (_options.Contains("a")) { _weights = &_weights1; }
-  //_sortIdcs    = other._sortIdcs;
-  _sortTVIdcs  = other._sortTVIdcs;
-  _varName     = other._varName;
-  _rho         = other._rho;
-  _x           = other._x;
-  _x0          = other._x0 ;
-  _x1          = other._x1 ;
-  _x2          = other._x2 ;
-  _xDatLo      = other._xDatLo;
-  _xDatHi      = other._xDatHi;
-  _xDatLo3s    = other._xDatLo3s;
-  _xDatHi3s    = other._xDatHi3s;
-  _mean        = other._mean;
-  _sigma       = other._sigma;
-
-  // BoxInfo
-  _netFluxZ    = other._netFluxZ;
-  _nEventsBW   = other._nEventsBW;
-  _nEventsBMSW = other._nEventsBMSW;
-  _xVarLo      = other._xVarLo;
-  _xVarHi      = other._xVarHi;
-  _xVarLoM3s   = other._xVarLoM3s;
-  _xVarLoP3s   = other._xVarLoP3s;
-  _xVarHiM3s   = other._xVarHiM3s;
-  _xVarHiP3s   = other._xVarHiP3s;
-  _bpsIdcs     = other._bpsIdcs;
-  _sIdcs       = other._sIdcs;
-  _bIdcs       = other._bIdcs;
-  _bmsIdcs     = other._bmsIdcs;
-
-  _rangeBoxInfo= other._rangeBoxInfo ;
-  _fullBoxInfo = other._fullBoxInfo ;
-
-  _idx         = other._idx;
-  _minWeight   = other._minWeight;
-  _maxWeight   = other._maxWeight;
-  _wMap        = other._wMap;
-
-  _covMat      = new TMatrixDSym(*other._covMat);
-  _corrMat     = new TMatrixDSym(*other._corrMat);
-  _rotMat      = new TMatrixD(*other._rotMat);
-  _sigmaR      = new TVectorD(*other._sigmaR);
-  _dx          = new TVectorD(*other._dx);
-  _sigmaAvgR   = other._sigmaAvgR;
 }
 
-
-RooKeysPdf::~RooKeysPdf() 
-{
-  if (_varItr)    delete _varItr;
-  if (_weightItr) delete _weightItr;
-  if (_covMat)    delete _covMat;
-  if (_corrMat)   delete _corrMat;
-  if (_rotMat)    delete _rotMat;
-  if (_sigmaR)    delete _sigmaR;
-  if (_dx)        delete _dx;
-  if (_weightDep) delete _weightDep ;
-
-  // delete all the boxinfos map
-  while ( !_rangeBoxInfo.empty() ) {
-    map<pair<string,int>,BoxInfo*>::iterator iter = _rangeBoxInfo.begin();
-    BoxInfo* box= (*iter).second;
-    _rangeBoxInfo.erase(iter);
-    delete box;
-  }
-
-  _dataPts.clear();
-  _dataPtsR.clear();
-  _weights0.clear();
-  _weights1.clear();
-  //_sortIdcs.clear();
-  _sortTVIdcs.clear();
-}
-
-
-void
-RooKeysPdf::createPdf(Bool_t firstCall) const
-{
-  // evaluation order of constructor.
-
-  if (firstCall) {
-    // set options
-    setOptions();
-    // initialization
-    initialize();
-  }
-
-  // copy dataset, calculate sigma_i's, determine min and max event weight
-  loadDataSet(firstCall);
-  // mirror dataset around dataset boundaries -- does not depend on event weights
-  if (_mirror) mirrorDataSet();
-  // store indices and weights of events with high enough weights
-  loadWeightSet();
-
-  // store indices of events in variable boundaries and box shell.
-//calculateShell(&_fullBoxInfo);
-  // calculate normalization needed in analyticalIntegral()
-//calculatePreNorm(&_fullBoxInfo);
-
-  // lookup table for determining which events contribute to a certain coordinate
-  sortDataIndices();
-
-  // determine static and/or adaptive bandwidth
-  calculateBandWidth();
-}
-
-
-void 
-RooKeysPdf::setOptions() const
-{
-  // set the configuration
-
-  _options.ToLower(); 
-
-  if( _options.Contains("a") ) { _weights = &_weights1; }
-  else                         { _weights = &_weights0; }
-  if( _options.Contains("m") )   _mirror = true;
-  else                           _mirror = false;
-  if( _options.Contains("d") )   _debug  = true;
-  else                           _debug  = false;
-  if( _options.Contains("v") ) { _debug = true;  _verbose = true; } 
-  else                         { _debug = false; _verbose = false; }
-
-  if( _debug || _verbose ) {
-    // coutD("InputOptions") << 
-    cout << "RooKeysPdf::setOptions()    options = " << _options 
-	 << "\n\tbandWidthType    = " << _options.Contains("a")    
-	 << "\n\tmirror           = " << _mirror
-	 << "\n\tdebug            = " << _debug            
-	 << "\n\tverbose          = " << _verbose          
-	 << endl;
-  }
-
-  if (_nSigma<2.0) {
-    cout << "RooKeysPdf::setOptions() : Warning : nSigma = " << _nSigma << " < 2.0. "
-	 << "Calculated normalization could be too large." 
-	 << endl;
-  }
+RooKeysPdf::~RooKeysPdf() {
+  delete[] _dataPts;
+  delete[] _weights;
 }
 
 
 void
-RooKeysPdf::initialize() const
-{
-  // initialization
-  _sqrt2pi   = sqrt(2.0*TMath::Pi()) ;
-  _nDim      = _varList.getSize();
-  _nEvents   = (Int_t)_data.numEntries();
-  _nEventsM  = _nEvents;
-  _fixedShape= kFALSE;
+RooKeysPdf::LoadDataSet( RooDataSet& data) {
+  delete[] _dataPts;
+  delete[] _weights;
 
-  if(_nDim==0) {
-    cout << "ERROR:  RooKeysPdf::initialize() : The observable list is empty. "
-	 << "Unable to begin generating the PDF." << endl;
-    assert (_nDim!=0);
-  }
-
-  if(_nEvents==0) {
-    cout << "ERROR:  RooKeysPdf::initialize() : The input data set is empty. "
-	 << "Unable to begin generating the PDF." << endl;
-    assert (_nEvents!=0);
-  }
-
-  _d         = static_cast<Double_t>(_nDim);
-
-  vector<Double_t> dummy(_nDim,0.);
-  _dataPts.resize(_nEvents,dummy);
-  _weights0.resize(_nEvents,dummy);
-  //_sortIdcs.resize(_nDim);
-  _sortTVIdcs.resize(_nDim);
+  // make new arrays for data and weights to fill
+  _nEvents= (Int_t)data.numEntries();
+  if (_mirrorLeft) _nEvents += data.numEntries();
+  if (_mirrorRight) _nEvents += data.numEntries();
 
-  _rho.resize(_nDim,_widthFactor);
+  _dataPts = new Double_t[_nEvents];
+  _weights = new Double_t[_nEvents];
 
-  _x.resize(_nDim,0.);
-  _x0.resize(_nDim,0.);
-  _x1.resize(_nDim,0.);
-  _x2.resize(_nDim,0.);
+  Double_t x0(0);
+  Double_t x1(0);
+  Double_t x2(0);
 
-  _mean.resize(_nDim,0.);
-  _sigma.resize(_nDim,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));
 
-  _xDatLo.resize(_nDim,0.);
-  _xDatHi.resize(_nDim,0.);
-  _xDatLo3s.resize(_nDim,0.);
-  _xDatHi3s.resize(_nDim,0.);
+    _dataPts[idata]= real.getVal();
+    x0++; x1+=_dataPts[idata]; x2+=_dataPts[idata]*_dataPts[idata];
+    idata++;
 
-  boxInfoInit(&_fullBoxInfo,0,0xFFFF);
-
-  _minWeight=0;
-  _maxWeight=0;
-  _wMap.clear();
-
-  _covMat = 0;
-  _corrMat= 0;
-  _rotMat = 0;
-  _sigmaR = 0;
-  _dx = new TVectorD(_nDim); _dx->Zero();
-  _dataPtsR.resize(_nEvents,*_dx);
-
-  _varItr->Reset() ;
-  RooRealVar* var ;
-  for(Int_t j=0; (var=(RooRealVar*)_varItr->Next()); ++j) {
-    _xDatLo[j] = var->getMin();
-    _xDatHi[j] = var->getMax();
-  }
-}
-
-
-void
-RooKeysPdf::loadDataSet(Bool_t firstCall) const
-{
-  // copy the dataset and calculate some useful variables
-
-  // first some initialization
-  _nEventsW=0.;
-  TMatrixD mat(_nDim,_nDim); 
-  if (!_covMat)  _covMat = new TMatrixDSym(_nDim);    
-  if (!_corrMat) _corrMat= new TMatrixDSym(_nDim);    
-  if (!_rotMat)  _rotMat = new TMatrixD(_nDim,_nDim); 
-  if (!_sigmaR)  _sigmaR = new TVectorD(_nDim);       
-  mat.Zero();
-  _covMat->Zero();
-  _corrMat->Zero();
-  _rotMat->Zero();
-  _sigmaR->Zero();
-
-  const RooArgSet* values= _data.get();  
-  vector<RooRealVar*> dVars(_nDim);
-  for  (Int_t j=0; j<_nDim; j++) {
-    dVars[j] = (RooRealVar*)values->find(_varName[j].c_str());
-    _x0[j]=_x1[j]=_x2[j]=0.;
-  }
-
-  RooArgSet* weightObs = _weight.arg().getObservables(_data) ;
-  Int_t nWObs = weightObs->getSize();
-
-  _idx.clear();
-  for (Int_t i=0; i<_nEvents; i++) {
-    _data.get(i); // fills dVars
-    _idx.push_back(i);
-    vector<Double_t>& point  = _dataPts[i];
-    TVectorD& pointV = _dataPtsR[i];
-
-    // update weight if weight depends on observables of event
-    if ( nWObs>0 ) { *weightObs = *values; } // update _weight
-    if ( fabs(_weight)>_maxWeight ) { _maxWeight = fabs(_weight); }
-    _nEventsW += _weight;
-
-    //cout << "Weight : " << _weight << endl;
-
-    for (Int_t j=0; j<_nDim; j++) {
-      for (Int_t k=0; k<_nDim; k++) 
-	mat(j,k) += dVars[j]->getVal() * dVars[k]->getVal() * _weight;
-
-      // only need to do once
-      if (firstCall) 
-	point[j] = pointV[j] = dVars[j]->getVal();
-
-      _x0[j] += 1. * _weight; 
-      _x1[j] += point[j] * _weight ; 
-      _x2[j] += point[j] * point[j] * _weight ;
-
-      // only need to do once
-      if (firstCall) {
-	if (point[j]<_xDatLo[j]) { _xDatLo[j]=point[j]; }
-	if (point[j]>_xDatHi[j]) { _xDatHi[j]=point[j]; }
-      }
+    if (_mirrorLeft) {
+      _dataPts[idata]= 2*_lo - real.getVal();
+      idata++;
     }
-  }
-
-  _n = TMath::Power(4./(_nEventsW*(_d+2.)), 1./(_d+4.)) ; 
-  // = (4/[n(dim(R) + 2)])^1/(dim(R)+4); dim(R) = 2
-  _minWeight = (0.5 - TMath::Erf(_nSigma/sqrt(2.))/2.) * _maxWeight;
 
-  for (Int_t j=0; j<_nDim; j++) {
-    _mean[j]  = _x1[j]/_x0[j];
-    _sigma[j] = sqrt(_x2[j]/_x0[j]-_mean[j]*_mean[j]);
-  }
-
-  for (Int_t j=0; j<_nDim; j++) {
-    for (Int_t k=0; k<_nDim; k++) 
-      (*_covMat)(j,k) = mat(j,k)/_x0[j] - _mean[j]*_mean[k] ;
-  }
-
-  // find decorrelation matrix and eigenvalues (R)
-  TMatrixDSymEigen evCalculator(*_covMat);
-  *_rotMat = evCalculator.GetEigenVectors();
-  *_rotMat = _rotMat->T(); // transpose
-  *_sigmaR = evCalculator.GetEigenValues();
-  for (Int_t j=0; j<_nDim; j++) { (*_sigmaR)[j] = sqrt((*_sigmaR)[j]); }
-
-  for (Int_t j=0; j<_nDim; j++) {
-    for (Int_t k=0; k<_nDim; k++) 
-      (*_corrMat)(j,k) = (*_covMat)(j,k)/(_sigma[j]*_sigma[k]) ;
-  }
-
-
-  if (_verbose) {
-    //_covMat->Print();
-    _rotMat->Print();
-    _corrMat->Print();
-    _sigmaR->Print();
-  }
-
-  _sigmaAvgR=1.;
-  for (Int_t j=0; j<_nDim; j++) { _sigmaAvgR *= (*_sigmaR)[j]; }
-  _sigmaAvgR = TMath::Power(_sigmaAvgR, 1./_d) ;
-
-  for (Int_t i=0; i<_nEvents; i++) {
-    TVectorD& pointR = _dataPtsR[i];
-    pointR *= *_rotMat;
-  }
-
-  if (_verbose)
-    cout << "RooKeysPdf::loadDataSet(" << this << ")" 
-	 << "\n Number of events in dataset: " << _nEvents 
-	 << "\n Weighted number of events in dataset: " << _nEventsW 
-	 << endl; 
-}
-
-
-void
-RooKeysPdf::mirrorDataSet() const
-{
-  // determine mirror dataset.
-  // mirror points are added around the physical boundaries of the dataset
-  // Two steps:
-  // 1. For each entry, determine if it should be mirrored (the mirror configuration).
-  // 2. For each mirror configuration, make the mirror points.
-
-  for (Int_t j=0; j<_nDim; j++) {
-    _xDatLo3s[j] = _xDatLo[j] + _nSigma * (_rho[j] * _n * _sigma[j]);
-    _xDatHi3s[j] = _xDatHi[j] - _nSigma * (_rho[j] * _n * _sigma[j]);
-  }
-
-  vector<Double_t> dummy(_nDim,0.);
-  
-  // 1.
-  for (Int_t i=0; i<_nEvents; i++) {    
-    vector<Double_t>& x = _dataPts[i];
-    
-    Int_t size = 1;
-    vector<vector<Double_t> > mpoints(size,dummy);
-    vector<vector<Int_t> > mjdcs(size);
-    
-    // create all mirror configurations for event i
-    for (Int_t j=0; j<_nDim; j++) {
-      
-      vector<Int_t>& mjdxK = mjdcs[0];
-      vector<Double_t>& mpointK = mpoints[0];
-      
-      // single mirror *at physical boundaries*
-      if ((x[j]>_xDatLo[j] && x[j]<_xDatLo3s[j]) && x[j]<(_xDatLo[j]+_xDatHi[j])/2.) { 
-	mpointK[j] = 2.*_xDatLo[j]-x[j]; 
-	mjdxK.push_back(j);
-      } else if ((x[j]<_xDatHi[j] && x[j]>_xDatHi3s[j]) && x[j]>(_xDatLo[j]+_xDatHi[j])/2.) { 
-	mpointK[j] = 2.*_xDatHi[j]-x[j]; 
-	mjdxK.push_back(j);
-      }
-    }
-    
-    vector<Int_t>& mjdx0 = mjdcs[0];
-    // no mirror point(s) for this event
-    if (size==1 && mjdx0.size()==0) continue;
-    
-    // 2.
-    // generate all mirror points for event i
-    vector<Int_t>& mjdx = mjdcs[0];
-    vector<Double_t>& mpoint = mpoints[0];
-    
-    // number of mirror points for this mirror configuration
-    Int_t eMir = 1 << mjdx.size(); 
-    vector<vector<Double_t> > epoints(eMir,x);
-    
-    for (Int_t m=0; m<Int_t(mjdx.size()); m++) {
-      Int_t size1 = 1 << m;
-      Int_t size2 = 1 << m+1;
-      // copy all previous mirror points
-      for (Int_t l=size1; l<size2; ++l) { 
-	epoints[l] = epoints[l-size1];
-	// fill high mirror points
-	vector<Double_t>& epoint = epoints[l];
-	epoint[mjdx[Int_t(mjdx.size()-1)-m]] = mpoint[mjdx[Int_t(mjdx.size()-1)-m]];
-      }
-    }
-    
-    // remove duplicate mirror points
-    // note that: first epoint == x
-    epoints.erase(epoints.begin());
-
-    // add mirror points of event i to total dataset
-    TVectorD pointR(_nDim); 
-
-    for (Int_t m=0; m<Int_t(epoints.size()); m++) {
-      _idx.push_back(i);
-      _dataPts.push_back(epoints[m]);
-      //_weights0.push_back(_weights0[i]);
-      for (Int_t j=0; j<_nDim; j++) { pointR[j] = (epoints[m])[j]; }
-      _dataPtsR.push_back(pointR);
-    }
-    
-    epoints.clear();
-    mpoints.clear();
-    mjdcs.clear();
-  } // end of event loop
-
-  _nEventsM = Int_t(_dataPts.size());
-}
-
-
-void
-RooKeysPdf::loadWeightSet() const
-{
-  _wMap.clear();
-  const RooArgSet* values= _data.get();  
-
-  RooArgSet* weightObs = _weight.arg().getObservables(_data) ;
-
-  Int_t nWObs =  weightObs->getSize();
-
-  for (Int_t i=0; i<_nEventsM; i++) {
-    _data.get(_idx[i]);
-    if ( nWObs>0 ) { *weightObs = *values; } // update _weight
-    if ( fabs(_weight)>_minWeight ) { 
-      //cout << "weight : " << _weight << endl;
-      _wMap[i] = _weight; 
+    if (_mirrorRight) {
+      _dataPts[idata]= 2*_hi - real.getVal();
+      idata++;
     }
   }
 
-  if (_verbose) { 
-    cout << "RooKeysPdf::loadWeightSet(" << this << ") : Number of weighted events : " << _wMap.size() << endl;
-  }
-}
-
+  Double_t mean=x1/x0;
+  Double_t sigma=sqrt(x2/x0-mean*mean);
+  Double_t h=TMath::Power(Double_t(4)/Double_t(3),0.2)*TMath::Power(_nEvents,-0.2)*_rho;
+  Double_t hmin=h*sigma*sqrt(2.)/10;
+  Double_t norm=h*sqrt(sigma)/(2.0*sqrt(3.0));
 
-void
-RooKeysPdf::calculateShell(BoxInfo* bi) const 
-{
-  // determine points in +/- nSigma shell around the box determined by the variable
-  // ranges. These points are needed in the normalization, to determine probability
-  // leakage in and out of the box.
-
-  //bi->netFluxZ = kTRUE;
-  //bi->bpsIdcs.clear();
-  //bi->sIdcs.clear();
-  //bi->bmsIdcs.clear();
-
-  for (Int_t j=0; j<_nDim; j++) {
-    if (bi->xVarLo[j]==_xDatLo[j] && bi->xVarHi[j]==_xDatHi[j]) { 
-      //cout << bi->xVarLo[j] << " " << _xDatLo[j] << " " << bi->xVarHi[j] << " " << _xDatHi[j] << endl;
-      bi->netFluxZ = bi->netFluxZ && kTRUE; 
-    } else { bi->netFluxZ = kFALSE; }
-
-    bi->xVarLoM3s[j] = bi->xVarLo[j] - _nSigma * (_rho[j] * _n * _sigma[j]);
-    bi->xVarLoP3s[j] = bi->xVarLo[j] + _nSigma * (_rho[j] * _n * _sigma[j]);
-    bi->xVarHiM3s[j] = bi->xVarHi[j] - _nSigma * (_rho[j] * _n * _sigma[j]);
-    bi->xVarHiP3s[j] = bi->xVarHi[j] + _nSigma * (_rho[j] * _n * _sigma[j]);
+  _weights=new Double_t[_nEvents];
+  for(Int_t j=0;j<_nEvents;++j) {
+    _weights[j]=norm/sqrt(g(_dataPts[j],h*sigma));
+    if (_weights[j]<hmin) _weights[j]=hmin;
   }
+  
+  for (i=0;i<_nPoints+1;++i) 
+    _lookupTable[i]=evaluateFull( _lo+Double_t(i)*_binWidth );
 
-  map<Int_t,Double_t>::iterator wMapItr = _wMap.begin();
-
-  //for (Int_t i=0; i<_nEventsM; i++) {    
-  for (; wMapItr!=_wMap.end(); ++wMapItr) {
-    Int_t i = (*wMapItr).first;
-
-    const vector<Double_t>& x = _dataPts[i];
-    Bool_t inVarRange(kTRUE);
-    Bool_t inVarRangePlusShell(kTRUE);
-
-    for (Int_t j=0; j<_nDim; j++) {
-
-      if (x[j]>bi->xVarLo[j] && x[j]<bi->xVarHi[j]) { 
-	inVarRange = inVarRange && kTRUE; 
-      } else { inVarRange = inVarRange && kFALSE; }    
-
-      if (x[j]>bi->xVarLoM3s[j] && x[j]<bi->xVarHiP3s[j]) { 
-	inVarRangePlusShell = inVarRangePlusShell && kTRUE;
-      } else { inVarRangePlusShell = inVarRangePlusShell && kFALSE; }
-    }
-
-    // event in range?
-    if (inVarRange) { 
-      bi->bIdcs.push_back(i);
-    }
-
-    // event in shell?
-    if (inVarRangePlusShell) { 
-      bi->bpsIdcs[i] = kTRUE;
-      Bool_t inShell(kFALSE);      
-      for (Int_t j=0; j<_nDim; j++) {
-	if ((x[j]>bi->xVarLoM3s[j] && x[j]<bi->xVarLoP3s[j]) && x[j]<(bi->xVarLo[j]+bi->xVarHi[j])/2.) { 
-	  inShell = kTRUE;
-	} else if ((x[j]>bi->xVarHiM3s[j] && x[j]<bi->xVarHiP3s[j]) && x[j]>(bi->xVarLo[j]+bi->xVarHi[j])/2.) { 
-	  inShell = kTRUE;
-	}
-      }
-      if (inShell) bi->sIdcs.push_back(i); // needed for normalization
-      else { 
-	bi->bmsIdcs.push_back(i);          // idem
-      }
-    }
-  }
-
-  if (_verbose)
-    cout << "RooKeysPdf::calculateShell() : " 
-	 << "\n Events in shell " << bi->sIdcs.size() 
-	 << "\n Events in box " << bi->bIdcs.size() 
-	 << "\n Events in box and shell " << bi->bpsIdcs.size() 
-	 << endl;
-}
-
-
-void
-RooKeysPdf::calculatePreNorm(BoxInfo* bi) const
-{
-  //bi->nEventsBMSW=0.;
-  //bi->nEventsBW=0.;
-
-  // box minus shell
-  for (Int_t i=0; i<Int_t(bi->bmsIdcs.size()); i++) 
-    bi->nEventsBMSW += _wMap[bi->bmsIdcs[i]];
-
-  // box
-  for (Int_t i=0; i<Int_t(bi->bIdcs.size()); i++) 
-    bi->nEventsBW += _wMap[bi->bIdcs[i]];
-
-  if (_verbose)
-    cout << "RooKeysPdf::calculatePreNorm() : " 
-	 << "\n nEventsBMSW " << bi->nEventsBMSW 
-	 << "\n nEventsBW " << bi->nEventsBW 
-	 << endl;
-}
-
-
-void
-RooKeysPdf::sortDataIndices(BoxInfo* bi) const
-{
-  // sort entries, as needed for loopRange()
-
-  /*
-  iiVec itrVec;
-  vector<vector<Double_t> >::iterator dpItr = _dataPts.begin();
-  for (Int_t i=0; dpItr!=_dataPts.end(); ++dpItr, ++i) {
-    if (bi) {
-      if (bi->bpsIdcs.find(i)!=bi->bpsIdcs.end()) 
-      //if (_wMap.find(i)!=_wMap.end()) 
-	itrVec.push_back(iiPair(i,dpItr));
-    } else itrVec.push_back(iiPair(i,dpItr));
-  }
-
-  for (Int_t j=0; j<_nDim; j++) { 
-    _sortIdcs[j].clear();
-    sort(itrVec.begin(),itrVec.end(),SorterL2H(j));
-    _sortIdcs[j] = itrVec;
-  }
-  */
-
-  itVec itrVecR;
-  vector<TVectorD>::iterator dpRItr = _dataPtsR.begin();
-  for (Int_t i=0; dpRItr!=_dataPtsR.end(); ++dpRItr, ++i) {
-    if (bi) {
-      if (bi->bpsIdcs.find(i)!=bi->bpsIdcs.end()) 
-      //if (_wMap.find(i)!=_wMap.end()) 
-	itrVecR.push_back(itPair(i,dpRItr));
-    } else itrVecR.push_back(itPair(i,dpRItr));
-  }
-
-  for (Int_t j=0; j<_nDim; j++) { 
-    _sortTVIdcs[j].clear();
-    sort(itrVecR.begin(),itrVecR.end(),SorterTV_L2H(j));
-    _sortTVIdcs[j] = itrVecR;
-  }
-
-  if (_verbose) {
-    for (Int_t j=0; j<_nDim; j++) { 
-      cout << "RooKeysPdf::sortDataIndices() : Number of sorted events : " << _sortTVIdcs[j].size() << endl; 
-    }
-  }
-}
-
-
-void
-RooKeysPdf::calculateBandWidth() const
-{
-  if(_verbose) { cout << "RooKeysPdf::calculateBandWidth()" << endl; }
-
-  // non-adaptive bandwidth 
-  // (default, and needed to calculate adaptive bandwidth)
-
-  if(!_options.Contains("a")) 
-    if (_verbose)
-      cout << "RooKeysPdf::calculateBandWidth() Using static bandwidth." << endl;
-
-  for (Int_t i=0; i<_nEvents; i++) {
-    //map<Int_t,Bool_t>::iterator bpsItr; 
-    //for (bpsItr=bi->bpsIdcs.begin(); bpsItr!=bi->bpsIdcs.end(); ++bpsItr) {
-    //Int_t i = (*bpsItr).first;
-    //if (i>=_nEvents) continue;
-
-    vector<Double_t>& weight = _weights0[i];
-    for (Int_t j=0; j<_nDim; j++) { weight[j] = _rho[j] * _n * (*_sigmaR)[j]; }
-  }
-
-  // adaptive width
-  if(_options.Contains("a")) {
-    if (_verbose)
-      cout << "RooKeysPdf::calculateBandWidth() Using adaptive bandwidth." << endl;
-
-    vector<Double_t> dummy(_nDim,0.);
-    //_weights1.clear();
-    _weights1.resize(_nEvents,dummy);
-
-    for(Int_t i=0; i<_nEvents; ++i) {
-      //for (bpsItr=bi->bpsIdcs.begin(); bpsItr!=bi->bpsIdcs.end(); ++bpsItr) {
-      //Int_t i = (*bpsItr).first;
-      //if (i>=_nEvents) continue;
-
-      vector<Double_t>& x = _dataPts[i];
-      Double_t f =  TMath::Power( gauss(x,_weights0)/_nEventsW , -1./(2.*_d) ) ;
-
-      vector<Double_t>& weight = _weights1[i];
-      for (Int_t j=0; j<_nDim; j++) {
-	Double_t norm = ((_rho[j]*_n*(*_sigmaR)[j])/sqrt(_sigmaAvgR)) ; 
-	weight[j] = norm * f / sqrt(12.);
-      }
-    }
-    _weights = &_weights1;
-  } 
-}
-
-
-Double_t
-RooKeysPdf::gauss(vector<Double_t>& x, vector<vector<Double_t> >& weights) const 
-{
-  // loop over all closest point to x, as determined by loopRange()
-
-  if(_nEvents==0) return 0.;
-
-  Double_t z=0.;
-  map<Int_t,Bool_t> ibMap;
-  ibMap.clear();
-
-  // determine loop range for event x
-  loopRange(x,ibMap);
-
-  map<Int_t,Bool_t>::iterator ibMapItr = ibMap.begin();
-
-  for (; ibMapItr!=ibMap.end(); ++ibMapItr) {
-    Int_t i = (*ibMapItr).first;
-
-    Double_t g(1.);
-
-    const vector<Double_t>& point  = _dataPts[i];
-    const vector<Double_t>& weight = weights[_idx[i]];
-
-    for (Int_t j=0; j<_nDim; j++) { (*_dx)[j] = x[j]-point[j]; }
-    *_dx *= *_rotMat; // rotate to decorrelated frame!
-
-    for (Int_t j=0; j<_nDim; j++) {
-      Double_t r = (*_dx)[j];  //x[j] - point[j];
-      Double_t c = 1./(2.*weight[j]*weight[j]);
-
-      g *= exp( -c*r*r );
-      g *= 1./(_sqrt2pi*weight[j]);
-      g *= _wMap[_idx[i]];
-    }
-    z += g;
-  }
-
-  return z;
-}
-
-
-void
-RooKeysPdf::loopRange(vector<Double_t>& x, map<Int_t,Bool_t>& ibMap) const
-{
-  // determine closest points to x, to loop over in evaluate()
-  /*
-  vector<Double_t> xm(_nDim);
-  vector<Double_t> xp(_nDim);
-
-  for (Int_t j=0; j<_nDim; j++) {
-    xRm[j] = xRp[j] = x[j];
-    xm[j] = x[j] - _nSigma * (_rho[j] * _n * _sigma[j]);
-    xp[j] = x[j] + _nSigma * (_rho[j] * _n * _sigma[j]);
-  }
-  vector<vector<Double_t> > xvecm(1,xm);
-  vector<vector<Double_t> > xvecp(1,xp);
-  */
-
-  TVectorD xRm(_nDim);
-  TVectorD xRp(_nDim);
-
-  for (Int_t j=0; j<_nDim; j++) { xRm[j] = xRp[j] = x[j]; }
-
-  xRm *= *_rotMat;
-  xRp *= *_rotMat;
-  for (Int_t j=0; j<_nDim; j++) {
-    xRm[j] -= _nSigma * (_rho[j] * _n * (*_sigmaR)[j]);
-    xRp[j] += _nSigma * (_rho[j] * _n * (*_sigmaR)[j]);
-  }
-
-  vector<TVectorD> xvecRm(1,xRm);
-  vector<TVectorD> xvecRp(1,xRp);
-
-  /*
-  map<Int_t,Bool_t> ibMapT;
-
-  for (Int_t j=0; j<_nDim; j++) {
-    ibMap.clear();
-    iiVec::iterator lo = lower_bound(_sortIdcs[j].begin(), _sortIdcs[j].end(),
-				     iiPair(0,xvecm.begin()), SorterL2H(j));
-    iiVec::iterator hi = upper_bound(_sortIdcs[j].begin(),_sortIdcs[j].end(),
-				     iiPair(0,xvecp.begin()), SorterL2H(j));
-    iiVec::iterator it=lo;
-    if (j==0) {
-      if (_nDim==1) { for (it=lo; it!=hi; ++it) ibMap[(*it).first] = kTRUE; }
-      else { for (it=lo; it!=hi; ++it) ibMapT[(*it).first] = kTRUE; }
-      continue;
-    }
-
-    for (it=lo; it!=hi; ++it) 
-      if (ibMapT.find((*it).first)!=ibMapT.end()) { ibMap[(*it).first] = kTRUE; }
-
-    ibMapT.clear();
-    if (j!=_nDim-1) { ibMapT = ibMap; }
-  }
-  */
-
-
-  map<Int_t,Bool_t> ibMapRT;
-
-  for (Int_t j=0; j<_nDim; j++) {
-    ibMap.clear();
-    itVec::iterator lo = lower_bound(_sortTVIdcs[j].begin(), _sortTVIdcs[j].end(),
-				     itPair(0,xvecRm.begin()), SorterTV_L2H(j));
-    itVec::iterator hi = upper_bound(_sortTVIdcs[j].begin(), _sortTVIdcs[j].end(),
-				     itPair(0,xvecRp.begin()), SorterTV_L2H(j));
-    itVec::iterator it=lo;
-    if (j==0) {
-      if (_nDim==1) { for (it=lo; it!=hi; ++it) ibMap[(*it).first] = kTRUE; }
-      else { for (it=lo; it!=hi; ++it) ibMapRT[(*it).first] = kTRUE; }
-      continue;
-    }
-
-    for (it=lo; it!=hi; ++it) 
-      if (ibMapRT.find((*it).first)!=ibMapRT.end()) { ibMap[(*it).first] = kTRUE; }
-
-    ibMapRT.clear();
-    if (j!=_nDim-1) { ibMapRT = ibMap; }
-  }
-}
-
-
-void
-RooKeysPdf::boxInfoInit(BoxInfo* bi, const char* rangeName, Int_t /*code*/) const
-{
-  vector<Bool_t> doInt(_nDim,kTRUE);
-//   vector<Bool_t> doInt(_nDim,kFALSE);
-//   for (Int_t j=0; j<_nDim; j++) {
-//     Int_t shiftj = 1 << j;
-//     if (code&shiftj) { 
-//       doInt[j] = kTRUE; 
-//     } 
-//   }
-
-  bi->filled = kFALSE;
-
-  bi->xVarLo.resize(_nDim,0.);
-  bi->xVarHi.resize(_nDim,0.);
-  bi->xVarLoM3s.resize(_nDim,0.);
-  bi->xVarLoP3s.resize(_nDim,0.);
-  bi->xVarHiM3s.resize(_nDim,0.);
-  bi->xVarHiP3s.resize(_nDim,0.);
-
-  bi->netFluxZ = kTRUE;
-  bi->bpsIdcs.clear();
-  bi->bIdcs.clear();
-  bi->sIdcs.clear();
-  bi->bmsIdcs.clear();
-
-  bi->nEventsBMSW=0.;
-  bi->nEventsBW=0.;
-
-  _varItr->Reset() ;
-  RooRealVar* var ;
-  for(Int_t j=0; (var=(RooRealVar*)_varItr->Next()); ++j) {
-    if (doInt[j]) {
-      bi->xVarLo[j] = var->getMin(rangeName);
-      bi->xVarHi[j] = var->getMax(rangeName);
-    } else {
-      bi->xVarLo[j] = var->getVal() ;
-      bi->xVarHi[j] = var->getVal() ;
-    }
-  }
-}
-
-
-Double_t 
-RooKeysPdf::evaluate() const 
-{
-  if (!_weightDep) {
-    TString name = Form("%s_params",GetName()) ;
-    _weightDep = new RooFormulaVar(name,name,"1",_weightParams) ;
-  }
-
-  if (_weightDep->isValueDirty() && !_fixedShape) {
-    cout << "RooKeysPdf::evaluate(" << GetName() << ") one of the weight parameters has changed, need to recalculate" << endl ;
-    // Clear dirty flag
-    _weightDep->getVal() ;
-    // recalc pdf
-    createPdf(kFALSE);
-  }
-
-  _varItr->Reset() ;
-  RooAbsReal* var ;
-  const RooArgSet* nset = _varList.nset() ;
-  for(Int_t j=0; (var=(RooAbsReal*)_varItr->Next()); ++j) {    
-    _x[j] = var->getVal(nset);
-  }
-
-  Double_t val = gauss(_x,*_weights);
-
-  if (val>=1E-20)
-    return val ;
-  else 
-    return (1E-20) ;
+  
 }
 
 
-Int_t 
-RooKeysPdf::getAnalyticalIntegral(RooArgSet& allVars, RooArgSet& analVars, const char* rangeName) const
-{
-  cout << "RooKeysPdf::getAnalyticalIntegral allVars = " << allVars << endl ;
-
-  Int_t code=0;
-
-  if (rangeName) { code=0; }
-  if (matchArgs(allVars,analVars,RooArgSet(_varList))) { code=1; }
-
-  return code;
-
-  /*
-  analVars.add(allVars) ;
-
-  Int_t code(0) ;
-  TIterator* iter = allVars.createIterator() ;
-  RooAbsArg* var ;
-  while((var=(RooAbsArg*)iter->Next())) {
-    Int_t index = _varList.index(var) ;
-    if (index>=0) {
-      cout << "code |= (1<<" << index << ")" << endl ;
-      code |= (1<<index) ;
-    }
+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;
   }
-  delete iter ;
-
-  cout << "code = " << code << endl ;
-  return code ;
-  */
-}
-
-
-Double_t 
-RooKeysPdf::analyticalIntegral(Int_t code, const char* rangeName) const
-{
-  if (_verbose) {
-    cout << "Calling RooKeysPdf::analyticalIntegral(" << GetName() << ") with code " << code 
-	 << " and rangeName " << (rangeName?rangeName:"<none>") << endl;
+  if (i>_nPoints-1) {
+    cerr << "got point above upper bound:"
+	 << Double_t(_x) << " > " << _hi
+	 << " -- performing linear extrapolation..." << endl;
+    i=_nPoints-1;
   }
-
-  // determine which observables need to be integrated over ...
-  Int_t nComb = 1 << (_nDim); 
-  assert(code>=1 && code<nComb) ;
-
-  vector<Bool_t> doInt(_nDim,kTRUE);
-//   vector<Bool_t> doInt(_nDim,kFALSE);
-//   for (Int_t j=0; j<_nDim; j++) {
-//     Int_t shiftj = 1 << j;
-//     if (code&shiftj) { 
-//       doInt[j] = kTRUE; 
-//     } 
-//   }
-
-  // get BoxInfo
-  BoxInfo* bi(0);
-
-  if (rangeName) {
-    bi = _rangeBoxInfo[make_pair(rangeName,code)] ;
-    if (!bi) {
-      bi = new BoxInfo ;
-      _rangeBoxInfo[make_pair(rangeName,code)] = bi ;      
-      boxInfoInit(bi,rangeName,code);
-    }
-  } else bi= &_fullBoxInfo ;
-
-  // have boundaries changed?
-  Bool_t newBounds(kFALSE);
-  _varItr->Reset() ;
-  RooRealVar* var ;
-  for(Int_t j=0; (var=(RooRealVar*)_varItr->Next()); ++j) {
-    if ((var->getMin(rangeName)-bi->xVarLo[j]!=0) ||
-	(var->getMax(rangeName)-bi->xVarHi[j]!=0)) {
-      newBounds = kTRUE;
+  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];
     }
   }
-
-  // reset
-  if (newBounds) {
-    cout << "RooKeysPdf::analyticalIntegral() : Found new boundaries ... " << (rangeName?rangeName:"<none>") << endl;
-    boxInfoInit(bi,rangeName,code);    
-  }
-
-  // recalculates netFluxZero and nEventsIR
-  if (!bi->filled || newBounds) {
-    // Fill box info with contents
-    calculateShell(bi);
-    calculatePreNorm(bi);
-    bi->filled = kTRUE;
-    sortDataIndices(bi);    
-  }
-
-  // first guess
-  Double_t norm=bi->nEventsBW;
-
-  if (_mirror && bi->netFluxZ) {
-    // KEYS expression is self-normalized
-    if (_verbose)
-      cout << "RooKeysPdf::analyticalIntegral() : Using mirrored normalization : " << bi->nEventsBW << endl;
-    return bi->nEventsBW;
-  } 
-  // calculate leakage in and out of variable range box
-  else 
-  {
-    norm = bi->nEventsBMSW; 
-    if (norm<0.) norm=0.;
-    
-    for (Int_t i=0; i<Int_t(bi->sIdcs.size()); ++i) {      
-      Double_t prob=1.;
-      const vector<Double_t>& x = _dataPts[bi->sIdcs[i]];
-      const vector<Double_t>& weight = (*_weights)[_idx[bi->sIdcs[i]]];
-      
-      vector<Double_t> chi(_nDim,100.);
-      
-      for (Int_t j=0; j<_nDim; j++) {
-	if(!doInt[j]) continue;
-
-	if ((x[j]>bi->xVarLoM3s[j] && x[j]<bi->xVarLoP3s[j]) && x[j]<(bi->xVarLo[j]+bi->xVarHi[j])/2.) 
-	  chi[j] = (x[j]-bi->xVarLo[j])/weight[j];
-	else if ((x[j]>bi->xVarHiM3s[j] && x[j]<bi->xVarHiP3s[j]) && x[j]>(bi->xVarLo[j]+bi->xVarHi[j])/2.) 
-	  chi[j] = (bi->xVarHi[j]-x[j])/weight[j];
-
-	if (chi[j]>0) // inVarRange
-	  prob *= (0.5 + TMath::Erf(fabs(chi[j])/sqrt(2.))/2.);
-	else // outside Var range
-	  prob *= (0.5 - TMath::Erf(fabs(chi[j])/sqrt(2.))/2.);
-      }
-
-      norm += prob * _wMap[_idx[bi->sIdcs[i]]];    
-    } 
-    
-    if (_verbose)
-      cout << "RooKeysPdf::analyticalIntegral() : Final normalization : " << norm << endl;
-    return norm;
-  }
+  
+  static const Double_t sqrt2pi(sqrt(2*TMath::Pi()));  
+  return y/(sqrt2pi*_nEvents);
 }
 
+Double_t RooKeysPdf::g(Double_t x,Double_t sigma) const {
+  
+  Double_t c=Double_t(1)/(2*sigma*sigma);
 
-Bool_t RooKeysPdf::redirectServersHook(const RooAbsCollection& /*newServerList*/, Bool_t /*mustReplaceAll*/, 
- 					 Bool_t /*nameChange*/, Bool_t /*isRecursive*/) 
-{
-  if (_weightDep) {
-    delete _weightDep ;
-    _weightDep=0 ;
+  Double_t y=0;
+  for (Int_t i=0;i<_nEvents;++i) {
+    Double_t r=x-_dataPts[i];
+    y+=exp(-c*r*r);
   }
   
-  return kFALSE;
+  static const Double_t sqrt2pi(sqrt(2*TMath::Pi()));  
+  return y/(sigma*sqrt2pi*_nEvents);
 }