From 05eb74d5891eab30b15356fc15cb85ca53c249be Mon Sep 17 00:00:00 2001
From: Fons Rademakers <Fons.Rademakers@cern.ch>
Date: Tue, 29 Jul 2008 11:58:09 +0000
Subject: [PATCH] first import of the RooStats code. Still many coding
 violations to be fixed.

git-svn-id: http://root.cern.ch/svn/root/trunk@24970 27541ba8-7e3a-0410-8455-c3a389f83636
---
 Makefile                                    |   4 +-
 config/Makefile.depend                      |  59 +-
 roofit/roostats/Module.mk                   |  70 ++
 roofit/roostats/inc/LinkDef.h               |  41 +
 roofit/roostats/inc/NumberCountingUtils.h   |  61 ++
 roofit/roostats/inc/SPlot.h                 |  55 ++
 roofit/roostats/src/NumberCountingUtils.cxx | 335 ++++++++
 roofit/roostats/src/SPlot.cxx               | 841 ++++++++++++++++++++
 8 files changed, 1445 insertions(+), 21 deletions(-)
 create mode 100644 roofit/roostats/Module.mk
 create mode 100644 roofit/roostats/inc/LinkDef.h
 create mode 100644 roofit/roostats/inc/NumberCountingUtils.h
 create mode 100644 roofit/roostats/inc/SPlot.h
 create mode 100644 roofit/roostats/src/NumberCountingUtils.cxx
 create mode 100644 roofit/roostats/src/SPlot.cxx

diff --git a/Makefile b/Makefile
index 12de714718a..1cac5d3ee3b 100644
--- a/Makefile
+++ b/Makefile
@@ -199,7 +199,7 @@ ifeq ($(BUILDCINTEX),yes)
 MODULES      += cint/cintex
 endif
 ifeq ($(BUILDROOFIT),yes)
-MODULES      += roofit/roofitcore roofit/roofit
+MODULES      += roofit/roofitcore roofit/roofit roofit/roostats
 endif
 ifeq ($(BUILDGDML),yes)
 MODULES      += geom/gdml
@@ -264,7 +264,7 @@ MODULES      += core/unix core/winnt graf2d/x11 graf2d/x11ttf \
                 graf2d/qt gui/qtroot gui/qtgsi net/xrootd net/netx net/alien \
                 proof/proofd proof/proofx proof/clarens proof/peac \
                 sql/oracle io/xmlparser math/mathmore cint/reflex cint/cintex \
-                cint/cint7 roofit/roofitcore roofit/roofit \
+                cint/cint7 roofit/roofitcore roofit/roofit roofit/roostats \
                 math/minuit2 net/monalisa math/fftw sql/odbc math/unuran \
                 geom/gdml graf3d/eve montecarlo/g4root net/glite misc/memstat
 MODULES      := $(sort $(MODULES))   # removes duplicates
diff --git a/config/Makefile.depend b/config/Makefile.depend
index 35b59951da7..0503f973eed 100644
--- a/config/Makefile.depend
+++ b/config/Makefile.depend
@@ -72,7 +72,10 @@ ALIENLIBDEPM           = $(XMLLIB) $(NETXLIB) $(TREELIB) $(PROOFPLAYERLIB) \
                          $(NETLIB) $(IOLIB)
 ROOFITCORELIBDEPM      = $(HISTLIB) $(GRAFLIB) $(MATRIXLIB) $(TREELIB) \
                          $(MINUITLIB) $(IOLIB) $(MATHCORELIB)
-ROOFITLIBDEPM          = $(ROOFITCORELIB) $(TREELIB) $(IOLIB) $(MATRIXLIB) $(MATHCORELIB)
+ROOFITLIBDEPM          = $(ROOFITCORELIB) $(TREELIB) $(IOLIB) $(MATRIXLIB) \
+                         $(MATHCORELIB)
+ROOSTATSLIBDEPM        = $(ROOFITLIB) $(ROOFITCORELIB) $(TREELIB) $(IOLIB) \
+                         $(MATRIXLIB) $(HISTLIB) $(MATHCORELIB)
 CINT7LIBDEPM           = $(REFLEXLIB)
 CINTEXLIBDEPM          = $(REFLEXLIB)
 REFLEXDICTLIBDEPM      = $(REFLEXLIB)
@@ -162,6 +165,7 @@ FOAMLIBDEP             = $(FOAMLIBDEPM)
 ALIENLIBDEP            = $(ALIENLIBDEPM)
 ROOFITCORELIBDEP       = $(ROOFITCORELIBDEPM)
 ROOFITLIBDEP           = $(ROOFITLIBDEPM)
+ROOSTATSLIBDEP         = $(ROOSTATSLIBDEPM)
 CINT7LIBDEP            = $(CINT7LIBDEPM)
 CINTEXLIBDEP           = $(CINTEXLIBDEPM)
 REFEXDICTLIBDEP        = $(REFLEXDICTLIBDEPM)
@@ -231,11 +235,13 @@ PROOFPLAYERLIBEXTRA     = lib/libProof.lib lib/libHist.lib lib/libTree.lib \
                           lib/libRIO.lib lib/libNet.lib lib/libThread.lib \
                           lib/libMathCore.lib
 PROOFDRAWLIBEXTRA       = lib/libTreePlayer.lib lib/libGraf3d.lib \
-                          lib/libGraf.lib lib/libGpad.lib lib/libProofPlayer.lib \
-                          lib/libHist.lib lib/libTree.lib lib/libProof.lib
+                          lib/libGraf.lib lib/libGpad.lib \
+                          lib/libProofPlayer.lib lib/libHist.lib \
+                          lib/libTree.lib lib/libProof.lib
 PROOFXLIBEXTRA          = lib/libNet.lib lib/libProof.lib lib/libThread.lib
-SESSIONVIEWERLIBEXTRA   = lib/libProof.lib lib/libGui.lib lib/libHist.lib lib/libGpad.lib \
-                          lib/libGraf.lib lib/libTree.lib lib/libMathCore.lib
+SESSIONVIEWERLIBEXTRA   = lib/libProof.lib lib/libGui.lib lib/libHist.lib \
+                          lib/libGpad.lib lib/libGraf.lib lib/libTree.lib \
+                          lib/libMathCore.lib
 PEACLIBEXTRA            = lib/libProof.lib lib/libClarens.lib
 PEACGUILIBEXTRA         = lib/libGui.lib
 EGLIBEXTRA              = lib/libGraf3d.lib lib/libGraf.lib lib/libGpad.lib \
@@ -250,15 +256,16 @@ TABLELIBEXTRA           = lib/libTree.lib lib/libGpad.lib lib/libRIO.lib \
                           lib/libGraf3d.lib lib/libGraf.lib lib/libHist.lib \
                           lib/libMathCore.lib
 MLPLIBEXTRA             = lib/libHist.lib lib/libMatrix.lib lib/libTree.lib \
-                          lib/libGraf.lib lib/libGpad.lib lib/libTreePlayer.lib \
-                          lib/libMathCore.lib
+                          lib/libGraf.lib lib/libGpad.lib \
+                          lib/libTreePlayer.lib lib/libMathCore.lib
 SPECTRUMLIBEXTRA        = lib/libHist.lib lib/libMatrix.lib
 TMVALIBEXTRA            = lib/libRIO.lib lib/libHist.lib lib/libMatrix.lib \
                           lib/libTree.lib lib/libGraf.lib lib/libGpad.lib \
                           lib/libTreePlayer.lib lib/libMLP.lib \
                           lib/libMinuit.lib lib/libMathCore.lib
 SPLOTLIBEXTRA           = lib/libMatrix.lib lib/libHist.lib lib/libTree.lib \
-                          lib/libTreePlayer.lib lib/libGraf3d.lib lib/libGraf.lib
+                          lib/libTreePlayer.lib lib/libGraf3d.lib \
+                          lib/libGraf.lib
 QUADPLIBEXTRA           = lib/libMatrix.lib 
 GLLIBEXTRA              = lib/libGraf3d.lib lib/libGui.lib lib/libGraf.lib \
                           lib/libHist.lib lib/libGed.lib lib/libMathCore.lib
@@ -284,7 +291,11 @@ ALIENLIBEXTRA           = lib/libXMLIO.lib lib/libNetx.lib lib/libTree.lib \
 ROOFITCORELIBEXTRA      = lib/libHist.lib lib/libGraf.lib lib/libMatrix.lib \
                           lib/libTree.lib lib/libMinuit.lib lib/libRIO.lib \
                           lib/libMathCore.lib
-ROOFITLIBEXTRA          = lib/libRooFitCore.lib lib/libTree.lib lib/libRIO.lib  lib/libMatrix.lib lib/libMathCore.lib
+ROOFITLIBEXTRA          = lib/libRooFitCore.lib lib/libTree.lib lib/libRIO.lib \
+                          lib/libMatrix.lib lib/libMathCore.lib
+ROOSTATSLIBEXTRA        = lib/libRooFit.lib lib/libRooFitCore.lib \
+                          lib/libTree.lib lib/libRIO.lib  lib/libHist.lib \
+                          lib/libMatrix.lib lib/libMathCore.lib
 CINT7LIBEXTRA           = lib/libReflex.lib
 CINTEXLIBEXTRA          = lib/libReflex.lib
 REFLEXDICTLIBEXTRA      = lib/libReflex.lib
@@ -334,15 +345,18 @@ MINUITLIBEXTRA          = -Llib -lGraf -lHist -lMatrix -lMathCore
 MINUIT2LIBEXTRA         = -Llib -lGraf -lHist -lMatrix -lMathCore
 FUMILILIBEXTRA          = -Llib -lGraf -lHist -lMathCore
 TREELIBEXTRA            = -Llib -lNet -lRIO -lThread
-TREEPLAYERLIBEXTRA      = -Llib -lTree -lGraf3d -lGraf -lHist -lGpad -lRIO -lMathCore
+TREEPLAYERLIBEXTRA      = -Llib -lTree -lGraf3d -lGraf -lHist -lGpad -lRIO \
+                          -lMathCore
 TREEVIEWERLIBEXTRA      = -Llib -lTree -lGpad -lGraf -lHist -lGui -lTreePlayer \
                           -lGed -lRIO -lMathCore
 PROOFLIBEXTRA           = -Llib -lNet -lTree -lThread -lRIO -lMathCore
-PROOFPLAYERLIBEXTRA     = -Llib -lProof -lHist -lTree -lRIO -lNet -lThread -lMathCore
-PROOFDRAWLIBEXTRA       = -Llib -lTreePlayer -lGraf3d -lGraf -lGpad -lProofPlayer \
-                          -lHist -lTree -lProof
+PROOFPLAYERLIBEXTRA     = -Llib -lProof -lHist -lTree -lRIO -lNet -lThread \
+                          -lMathCore
+PROOFDRAWLIBEXTRA       = -Llib -lTreePlayer -lGraf3d -lGraf -lGpad \
+                          -lProofPlayer -lHist -lTree -lProof
 PROOFXLIBEXTRA          = -Llib -lNet -lProof -lThread
-SESSIONVIEWERLIBEXTRA   = -Llib -lProof -lGui -lHist -lGpad -lGraf -lTree -lMathCore
+SESSIONVIEWERLIBEXTRA   = -Llib -lProof -lGui -lHist -lGpad -lGraf -lTree \
+                          -lMathCore
 PEACLIBEXTRA            = -Llib -lProof -lClarens
 PEACGUILIBEXTRA         = -Llib -lGui
 X3DLIBEXTRA             = -Llib -lGraf3d -lGui
@@ -354,12 +368,15 @@ PYTHIA6LIBEXTRA         = -Llib -lEG -lGraf -lVMC -lPhysics $(FPYTHIA6LIBDIR) \
 PYTHIA8LIBEXTRA         = -Llib -lEG -lGraf -lVMC -lPhysics $(FPYTHIA8LIBDIR) \
                           $(FPYTHIA8LIB)
 X11TTFLIBEXTRA          = -Llib -lGX11 -lGraf
-TABLELIBEXTRA           = -Llib -lTree -lGpad -lGraf3d -lGraf -lHist -lRIO -lMathCore
-GLLIBEXTRA              = -Llib -lGpad -lGraf3d -lGui -lGraf -lHist -lGed -lMathCore
+TABLELIBEXTRA           = -Llib -lTree -lGpad -lGraf3d -lGraf -lHist -lRIO \
+                          -lMathCore
+GLLIBEXTRA              = -Llib -lGpad -lGraf3d -lGui -lGraf -lHist -lGed \
+                          -lMathCore
 HBOOKLIBEXTRA           = -Llib -lHist -lMatrix -lTree -lGraf -lTreePlayer \
                           -lRIO -lminicern
 GEOMLIBEXTRA            = -Llib -lRIO -lMathCore
-GEOMPAINTERLIBEXTRA     = -Llib -lGeom -lTree -lGraf3d -lHist -lGpad -lRIO -lMathCore
+GEOMPAINTERLIBEXTRA     = -Llib -lGeom -lTree -lGraf3d -lHist -lGpad -lRIO \
+                          -lMathCore
 GEOMBUILDERLIBEXTRA     = -Llib -lGeom -lGraf3d -lGpad -lGraf -lGui -lGed
 ASIMAGELIBEXTRA         = -Llib -lGraf -lMathCore
 ASIMAGEGUILIBEXTRA      = -Llib -lGraf -lHist -lGui -lASImage -lRIO
@@ -369,7 +386,8 @@ MLPLIBEXTRA             = -Llib -lHist -lMatrix -lTree -lGraf -lGpad \
 SPECTRUMLIBEXTRA        = -Llib -lHist -lMatrix
 TMVALIBEXTRA            = -Llib -lRIO -lHist -lMatrix -lTree -lGraf -lGpad \
                           -lTreePlayer -lMLP -lMinuit -lMathCore
-SPLOTLIBEXTRA           = -Llib -lMatrix -lHist -lTree -lTreePlayer -lGraf3d -lGraf
+SPLOTLIBEXTRA           = -Llib -lMatrix -lHist -lTree -lTreePlayer -lGraf3d \
+                          -lGraf
 QTROOTLIBEXTRA          = -Llib -lGui -lGQt
 GQTLIBEXTRA             = -Llib -lGui -lGpad -lGraf -lRint
 QUADPLIBEXTRA           = -Llib -lMatrix
@@ -379,8 +397,11 @@ GUIHTMLLIBEXTRA         = -Llib -lGui -lGraf -lNet
 XMLLIBEXTRA             = -Llib -lRIO
 FOAMLIBEXTRA            = -Llib -lHist
 ALIENLIBEXTRA           = -Llib -lXMLIO -lNetx -lTree -lProofPlayer -lNet -lRIO
-ROOFITCORELIBEXTRA      = -Llib -lHist -lGraf -lMatrix -lTree -lMinuit -lRIO -lMathCore
+ROOFITCORELIBEXTRA      = -Llib -lHist -lGraf -lMatrix -lTree -lMinuit -lRIO \
+                          -lMathCore
 ROOFITLIBEXTRA          = -Llib -lRooFitCore -lTree -lRIO -lMatrix -lMathCore
+ROOSTATSLIBEXTRA        = -Llib -lRooFit -lRooFitCore -lTree -lRIO -lMatrix \
+                          -lHist -lMathCore
 CINT7LIBEXTRA           = -Llib -lReflex
 CINTEXLIBEXTRA          = -Llib -lReflex
 REFLEXDICTLIBEXTRA      = -Llib -lReflex
diff --git a/roofit/roostats/Module.mk b/roofit/roostats/Module.mk
new file mode 100644
index 00000000000..83ddc786c1a
--- /dev/null
+++ b/roofit/roostats/Module.mk
@@ -0,0 +1,70 @@
+# Module.mk for roostats module
+# Copyright (c) 2008 Rene Brun and Fons Rademakers
+#
+# Author: Kyle Cranmer
+
+MODNAME      := roostats
+MODDIR       := roofit/$(MODNAME)
+MODDIRS      := $(MODDIR)/src
+MODDIRI      := $(MODDIR)/inc
+
+ROOSTATSDIR  := $(MODDIR)
+ROOSTATSDIRS := $(ROOSTATSDIR)/src
+ROOSTATSDIRI := $(ROOSTATSDIR)/inc
+
+##### libRooStats #####
+ROOSTATSL    := $(MODDIRI)/LinkDef.h
+ROOSTATSDS   := $(MODDIRS)/G__RooStats.cxx
+ROOSTATSDO   := $(ROOSTATSDS:.cxx=.o)
+ROOSTATSDH   := $(ROOSTATSDS:.cxx=.h)
+
+ROOSTATSH    := $(filter-out $(MODDIRI)/LinkDef%,$(wildcard $(MODDIRI)/*.h))
+ROOSTATSS    := $(filter-out $(MODDIRS)/G__%,$(wildcard $(MODDIRS)/*.cxx))
+ROOSTATSO    := $(ROOSTATSS:.cxx=.o)
+
+ROOSTATSDEP  := $(ROOSTATSO:.o=.d) $(ROOSTATSDO:.o=.d)
+
+ROOSTATSLIB  := $(LPATH)/libRooStats.$(SOEXT)
+ROOSTATSMAP  := $(ROOSTATSLIB:.$(SOEXT)=.rootmap)
+
+# used in the main Makefile
+ALLHDRS      += $(patsubst $(MODDIRI)/%.h,include/%.h,$(ROOSTATSH))
+ALLLIBS      += $(ROOSTATSLIB)
+ALLMAPS      += $(ROOSTATSMAP)
+
+# include all dependency files
+INCLUDEFILES += $(ROOSTATSDEP)
+
+##### local rules #####
+.PHONY:         all-$(MODNAME) clean-$(MODNAME) distclean-$(MODNAME)
+
+include/%.h:    $(ROOSTATSDIRI)/%.h
+		cp $< $@
+
+$(ROOSTATSLIB): $(ROOSTATSO) $(ROOSTATSDO) $(ORDER_) $(MAINLIBS) \
+                $(ROOSTATSLIBDEP)
+		@$(MAKELIB) $(PLATFORM) $(LD) "$(LDFLAGS)" \
+		   "$(SOFLAGS)" libRooStats.$(SOEXT) $@ \
+		   "$(ROOSTATSO) $(ROOSTATSDO)" \
+		   "$(ROOSTATSLIBEXTRA)"
+
+$(ROOSTATSDS):  $(ROOSTATSH) $(ROOSTATSL) $(ROOTCINTTMPDEP)
+		@echo "Generating dictionary $@..."
+		$(ROOTCINTTMP) -f $@ -c $(ROOSTATSH) $(ROOSTATSL)
+
+$(ROOSTATSMAP): $(RLIBMAP) $(MAKEFILEDEP) $(ROOSTATSL)
+		$(RLIBMAP) -o $(ROOSTATSMAP) -l $(ROOSTATSLIB) \
+		   -d $(ROOSTATSLIBDEPM) -c $(ROOSTATSL)
+
+all-$(MODNAME): $(ROOSTATSLIB) $(ROOSTATSMAP)
+
+clean-$(MODNAME):
+		@rm -f $(ROOSTATSO) $(ROOSTATSDO)
+
+clean::         clean-$(MODNAME)
+
+distclean-$(MODNAME): clean-$(MODNAME)
+		@rm -rf $(ROOSTATSDEP) $(ROOSTATSLIB) $(ROOSTATSMAP) \
+		   $(ROOSTATSDS) $(ROOSTATSDH)
+
+distclean::     distclean-$(MODNAME)
diff --git a/roofit/roostats/inc/LinkDef.h b/roofit/roostats/inc/LinkDef.h
new file mode 100644
index 00000000000..274b4c586f0
--- /dev/null
+++ b/roofit/roostats/inc/LinkDef.h
@@ -0,0 +1,41 @@
+/* @(#)root/roostats:$Id$ */
+
+/*************************************************************************
+ * Copyright (C) 1995-2008, Rene Brun and Fons Rademakers.               *
+ * All rights reserved.                                                  *
+ *                                                                       *
+ * For the licensing terms see $ROOTSYS/LICENSE.                         *
+ * For the list of contributors see $ROOTSYS/README/CREDITS.             *
+ *************************************************************************/
+
+#ifdef __CINT__ 
+
+#pragma link off all globals;
+#pragma link off all classes;
+#pragma link off all functions;
+
+#pragma link C++ namespace NumberCountingUtils;
+#pragma link C++ namespace Statistics;
+
+// for auto-loading namespaces
+#ifdef USE_FOR_AUTLOADING
+#pragma link C++ class NumberCountingUtils;
+#pragma link C++ class Statistics;
+#endif
+
+#pragma link C++ class SPlot+;
+
+#pragma link C++ function NumberCountingUtils::BinomialExpZ(Double_t,Double_t,Double_t);
+#pragma link C++ function NumberCountingUtils::BinomialWithTauExpZ(Double_t,Double_t,Double_t);
+#pragma link C++ function NumberCountingUtils::BinomialObsZ(Double_t,Double_t,Double_t);
+#pragma link C++ function NumberCountingUtils::BinomialWithTauObsZ(Double_t,Double_t,Double_t);
+#pragma link C++ function NumberCountingUtils::BinomialExpP(Double_t,Double_t,Double_t);
+#pragma link C++ function NumberCountingUtils::BinomialWithTauExpP(Double_t,Double_t,Double_t);
+#pragma link C++ function NumberCountingUtils::BinomialObsP(Double_t,Double_t,Double_t);
+#pragma link C++ function NumberCountingUtils::BinomialWithTauObsP(Double_t,Double_t,Double_t);
+
+#pragma link C++ function NumberCountingUtils::ProfileCombinationExpZ(Double_t*,Double_t*,Double_t*,Int_t);
+
+#pragma link C++ function Statistics::PValueToSignificance(Double_t);
+
+#endif
diff --git a/roofit/roostats/inc/NumberCountingUtils.h b/roofit/roostats/inc/NumberCountingUtils.h
new file mode 100644
index 00000000000..ae587de901c
--- /dev/null
+++ b/roofit/roostats/inc/NumberCountingUtils.h
@@ -0,0 +1,61 @@
+// @(#)root/roostats:$Id$
+// Author: Kyle Cranmer   28/07/2008
+
+/*************************************************************************
+ * Copyright (C) 1995-2008, Rene Brun and Fons Rademakers.               *
+ * All rights reserved.                                                  *
+ *                                                                       *
+ * For the licensing terms see $ROOTSYS/LICENSE.                         *
+ * For the list of contributors see $ROOTSYS/README/CREDITS.             *
+ *************************************************************************/
+
+#ifndef ROOT_NumberCountingUtils
+#define ROOT_NumberCountingUtils
+
+#ifndef ROOT_TMath
+#include "TMath.h"
+#endif
+
+namespace Statistics {
+  inline Double_t PValueToSignificance(Double_t pvalue){
+//    return sqrt(2.)*TMath::ErfInverse(1 - 2.*pvalue);
+    return TMath::Abs(TMath::NormQuantile(pvalue) ); 
+  }
+}
+
+/////////////////////////////////////////
+// NumberCountingUtils
+//
+// Encapsulates common number counting utilities
+/////////////////////////////////////////
+
+namespace  NumberCountingUtils {
+
+  ///////////////////////////////////
+  // Standalone Functions.
+  // Naming conventions:
+  //  Exp = Expected
+  //  Obs = Observed
+  //  P   = p-value
+  //  Z   = Z-value or significance in Sigma (one-sided convention)
+  //////////////////////////////////
+
+  
+  Double_t BinomialExpZ(Double_t, Double_t, Double_t);
+  Double_t BinomialWithTauExpZ(Double_t, Double_t, Double_t);   
+  Double_t BinomialObsZ(Double_t, Double_t, Double_t);
+  Double_t BinomialWithTauObsZ(Double_t, Double_t, Double_t);
+
+  Double_t BinomialExpP(Double_t, Double_t, Double_t);
+  Double_t BinomialWithTauExpP(Double_t, Double_t, Double_t);
+  Double_t BinomialObsP(Double_t, Double_t, Double_t);
+  Double_t BinomialWithTauObsP(Double_t, Double_t, Double_t);
+
+  ///////////////////////////////////
+  // RooFit based Functions
+  //////////////////////////////////
+  Double_t ProfileCombinationExpZ(Double_t*, Double_t*, Double_t*, Int_t );
+
+}
+
+#endif
diff --git a/roofit/roostats/inc/SPlot.h b/roofit/roostats/inc/SPlot.h
new file mode 100644
index 00000000000..9c2278610ba
--- /dev/null
+++ b/roofit/roostats/inc/SPlot.h
@@ -0,0 +1,55 @@
+// @(#)root/roostats:$Id$
+// Author: Kyle Cranmer   21/07/2008
+
+/*************************************************************************
+ * Copyright (C) 1995-2008, Rene Brun and Fons Rademakers.               *
+ * All rights reserved.                                                  *
+ *                                                                       *
+ * For the licensing terms see $ROOTSYS/LICENSE.                         *
+ * For the list of contributors see $ROOTSYS/README/CREDITS.             *
+ *************************************************************************/
+
+#ifndef ROOT_SPlot
+#define ROOT_SPlot
+
+class RooAbsReal;
+class RooAbsPdf;
+class RooFitResult;
+class RooRealVar;
+class RooSimultaneous;
+
+#ifndef ROOT_TH1
+#include "TH1.h"
+#endif
+#include "RooFitResult.h"
+#include "RooRealVar.h"
+#include "RooHist.h"
+#include "RooPlot.h"
+#include "RooDataSet.h"
+
+class SPlot : public TH1F {
+public:
+  SPlot();
+  SPlot(const SPlot &other);
+  SPlot(const char* name, const char *title, Int_t nbins, Double_t xmin, Double_t xmax);
+
+  static RooDataSet* 
+  AddSWeightToData(const RooSimultaneous* pdf, const RooArgList &yieldsTmp, 
+		   RooDataSet &data, const RooArgSet &projDeps=RooArgSet()) ;
+  
+
+ void FillSPlot(const RooDataSet &data, TString varname, TString weightname);
+
+  void FillSPlot(const RooAbsReal &x, RooAbsReal &nstar, RooDataSet data, const RooFitResult &fitRes, const RooArgList &pdfList, const RooArgList &yields, Bool_t doErrors, const RooArgSet &projDeps=RooArgSet() );
+  void FillSPlot(const RooAbsReal &x, RooAbsReal &nstar, RooDataSet data, const RooFitResult &fitRes, const RooArgList &pdfList, const RooArgList &yields, RooAbsPdf &totalPdf, Bool_t doErrors, const RooArgSet &projDeps=RooArgSet() );
+
+  void FillSPlot(const RooAbsReal &x, RooAbsReal &nstar, RooDataSet data, const RooFitResult &fitRes, RooAbsPdf &totalPdf, RooArgList &yields, Bool_t doErrors, const RooArgSet &projDeps=RooArgSet() );
+
+  Double_t GetComponentValue(RooAbsPdf &pdf, RooArgList &yieldsTmp, Int_t igood, RooArgSet &normSet);
+
+protected:
+
+  ClassDef(SPlot,1)   // Make sPlot
+};
+
+#endif
diff --git a/roofit/roostats/src/NumberCountingUtils.cxx b/roofit/roostats/src/NumberCountingUtils.cxx
new file mode 100644
index 00000000000..d9dd9cf8266
--- /dev/null
+++ b/roofit/roostats/src/NumberCountingUtils.cxx
@@ -0,0 +1,335 @@
+// @(#)root/roostats:$Id$
+// Author: Kyle Cranmer   28/07/2008
+
+/*************************************************************************
+ * Copyright (C) 1995-2008, Rene Brun and Fons Rademakers.               *
+ * All rights reserved.                                                  *
+ *                                                                       *
+ * For the licensing terms see $ROOTSYS/LICENSE.                         *
+ * For the list of contributors see $ROOTSYS/README/CREDITS.             *
+ *************************************************************************/
+
+/////////////////////////////////////////
+// NumberCountingUtils
+//
+// Encapsulates common number counting utilities
+/////////////////////////////////////////
+  ///////////////////////////////////
+  // Standalone Functions.
+  // Naming conventions:
+  //  Exp = Expected
+  //  Obs = Observed
+  //  P   = p-value
+  //  Z   = Z-value or significance in Sigma (one-sided convention)
+  //////////////////////////////////
+
+#include "NumberCountingUtils.h"
+
+
+// Without this macro the THtml doc for TMath can not be generated
+#if !defined(R__ALPHA) && !defined(R__SOLARIS) && !defined(R__ACC) && !defined(R__FBSD)
+NamespaceImp(NumberCountingUtils)
+#endif
+
+Double_t NumberCountingUtils::BinomialExpP(Double_t signalExp, Double_t backgroundExp, Double_t relativeBkgUncert){
+  // Expected P-value for s=0 in a ratio of Poisson means.  
+  // Here the background and its uncertainty are provided directly and 
+  // assumed to be from the double Poisson counting setup described in the 
+  // BinomialWithTau functions.  
+  // Normally one would know tau directly, but here it is determiend from
+  // the background uncertainty.  This is not strictly correct, but a useful 
+  // approximation.
+  //
+  //
+  // This is based on code and comments from Bob Cousins 
+  //  based on the following papers:
+  //
+  // Statistical Challenges for Searches for New Physics at the LHC
+  // Authors: Kyle Cranmer
+  // http://arxiv.org/abs/physics/0511028
+  //
+  //  Measures of Significance in HEP and Astrophysics
+  //  Authors: J. T. Linnemann
+  //  http://arxiv.org/abs/physics/0312059
+  //
+  // In short, this is the exact frequentist solution to the problem of
+  // a main measurement x distributed as a Poisson around s+b and a sideband or 
+  // auxiliary measurement y distributed as a Poisson around \taub.  Eg. 
+  // L(x,y|s,b,\tau) = Pois(x|s+b)Pois(y|\tau b)
+
+
+  //SIDE BAND EXAMPLE
+  //See Eqn. (19) of Cranmer and pp. 36-37 of Linnemann.
+  //150 total events in signalExp region, 100 in sideband of equal size
+  Double_t mainInf = signalExp+backgroundExp;  //Given
+  Double_t tau = 1./backgroundExp/(relativeBkgUncert*relativeBkgUncert);
+  Double_t auxiliaryInf = backgroundExp*tau;  //Given
+  
+  Double_t P_Bi = TMath::BetaIncomplete(1./(1.+tau),mainInf,auxiliaryInf+1);
+  return P_Bi;
+  
+/*
+Now, if instead the mean background level b in the signal region is
+specified, along with Gaussian rms sigb, then one can fake a Poisson
+sideband (see Linnemann, p. 35, converted to Cranmer's notation) by
+letting tau = b/(sigb*sigb) and y = b*tau.  Thus, for example, if one
+has x=150 and b = 100 +/- 10, one then derives tau and y.  Then one
+has the same two lines of ROOT calling BetaIncomplete and ErfInverse.
+Since I chose these numbers to revert to the previous example, we get
+the same answer:
+*/
+/*
+//GAUSSIAN FAKED AS POISSON EXAMPLE
+x = 150.    //Given
+b = 100.    //Given
+sigb = 10.  //Given
+tau = b/(sigb*sigb)
+y = tau*b   
+Z_Bi = TMath::BetaIncomplete(1./(1.+tau),x,y+1)    
+S = sqrt(2)*TMath::ErfInverse(1 - 2*Z_Bi)     
+
+*/
+
+}
+
+
+Double_t NumberCountingUtils::BinomialWithTauExpP(Double_t signalExp, Double_t backgroundExp, Double_t tau){
+  // Expected P-value for s=0 in a ratio of Poisson means.  
+  // Based on two expectations, a main measurement that might have signal
+  // and an auxiliarly measurement for the background that is signal free.
+  // The expected background in the auxiliary measurement is a factor
+  // tau larger than in the main measurement.
+
+  Double_t mainInf = signalExp+backgroundExp;  //Given
+  Double_t auxiliaryInf = backgroundExp*tau;  //Given
+  
+  Double_t P_Bi = TMath::BetaIncomplete(1./(1.+tau),mainInf,auxiliaryInf+1);
+  
+  return P_Bi;
+  
+}
+
+Double_t NumberCountingUtils::BinomialObsP(Double_t mainObs, Double_t backgroundObs, Double_t relativeBkgUncert){
+  // P-value for s=0 in a ratio of Poisson means.  
+  // Here the background and its uncertainty are provided directly and 
+  // assumed to be from the double Poisson counting setup.  
+  // Normally one would know tau directly, but here it is determiend from
+  // the background uncertainty.  This is not strictly correct, but a useful 
+  // approximation.
+  
+  Double_t tau = 1./backgroundObs/(relativeBkgUncert*relativeBkgUncert);
+  Double_t auxiliaryInf = backgroundObs*tau;  //Given
+  
+    
+  //SIDE BAND EXAMPLE
+  //See Eqn. (19) of Cranmer and pp. 36-37 of Linnemann.
+  Double_t P_Bi = TMath::BetaIncomplete(1./(1.+tau),mainObs,auxiliaryInf+1);
+  
+  return P_Bi;
+
+}
+
+
+Double_t NumberCountingUtils::BinomialWithTauObsP(Double_t mainObs, Double_t auxiliaryObs, Double_t tau){
+  // P-value for s=0 in a ratio of Poisson means.  
+  // Based on two observations, a main measurement that might have signal
+  // and an auxiliarly measurement for the background that is signal free.
+  // The expected background in the auxiliary measurement is a factor
+  // tau larger than in the main measurement.
+
+  //SIDE BAND EXAMPLE
+  //See Eqn. (19) of Cranmer and pp. 36-37 of Linnemann.
+  Double_t P_Bi = TMath::BetaIncomplete(1./(1.+tau),mainObs,auxiliaryObs+1);
+  
+  return P_Bi;
+  
+}
+
+Double_t NumberCountingUtils::BinomialExpZ(Double_t signalExp, Double_t backgroundExp, Double_t relativeBkgUncert) {    
+  // See BinomialExpP
+  return Statistics::PValueToSignificance( BinomialExpP(signalExp,backgroundExp,relativeBkgUncert) ) ;
+  }
+
+Double_t NumberCountingUtils::BinomialWithTauExpZ(Double_t signalExp, Double_t backgroundExp, Double_t tau){
+  // See BinomialWithTauExpP
+  return Statistics::PValueToSignificance( BinomialWithTauExpP(signalExp,backgroundExp,tau) ) ;
+}
+
+
+Double_t NumberCountingUtils::BinomialObsZ(Double_t mainObs, Double_t backgroundObs, Double_t relativeBkgUncert){
+  // See BinomialObsZ
+  return Statistics::PValueToSignificance( BinomialObsP(mainObs,backgroundObs,relativeBkgUncert) ) ;
+}
+
+Double_t NumberCountingUtils::BinomialWithTauObsZ(Double_t mainObs, Double_t auxiliaryObs, Double_t tau){
+  // See BinomialWithTauObsZ
+  return Statistics::PValueToSignificance( BinomialWithTauObsZ(mainObs,auxiliaryObs,tau) ) ;  
+}
+
+/////////////////////////////////////////////////////////////
+//
+//  RooFit based Functions
+//
+/////////////////////////////////////////////////////////////
+#include "RooRealVar.h"
+#include "RooConstVar.h"
+#include "RooAddition.h"
+#include "RooProduct.h"
+#include "RooDataSet.h"
+#include "RooProdPdf.h"
+#include "RooPlot.h"
+#include "TMath.h"
+#include "TCanvas.h"
+#include "RooFitResult.h"
+#include "RooNLLVar.h"
+#include "RooPoisson.h"
+#include "RooGaussian.h"
+#include "RooMinuit.h"
+#include "RooGlobalFunc.h"
+#include "RooCmdArg.h"
+#include "TH2F.h"
+#include "TTree.h"
+#include <sstream>
+
+
+Double_t NumberCountingUtils::ProfileCombinationExpZ(Double_t* sig, 
+						     Double_t* back, 
+						     Double_t* back_syst, 
+						     Int_t nbins){
+
+  // A number counting combination for N channels with uncorrelated background 
+  //  uncertainty.  
+  // Background uncertainty taken into account via the profile likelihood ratio.
+  // Arguements are an array of expected signal, expected background, and relative 
+  // background uncertainty (eg. 0.1 for 10% uncertainty), and the number of channels.
+
+  using namespace RooFit;
+  using std::vector;
+
+  vector<RooRealVar*> backVec, tauVec, xVec, yVec;
+  vector<RooProduct*> sigVec;
+  vector<RooFormulaVar*> splusbVec;
+  vector<RooPoisson*> sigRegions, sidebands;
+  TList likelihoodFactors;
+  TList observablesCollection;
+
+  TTree* tree = new TTree();
+  Double_t* xForTree = new Double_t[nbins];
+  Double_t* yForTree = new Double_t[nbins];
+
+  Double_t MaxSigma = 8; // Needed to set ranges for varaibles.
+
+  RooRealVar*   masterSignal = 
+    new RooRealVar("masterSignal","masterSignal",1., 0., 3.);
+  for(Int_t i=0; i<nbins; ++i){
+    std::stringstream str;
+    str<<"_"<<i;
+    RooRealVar*   expectedSignal = 
+      new RooRealVar(("expected_s"+str.str()).c_str(),("expected_s"+str.str()).c_str(),sig[i], 0., 2*sig[i]);
+    expectedSignal->setConstant(kTRUE);
+
+    RooProduct*   s = 
+      new RooProduct(("s"+str.str()).c_str(),("s"+str.str()).c_str(), RooArgSet(*masterSignal, *expectedSignal)); 
+
+    RooRealVar*   b = 
+      new RooRealVar(("b"+str.str()).c_str(),("b"+str.str()).c_str(),back[i],  0., 1.2*back[i]+MaxSigma*(sqrt(back[i])+back[i]*back_syst[i]));
+    b->Print();
+    Double_t _tau = 1./back[i]/back_syst[i]/back_syst[i];
+    RooRealVar*  tau = 
+      new RooRealVar(("tau"+str.str()).c_str(),("tau"+str.str()).c_str(),_tau,0,2*_tau); 
+    tau->setConstant(kTRUE);
+
+    RooAddition*  splusb = 
+      new RooAddition(("splusb"+str.str()).c_str(),("s"+str.str()+"+"+"b"+str.str()).c_str(),   
+		      RooArgSet(*s,*b)); 
+    RooProduct*   bTau = 
+      new RooProduct(("bTau"+str.str()).c_str(),("b*tau"+str.str()).c_str(),   RooArgSet(*b, *tau)); 
+    RooRealVar*   x = 
+      new RooRealVar(("x"+str.str()).c_str(),("x"+str.str()).c_str(),  sig[i]+back[i], 0., 1.2*sig[i]+back[i]+MaxSigma*sqrt(sig[i]+back[i]));
+    RooRealVar*   y = 
+      new RooRealVar(("y"+str.str()).c_str(),("y"+str.str()).c_str(),  back[i]*_tau,  0., 1.2*back[i]*_tau+MaxSigma*sqrt(back[i]*_tau));
+
+
+    RooPoisson* sigRegion = 
+      new RooPoisson(("sigRegion"+str.str()).c_str(),("sigRegion"+str.str()).c_str(), *x,*splusb);
+    RooPoisson* sideband = 
+      new RooPoisson(("sideband"+str.str()).c_str(),("sideband"+str.str()).c_str(), *y,*bTau);
+
+    sigVec.push_back(s);
+    backVec.push_back(b);
+    tauVec.push_back(tau);
+    xVec.push_back(x);
+    yVec.push_back(y);
+    sigRegions.push_back(sigRegion);
+    sidebands.push_back(sideband);
+
+    likelihoodFactors.Add(sigRegion);
+    likelihoodFactors.Add(sideband);
+    observablesCollection.Add(x);
+    observablesCollection.Add(y);
+    
+    // print to see range on variables
+    //    x->Print();
+    //    y->Print();
+    //    b->Print();
+
+
+    xForTree[i] = sig[i]+back[i];
+    yForTree[i] = back[i]*_tau;
+    tree->Branch(("x"+str.str()).c_str(), xForTree+i ,("x"+str.str()+"/D").c_str());
+    tree->Branch(("y"+str.str()).c_str(), yForTree+i ,("y"+str.str()+"/D").c_str());
+  }
+  tree->Fill();
+  //  tree->Print();
+  //  tree->Scan();
+
+  RooArgSet likelihoodFactorSet(likelihoodFactors);
+  RooProdPdf joint("joint","joint", likelihoodFactorSet );
+  //  likelihoodFactorSet.Print();
+
+  //  cout << "\n print model" << endl;
+  //  joint.Print();
+  //  joint.printCompactTree();
+
+  //  RooArgSet* observableSet = new RooArgSet(observablesCollection);
+  RooArgList* observableList = new RooArgList(observablesCollection);
+
+  //  observableSet->Print();
+  //  observableList->Print();
+
+  //  cout << "Make hypothetical dataset:" << endl;
+  RooDataSet* toyMC = new RooDataSet("data","data", tree, *observableList); // one experiment
+  toyMC->Scan();
+
+  //  cout << "about to do fit \n\n" << endl;
+  RooFitResult* fit = joint.fitTo(*toyMC,Extended(kFALSE),Strategy(0),Hesse(kFALSE),Save(kTRUE),PrintLevel(-1));
+
+  //RooFitResult* fit = joint.fitTo(*toyMC,"sr");
+  //  fit->Print();
+
+  //  joint.Print("v");
+
+  ////////////////////////////////////////
+  /// Calculate significance
+  //////////////////////////////
+  //  cout << "\nFit to signal plus background:" << endl;
+  masterSignal->Print();
+  for(Int_t i=0; i<nbins; ++i) backVec.at(i)->Print();
+  fit->Print();
+  Double_t NLLatMLE= fit->minNll();
+
+
+
+  //  cout << "\nFit to background only:" << endl;
+  masterSignal->setVal(0);
+  masterSignal->setConstant();
+  RooFitResult* fit2 = joint.fitTo(*toyMC,Extended(kFALSE),Hesse(kFALSE),Strategy(0), Minos(kFALSE), Save(kTRUE),PrintLevel(-1));
+
+  masterSignal->Print();
+  for(Int_t i=0; i<nbins; ++i) backVec.at(i)->Print();
+  Double_t NLLatCondMLE= fit2->minNll();
+  fit2->Print();
+
+  return sqrt( 2*(NLLatCondMLE-NLLatMLE)); 
+
+}
diff --git a/roofit/roostats/src/SPlot.cxx b/roofit/roostats/src/SPlot.cxx
new file mode 100644
index 00000000000..edb3a77df25
--- /dev/null
+++ b/roofit/roostats/src/SPlot.cxx
@@ -0,0 +1,841 @@
+// @(#)root/roostats:$Id$
+// Author: Kyle Cranmer   28/07/2008
+
+/*************************************************************************
+ * Copyright (C) 1995-2008, Rene Brun and Fons Rademakers.               *
+ * All rights reserved.                                                  *
+ *                                                                       *
+ * For the licensing terms see $ROOTSYS/LICENSE.                         *
+ * For the list of contributors see $ROOTSYS/README/CREDITS.             *
+ *************************************************************************/
+
+/*****************************************************************************
+ * Project: RooStats
+ * Package: RooFit/RooStats  
+ *
+ * Authors:                     
+ *   Original code from M. Pivk as part of MLFit package from BaBar.
+ *   Modifications:
+ *     Giacinto Piacquadio, Maurizio Pierini: modifications for new RooFit version
+ *     George H. Lewis, Kyle Cranmer: generalized for weighted events
+ * 
+ * Porting to RooStats (with permission) by Kyle Cranmer, July 2008
+ *  documentation for the multiple versions of fillSplot are needed.
+ *
+ *****************************************************************************/
+
+
+
+// This class calculates sWeights used to create an sPlot.  
+// The code is based on 
+// ``SPlot: A statistical tool to unfold data distributions,'' 
+//  Nucl. Instrum. Meth. A 555, 356 (2005) 
+//  [arXiv:physics/0402083].
+//
+// An SPlot gives us  the distribution of some variable, x in our 
+// data sample for a given species (eg. signal or background).  
+// The result is similar to a likelihood projection plot, but no cuts are made, 
+//  so every event contributes to the distribution.
+//
+// [Usage]
+// To use this class, you first must perform your fit twice:  
+// The first time perform your nominal fit.
+// For the second fit, fix your parameters at the minimum, float only your yields 
+// (normalizations), and remove any PDFs correlated with the variable of interest.
+//  Be sure to save the RooFitResult.  
+
+#include <vector>
+#include <map>
+
+#include "SPlot.h"
+#include "RooAbsPdf.h"
+#include "RooDataSet.h"
+#include "RooRealVar.h"
+#include "RooSimultaneous.h"
+
+#include "TMatrixD.h"
+
+ClassImp(SPlot) ;
+
+
+//____________________________________________________________________
+SPlot::SPlot() :
+  TH1F()
+{
+  // Default constructor
+}
+
+//____________________________________________________________________
+SPlot::SPlot(const SPlot &other) :
+  TH1F(other)
+{
+}
+
+//____________________________________________________________________
+SPlot::SPlot(const char* name, const char* title, Int_t nbins, Double_t xmin, Double_t xmax) :
+  TH1F(name, title, nbins, xmin, xmax)
+{
+  // Constructor
+}
+
+
+//____________________________________________________________________
+RooDataSet* SPlot::AddSWeightToData(const RooSimultaneous* pdf,
+				      const RooArgList &yieldsTmp,
+				      RooDataSet &data, const RooArgSet &projDeps) 
+{  
+
+  // Method which adds the sWeights to the dataset.
+  // input is the PDF, a RooArgList of the yields (floating)
+  // the dataset to which the sWeights should be added,
+  // and a RooArgSet of the projDeps (needs better description).
+
+  Int_t nspec = yieldsTmp.getSize();
+  RooArgList yields = *(RooArgList*)yieldsTmp.snapshot(kFALSE);
+
+  // The list of variables to normalize over when calculating PDF values.
+  RooArgSet vars(*data.get());
+  vars.remove(projDeps, kTRUE, kTRUE);
+
+  // Attach data set
+  const_cast<RooSimultaneous*>(pdf)->attachDataSet(data);
+    
+  // first calculate the pdf values for all species and all events
+  std::vector<RooRealVar*> yieldvars ;
+  RooArgSet* parameters = pdf->getParameters(&data) ;
+  //parameters->Print("V") ;
+
+  std::vector<Double_t> yieldvalues ;
+  for (Int_t k = 0; k < nspec; ++k) {
+    RooRealVar* thisyield = dynamic_cast<RooRealVar*>(yields.at(k)) ;
+    RooRealVar* yieldinpdf = dynamic_cast<RooRealVar*>(parameters->find(thisyield->GetName() )) ;
+    std::cout << "yield in pdf: " << yieldinpdf << " " << thisyield->getVal() << std::endl ;
+    yieldvars.push_back(yieldinpdf) ;
+    yieldvalues.push_back(thisyield->getVal()) ;
+  }
+
+  Int_t numevents = data.numEntries() ;
+ 
+  std::vector<std::vector<Double_t> > pdfvalues(numevents,std::vector<Double_t>(nspec,0)) ; 
+  
+  // set all yield to zero
+  for(Int_t m=0; m<nspec; ++m) yieldvars[m]->setVal(0) ;
+  
+  for (Int_t ievt = 0; ievt <numevents; ievt++) {
+    if (ievt % 100 == 0) {
+      std::cout << ".";
+      std::cout.flush();
+    }
+    RooArgSet row(*data.get(ievt));
+    for(Int_t k = 0; k < nspec; ++k) {
+      // set this yield to 1
+      yieldvars[k]->setVal( 1 ) ;
+      // evaluate the pdf
+      Double_t f_k = pdf->getVal(&vars) ;
+      pdfvalues[ievt][k] = f_k ;
+      if( !(f_k>1 || f_k<1) ) std::cout << "Strange pdf value: " << ievt << " " << k << " " << f_k << std::endl ;
+      yieldvars[k]->setVal( 0 ) ;
+    }
+  }
+
+  // check that the likelihood normalization is fine
+  std::vector<Double_t> norm(nspec,0) ;
+  for (Int_t ievt = 0; ievt <numevents ; ievt++) {
+    Double_t dnorm(0) ;
+    for(Int_t k=0; k<nspec; ++k) dnorm += yieldvalues[k] * pdfvalues[ievt][k] ;
+    for(Int_t j=0; j<nspec; ++j) norm[j] += pdfvalues[ievt][j]/dnorm ;
+  }
+  
+  std::cout << "likelihood norms: "  ;
+  for(Int_t k=0; k<nspec; ++k) std::cout << norm[k] << " " ;
+  std::cout << std::endl ;
+
+  // Make a TMatrixD to hold the covariance matrix.
+  TMatrixD covInv(nspec, nspec);
+  for (Int_t i = 0; i < nspec; i++) for (Int_t j = 0; j < nspec; j++) covInv(i,j) = 0;
+
+  std::cout << "Calculating covariance matrix";
+  for (Int_t ievt = 0; ievt < numevents; ++ievt) {
+
+    // Calculate contribution to the inverse of the covariance
+    // matrix. See BAD 509 V2 eqn. 15
+
+    // Sum for the denominator
+    Double_t dsum(0);
+    for(Int_t k = 0; k < nspec; ++k) 
+      dsum += pdfvalues[ievt][k] * yieldvalues[k] ;
+
+    for(Int_t n=0; n<nspec; ++n)
+      for(Int_t j=0; j<nspec; ++j) 
+	covInv(n,j) +=  pdfvalues[ievt][n]*pdfvalues[ievt][j]/(dsum*dsum);
+  }
+  // Covariance inverse should now be computed!
+  covInv.Print();
+  
+  // Invert to get the covariance matrix
+  if (covInv.Determinant() <=0) {
+    std::cout << "SPlot Error: covariance matrix is singular; I can't invert it!" << std::endl;
+    covInv.Print();
+    return 0 ;
+  }
+
+  TMatrixD covMatrix(TMatrixD::kInverted,covInv);
+  covMatrix.Print() ;
+
+  //check cov normalization
+  for(Int_t k=0; k<nspec; ++k) {
+    Double_t covnorm(0) ;
+    for(Int_t m=0; m<nspec; ++m) covnorm += covInv[k][m]*yieldvalues[m] ;
+    Double_t sumrow(0) ;
+    for(Int_t m = 0; m < nspec; ++m) sumrow += covMatrix[k][m] ;
+    std::cout << yieldvalues[k] << " " << sumrow << " " << covnorm << std::endl ;
+  }
+
+  // calculate for each event the sWeight (BAD 509 V2 eq. 21)
+  std::cout << "Calculating sWeight";
+  std::vector<RooRealVar*> sweightvec ;
+  std::vector<RooRealVar*> pdfvec ;  
+  RooArgSet sweightset ;
+
+  char wname[256] ;
+  for(Int_t k=0; k<nspec; ++k) {
+    sprintf(wname,"%s_sw", yieldvars[k]->GetName()) ;
+    RooRealVar* var = new RooRealVar(wname,wname,0) ;
+    sweightvec.push_back( var) ;
+    sweightset.add(*var) ;
+    sprintf(wname,"L_%s", yieldvars[k]->GetName()) ;
+    var = new RooRealVar(wname,wname,0) ;
+    pdfvec.push_back( var) ;
+    sweightset.add(*var) ;
+  }
+  sweightset.add(*data.get()) ;
+  RooDataSet* sWeightData = new RooDataSet("dataset", "dataset with sWeights", sweightset);
+  
+  for(Int_t ievt = 0; ievt < numevents; ++ievt) {
+    
+    data.get(ievt) ;
+
+    // sum for denominator
+    Double_t dsum(0);
+    for(Int_t k = 0; k < nspec; ++k) dsum += pdfvalues[ievt][k] * yieldvalues[k] ;
+    
+    // covariance weighted pdf for each specief
+    Double_t sweightsum(0) ;
+    for(Int_t n=0; n<nspec; ++n) {
+      Double_t nsum(0) ;
+      for(Int_t j=0; j<nspec; ++j) nsum += covMatrix(n,j) * pdfvalues[ievt][j] ;      
+      sweightvec[n]->setVal(nsum/dsum) ;
+      pdfvec[n]->setVal( pdfvalues[ievt][n] ) ;
+      sweightsum+=  nsum/dsum ;
+      if( !(fabs(nsum/dsum)>=0 ) ) {
+	std::cout << "error: " << nsum/dsum << std::endl ;
+	return 0 ;
+      }
+
+      //std::cout << nsum/dsum << " " ;
+    }
+    sWeightData->add(sweightset) ;
+    //std::cout << "sum : " << sweightsum << std::endl ;
+  }
+  std::cout << "number of entries in new dataset: " << data.numEntries() << " " 
+       << sWeightData->numEntries() << std::endl ;
+
+  //RooDataSet mergeddata; 
+  //mergeddata.merge(&data,&sWeightData) ;
+  //data.merge(&sWeightData);
+  //std::cout << "number of entries in final dataset: " << data.numEntries() << std::endl ;
+  return sWeightData ;
+}
+
+//____________________________________________________________________
+void SPlot::FillSPlot(const RooDataSet &data, TString varname, TString weightname) 
+{
+  // Method to fill an SPlot for a given variable varname
+  if (data.get()->find(varname) == NULL) {
+    std::cout << "Can't find variable " << varname << " in data set!" << std::endl;
+    return;
+  }
+  
+  if (data.get()->find(weightname) == NULL){
+    std::cout << "Can't find weight " << weightname << " in data set!" << std::endl;
+    return;
+  }
+  
+  
+  for (Int_t ievt = 0; ievt < data.numEntries(); ievt++) {
+    RooArgList row(*data.get(ievt));
+    Double_t xval = ((RooAbsReal*)row.find(varname))->getVal();
+    
+    Double_t p = ((RooAbsReal*)row.find(weightname))->getVal();
+    
+    Fill(xval,p);
+  }
+  
+  
+}
+
+
+
+//____________________________________________________________________
+void SPlot::FillSPlot(const RooAbsReal &x, RooAbsReal &nstar, RooDataSet data, const RooFitResult &fitRes, const RooArgList &pdfListTmp, const RooArgList &yieldsTmp, RooAbsPdf &totalPdf, Bool_t doErrors, const RooArgSet &projDeps) 
+{
+  // Alternate method to fill an SPlot for the variable x.  Better description of this method is needed.
+
+  Bool_t verbose = kTRUE;
+  if (verbose) {
+    std::cout << "yieldsTmp:" << std::endl;
+    yieldsTmp.Print("V");
+    std::cout << "pdfListTmp:" << std::endl;
+    pdfListTmp.Print();
+  }
+  
+  // Size of bins...
+  Double_t xmin = GetXaxis()->GetXmin();
+  Double_t xmax = GetXaxis()->GetXmax();
+  Double_t nbins = GetNbinsX();
+  Double_t binSize = (xmax - xmin)/nbins;
+
+  if (verbose) {
+    std::cout << "Bins: " << xmin << " to " << xmax << " with " << nbins << " bins." << std::endl;
+    std::cout << "binSize = " << binSize << std::endl;
+  }
+  
+  // Number of species in this fit.
+  Int_t nspec = yieldsTmp.getSize();
+
+  // The list of parameters (with their final fit values)
+  RooArgList finalPars = fitRes.floatParsFinal();
+
+  // Number of parameters in the fit result.
+  Int_t npars = finalPars.getSize();
+
+  RooArgList pdfList = *(RooArgList*)pdfListTmp.snapshot();
+  RooArgList yields = *(RooArgList*)yieldsTmp.snapshot(kFALSE);
+  //RooAbsPdf totalPdf = *(RooAbsPdf*)totalPdfTmp.Clone();
+  
+  if (verbose) {
+    std::cout << "Yields I will use in calculation:" << std::endl;
+    yields.Print("V");
+    std::cout << "pdfList:" << std::endl;
+    pdfList.Print();
+  }
+
+  // The list of variables to normalize over when calculating PDF values.
+  RooArgSet vars(*data.get());
+  vars.remove(projDeps, kTRUE, kTRUE);
+
+  // Make a TMatrixD to hold the covariance matrix.
+  TMatrixD covMatrix(npars, npars);
+  
+  // Loop over all the parameters to make the covariance matrix.
+  for (Int_t i = 0; i < npars; i++) {
+    for (Int_t j = 0; j < npars; j++) {
+      const RooRealVar *rowVar= (const RooRealVar*)finalPars.at(i);
+      const RooRealVar *colVar= (const RooRealVar*)finalPars.at(j);
+      assert(0 != rowVar && 0 != colVar);
+      covMatrix(i,j) = rowVar->getError()*colVar->getError()*fitRes.correlation(rowVar->GetName(),colVar->GetName());  
+    }
+  }
+  
+  // Get the inverse of the covariance matrix
+  // First check if it's singular
+  if (covMatrix.Determinant() == 0) {
+    std::cout << "SPlot Error: covariance matrix is singular;  I can't invert it!" << std::endl;
+    covMatrix.Print();
+    return;
+  }
+  TMatrixD covInv(TMatrixD::kInverted,covMatrix);
+
+  if (verbose) {
+    std::cout << "Covariance matrix:" << std::endl;
+    covMatrix.Print();
+    std::cout << "Inverse of covariance matrix:" << std::endl;
+    covInv.Print();
+  }
+  
+  // Make a matrix to hold V(i,j) inverse.
+  TMatrixD vinv(nspec, nspec);
+
+  // And fill it with the correct numbers...
+  Int_t istar(0);
+  Int_t vi = 0;
+  for (Int_t ci = 0; ci < npars; ci++) {
+    // If this parameter isn't a yield, move to the next row
+    if (yields.find(finalPars.at(ci)->GetName()) == 0) continue;
+
+    // If this parameter is the one of interest (nstar), then remember its index.
+    TString name = ((RooRealVar*)finalPars.at(ci))->GetName();
+    if (!name.CompareTo(nstar.GetName())) {
+      istar = vi;
+    }
+
+    Int_t vj = 0;
+    for (Int_t cj = 0; cj < npars; cj++) {
+
+      // If this parameter isn't a yield, move to the next column
+      if (!yields.contains(*finalPars.at(cj))) continue;
+
+      // This element's row and column correspond to yield parameters.  Put it in V inverse.
+      vinv(vi, vj) = covInv(ci, cj);
+      vj++;
+    }
+    vi++;
+  }
+
+  // Now invert V(i, j) inverse to get V(i, j)
+  if (vinv.Determinant() == 0) {
+    std::cout << "SPlot Error: Yield covariance matrix V inverse is singular and can't be inverted!" << std::endl;
+    vinv.Print();
+    return;
+  }
+  
+  TMatrixD v(TMatrixD::kInverted,vinv);
+
+  if (verbose) {
+    std::cout << "V inverse:" << std::endl;
+    vinv.Print();
+    std::cout << "V:" << std::endl;
+    v.Print();
+    
+    Double_t sum = 0;
+    for (Int_t j = 0; j < nspec; j++) {
+      sum += v(j,istar);
+    }
+    std::cout << "Sum of star column in V: " << sum << std::endl;
+    
+  }
+
+
+  
+  Double_t sum = 0;
+  //  Double_t sumtmp = 0;
+  
+  // This forces the error in a bin to be calculated as the sqrt of the sum of the squares of
+  // weights, as they should be.
+  if (doErrors) Sumw2();
+
+  totalPdf.attachDataSet(data);
+  for (Int_t ievt = 0; ievt < data.numEntries(); ievt++) {
+    
+    if (ievt % 100 == 0) std::cout << "Event: " << ievt << std::endl;
+    // Read this event and find the value of x for this event.
+    const RooArgSet *row = data.get(ievt);
+    Double_t xval = ((RooAbsReal*)row->find(x.GetName()))->getVal();
+    
+    // Loop over the species and calculate P.
+    Double_t numerator = 0;
+    Double_t denominator = 0;    
+    for (Int_t i = 0; i < nspec ; i++){
+
+      RooAbsPdf *pdf = (RooAbsPdf*)pdfList.at(i);
+      pdf->attachDataSet(data);
+      Double_t pdfval = pdf->getVal(&vars);
+      numerator += v(istar, i)*pdfval;
+      
+      //Double_t ni = ((RooAbsReal*)yields.at(i))->getVal();
+      //denominator += ni*pdfval;
+    }
+    denominator = totalPdf.getVal(&vars);
+
+    Double_t p = 1/nstar.getVal()*(numerator/denominator);
+    if (xval > xmin && xval < xmax) sum += p*nstar.getVal();
+    
+    Fill(xval, p*nstar.getVal());
+
+  }// end event loop
+
+  SetEntries(sum*Double_t(binSize));
+  if (verbose) std::cout << "Entries should be: " << sum*Double_t(binSize) << " (" << sum << " events)" << std::endl;
+  
+}
+
+//____________________________________________________________________
+void SPlot::FillSPlot(const RooAbsReal &x, RooAbsReal &nstar, RooDataSet data, const RooFitResult &fitRes, const RooArgList &pdfListTmp, const RooArgList &yieldsTmp, Bool_t doErrors, const RooArgSet &projDeps) 
+{
+  // Alternate method to fill an SPlot for the variable x.  Better description of this method is needed.
+
+  Bool_t verbose = kTRUE;
+  if (verbose) {
+    std::cout << "nstar: " << std::endl;
+    nstar.Print();
+    std::cout << "yieldsTmp:" << std::endl;
+    yieldsTmp.Print("V");
+    std::cout << "pdfListTmp:" << std::endl;
+    pdfListTmp.Print();
+  }
+  
+  // Size of bins...
+  Double_t xmin = GetXaxis()->GetXmin();
+  Double_t xmax = GetXaxis()->GetXmax();
+  Double_t nbins = GetNbinsX();
+  Double_t binSize = (xmax - xmin)/nbins;
+
+  if (verbose) {
+    std::cout << "Bins: " << xmin << " to " << xmax << " with " << nbins << " bins." << std::endl;
+    std::cout << "binSize = " << binSize << std::endl;
+  }
+  
+  // Number of species in this fit.
+  Int_t nspec = yieldsTmp.getSize();
+
+  // The list of parameters (with their final fit values)
+  RooArgList finalPars = fitRes.floatParsFinal();
+
+  // Number of parameters in the fit result.
+  Int_t npars = finalPars.getSize();
+
+  RooArgList pdfList = *(RooArgList*)pdfListTmp.snapshot();
+  RooArgList yields = *(RooArgList*)yieldsTmp.snapshot(kFALSE);
+
+  if (verbose) {
+    std::cout << "Yields I will use in calculation:" << std::endl;
+    yields.Print("V");
+    std::cout << "pdfList:" << std::endl;
+    pdfList.Print();
+  }
+
+  // The list of variables to normalize over when calculating PDF values.
+  RooArgSet vars(*data.get());
+  vars.remove(projDeps, kTRUE, kTRUE);
+
+  // Make a TMatrixD to hold the covariance matrix.
+  TMatrixD covMatrix(npars, npars);
+  
+  // Loop over all the parameters to make the covariance matrix.
+  for (Int_t i = 0; i < npars; i++) {
+    for (Int_t j = 0; j < npars; j++) {
+      const RooRealVar *rowVar= (const RooRealVar*)finalPars.at(i);
+      const RooRealVar *colVar= (const RooRealVar*)finalPars.at(j);
+      assert(0 != rowVar && 0 != colVar);
+      covMatrix(i,j) = rowVar->getError()*colVar->getError()*fitRes.correlation(rowVar->GetName(),colVar->GetName());  
+    }
+  }
+  
+  // Get the inverse of the covariance matrix
+  // First check if it's singular
+  if (covMatrix.Determinant() == 0) {
+    std::cout << "SPlot Error: covariance matrix is singular;  I can't invert it!" << std::endl;
+    covMatrix.Print();
+    return;
+  }
+  TMatrixD covInv(TMatrixD::kInverted,covMatrix);
+
+  if (verbose) {
+    std::cout << "Covariance matrix:" << std::endl;
+    covMatrix.Print();
+    std::cout << "Inverse of covariance matrix:" << std::endl;
+    covInv.Print();
+  }
+  
+  // Make a matrix to hold V(i,j) inverse.
+  TMatrixD vinv(nspec, nspec);
+
+  // And fill it with the correct numbers...
+  Int_t istar(0);
+  Int_t vi = 0;
+  for (Int_t ci = 0; ci < npars; ci++) {
+    // If this parameter isn't a yield, move to the next row
+    if (yields.find(finalPars.at(ci)->GetName()) == 0) continue;
+
+    // If this parameter is the one of interest (nstar), then remember its index.
+    TString name = ((RooRealVar*)finalPars.at(ci))->GetName();
+    if (!name.CompareTo(nstar.GetName())) {
+      istar = vi;
+    }
+
+    Int_t vj = 0;
+    for (Int_t cj = 0; cj < npars; cj++) {
+
+      // If this parameter isn't a yield, move to the next column
+      if (!yields.contains(*finalPars.at(cj))) continue;
+
+      // This element's row and column correspond to yield parameters.  Put it in V inverse.
+      vinv(vi, vj) = covInv(ci, cj);
+      vj++;
+    }
+    vi++;
+  }
+
+  // Now invert V(i, j) inverse to get V(i, j)
+  if (vinv.Determinant() == 0) {
+    std::cout << "SPlot Error: Yield covariance matrix V inverse is singular and can't be inverted!" << std::endl;
+    vinv.Print();
+    return;
+  }
+  
+  TMatrixD v(TMatrixD::kInverted,vinv);
+
+  if (verbose) {
+    std::cout << "V inverse:" << std::endl;
+    vinv.Print();
+    std::cout << "V:" << std::endl;
+    v.Print();
+    
+    Double_t sum = 0;
+    for (Int_t j = 0; j < nspec; j++) {
+      sum += v(j,istar);
+    }
+    std::cout << "Sum of star column in V: " << sum << std::endl;
+    
+  }
+
+
+  
+  Double_t sum = 0;
+  Double_t sumtmp = 0;
+  
+  // This forces the error in a bin to be calculated as the sqrt of the sum of the squares of
+  // weights, as they should be.
+  if (doErrors) Sumw2();
+
+  for (Int_t i = 0; i < nspec; i++) {
+    RooAbsPdf *pdf = (RooAbsPdf*)pdfList.at(i);
+    pdf->attachDataSet(data);
+  }
+
+  for (Int_t ievt = 0; ievt < data.numEntries(); ievt++) {
+    
+    if (ievt % 100 == 0) std::cout << ".";
+    // Read this event and find the value of x for this event.
+    const RooArgSet *row = data.get(ievt);
+    Double_t xval = ((RooAbsReal*)row->find(x.GetName()))->getVal();
+    
+    // Loop over the species and calculate P.
+    Double_t numerator = 0;
+    Double_t denominator = 0;    
+    for (Int_t i = 0; i < nspec ; i++){
+
+      RooAbsPdf *pdf = (RooAbsPdf*)pdfList.at(i);
+      //pdf->attachDataSet(data);
+      Double_t pdfval = pdf->getVal(&vars);
+      numerator += v(istar, i)*pdfval;
+      
+      Double_t ni = ((RooAbsReal*)yields.at(i))->getVal();
+      denominator += ni*pdfval;
+    }
+    
+    Double_t p = 1/nstar.getVal()*(numerator/denominator);
+    sumtmp += ((RooAbsPdf*)pdfList.at(istar))->getVal(&vars)/denominator;
+
+    //if (xval > xmin && xval < xmax)
+      sum += p*nstar.getVal();
+    
+    Fill(xval, p*nstar.getVal());
+
+  }// end event loop
+
+  SetEntries(sum*Double_t(binSize));
+  
+  std::cout << std::endl;
+  if (verbose) std::cout << "Entries should be: " << sum*Double_t(binSize) << " (" << sum << " events)" << std::endl;
+  if (verbose) std::cout << "Sum of likelihood ratios for nstar: " << sumtmp << std::endl;
+  
+}
+
+
+//____________________________________________________________________
+void SPlot::FillSPlot(const RooAbsReal &x, RooAbsReal &nstar, RooDataSet data, const RooFitResult &fitRes, RooAbsPdf &totalPdf, RooArgList &yields, Bool_t doErrors, const RooArgSet &projDeps) 
+{
+  // Alternate method to fill an SPlot for the variable x.  Better description of this method is needed.
+
+  Bool_t verbose = kTRUE;
+  if (verbose) {
+    //std::cout << "yieldsTmp:" << std::endl;
+    //yieldsTmp.Print("V");
+    //std::cout << "pdfListTmp:" << std::endl;
+    //pdfListTmp.Print();
+  }
+  
+  // Size of bins...
+  Double_t xmin = GetXaxis()->GetXmin();
+  Double_t xmax = GetXaxis()->GetXmax();
+  Double_t nbins = GetNbinsX();
+  Double_t binSize = (xmax - xmin)/nbins;
+
+  if (verbose) {
+    std::cout << "Bins: " << xmin << " to " << xmax << " with " << nbins << " bins." << std::endl;
+    std::cout << "binSize = " << binSize << std::endl;
+  }
+  
+  // Number of species in this fit.
+  Int_t nspec = yields.getSize();
+
+  // The list of parameters (with their final fit values)
+  RooArgList finalPars = fitRes.floatParsFinal();
+
+  // Number of parameters in the fit result.
+  Int_t npars = finalPars.getSize();
+
+  //RooArgList pdfList = *(RooArgList*)pdfListTmp.snapshot();
+  //RooArgList yields = *(RooArgList*)yieldsTmp.snapshot(kFALSE);
+  //RooAbsPdf totalPdf = *(RooAbsPdf*)totalPdfTmp.Clone();
+  
+  if (verbose) {
+    std::cout << "Yields I will use in calculation:" << std::endl;
+    yields.Print("V");
+    //std::cout << "pdfList:" << std::endl;
+    //pdfList.Print();
+  }
+
+  // The list of variables to normalize over when calculating PDF values.
+  RooArgSet vars(*data.get());
+  vars.remove(projDeps, kTRUE, kTRUE);
+
+  // Make a TMatrixD to hold the covariance matrix.
+  TMatrixD covMatrix(npars, npars);
+  
+  // Loop over all the parameters to make the covariance matrix.
+  for (Int_t i = 0; i < npars; i++) {
+    for (Int_t j = 0; j < npars; j++) {
+      const RooRealVar *rowVar= (const RooRealVar*)finalPars.at(i);
+      const RooRealVar *colVar= (const RooRealVar*)finalPars.at(j);
+      assert(0 != rowVar && 0 != colVar);
+      covMatrix(i,j) = rowVar->getError()*colVar->getError()*fitRes.correlation(rowVar->GetName(),colVar->GetName());  
+    }
+  }
+  
+  // Get the inverse of the covariance matrix
+  // First check if it's singular
+  if (covMatrix.Determinant() == 0) {
+    std::cout << "SPlot Error: covariance matrix is singular;  I can't invert it!" << std::endl;
+    covMatrix.Print();
+    return;
+  }
+  TMatrixD covInv(TMatrixD::kInverted,covMatrix);
+
+  if (verbose) {
+    std::cout << "Covariance matrix:" << std::endl;
+    covMatrix.Print();
+    std::cout << "Inverse of covariance matrix:" << std::endl;
+    covInv.Print();
+  }
+  
+  // Make a matrix to hold V(i,j) inverse.
+  TMatrixD vinv(nspec, nspec);
+
+  // And fill it with the correct numbers...
+  Int_t istar(0);
+  Int_t vi = 0;
+  for (Int_t ci = 0; ci < npars; ci++) {
+    // If this parameter isn't a yield, move to the next row
+    if (yields.find(finalPars.at(ci)->GetName()) == 0) continue;
+
+    // If this parameter is the one of interest (nstar), then remember its index.
+    TString name = ((RooRealVar*)finalPars.at(ci))->GetName();
+    if (!name.CompareTo(nstar.GetName())) {
+      istar = vi;
+    }
+
+    Int_t vj = 0;
+    for (Int_t cj = 0; cj < npars; cj++) {
+
+      // If this parameter isn't a yield, move to the next column
+      if (!yields.contains(*finalPars.at(cj))) continue;
+
+      // This element's row and column correspond to yield parameters.  Put it in V inverse.
+      vinv(vi, vj) = covInv(ci, cj);
+      vj++;
+    }
+    vi++;
+  }
+
+  // Now invert V(i, j) inverse to get V(i, j)
+  if (vinv.Determinant() == 0) {
+    std::cout << "SPlot Error: Yield covariance matrix V inverse is singular and can't be inverted!" << std::endl;
+    vinv.Print();
+    return;
+  }
+  
+  TMatrixD v(TMatrixD::kInverted,vinv);
+
+  if (verbose) {
+    std::cout << "V inverse:" << std::endl;
+    vinv.Print();
+    std::cout << "V:" << std::endl;
+    v.Print();
+    
+    Double_t sum = 0;
+    for (Int_t j = 0; j < nspec; j++) {
+      sum += v(j,istar);
+    }
+    std::cout << "Sum of star column in V: " << sum << std::endl;
+    
+  }
+
+
+  
+  Double_t sum = 0;
+  //Double_t sumtmp = 0;
+  
+  // This forces the error in a bin to be calculated as the sqrt of the sum of the squares of
+  // weights, as they should be.
+  if (doErrors) Sumw2();
+
+  totalPdf.attachDataSet(data);
+  for (Int_t ievt = 0; ievt < data.numEntries(); ievt++) {
+    
+    if (ievt % 100 == 0) std::cout << "Event: " << ievt << std::endl;
+    // Read this event and find the value of x for this event.
+    const RooArgSet *row = data.get(ievt);
+    Double_t xval = ((RooAbsReal*)row->find(x.GetName()))->getVal();
+    
+    // Loop over the species and calculate P.
+    Double_t numerator = 0;
+    Double_t denominator = 0;    
+    for (Int_t i = 0; i < nspec ; i++){
+
+      //RooAbsPdf *pdf = (RooAbsPdf*)pdfList.at(i);
+      //pdf->attachDataSet(data);
+      //Double_t pdfval = pdf->getVal(&vars);
+      Double_t pdfval = GetComponentValue(totalPdf, yields, i, vars);
+      numerator += v(istar, i)*pdfval;
+      
+      //Double_t ni = ((RooAbsReal*)yields.at(i))->getVal();
+      //denominator += ni*pdfval;
+    }
+    denominator = totalPdf.getVal(&vars);
+
+    Double_t p = 1/nstar.getVal()*(numerator/denominator);
+    if (xval > xmin && xval < xmax) sum += p*nstar.getVal();
+    
+    Fill(xval, p*nstar.getVal());
+
+  }// end event loop
+
+  SetEntries(sum*Double_t(binSize));
+  if (verbose) std::cout << "Entries should be: " << sum*Double_t(binSize) << " (" << sum << " events)" << std::endl;
+  
+}
+
+
+//____________________________________________________________________
+Double_t SPlot::GetComponentValue(RooAbsPdf &pdf, RooArgList &yieldsTmp, Int_t igood, RooArgSet &normSet) 
+{
+  // Alternate method to fill an SPlot for the variable x.  Better description of this method is needed.
+
+  Int_t i=0;
+  Int_t nspec = yieldsTmp.getSize();
+  std::vector<Double_t> yields(nspec);
+  //  std::cout << "Before: " << pdf.getVal(&normSet) << std::endl;
+  for (i=0; i < nspec; i++) {
+    yields[i] = ((RooRealVar*)yieldsTmp.at(i))->getVal();
+    ((RooRealVar*)yieldsTmp.at(i))->setVal(0);
+  }
+  
+  ((RooRealVar*)yieldsTmp.at(igood))->setVal(1);
+  
+  Double_t result = pdf.getVal(&normSet);
+  //  std::cout << "During: " << result << std::endl;
+
+  for (i=0; i < nspec; i++) {
+    ((RooRealVar*)yieldsTmp.at(i))->setVal(yields[i]);
+  }
+  //  std::cout << "After: " << pdf.getVal(&normSet) << std::endl;
+  return result;
+  
+}
+
+
+
+
+
-- 
GitLab