CMS 3D CMS Logo

 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Pages
HybridNew.cc
Go to the documentation of this file.
1 #include <stdexcept>
2 #include <cstdio>
3 #include <unistd.h>
4 #include <sys/types.h>
5 #include <sys/wait.h>
6 #include <errno.h>
7 
8 #include "../interface/HybridNew.h"
9 #include <TFile.h>
10 #include <TF1.h>
11 #include <TKey.h>
12 #include <TLine.h>
13 #include <TCanvas.h>
14 #include <TGraphErrors.h>
15 #include <TStopwatch.h>
16 #include "RooRealVar.h"
17 #include "RooArgSet.h"
18 #include "RooAbsPdf.h"
19 #include "RooFitResult.h"
20 #include "RooRandom.h"
21 #include "RooAddPdf.h"
22 #include "RooConstVar.h"
23 #include "RooMsgService.h"
24 #include <RooStats/ModelConfig.h>
25 #include <RooStats/FrequentistCalculator.h>
26 #include <RooStats/HybridCalculator.h>
27 #include <RooStats/SimpleLikelihoodRatioTestStat.h>
28 #include <RooStats/RatioOfProfiledLikelihoodsTestStat.h>
29 #include <RooStats/ProfileLikelihoodTestStat.h>
30 #include <RooStats/ToyMCSampler.h>
31 #include <RooStats/HypoTestPlot.h>
32 #include "../interface/Combine.h"
33 #include "../interface/CloseCoutSentry.h"
34 #include "../interface/RooFitGlobalKillSentry.h"
35 #include "../interface/SimplerLikelihoodRatioTestStat.h"
36 #include "../interface/ProfiledLikelihoodRatioTestStat.h"
37 #include "../interface/SimplerLikelihoodRatioTestStatExt.h"
38 #include "../interface/ProfiledLikelihoodRatioTestStatExt.h"
39 #include "../interface/BestFitSigmaTestStat.h"
40 #include "../interface/ToyMCSamplerOpt.h"
41 #include "../interface/utils.h"
42 #include "../interface/ProfileLikelihood.h"
43 #include "../interface/ProfilingTools.h"
44 
45 using namespace RooStats;
46 
48 unsigned int HybridNew::nToys_ = 500;
49 double HybridNew::clsAccuracy_ = 0.005;
50 double HybridNew::rAbsAccuracy_ = 0.1;
51 double HybridNew::rRelAccuracy_ = 0.05;
52 double HybridNew::interpAccuracy_ = 0.2;
53 std::string HybridNew::rule_ = "CLs";
54 std::string HybridNew::testStat_ = "LEP";
55 bool HybridNew::genNuisances_ = true;
56 bool HybridNew::genGlobalObs_ = false;
57 bool HybridNew::fitNuisances_ = false;
58 unsigned int HybridNew::iterations_ = 1;
59 unsigned int HybridNew::nCpu_ = 0; // proof-lite mode
60 unsigned int HybridNew::fork_ = 1; // fork mode
61 std::string HybridNew::rValue_ = "1.0";
62 RooArgSet HybridNew::rValues_;
63 bool HybridNew::CLs_ = false;
64 bool HybridNew::saveHybridResult_ = false;
65 bool HybridNew::readHybridResults_ = false;
66 bool HybridNew::expectedFromGrid_ = false;
67 bool HybridNew::clsQuantiles_ = true;
69 bool HybridNew::fullBToys_ = false;
70 bool HybridNew::fullGrid_ = false;
71 bool HybridNew::saveGrid_ = false;
72 bool HybridNew::noUpdateGrid_ = false;
73 std::string HybridNew::gridFile_ = "";
76 std::string HybridNew::algo_ = "logSecant";
79 bool HybridNew::newToyMCSampler_ = true;
80 bool HybridNew::rMinSet_ = false;
81 bool HybridNew::rMaxSet_ = false;
82 std::string HybridNew::plot_;
83 std::string HybridNew::minimizerAlgo_ = "Minuit2";
85 bool HybridNew::reportPVal_ = false;
86 
87 #define EPS 1e-9
88 
90 LimitAlgo("HybridNew specific options") {
91  options_.add_options()
92  ("rule", boost::program_options::value<std::string>(&rule_)->default_value(rule_), "Rule to use: CLs, CLsplusb")
93  ("testStat",boost::program_options::value<std::string>(&testStat_)->default_value(testStat_), "Test statistics: LEP, TEV, LHC (previously known as Atlas), Profile.")
94  ("singlePoint", boost::program_options::value<std::string>(&rValue_)->default_value(rValue_), "Just compute CLs for the given value of the parameter of interest. In case of multiple parameters, use a syntax 'name=value,name2=value2,...'")
95  ("onlyTestStat", "Just compute test statistics, not actual p-values (works only with --singlePoint)")
96  ("generateNuisances", boost::program_options::value<bool>(&genNuisances_)->default_value(genNuisances_), "Generate nuisance parameters for each toy")
97  ("generateExternalMeasurements", boost::program_options::value<bool>(&genGlobalObs_)->default_value(genGlobalObs_), "Generate external measurements for each toy, taken from the GlobalObservables of the ModelConfig")
98  ("fitNuisances", boost::program_options::value<bool>(&fitNuisances_)->default_value(fitNuisances_), "Fit the nuisances, when not generating them.")
99  ("searchAlgo", boost::program_options::value<std::string>(&algo_)->default_value(algo_), "Algorithm to use to search for the limit (bisection, logSecant)")
100  ("toysH,T", boost::program_options::value<unsigned int>(&nToys_)->default_value(nToys_), "Number of Toy MC extractions to compute CLs+b, CLb and CLs")
101  ("clsAcc", boost::program_options::value<double>(&clsAccuracy_ )->default_value(clsAccuracy_), "Absolute accuracy on CLs to reach to terminate the scan")
102  ("rAbsAcc", boost::program_options::value<double>(&rAbsAccuracy_)->default_value(rAbsAccuracy_), "Absolute accuracy on r to reach to terminate the scan")
103  ("rRelAcc", boost::program_options::value<double>(&rRelAccuracy_)->default_value(rRelAccuracy_), "Relative accuracy on r to reach to terminate the scan")
104  ("interpAcc", boost::program_options::value<double>(&interpAccuracy_)->default_value(interpAccuracy_), "Minimum uncertainty from interpolation delta(x)/(max(x)-min(x))")
105  ("iterations,i", boost::program_options::value<unsigned int>(&iterations_)->default_value(iterations_), "Number of times to throw 'toysH' toys to compute the p-values (for --singlePoint if clsAcc is set to zero disabling adaptive generation)")
106  ("fork", boost::program_options::value<unsigned int>(&fork_)->default_value(fork_), "Fork to N processes before running the toys (set to 0 for debugging)")
107  ("nCPU", boost::program_options::value<unsigned int>(&nCpu_)->default_value(nCpu_), "Use N CPUs with PROOF Lite (experimental!)")
108  ("saveHybridResult", "Save result in the output file")
109  ("readHybridResults", "Read and merge results from file (requires 'toysFile' or 'grid')")
110  ("grid", boost::program_options::value<std::string>(&gridFile_), "Use the specified file containing a grid of SamplingDistributions for the limit (implies readHybridResults).\n For --singlePoint or --signif use --toysFile=x.root --readHybridResult instead of this.")
111  ("expectedFromGrid", boost::program_options::value<float>(&quantileForExpectedFromGrid_)->default_value(0.5), "Use the grid to compute the expected limit for this quantile")
112  ("signalForSignificance", boost::program_options::value<std::string>()->default_value("1"), "Use this value of the parameter of interest when generating signal toys for expected significance (same syntax as --singlePoint)")
113  ("clsQuantiles", boost::program_options::value<bool>(&clsQuantiles_)->default_value(clsQuantiles_), "Compute correct quantiles of CLs or CLsplusb instead of assuming they're the same as CLb ones")
114  //("importanceSamplingNull", boost::program_options::value<bool>(&importanceSamplingNull_)->default_value(importanceSamplingNull_),
115  // "Enable importance sampling for null hypothesis (background only)")
116  //("importanceSamplingAlt", boost::program_options::value<bool>(&importanceSamplingAlt_)->default_value(importanceSamplingAlt_),
117  // "Enable importance sampling for alternative hypothesis (signal plus background)")
118  ("optimizeTestStatistics", boost::program_options::value<bool>(&optimizeTestStatistics_)->default_value(optimizeTestStatistics_),
119  "Use optimized test statistics if the likelihood is not extended (works for LEP and TEV test statistics).")
120  ("optimizeProductPdf", boost::program_options::value<bool>(&optimizeProductPdf_)->default_value(optimizeProductPdf_),
121  "Optimize the code factorizing pdfs")
122  ("minimizerAlgo", boost::program_options::value<std::string>(&minimizerAlgo_)->default_value(minimizerAlgo_), "Choice of minimizer used for profiling (Minuit vs Minuit2)")
123  ("minimizerTolerance", boost::program_options::value<float>(&minimizerTolerance_)->default_value(minimizerTolerance_), "Tolerance for minimizer used for profiling")
124  ("plot", boost::program_options::value<std::string>(&plot_), "Save a plot of the result (test statistics distributions or limit scan)")
125  ("frequentist", "Shortcut to switch to Frequentist mode (--generateNuisances=0 --generateExternalMeasurements=1 --fitNuisances=1)")
126  ("newToyMCSampler", boost::program_options::value<bool>(&newToyMCSampler_)->default_value(newToyMCSampler_), "Use new ToyMC sampler with support for mixed binned-unbinned generation. On by default, you can turn it off if it doesn't work for your workspace.")
127  ("fullGrid", "Evaluate p-values at all grid points, without optimitations")
128  ("saveGrid", "Save CLs or (or FC p-value) at all grid points in the output tree. The value of 'r' is saved in the 'limit' branch, while the CLs or p-value in the 'quantileExpected' branch and the uncertainty on 'limitErr' (since there's no quantileExpectedErr)")
129  ("noUpdateGrid", "Do not update test statistics at grid points")
130  ("fullBToys", "Run as many B toys as S ones (default is to run 1/4 of b-only toys)")
131  ("pvalue", "Report p-value instead of significance (when running with --significance)")
132  ;
133 }
134 
135 void HybridNew::applyOptions(const boost::program_options::variables_map &vm) {
136  rMinSet_ = vm.count("rMin")>0; rMaxSet_ = vm.count("rMax")>0;
137  if (vm.count("expectedFromGrid") && !vm["expectedFromGrid"].defaulted()) {
138  //if (!vm.count("grid")) throw std::invalid_argument("HybridNew: Can't use --expectedFromGrid without --grid!");
139  if (quantileForExpectedFromGrid_ <= 0 || quantileForExpectedFromGrid_ >= 1.0) throw std::invalid_argument("HybridNew: the quantile for the expected limit must be between 0 and 1");
140  expectedFromGrid_ = true;
142  }
143  if (vm.count("frequentist")) {
145  if (vm["testStat"].defaulted()) testStat_ = "LHC";
146  if (vm["toys"].as<int>() > 0 and vm.count("toysFrequentist")) {
147  if (vm["fitNuisances"].defaulted() && withSystematics) {
148  std::cout << "When tossing frequenst toys outside the HybridNew, the nuisances will not be refitted for each toy by default. This can be changed by specifying explicitly the fitNuisances option" << std::endl;
149  fitNuisances_ = false;
150  }
151  }
152  }
153  if (genGlobalObs_ && genNuisances_) {
154  std::cerr << "ALERT: generating both global observables and nuisance parameters at the same time is not validated." << std::endl;
155  }
156  if (!vm["singlePoint"].defaulted()) {
157  if (doSignificance_) throw std::invalid_argument("HybridNew: Can't use --significance and --singlePoint at the same time");
158  workingMode_ = ( vm.count("onlyTestStat") ? MakeTestStatistics : MakePValues );
159  } else if (vm.count("onlyTestStat")) {
161  else throw std::invalid_argument("HybridNew: --onlyTestStat works only with --singlePoint or --significance");
162  } else if (doSignificance_) {
164  rValue_ = vm["signalForSignificance"].as<std::string>();
165  } else {
167  }
168  saveHybridResult_ = vm.count("saveHybridResult");
169  readHybridResults_ = vm.count("readHybridResults") || vm.count("grid");
170  if (readHybridResults_ && !(vm.count("toysFile") || vm.count("grid"))) throw std::invalid_argument("HybridNew: must have 'toysFile' or 'grid' option to have 'readHybridResults'\n");
171  mass_ = vm["mass"].as<float>();
172  fullGrid_ = vm.count("fullGrid");
173  saveGrid_ = vm.count("saveGrid");
174  fullBToys_ = vm.count("fullBToys");
175  noUpdateGrid_ = vm.count("noUpdateGrid");
176  reportPVal_ = vm.count("pvalue");
177  validateOptions();
178 }
179 
182  validateOptions();
183 }
184 
186  if (fork_ > 1) nToys_ /= fork_; // makes more sense
187  if (rule_ == "CLs") {
188  CLs_ = true;
189  } else if (rule_ == "CLsplusb") {
190  CLs_ = false;
191  } else if (rule_ == "FC") {
192  CLs_ = false;
193  } else {
194  throw std::invalid_argument("HybridNew: Rule must be either 'CLs' or 'CLsplusb'");
195  }
196  if (testStat_ == "SimpleLikelihoodRatio" || testStat_ == "SLR" ) { testStat_ = "LEP"; }
197  if (testStat_ == "RatioOfProfiledLikelihoods" || testStat_ == "ROPL") { testStat_ = "TEV"; }
198  if (testStat_ == "ProfileLikelihood" || testStat_ == "PL") { testStat_ = "Profile"; }
199  if (testStat_ == "ModifiedProfileLikelihood" || testStat_ == "MPL") { testStat_ = "LHC"; }
200  if (testStat_ == "SignFlipProfileLikelihood" || testStat_ == "SFPL") { testStat_ = "LHCFC"; }
201  if (testStat_ == "Atlas") { testStat_ = "LHC"; std::cout << "Note: the Atlas test statistics is now known as LHC test statistics.\n" << std::endl; }
202  if (testStat_ != "LEP" && testStat_ != "TEV" && testStat_ != "LHC" && testStat_ != "LHCFC" && testStat_ != "Profile" && testStat_ != "MLZ") {
203  throw std::invalid_argument("HybridNew: Test statistics should be one of 'LEP' or 'TEV' or 'LHC' (previously known as 'Atlas') or 'Profile'");
204  }
205  if (verbose) {
206  if (testStat_ == "LEP") std::cout << ">>> using the Simple Likelihood Ratio test statistics (Q_LEP)" << std::endl;
207  if (testStat_ == "TEV") std::cout << ">>> using the Ratio of Profiled Likelihoods test statistics (Q_TEV)" << std::endl;
208  if (testStat_ == "LHC") std::cout << ">>> using the Profile Likelihood test statistics modified for upper limits (Q_LHC)" << std::endl;
209  if (testStat_ == "LHCFC") std::cout << ">>> using the Profile Likelihood test statistics modified for upper limits and Feldman-Cousins (Q_LHCFC)" << std::endl;
210  if (testStat_ == "Profile") std::cout << ">>> using the Profile Likelihood test statistics not modified for upper limits (Q_Profile)" << std::endl;
211  if (testStat_ == "MLZ") std::cout << ">>> using the Maximum likelihood estimator of the signal strength as test statistics" << std::endl;
212  }
214  // If not generating toys, don't need to fit nuisance parameters
215  fitNuisances_ = false;
216  }
217  if (reportPVal_ && workingMode_ != MakeSignificance) throw std::invalid_argument("HybridNew: option --pvalue must go together with --significance");
218 }
219 
220 void HybridNew::setupPOI(RooStats::ModelConfig *mc_s) {
221  RooArgSet POI(*mc_s->GetParametersOfInterest());
222  if (rValue_.find("=") == std::string::npos) {
223  if (POI.getSize() != 1) throw std::invalid_argument("Error: the argument to --singlePoint or --signalForSignificance is a single value, but there are multiple POIs");
224  POI.snapshot(rValues_);
225  errno = 0; // check for errors in str->float conversion
226  ((RooRealVar*)rValues_.first())->setVal(strtod(rValue_.c_str(),NULL));
227  if (errno != 0) std::invalid_argument("Error: the argument to --singlePoint or --signalForSignificance is not a valid number.");
228  } else {
229  std::string::size_type eqidx = 0, colidx = 0, colidx2;
230  do {
231  eqidx = rValue_.find("=", colidx);
232  colidx2 = rValue_.find(",", colidx+1);
233  if (eqidx == std::string::npos || (colidx2 != std::string::npos && colidx2 < eqidx)) {
234  throw std::invalid_argument("Error: the argument to --singlePoint or --signalForSignificance is not in the forms 'value' or 'name1=value1,name2=value2,...'\n");
235  }
236  std::string poiName = rValue_.substr(colidx, eqidx);
237  std::string poiVal = rValue_.substr(eqidx+1, (colidx2 == std::string::npos ? std::string::npos : colidx2 - eqidx - 1));
238  RooAbsArg *poi = POI.find(poiName.c_str());
239  if (poi == 0) throw std::invalid_argument("Error: unknown parameter '"+poiName+"' passed to --singlePoint or --signalForSignificance.");
240  rValues_.addClone(*poi);
241  errno = 0;
242  rValues_.setRealValue(poi->GetName(), strtod(poiVal.c_str(),NULL));
243  if (errno != 0) throw std::invalid_argument("Error: invalid value '"+poiVal+"' for parameter '"+poiName+"' passed to --singlePoint or --signalForSignificance.");
244  } while (colidx2 != std::string::npos);
245  if (rValues_.getSize() != POI.getSize()) {
246  throw std::invalid_argument("Error: not all parameters of interest specified in --singlePoint or --signalForSignificance");
247  }
248  }
249 }
250 
251 bool HybridNew::run(RooWorkspace *w, RooStats::ModelConfig *mc_s, RooStats::ModelConfig *mc_b, RooAbsData &data, double &limit, double &limitErr, const double *hint) {
254  perf_totalToysRun_ = 0; // reset performance counter
255  if (rValues_.getSize() == 0) setupPOI(mc_s);
256  switch (workingMode_) {
257  case MakeLimit: return runLimit(w, mc_s, mc_b, data, limit, limitErr, hint);
258  case MakeSignificance: return runSignificance(w, mc_s, mc_b, data, limit, limitErr, hint);
259  case MakePValues: return runSinglePoint(w, mc_s, mc_b, data, limit, limitErr, hint);
260  case MakeTestStatistics:
262  return runTestStatistics(w, mc_s, mc_b, data, limit, limitErr, hint);
263  }
264  assert("Shouldn't get here" == 0);
265 }
266 
267 bool HybridNew::runSignificance(RooWorkspace *w, RooStats::ModelConfig *mc_s, RooStats::ModelConfig *mc_b, RooAbsData &data, double &limit, double &limitErr, const double *hint) {
269  std::auto_ptr<RooStats::HybridCalculator> hc(create(w, mc_s, mc_b, data, rValues_, setup));
270  std::auto_ptr<HypoTestResult> hcResult;
271  if (readHybridResults_) {
272  hcResult.reset(readToysFromFile(rValues_));
273  } else {
274  hcResult.reset(evalGeneric(*hc));
275  for (unsigned int i = 1; i < iterations_; ++i) {
276  std::auto_ptr<HypoTestResult> more(evalGeneric(*hc));
277  hcResult->Append(more.get());
278  if (verbose) std::cout << "\t1 - CLb = " << hcResult->CLb() << " +/- " << hcResult->CLbError() << std::endl;
279  }
280  }
281  if (hcResult.get() == 0) {
282  std::cerr << "Hypotest failed" << std::endl;
283  return false;
284  }
285  if (saveHybridResult_) {
286  TString name = TString::Format("HypoTestResult_mh%g",mass_);
287  RooLinkedListIter it = rValues_.iterator();
288  for (RooRealVar *rIn = (RooRealVar*) it.Next(); rIn != 0; rIn = (RooRealVar*) it.Next()) {
289  name += Form("_%s%g", rIn->GetName(), rIn->getVal());
290  }
291  name += Form("_%u", RooRandom::integer(std::numeric_limits<UInt_t>::max() - 1));
292  writeToysHere->WriteTObject(new HypoTestResult(*hcResult), name);
293  if (verbose) std::cout << "Hybrid result saved as " << name << " in " << writeToysHere->GetFile()->GetName() << " : " << writeToysHere->GetPath() << std::endl;
294  }
295  if (verbose > 1) {
296  std::cout << "Observed test statistics in data: " << hcResult->GetTestStatisticData() << std::endl;
297  std::cout << "Background-only toys sampled: " << hcResult->GetNullDistribution()->GetSize() << std::endl;
298  }
300  // I don't need to flip the P-values for significances, only for limits
301  hcResult->SetTestStatisticData(hcResult->GetTestStatisticData()+EPS); // issue with < vs <= in discrete models
302  double sig = hcResult->Significance();
303  double sigHi = RooStats::PValueToSignificance( (hcResult->CLb() - hcResult->CLbError()) ) - sig;
304  double sigLo = RooStats::PValueToSignificance( (hcResult->CLb() + hcResult->CLbError()) ) - sig;
305  if (reportPVal_) {
306  limit = hcResult->NullPValue();
307  limitErr = hcResult->NullPValueError();
308  } else {
309  limit = sig;
310  limitErr = std::max(sigHi,-sigLo);
311  }
312  std::cout << "\n -- Hybrid New -- \n";
313  std::cout << "Significance: " << sig << " " << sigLo << "/+" << sigHi << "\n";
314  std::cout << "Null p-value: " << hcResult->NullPValue() << " +/- " << hcResult->NullPValueError() << "\n";
315  return isfinite(limit);
316 }
317 
318 bool HybridNew::runLimit(RooWorkspace *w, RooStats::ModelConfig *mc_s, RooStats::ModelConfig *mc_b, RooAbsData &data, double &limit, double &limitErr, const double *hint) {
319  if (mc_s->GetParametersOfInterest()->getSize() != 1) throw std::logic_error("Cannot run limits in more than one dimension, for the moment.");
320  RooRealVar *r = dynamic_cast<RooRealVar *>(mc_s->GetParametersOfInterest()->first()); r->setConstant(true);
321  w->loadSnapshot("clean");
322 
323  if ((hint != 0) && (*hint > r->getMin())) {
324  r->setMax(std::min<double>(3.0 * (*hint), r->getMax()));
325  r->setMin(std::max<double>(0.3 * (*hint), r->getMin()));
326  }
327 
328  typedef std::pair<double,double> CLs_t;
329 
330  double clsTarget = 1 - cl;
331  CLs_t clsMin(1,0), clsMax(0,0), clsMid(0,0);
332  double rMin = r->getMin(), rMax = r->getMax();
333  limit = 0.5*(rMax + rMin);
334  limitErr = 0.5*(rMax - rMin);
335  bool done = false;
336 
337  TF1 expoFit("expoFit","[0]*exp([1]*(x-[2]))", rMin, rMax);
338 
339  if (readHybridResults_) {
340  if (verbose > 0) std::cout << "Search for upper limit using pre-computed grid of p-values" << std::endl;
341 
342  if (!gridFile_.empty()) {
343  if (grid_.empty()) {
344  std::auto_ptr<TFile> gridFile(TFile::Open(gridFile_.c_str()));
345  if (gridFile.get() == 0) throw std::runtime_error(("Can't open grid file "+gridFile_).c_str());
346  TDirectory *toyDir = gridFile->GetDirectory("toys");
347  if (!toyDir) throw std::logic_error("Cannot use readHypoTestResult: empty toy dir in input file empty");
348  readGrid(toyDir, rMinSet_ ? rMin : -99e99, rMaxSet_ ? rMax :+99e99);
349  }
350  if (grid_.size() <= 1) throw std::logic_error("The grid must contain at least 2 points.");
351  if (noUpdateGrid_) {
352  if (testStat_ == "LHCFC" && rule_ == "FC" && (saveGrid_ || lowerLimit_)) {
353  std::cout << "Will have to re-run points for which the test statistics was set to zero" << std::endl;
354  updateGridDataFC(w, mc_s, mc_b, data, !fullGrid_, clsTarget);
355  } else {
356  std::cout << "Will use the test statistics that had already been computed" << std::endl;
357  }
358  } else {
359  updateGridData(w, mc_s, mc_b, data, !fullGrid_, clsTarget);
360  }
361  } else throw std::logic_error("When setting a limit reading results from file, a grid file must be specified with option --grid");
362  if (grid_.size() <= 1) throw std::logic_error("The grid must contain at least 2 points.");
363 
364  useGrid();
365 
366  double minDist=1e3;
367  double nearest = 0;
368  rMin = limitPlot_->GetX()[0];
369  rMax = limitPlot_->GetX()[limitPlot_->GetN()-1];
370  for (int i = 0, n = limitPlot_->GetN(); i < n; ++i) {
371  double x = limitPlot_->GetX()[i], y = limitPlot_->GetY()[i], ey = limitPlot_->GetErrorY(i);
372  if (verbose > 0) printf(" r %.2f: %s = %6.4f +/- %6.4f\n", x, CLs_ ? "CLs" : "CLsplusb", y, ey);
373  if (saveGrid_) { limit = x; limitErr = ey; Combine::commitPoint(false, y); }
374  if (y-3*max(ey,0.01) >= clsTarget) { rMin = x; clsMin = CLs_t(y,ey); }
375  if (fabs(y-clsTarget) < minDist) { nearest = x; minDist = fabs(y-clsTarget); }
376  rMax = x; clsMax = CLs_t(y,ey);
377  if (y+3*max(ey,0.01) <= clsTarget && !fullGrid_) break;
378  }
379  limit = nearest;
380  if (verbose > 0) std::cout << " after scan x ~ " << limit << ", bounds [ " << rMin << ", " << rMax << "]" << std::endl;
381  limitErr = std::max(limit-rMin, rMax-limit);
382  expoFit.SetRange(rMin,rMax);
383 
384  if (limitErr < std::max(rAbsAccuracy_, rRelAccuracy_ * limit)) {
385  if (verbose > 1) std::cout << " reached accuracy " << limitErr << " below " << std::max(rAbsAccuracy_, rRelAccuracy_ * limit) << std::endl;
386  done = true;
387  }
388  } else {
389  limitPlot_.reset(new TGraphErrors());
390 
391  if (verbose > 0) std::cout << "Search for upper limit to the limit" << std::endl;
392  for (int tries = 0; tries < 6; ++tries) {
393  clsMax = eval(w, mc_s, mc_b, data, rMax);
394  if (lowerLimit_) break; // we can't search for lower limits this way
395  if (clsMax.first == 0 || clsMax.first + 3 * fabs(clsMax.second) < clsTarget ) break;
396  rMax += rMax;
397  if (tries == 5) {
398  std::cerr << "Cannot set higher limit: at " << r->GetName() << " = " << rMax << " still get " << (CLs_ ? "CLs" : "CLsplusb") << " = " << clsMax.first << std::endl;
399  return false;
400  }
401  }
402  if (verbose > 0) std::cout << "Search for lower limit to the limit" << std::endl;
403  clsMin = (CLs_ && rMin == 0 ? CLs_t(1,0) : eval(w, mc_s, mc_b, data, rMin));
404  if (!lowerLimit_ && clsMin.first != 1 && clsMin.first - 3 * fabs(clsMin.second) < clsTarget) {
405  if (CLs_) {
406  rMin = 0;
407  clsMin = CLs_t(1,0); // this is always true for CLs
408  } else {
409  rMin = -rMax / 4;
410  for (int tries = 0; tries < 6; ++tries) {
411  clsMin = eval(w, mc_s, mc_b, data, rMin);
412  if (clsMin.first == 1 || clsMin.first - 3 * fabs(clsMin.second) > clsTarget) break;
413  rMin += rMin;
414  if (tries == 5) {
415  std::cerr << "Cannot set lower limit: at " << r->GetName() << " = " << rMin << " still get " << (CLs_ ? "CLs" : "CLsplusb") << " = " << clsMin.first << std::endl;
416  return false;
417  }
418  }
419  }
420  }
421 
422  if (verbose > 0) std::cout << "Now doing proper bracketing & bisection" << std::endl;
423  do {
424  // determine point by bisection or interpolation
425  limit = 0.5*(rMin+rMax); limitErr = 0.5*(rMax-rMin);
426  if (algo_ == "logSecant" && clsMax.first != 0 && clsMin.first != 0) {
427  double logMin = log(clsMin.first), logMax = log(clsMax.first), logTarget = log(clsTarget);
428  limit = rMin + (rMax-rMin) * (logTarget - logMin)/(logMax - logMin);
429  if (clsMax.second != 0 && clsMin.second != 0) {
430  limitErr = hypot((logTarget-logMax) * (clsMin.second/clsMin.first), (logTarget-logMin) * (clsMax.second/clsMax.first));
431  limitErr *= (rMax-rMin)/((logMax-logMin)*(logMax-logMin));
432  }
433  // disallow "too precise" interpolations
434  if (limitErr < interpAccuracy_ * (rMax-rMin)) limitErr = interpAccuracy_ * (rMax-rMin);
435  }
436  r->setError(limitErr);
437 
438  // exit if reached accuracy on r
439  if (limitErr < std::max(rAbsAccuracy_, rRelAccuracy_ * limit)) {
440  if (verbose > 1) std::cout << " reached accuracy " << limitErr << " below " << std::max(rAbsAccuracy_, rRelAccuracy_ * limit) << std::endl;
441  done = true; break;
442  }
443 
444  // evaluate point
445  clsMid = eval(w, mc_s, mc_b, data, limit, true, clsTarget);
446  if (clsMid.second == -1) {
447  std::cerr << "Hypotest failed" << std::endl;
448  return false;
449  }
450 
451  // if sufficiently far away, drop one of the points
452  if (fabs(clsMid.first-clsTarget) >= 2*clsMid.second) {
453  if ((clsMid.first>clsTarget) == (clsMax.first>clsTarget)) {
454  rMax = limit; clsMax = clsMid;
455  } else {
456  rMin = limit; clsMin = clsMid;
457  }
458  } else {
459  if (verbose > 0) std::cout << "Trying to move the interval edges closer" << std::endl;
460  double rMinBound = rMin, rMaxBound = rMax;
461  // try to reduce the size of the interval
462  while (clsMin.second == 0 || fabs(rMin-limit) > std::max(rAbsAccuracy_, rRelAccuracy_ * limit)) {
463  rMin = 0.5*(rMin+limit);
464  clsMin = eval(w, mc_s, mc_b, data, rMin, true, clsTarget);
465  if (fabs(clsMin.first-clsTarget) <= 2*clsMin.second) break;
466  rMinBound = rMin;
467  }
468  while (clsMax.second == 0 || fabs(rMax-limit) > std::max(rAbsAccuracy_, rRelAccuracy_ * limit)) {
469  rMax = 0.5*(rMax+limit);
470  clsMax = eval(w, mc_s, mc_b, data, rMax, true, clsTarget);
471  if (fabs(clsMax.first-clsTarget) <= 2*clsMax.second) break;
472  rMaxBound = rMax;
473  }
474  expoFit.SetRange(rMinBound,rMaxBound);
475  break;
476  }
477  } while (true);
478 
479  }
480 
481  if (!done) { // didn't reach accuracy with scan, now do fit
482  double rMinBound, rMaxBound; expoFit.GetRange(rMinBound, rMaxBound);
483  if (verbose) {
484  std::cout << "\n -- HybridNew, before fit -- \n";
485  std::cout << "Limit: " << r->GetName() << " < " << limit << " +/- " << limitErr << " [" << rMinBound << ", " << rMaxBound << "]\n";
486  }
487 
488  expoFit.FixParameter(0,clsTarget);
489  double clsmaxfirst = clsMax.first;
490  if ( clsmaxfirst == 0.0 ) clsmaxfirst = 0.005;
491  double par1guess = log(clsmaxfirst/clsMin.first)/(rMax-rMin);
492  expoFit.SetParameter(1,par1guess);
493  expoFit.SetParameter(2,limit);
494  limitErr = std::max(fabs(rMinBound-limit), fabs(rMaxBound-limit));
495  int npoints = 0;
496  for (int j = 0; j < limitPlot_->GetN(); ++j) {
497  if (limitPlot_->GetX()[j] >= rMinBound && limitPlot_->GetX()[j] <= rMaxBound) npoints++;
498  }
499  for (int i = 0, imax = (readHybridResults_ ? 0 : 8); i <= imax; ++i, ++npoints) {
500  limitPlot_->Sort();
501  limitPlot_->Fit(&expoFit,(verbose <= 1 ? "QNR EX0" : "NR EX0"));
502  if (verbose) {
503  std::cout << "Fit to " << npoints << " points: " << expoFit.GetParameter(2) << " +/- " << expoFit.GetParError(2) << std::endl;
504  }
505  if ((rMinBound < expoFit.GetParameter(2)) && (expoFit.GetParameter(2) < rMaxBound) && (expoFit.GetParError(2) < 0.5*(rMaxBound-rMinBound))) {
506  // sanity check fit result
507  limit = expoFit.GetParameter(2);
508  limitErr = expoFit.GetParError(2);
509  if (limitErr < std::max(rAbsAccuracy_, rRelAccuracy_ * limit)) break;
510  }
511  // add one point in the interval.
512  double rTry = RooRandom::uniform()*(rMaxBound-rMinBound)+rMinBound;
513  if (i != imax) eval(w, mc_s, mc_b, data, rTry, true, clsTarget);
514  }
515  }
516 
517  if (!plot_.empty() && limitPlot_.get()) {
518  TCanvas *c1 = new TCanvas("c1","c1");
519  limitPlot_->Sort();
520  limitPlot_->SetLineWidth(2);
521  double xmin = r->getMin(), xmax = r->getMax();
522  for (int j = 0; j < limitPlot_->GetN(); ++j) {
523  if (limitPlot_->GetY()[j] > 1.4*clsTarget || limitPlot_->GetY()[j] < 0.6*clsTarget) continue;
524  xmin = std::min(limitPlot_->GetX()[j], xmin);
525  xmax = std::max(limitPlot_->GetX()[j], xmax);
526  }
527  limitPlot_->GetXaxis()->SetRangeUser(xmin,xmax);
528  limitPlot_->GetYaxis()->SetRangeUser(0.5*clsTarget, 1.5*clsTarget);
529  limitPlot_->Draw("AP");
530  expoFit.Draw("SAME");
531  TLine line(limitPlot_->GetX()[0], clsTarget, limitPlot_->GetX()[limitPlot_->GetN()-1], clsTarget);
532  line.SetLineColor(kRed); line.SetLineWidth(2); line.Draw();
533  line.DrawLine(limit, 0, limit, limitPlot_->GetY()[0]);
534  line.SetLineWidth(1); line.SetLineStyle(2);
535  line.DrawLine(limit-limitErr, 0, limit-limitErr, limitPlot_->GetY()[0]);
536  line.DrawLine(limit+limitErr, 0, limit+limitErr, limitPlot_->GetY()[0]);
537  c1->Print(plot_.c_str());
538  }
539 
540  std::cout << "\n -- Hybrid New -- \n";
541  std::cout << "Limit: " << r->GetName() << " < " << limit << " +/- " << limitErr << " @ " << cl * 100 << "% CL\n";
542  if (verbose > 1) std::cout << "Total toys: " << perf_totalToysRun_ << std::endl;
543  return true;
544 }
545 
546 bool HybridNew::runSinglePoint(RooWorkspace *w, RooStats::ModelConfig *mc_s, RooStats::ModelConfig *mc_b, RooAbsData &data, double &limit, double &limitErr, const double *hint) {
547  std::pair<double, double> result = eval(w, mc_s, mc_b, data, rValues_, clsAccuracy_ != 0);
548  std::cout << "\n -- Hybrid New -- \n";
549  std::cout << (CLs_ ? "CLs = " : "CLsplusb = ") << result.first << " +/- " << result.second << std::endl;
550  if (verbose > 1) std::cout << "Total toys: " << perf_totalToysRun_ << std::endl;
551  limit = result.first;
552  limitErr = result.second;
553  return true;
554 }
555 
556 bool HybridNew::runTestStatistics(RooWorkspace *w, RooStats::ModelConfig *mc_s, RooStats::ModelConfig *mc_b, RooAbsData &data, double &limit, double &limitErr, const double *hint) {
557  bool isProfile = (testStat_ == "LHC" || testStat_ == "LHCFC" || testStat_ == "Profile");
559  std::auto_ptr<RooStats::HypoTestResult> result(readToysFromFile(rValues_));
560  applyExpectedQuantile(*result);
561  limit = -2 * result->GetTestStatisticData();
562  } else {
564  std::auto_ptr<RooStats::HybridCalculator> hc(create(w, mc_s, mc_b, data, rValues_, setup));
565  RooArgSet nullPOI(*setup.modelConfig_bonly.GetSnapshot());
566  if (isProfile) {
568  nullPOI.assignValueOnly(rValues_);
569  }
570  limit = -2 * setup.qvar->Evaluate(data, nullPOI);
571  }
572  if (isProfile) limit = -limit; // there's a sign flip for these two
573  std::cout << "\n -- Hybrid New -- \n";
574  std::cout << "-2 ln Q_{"<< testStat_<<"} = " << limit << std::endl;
575  return true;
576 }
577 
578 std::pair<double, double> HybridNew::eval(RooWorkspace *w, RooStats::ModelConfig *mc_s, RooStats::ModelConfig *mc_b, RooAbsData &data, double rVal, bool adaptive, double clsTarget) {
579  RooArgSet rValues;
580  mc_s->GetParametersOfInterest()->snapshot(rValues);
581  RooRealVar *r = dynamic_cast<RooRealVar*>(rValues.first());
582  if (rVal > r->getMax()) r->setMax(2*rVal);
583  r->setVal(rVal);
584  return eval(w,mc_s,mc_b,data,rValues,adaptive,clsTarget);
585 }
586 
587 std::pair<double, double> HybridNew::eval(RooWorkspace *w, RooStats::ModelConfig *mc_s, RooStats::ModelConfig *mc_b, RooAbsData &data, const RooAbsCollection & rVals, bool adaptive, double clsTarget) {
588  if (readHybridResults_) {
589  bool isProfile = (testStat_ == "LHC" || testStat_ == "LHCFC" || testStat_ == "Profile");
590  std::auto_ptr<RooStats::HypoTestResult> result(readToysFromFile(rVals));
591  std::pair<double, double> ret(-1,-1);
592  assert(result.get() != 0 && "Null result in HybridNew::eval(Workspace,...) after readToysFromFile");
593  if (expectedFromGrid_) {
594  applyExpectedQuantile(*result);
595  result->SetTestStatisticData(result->GetTestStatisticData() + (isProfile ? -EPS : EPS));
596  } else if (!noUpdateGrid_) {
597  Setup setup;
598  std::auto_ptr<RooStats::HybridCalculator> hc = create(w, mc_s, mc_b, data, rVals, setup);
599  RooArgSet nullPOI(*setup.modelConfig_bonly.GetSnapshot());
600  if (isProfile) nullPOI.assignValueOnly(rVals);
601  double testStat = setup.qvar->Evaluate(data, nullPOI);
602  result->SetTestStatisticData(testStat + (isProfile ? -EPS : EPS));
603  }
604  ret = eval(*result, rVals);
605  return ret;
606  }
607 
609  RooLinkedListIter it = rVals.iterator();
610  for (RooRealVar *rIn = (RooRealVar*) it.Next(); rIn != 0; rIn = (RooRealVar*) it.Next()) {
611  RooRealVar *r = dynamic_cast<RooRealVar *>(mc_s->GetParametersOfInterest()->find(rIn->GetName()));
612  r->setVal(rIn->getVal());
613  if (verbose) std::cout << " " << r->GetName() << " = " << rIn->getVal() << " +/- " << r->getError() << std::endl;
614  }
615  std::auto_ptr<RooStats::HybridCalculator> hc(create(w, mc_s, mc_b, data, rVals, setup));
616  std::pair<double, double> ret = eval(*hc, rVals, adaptive, clsTarget);
617 
618  // add to plot
619  if (limitPlot_.get()) {
620  limitPlot_->Set(limitPlot_->GetN()+1);
621  limitPlot_->SetPoint(limitPlot_->GetN()-1, ((RooAbsReal*)rVals.first())->getVal(), ret.first);
622  limitPlot_->SetPointError(limitPlot_->GetN()-1, 0, ret.second);
623  }
624 
625  return ret;
626 }
627 
628 
629 
630 std::auto_ptr<RooStats::HybridCalculator> HybridNew::create(RooWorkspace *w, RooStats::ModelConfig *mc_s, RooStats::ModelConfig *mc_b, RooAbsData &data, double rVal, HybridNew::Setup &setup) {
631  RooArgSet rValues;
632  mc_s->GetParametersOfInterest()->snapshot(rValues);
633  RooRealVar *r = dynamic_cast<RooRealVar*>(rValues.first());
634  if (rVal > r->getMax()) r->setMax(2*rVal);
635  r->setVal(rVal);
636  return create(w,mc_s,mc_b,data,rValues,setup);
637 }
638 
639 std::auto_ptr<RooStats::HybridCalculator> HybridNew::create(RooWorkspace *w, RooStats::ModelConfig *mc_s, RooStats::ModelConfig *mc_b, RooAbsData &data, const RooAbsCollection & rVals, HybridNew::Setup &setup) {
640  using namespace RooStats;
641 
642  w->loadSnapshot("clean");
643  // realData_ = &data;
644 
645  RooArgSet poi(*mc_s->GetParametersOfInterest()), params(poi);
646  RooRealVar *r = dynamic_cast<RooRealVar *>(poi.first());
647 
648  if (poi.getSize() == 1) { // here things are a bit more convoluted, although they could probably be cleaned up
649  double rVal = ((RooAbsReal*)rVals.first())->getVal();
650  if (testStat_ != "MLZ") r->setMax(rVal);
651  r->setVal(rVal);
652  if (testStat_ == "LHC" || testStat_ == "Profile") {
653  r->setConstant(false); r->setMin(0);
655  r->setVal(0);
656  r->removeMax();
657  }
658  } else {
659  r->setConstant(true);
660  }
661  } else {
662  if (testStat_ == "Profile") utils::setAllConstant(poi, false);
663  else if (testStat_ == "LEP" || testStat_ == "TEV") utils::setAllConstant(poi, true);
664  poi.assignValueOnly(rVals);
665  }
666 
667  //set value of "globalConstrained" nuisances to the value of the corresponding global observable and set them constant
668  //also fill the RooArgLists which can be passed to the test statistic in order to produce the correct behaviour
669  //this is only supported currently for the optimized version of the LHC-type test statistic
670  RooArgList gobsParams;
671  RooArgList gobs;
673  RooArgList allnuis(*mc_s->GetNuisanceParameters());
674  RooArgList allgobs(*mc_s->GetGlobalObservables());
675  for (int i=0; i<allnuis.getSize(); ++i) {
676  RooRealVar *nuis = (RooRealVar*)allnuis.at(i);
677  if (nuis->getAttribute("globalConstrained")) {
678  RooRealVar *glob = (RooRealVar*)allgobs.find(TString::Format("%s_In",nuis->GetName()));
679  if (glob) {
680  nuis->setVal(glob->getVal());
681  nuis->setConstant();
682  gobsParams.add(*nuis);
683  gobs.add(*glob);
684  }
685  }
686  }
687  }
688 
689  std::auto_ptr<RooFitResult> fitMu, fitZero;
690  if (fitNuisances_ && mc_s->GetNuisanceParameters() && withSystematics) {
691  TStopwatch timer;
692  bool isExt = mc_s->GetPdf()->canBeExtended();
693  utils::setAllConstant(poi, true);
695  RooAbsPdf *pdfB = mc_b->GetPdf();
696  if (poi.getSize() == 1) {
697  r->setVal(0); pdfB = mc_s->GetPdf();
698  }
699  timer.Start();
700  {
701  CloseCoutSentry sentry(verbose < 3);
702  fitZero.reset(pdfB->fitTo(data, RooFit::Save(1), RooFit::Minimizer("Minuit2","minimize"), RooFit::Strategy(1), RooFit::Hesse(0), RooFit::Extended(isExt), RooFit::Constrain(*mc_s->GetNuisanceParameters())));
703  }
704  if (verbose > 1) { std::cout << "Zero signal fit" << std::endl; fitZero->Print("V"); }
705  if (verbose > 1) { std::cout << "Fitting of the background hypothesis done in " << timer.RealTime() << " s" << std::endl; }
706  poi.assignValueOnly(rVals);
707  timer.Start();
708  {
709  CloseCoutSentry sentry(verbose < 3);
710  fitMu.reset(mc_s->GetPdf()->fitTo(data, RooFit::Save(1), RooFit::Minimizer("Minuit2","minimize"), RooFit::Strategy(1), RooFit::Hesse(0), RooFit::Extended(isExt), RooFit::Constrain(*mc_s->GetNuisanceParameters())));
711  }
712  if (verbose > 1) { std::cout << "Reference signal fit" << std::endl; fitMu->Print("V"); }
713  if (verbose > 1) { std::cout << "Fitting of the signal-plus-background hypothesis done in " << timer.RealTime() << " s" << std::endl; }
714  } else { fitNuisances_ = false; }
715 
716  // since ModelConfig cannot allow re-setting sets, we have to re-make everything
717  setup.modelConfig = ModelConfig("HybridNew_mc_s", w);
718  setup.modelConfig.SetPdf(*mc_s->GetPdf());
719  setup.modelConfig.SetObservables(*mc_s->GetObservables());
720  setup.modelConfig.SetParametersOfInterest(*mc_s->GetParametersOfInterest());
721  if (withSystematics) {
722  if (genNuisances_ && mc_s->GetNuisanceParameters()) setup.modelConfig.SetNuisanceParameters(*mc_s->GetNuisanceParameters());
723  if (genGlobalObs_ && mc_s->GetGlobalObservables()) setup.modelConfig.SetGlobalObservables(*mc_s->GetGlobalObservables());
724  // if (genGlobalObs_ && mc_s->GetGlobalObservables()) snapGlobalObs_.reset(mc_s->GetGlobalObservables()->snapshot());
725  }
726 
727  setup.modelConfig_bonly = ModelConfig("HybridNew_mc_b", w);
728  setup.modelConfig_bonly.SetPdf(*mc_b->GetPdf());
729  setup.modelConfig_bonly.SetObservables(*mc_b->GetObservables());
730  setup.modelConfig_bonly.SetParametersOfInterest(*mc_b->GetParametersOfInterest());
731  if (withSystematics) {
732  if (genNuisances_ && mc_b->GetNuisanceParameters()) setup.modelConfig_bonly.SetNuisanceParameters(*mc_b->GetNuisanceParameters());
733  if (genGlobalObs_ && mc_b->GetGlobalObservables()) setup.modelConfig_bonly.SetGlobalObservables(*mc_b->GetGlobalObservables());
734  }
735 
736  if (withSystematics && !genNuisances_) {
737  // The pdf will contain non-const parameters which are not observables
738  // and the HybridCalculator will assume they're nuisances and try to generate them
739  // to avoid this, we force him to generate a fake nuisance instead
740  if (w->var("__HybridNew_fake_nuis__") == 0) {
741  w->factory("__HybridNew_fake_nuis__[0.5,0,1]");
742  w->factory("Uniform::__HybridNew_fake_nuisPdf__(__HybridNew_fake_nuis__)");
743  }
744  setup.modelConfig.SetNuisanceParameters(RooArgSet(*w->var("__HybridNew_fake_nuis__")));
745  setup.modelConfig_bonly.SetNuisanceParameters(RooArgSet(*w->var("__HybridNew_fake_nuis__")));
746  }
747 
748 
749  // create snapshots
750  RooArgSet paramsZero;
751  if (poi.getSize() == 1) { // in the trivial 1D case, the background has POI=0.
752  paramsZero.addClone(*rVals.first());
753  paramsZero.setRealValue(rVals.first()->GetName(), 0);
754  }
755  if (fitNuisances_) params.add(fitMu->floatParsFinal());
756  if (fitNuisances_) paramsZero.addClone(fitZero->floatParsFinal());
757  setup.modelConfig.SetSnapshot(params);
758  setup.modelConfig_bonly.SetSnapshot(paramsZero);
759  TString paramsSnapName = TString::Format("%s_%s_snapshot", setup.modelConfig.GetName(), params.GetName());
760  TString paramsZSnapName = TString::Format("%s__snapshot", setup.modelConfig_bonly.GetName());
761  RooFit::MsgLevel level = RooMsgService::instance().globalKillBelow();
762  RooMsgService::instance().setGlobalKillBelow(RooFit::ERROR);
763  w->defineSet(paramsSnapName, params , true);
764  w->defineSet(paramsZSnapName, paramsZero ,true);
765  RooMsgService::instance().setGlobalKillBelow(level);
766 
767  // Create pdfs without nusiances terms, can be used for LEP tests statistics and
768  // for generating toys when not generating global observables
769  RooAbsPdf *factorizedPdf_s = setup.modelConfig.GetPdf(), *factorizedPdf_b = setup.modelConfig_bonly.GetPdf();
771  RooArgList constraints;
772  RooAbsPdf *factorizedPdf_s = utils::factorizePdf(*mc_s->GetObservables(), *mc_s->GetPdf(), constraints);
773  RooAbsPdf *factorizedPdf_b = utils::factorizePdf(*mc_b->GetObservables(), *mc_b->GetPdf(), constraints);
774  if (factorizedPdf_s != mc_s->GetPdf()) setup.cleanupList.addOwned(*factorizedPdf_s);
775  if (factorizedPdf_b != mc_b->GetPdf()) setup.cleanupList.addOwned(*factorizedPdf_b);
776  setup.modelConfig.SetPdf(*factorizedPdf_s);
777  setup.modelConfig_bonly.SetPdf(*factorizedPdf_b);
778  }
779 
780  if (testStat_ == "LEP") {
781  //SLR is evaluated using the central value of the nuisance parameters, so we have to put them in the parameter sets
782  if (withSystematics) {
783  if (!fitNuisances_) {
784  params.add(*mc_s->GetNuisanceParameters(), true);
785  paramsZero.addClone(*mc_b->GetNuisanceParameters(), true);
786  } else {
787  std::cerr << "ALERT: using LEP test statistics with --fitNuisances is not validated and most likely broken" << std::endl;
788  params.assignValueOnly(*mc_s->GetNuisanceParameters());
789  paramsZero.assignValueOnly(*mc_s->GetNuisanceParameters());
790  }
791  }
792  RooAbsPdf *pdfB = factorizedPdf_b;
793  if (poi.getSize() == 1) pdfB = factorizedPdf_s; // in this case we can remove the arbitrary constant from the test statistics.
795  if (!mc_s->GetPdf()->canBeExtended()) {
796  setup.qvar.reset(new SimplerLikelihoodRatioTestStat(*pdfB,*factorizedPdf_s, paramsZero, params));
797  } else {
798  setup.qvar.reset(new SimplerLikelihoodRatioTestStatOpt(*mc_s->GetObservables(), *pdfB, *factorizedPdf_s, paramsZero, params, withSystematics));
799  }
800  } else {
801  std::cerr << "ALERT: LEP test statistics without optimization not validated." << std::endl;
802  RooArgSet paramsSnap; params.snapshot(paramsSnap); // needs a snapshot
803  setup.qvar.reset(new SimpleLikelihoodRatioTestStat(*pdfB,*factorizedPdf_s));
804  ((SimpleLikelihoodRatioTestStat&)*setup.qvar).SetNullParameters(paramsZero); // Null is B
805  ((SimpleLikelihoodRatioTestStat&)*setup.qvar).SetAltParameters(paramsSnap);
806  }
807  } else if (testStat_ == "TEV") {
808  std::cerr << "ALERT: Tevatron test statistics not yet validated." << std::endl;
809  RooAbsPdf *pdfB = factorizedPdf_b;
810  if (poi.getSize() == 1) pdfB = factorizedPdf_s; // in this case we can remove the arbitrary constant from the test statistics.
812  setup.qvar.reset(new ProfiledLikelihoodRatioTestStatOpt(*mc_s->GetObservables(), *pdfB, *mc_s->GetPdf(), mc_s->GetNuisanceParameters(), paramsZero, params));
813  ((ProfiledLikelihoodRatioTestStatOpt&)*setup.qvar).setPrintLevel(verbose);
814  } else {
815  setup.qvar.reset(new RatioOfProfiledLikelihoodsTestStat(*mc_s->GetPdf(), *pdfB, setup.modelConfig.GetSnapshot()));
816  ((RatioOfProfiledLikelihoodsTestStat&)*setup.qvar).SetSubtractMLE(false);
817  }
818  } else if (testStat_ == "LHC" || testStat_ == "LHCFC" || testStat_ == "Profile") {
819  if (poi.getSize() != 1 && testStat_ != "Profile") {
820  throw std::logic_error("ERROR: modified profile likelihood definitions (LHC, LHCFC) do not make sense in more than one dimension");
821  }
825  if (testStat_ == "Profile") side = ProfiledLikelihoodTestStatOpt::twoSidedDef;
826  if (workingMode_ == MakeSignificance) r->setVal(0.0);
827  setup.qvar.reset(new ProfiledLikelihoodTestStatOpt(*mc_s->GetObservables(), *mc_s->GetPdf(), mc_s->GetNuisanceParameters(), params, poi, gobsParams,gobs, verbose, side));
828  } else {
829  std::cerr << "ALERT: LHC test statistics without optimization not validated." << std::endl;
830  setup.qvar.reset(new ProfileLikelihoodTestStat(*mc_s->GetPdf()));
831  if (testStat_ == "LHC") {
832  ((ProfileLikelihoodTestStat&)*setup.qvar).SetOneSided(true);
833  } else if (testStat_ == "LHCFC") {
834  throw std::invalid_argument("Test statistics LHCFC is not supported without optimization");
835  }
836  }
837  } else if (testStat_ == "MLZ") {
838  if (workingMode_ == MakeSignificance) r->setVal(0.0);
839  setup.qvar.reset(new BestFitSigmaTestStat(*mc_s->GetObservables(), *mc_s->GetPdf(), mc_s->GetNuisanceParameters(), params, verbose));
840  }
841 
842  RooAbsPdf *nuisancePdf = 0;
844  nuisancePdf = utils::makeNuisancePdf(*mc_s);
845  if (nuisancePdf) setup.cleanupList.addOwned(*nuisancePdf);
846  }
847  if (newToyMCSampler_) {
848  setup.toymcsampler.reset(new ToyMCSamplerOpt(*setup.qvar, nToys_, nuisancePdf, genNuisances_));
849  } else {
850  std::cerr << "ALERT: running with newToyMC=0 not validated." << std::endl;
851  setup.toymcsampler.reset(new ToyMCSampler(*setup.qvar, nToys_));
852  }
853 
854  if (!mc_b->GetPdf()->canBeExtended()) setup.toymcsampler->SetNEventsPerToy(1);
855 
856  if (nCpu_ > 0) {
857  std::cerr << "ALERT: running with proof not validated." << std::endl;
858  if (verbose > 1) std::cout << " Will use " << nCpu_ << " CPUs." << std::endl;
859  setup.pc.reset(new ProofConfig(*w, nCpu_, "", kFALSE));
860  setup.toymcsampler->SetProofConfig(setup.pc.get());
861  }
862 
863 
864  std::auto_ptr<HybridCalculator> hc(new HybridCalculator(data, setup.modelConfig, setup.modelConfig_bonly, setup.toymcsampler.get()));
865  if (genNuisances_ || !genGlobalObs_) {
866  if (withSystematics) {
867  setup.toymcsampler->SetGlobalObservables(*setup.modelConfig.GetNuisanceParameters());
868  (static_cast<HybridCalculator&>(*hc)).ForcePriorNuisanceNull(*nuisancePdf);
869  (static_cast<HybridCalculator&>(*hc)).ForcePriorNuisanceAlt(*nuisancePdf);
870  }
871  } else if (genGlobalObs_ && !genNuisances_) {
872  setup.toymcsampler->SetGlobalObservables(*setup.modelConfig.GetGlobalObservables());
873  hc->ForcePriorNuisanceNull(*w->pdf("__HybridNew_fake_nuisPdf__"));
874  hc->ForcePriorNuisanceAlt(*w->pdf("__HybridNew_fake_nuisPdf__"));
875  }
876 
877  // we need less B toys than S toys
879  // need only B toys. just keep a few S+B ones to avoid possible divide-by-zero errors somewhere
880  hc->SetToys(nToys_, int(0.01*nToys_)+1);
881  if (fullBToys_) {
882  hc->SetToys(nToys_, nToys_);
883  }
884  } else if (!CLs_) {
885  // we need only S+B toys to compute CLs+b
886  hc->SetToys(fullBToys_ ? nToys_ : int(0.01*nToys_)+1, nToys_);
887  //for two sigma bands need an equal number of B
888  if (expectedFromGrid_ && (fabs(0.5-quantileForExpectedFromGrid_)>=0.4) ) {
889  hc->SetToys(nToys_, nToys_);
890  }
891  } else {
892  // need both, but more S+B than B
893  hc->SetToys(fullBToys_ ? nToys_ : int(0.25*nToys_), nToys_);
894  //for two sigma bands need an equal number of B
895  if (expectedFromGrid_ && (fabs(0.5-quantileForExpectedFromGrid_)>=0.4) ) {
896  hc->SetToys(nToys_, nToys_);
897  }
898  }
899 
900  static const char * istr = "__HybridNew__importanceSamplingDensity";
902  std::cerr << "ALERT: running with importance sampling not validated (and probably not working)." << std::endl;
903  if(verbose > 1) std::cout << ">>> Enabling importance sampling for null hyp." << std::endl;
904  if(!withSystematics) {
905  throw std::invalid_argument("Importance sampling is not available without systematics");
906  }
907  RooArgSet importanceSnapshot;
908  importanceSnapshot.addClone(poi);
909  importanceSnapshot.addClone(*mc_s->GetNuisanceParameters());
910  if (verbose > 2) importanceSnapshot.Print("V");
911  hc->SetNullImportanceDensity(mc_b->GetPdf(), &importanceSnapshot);
912  }
914  std::cerr << "ALERT: running with importance sampling not validated (and probably not working)." << std::endl;
915  if(verbose > 1) std::cout << ">>> Enabling importance sampling for alt. hyp." << std::endl;
916  if(!withSystematics) {
917  throw std::invalid_argument("Importance sampling is not available without systematics");
918  }
919  if (w->pdf(istr) == 0) {
920  w->factory("__oneHalf__[0.5]");
921  RooAddPdf *sum = new RooAddPdf(istr, "fifty-fifty", *mc_s->GetPdf(), *mc_b->GetPdf(), *w->var("__oneHalf__"));
922  w->import(*sum);
923  }
924  RooArgSet importanceSnapshot;
925  importanceSnapshot.addClone(poi);
926  importanceSnapshot.addClone(*mc_s->GetNuisanceParameters());
927  if (verbose > 2) importanceSnapshot.Print("V");
928  hc->SetAltImportanceDensity(w->pdf(istr), &importanceSnapshot);
929  }
930 
931  return hc;
932 }
933 
934 std::pair<double,double>
935 HybridNew::eval(RooStats::HybridCalculator &hc, const RooAbsCollection & rVals, bool adaptive, double clsTarget) {
936  std::auto_ptr<HypoTestResult> hcResult(evalGeneric(hc));
938  if (hcResult.get() == 0) {
939  std::cerr << "Hypotest failed" << std::endl;
940  return std::pair<double, double>(-1,-1);
941  }
942  if (testStat_ == "LHC" || testStat_ == "LHCFC" || testStat_ == "Profile") {
943  // I need to flip the P-values
944  hcResult->SetTestStatisticData(hcResult->GetTestStatisticData()-EPS); // issue with < vs <= in discrete models
945  } else {
946  hcResult->SetTestStatisticData(hcResult->GetTestStatisticData()+EPS); // issue with < vs <= in discrete models
947  hcResult->SetPValueIsRightTail(!hcResult->GetPValueIsRightTail());
948  }
949  std::pair<double,double> cls = eval(*hcResult, rVals);
950  if (verbose) std::cout << (CLs_ ? "\tCLs = " : "\tCLsplusb = ") << cls.first << " +/- " << cls.second << std::endl;
951  if (adaptive) {
952  if (CLs_) {
953  hc.SetToys(int(0.25*nToys_ + 1), nToys_);
954  }
955  else {
956  hc.SetToys(1, nToys_);
957  }
958  //for two sigma bands need an equal number of B
959  if (expectedFromGrid_ && (fabs(0.5-quantileForExpectedFromGrid_)>=0.4) ) {
960  hc.SetToys(nToys_, nToys_);
961  }
962  while (cls.second >= clsAccuracy_ && (clsTarget == -1 || fabs(cls.first-clsTarget) < 3*cls.second) ) {
963  std::auto_ptr<HypoTestResult> more(evalGeneric(hc));
964  more->SetBackgroundAsAlt(false);
965  if (testStat_ == "LHC" || testStat_ == "LHCFC" || testStat_ == "Profile") more->SetPValueIsRightTail(!more->GetPValueIsRightTail());
966  hcResult->Append(more.get());
968  cls = eval(*hcResult, rVals);
969  if (verbose) std::cout << (CLs_ ? "\tCLs = " : "\tCLsplusb = ") << cls.first << " +/- " << cls.second << std::endl;
970  }
971  } else if (iterations_ > 1) {
972  for (unsigned int i = 1; i < iterations_; ++i) {
973  std::auto_ptr<HypoTestResult> more(evalGeneric(hc));
974  more->SetBackgroundAsAlt(false);
975  if (testStat_ == "LHC" || testStat_ == "LHCFC" || testStat_ == "Profile") more->SetPValueIsRightTail(!more->GetPValueIsRightTail());
976  hcResult->Append(more.get());
978  cls = eval(*hcResult, rVals);
979  if (verbose) std::cout << (CLs_ ? "\tCLs = " : "\tCLsplusb = ") << cls.first << " +/- " << cls.second << std::endl;
980  }
981  }
982 
983  if (verbose > 0) {
984  std::cout <<
985  "\tCLs = " << hcResult->CLs() << " +/- " << hcResult->CLsError() << "\n" <<
986  "\tCLb = " << hcResult->CLb() << " +/- " << hcResult->CLbError() << "\n" <<
987  "\tCLsplusb = " << hcResult->CLsplusb() << " +/- " << hcResult->CLsplusbError() << "\n" <<
988  std::endl;
989  }
990 
991  perf_totalToysRun_ += (hcResult->GetAltDistribution()->GetSize() + hcResult->GetNullDistribution()->GetSize());
992 
993  if (!plot_.empty() && workingMode_ != MakeLimit) {
994  HypoTestPlot plot(*hcResult, 30);
995  TCanvas *c1 = new TCanvas("c1","c1");
996  plot.Draw();
997  c1->Print(plot_.c_str());
998  delete c1;
999  }
1000  if (saveHybridResult_) {
1001  TString name = TString::Format("HypoTestResult_mh%g",mass_);
1002  RooLinkedListIter it = rVals.iterator();
1003  for (RooRealVar *rIn = (RooRealVar*) it.Next(); rIn != 0; rIn = (RooRealVar*) it.Next()) {
1004  name += Form("_%s%g", rIn->GetName(), rIn->getVal());
1005  }
1006  name += Form("_%u", RooRandom::integer(std::numeric_limits<UInt_t>::max() - 1));
1007  writeToysHere->WriteTObject(new HypoTestResult(*hcResult), name);
1008  if (verbose) std::cout << "Hybrid result saved as " << name << " in " << writeToysHere->GetFile()->GetName() << " : " << writeToysHere->GetPath() << std::endl;
1009  }
1010 
1011  return cls;
1012 }
1013 
1014 std::pair<double,double> HybridNew::eval(const RooStats::HypoTestResult &hcres, const RooAbsCollection & rVals)
1015 {
1016  double rVal = ((RooAbsReal*)rVals.first())->getVal();
1017  return eval(hcres,rVal);
1018 }
1019 
1020 std::pair<double,double> HybridNew::eval(const RooStats::HypoTestResult &hcres, double rVal)
1021 {
1022  if (testStat_ == "LHCFC") {
1023  RooStats::SamplingDistribution * bDistribution = hcres.GetNullDistribution(), * sDistribution = hcres.GetAltDistribution();
1024  const std::vector<Double_t> & bdist = bDistribution->GetSamplingDistribution();
1025  const std::vector<Double_t> & bweight = bDistribution->GetSampleWeights();
1026  const std::vector<Double_t> & sdist = sDistribution->GetSamplingDistribution();
1027  const std::vector<Double_t> & sweight = sDistribution->GetSampleWeights();
1028  Double_t data = hcres.GetTestStatisticData();
1029  std::vector<Double_t> absbdist(bdist.size()), abssdist(sdist.size());
1030  std::vector<Double_t> absbweight(bweight), abssweight(sweight);
1031  Double_t absdata;
1032  if (rule_ == "FC") {
1033  for (int i = 0, n = absbdist.size(); i < n; ++i) absbdist[i] = fabs(bdist[i]);
1034  for (int i = 0, n = abssdist.size(); i < n; ++i) abssdist[i] = fabs(sdist[i]);
1035  absdata = fabs(data)-2*minimizerTolerance_; // needed here since zeros are not exact by more than tolerance
1036  } else {
1037  for (int i = 0, n = absbdist.size(); i < n; ++i) absbdist[i] = max(0., bdist[i]);
1038  for (int i = 0, n = abssdist.size(); i < n; ++i) abssdist[i] = max(0., sdist[i]);
1039  absdata = max(0., data) - EPS;
1040  }
1041  if (rVal == 0) { // S+B toys are equal to B ones!
1042  abssdist.reserve(absbdist.size() + abssdist.size());
1043  abssdist.insert(abssdist.end(), absbdist.begin(), absbdist.end());
1044  abssweight.reserve(absbweight.size() + abssweight.size());
1045  abssweight.insert(abssweight.end(), absbweight.begin(), absbweight.end());
1046  }
1047  RooStats::HypoTestResult result;
1048  RooStats::SamplingDistribution *abssDist = new RooStats::SamplingDistribution("s","s",abssdist,abssweight);
1049  RooStats::SamplingDistribution *absbDist = new RooStats::SamplingDistribution("b","b",absbdist,absbweight);
1050  result.SetNullDistribution(absbDist);
1051  result.SetAltDistribution(abssDist);
1052  result.SetTestStatisticData(absdata);
1053  result.SetPValueIsRightTail(!result.GetPValueIsRightTail());
1054  if (CLs_) {
1055  return std::pair<double,double>(result.CLs(), result.CLsError());
1056  } else {
1057  return std::pair<double,double>(result.CLsplusb(), result.CLsplusbError());
1058  }
1059  } else {
1060  if (CLs_) {
1061  return std::pair<double,double>(hcres.CLs(), hcres.CLsError());
1062  } else {
1063  return std::pair<double,double>(hcres.CLsplusb(), hcres.CLsplusbError());
1064  }
1065  }
1066 }
1067 
1068 void HybridNew::applyExpectedQuantile(RooStats::HypoTestResult &hcres) {
1069  if (expectedFromGrid_) {
1071  applySignalQuantile(hcres);
1072  } else if (clsQuantiles_) {
1073  applyClsQuantile(hcres);
1074  } else {
1075  std::vector<Double_t> btoys = hcres.GetNullDistribution()->GetSamplingDistribution();
1076  std::sort(btoys.begin(), btoys.end());
1077  Double_t testStat = btoys[std::min<int>(floor((1.-quantileForExpectedFromGrid_) * btoys.size()+0.5), btoys.size())];
1078  if (verbose > 0) std::cout << "Text statistics for " << quantileForExpectedFromGrid_ << " quantile: " << testStat << std::endl;
1079  hcres.SetTestStatisticData(testStat);
1080  //std::cout << "CLs quantile = " << (CLs_ ? hcres.CLs() : hcres.CLsplusb()) << " for test stat = " << testStat << std::endl;
1081  }
1082  }
1083 }
1084 void HybridNew::applyClsQuantile(RooStats::HypoTestResult &hcres) {
1085  RooStats::SamplingDistribution * bDistribution = hcres.GetNullDistribution(), * sDistribution = hcres.GetAltDistribution();
1086  const std::vector<Double_t> & bdist = bDistribution->GetSamplingDistribution();
1087  const std::vector<Double_t> & bweight = bDistribution->GetSampleWeights();
1088  const std::vector<Double_t> & sdist = sDistribution->GetSamplingDistribution();
1089  const std::vector<Double_t> & sweight = sDistribution->GetSampleWeights();
1090  TStopwatch timer;
1091 
1093  timer.Start();
1094  std::vector<std::pair<double,double> > bcumul; bcumul.reserve(bdist.size());
1095  std::vector<std::pair<double,double> > scumul; scumul.reserve(sdist.size());
1096  double btot = 0, stot = 0;
1097  for (std::vector<Double_t>::const_iterator it = bdist.begin(), ed = bdist.end(), itw = bweight.begin(); it != ed; ++it, ++itw) {
1098  bcumul.push_back(std::pair<double,double>(*it, *itw));
1099  btot += *itw;
1100  }
1101  for (std::vector<Double_t>::const_iterator it = sdist.begin(), ed = sdist.end(), itw = sweight.begin(); it != ed; ++it, ++itw) {
1102  scumul.push_back(std::pair<double,double>(*it, *itw));
1103  stot += *itw;
1104  }
1105  double sinv = 1.0/stot, binv = 1.0/btot, runningSum;
1106  // now compute integral distribution of Q(s+b data) so that we can quickly compute the CL_{s+b} for all test stats.
1107  std::sort(scumul.begin(), scumul.end());
1108  runningSum = 0;
1109  for (std::vector<std::pair<double,double> >::reverse_iterator it = scumul.rbegin(), ed = scumul.rend(); it != ed; ++it) {
1110  runningSum += it->second;
1111  it->second = runningSum * sinv;
1112  }
1113  std::sort(bcumul.begin(), bcumul.end());
1114  std::vector<std::pair<double,std::pair<double,double> > > xcumul; xcumul.reserve(bdist.size());
1115  runningSum = 0;
1116  std::vector<std::pair<double,double> >::const_iterator sbegin = scumul.begin(), send = scumul.end();
1117  //int k = 0;
1118  for (std::vector<std::pair<double,double> >::const_reverse_iterator it = bcumul.rbegin(), ed = bcumul.rend(); it != ed; ++it) {
1119  runningSum += it->second;
1120  std::vector<std::pair<double,double> >::const_iterator match = std::upper_bound(sbegin, send, std::pair<double,double>(it->first, 0));
1121  if (match == send) {
1122  //std::cout << "Did not find match, for it->first == " << it->first << ", as back = ( " << scumul.back().first << " , " << scumul.back().second << " ) " << std::endl;
1123  double clsb = (scumul.back().second > 0.5 ? 1.0 : 0.0), clb = runningSum*binv, cls = clsb / clb;
1124  xcumul.push_back(std::make_pair(CLs_ ? cls : clsb, *it));
1125  } else {
1126  double clsb = match->second, clb = runningSum*binv, cls = clsb / clb;
1127  //if ((++k) % 100 == 0) printf("At %+8.5f CLb = %6.4f, CLsplusb = %6.4f, CLs =%7.4f\n", it->first, clb, clsb, cls);
1128  xcumul.push_back(std::make_pair(CLs_ ? cls : clsb, *it));
1129  }
1130  }
1131  // sort
1132  std::sort(xcumul.begin(), xcumul.end());
1133  // get quantile
1134  runningSum = 0; double cut = quantileForExpectedFromGrid_ * btot;
1135  for (std::vector<std::pair<double,std::pair<double,double> > >::const_iterator it = xcumul.begin(), ed = xcumul.end(); it != ed; ++it) {
1136  runningSum += it->second.second;
1137  if (runningSum >= cut) {
1138  hcres.SetTestStatisticData(it->second.first);
1139  //std::cout << "CLs quantile = " << it->first << " for test stat = " << it->second.first << std::endl;
1140  break;
1141  }
1142  }
1143  //std::cout << "CLs quantile = " << (CLs_ ? hcres.CLs() : hcres.CLsplusb()) << std::endl;
1144  //std::cout << "Computed quantiles in " << timer.RealTime() << " s" << std::endl;
1145 #if 0
1146 
1147  timer.Start();
1148  std::vector<std::pair<double, double> > values(bdist.size());
1149  for (int i = 0, n = bdist.size(); i < n; ++i) {
1150  hcres.SetTestStatisticData( bdist[i] );
1151  values[i] = std::pair<double, double>(CLs_ ? hcres.CLs() : hcres.CLsplusb(), bdist[i]);
1152  }
1153  std::sort(values.begin(), values.end());
1154  int index = std::min<int>(floor((1.-quantileForExpectedFromGrid_) * values.size()+0.5), values.size());
1155  std::cout << "CLs quantile = " << values[index].first << " for test stat = " << values[index].second << std::endl;
1156  hcres.SetTestStatisticData(values[index].second);
1157  std::cout << "CLs quantile = " << (CLs_ ? hcres.CLs() : hcres.CLsplusb()) << " for test stat = " << values[index].second << std::endl;
1158  std::cout << "Computed quantiles in " << timer.RealTime() << " s" << std::endl;
1159 #endif
1160 }
1161 
1162 void HybridNew::applySignalQuantile(RooStats::HypoTestResult &hcres) {
1163  std::vector<Double_t> stoys = hcres.GetAltDistribution()->GetSamplingDistribution();
1164  std::sort(stoys.begin(), stoys.end());
1165  Double_t testStat = stoys[std::min<int>(floor(quantileForExpectedFromGrid_ * stoys.size()+0.5), stoys.size())];
1166  if (verbose > 0) std::cout << "Text statistics for " << quantileForExpectedFromGrid_ << " quantile: " << testStat << std::endl;
1167  hcres.SetTestStatisticData(testStat);
1168 }
1169 
1170 RooStats::HypoTestResult * HybridNew::evalGeneric(RooStats::HybridCalculator &hc, bool noFork) {
1171  if (fork_ && !noFork) return evalWithFork(hc);
1172  else {
1173  TStopwatch timer; timer.Start();
1174  RooStats::HypoTestResult * ret = hc.GetHypoTest();
1175  if (runtimedef::get("HybridNew_Timing")) std::cout << "Evaluated toys in " << timer.RealTime() << " s " << std::endl;
1176  return ret;
1177  }
1178 }
1179 
1180 RooStats::HypoTestResult * HybridNew::evalWithFork(RooStats::HybridCalculator &hc) {
1181  TStopwatch timer;
1182  std::auto_ptr<RooStats::HypoTestResult> result(0);
1183  char *tmpfile = tempnam(NULL,"rstat");
1184  unsigned int ich = 0;
1185  std::vector<UInt_t> newSeeds(fork_);
1186  for (ich = 0; ich < fork_; ++ich) {
1188  if (!fork()) break; // spawn children (but only in the parent thread)
1189  }
1190  if (ich == fork_) { // if i'm the parent
1191  int cstatus, ret;
1192  do {
1193  do { ret = waitpid(-1, &cstatus, 0); } while (ret == -1 && errno == EINTR);
1194  } while (ret != -1);
1195  if (ret == -1 && errno != ECHILD) throw std::runtime_error("Didn't wait for child");
1196  for (ich = 0; ich < fork_; ++ich) {
1197  TFile *f = TFile::Open(TString::Format("%s.%d.root", tmpfile, ich));
1198  if (f == 0) throw std::runtime_error(TString::Format("Child didn't leave output file %s.%d.root", tmpfile, ich).Data());
1199  RooStats::HypoTestResult *res = dynamic_cast<RooStats::HypoTestResult *>(f->Get("result"));
1200  if (res == 0) throw std::runtime_error(TString::Format("Child output file %s.%d.root is corrupted", tmpfile, ich).Data());
1201  if (result.get()) result->Append(res); else result.reset(dynamic_cast<RooStats::HypoTestResult *>(res->Clone()));
1202  f->Close();
1203  unlink(TString::Format("%s.%d.root", tmpfile, ich).Data());
1204  unlink(TString::Format("%s.%d.out.txt", tmpfile, ich).Data());
1205  unlink(TString::Format("%s.%d.err.txt", tmpfile, ich).Data());
1206  }
1207  } else {
1208  RooRandom::randomGenerator()->SetSeed(newSeeds[ich]);
1209  freopen(TString::Format("%s.%d.out.txt", tmpfile, ich).Data(), "w", stdout);
1210  freopen(TString::Format("%s.%d.err.txt", tmpfile, ich).Data(), "w", stderr);
1211  std::cout << " I'm child " << ich << ", seed " << newSeeds[ich] << std::endl;
1212  RooStats::HypoTestResult *hcResult = evalGeneric(hc, /*noFork=*/true);
1213  TFile *f = TFile::Open(TString::Format("%s.%d.root", tmpfile, ich), "RECREATE");
1214  f->WriteTObject(hcResult, "result");
1215  f->ls();
1216  f->Close();
1217  fflush(stdout); fflush(stderr);
1218  std::cout << "And I'm done" << std::endl;
1219  throw std::runtime_error("done"); // I have to throw instead of exiting, otherwise there's no proper stack unwinding
1220  // and deleting of intermediate objects, and when the statics get deleted it crashes
1221  // in 5.27.06 (but not in 5.28)
1222  }
1223  free(tmpfile);
1224  if (verbose > 1) { std::cout << " Evaluation of p-values done in " << timer.RealTime() << " s" << std::endl; }
1225  return result.release();
1226 }
1227 
1228 #if 0
1229 
1232 RooStats::HypoTestResult * HybridNew::evalFrequentist(RooStats::HybridCalculator &hc) {
1233  int toysSB = (workingMode_ == MakeSignificance ? 1 : nToys_);
1234  int toysB = (workingMode_ == MakeSignificance ? nToys_ : (CLs_ ? nToys_/4+1 : 1));
1235  RooArgSet obs(*hc.GetAlternateModel()->GetObservables());
1236  RooArgSet nuis(*hc.GetAlternateModel()->GetNuisanceParameters());
1237  RooArgSet gobs(*hc.GetAlternateModel()->GetGlobalObservables());
1238  RooArgSet nullPoi(*hc.GetNullModel()->GetSnapshot());
1239  std::auto_ptr<RooAbsCollection> parS(hc.GetAlternateModel()->GetPdf()->getParameters(obs));
1240  std::auto_ptr<RooAbsCollection> parB(hc.GetNullModel()->GetPdf()->getParameters(obs));
1241  RooArgList constraintsS, constraintsB;
1242  RooAbsPdf *factorS = hc.GetAlternateModel()->GetPdf();
1243  RooAbsPdf *factorB = hc.GetNullModel()->GetPdf();
1244  //std::auto_ptr<RooAbsPdf> factorS(utils::factorizePdf(obs, *hc.GetAlternateModel()->GetPdf(), constraintsS));
1245  //std::auto_ptr<RooAbsPdf> factorB(utils::factorizePdf(obs, *hc.GetNullModel()->GetPdf(), constraintsB));
1246  std::auto_ptr<RooAbsPdf> nuisPdf(utils::makeNuisancePdf(const_cast<RooStats::ModelConfig&>(*hc.GetAlternateModel())));
1247  std::vector<Double_t> distSB, distB;
1248  *parS = *snapGlobalObs_;
1249  Double_t tsData = hc.GetTestStatSampler()->GetTestStatistic()->Evaluate(*realData_, nullPoi);
1250  if (verbose > 2) std::cout << "Test statistics on data: " << tsData << std::endl;
1251  for (int i = 0; i < toysSB; ++i) {
1252  // Initialize parameters to snapshot
1253  *parS = *hc.GetAlternateModel()->GetSnapshot();
1254  // Throw global observables, and set them
1255  if (verbose > 2) { std::cout << "Generating global obs starting from " << std::endl; parS->Print("V"); }
1256  std::auto_ptr<RooDataSet> gdata(nuisPdf->generate(gobs, 1));
1257  *parS = *gdata->get(0);
1258  if (verbose > 2) { std::cout << "Generated global obs" << std::endl; utils::printRAD(&*gdata); }
1259  // Throw observables
1260  if (verbose > 2) { std::cout << "Generating obs starting from " << std::endl; parS->Print("V"); }
1261  std::auto_ptr<RooDataSet> data(factorS->generate(obs, RooFit::Extended()));
1262  if (verbose > 2) { std::cout << "Generated obs" << std::endl; utils::printRAD(&*data); }
1263  // Evaluate T.S.
1264  distSB.push_back(hc.GetTestStatSampler()->GetTestStatistic()->Evaluate(*data, nullPoi));
1265  //if std::cout << "Test statistics on S+B : " << distSB.back() << std::endl;
1266  }
1267  for (int i = 0; i < toysB; ++i) {
1268  // Initialize parameters to snapshot
1269  *parB = *hc.GetNullModel()->GetSnapshot();
1270  //*parB = *hc.GetAlternateModel()->GetSnapshot();
1271  // Throw global observables, and set them
1272  if (verbose > 2) { std::cout << "Generating global obs starting from " << std::endl; parB->Print("V"); }
1273  std::auto_ptr<RooDataSet> gdata(nuisPdf->generate(gobs, 1));
1274  *parB = *gdata->get(0);
1275  if (verbose > 2) { std::cout << "Generated global obs" << std::endl; utils::printRAD(&*gdata); }
1276  // Throw observables
1277  if (verbose > 2) { std::cout << "Generating obs starting from " << std::endl; parB->Print("V"); }
1278  std::auto_ptr<RooDataSet> data(factorB->generate(obs, RooFit::Extended()));
1279  if (verbose > 2) { std::cout << "Generated obs" << std::endl; utils::printRAD(&*data); }
1280  // Evaluate T.S.
1281  distB.push_back(hc.GetTestStatSampler()->GetTestStatistic()->Evaluate(*data, nullPoi));
1282  //std::cout << "Test statistics on B : " << distB.back() << std::endl;
1283  }
1284  // Load reference global observables
1285  RooStats::HypoTestResult *ret = new RooStats::HypoTestResult();
1286  ret->SetTestStatisticData(tsData);
1287  ret->SetAltDistribution(new RooStats::SamplingDistribution("sb","sb",distSB));
1288  ret->SetNullDistribution(new RooStats::SamplingDistribution("b","b",distB));
1289  return ret;
1290 }
1291 #endif
1292 
1293 RooStats::HypoTestResult * HybridNew::readToysFromFile(const RooAbsCollection & rVals) {
1294  if (!readToysFromHere) throw std::logic_error("Cannot use readHypoTestResult: option toysFile not specified, or input file empty");
1295  TDirectory *toyDir = readToysFromHere->GetDirectory("toys");
1296  if (!toyDir) throw std::logic_error("Cannot use readHypoTestResult: empty toy dir in input file empty");
1297  if (verbose) std::cout << "Reading toys for ";
1298  TString prefix1 = TString::Format("HypoTestResult_mh%g",mass_);
1299  TString prefix2 = TString::Format("HypoTestResult");
1300  RooLinkedListIter it = rVals.iterator();
1301  for (RooRealVar *rIn = (RooRealVar*) it.Next(); rIn != 0; rIn = (RooRealVar*) it.Next()) {
1302  if (verbose) std::cout << rIn->GetName() << " = " << rIn->getVal() << " ";
1303  prefix1 += Form("_%s%g", rIn->GetName(), rIn->getVal());
1304  prefix2 += Form("_%s%g", rIn->GetName(), rIn->getVal());
1305  }
1306  if (verbose) std::cout << std::endl;
1307  std::auto_ptr<RooStats::HypoTestResult> ret;
1308  TIter next(toyDir->GetListOfKeys()); TKey *k;
1309  while ((k = (TKey *) next()) != 0) {
1310  if (TString(k->GetName()).Index(prefix1) != 0 && TString(k->GetName()).Index(prefix2) != 0) continue;
1311  RooStats::HypoTestResult *toy = dynamic_cast<RooStats::HypoTestResult *>(toyDir->Get(k->GetName()));
1312  if (toy == 0) continue;
1313  if (verbose > 1) std::cout << " - " << k->GetName() << std::endl;
1314  if (ret.get() == 0) {
1315  ret.reset(new RooStats::HypoTestResult(*toy));
1316  } else {
1317  ret->Append(toy);
1318  }
1319  }
1320 
1321  if (ret.get() == 0) {
1322  std::cout << "ERROR: parameter point not found in input root file.\n";
1323  rVals.Print("V");
1324  if (verbose > 0) toyDir->ls();
1325  std::cout << "ERROR: parameter point not found in input root file" << std::endl;
1326  throw std::invalid_argument("Missing input");
1327  }
1328  if (verbose > 0) {
1329  std::cout <<
1330  "\tCLs = " << ret->CLs() << " +/- " << ret->CLsError() << "\n" <<
1331  "\tCLb = " << ret->CLb() << " +/- " << ret->CLbError() << "\n" <<
1332  "\tCLsplusb = " << ret->CLsplusb() << " +/- " << ret->CLsplusbError() << "\n" <<
1333  std::endl;
1334  if (!plot_.empty() && workingMode_ != MakeLimit) {
1335  HypoTestPlot plot(*ret, 30);
1336  TCanvas *c1 = new TCanvas("c1","c1");
1337  plot.Draw();
1338  c1->Print(plot_.c_str());
1339  delete c1;
1340  }
1341  }
1342  return ret.release();
1343 }
1344 
1345 void HybridNew::readGrid(TDirectory *toyDir, double rMin, double rMax) {
1346  if (rValues_.getSize() != 1) throw std::runtime_error("Running limits with grid only works in one dimension for the moment");
1347  clearGrid();
1348 
1349  TIter next(toyDir->GetListOfKeys()); TKey *k; const char *poiName = rValues_.first()->GetName();
1350  while ((k = (TKey *) next()) != 0) {
1351  TString name(k->GetName());
1352  if (name.Index("HypoTestResult_mh") == 0) {
1353  if (name.Index(TString::Format("HypoTestResult_mh%g_%s",mass_,poiName)) != 0 || name.Index("_", name.Index("_")+1) == -1) continue;
1354  name.ReplaceAll(TString::Format("HypoTestResult_mh%g_%s",mass_,poiName),""); // remove the prefix
1355  if (name.Index("_") == -1) continue; // check if it has the _<uniqueId> postfix
1356  name.Remove(name.Index("_"),name.Length()); // remove it before calling atof
1357  } else if (name.Index("HypoTestResult_") == 0) {
1358  // let's put a warning here, since results of this form were supported in the past
1359  std::cout << "HybridNew::readGrid: HypoTestResult with non-conformant name " << name << " will be skipped" << std::endl;
1360  continue;
1361  } else continue;
1362  double rVal = atof(name.Data());
1363  if (rVal < rMin || rVal > rMax) continue;
1364  if (verbose > 2) std::cout << " Do " << k->GetName() << " -> " << name << " --> " << rVal << std::endl;
1365  RooStats::HypoTestResult *toy = dynamic_cast<RooStats::HypoTestResult *>(toyDir->Get(k->GetName()));
1366  RooStats::HypoTestResult *&merge = grid_[rVal];
1367  if (merge == 0) merge = new RooStats::HypoTestResult(*toy);
1368  else merge->Append(toy);
1369  merge->ResetBit(1);
1370  }
1371  if (verbose > 1) {
1372  std::cout << "GRID, as is." << std::endl;
1373  typedef std::map<double, RooStats::HypoTestResult *>::iterator point;
1374  for (point it = grid_.begin(), ed = grid_.end(); it != ed; ++it) {
1375  std::cout << " - " << it->first << " (CLs = " << it->second->CLs() << " +/- " << it->second->CLsError() << ")" << std::endl;
1376  }
1377  }
1378 }
1379 void HybridNew::updateGridData(RooWorkspace *w, RooStats::ModelConfig *mc_s, RooStats::ModelConfig *mc_b, RooAbsData &data, bool smart, double clsTarget_) {
1380  typedef std::map<double, RooStats::HypoTestResult *>::iterator point;
1381  if (!smart) {
1382  for (point it = grid_.begin(), ed = grid_.end(); it != ed; ++it) {
1383  it->second->ResetBit(1);
1384  updateGridPoint(w, mc_s, mc_b, data, it);
1385  }
1386  } else {
1387  typedef std::pair<double,double> CLs_t;
1388  std::vector<point> points; points.reserve(grid_.size());
1389  std::vector<CLs_t> values; values.reserve(grid_.size());
1390  for (point it = grid_.begin(), ed = grid_.end(); it != ed; ++it) { points.push_back(it); values.push_back(CLs_t(-99, -99)); }
1391  int iMin = 0, iMax = points.size()-1;
1392  while (iMax-iMin > 3) {
1393  if (verbose > 1) std::cout << "Bisecting range [" << iMin << ", " << iMax << "]" << std::endl;
1394  int iMid = (iMin+iMax)/2;
1395  CLs_t clsMid = values[iMid] = updateGridPoint(w, mc_s, mc_b, data, points[iMid]);
1396  if (verbose > 1) std::cout << " Midpoint " << iMid << " value " << clsMid.first << " +/- " << clsMid.second << std::endl;
1397  if (clsMid.first - 3*max(clsMid.second,0.01) > clsTarget_) {
1398  if (verbose > 1) std::cout << " Replacing Min" << std::endl;
1399  iMin = iMid; continue;
1400  } else if (clsMid.first + 3*max(clsMid.second,0.01) < clsTarget_) {
1401  if (verbose > 1) std::cout << " Replacing Max" << std::endl;
1402  iMax = iMid; continue;
1403  } else {
1404  if (verbose > 1) std::cout << " Tightening Range" << std::endl;
1405  while (iMin < iMid-1) {
1406  int iLo = (iMin+iMid)/2;
1407  CLs_t clsLo = values[iLo] = updateGridPoint(w, mc_s, mc_b, data, points[iLo]);
1408  if (verbose > 1) std::cout << " Lowpoint " << iLo << " value " << clsLo.first << " +/- " << clsLo.second << std::endl;
1409  if (clsLo.first - 3*max(clsLo.second,0.01) > clsTarget_) iMin = iLo;
1410  else break;
1411  }
1412  while (iMax > iMid+1) {
1413  int iHi = (iMax+iMid)/2;
1414  CLs_t clsHi = values[iHi] = updateGridPoint(w, mc_s, mc_b, data, points[iHi]);
1415  if (verbose > 1) std::cout << " Highpoint " << iHi << " value " << clsHi.first << " +/- " << clsHi.second << std::endl;
1416  if (clsHi.first + 3*max(clsHi.second,0.01) < clsTarget_) iMax = iHi;
1417  else break;
1418  }
1419  break;
1420  }
1421  }
1422  if (verbose > 1) std::cout << "Final range [" << iMin << ", " << iMax << "]" << std::endl;
1423  for (int i = 0; i < iMin; ++i) {
1424  points[i]->second->SetBit(1);
1425  if (verbose > 1) std::cout << " Will not use point " << i << " (r " << points[i]->first << ")" << std::endl;
1426  }
1427  for (int i = iMin; i <= iMax; ++i) {
1428  points[i]->second->ResetBit(1);
1429  if (values[i].first < -2) {
1430  if (verbose > 1) std::cout << " Updaing point " << i << " (r " << points[i]->first << ")" << std::endl;
1431  updateGridPoint(w, mc_s, mc_b, data, points[i]);
1432  }
1433  else if (verbose > 1) std::cout << " Point " << i << " (r " << points[i]->first << ") was already updated during search." << std::endl;
1434  }
1435  for (int i = iMax+1, n = points.size(); i < n; ++i) {
1436  points[i]->second->SetBit(1);
1437  if (verbose > 1) std::cout << " Will not use point " << i << " (r " << points[i]->first << ")" << std::endl;
1438  }
1439  }
1440 }
1441 void HybridNew::updateGridDataFC(RooWorkspace *w, RooStats::ModelConfig *mc_s, RooStats::ModelConfig *mc_b, RooAbsData &data, bool smart, double clsTarget_) {
1442  typedef std::map<double, RooStats::HypoTestResult *>::iterator point;
1443  std::vector<Double_t> rToUpdate; std::vector<point> pointToUpdate;
1444  for (point it = grid_.begin(), ed = grid_.end(); it != ed; ++it) {
1445  it->second->ResetBit(1);
1446  if (it->first == 0 || fabs(it->second->GetTestStatisticData()) <= 2*minimizerTolerance_) {
1447  rToUpdate.push_back(it->first);
1448  pointToUpdate.push_back(it);
1449  }
1450  }
1451  if (verbose > 0) std::cout << "A total of " << rToUpdate.size() << " points will be updated." << std::endl;
1452  Setup setup;
1453  std::auto_ptr<RooStats::HybridCalculator> hc = create(w, mc_s, mc_b, data, rToUpdate.back(), setup);
1454  RooArgSet nullPOI(*setup.modelConfig_bonly.GetSnapshot());
1455  std::vector<Double_t> qVals = ((ProfiledLikelihoodTestStatOpt&)(*setup.qvar)).Evaluate(data, nullPOI, rToUpdate);
1456  for (int i = 0, n = rToUpdate.size(); i < n; ++i) {
1457  pointToUpdate[i]->second->SetTestStatisticData(qVals[i] - EPS);
1458  }
1459  if (verbose > 0) std::cout << "All points have been updated." << std::endl;
1460 }
1461 
1462 std::pair<double,double> HybridNew::updateGridPoint(RooWorkspace *w, RooStats::ModelConfig *mc_s, RooStats::ModelConfig *mc_b, RooAbsData &data, std::map<double, RooStats::HypoTestResult *>::iterator point) {
1463  typedef std::pair<double,double> CLs_t;
1464  bool isProfile = (testStat_ == "LHC" || testStat_ == "LHCFC" || testStat_ == "Profile");
1465  if (point->first == 0 && CLs_) return std::pair<double,double>(1,0);
1466  RooArgSet poi(*mc_s->GetParametersOfInterest());
1467  RooRealVar *r = dynamic_cast<RooRealVar *>(poi.first());
1468  if (expectedFromGrid_) {
1469  applyExpectedQuantile(*point->second);
1470  point->second->SetTestStatisticData(point->second->GetTestStatisticData() + (isProfile ? EPS : EPS));
1471  } else {
1472  Setup setup;
1473  std::auto_ptr<RooStats::HybridCalculator> hc = create(w, mc_s, mc_b, data, point->first, setup);
1474  RooArgSet nullPOI(*setup.modelConfig_bonly.GetSnapshot());
1475  if (isProfile) nullPOI.setRealValue(r->GetName(), point->first);
1476  double testStat = setup.qvar->Evaluate(data, nullPOI);
1477  point->second->SetTestStatisticData(testStat + (isProfile ? EPS : EPS));
1478  }
1479  if (verbose > 1) {
1480  std::cout << "At " << r->GetName() << " = " << point->first << ":\n" <<
1481  "\tCLs = " << point->second->CLs() << " +/- " << point->second->CLsError() << "\n" <<
1482  "\tCLb = " << point->second->CLb() << " +/- " << point->second->CLbError() << "\n" <<
1483  "\tCLsplusb = " << point->second->CLsplusb() << " +/- " << point->second->CLsplusbError() << "\n" <<
1484  std::endl;
1485  }
1486 
1487  return eval(*point->second, point->first);
1488 }
1490  typedef std::pair<double,double> CLs_t;
1491  int i = 0, n = 0;
1492  limitPlot_.reset(new TGraphErrors(1));
1493  for (std::map<double, RooStats::HypoTestResult *>::iterator itg = grid_.begin(), edg = grid_.end(); itg != edg; ++itg, ++i) {
1494  if (itg->second->TestBit(1)) continue;
1495  CLs_t val(1,0);
1496  if (CLs_) {
1497  if (itg->first > 0) val = eval(*itg->second, itg->first);
1498  } else {
1499  val = eval(*itg->second, itg->first);
1500  }
1501  if (val.first == -1) continue;
1502  if (val.second == 0 && (val.first != 1 && val.first != 0)) continue;
1503  limitPlot_->Set(n+1);
1504  limitPlot_->SetPoint( n, itg->first, val.first);
1505  limitPlot_->SetPointError(n, 0, val.second);
1506  n++;
1507  }
1508 }
1510  for (std::map<double, RooStats::HypoTestResult *>::iterator it = grid_.begin(), ed = grid_.end(); it != ed; ++it) {
1511  delete it->second;
1512  }
1513  grid_.clear();
1514 }
1515 
#define DEBUG
int i
Definition: DBlmapReader.cc:9
TDirectory * readToysFromHere
Definition: Combine.cc:66
static std::string rule_
Definition: HybridNew.h:44
std::auto_ptr< RooStats::ProofConfig > pc
Definition: HybridNew.h:86
static unsigned int iterations_
Definition: HybridNew.h:49
static bool importanceSamplingNull_
Definition: HybridNew.h:59
static unsigned int fork_
Definition: HybridNew.h:58
bool doSignificance_
Definition: Combine.cc:69
std::auto_ptr< RooStats::ToyMCSampler > toymcsampler
Definition: HybridNew.h:85
bool lowerLimit_
Definition: Combine.cc:70
bool setAllConstant(const RooAbsCollection &coll, bool constant=true)
set all RooRealVars to constants. return true if at least one changed status
Definition: utils.cc:248
RooStats::ModelConfig modelConfig
Definition: HybridNew.h:83
static PFTauRenderPlugin instance
RooStats::HypoTestResult * evalGeneric(RooStats::HybridCalculator &hc, bool forceNoFork=false)
Definition: HybridNew.cc:1170
virtual bool runSignificance(RooWorkspace *w, RooStats::ModelConfig *mc_s, RooStats::ModelConfig *mc_b, RooAbsData &data, double &limit, double &limitErr, const double *hint)
Definition: HybridNew.cc:267
int get(const char *name)
void updateGridDataFC(RooWorkspace *w, RooStats::ModelConfig *mc_s, RooStats::ModelConfig *mc_b, RooAbsData &data, bool smart, double clsTarget)
Definition: HybridNew.cc:1441
void validateOptions()
Definition: HybridNew.cc:185
virtual bool runLimit(RooWorkspace *w, RooStats::ModelConfig *mc_s, RooStats::ModelConfig *mc_b, RooAbsData &data, double &limit, double &limitErr, const double *hint)
Definition: HybridNew.cc:318
long int integer
Definition: mlp_lapack.h:12
static const int WARNING
bool withSystematics
Definition: Combine.cc:68
float mass_
Definition: HybridNew.h:70
static std::string rValue_
Definition: HybridNew.h:47
#define NULL
Definition: scimark2.h:8
#define min(a, b)
Definition: mlp_lapack.h:161
RooAbsPdf * makeNuisancePdf(RooStats::ModelConfig &model, const char *name="nuisancePdf")
Definition: utils.cc:200
RooArgSet cleanupList
Definition: HybridNew.h:87
static std::string algo_
Definition: HybridNew.h:60
static float minimizerTolerance_
Definition: HybridNew.h:63
static double interpAccuracy_
Definition: HybridNew.h:42
uint16_t size_type
static std::string minimizerAlgo_
Definition: HybridNew.h:62
static WorkingMode workingMode_
Definition: HybridNew.h:40
TDirectory * writeToysHere
Definition: Combine.cc:65
void applySignalQuantile(RooStats::HypoTestResult &hcres)
Definition: HybridNew.cc:1162
static bool saveHybridResult_
Definition: HybridNew.h:50
virtual const std::string & name() const
Definition: HybridNew.h:32
#define EPS
Definition: HybridNew.cc:87
U second(std::pair< T, U > const &p)
static double rAbsAccuracy_
Definition: HybridNew.h:42
static void commitPoint(bool expected, float quantile)
Save a point into the output tree. Usually if expected = false, quantile should be set to -1 (except ...
Definition: Combine.cc:557
void clearGrid()
Definition: HybridNew.cc:1509
static float quantileForExpectedFromGrid_
Definition: HybridNew.h:53
void updateGridData(RooWorkspace *w, RooStats::ModelConfig *mc_s, RooStats::ModelConfig *mc_b, RooAbsData &data, bool smart, double clsTarget)
Definition: HybridNew.cc:1379
virtual void applyOptions(const boost::program_options::variables_map &vm)
Definition: HybridNew.cc:135
void applyExpectedQuantile(RooStats::HypoTestResult &hcres)
Definition: HybridNew.cc:1068
const T & max(const T &a, const T &b)
std::auto_ptr< RooStats::TestStatistic > qvar
Definition: HybridNew.h:84
RooAbsPdf * factorizePdf(const RooArgSet &observables, RooAbsPdf &pdf, RooArgList &constraints)
Definition: utils.cc:80
static bool reportPVal_
Definition: HybridNew.h:45
static bool CLs_
Definition: HybridNew.h:43
tuple result
Definition: query.py:137
virtual bool run(RooWorkspace *w, RooStats::ModelConfig *mc_s, RooStats::ModelConfig *mc_b, RooAbsData &data, double &limit, double &limitErr, const double *hint)
Definition: HybridNew.cc:251
Float_t g_quantileExpected_
Definition: Combine.cc:63
std::pair< double, double > eval(RooWorkspace *w, RooStats::ModelConfig *mc_s, RooStats::ModelConfig *mc_b, RooAbsData &data, const RooAbsCollection &rVals, bool adaptive=false, double clsTarget=-1)
generic version
Definition: HybridNew.cc:587
int j
Definition: DBlmapReader.cc:9
double f[11][100]
static bool saveGrid_
Definition: HybridNew.h:56
std::map< double, RooStats::HypoTestResult * > grid_
Definition: HybridNew.h:119
static unsigned int nCpu_
Definition: HybridNew.h:58
static bool fullGrid_
Definition: HybridNew.h:55
virtual bool runTestStatistics(RooWorkspace *w, RooStats::ModelConfig *mc_s, RooStats::ModelConfig *mc_b, RooAbsData &data, double &limit, double &limitErr, const double *hint)
Definition: HybridNew.cc:556
static bool rMaxSet_
Definition: HybridNew.h:69
static unsigned int nToys_
Definition: HybridNew.h:41
bool first
Definition: L1TdeRCT.cc:94
static bool genGlobalObs_
Definition: HybridNew.h:46
float cl
Definition: Combine.cc:71
int k[5][pyjets_maxn]
static std::string testStat_
Definition: HybridNew.h:44
static bool optimizeProductPdf_
Definition: HybridNew.h:65
static bool noUpdateGrid_
Definition: HybridNew.h:57
void setupPOI(RooStats::ModelConfig *mc_s)
Definition: HybridNew.cc:220
RooStats::HypoTestResult * readToysFromFile(const RooAbsCollection &rVals)
Definition: HybridNew.cc:1293
Setup Minimizer configuration on creation, reset the previous one on destruction. ...
void useGrid()
Definition: HybridNew.cc:1489
static std::string gridFile_
Definition: HybridNew.h:51
unsigned int perf_totalToysRun_
Definition: HybridNew.h:76
std::auto_ptr< TGraphErrors > limitPlot_
Definition: HybridNew.h:73
void printRAD(const RooAbsData *d)
Definition: utils.cc:56
char data[epos_bytes_allocation]
Definition: EPOS_Wrapper.h:82
static bool optimizeTestStatistics_
Definition: HybridNew.h:66
std::pair< double, double > updateGridPoint(RooWorkspace *w, RooStats::ModelConfig *mc_s, RooStats::ModelConfig *mc_b, RooAbsData &data, std::map< double, RooStats::HypoTestResult * >::iterator point)
Definition: HybridNew.cc:1462
static bool genNuisances_
Definition: HybridNew.h:46
static std::string plot_
Definition: HybridNew.h:61
static double rRelAccuracy_
Definition: HybridNew.h:42
RooStats::ModelConfig modelConfig_bonly
Definition: HybridNew.h:83
perl if(1 lt scalar(@::datatypes))
Definition: edlooper.cc:31
static bool rMinSet_
Definition: HybridNew.h:68
tuple cout
Definition: gather_cfg.py:121
std::pair< typename Association::data_type::first_type, double > match(Reference key, Association association, bool bestMatchByMaxValue)
Generic matching function.
Definition: Utils.h:6
static bool expectedFromGrid_
Definition: HybridNew.h:52
tuple level
Definition: testEve_cfg.py:34
static bool newToyMCSampler_
Definition: HybridNew.h:67
void applyClsQuantile(RooStats::HypoTestResult &hcres)
Definition: HybridNew.cc:1084
Definition: DDAxes.h:10
boost::program_options::options_description options_
Definition: LimitAlgo.h:31
void readGrid(TDirectory *directory, double rMin, double rMax)
Definition: HybridNew.cc:1345
virtual void applyDefaultOptions()
Definition: HybridNew.cc:180
static bool clsQuantiles_
Definition: HybridNew.h:52
virtual bool runSinglePoint(RooWorkspace *w, RooStats::ModelConfig *mc_s, RooStats::ModelConfig *mc_b, RooAbsData &data, double &limit, double &limitErr, const double *hint)
Definition: HybridNew.cc:546
static bool importanceSamplingAlt_
Definition: HybridNew.h:59
RooStats::HypoTestResult * evalWithFork(RooStats::HybridCalculator &hc)
Definition: HybridNew.cc:1180
void setup(std::vector< TH2F > &depth, std::string name, std::string units="")
static bool fitNuisances_
Definition: HybridNew.h:46
*vegas h *****************************************************used in the default bin number in original ***version of VEGAS is ***a higher bin number might help to derive a more precise ***grade subtle point
Definition: invegas.h:5
static bool readHybridResults_
Definition: HybridNew.h:50
static bool fullBToys_
Definition: HybridNew.h:54
static const int ERROR
static RooArgSet rValues_
Definition: HybridNew.h:48
static double clsAccuracy_
Definition: HybridNew.h:42
T w() const
std::auto_ptr< RooStats::HybridCalculator > create(RooWorkspace *w, RooStats::ModelConfig *mc_s, RooStats::ModelConfig *mc_b, RooAbsData &data, const RooAbsCollection &rVals, Setup &setup)
generic version
Definition: HybridNew.cc:639