diff --git a/BuildFile.xml b/BuildFile.xml
index 65359c41263d9..587ccbbd97cf9 100644
--- a/BuildFile.xml
+++ b/BuildFile.xml
@@ -4,6 +4,7 @@
+
diff --git a/bin/combine.cpp b/bin/combine.cpp
index 587374a2c65fd..6fc1fb0efe0ff 100644
--- a/bin/combine.cpp
+++ b/bin/combine.cpp
@@ -237,8 +237,13 @@ int main(int argc, char **argv) {
if (vm.count("X-fpeMask")) gSystem->SetFPEMask(vm["X-fpeMask"].as());
+ // CMSDAS Defaults (you can turn off with --X-rtd =0
+ runtimedef::set("OPTIMIZE_BOUNDS", 1);
+ runtimedef::set("ADDNLL_RECURSIVE", 1);
+ runtimedef::set("ADDNLL_GAUSSNLL", 1);
+ runtimedef::set("ADDNLL_HISTNLL", 1);
+ runtimedef::set("TMCSO_AdaptivePseudoAsimov", 1);
- // if you have libraries, it's time to load them now
for (vector::const_iterator rtdp = runtimeDefines.begin(), endrtdp = runtimeDefines.end(); rtdp != endrtdp; ++rtdp) {
std::string::size_type idx = rtdp->find('=');
if (idx == std::string::npos) {
diff --git a/interface/CachingNLL.h b/interface/CachingNLL.h
index b8ba291c6f480..60e6c71870da0 100644
--- a/interface/CachingNLL.h
+++ b/interface/CachingNLL.h
@@ -13,6 +13,11 @@
#include
#include
#include
+#include
+#include "../interface/SimpleGaussianConstraint.h"
+#include
+
+class RooMultiPdf;
// Part zero: ArgSet checker
namespace cacheutils {
@@ -55,20 +60,38 @@ class CachingPdf {
public:
CachingPdf(RooAbsReal *pdf, const RooArgSet *obs) ;
CachingPdf(const CachingPdf &other) ;
- ~CachingPdf() ;
+ virtual ~CachingPdf() ;
const std::vector & eval(const RooAbsData &data) ;
const RooAbsReal *pdf() const { return pdf_; }
void setDataDirty() { lastData_ = 0; }
- private:
+ protected:
const RooArgSet *obs_;
RooAbsReal *pdfOriginal_;
RooArgSet pdfPieces_;
RooAbsReal *pdf_;
const RooAbsData *lastData_;
ValuesCache cache_;
- void realFill_(const RooAbsData &data, std::vector &values) ;
+ std::vector nonZeroW_;
+ unsigned int nonZeroWEntries_;
+ virtual void newData_(const RooAbsData &data) ;
+ virtual void realFill_(const RooAbsData &data, std::vector &values) ;
};
+template
+class OptimizedCachingPdfT : public CachingPdf {
+ public:
+ OptimizedCachingPdfT(RooAbsReal *pdf, const RooArgSet *obs) :
+ CachingPdf(pdf,obs), vpdf_(0) {}
+ OptimizedCachingPdfT(const OptimizedCachingPdfT &other) :
+ CachingPdf(other), vpdf_(0) {}
+ virtual ~OptimizedCachingPdfT() { delete vpdf_; }
+ protected:
+ virtual void realFill_(const RooAbsData &data, std::vector &values) ;
+ virtual void newData_(const RooAbsData &data) ;
+ VPdfT *vpdf_;
+};
+
+
class CachingAddNLL : public RooAbsReal {
public:
CachingAddNLL(const char *name, const char *title, RooAbsPdf *pdf, RooAbsData *data) ;
@@ -88,16 +111,20 @@ class CachingAddNLL : public RooAbsReal {
RooSetProxy & params() { return params_; }
private:
void setup_();
+ void addPdfs_(RooAddPdf *addpdf, bool recursive, const RooArgList & basecoeffs) ;
RooAbsPdf *pdf_;
RooSetProxy params_;
const RooAbsData *data_;
std::vector weights_;
double sumWeights_;
mutable std::vector coeffs_;
- mutable std::vector pdfs_;
+ mutable boost::ptr_vector pdfs_;
+ mutable boost::ptr_vector prods_;
mutable std::vector integrals_;
+ mutable std::vector > multiPdfs_;
mutable std::vector partialSum_;
- mutable bool isRooRealSum_;
+ mutable std::vector workingArea_;
+ mutable bool isRooRealSum_, fastExit_;
double zeroPoint_;
};
@@ -117,18 +144,9 @@ class CachingSimNLL : public RooAbsReal {
static void setNoDeepLogEvalError(bool noDeep) { noDeepLEE_ = noDeep; }
void setZeroPoint() ;
void clearZeroPoint() ;
+ static void forceUnoptimizedConstraints() { optimizeContraints_ = false; }
friend class CachingAddNLL;
private:
- class SimpleGaussianConstraint : public RooGaussian {
- public:
- SimpleGaussianConstraint(const RooGaussian &g) : RooGaussian(g, "") {}
- double getLogValFast() const {
- Double_t arg = x - mean;
- Double_t sig = sigma ;
- return -0.5*arg*arg/(sig*sig);
- }
- };
-
void setup_();
RooSimultaneous *pdfOriginal_;
const RooAbsData *dataOriginal_;
@@ -138,11 +156,13 @@ class CachingSimNLL : public RooAbsReal {
std::auto_ptr factorizedPdf_;
std::vector constrainPdfs_;
std::vector constrainPdfsFast_;
+ std::vector constrainPdfsFastOwned_;
std::vector pdfs_;
std::auto_ptr dataSets_;
std::vector datasets_;
static bool noDeepLEE_;
static bool hasError_;
+ static bool optimizeContraints_;
std::vector constrainZeroPoints_;
std::vector constrainZeroPointsFast_;
};
diff --git a/interface/Combine.h b/interface/Combine.h
index 001d67d6da316..3807aa3f74e17 100644
--- a/interface/Combine.h
+++ b/interface/Combine.h
@@ -71,6 +71,7 @@ class Combine {
bool makeTempDir_;
bool rebuildSimPdf_;
bool optSimPdf_;
+ bool noMCbonly_;
static TTree *tree_;
};
diff --git a/interface/FastTemplate.h b/interface/FastTemplate.h
index de2fe6358aa37..c49aab1ab9984 100644
--- a/interface/FastTemplate.h
+++ b/interface/FastTemplate.h
@@ -4,31 +4,36 @@
#include
#include
#include
+#include
class FastTemplate {
public:
typedef double T;
- FastTemplate() : size_(0), values_(0) {}
- FastTemplate(unsigned int size) : size_(size), values_(new T[size_]) {}
- FastTemplate(const FastTemplate &other) : size_(other.size_), values_(size_ ? new T[size_] : 0) { if (size_) CopyValues(other); }
- FastTemplate(const TH1 &other) : size_(other.GetNbinsX()), values_(new T[size_]) { CopyValues(other); }
- FastTemplate(const TH2 &other) : size_(other.GetNbinsX()*other.GetNbinsY()), values_(new T[size_]) { CopyValues(other); }
+ typedef std::vector AT;
+ FastTemplate() : size_(0), values_() {}
+ FastTemplate(unsigned int size) : size_(size), values_(size_) {}
+ FastTemplate(const FastTemplate &other) : size_(other.size()), values_(other.values_) {}
+ FastTemplate(const TH1 &other) : size_(other.GetNbinsX()), values_(size_) { CopyValues(other); }
+ FastTemplate(const TH2 &other) : size_(other.GetNbinsX()*other.GetNbinsY()), values_(size_) { CopyValues(other); }
FastTemplate & operator=(const FastTemplate &other) {
- if (size_ != other.size_) {
- delete [] values_; size_ = other.size_; values_ = new T[size_];
+ if (&other != this) {
+ size_ = other.size_;
+ values_ = other.values_;
}
- CopyValues(other); return *this;
+ return *this;
}
FastTemplate & operator=(const TH1 &other) {
- if (size_ != unsigned(other.GetNbinsX())) {
- delete [] values_; size_ = other.GetNbinsX(); values_ = new T[size_];
+ if (size() != unsigned(other.GetNbinsX())) {
+ size_ = other.GetNbinsX();
+ values_.resize(size_);
}
CopyValues(other); return *this;
}
- ~FastTemplate() { delete [] values_; }
+ ~FastTemplate() { }
void Resize(unsigned int newsize) {
- if (newsize != size_) {
- delete [] values_; size_ = newsize; values_ = new T[size_];
+ if (newsize != size()) {
+ size_ = newsize;
+ values_.resize(size_);
}
}
T Integral() const ;
@@ -39,6 +44,10 @@ class FastTemplate {
void CopyValues(const TH2 &other) ;
T & operator[](unsigned int i) { return values_[i]; }
const T & operator[](unsigned int i) const { return values_[i]; }
+ /// return the full size of the template
+ const unsigned int fullsize() const { return values_.size(); }
+ /// return the active size of the template (can be less than the full size if the SetActiveSize
+ /// has been used to inform the code that only the first N bins are not empty)
const unsigned int size() const { return size_; }
/// *this = log(*this)
@@ -54,33 +63,39 @@ class FastTemplate {
/// Does this += x * (diff + (sum)*y)
void Meld(const FastTemplate & diff, const FastTemplate & sum, T x, T y) ;
/// protect from underflows (*this = max(*this, minimum));
- void CropUnderflows(T minimum=1e-9);
+ void CropUnderflows(T minimum=1e-9, bool activebinsonly=true);
+
+ /// Tell the code that only the first N bins of the template are non-empty,
+ /// and so that only those have to be considered when doing operations
+ void SetActiveSize(unsigned int size) { size_ = size; }
void Dump() const ;
protected:
- unsigned int size_;
- T *values_;
+ unsigned int size_;
+ AT values_;
};
class FastHisto : public FastTemplate {
public:
- FastHisto() : FastTemplate(), binEdges_(0), binWidths_(0) {}
+ FastHisto() : FastTemplate(), binEdges_(), binWidths_() {}
FastHisto(const TH1 &hist) ;
FastHisto(const FastHisto &other) ;
FastHisto & operator=(const FastHisto &other) {
- if (size_ != other.size_) {
- FastHisto fh(other);
- swap(fh);
+ if (size() != other.size()) {
+ size_ = other.size_;
+ values_ = other.values_;
+ binWidths_ = other.binWidths_;
+ binEdges_ = other.binEdges_;
} else CopyValues(other);
return *this;
}
FastHisto & operator=(const TH1 &other) {
- if (size_ != unsigned(other.GetNbinsX())) {
+ if (size() != unsigned(other.GetNbinsX())) {
FastHisto fh(other);
swap(fh);
} else CopyValues(other);
- CopyValues(other); return *this;
+ return *this;
}
- ~FastHisto() { delete [] binEdges_; delete [] binWidths_; }
+ ~FastHisto() { }
void swap(FastHisto &other) {
std::swap(size_, other.size_);
std::swap(values_, other.values_);
@@ -88,6 +103,8 @@ class FastHisto : public FastTemplate {
std::swap(binEdges_, other.binEdges_);
}
T GetAt(const T &x) const ;
+ int FindBin(const T &x) const ;
+ const T & GetBinContent(int bin) const { return values_[bin]; }
T IntegralWidth() const ;
void Normalize() {
T sum = IntegralWidth();
@@ -96,27 +113,32 @@ class FastHisto : public FastTemplate {
void Dump() const ;
private:
- T *binEdges_;
- T *binWidths_;
+ AT binEdges_;
+ AT binWidths_;
};
class FastHisto2D : public FastTemplate {
public:
- FastHisto2D() : FastTemplate(), binX_(0), binY_(0), binEdgesX_(0), binEdgesY_(0), binWidths_(0) {}
+ FastHisto2D() : FastTemplate(), binX_(0), binY_(0), binEdgesX_(), binEdgesY_(), binWidths_() {}
FastHisto2D(const TH2 &hist, bool normXonly=false) ;
FastHisto2D(const FastHisto2D &other) ;
FastHisto2D & operator=(const FastHisto2D &other) {
- if (binX_ != other.binY_ || binY_ != other.binY_) {
- FastHisto2D fh(other);
- swap(fh);
+ if (binX() != other.binX() || binY() != other.binY()) {
+ size_ = other.size_;
+ values_ = other.values_;
+ binWidths_ = other.binWidths_;
+ binEdgesX_ = other.binEdgesX_;
+ binEdgesY_ = other.binEdgesY_;
+ binX_ = other.binX_;
+ binY_ = other.binY_;
} else CopyValues(other);
return *this;
}
- ~FastHisto2D() { delete [] binEdgesX_; delete [] binEdgesY_; delete [] binWidths_; }
+ ~FastHisto2D() { }
void swap(FastHisto2D &other) {
+ std::swap(size_, other.size_);
std::swap(binX_, other.binX_);
std::swap(binY_, other.binY_);
- std::swap(size_, other.size_);
std::swap(values_, other.values_);
std::swap(binWidths_, other.binWidths_);
std::swap(binEdgesX_, other.binEdgesX_);
@@ -124,6 +146,8 @@ class FastHisto2D : public FastTemplate {
}
T GetAt(const T &x, const T &y) const ;
T IntegralWidth() const ;
+ unsigned int binX() const { return binX_; }
+ unsigned int binY() const { return binY_; }
void Normalize() {
T sum = IntegralWidth();
if (sum > 0) Scale(1.0f/sum);
@@ -134,9 +158,9 @@ class FastHisto2D : public FastTemplate {
void Dump() const ;
private:
unsigned int binX_, binY_;
- T *binEdgesX_;
- T *binEdgesY_;
- T *binWidths_;
+ AT binEdgesX_;
+ AT binEdgesY_;
+ AT binWidths_;
};
diff --git a/interface/FitterAlgoBase.h b/interface/FitterAlgoBase.h
index 1e2842c261f0d..7a673ac160e4b 100644
--- a/interface/FitterAlgoBase.h
+++ b/interface/FitterAlgoBase.h
@@ -56,6 +56,9 @@ class FitterAlgoBase : public LimitAlgo {
RooFitResult *doFit(RooAbsPdf &pdf, RooAbsData &data, const RooArgList &rs, const RooCmdArg &constrain, bool doHesse=true, int ndim=1,bool reuseNLL=false, bool saveFitResult=true) ;
double findCrossing(CascadeMinimizer &minim, RooAbsReal &nll, RooRealVar &r, double level, double rStart, double rBound) ;
double findCrossingNew(CascadeMinimizer &minim, RooAbsReal &nll, RooRealVar &r, double level, double rStart, double rBound) ;
+
+ void optimizeBounds(const RooWorkspace *w, const RooStats::ModelConfig *mc) ;
+ void restoreBounds(const RooWorkspace *w, const RooStats::ModelConfig *mc) ;
};
diff --git a/interface/RooMinimizerOpt.h b/interface/RooMinimizerOpt.h
index 9cc2789b0dd63..441f15c550479 100644
--- a/interface/RooMinimizerOpt.h
+++ b/interface/RooMinimizerOpt.h
@@ -13,15 +13,42 @@ class RooMinimizerOpt : public RooMinimizer {
public:
RooMinimizerOpt(RooAbsReal& function) ;
Double_t edm();
+ Int_t minimize(const char* type, const char* alg=0) ;
+ Int_t improve() ;
+ Int_t migrad() ;
+ Int_t hesse() ;
+ Int_t minos() ;
+ Int_t minos(const RooArgSet& minosParamList) ;
+
};
class RooMinimizerFcnOpt : public RooMinimizerFcn {
public:
RooMinimizerFcnOpt(RooAbsReal *funct, RooMinimizer *context, bool verbose = false);
+ RooMinimizerFcnOpt(const RooMinimizerFcnOpt &other) ;
virtual ROOT::Math::IBaseFunctionMultiDim* Clone() const;
+ Bool_t Synchronize(std::vector& parameters, Bool_t optConst, Bool_t verbose);
+ void initStdVects() const ;
protected:
virtual double DoEval(const double * x) const;
mutable std::vector _vars;
+ mutable std::vector _vals;
+ mutable std::vector _hasOptimzedBounds;
+ struct OptBound {
+ double softMin, softMax, hardMin, hardMax;
+ double transform(double x) const {
+ if (x < softMin) {
+ double dx = softMin-x; // > 0
+ return hardMin + ( (softMin-hardMin) + dx ) * std::exp ( -2*dx/(softMin-hardMin) );
+ } else if (x > softMax) {
+ double dx = x-softMax;
+ return hardMax - ( (hardMax-softMax) + dx ) * std::exp ( -2*dx/(hardMax-softMax) );
+ } else {
+ return x;
+ }
+ }
+ };
+ mutable std::vector _optimzedBounds;
};
#endif
diff --git a/interface/SimpleGaussianConstraint.h b/interface/SimpleGaussianConstraint.h
new file mode 100644
index 0000000000000..a751232af481d
--- /dev/null
+++ b/interface/SimpleGaussianConstraint.h
@@ -0,0 +1,37 @@
+#ifndef SimpleGaussianConstraint_h
+#define SimpleGaussianConstraint_h
+
+#include
+
+class SimpleGaussianConstraint : public RooGaussian {
+ public:
+ SimpleGaussianConstraint() {} ;
+ SimpleGaussianConstraint(const char *name, const char *title,
+ RooAbsReal& _x, RooAbsReal& _mean, RooAbsReal& _sigma):
+ RooGaussian(name,title,_x,_mean,_sigma) { init(); }
+ SimpleGaussianConstraint(const SimpleGaussianConstraint& other, const char* name=0) :
+ RooGaussian(other, name) { init(); }
+ SimpleGaussianConstraint(const RooGaussian &g) : RooGaussian(g, "") { init(); }
+
+ virtual TObject* clone(const char* newname) const { return new SimpleGaussianConstraint(*this,newname); }
+ inline virtual ~SimpleGaussianConstraint() { }
+
+ double getLogValFast() const {
+ if (_valueDirty) {
+ Double_t arg = x - mean;
+ //Double_t sig = sigma ;
+ //return -0.5*arg*arg/(sig*sig);
+ _value = scale_*arg*arg;
+ _valueDirty = false;
+ }
+ return _value;
+ }
+
+ private:
+ double scale_;
+ void init() ;
+
+ ClassDef(SimpleGaussianConstraint,1) // Gaussian PDF with fast log
+};
+
+#endif
diff --git a/interface/VectorizedGaussian.h b/interface/VectorizedGaussian.h
new file mode 100644
index 0000000000000..b364c36ad9bbd
--- /dev/null
+++ b/interface/VectorizedGaussian.h
@@ -0,0 +1,27 @@
+#ifndef VectorizedGaussian_h
+#define VectorizedGaussian_h
+
+#include
+#include
+#include
+
+class VectorizedGaussian {
+ class Worker : public RooGaussian {
+ public:
+ Worker(const RooGaussian &g) : RooGaussian(g, "") {}
+ const RooAbsReal & xvar() const { return x.arg(); }
+ const RooAbsReal & meanvar() const { return mean.arg(); }
+ const RooAbsReal & sigvar() const { return sigma.arg(); }
+ };
+ public:
+ VectorizedGaussian(const RooGaussian &gaus, const RooAbsData &data) ;
+ void fill(std::vector &out) const ;
+ private:
+ const RooRealVar * x_;
+ const RooAbsReal * mean_;
+ const RooAbsReal * sigma_;
+ std::vector xvals_;
+ mutable std::vector work_, work2_;
+};
+
+#endif
diff --git a/interface/VerticalInterpHistPdf.h b/interface/VerticalInterpHistPdf.h
index cbabccbe9a4f5..1a6001915d6fb 100644
--- a/interface/VerticalInterpHistPdf.h
+++ b/interface/VerticalInterpHistPdf.h
@@ -12,10 +12,10 @@
#include "../interface/FastTemplate.h"
#include
-#define FastVerticalInterpHistPdf_CopyConstructor
-#define FastVerticalInterpHistPdf_Serializable
-
class FastVerticalInterpHistPdf;
+class FastVerticalInterpHistPdf2Base;
+class FastVerticalInterpHistPdf2;
+class FastVerticalInterpHistPdf2D2;
class VerticalInterpHistPdf : public RooAbsPdf {
public:
@@ -85,6 +85,8 @@ class FastVerticalInterpHistPdfBase : public RooAbsPdf {
/// Must be public, for serialization
struct Morph { FastTemplate sum; FastTemplate diff; };
+
+ friend class FastVerticalInterpHistPdf2Base;
protected:
RooRealProxy _x;
RooListProxy _funcList ; // List of component FUNCs
@@ -122,6 +124,7 @@ class FastVerticalInterpHistPdfBase : public RooAbsPdf {
};
+struct FastVerticalInterpHistPdfV;
class FastVerticalInterpHistPdf : public FastVerticalInterpHistPdfBase {
public:
@@ -133,11 +136,7 @@ class FastVerticalInterpHistPdf : public FastVerticalInterpHistPdfBase {
FastVerticalInterpHistPdf(const FastVerticalInterpHistPdf& other, const char* name=0) :
FastVerticalInterpHistPdfBase(other, name),
_x("x",this,other._x),
-#ifdef FastVerticalInterpHistPdf_CopyConstructor
_cache(other._cache), _cacheNominal(other._cacheNominal), _cacheNominalLog(other._cacheNominalLog) {}
-#else
- _cache(), _cacheNominal(), _cacheNominalLog() {}
-#endif
virtual TObject* clone(const char* newname) const { return new FastVerticalInterpHistPdf(*this,newname) ; }
virtual ~FastVerticalInterpHistPdf() {}
@@ -145,6 +144,8 @@ class FastVerticalInterpHistPdf : public FastVerticalInterpHistPdfBase {
Bool_t hasCache() const { return _cache.size() > 0; }
Bool_t isCacheReady() const { return _cache.size() > 0 && _init; }
+ friend class FastVerticalInterpHistPdfV;
+ friend class FastVerticalInterpHistPdf2;
protected:
RooRealProxy _x;
@@ -164,6 +165,21 @@ class FastVerticalInterpHistPdf : public FastVerticalInterpHistPdfBase {
ClassDef(FastVerticalInterpHistPdf,1) //
};
+class FastVerticalInterpHistPdfV {
+ public:
+ FastVerticalInterpHistPdfV(const FastVerticalInterpHistPdf &, const RooAbsData &data) ;
+ void fill(std::vector &out) const ;
+ private:
+ const FastVerticalInterpHistPdf & hpdf_;
+ int begin_, end_, nbins_;
+ struct Block {
+ int index, begin, end;
+ Block(int i, int begin_, int end_) : index(i), begin(begin_), end(end_) {}
+ };
+ std::vector blocks_;
+ std::vector bins_;
+};
+
class FastVerticalInterpHistPdf2D : public FastVerticalInterpHistPdfBase {
public:
@@ -179,21 +195,20 @@ class FastVerticalInterpHistPdf2D : public FastVerticalInterpHistPdfBase {
FastVerticalInterpHistPdf2D(const FastVerticalInterpHistPdf2D& other, const char* name=0) :
FastVerticalInterpHistPdfBase(other, name),
_x("x",this,other._x), _y("y",this,other._y), _conditional(other._conditional),
-#ifdef FastVerticalInterpHistPdf_CopyConstructor
_cache(other._cache), _cacheNominal(other._cacheNominal), _cacheNominalLog(other._cacheNominalLog) {}
-#else
- _cache(), _cacheNominal(), _cacheNominalLog() {}
-#endif
virtual TObject* clone(const char* newname) const { return new FastVerticalInterpHistPdf2D(*this,newname) ; }
virtual ~FastVerticalInterpHistPdf2D() {}
- Double_t evaluate() const ;
-
- Bool_t selfNormalized() const { return kTRUE; }
+ const RooRealVar & x() const { return dynamic_cast(_x.arg()); }
+ const RooRealVar & y() const { return dynamic_cast(_y.arg()); }
Bool_t conditional() const { return _conditional; }
+ Double_t evaluate() const ;
+
Bool_t hasCache() const { return _cache.size() > 0; }
Bool_t isCacheReady() const { return _cache.size() > 0 && _init; }
+
+ friend class FastVerticalInterpHistPdf2D2;
protected:
RooRealProxy _x, _y;
bool _conditional;
@@ -215,6 +230,158 @@ class FastVerticalInterpHistPdf2D : public FastVerticalInterpHistPdfBase {
};
+class FastVerticalInterpHistPdf2Base : public RooAbsPdf {
+public:
+
+ FastVerticalInterpHistPdf2Base() ;
+ FastVerticalInterpHistPdf2Base(const char *name, const char *title, const RooArgSet &obs, const TList & funcList, const RooArgList& coefList, Double_t smoothRegion=1., Int_t smoothAlgo=1) ;
+ FastVerticalInterpHistPdf2Base(const FastVerticalInterpHistPdf2Base& other, const char* name=0) ;
+ explicit FastVerticalInterpHistPdf2Base(const FastVerticalInterpHistPdfBase& other, const char* name=0) ;
+ virtual TObject* clone(const char* newname) const = 0;
+ virtual ~FastVerticalInterpHistPdf2Base() ;
+
+ Bool_t selfNormalized() const { return kTRUE; }
+
+ Double_t evaluate() const = 0;
+
+ const RooArgList& coefList() const { return _coefList ; }
+
+ virtual void setActiveBins(unsigned int bins) {}
+
+ /// Must be public, for serialization
+ typedef FastVerticalInterpHistPdfBase::Morph Morph;
+protected:
+ RooListProxy _coefList ; // List of coefficients
+ Double_t _smoothRegion;
+ Int_t _smoothAlgo;
+
+ // set to true after _morphParams and _sentry are initialized
+ mutable bool _initBase; //! not to be serialized
+
+ // to check if parameters change
+ mutable SimpleCacheSentry _sentry; //! not to be serialized
+
+ // For additive morphing, histograms of (fUp-f0)+(fDown-f0) and (fUp-f0)-(fDown-f0)
+ // For multiplicative morphing, log(fUp/f0)+log(fDown/f0), log(fUp/f0)-log(fDown/f0)
+ // NOTE: it's the responsibility of the daughter to make sure these are initialized!!!
+ std::vector _morphs;
+
+ // Coefficients of the list in _coefList, already dynamic_cast'ed and in a vector
+ mutable std::vector _morphParams; //! not to be serialized
+
+ // Prepare morphing data for a triplet of templates
+ void initMorph(Morph &out, const FastTemplate &nominal, FastTemplate &lo, FastTemplate &hi) const;
+
+ // Do the vertical morphing from nominal value and morphs into cache.
+ // Do not normalize yet, as that depends on the dimension of the template
+ void syncTotal(FastTemplate &cache, const FastTemplate &cacheNominal, const FastTemplate &cacheNominalLog) const ;
+
+ // return a smooth function that is equal to +/-1 for |x| >= smoothRegion_ and it's null in zero
+ inline double smoothStepFunc(double x) const {
+ if (fabs(x) >= _smoothRegion) return x > 0 ? +1 : -1;
+ double xnorm = x/_smoothRegion, xnorm2 = xnorm*xnorm;
+ return 0.125 * xnorm * (xnorm2 * (3.*xnorm2 - 10.) + 15);
+ }
+
+ // initialize the morphParams and the sentry. to be called by the daughter class, sets also _initBase to true
+ void initBase() const ;
+
+private:
+ ClassDef(FastVerticalInterpHistPdf2Base,1) //
+};
+
+
+struct FastVerticalInterpHistPdf2V;
+class FastVerticalInterpHistPdf2 : public FastVerticalInterpHistPdf2Base {
+public:
+
+ FastVerticalInterpHistPdf2() : FastVerticalInterpHistPdf2Base() {}
+ FastVerticalInterpHistPdf2(const char *name, const char *title, const RooRealVar &x, const TList & funcList, const RooArgList& coefList, Double_t smoothRegion=1., Int_t smoothAlgo=1) ;
+
+ FastVerticalInterpHistPdf2(const FastVerticalInterpHistPdf2& other, const char* name=0) :
+ FastVerticalInterpHistPdf2Base(other, name),
+ _x("x",this,other._x),
+ _cache(other._cache), _cacheNominal(other._cacheNominal), _cacheNominalLog(other._cacheNominalLog) {}
+ explicit FastVerticalInterpHistPdf2(const FastVerticalInterpHistPdf& other, const char* name=0) ;
+ virtual TObject* clone(const char* newname) const { return new FastVerticalInterpHistPdf2(*this,newname) ; }
+ virtual ~FastVerticalInterpHistPdf2() {}
+
+ virtual void setActiveBins(unsigned int bins) ;
+ Double_t evaluate() const ;
+
+ friend class FastVerticalInterpHistPdf2V;
+protected:
+ RooRealProxy _x;
+
+ /// Cache of the result
+ mutable FastHisto _cache; //! not to be serialized
+
+ /// Cache of nominal pdf (additive morphing) and its bin-by-bin logarithm (multiplicative)
+ FastHisto _cacheNominal;
+ FastHisto _cacheNominalLog;
+
+ void syncTotal() const ;
+ void initNominal(TObject *nominal) ;
+ void initComponent(int which, TObject *hi, TObject *lo) ;
+
+private:
+ ClassDef(FastVerticalInterpHistPdf2,1) //
+};
+class FastVerticalInterpHistPdf2V {
+ public:
+ FastVerticalInterpHistPdf2V(const FastVerticalInterpHistPdf2 &, const RooAbsData &data) ;
+ void fill(std::vector &out) const ;
+ private:
+ const FastVerticalInterpHistPdf2 & hpdf_;
+ int begin_, end_, nbins_;
+ struct Block {
+ int index, begin, end;
+ Block(int i, int begin_, int end_) : index(i), begin(begin_), end(end_) {}
+ };
+ std::vector blocks_;
+ std::vector bins_;
+};
+
+
+
+class FastVerticalInterpHistPdf2D2 : public FastVerticalInterpHistPdf2Base {
+public:
+
+ FastVerticalInterpHistPdf2D2() : FastVerticalInterpHistPdf2Base() {}
+ FastVerticalInterpHistPdf2D2(const char *name, const char *title, const RooRealVar &x, const RooRealVar &y, bool conditional, const TList & funcList, const RooArgList& coefList, Double_t smoothRegion=1., Int_t smoothAlgo=1) ;
+
+ FastVerticalInterpHistPdf2D2(const FastVerticalInterpHistPdf2D2& other, const char* name=0) :
+ FastVerticalInterpHistPdf2Base(other, name),
+ _x("x",this,other._x), _y("y",this,other._y), _conditional(other._conditional),
+ _cache(other._cache), _cacheNominal(other._cacheNominal), _cacheNominalLog(other._cacheNominalLog) {}
+ explicit FastVerticalInterpHistPdf2D2(const FastVerticalInterpHistPdf2D& other, const char* name=0) ;
+ virtual TObject* clone(const char* newname) const { return new FastVerticalInterpHistPdf2D2(*this,newname) ; }
+ virtual ~FastVerticalInterpHistPdf2D2() {}
+
+ const RooRealVar & x() const { return dynamic_cast(_x.arg()); }
+ const RooRealVar & y() const { return dynamic_cast(_y.arg()); }
+ Bool_t conditional() const { return _conditional; }
+
+ Double_t evaluate() const ;
+protected:
+ RooRealProxy _x, _y;
+ bool _conditional;
+
+ /// Cache of the result
+ mutable FastHisto2D _cache; //! not to be serialized
+
+ /// Cache of nominal pdf (additive morphing) and its bin-by-bin logarithm (multiplicative)
+ FastHisto2D _cacheNominal;
+ FastHisto2D _cacheNominalLog;
+
+ void syncTotal() const ;
+ void initNominal(TObject *nominal) ;
+ void initComponent(int which, TObject *hi, TObject *lo) ;
+
+private:
+ ClassDef(FastVerticalInterpHistPdf2D2,1) //
+};
+
diff --git a/python/DatacardParser.py b/python/DatacardParser.py
index 13a23b6b15ee1..697d1f4269d46 100644
--- a/python/DatacardParser.py
+++ b/python/DatacardParser.py
@@ -16,6 +16,10 @@ def addDatacardParserOptions(parser):
parser.add_option("-L", "--LoadLibrary", dest="libs", type="string" , action="append", help="Load these libraries")
parser.add_option("--poisson", dest="poisson", default=0, type="int", help="If set to a positive number, binned datasets wih more than this number of entries will be generated using poissonians")
parser.add_option("--default-morphing", dest="defMorph", type="string", default="shape2N", help="Default template morphing algorithm (to be used when the datacard has just 'shape')")
+ parser.add_option("--no-b-only","--for-fits", dest="noBOnly", default=False, action="store_true", help="Do not save the background-only pdf (saves time)")
+ parser.add_option("--no-optimize-pdfs", dest="noOptimizePdf", default=False, action="store_true", help="Do not save the RooSimultaneous as RooSimultaneousOpt and Gaussian constraints as SimpleGaussianConstraint")
+ #parser.add_option("--use-HistPdf", dest="useHistPdf", type="string", default="always", help="Use RooHistPdf for TH1s: 'always' (default), 'never', 'when-constant' (i.e. not when doing template morphing)")
+ parser.add_option("--use-HistPdf", dest="useHistPdf", type="string", default="never", help="Use RooHistPdf for TH1s: 'always', 'never' (default), 'when-constant' (i.e. not when doing template morphing)")
parser.add_option("--X-exclude-nuisance", dest="nuisancesToExclude", type="string", action="append", default=[], help="Exclude nuisances that match these regular expressions.")
parser.add_option("--X-rescale-nuisance", dest="nuisancesToRescale", type="string", action="append", nargs=2, default=[], help="Rescale by this factor the nuisances that match these regular expressions (the rescaling is applied to the sigma of the gaussian constraint term).")
parser.add_option("--X-force-no-simpdf", dest="forceNonSimPdf", default=False, action="store_true", help="FOR DEBUG ONLY: Do not produce a RooSimultaneous if there is just one channel (note: can affect performance)")
@@ -23,6 +27,11 @@ def addDatacardParserOptions(parser):
parser.add_option("--X-no-jmax", dest="noJMax", default=False, action="store_true", help="FOR DEBUG ONLY: Turn off the consistency check between jmax and number of processes.")
parser.add_option("--X-allow-no-signal", dest="allowNoSignal", default=False, action="store_true", help="Allow parsing datacards that contain only backgrounds")
parser.add_option("--X-allow-no-background", dest="allowNoBackground", default=False, action="store_true", help="Allow parsing datacards that contain only signal")
+ #parser.add_option("--X-optimize-templates", dest="optimizeExistingTemplates", default=False, action="store_true", help="Optimize templates on the fly (relevant for HZZ)")
+ #parser.add_option("--X-optimize-bound-nusances", dest="optimizeBoundNuisances", default=False, action="store_true", help="Flag nuisances to have a different implementation of bounds")
+ parser.add_option("--X-no-optimize-templates", dest="optimizeExistingTemplates", default=True, action="store_false", help="Don't optimize templates on the fly (relevant for HZZ)")
+ parser.add_option("--X-no-optimize-bound-nusances", dest="optimizeBoundNuisances", default=True, action="store_false", help="Don't flag nuisances to have a different implementation of bounds")
+ parser.add_option("--X-no-optimize-bins", dest="optimizeTemplateBins", default=True, action="store_false", help="Don't optimize template bins")
from HiggsAnalysis.CombinedLimit.Datacard import Datacard
diff --git a/python/ModelTools.py b/python/ModelTools.py
index 5e1ed1da663cc..65a7b7c215b3e 100644
--- a/python/ModelTools.py
+++ b/python/ModelTools.py
@@ -97,10 +97,14 @@ def doNuisances(self):
if re.match(pn, n):
sig = float(pf); sigscale = sig * (4 if pdf == "shape" else 7)
r = "-%g,%g" % (sigscale,sigscale)
- self.doObj("%s_Pdf" % n, "Gaussian", "%s[%s], %s_In[0,%s], %g" % (n,r,n,r,sig));
+ if self.options.noOptimizePdf:
+ self.doObj("%s_Pdf" % n, "Gaussian", "%s[%s], %s_In[0,%s], %g" % (n,r,n,r,sig));
+ else:
+ self.doObj("%s_Pdf" % n, "SimpleGaussianConstraint", "%s[%s], %s_In[0,%s], %g" % (n,r,n,r,sig));
globalobs.append("%s_In" % n)
if self.options.bin:
self.out.var("%s_In" % n).setConstant(True)
+ if self.options.optimizeBoundNuisances: self.out.var(n).setAttribute("optimizeBounds")
elif pdf == "gmM":
val = 0;
for c in errline.values(): #list channels
@@ -202,6 +206,7 @@ def doNuisances(self):
self.doObj("%s_Pdf" % n, "Gaussian", "%s, %s_In[%s,%g,%g], %s" % (n, n, args[0], self.out.var(n).getMin(), self.out.var(n).getMax(), args[1]))
self.out.var("%s_In" % n).setConstant(True)
globalobs.append("%s_In" % n)
+ #if self.options.optimizeBoundNuisances: self.out.var(n).setAttribute("optimizeBounds")
else: raise RuntimeError, "Unsupported pdf %s" % pdf
if nofloat:
self.out.var("%s" % n).setAttribute("globalConstrained",True)
@@ -311,6 +316,7 @@ def doModelConfigs(self):
if self.out.set("globalObservables"): mc.SetGlobalObservables(self.out.set("globalObservables"))
if self.options.verbose > 1: mc.Print("V")
self.out._import(mc, mc.GetName())
+ if self.options.noBOnly: break
discparams = ROOT.RooArgSet("discreteParams")
for cpar in self.discrete_param_set:
roocpar = self.out.cat(cpar)
diff --git a/python/PhysicsModel.py b/python/PhysicsModel.py
index df4e41d75e763..51cfe1357e27c 100644
--- a/python/PhysicsModel.py
+++ b/python/PhysicsModel.py
@@ -122,7 +122,7 @@ def getHiggsProdDecMode(bin,process,options):
raise RuntimeError, "Validation Error: signal process %s not among the allowed ones." % processSource
#
foundDecay = None
- for D in [ "hww", "hzz", "hgg", "htt", "hbb", 'hzg', 'hmm' ]:
+ for D in [ "hww", "hzz", "hgg", "htt", "hbb", 'hzg', 'hmm', 'hinv' ]:
if D in decaySource:
if foundDecay: raise RuntimeError, "Validation Error: decay string %s contains multiple known decay names" % decaySource
foundDecay = D
@@ -133,6 +133,11 @@ def getHiggsProdDecMode(bin,process,options):
if D in decaySource:
if foundEnergy: raise RuntimeError, "Validation Error: decay string %s contains multiple known energies" % decaySource
foundEnergy = D
+ if not foundEnergy:
+ for D in [ '7TeV', '8TeV', '14TeV' ]:
+ if D in options.fileName+":"+bin:
+ if foundEnergy: raise RuntimeError, "Validation Error: decay string %s contains multiple known energies" % decaySource
+ foundEnergy = D
if not foundEnergy:
foundEnergy = '7TeV' ## To ensure backward compatibility
print "Warning: decay string %s does not contain any known energy, assuming %s" % (decaySource, foundEnergy)
diff --git a/python/ShapeTools.py b/python/ShapeTools.py
index 6799f5fdd8900..af3a0b4c80303 100644
--- a/python/ShapeTools.py
+++ b/python/ShapeTools.py
@@ -38,12 +38,19 @@ def doObservables(self):
self.doCombinedDataset()
def doIndividualModels(self):
for b in self.DC.bins:
+ #print " + Getting model for bin %s" % (b)
pdfs = ROOT.RooArgList(); bgpdfs = ROOT.RooArgList()
coeffs = ROOT.RooArgList(); bgcoeffs = ROOT.RooArgList()
for p in self.DC.exp[b].keys(): # so that we get only self.DC.processes contributing to this bin
if self.DC.exp[b][p] == 0: continue
if self.physics.getYieldScale(b,p) == 0: continue # exclude really the pdf
+ #print " +--- Getting pdf for %s in bin %s" % (p,b)
(pdf,coeff) = (self.getPdf(b,p), self.out.function("n_exp_bin%s_proc_%s" % (b,p)))
+ if self.options.optimizeExistingTemplates:
+ pdf1 = self.optimizeExistingTemplates(pdf)
+ if (pdf1 != pdf):
+ self.out.dont_delete.append(pdf1)
+ pdf = pdf1
extranorm = self.getExtraNorm(b,p)
if extranorm:
prodset = ROOT.RooArgList(self.out.function("n_exp_bin%s_proc_%s" % (b,p)))
@@ -62,41 +69,47 @@ def doIndividualModels(self):
bgpdfs.add(pdf); bgcoeffs.add(coeff)
if self.options.verbose: print "Creating RooAddPdf %s with %s elements" % ("pdf_bin"+b, coeffs.getSize())
sum_s = ROOT.RooAddPdf("pdf_bin%s" % b, "", pdfs, coeffs)
- sum_b = ROOT.RooAddPdf("pdf_bin%s_bonly" % b, "", bgpdfs, bgcoeffs)
+ if not self.options.noBOnly: sum_b = ROOT.RooAddPdf("pdf_bin%s_bonly" % b, "", bgpdfs, bgcoeffs)
if b in self.pdfModes:
sum_s.setAttribute('forceGen'+self.pdfModes[b].title())
- sum_b.setAttribute('forceGen'+self.pdfModes[b].title())
+ if not self.options.noBOnly: sum_b.setAttribute('forceGen'+self.pdfModes[b].title())
if len(self.DC.systs):
## rename the pdfs
- sum_s.SetName("pdf_bin%s_nuis" % b); sum_b.SetName("pdf_bin%s_bonly_nuis" % b)
+ sum_s.SetName("pdf_bin%s_nuis" % b);
+ if not self.options.noBOnly: sum_b.SetName("pdf_bin%s_bonly_nuis" % b)
# now we multiply by all the nuisances, but avoiding nested products
# so we first make a list of all nuisances plus the RooAddPdf
sumPlusNuis_s = ROOT.RooArgList(self.out.nuisPdfs); sumPlusNuis_s.add(sum_s)
- sumPlusNuis_b = ROOT.RooArgList(self.out.nuisPdfs); sumPlusNuis_b.add(sum_b)
# then make RooProdPdf and import it
pdf_s = ROOT.RooProdPdf("pdf_bin%s" % b, "", sumPlusNuis_s)
- pdf_b = ROOT.RooProdPdf("pdf_bin%s_bonly" % b, "", sumPlusNuis_b)
+ if not self.options.noBOnly:
+ sumPlusNuis_b = ROOT.RooArgList(self.out.nuisPdfs); sumPlusNuis_b.add(sum_b)
+ pdf_b = ROOT.RooProdPdf("pdf_bin%s_bonly" % b, "", sumPlusNuis_b)
if b in self.pdfModes:
pdf_s.setAttribute('forceGen'+self.pdfModes[b].title())
- pdf_b.setAttribute('forceGen'+self.pdfModes[b].title())
+ if not self.options.noBOnly: pdf_b.setAttribute('forceGen'+self.pdfModes[b].title())
self.out._import(pdf_s, ROOT.RooFit.RenameConflictNodes(b))
- self.out._import(pdf_b, ROOT.RooFit.RecycleConflictNodes(), ROOT.RooFit.Silence())
+ if not self.options.noBOnly:
+ self.out._import(pdf_b, ROOT.RooFit.RecycleConflictNodes(), ROOT.RooFit.Silence())
else:
self.out._import(sum_s, ROOT.RooFit.RenameConflictNodes(b))
- self.out._import(sum_b, ROOT.RooFit.RecycleConflictNodes(), ROOT.RooFit.Silence())
+ if not self.options.noBOnly:
+ self.out._import(sum_b, ROOT.RooFit.RecycleConflictNodes(), ROOT.RooFit.Silence())
def doCombination(self):
## Contrary to Number-counting models, here each channel PDF already contains the nuisances
## So we just have to build the combined pdf
if len(self.DC.bins) > 1 or not self.options.forceNonSimPdf:
for (postfixIn,postfixOut) in [ ("","_s"), ("_bonly","_b") ]:
- simPdf = ROOT.RooSimultaneous("model"+postfixOut, "model"+postfixOut, self.out.binCat)
+ simPdf = ROOT.RooSimultaneous("model"+postfixOut, "model"+postfixOut, self.out.binCat) if self.options.noOptimizePdf else ROOT.RooSimultaneousOpt("model"+postfixOut, "model"+postfixOut, self.out.binCat)
for b in self.DC.bins:
pdfi = self.out.pdf("pdf_bin%s%s" % (b,postfixIn))
simPdf.addPdf(pdfi, b)
self.out._import(simPdf)
+ if self.options.noBOnly: break
else:
self.out._import(self.out.pdf("pdf_bin%s" % self.DC.bins[0]).clone("model_s"), ROOT.RooFit.Silence())
- self.out._import(self.out.pdf("pdf_bin%s_bonly" % self.DC.bins[0]).clone("model_b"), ROOT.RooFit.Silence())
+ if not self.options.noBOnly:
+ self.out._import(self.out.pdf("pdf_bin%s_bonly" % self.DC.bins[0]).clone("model_b"), ROOT.RooFit.Silence())
if self.options.fixpars:
pars = self.out.pdf("model_s").getParameters(self.out.obs)
iter = pars.createIterator()
@@ -325,7 +338,7 @@ def getPdf(self,channel,process,_cache={}):
postFix="Sig" if (process in self.DC.isSignal and self.DC.isSignal[process]) else "Bkg"
if _cache.has_key((channel,process)): return _cache[(channel,process)]
shapeNominal = self.getShape(channel,process)
- nominalPdf = self.shape2Pdf(shapeNominal,channel,process)
+ nominalPdf = self.shape2Pdf(shapeNominal,channel,process) if (self.options.useHistPdf == "always" or shapeNominal == None) else shapeNominal
if shapeNominal == None: return nominalPdf # no point morphing a fake shape
morphs = []; shapeAlgo = None
for (syst,nofloat,pdf,args,errline) in self.DC.systs:
@@ -344,14 +357,25 @@ def getPdf(self,channel,process,_cache={}):
shapeDown = self.getShape(channel,process,syst+"Down")
if shapeUp.ClassName() != shapeNominal.ClassName(): raise RuntimeError, "Mismatched shape types for channel %s, process %s, syst %s" % (channel,process,syst)
if shapeDown.ClassName() != shapeNominal.ClassName(): raise RuntimeError, "Mismatched shape types for channel %s, process %s, syst %s" % (channel,process,syst)
- morphs.append((syst,errline[channel][process],self.shape2Pdf(shapeUp,channel,process),self.shape2Pdf(shapeDown,channel,process)))
- if len(morphs) == 0: return nominalPdf
+ if self.options.useHistPdf == "always":
+ morphs.append((syst,errline[channel][process],self.shape2Pdf(shapeUp,channel,process),self.shape2Pdf(shapeDown,channel,process)))
+ else:
+ morphs.append((syst,errline[channel][process],shapeUp,shapeDown))
+ if len(morphs) == 0:
+ if self.options.useHistPdf == "always":
+ return nominalPdf
+ else:
+ return self.shape2Pdf(shapeNominal,channel,process)
if shapeAlgo == "shapeN": stderr.write("Warning: the shapeN implementation in RooStats and L&S are different\n")
- pdfs = ROOT.RooArgList(nominalPdf)
+ pdfs = ROOT.RooArgList(nominalPdf) if self.options.useHistPdf == "always" else ROOT.TList()
+ if self.options.useHistPdf != "always": pdfs.Add(nominalPdf)
coeffs = ROOT.RooArgList()
minscale = 1
for (syst,scale,pdfUp,pdfDown) in morphs:
- pdfs.add(pdfUp); pdfs.add(pdfDown);
+ if self.options.useHistPdf == "always":
+ pdfs.add(pdfUp); pdfs.add(pdfDown);
+ else:
+ pdfs.Add(pdfUp); pdfs.Add(pdfDown);
if scale == 1:
coeffs.add(self.out.var(syst))
else: # must scale it :-/
@@ -364,6 +388,39 @@ def getPdf(self,channel,process,_cache={}):
if shapeAlgo == "shape": shapeAlgo = self.options.defMorph
if "shapeL" in shapeAlgo: qrange = 0;
elif "shapeN" in shapeAlgo: qalgo = -1;
+ if self.options.useHistPdf != "always":
+ if nominalPdf.InheritsFrom("TH1"):
+ rebins = ROOT.TList()
+ maxbins = 0
+ for i in xrange(pdfs.GetSize()):
+ rebinned = self.rebinH1(pdfs.At(i))
+ rebins.Add(rebinned)
+ maxbins = max(maxbins, rebinned._original_bins)
+ rhp = ROOT.FastVerticalInterpHistPdf2("shape%s_%s_%s_morph" % (postFix,channel,process), "", self.out.binVar, rebins, coeffs, qrange, qalgo)
+ if self.options.optimizeTemplateBins and maxbins < self.out.maxbins:
+ #print "Optimizing binning: %d -> %d for %s " % (self.out.maxbins, maxbins, rhp.GetName())
+ rhp.setActiveBins(maxbins)
+ _cache[(channel,process)] = rhp
+ return rhp
+ elif nominalPdf.InheritsFrom("RooHistPdf") or nominalPdf.InheritsFrom("RooDataHist"):
+ nominalPdf = self.shape2Pdf(shapeNominal,channel,process)
+ pdfs.Clear(); ## now it contains "RooDataHist", it should contain "RooHistPdf"
+ pdfs.Add(nominalPdf)
+ for (syst,scale,shapeUp,shapeDown) in morphs:
+ pdfs.Add(self.shape2Pdf(shapeUp,channel,process))
+ pdfs.Add(self.shape2Pdf(shapeDown,channel,process))
+ histpdf = nominalPdf if nominalPdf.InheritsFrom("RooDataHist") else nominalPdf.dataHist()
+ xvar = histpdf.get().first()
+ rhp = ROOT.FastVerticalInterpHistPdf2("shape%s_%s_%s_morph" % (postFix,channel,process), "", xvar, pdfs, coeffs, qrange, qalgo)
+ _cache[(channel,process)] = rhp
+ return rhp
+ else:
+ pdflist = ROOT.RooArgList()
+ nominalPdf = self.shape2Pdf(shapeNominal,channel,process)
+ for (syst,scale,shapeUp,shapeDown) in morphs:
+ pdflist.add(self.shape2Pdf(shapeUp,channel,process))
+ pdflist.add(self.shape2Pdf(shapeDown,channel,process))
+ pdfs = pdflist
if "2a" in shapeAlgo: # old shape2
if not nominalPdf.InheritsFrom("RooHistPdf"): raise RuntimeError, "Algorithms 'shape2', 'shapeL2', shapeN2' only work with histogram templates"
if nominalPdf.dataHist().get().getSize() != 1: raise RuntimeError, "Algorithms 'shape2', 'shapeL2', shapeN2' only work in one dimension"
@@ -420,6 +477,12 @@ def getExtraNorm(self,channel,process):
self.doObj( "systeff_%s_%s_%s" % (channel,process,syst), "AsymPow", "%f,%f,%s" % (kappasScaled[0], kappasScaled[1], syst) )
terms.append( "systeff_%s_%s_%s" % (channel,process,syst) )
return terms if terms else None;
+ def rebinH1(self,shape):
+ rebinh1 = ROOT.TH1F(shape.GetName()+"_rebin", "", self.out.maxbins, 0.0, float(self.out.maxbins))
+ for i in range(1,min(shape.GetNbinsX(),self.out.maxbins)+1):
+ rebinh1.SetBinContent(i, shape.GetBinContent(i))
+ rebinh1._original_bins = shape.GetNbinsX()
+ return rebinh1;
def shape2Data(self,shape,channel,process,_cache={}):
postFix="Sig" if (process in self.DC.isSignal and self.DC.isSignal[process]) else "Bkg"
if shape == None:
@@ -442,11 +505,9 @@ def shape2Data(self,shape,channel,process,_cache={}):
return _cache[name]
if not _cache.has_key(shape.GetName()):
if shape.ClassName().startswith("TH1"):
- rebinh1 = ROOT.TH1F(shape.GetName()+"_rebin", "", self.out.maxbins, 0.0, float(self.out.maxbins))
- for i in range(1,min(shape.GetNbinsX(),self.out.maxbins)+1):
- rebinh1.SetBinContent(i, shape.GetBinContent(i))
+ rebinh1 = self.rebinH1(shape)
rdh = ROOT.RooDataHist(shape.GetName(), shape.GetName(), ROOT.RooArgList(self.out.binVar), rebinh1)
- self.out._import(rdh)
+ #self.out._import(rdh)
_cache[shape.GetName()] = rdh
elif shape.ClassName() in ["RooDataHist", "RooDataSet"]:
return shape
@@ -461,18 +522,23 @@ def shape2Pdf(self,shape,channel,process,_cache={}):
return _cache[name]
if not _cache.has_key(shape.GetName()+"Pdf"):
if shape.ClassName().startswith("TH1"):
- rdh = self.shape2Data(shape,channel,process)
- rhp = self.doObj("%sPdf" % shape.GetName(), "HistPdf", "{%s}, %s" % (self.out.binVar.GetName(), shape.GetName()))
- _cache[shape.GetName()+"Pdf"] = rhp
+ if self.options.useHistPdf == "never":
+ shape = self.rebinH1(shape)
+ list = ROOT.TList(); list.Add(shape);
+ rhp = ROOT.FastVerticalInterpHistPdf2("%sPdf" % shape.GetName(), "", self.out.binVar, list, ROOT.RooArgList())
+ _cache[shape.GetName()+"Pdf"] = rhp
+ else:
+ rdh = self.shape2Data(shape,channel,process)
+ rhp = ROOT.RooHistPdf("%sPdf" % shape.GetName(), "", ROOT.RooArgSet(self.out.binVar), rdh)
+ rhp.rdh = rdh # so it doesn't get deleted
+ _cache[shape.GetName()+"Pdf"] = rhp
elif shape.InheritsFrom("RooAbsPdf"):
_cache[shape.GetName()+"Pdf"] = shape
elif shape.InheritsFrom("RooDataHist"):
rhp = ROOT.RooHistPdf("%sPdf" % shape.GetName(), "", shape.get(), shape)
- self.out._import(rhp)
_cache[shape.GetName()+"Pdf"] = rhp
elif shape.InheritsFrom("RooDataSet"):
rkp = ROOT.RooKeysPdf("%sPdf" % shape.GetName(), "", self.out.var(shape.var), shape,3,1.5);
- self.out._import(rkp)
_cache[shape.GetName()+"Pdf"] = rkp
else:
raise RuntimeError, "shape2Pdf not implemented for %s" % shape.ClassName()
@@ -485,4 +551,20 @@ def argSetToString(self,argset):
if not arg: break
names.append(arg.GetName())
return ",".join(names)
+ def optimizeExistingTemplates(self,pdf):
+ if pdf.ClassName() == "FastVerticalInterpHistPdf2D":
+ return ROOT.FastVerticalInterpHistPdf2D2(pdf, "%s_opt" % pdf.GetName())
+ elif pdf.ClassName() == "RooProdPdf" and pdf.pdfList().getSize() == 2:
+ f1 = pdf.pdfList().at(0)
+ f2 = pdf.pdfList().at(1)
+ #pdf.Print("")
+ if f2.ClassName() == "FastVerticalInterpHistPdf2D" and f2.conditional():
+ f1 = self.optimizeExistingTemplates(f1)
+ f2 = ROOT.FastVerticalInterpHistPdf2D2(f2, "%s_opt" % f2.GetName())
+ ret = ROOT.RooProdPdf("%s_opt" % pdf.GetName(), "", ROOT.RooArgSet(f1), ROOT.RooFit.Conditional(ROOT.RooArgSet(f2),ROOT.RooArgSet(f2.y())))
+ ret.optf2 = f2
+ ret.optf1 = f1
+ #print "Optimize %s in \t" % (pdf.GetName()),; ret.Print("")
+ return ret
+ return pdf
diff --git a/src/AsimovUtils.cc b/src/AsimovUtils.cc
index 3dcb0c57e81f3..5f7e1866b5c2a 100644
--- a/src/AsimovUtils.cc
+++ b/src/AsimovUtils.cc
@@ -107,7 +107,7 @@ RooAbsData *asimovutils::asimovDatasetWithFit(RooStats::ModelConfig *mc, RooAbsD
throw std::runtime_error(Form("AsimovUtils: can't find nuisance for constraint term %s", cterm->GetName()));
}
std::string pdfName(cterm->ClassName());
- if (pdfName == "RooGaussian" || pdfName == "RooBifurGauss" || pdfName == "RooPoisson" || pdfName == "RooGenericPdf") {
+ if (pdfName == "RooGaussian" || pdfName == "SimpleGaussianConstraint" || pdfName == "RooBifurGauss" || pdfName == "RooPoisson" || pdfName == "RooGenericPdf") {
// this is easy
rrv.setVal(match->getVal());
} else if (pdfName == "RooGamma") {
diff --git a/src/BayesianToyMC.cc b/src/BayesianToyMC.cc
index 5657646e5adda..f03695551fe01 100644
--- a/src/BayesianToyMC.cc
+++ b/src/BayesianToyMC.cc
@@ -13,6 +13,7 @@
#include