ra4_stats  0341147a0dc35f80f4e12c6003afb76a38e2ed6e
workspace_generator.cpp
Go to the documentation of this file.
2 
3 #include <iostream>
4 #include <iomanip>
5 #include <sstream>
6 #include <fstream>
7 #include <array>
8 #include <algorithm>
9 #include <numeric>
10 
11 #include "TDirectory.h"
12 
13 #include "RooPoisson.h"
14 #include "RooDataSet.h"
15 #include "RooRealVar.h"
16 
17 #include "RooStats/ModelConfig.h"
18 
19 #include "utilities.hpp"
20 
21 using namespace std;
22 
25 poisson_distribution<> WorkspaceGenerator::dist_(1.);
26 
28  const set<Block> &blocks,
29  const set<Process> &backgrounds,
30  const Process &signal,
31  const Process &data,
32  const string &systematics_file,
33  const bool use_r4, const double sig_strength, const double sig_xsec_f):
34  baseline_(baseline),
35  backgrounds_(backgrounds),
36  signal_(signal),
37  data_(data),
38  injection_(),
39  inject_other_signal_(false),
40  blocks_(blocks),
41  obs_vals_(),
42  obs_gens_(),
43  systematics_file_(systematics_file),
44  use_r4_(use_r4),
45  sig_strength_(sig_strength),
46  sig_xsec_f_(sig_xsec_f),
47  rmax_(20.),
48  w_("w"),
49  poi_(),
50  observables_(),
51  glob_observables_(),
52  nuisances_(),
53  systematics_(),
54  free_systematics_(),
55  luminosity_(4.),
56  print_level_(PrintLevel::important),
57  do_systematics_(true),
58  do_dilepton_(false),
59  do_mc_kappa_correction_(true),
60  num_toys_(0),
61  gaus_approx_(true),
62  w_is_valid_(false){
63  w_.cd();
64 }
65 
67  if(print_level_ >= PrintLevel::everything) DBG(file_name);
69  w_.writeToFile(file_name.c_str());
71  DBG("");
72  w_.Print();
73  }
75  cout << *this << endl;
76  }
78  cout << endl << "Wrote workspace to file " << file_name << endl<< endl;
79  }
80 }
81 
83  return luminosity_;
84 }
85 
87  if(luminosity != luminosity_){
88  luminosity_ = luminosity;
89  w_is_valid_ = false;
90  }
91  return *this;
92 }
93 
95  return do_systematics_;
96 }
97 
99  if(do_systematics != do_systematics_){
101  w_is_valid_ = false;
102  }
103  return *this;
104 }
105 
107  return do_dilepton_;
108 }
109 
111  if(do_dilepton != do_dilepton_){
112  do_dilepton_ = do_dilepton;
113  w_is_valid_ = false;
114  }
115  return *this;
116 }
117 
119  return print_level_;
120 }
121 
123  print_level_ = print_level;
124  return *this;
125 }
126 
129 }
130 
132  if(do_mc_kappa_correction_ != do_kappa_correction){
133  do_mc_kappa_correction_ = do_kappa_correction;
134  w_is_valid_ = false;
135  }
136  return *this;
137 }
138 
140  return rmax_;
141 }
142 
144  if(rmax != rmax_){
145  rmax_ = rmax;
146  w_is_valid_ = false;
147  }
148  return *this;
149 }
150 
152  return gaus_approx_;
153 }
154 
156  gaus_approx_ = use_gaus_approx;
157  return *this;
158 }
159 
162  return yields_.GetYield(key);
163 }
164 
166  const Process &process,
167  const Cut &cut) const{
168  return GetYield(YieldKey(bin, process, cut));
169 }
170 
172  const Process &process) const{
173  return GetYield(bin, process, baseline_);
174 }
175 
176 size_t WorkspaceGenerator::AddToys(size_t num_toys){
177  if(print_level_ >= PrintLevel::everything) DBG(num_toys);
179  if(num_toys == 0) return num_toys_;
180  const RooArgSet *obs_orig = w_.set("observables");
181  if(obs_orig == nullptr) ERROR("Could not get observables list for toy generation");
182  RooArgSet obs(*obs_orig);
183  SetupToys(obs);
184  for(size_t itoy = num_toys_; itoy < num_toys_+num_toys; ++itoy){
185  GenerateToys(obs);
186  RooDataSet data_new(("data_obs_"+to_string(itoy)).c_str(), ("data_obs_"+to_string(itoy)).c_str(), obs);
187  data_new.add(obs);
188  w_.import(data_new);
189  }
190  ResetToys(obs);
191  num_toys_ += num_toys;
192  return num_toys_;
193 }
194 
195 
196 
199  return injection_;
200  }else{
201  return signal_;
202  }
203 }
204 
206  inject_other_signal_ = true;
207  injection_ = injection;
208  return *this;
209 }
210 
212  return inject_other_signal_;
213 }
214 
216  inject_other_signal_ = false;
217  return *this;
218 }
219 
220 void WorkspaceGenerator::SetupToys(const RooArgSet &obs){
222  obs_vals_.clear();
223  obs_gens_.clear();
224  TIterator *iter_ptr = obs.createIterator();
225  if(iter_ptr == nullptr) ERROR("Could not generator iterator to set up toys");
226  for(; iter_ptr != nullptr && *(*iter_ptr) != nullptr; iter_ptr->Next()){
227  RooAbsReal *arg = static_cast<RooAbsReal*>(*(*iter_ptr));
228  if(arg == nullptr) continue;
229  string name = arg->GetName();
230  if(Contains(name,"nobsmc")) continue;
231  double value = arg->getVal();
232  obs_vals_[name] = value;
233  obs_gens_[name] = poisson_distribution<>(value);
234  }
235  iter_ptr->Reset();
236 }
237 
238 void WorkspaceGenerator::GenerateToys(RooArgSet &obs){
240  TIterator *iter_ptr = obs.createIterator();
241  if(iter_ptr == nullptr) ERROR("Could not generator iterator to set up toys");
242  for(; iter_ptr != nullptr && *(*iter_ptr) != nullptr; iter_ptr->Next()){
243  RooRealVar *arg = static_cast<RooRealVar*>(*(*iter_ptr));
244  if(arg == nullptr) continue;
245  string name = arg->GetName();
246  if(Contains(name,"nobsmc")) continue;
247  arg->setVal(obs_gens_[name](prng_));
248  }
249  iter_ptr->Reset();
250 }
251 
252 void WorkspaceGenerator::ResetToys(RooArgSet &obs){
254  TIterator *iter_ptr = obs.createIterator();
255  if(iter_ptr == nullptr) ERROR("Could not generator iterator to set up toys");
256  for(; iter_ptr != nullptr && *(*iter_ptr) != nullptr; iter_ptr->Next()){
257  RooRealVar *arg = static_cast<RooRealVar*>(*(*iter_ptr));
258  if(arg == nullptr) continue;
259  string name = arg->GetName();
260  if(Contains(name,"nobsmc")) continue;
261  double value = obs_vals_.at(name);
262  arg->setVal(value);
263  }
264  iter_ptr->Reset();
265 }
266 
268  array<int, 128> sd;
269  random_device r;
270  generate_n(sd.begin(), sd.size(), ref(r));
271  seed_seq ss(begin(sd), end(sd));
272  return mt19937_64(ss);
273 }
274 
276  using param_t = decltype(dist_)::param_type;
277  dist_.param(param_t{rate});
278  return dist_(prng_);
279 }
280 
283  string old_name = w_.GetName();
284  w_.Delete();
285  gDirectory->Delete(old_name.c_str());
286  w_.Clear();
287  w_ = RooWorkspace("w");
288  w_.SetName("w");
289  w_.cd();
290 
291  if(do_dilepton_){
293  }
294  if(do_systematics_){
296  }
297  AddPOI();
299 
300  for(const auto &block: blocks_){
301  AddData(block);
302  AddMCYields(block);
303  AddMCPdfs(block);
304  AddMCProcessSums(block);
305  AddBackgroundFractions(block);
306  AddABCDParameters(block);
310  AddSignalPredictions(block);
311  AddPdfs(block);
312  AddDebug(block);
313  }
314 
315  // AddDummyNuisance();
316  AddFullPdf();
318  AddModels();
319 
320  w_is_valid_ = true;
321 }
322 
325  w_.factory(("r[1.,0.,"+to_string(rmax_)+"]").c_str());
326  Append(poi_, "r");
327 }
328 
330  if(systematics_file_ == "") return;
331  ifstream file(systematics_file_);
332  vector<string> lines;
333  string one_line;
334  while(getline(file, one_line)){
335  CleanLine(one_line);
336  if(one_line != ""){
337  lines.push_back(one_line);
338  }
339  }
340 
341  vector<vector<string> > words;
342  for(const auto &line: lines){
343  vector<string> these_words = Tokenize(line);
344  words.push_back(these_words);
345  }
346 
347  auto all_prc = backgrounds_;
348  Append(all_prc, signal_);
349  string syst_name;
350  auto process_list = all_prc;
351  process_list.clear();
352 
353  free_systematics_.clear();
354  FreeSystematic this_systematic("BADBADBADBADBADBADBADBADBAD");
355  bool ready = false;
356  for(const auto &line: words){
357  if(line.size() < 2){
358  string out;
359  for(const auto &word: line) out += word;
360  ERROR("Bad systematics line: "+out);
361  }
362  if(line.at(0) == "SYSTEMATIC"){
363  if(ready){
364  Append(free_systematics_, this_systematic);
365  }
366  this_systematic = FreeSystematic(line.at(1));
367  ready = true;
368  }else if(line[0] == "PROCESSES"){
369  process_list.clear();
370  for(size_t iword = 1; iword < line.size(); ++iword){
371  bool found = false;
372  vector<string> names = Tokenize(line.at(iword), ", ");
373  for(const auto &name: names){
374  for(const auto &prc: all_prc){
375  if(name == prc.Name()){
376  Append(process_list, prc);
377  found = true;
378  }
379  }
380  if(!found){
381  ERROR("Systematic "+this_systematic.Name()
382  +" could not be applied to process "+line.at(iword));
383  }
384  }
385  }
386  }else{
387  bool found = false;
388  string clean_line(line.at(0));
389  ReplaceAll(clean_line, " ", "");
390  ReplaceAll(clean_line, "\t", "");
391  for(const auto &block: blocks_){
392  for(const auto &vbin: block.Bins()){
393  for(const auto &bin: vbin){
394  if(bin.Name() != clean_line) continue;
395  for(const auto &prc: process_list){
396  float syst(atof(line.at(1).c_str()));
397  if(isnan(syst)){
398  DBG("Systematic " << this_systematic.Name() << " is NaN for bin "
399  << bin.Name() << ", process " << prc.Name());
400  syst = 0.;
401  }
402  if(isinf(syst)){
403  DBG("Systematic " << this_systematic.Name() << " is infinite for bin "
404  << bin.Name() << ", process " << prc.Name());
405  if(syst>0.){
406  syst = 1.;
407  }else{
408  syst = -1.;
409  }
410  }
411  if(syst>=0) this_systematic.Strength(bin, prc) = log(1+syst);
412  else this_systematic.Strength(bin, prc) = -log(1+fabs(syst));
413  found = true;
414  }
415 
416  }
417  }
418  }
419  if(!found){
420  ERROR("Systematic "+this_systematic.Name()
421  +" could not be applied to bin "+line.at(0));
422  }
423  }
424  }
425  if(ready){
426  Append(free_systematics_, this_systematic);
427  }
428 }
429 
430 void WorkspaceGenerator::CleanLine(string &line){
431  ReplaceAll(line, "=", "");
432  string old = line;
433  do{
434  old = line;
435  ReplaceAll(line, " ", " ");
436  } while (line != old);
437  while(line.size() > 0 && line[0] == ' '){
438  line = line.substr(1);
439  }
440  if(line.size() > 0 && line[0] == '#'){
441  line = "";
442  }
443 }
444 
447 
448  set<Block> new_blocks;
449  for(const auto &block: blocks_){
450  Block new_block = block;
451  for(auto &vbin: new_block.Bins()){
452  for(auto &bin: vbin){
453  if(!NeedsDileptonBin(bin)) continue;
454  Bin dilep_bin = bin;
455  Cut dilep_baseline = baseline_;
456  MakeDileptonBin(bin, dilep_bin, dilep_baseline);
457  GammaParams dilep_gp(0., 0.);
458  if(dilep_bin.Blind()){
459  for(const auto &bkg: backgrounds_){
460  dilep_gp += GetYield(dilep_bin, bkg, dilep_baseline);
461  }
462  }else{
463  dilep_gp = GetYield(dilep_bin, data_, dilep_baseline);
464  }
465 
466  double strength = 1.;
467  string name = "dilep_"+bin.Name();
468  if(dilep_gp.Yield()>1.){
469  strength = 1./sqrt(dilep_gp.Yield());
470  }
471  Systematic syst(name, strength);
472  bin.AddSystematic(syst);
473  }
474  }
475  Append(new_blocks, new_block);
476  }
477  blocks_ = new_blocks;
478 }
479 
482  return Contains(static_cast<string>(bin.Cut()), "mt>")
483  && (Contains(static_cast<string>(bin.Cut()), "(nels+nmus)==1")
484  || Contains(static_cast<string>(bin.Cut()), "(nmus+nels)==1")
485  || Contains(static_cast<string>(bin.Cut()), "nels+nmus==1")
486  || Contains(static_cast<string>(bin.Cut()), "nmus+nels==1")
487  || Contains(static_cast<string>(bin.Cut()), "nleps==1")
488  || Contains(static_cast<string>(baseline_), "(nels+nmus)==1")
489  || Contains(static_cast<string>(baseline_), "(nmus+nels)==1")
490  || Contains(static_cast<string>(baseline_), "nels+nmus==1")
491  || Contains(static_cast<string>(baseline_), "nmus+nels==1")
492  || Contains(static_cast<string>(baseline_), "nleps==1"));
493 }
494 
495 void WorkspaceGenerator::MakeDileptonBin(const Bin &bin, Bin &dilep_bin, Cut &dilep_cut) const{
497  DBG(bin << ", " << dilep_bin << ", " << dilep_cut);
498  }
499  dilep_bin = bin;
500  dilep_bin.Name("dilep_"+dilep_bin.Name());
501  dilep_cut = baseline_;
502  dilep_bin.Cut().Replace("(nels+nmus)==1", "(nels+nmus)==2");
503  dilep_bin.Cut().Replace("(nmus+nels)==1", "(nmus+nels)==2");
504  dilep_bin.Cut().Replace("nels+nmus==1", "nels+nmus==2");
505  dilep_bin.Cut().Replace("nmus+nels==1", "nmus+nels==2");
506  dilep_bin.Cut().Replace("nleps==1", "nleps==2");
507  dilep_bin.Cut().RmCutOn("nbm", "nbm>=1&&nbm<=2");
508  dilep_bin.Cut().RmCutOn("met", "met>200&&met<=400");
509  dilep_bin.Cut().RmCutOn("mt");
510  dilep_cut.Replace("(nels+nmus)==1", "(nels+nmus)==2");
511  dilep_cut.Replace("(nmus+nels)==1", "(nmus+nels)==2");
512  dilep_cut.Replace("nels+nmus==1", "nels+nmus==2");
513  dilep_cut.Replace("nmus+nels==1", "nmus+nels==2");
514  dilep_cut.Replace("nleps==1", "nleps==2");
515  dilep_cut.RmCutOn("nbm", "nbm>=1&&nbm<=2");
516  dilep_cut.RmCutOn("met", "met>200&&met<=400");
517  dilep_cut.RmCutOn("mt");
518 }
519 
522  for(const auto &block: blocks_){
523  for(const auto &vbin: block.Bins()){
524  for(const auto &bin: vbin){
525  for(const auto &syst: bin.Systematics()){
526  AddSystematicGenerator(syst.Name());
527  string full_name = syst.Name()+"_BLK_"+block.Name()+"_BIN_"+bin.Name();
528  ostringstream oss;
529  oss << "strength_" << full_name << "[" << syst.Strength() << "]" << flush;
530  w_.factory(oss.str().c_str());
531  oss.str("");
532  oss << "expr::" << full_name
533  << "('exp(@0*@1)',strength_" << full_name << "," << syst.Name() << ")" << flush;
534  w_.factory(oss.str().c_str());
535  }
536  }
537  }
538  }
539 
540  auto all_prcs = backgrounds_;
541  Append(all_prcs, signal_);
542  for(const auto &bkg: all_prcs){
543  for(const auto &syst: bkg.Systematics()){
544  AddSystematicGenerator(syst.Name());
545  string full_name = syst.Name()+"_PRC_"+bkg.Name();
546  ostringstream oss;
547  oss << "strength_" << full_name << "[" << syst.Strength() << "]" << flush;
548  w_.factory(oss.str().c_str());
549  oss.str("");
550  oss << "expr::" << full_name
551  << "('exp(@0*@1)',strength_" << full_name << "," << syst.Name() << ")" << flush;
552  w_.factory(oss.str().c_str());
553  }
554  }
555 
556  for(const auto &syst: free_systematics_){
557  AddSystematicGenerator(syst.Name());
558  for(const auto &block: blocks_){
559  for(const auto &vbin: block.Bins()){
560  for(const auto &bin: vbin){
561  for(const auto &prc: all_prcs){
562  if(!syst.HasEntry(bin, prc)) continue;
563  string full_name = syst.Name()+"_BIN_"+bin.Name()+"_PRC_"+prc.Name();
564  ostringstream oss;
565  oss << "strength_" << full_name << "[" << syst.Strength(bin, prc) << "]" << flush;
566  w_.factory(oss.str().c_str());
567  oss.str("");
568  oss << "expr::" << full_name
569  << "('exp(@0*@1)',strength_" << full_name << "," << syst.Name() << ")" << flush;
570  w_.factory(oss.str().c_str());
571  }
572  }
573  }
574  }
575  }
576 }
577 
580  if(systematics_.find(name) != systematics_.end()) return;
581  ostringstream oss;
582  oss.str("");
583  oss << name << "_0" << flush;
584  Append(glob_observables_, oss.str());
585  oss << "[0.]" << flush;
586  w_.factory(oss.str().c_str());
587  w_.factory(("RooGaussian::constraint_"+name+"("+name+"[0.,-10.,10.],"+name+"_0,1.)").c_str());
588  Append(nuisances_, name);
589  Append(systematics_, name);
590 }
591 
594  for(const auto &vbin: block.Bins()){
595  for(const auto &bin: vbin){
596  GammaParams gps(0., 0.);
597  if(bin.Blind()){
598  for(const auto &bkg: backgrounds_){
599  gps += GetYield(bin, bkg);
600  }
601  // Injecting signal
603  gps += sig_strength_*GetYield(bin, injection_);
604  }else{
605  gps += sig_strength_*GetYield(bin, signal_);
606  }
607  }else{
608  gps = GetYield(bin, data_);
609  }
610 
611  ostringstream oss;
612  oss << "nobs_BLK_" << block.Name()
613  << "_BIN_" << bin.Name() << flush;
614  if(use_r4_ || !Contains(bin.Name(), "4")){
615  Append(observables_, oss.str());
616  } //attn
617  oss << "[" << gps.Yield() << "]" << flush;
618  w_.factory(oss.str().c_str());
619  }
620  }
621 }
622 
625  for(const auto &vbin: block.Bins()){
626  for(const auto &bin: vbin){
627  for(const auto &bkg: backgrounds_){
628  string var = "expr::frac_BIN_"+bin.Name()+"_PRC_"+bkg.Name()
629  +"('@0/@1',ymc_BLK_"+block.Name()+"_BIN_"+bin.Name()+"_PRC_"+bkg.Name()
630  +",ymc_BLK_"+block.Name()+"_BIN_"+bin.Name()+")";
631  w_.factory(var.c_str());
632  }
633  }
634  }
635 }
636 
640 
641  ostringstream rxss, ryss;
642  rxss << "sum::rxnorm_BLK_" << block.Name() << "(1.,";
643  ryss << "sum::rynorm_BLK_" << block.Name() << "(1.,";
644  ostringstream oss;
645  oss << "norm_BLK_" << block.Name() << flush;
646  // Append(nuisances_, oss.str());
647  oss << "[" << max(1., 0.8*by.Total().Yield()) << ",0.,"
648  << max(5.*by.Total().Yield(), 20.) << "]" << flush;
649  w_.factory(oss.str().c_str());
650  for(size_t irow = 0; irow < by.RowSums().size(); ++irow){
651  if(irow == by.MaxRow()) continue;
652  oss.str("");
653  oss << "ry" << (irow+1) << (by.MaxRow()+1) << "_BLK_" << block.Name() << flush;
654  ryss << "," << oss.str();
655  // Append(nuisances_, oss.str());
656  oss << "[" << by.RowSums().at(irow).Yield()/by.RowSums().at(by.MaxRow()).Yield()
657  << ",0.,10.]" << flush;
658  w_.factory(oss.str().c_str());
659  }
660  ryss << ")" << flush;
661  w_.factory(ryss.str().c_str());
662  for(size_t icol = 0; icol < by.ColSums().size(); ++icol){
663  if(icol == by.MaxCol()) continue;
664  oss.str("");
665  oss << "rx" << (icol+1) << (by.MaxCol()+1) << "_BLK_" << block.Name() << flush;
666  rxss << "," << oss.str();
667  // Append(nuisances_, oss.str()); /
668  oss << "[" << by.ColSums().at(icol).Yield()/by.ColSums().at(by.MaxCol()).Yield()
669  << ",0.,10.]" << flush;
670  w_.factory(oss.str().c_str());
671  }
672  rxss << ")" << flush;
673  w_.factory(rxss.str().c_str());
674  oss.str("");
675  oss << "prod::rnorm_BLK_" << block.Name()
676  << "(rxnorm_BLK_" << block.Name()
677  << ",rynorm_BLK_" << block.Name() << ")" << flush;
678  w_.factory(oss.str().c_str());
679  oss.str("");
680  oss << "expr::rscale_BLK_" << block.Name()
681  << "('@0/@1',norm_BLK_" << block.Name()
682  << ",rnorm_BLK_" << block.Name() << ")" << flush;
683  w_.factory(oss.str().c_str());
684 }
685 
689  size_t max_row = by.MaxRow();
690  size_t max_col = by.MaxCol();
691  for(size_t irow = 0; irow < block.Bins().size(); ++irow){
692  for(size_t icol = 0; icol < block.Bins().at(irow).size(); ++icol){
693  const Bin &bin = block.Bins().at(irow).at(icol);
694  string bb_name = "BLK_"+block.Name()+"_BIN_"+bin.Name();
695  vector<string> prod_list;
696  for(const auto &bkg: backgrounds_){
697  string prod_name = "rate_"+bb_name+"_PRC_"+bkg.Name();
698  Append(prod_list, prod_name);
699  string factory_string = "prod::"+prod_name+"(rscale_BLK_"+block.Name();
700  if(icol != max_col){
701  ostringstream oss;
702  oss << ",rx" << (icol+1) << (max_col+1) << "_BLK_" << block.Name() << flush;
703  factory_string += oss.str();
704  }
705  if(irow != max_row){
706  ostringstream oss;
707  oss << ",ry" << (irow+1) << (max_row+1) << "_BLK_" << block.Name() << flush;
708  factory_string += oss.str();
709  }
710  factory_string += (",frac_BIN_"+bin.Name()+"_PRC_"+bkg.Name());
711  if(do_systematics_){
712  for(const auto &syst: bkg.Systematics()){
713  factory_string += (","+syst.Name()+"_PRC_"+bkg.Name());
714  }
715  for(const auto &syst: free_systematics_){
716  if(syst.HasEntry(bin, bkg)){
717  factory_string += (","+syst.Name()+"_BIN_"+bin.Name()+"_PRC_"+bkg.Name());
718  }
719  }
720  }
721  factory_string += ")";
722  w_.factory(factory_string.c_str());
723  }
724  string factory_string="sum::nbkg_raw_"+bb_name+"(";
725  for(auto prod = prod_list.cbegin(); prod != prod_list.cend(); ++prod){
726  if(prod != prod_list.cbegin()) factory_string += ",";
727  factory_string += *prod;
728  }
729  factory_string += ")";
730  w_.factory(factory_string.c_str());
731  }
732  }
733 }
734 
737  AddMCRowSums(block);
738  AddMCColSums(block);
739  AddMCTotal(block);
740  AddMCPrediction(block);
741  AddMCKappa(block);
742 }
743 
746  for(const auto &vbin: block.Bins()){
747  for(const auto &bin: vbin){
748  string bb_name = "BLK_"+block.Name()+"_BIN_"+bin.Name();
749  ostringstream oss;
750  auto all_prcs = backgrounds_;
751  Append(all_prcs, signal_);
752  for(const auto &bkg: all_prcs){
753  GammaParams gp = GetYield(bin, bkg);
754  if(Contains(bkg.Name(), "sig")) gp *= sig_xsec_f_;
755  string bbp_name = bb_name + "_PRC_"+bkg.Name();
756  oss.str("");
757  oss << "nobsmc_" << bbp_name << flush;
758  Append(glob_observables_, oss.str());
759  oss << "[" << gp.NEffective() << "]" << flush;
760  w_.factory(oss.str().c_str());
761  oss.str("");
762  oss << "nmc_" << bbp_name << flush;
763  Append(nuisances_, oss.str());
764  oss << "[" << gp.NEffective()
765  << ",0.," << max(5.*gp.NEffective(), 20.) << "]" << flush;
766  w_.factory(oss.str().c_str());
767  oss.str("");
768  oss << "wmc_" << bbp_name << "[" << gp.Weight() << "]" << flush;
769  w_.factory(oss.str().c_str());
770  oss.str("");
771  oss << "prod::ymc_" << bbp_name
772  << "(nmc_" << bbp_name
773  << ",wmc_" << bbp_name << ")" << flush;
774  w_.factory(oss.str().c_str());
775  }
776  oss.str("");
777  }
778  }
779 }
780 
783  bool first = true;
784  string factory_string = "PROD::pdf_mc_"+block.Name()+"(";
785  for(const auto &vbin: block.Bins()){
786  for(const auto &bin: vbin){
787  auto all_prcs = backgrounds_;
788  Append(all_prcs, signal_);
789  for(const auto &bkg: all_prcs){
790  string bbp_name = "BLK_"+block.Name()+"_BIN_"+bin.Name()+"_PRC_"+bkg.Name();
791  AddPoisson("pdf_mc_"+bbp_name, "nobsmc_"+bbp_name, "nmc_"+bbp_name, gaus_approx_);
792  if(first) first = false;
793  else factory_string += ",";
794  factory_string += "pdf_mc_"+bbp_name;
795  }
796  }
797  }
798  factory_string += ")";
799  w_.factory(factory_string.c_str());
800 }
801 
804  for(const auto &vbin: block.Bins()){
805  for(const auto &bin: vbin){
806  ostringstream oss;
807  string bb_name = "BLK_"+block.Name()+"_BIN_"+bin.Name();
808  oss << "sum::ymc_" << bb_name << "(";
809  if(backgrounds_.size() > 0){
810  auto bkg = backgrounds_.cbegin();
811  string name = "ymc_"+bb_name+"_PRC_"+bkg->Name();
812  oss << name;
813  for(++bkg; bkg != backgrounds_.cend(); ++bkg){
814  name = "ymc_"+bb_name+"_PRC_"+bkg->Name();
815  oss << "," << name;
816  }
817  }
818  oss << ")" << flush;
819  w_.factory(oss.str().c_str());
820  }
821  }
822 }
823 
826  for(size_t irow = 0; irow < block.Bins().size(); ++irow){
827  ostringstream oss;
828  oss << "sum::rowmc" << (irow+1) << "_BLK_" << block.Name() << "(";
829  auto bin = block.Bins().at(irow).cbegin();
830  oss << "ymc_BLK_" << block.Name() << "_BIN_" << bin->Name();
831  for(++bin; bin != block.Bins().at(irow).cend(); ++bin){
832  oss << ",ymc_BLK_" << block.Name() << "_BIN_" << bin->Name();
833  }
834  oss << ")" << flush;
835  w_.factory(oss.str().c_str());
836  }
837 }
838 
841  if(block.Bins().size() > 0 && block.Bins().at(0).size() > 0){
842  for(size_t icol = 0; icol < block.Bins().at(0).size(); ++icol){
843  ostringstream oss;
844  oss << "sum::colmc" << (icol+1) << "_BLK_" << block.Name() << "(";
845  size_t irow = 0;
846  oss << "ymc_BLK_" << block.Name() << "_BIN_" << block.Bins().at(irow).at(icol).Name();
847  for(irow = 1; irow < block.Bins().size(); ++irow){
848  if(icol < block.Bins().at(irow).size()){
849  oss << ",ymc_BLK_" << block.Name() << "_BIN_" << block.Bins().at(irow).at(icol).Name();
850  }
851  }
852  oss << ")" << flush;;
853  w_.factory(oss.str().c_str());
854  }
855  }
856 }
857 
860  ostringstream oss;
861  oss << "sum::totmc_BLK_" << block.Name() << "(";
862  if(block.Bins().size() > 0){
863  oss << "rowmc1_BLK_" << block.Name();
864  for(size_t irow = 1; irow < block.Bins().size(); ++irow){
865  oss << ",rowmc" << (irow+1) << "_BLK_" << block.Name();
866  }
867  }
868  oss << ")" << flush;
869  w_.factory(oss.str().c_str());
870 }
871 
874  for(size_t irow = 0; irow < block.Bins().size(); ++irow){
875  for(size_t icol = 0; icol < block.Bins().at(irow).size(); ++icol){
876  const Bin &bin = block.Bins().at(irow).at(icol);
877  ostringstream oss;
878  oss << "expr::predmc_BLK_" << block.Name() << "_BIN_" << bin.Name() << "("
879  << "'(@0*@1)/@2',rowmc" << (irow+1) << "_BLK_" << block.Name()
880  << ",colmc" << (icol+1) << "_BLK_" << block.Name()
881  << ",totmc_BLK_" << block.Name() << ")" << flush;
882  w_.factory(oss.str().c_str());
883  }
884  }
885 }
886 
889  for(size_t irow = 0; irow < block.Bins().size(); ++irow){
890  for(size_t icol = 0; icol < block.Bins().at(irow).size(); ++icol){
891  const Bin &bin = block.Bins().at(irow).at(icol);
892  string bb_name = "BLK_"+block.Name()+"_BIN_"+bin.Name();
893  ostringstream oss;
894  oss << "expr::kappamc_" << bb_name << "("
895  << "'@0/@1',ymc_" << bb_name
896  << ",predmc_" << bb_name
897  << ")" << flush;
898  w_.factory(oss.str().c_str());
899  }
900  }
901 }
902 
905  for(const auto &vbin: block.Bins()){
906  for(const auto &bin: vbin){
907  string bb_name = "BLK_"+block.Name()+"_BIN_"+bin.Name();
908  ostringstream oss;
909  oss << "prod::nbkg_" << bb_name << "("
910  << "nbkg_raw_" << bb_name;
911  for(const auto &syst: bin.Systematics()){
912  if(do_systematics_ && syst.Name().substr(0,6) != "dilep_"){
913  oss << "," << syst.Name() << "_" << bb_name;
914  }
915  }
916  if(do_systematics_){
917  for(const auto &prc: backgrounds_){
918  for(const auto &syst: prc.Systematics()){
919  oss << "," << syst.Name() << "_BIN_" << bin.Name() << "_PRC_" << prc.Name();
920  }
921  }
922  }
924  oss << ",kappamc_" << bb_name;
925  }
926  oss << ")" << flush;
927  w_.factory(oss.str().c_str());
928  }
929  }
930 }
931 
934  for(const auto &vbin: block.Bins()){
935  for(const auto &bin: vbin){
936  ostringstream oss;
937  oss.str("");
938  oss << "prod::nsig_BLK_" << block.Name()
939  << "_BIN_" << bin.Name()
940  << "(r,"
941  << "ymc_BLK_" << block.Name()
942  << "_BIN_" << bin.Name()
943  << "_PRC_" << signal_.Name();
944  if(do_systematics_){
945  for(const auto &syst: signal_.Systematics()){
946  oss << "," << syst.Name() << "_BIN_" << bin.Name() << "_PRC_" << signal_.Name();
947  }
948  for(const auto &syst: free_systematics_){
949  if(!syst.HasEntry(bin, signal_)) continue;
950  oss << "," << syst.Name() << "_BIN_" << bin.Name() << "_PRC_" << signal_.Name();
951  }
952  }
953  oss << ")" << flush;
954  w_.factory(oss.str().c_str());
955  }
956  }
957 }
958 
961  string null_list = "", alt_list = "";
962  bool is_first = true;
963  for(const auto &vbin: block.Bins()){
964  for(const auto &bin: vbin){
965  if(!is_first){
966  null_list += ",";
967  alt_list += ",";
968  }
969  string bb_name = "_BLK_"+block.Name() +"_BIN_"+bin.Name();
970  string null_name = "pdf_null"+bb_name;
971  string alt_name = "pdf_alt"+bb_name;
972  w_.factory(("sum::nexp"+bb_name+"(nbkg"+bb_name+",nsig"+bb_name+")").c_str());
973  if(use_r4_ || !Contains(bb_name, "4")){
974  null_list += null_name;
975  alt_list += alt_name;
976  AddPoisson("pdf_null"+bb_name, "nobs"+bb_name, "nbkg"+bb_name, false);
977  AddPoisson("pdf_alt"+bb_name, "nobs"+bb_name, "nexp"+bb_name, false);
978  is_first = false;
979  }
980  }
981  }
982  w_.factory(("PROD:pdf_null_BLK_"+block.Name()+"("+null_list+")").c_str());
983  w_.factory(("PROD:pdf_alt_BLK_"+block.Name()+"("+alt_list+")").c_str());
984 }
985 
988  const auto &bins = block.Bins();
989  for(size_t iy = 1; iy < bins.size(); ++iy){
990  for(size_t ix = 1; ix < bins.at(iy).size(); ++ix){
991  const auto &r1 = "BLK_"+block.Name()+"_BIN_"+bins.at(0).at(0).Name();
992  const auto &r2 = "BLK_"+block.Name()+"_BIN_"+bins.at(0).at(ix).Name();
993  const auto &r3 = "BLK_"+block.Name()+"_BIN_"+bins.at(iy).at(0).Name();
994  const auto &r4 = "BLK_"+block.Name()+"_BIN_"+bins.at(iy).at(ix).Name();
995  w_.factory(("expr::syskappa_"+r4+"('(@0*@1)/(@2*@3)',nbkg_"+r4+",nbkg_"+r1+",nbkg_"+r2+",nbkg_"+r3+")").c_str());
996  w_.factory(("expr::nosyskappa_"+r4+"('(@0*@1)/(@2*@3)',ymc_"+r4+",ymc_"+r1+",ymc_"+r2+",ymc_"+r3+")").c_str());
997  }
998  }
999 }
1000 
1002  w_.factory("RooGaussian::pdf_dummy_nuisance(dummy_nuisance[0.,-10.,10.],0.,1.)");
1003  Append(nuisances_, "dummy_nuisance");
1004 }
1005 
1008  string null_list = "";//"pdf_dummy_nuisance";
1009  string alt_list = "";//"pdf_dummy_nuisance";
1010  bool is_first = true;
1011  for(const auto &block: blocks_){
1012  null_list += (is_first ? "pdf_null_BLK_" : ",pdf_null_BLK_") +block.Name();
1013  alt_list += (is_first ? "pdf_alt_BLK_" : ",pdf_alt_BLK_" ) +block.Name();
1014  is_first = false;
1015  }
1017  for(const auto &syst: systematics_){
1018  null_list += (",constraint_"+syst);
1019  alt_list += (",constraint_"+syst);
1020  }
1021  }
1022  for(const auto & block: blocks_){
1023  null_list += (",pdf_mc_"+block.Name());
1024  alt_list += (",pdf_mc_"+block.Name());
1025  }
1026  w_.factory(("PROD::model_b("+null_list+")").c_str());
1027  w_.factory(("PROD::model_s("+alt_list+")").c_str());
1028 }
1029 
1032  DefineParameterSet("POI", poi_);
1033  DefineParameterSet("nuisances", nuisances_);
1034  DefineParameterSet("observables", observables_);
1035  DefineParameterSet("globalObservables", glob_observables_);
1036  auto xxx = w_.set("observables");
1037  RooDataSet data_obs{"data_obs", "data_obs", *xxx};
1038  data_obs.add(*w_.set("observables"));
1039  w_.import(data_obs);
1040 }
1041 
1042 void WorkspaceGenerator::DefineParameterSet(const string &set_name,
1043  const set<string> &var_names){
1044  if(print_level_ >= PrintLevel::everything) DBG(set_name);
1045  if(var_names.size()==0){
1046  w_.defineSet(set_name.c_str(), "");
1047  }else{
1048  w_.defineSet(set_name.c_str(), var_names.cbegin()->c_str());
1049  for(auto name = ++var_names.cbegin();
1050  name != var_names.cend();
1051  ++name){
1052  w_.extendSet(set_name.c_str(), name->c_str());
1053  }
1054  }
1055 }
1056 
1059  RooStats::ModelConfig model_config("ModelConfig", &w_);
1060  model_config.SetPdf(*w_.pdf("model_s"));
1061  model_config.SetParametersOfInterest(*w_.set("POI"));
1062  model_config.SetObservables(*w_.set("observables"));
1063  model_config.SetNuisanceParameters(*w_.set("nuisances"));
1064  model_config.SetGlobalObservables(*w_.set("globalObservables"));
1065 
1066  RooStats::ModelConfig model_config_bonly("ModelConfig_bonly", &w_);
1067  model_config_bonly.SetPdf(*w_.pdf("model_b"));
1068  model_config_bonly.SetParametersOfInterest(*w_.set("POI"));
1069  model_config_bonly.SetObservables(*w_.set("observables"));
1070  model_config_bonly.SetNuisanceParameters(*w_.set("nuisances"));
1071  model_config_bonly.SetGlobalObservables(*w_.set("globalObservables"));
1072 
1073  w_.import(model_config);
1074  w_.import(model_config_bonly);
1075 }
1076 
1077 void WorkspaceGenerator::AddPoisson(const string &pdf_name,
1078  const string &n_name,
1079  const string &mu_name,
1080  bool allow_approx){
1081  RooAbsReal *v_mu = w_.var(mu_name.c_str());
1082  if(!v_mu) v_mu = w_.function(mu_name.c_str());
1083  if(!v_mu) v_mu = w_.var(n_name.c_str());
1084  if(!v_mu) v_mu = w_.function(n_name.c_str());
1085  double mu = v_mu->getVal();
1086  if(mu <= 50. || !allow_approx){
1087  w_.factory(("RooPoisson::"+pdf_name+"("+n_name+","+mu_name+")").c_str());
1088  (static_cast<RooPoisson*>(w_.pdf(pdf_name.c_str())))->setNoRounding();
1089  (static_cast<RooPoisson*>(w_.pdf(pdf_name.c_str())))->protectNegativeMean();
1090  }else{
1091  w_.factory(("expr::sqrt_"+mu_name+"('sqrt(@0)',"+mu_name+")").c_str());
1092  w_.factory(("RooGaussian::"+pdf_name+"("+n_name+","+mu_name+",sqrt_"+mu_name+")").c_str());
1093  }
1094 }
1095 
1096 ostream & operator<<(ostream& stream, const WorkspaceGenerator &wg){
1097  for(const auto &block: wg.blocks_){
1098  for(const auto &vbin: block.Bins()){
1099  for(const auto &bin: vbin){
1100  wg.PrintComparison(stream, bin, wg.data_, block);
1101  wg.PrintComparison(stream, bin, wg.signal_, block);
1102  for(const auto &bkg: wg.backgrounds_){
1103  wg.PrintComparison(stream, bin, bkg, block);
1104  }
1105  }
1106  }
1107  }
1108  return stream;
1109 }
1110 
1111 void WorkspaceGenerator::PrintComparison(ostream &stream, const Bin &bin,
1112  const Process &process, const Block &block) const{
1114  DBG(bin << ", " << process << ", " << block);
1115  }
1116 
1117  GammaParams gp(0., 0.);
1118  if(!(process.IsData() && bin.Blind())){
1119  gp = GetYield(bin, process);
1120  }
1121 
1122  ostringstream name;
1123  name << (process.IsData() ? "nobs" : process.IsSignal() ? "ymc" : "rate")
1124  << "_BLK_" << block.Name()
1125  << "_BIN_" << bin.Name();
1126  if(!process.IsData()){
1127  name << "_PRC_" << process.Name();
1128  }
1129  name << flush;
1130 
1131  stream << setw(64) << name.str() << ": "
1132  << setw(8) << gp.Yield()
1133  << " +- " << setw(8) << gp.CorrectedUncertainty()
1134  << " => ";
1135  RooAbsReal *fp = w_.function(name.str().c_str());
1136  if(fp){
1137  stream << setw(8) << fp->getVal() << endl;
1138  }else{
1139  stream << "Not found" << endl;
1140  }
1141 }
void Append(T &collection, const typename T::value_type &value)
Definition: utilities.hpp:48
WorkspaceGenerator & SetLuminosity(double luminosity)
double Weight() const
void SetupToys(const RooArgSet &obs)
std::set< std::string > observables_
size_t MaxRow() const
double CorrectedUncertainty() const
void AddFullBackgroundPredictions(const Block &block)
WorkspaceGenerator(const Cut &baseline, const std::set< Block > &blocks, const std::set< Process > &backgrounds, const Process &signal, const Process &data, const std::string &systematics_file="", const bool use_r4=true, const double sig_strength=0., const double sig_xsec_f=1.)
Definition: bin.hpp:12
#define DBG(x)
Definition: utilities.hpp:16
WorkspaceGenerator & SetRMax(double rmax)
const std::string & Name() const
Definition: process.cpp:52
std::set< std::string > poi_
Cut & RmCutOn(const Cut &to_rm, const Cut &rep=Cut())
Definition: cut.cpp:31
void AddRawBackgroundPredictions(const Block &block)
WorkspaceGenerator & SetDoSystematics(bool do_systematics)
void AddMCTotal(const Block &block)
std::set< std::string > nuisances_
const SystCollection & Systematics() const
Definition: process.cpp:110
WorkspaceGenerator & SetInjectionModel(const Process &injection)
void MakeDileptonBin(const Bin &bin, Bin &dilep_bin, Cut &dilep_cut) const
Definition: cut.hpp:8
void AddMCRowSums(const Block &block)
double Strength(const Bin &bin, const Process &process) const
Cut & Replace(const Cut &orig, const Cut &rep)
Definition: cut.cpp:17
void ReplaceAll(std::string &str, const std::string &orig, const std::string &rep)
Definition: utilities.cpp:34
STL namespace.
bool Contains(const std::string &str, const std::string &pat)
Definition: utilities.cpp:26
static void CleanLine(std::string &line)
bool GetDefaultInjectionModel() const
bool GetDoSystematics() const
friend std::ostream & operator<<(std::ostream &stream, const WorkspaceGenerator &wg)
std::vector< GammaParams > RowSums() const
std::map< std::string, std::poisson_distribution<> > obs_gens_
static std::mt19937_64 prng_
void AddKappas(const Block &block)
void AddMCPrediction(const Block &block)
void AddMCKappa(const Block &block)
std::map< std::string, double > obs_vals_
const bool & IsData() const
Definition: process.cpp:86
std::tuple< Bin, Process, Cut > YieldKey
Definition: yield_key.hpp:11
WorkspaceGenerator & SetKappaCorrected(bool do_kappa_correction)
void AddSignalPredictions(const Block &block)
void AddSystematicGenerator(const std::string &name)
std::set< std::string > systematics_
size_t MaxCol() const
WorkspaceGenerator & SetDoDilepton(bool do_systematics)
void AddABCDParameters(const Block &block)
const class Cut & Cut() const
Definition: bin.cpp:28
#define ERROR(x)
Definition: utilities.hpp:15
void AddMCColSums(const Block &block)
void WriteToFile(const std::string &file_name)
GammaParams Total() const
double Yield() const
void AddMCYields(const Block &block)
int rmax
Definition: change_r.py:20
bool NeedsDileptonBin(const Bin &bin) const
static int GetPoisson(double rate)
Definition: block.hpp:12
std::set< std::string > glob_observables_
void DefineParameterSet(const std::string &cat_name, const std::set< std::string > &var_names)
static std::poisson_distribution dist_
static YieldManager yields_
std::set< Block > blocks_
std::set< FreeSystematic > free_systematics_
void AddPdfs(const Block &block)
void GenerateToys(RooArgSet &obs)
const bool & IsSignal() const
Definition: process.cpp:94
GammaParams GetYield(const YieldKey &key) const
const Process & GetInjectionModel() const
void PrintComparison(std::ostream &stream, const Bin &bin, const Process &process, const Block &block) const
void ResetToys(RooArgSet &obs)
void AddData(const Block &block)
void AddMCPdfs(const Block &block)
std::set< Process > backgrounds_
const std::string & Name() const
Definition: block.cpp:19
const std::string & Name() const
Definition: bin.cpp:19
PrintLevel GetPrintLevel() const
GammaParams GetYield(const YieldKey &key) const
const std::vector< std::vector< Bin > > & Bins() const
Definition: block.cpp:28
WorkspaceGenerator & SetDefaultInjectionModel()
void AddMCProcessSums(const Block &block)
const double & Luminosity() const
void AddBackgroundFractions(const Block &block)
WorkspaceGenerator & SetPrintLevel(PrintLevel print_level)
bool GetKappaCorrected() const
double NEffective() const
const std::string & Name() const
void AddDebug(const Block &block)
double GetLuminosity() const
std::vector< GammaParams > ColSums() const
static std::mt19937_64 InitializePRNG()
bool Blind() const
Definition: bin.cpp:36
size_t AddToys(size_t num_toys=0)
std::vector< std::string > Tokenize(const std::string &input, const std::string &tokens=" ")
Definition: utilities.cpp:101
void AddPoisson(const std::string &pdf_name, const std::string &n_name, const std::string &mu_name, bool allow_approx)