CMS 3D CMS Logo

TagProbeFitter.cc
Go to the documentation of this file.
2 #include <stdexcept>
3 //#include "TagProbeFitter.h"
4 
5 #include "TROOT.h"
6 #include "TFile.h"
7 #include "TPad.h"
8 #include "TText.h"
9 #include "TCanvas.h"
10 #include "TGraphAsymmErrors.h"
11 #include "TH2F.h"
12 #include "TStyle.h"
13 #include "Math/QuantFuncMathCore.h"
14 #include "Roo1DTable.h"
15 #include "RooAbsDataStore.h"
16 #include "RooAbsReal.h"
17 #include "RooAddPdf.h"
18 #include "RooBinning.h"
19 #include "RooBinningCategory.h"
20 #include "RooCategory.h"
21 #include "RooChebychev.h"
22 #include "RooDataHist.h"
23 #include "RooDataSet.h"
24 #include "RooEfficiency.h"
25 #include "RooExtendPdf.h"
26 #include "RooFitResult.h"
27 #include "RooFormulaVar.h"
28 #include "RooGaussian.h"
29 #include "RooGenericPdf.h"
30 #include "RooGlobalFunc.h"
31 #include "RooLinkedListIter.h"
32 #include "RooMappedCategory.h"
33 #include "RooMinimizer.h"
34 #include "RooMinuit.h"
35 #include "RooMsgService.h"
36 #include "RooMultiCategory.h"
37 #include "RooNLLVar.h"
38 #include "RooNumIntConfig.h"
39 #include "RooPlot.h"
40 #include "RooProdPdf.h"
41 #include "RooProfileLL.h"
42 #include "RooRealVar.h"
43 #include "RooSimultaneous.h"
44 #include "RooThresholdCategory.h"
45 #include "RooTrace.h"
46 #include "RooWorkspace.h"
47 #include "RooTreeDataStore.h"
48 
49 using namespace std;
50 using namespace RooFit;
51 
52 TagProbeFitter::TagProbeFitter(const std::vector<std::string>& inputFileNames, string inputDirectoryName, string inputTreeName, string outputFileName, int numCPU_, bool saveWorkspace_, bool floatShapeParameters_, const std::vector<std::string>& fixVars_){
53  inputTree = new TChain((inputDirectoryName+"/"+inputTreeName).c_str());
54  for(size_t i=0; i<inputFileNames.size(); i++){
55  inputTree->Add(inputFileNames[i].c_str());
56  }
57  outputFile = new TFile(outputFileName.c_str(),"recreate");
58  outputDirectory = outputFile->mkdir(inputDirectoryName.c_str());
59  numCPU = numCPU_;
60  saveWorkspace = saveWorkspace_;
61  massBins = 0; // automatic default
62  floatShapeParameters = floatShapeParameters_;
63  fixVars = fixVars_;
64  weightVar = "";
65  if(!floatShapeParameters && fixVars.empty()) std::cout << "TagProbeFitter: " << "You wnat to fix some variables but do not specify them!";
66 
67  gROOT->SetStyle("Plain");
68  gStyle->SetTitleFillColor(0);
69  gStyle->SetPalette(1);
70  gStyle->SetOptStat(0);
71  gStyle->SetPaintTextFormat(".2f");
72 
73  quiet = false;
74 
75  binnedFit = false;
76 
77  doSaveDistributionsPlot = true;
78 
79  // make integration very precise
80  RooAbsReal::defaultIntegratorConfig()->setEpsAbs(1e-13);
81  RooAbsReal::defaultIntegratorConfig()->setEpsRel(1e-13);
82 
83  split_mode = 0;
84 }
85 
87  if(inputTree)
88  delete inputTree;
89  if(outputFile)
90  outputFile->Close();
91 }
92 
93 void TagProbeFitter::setQuiet(bool quiet_) {
94  quiet = quiet_;
95  if (quiet) {
96  RooMsgService::instance().setGlobalKillBelow(RooFit::ERROR);
97  } else {
98  RooMsgService::instance().setGlobalKillBelow(RooFit::WARNING);
99  }
100 }
101 
102 void TagProbeFitter::setSplitMode(unsigned int nevents) {
103  split_mode = nevents;
104 }
105 
106 bool TagProbeFitter::addVariable(string name, string title, double low, double hi, string units){
107  RooRealVar temp(name.c_str(), title.c_str(), low, hi, units.c_str());
108  temp.setBins(5000,"cache");
109  variables.addClone(temp);
110  return true;
111 }
112 
113 bool TagProbeFitter::addCategory(string name, string title, string expression){
114  RooCategory* c = (RooCategory*) parameterParser.factory(expression.c_str());
115  if(!c)
116  return false;
117  //set the name of the category to the passed name instead of the one in the expression
118  c->SetName(name.c_str());
119  c->SetTitle(title.c_str());
120  variables.addClone(*c);
121  return true;
122 }
123 
124 bool TagProbeFitter::addExpression(string expressionName, string title, string expression, const std::vector<string>& arguments) {
125  expressionVars.push_back(make_pair(make_pair(expressionName,title), make_pair(expression,arguments)));
126  return true;
127 }
128 
129 
130 bool TagProbeFitter::addThresholdCategory(string categoryName, string title, string varName, double cutValue){
131  thresholdCategories.push_back(make_pair(make_pair(categoryName,title), make_pair(varName,cutValue)));
132  return true;
133 }
134 
135 
136 void TagProbeFitter::addPdf(string name, vector<string>& pdfCommands){
137  pdfs[name] = pdfCommands;
138 }
139 
141  massBins = bins;
142 }
143 
145  weightVar = var;
146 }
147 
148 string TagProbeFitter::calculateEfficiency(string dirName,const std::vector<string>& effCats,const std::vector<string>& effStates, vector<string>& unbinnedVariables, map<string, vector<double> >& binnedReals, map<string, std::vector<string> >& binnedCategories, vector<string>& binToPDFmap){
149  //go to home directory
150  outputDirectory->cd();
151  //make a directory corresponding to this efficiency binning
152  gDirectory->mkdir(dirName.c_str())->cd();
153 
154  RooArgSet dataVars;
155 
156  //collect unbinned variables
157  for(vector<string>::iterator v=unbinnedVariables.begin(); v!=unbinnedVariables.end(); v++){
158  dataVars.addClone(variables[v->c_str()], true);
159  if (binnedFit && (v == unbinnedVariables.begin())) {
160  ((RooRealVar&)dataVars[v->c_str()]).setBins(massBins);
161  }
162  }
163  //collect the binned variables and the corresponding bin categories
164  RooArgSet binnedVariables;
165  RooArgSet binCategories;
166  for(map<string, vector<double> >::iterator v=binnedReals.begin(); v!=binnedReals.end(); v++){
167  TString name = v->first;
168  if (variables.find(name) == nullptr) { cerr << "Binned variable '"<<name<<"' not found." << endl; return "Error"; }
169  binnedVariables.add(*dataVars.addClone(variables[name]));
170  ((RooRealVar&)binnedVariables[name]).setBinning( RooBinning(v->second.size()-1, &v->second[0]) );
171  binCategories.addClone( RooBinningCategory(name+"_bins", name+"_bins", (RooRealVar&)binnedVariables[name]) );
172  }
173 
174  //collect the category variables and the corresponding mapped categories
175  RooArgSet categories;
176  RooArgSet mappedCategories;
177  for(map<string, vector<string> >::iterator v=binnedCategories.begin(); v!=binnedCategories.end(); v++){
178  TString name = v->first;
179  if (variables.find(name) == nullptr) { cerr << "Binned category '"<<name<<"' not found." << endl; return "Error"; }
180  categories.add(*dataVars.addClone(variables[name]));
181  mappedCategories.addClone(RooMappedCategory(name+"_bins", name+"_bins", (RooCategory&)categories[name]));
182  for(unsigned int i = 0; i<v->second.size(); i++){
183  ((RooMappedCategory&)mappedCategories[name+"_bins"]).map(v->second[i].c_str(), name+"_"+TString(v->second[i].c_str()).ReplaceAll(",","_"));
184  }
185  }
186 
187  // add the efficiency category if it's not a dynamic one
188  for (vector<string>::const_iterator effCat = effCats.begin(); effCat != effCats.end(); ++effCat) {
189  if (variables.find(effCat->c_str()) != nullptr) {
190  dataVars.addClone(variables[effCat->c_str()], true);
191  }
192  }
193 
194  // add all variables used in expressions
195  for(vector<pair<pair<string,string>, pair<string, vector<string> > > >::const_iterator ev = expressionVars.begin(), eve = expressionVars.end(); ev != eve; ++ev){
196  for (vector<string>::const_iterator it = ev->second.second.begin(), ed = ev->second.second.end(); it != ed; ++it) {
197  // provided that they are real variables themselves
198  if (variables.find(it->c_str())) dataVars.addClone(variables[it->c_str()], true);
199  }
200  }
201  // add all real variables used in cuts
202  for(vector<pair<pair<string,string>, pair<string, double> > >::const_iterator tc = thresholdCategories.begin(), tce = thresholdCategories.end(); tc != tce; ++tc){
203  if (variables.find(tc->second.first.c_str())) dataVars.addClone(variables[tc->second.first.c_str()], true);
204  }
205 
206 
207  //now add the necessary mass and passing variables to make the unbinned RooDataSet
208  RooDataSet* data(nullptr);
209  if (not split_mode){
210  data = new RooDataSet("data", "data", inputTree,
211  dataVars,
212  /*selExpr=*/"", /*wgtVarName=*/(weightVar.empty() ? nullptr : weightVar.c_str()));
213 
214  // Now add all expressions that are computed dynamically
215  for(vector<pair<pair<string,string>, pair<string, vector<string> > > >::const_iterator ev = expressionVars.begin(), eve = expressionVars.end(); ev != eve; ++ev){
216  RooArgList args;
217  for (vector<string>::const_iterator it = ev->second.second.begin(), ed = ev->second.second.end(); it != ed; ++it) {
218  args.add(dataVars[it->c_str()]);
219  }
220  RooFormulaVar expr(ev->first.first.c_str(), ev->first.second.c_str(), ev->second.first.c_str(), args);
221  RooRealVar *col = (RooRealVar *) data->addColumn(expr);
222  dataVars.addClone(*col);
223  }
224 
225  // And add all dynamic categories from thresholds
226  for(vector<pair<pair<string,string>, pair<string, double> > >::const_iterator tc = thresholdCategories.begin(), tce = thresholdCategories.end(); tc != tce; ++tc){
227  RooThresholdCategory tmp(tc->first.first.c_str(), tc->first.second.c_str(), (RooAbsReal &)dataVars[tc->second.first.c_str()], "above", 1);
228  tmp.addThreshold(tc->second.second, "below",0);
229  RooCategory *cat = (RooCategory *) data->addColumn(tmp);
230  dataVars.addClone(*cat);
231  }
232  }
233 
234  //merge the bin categories to a MultiCategory for convenience
235  RooMultiCategory allCats("allCats", "allCats", RooArgSet(binCategories, mappedCategories));
236  string effName;
237 
238  if (not split_mode){
239  data->addColumn(allCats);
240  //setup the efficiency category
241  if (effCats.size() == 1) {
242  effName = effCats.front() + "::" + effStates.front();
243  RooMappedCategory efficiencyCategory("_efficiencyCategory_", "_efficiencyCategory_", (RooCategory&)dataVars[effCats.front().c_str()], "Failed");
244  efficiencyCategory.map(effStates.front().c_str(), "Passed");
245  data->addColumn( efficiencyCategory );
246  } else {
247  RooArgSet rooEffCats;
248  string multiState = "{";
249  for (size_t i = 0; i < effCats.size(); ++i) {
250  if (i) { multiState += ";"; effName += " && "; }
251  rooEffCats.add((RooCategory &) dataVars[effCats[i].c_str()]);
252  multiState += effStates[i];
253  effName = effCats[i] + "::" + effStates[i];
254  }
255  multiState += "}";
256  RooMultiCategory efficiencyMultiCategory("_efficiencyMultiCategory_", "_efficiencyMultiCategory_", rooEffCats);
257  RooMappedCategory efficiencyCategory("_efficiencyCategory_", "_efficiencyCategory_", efficiencyMultiCategory, "Failed");
258  efficiencyCategory.map(multiState.c_str(), "Passed");
259  data->addColumn( efficiencyCategory );
260  }
261  }
262 
263  //setup the pdf category
264  RooMappedCategory pdfCategory("_pdfCategory_", "_pdfCategory_", allCats, (!binToPDFmap.empty())?binToPDFmap[0].c_str():"all");
265  for(unsigned int i = 1; i<binToPDFmap.size(); i+=2){
266  pdfCategory.map(binToPDFmap[i].c_str(), binToPDFmap[i+1].c_str());
267  }
268  if (not split_mode) data->addColumn( pdfCategory );
269 
270  //create the empty efficiency datasets from the binned variables
271  RooRealVar efficiency("efficiency", "Efficiency", 0, 1);
272 
273  RooDataSet fitEfficiency("fit_eff", "Efficiency from unbinned ML fit", RooArgSet(RooArgSet(binnedVariables, categories), efficiency), StoreAsymError(RooArgSet(binnedVariables, efficiency)));
274 
275  RooDataSet cntEfficiency("cnt_eff", "Efficiency from counting", RooArgSet(RooArgSet(binnedVariables, categories), efficiency), StoreAsymError(RooArgSet(binnedVariables, efficiency)));
276 
277  if (not split_mode){
278  if(!floatShapeParameters){
279  //fitting whole dataset to get initial values for some parameters
280  RooWorkspace* w = new RooWorkspace();
281  w->import(*data);
282  efficiency.setVal(0);//reset
283  efficiency.setAsymError(0,0);
284  std::cout << "ALL dataset: calling doFitEfficiency with pdf: " << pdfCategory.getLabel() << std::endl;
285  doFitEfficiency(w, pdfCategory.getLabel(), efficiency);
286  delete w;
287  }
288  } else {
289  // disactive not needed branches
290  inputTree->SetBranchStatus("*", false);
291  TIterator* iter = dataVars.createIterator();
292  TObject* obj(nullptr);
293  while ( (obj = iter->Next()) )
294  inputTree->SetBranchStatus(obj->GetName(),true);
295  }
296 
297  // loop over all bins with the help of allCats
298  // store index values in a separate vector to avoid issues
299  // with iteration over changing allCats object
300  std::vector<Int_t> allCatValues;
301  TIterator* it = allCats.typeIterator();
302  for(RooCatType* t = (RooCatType*)it->Next(); t!=nullptr; t = (RooCatType*)it->Next() )
303  allCatValues.push_back(t->getVal());
304  for (auto iCat : allCatValues){
305  const RooCatType* t = allCats.lookupType(iCat);
306  //name of the multicategory
307  TString catName = t->GetName();
308  //skip unmapped states
309  if(catName.Contains("NotMapped")) continue;
310 
311  RooDataSet* data_bin(nullptr);
312  RooArgSet tmpVars;
313 
314  if (not split_mode){
315  //create the dataset
316  data_bin = (RooDataSet*) data->reduce(Cut(TString::Format("allCats==%d",iCat)));
317  } else {
318  data_bin = new RooDataSet("data", "data",
319  dataVars,
320  (weightVar.empty() ? nullptr : weightVar.c_str()));
321 
322  TDirectory* tmp = gDirectory;
323  gROOT->cd();
324 
325  // loop over input data and fill the dataset with events for
326  // current category
327  unsigned int n_entries = inputTree->GetEntries();
328  printf("Input number of events: %u\n", n_entries);
329  unsigned int first_entry = 0;
330  while (first_entry<n_entries){
331  TTree* copyTree = inputTree->CopyTree("","",split_mode,first_entry);
332  RooTreeDataStore store("reader","reader",dataVars,*copyTree,
333  /*selExpr=*/"", /*wgtVarName=*/(weightVar.empty() ? nullptr : weightVar.c_str()));
334  for (unsigned int i=0; i<store.GetEntries(); ++i){
335  store.get(i);
336  if (allCats.getIndex()==iCat){
337  data_bin->add(dataVars,
338  weightVar.empty() ? 1.0 : dataVars.getRealValue(weightVar.c_str()));
339  }
340  }
341  delete copyTree;
342  first_entry += split_mode;
343  data_bin->Print("V");
344  }
345  data_bin->Print("V");
346  tmp->cd();
347 
348  // Now add all expressions that are computed dynamically
349  for(vector<pair<pair<string,string>, pair<string, vector<string> > > >::const_iterator ev = expressionVars.begin(), eve = expressionVars.end(); ev != eve; ++ev){
350  RooArgList args;
351  for (vector<string>::const_iterator it = ev->second.second.begin(), ed = ev->second.second.end(); it != ed; ++it) {
352  args.add(dataVars[it->c_str()]);
353  }
354  RooFormulaVar expr(ev->first.first.c_str(), ev->first.second.c_str(), ev->second.first.c_str(), args);
355  RooRealVar *col = (RooRealVar *) data_bin->addColumn(expr);
356  tmpVars.add(*dataVars.addClone(*col));
357  }
358 
359  // And add all dynamic categories from thresholds
360  for(vector<pair<pair<string,string>, pair<string, double> > >::const_iterator tc = thresholdCategories.begin(),
361  tce = thresholdCategories.end(); tc != tce; ++tc){
362  RooThresholdCategory tmp(tc->first.first.c_str(), tc->first.second.c_str(), (RooAbsReal &)dataVars[tc->second.first.c_str()], "above", 1);
363  tmp.addThreshold(tc->second.second, "below",0);
364  RooCategory *cat = (RooCategory *) data_bin->addColumn(tmp);
365  tmpVars.add(*dataVars.addClone(*cat));
366  }
367 
368  //setup the efficiency category
369  if (effCats.size() == 1) {
370  effName = effCats.front() + "::" + effStates.front();
371  RooMappedCategory efficiencyCategory("_efficiencyCategory_", "_efficiencyCategory_", (RooCategory&)dataVars[effCats.front().c_str()], "Failed");
372  efficiencyCategory.map(effStates.front().c_str(), "Passed");
373  data_bin->addColumn( efficiencyCategory );
374  } else {
375  RooArgSet rooEffCats;
376  string multiState = "{";
377  for (size_t i = 0; i < effCats.size(); ++i) {
378  if (i) { multiState += ";"; effName += " && "; }
379  rooEffCats.add((RooCategory &) dataVars[effCats[i].c_str()]);
380  multiState += effStates[i];
381  effName = effCats[i] + "::" + effStates[i];
382  }
383  multiState += "}";
384  RooMultiCategory efficiencyMultiCategory("_efficiencyMultiCategory_", "_efficiencyMultiCategory_", rooEffCats);
385  RooMappedCategory efficiencyCategory("_efficiencyCategory_", "_efficiencyCategory_", efficiencyMultiCategory, "Failed");
386  efficiencyCategory.map(multiState.c_str(), "Passed");
387  data_bin->addColumn( efficiencyCategory );
388  }
389  data_bin->addColumn( pdfCategory );
390  }
391 
392  //set the category variables by reading the first event
393  const RooArgSet* row = data_bin->get();
394 
395  //get PDF name
396  TString pdfName(((RooCategory*)row->find("_pdfCategory_"))->getLabel());
397 
398  //make directory name
399  TString dirName = catName;
400  dirName.ReplaceAll("{","").ReplaceAll("}","").ReplaceAll(";","__");
401  if(pdfName.Length() > 0){
402  dirName.Append("__").Append(pdfName);
403  }
404 
405  cout<<"Fitting bin: "<<dirName<<endl;
406  //make a directory for each bin
407  gDirectory->mkdir(dirName)->cd();
408 
409 
410  //create a workspace
411  RooWorkspace* w = new RooWorkspace();
412  //import the data
413  w->import(*data_bin);
414  delete data_bin; // clean up earlier
415  data_bin = dynamic_cast<RooDataSet*>(w->data("data")); // point to the data that's in the workspace now (saves memory)
416 
417  //save the distribution of variables
418  if (doSaveDistributionsPlot) saveDistributionsPlot(w);
419  //do the fitting only if there is sufficient number of events
420  if(data_bin->numEntries()>0){
421  //set the values of binnedVariables to the mean value in this data bin
422  RooArgSet meanOfVariables;
423  RooLinkedListIter vit = binnedVariables.iterator();
424  for(RooRealVar* v = (RooRealVar*)vit.Next(); v!=nullptr; v = (RooRealVar*)vit.Next() ){
425  meanOfVariables.addClone(*v);
426  double mean = w->data("data")->mean(*v);
427  RooBinning binning((RooBinning&)v->getBinning());
428  int ind = binning.binNumber(mean);
429  RooRealVar& newVar = (RooRealVar&)meanOfVariables[v->GetName()];
430  newVar.setVal(mean);
431  newVar.setAsymError(binning.binLow(ind)-mean, binning.binHigh(ind)-mean);
432  }
433 
434  //put an entry in the efficiency dataset
435  //note that the category values are coming from data_bin->get(0)
436  meanOfVariables.addClone(*data_bin->get(0), true);
437 
438  efficiency.setVal(0);//reset
439  efficiency.setAsymError(0,0);
440  doFitEfficiency(w, pdfName.Data(), efficiency);
441  fitEfficiency.add( RooArgSet(meanOfVariables, efficiency) );
442 
443 /* efficiency.setVal(0);//reset
444  doSBSEfficiency(w, efficiency);
445  sbsEfficiency.add( RooArgSet(meanOfVariables, efficiency) );*/
446 
447  efficiency.setVal(0);//reset
448  doCntEfficiency(w, efficiency);
449  cntEfficiency.add( RooArgSet(meanOfVariables, efficiency) );
450  }
451  //save the workspace if requested
452  if(saveWorkspace){
453  w->Write("w");
454  }
455  //clean up
456  delete w;
457  if (split_mode) dataVars.remove(tmpVars);
458  //get back to the initial directory
459  gDirectory->cd("..");
460  }
461 
462  //save the efficiency data
463  fitEfficiency.Write();
464  gDirectory->mkdir("fit_eff_plots")->cd();
465  saveEfficiencyPlots(fitEfficiency, effName, binnedVariables, mappedCategories);
466  gDirectory->cd("..");
467 
468 /* sbsEfficiency.Write();
469  gDirectory->mkdir("sbs_eff_plots")->cd();
470  saveEfficiencyPlots(sbsEfficiency, effCat+"::"+effState, binnedVariables, mappedCategories);
471  gDirectory->cd("..");*/
472 
473  cntEfficiency.Write();
474  gDirectory->mkdir("cnt_eff_plots")->cd();
475  saveEfficiencyPlots(cntEfficiency, effName, binnedVariables, mappedCategories);
476  gDirectory->cd("..");
477 
478  if (not split_mode) delete data;
479 
480  //empty string means no error
481  return "";
482 }
483 
484 void TagProbeFitter::doFitEfficiency(RooWorkspace* w, string pdfName, RooRealVar& efficiency){
485  //if pdfName is empty skip the fit
486  if(pdfName == "all"){
487  return;
488  }
489  //create the simultaneous pdf of name pdfName
490  createPdf(w, pdfs[pdfName]);
491  //set the initial values for the yields of signal and background
492  setInitialValues(w);
493  std::unique_ptr<RooFitResult> res;
494 
495  RooAbsData *data = w->data("data");
496  std::unique_ptr<RooDataHist> bdata;
497  if (binnedFit) {
498  // get variables from data, which contain also other binning or expression variables
499  const RooArgSet *dataObs = data->get(0);
500  // remove everything which is not a dependency of the pdf
501  RooArgSet *obs = w->pdf("simPdf")->getObservables(dataObs);
502  bdata.reset(new RooDataHist("data_binned", "data_binned", *obs, *data));
503  w->import(*bdata);
504  data = w->data("data_binned");
505  delete obs;
506  }
507 
508  double totPassing = data->sumEntries("_efficiencyCategory_==_efficiencyCategory_::Passed");
509  double totFailing = data->sumEntries("_efficiencyCategory_==_efficiencyCategory_::Failed");
510 
511  RooAbsReal* simNLL = w->pdf("simPdf")->createNLL(*data,Extended(true),NumCPU(numCPU));
512 
513  RooMinimizer minimizer(*simNLL); // we are going to use this for 'scan'
514  RooMinuit minuit(*simNLL);
515  minuit.setStrategy(1);
516  minuit.setProfile(true);
517  RooProfileLL profileLL("simPdfNLL","",*simNLL,*w->var("efficiency"));
518 
519 
520  //******* The block of code below is to make the fit converge faster.
521  // ****** This part is OPTIONAL, i.e., off be default. User can activate this
522  // ****** by setting the following parameters: "fixVars" and "floatShapeParameters"
523  // ****** Here is the full logic:
534 
535 
536  if(!fixVars.empty()){
537  // calculate initial values for parameters user want to fix
538  if(!floatShapeParameters && fixVarValues.empty()){
539  // we want to fix these parameters for each bin.
540  // the following sequence fixes them, fits, releases and fits again
541  // to get reasonable values.
542  // ----------------------------------------------------------------------
543  // This procedure works only once with a whole dataset (without binning)
544  // ----------------------------------------------------------------------
545 
546  // fix them
547  varFixer(w,true);
548  //do fit
549  minimizer.minimize("Minuit2","Scan");
550  minuit.migrad();
551  minuit.hesse();
552  //minuit.minos();
553  //w->pdf("simPdf")->fitTo(*data, Save(true), Extended(true), NumCPU(numCPU), Strategy(2),
554  //PrintLevel(quiet?-1:1), PrintEvalErrors(quiet?-1:1), Warnings(!quiet));
555  //release vars
556  varFixer(w,false);
557  //do fit
558  minimizer.minimize("Minuit2","Scan");
559  minuit.migrad();
560  minuit.hesse();
561  //minuit.minos();
562  //w->pdf("simPdf")->fitTo(*data, Save(true), Extended(true), NumCPU(numCPU), Strategy(2),
563  //PrintLevel(quiet?-1:1), PrintEvalErrors(quiet?-1:1), Warnings(!quiet));
564  //save vars
565  varSaver(w);
566  // now we have a starting point. Fit will converge faster.
567  }
568 
569  // here we can use initial values if we want (this works for each bin)
570  if(!floatShapeParameters) varRestorer(w); //restore vars
571 
572  //do fit
573  minimizer.minimize("Minuit2","Scan");
574  minuit.migrad();
575  minuit.hesse();
576  // initialize the profile likelihood
577  profileLL.getVal();
578  RooMinimizer* profMinuit = profileLL.minimizer();
579  profMinuit->setProfile(true);
580  profMinuit->setStrategy(2);
581  profMinuit->setPrintLevel(1);
582  profMinuit->minos(*w->var("efficiency"));
583  res.reset( profMinuit->save() );
584  //res = w->pdf("simPdf")->fitTo(*data, Save(true), Extended(true), NumCPU(numCPU), Strategy(2),
585  //Minos(*w->var("efficiency")), PrintLevel(quiet?-1:1),
586  //PrintEvalErrors(quiet?-1:1), Warnings(!quiet));
587  }//if(!fixVars.empty())
588 
589  // (default = true) if we don't want to fix any parameters or want to fit each bin with all parameters floating
590  if(floatShapeParameters){
591  //release vars
592  varFixer(w,false);
593 
594  //do fit
595  minimizer.minimize("Minuit2","Scan");
596  minuit.migrad();
597  minuit.hesse();
598  res.reset( w->pdf("simPdf")->fitTo(*data, Save(true), Extended(true), NumCPU(numCPU), Strategy(2),
599  Minos(*w->var("efficiency")), PrintLevel(quiet?-1:1),
600  PrintEvalErrors(quiet?-1:1), Warnings(!quiet)) );
601  }
602 
603 
604 
605  // save everything
606  res->Write("fitresults");
607  w->saveSnapshot("finalState",w->components());
608  saveFitPlot(w);
609  //extract the efficiency parameter from the results
610  RooRealVar* e = (RooRealVar*) res->floatParsFinal().find("efficiency");
611  //What's wrong with this? and why don't they copy the errors!
612  //efficiency = *e;
613  efficiency.setVal(e->getVal());
614  Double_t errLo = e->getErrorLo(), errHi = e->getErrorHi();
615  if (errLo == 0 && e->getVal() < 0.5) errLo = e->getMin()-e->getVal();
616  if (errHi == 0 && e->getVal() > 0.5) errHi = e->getMax()-e->getVal();
617  efficiency.setAsymError(errLo, errHi);
618 
619  if (totPassing * totFailing == 0) {
620  RooRealVar* nTot = (RooRealVar*) res->floatParsFinal().find("numTot");
621  RooRealVar* fSig = (RooRealVar*) res->floatParsFinal().find("fSigAll");
622  double cerr = ROOT::Math::beta_quantile( 1-(1.0-.68540158589942957)/2, 1, nTot->getVal() * fSig->getVal() );
623  /*
624  std::cout << "======================================================================================" << std::endl;
625  std::cout << "======= totPassing " << totPassing << ", totFailing " << totFailing << std::endl;
626  std::cout << "======= FIT: e " << e->getVal() << ", e Lo " << e->getErrorLo() << ", e Hi " << e->getErrorHi() << std::endl;
627  std::cout << "======= FIT:nS " << nS->getVal() << ", nS Lo " << nS->getErrorLo() << ", nS Hi " << nS->getErrorHi() << std::endl;
628  std::cout << "======= FIT:nB " << nB->getVal() << ", nB Lo " << nB->getErrorLo() << ", nB Hi " << nB->getErrorHi() << std::endl;
629  std::cout << "======= CNT: " << cerr << std::endl;
630  std::cout << "======================================================================================" << std::endl;
631  */
632  if (totPassing == 0) {
633  efficiency.setVal(0);
634  efficiency.setAsymError(0,cerr);
635  } else {
636  efficiency.setVal(1);
637  efficiency.setAsymError(-cerr,0);
638  }
639  }
640 
641  delete simNLL;
642 }
643 
644 void TagProbeFitter::createPdf(RooWorkspace* w, vector<string>& pdfCommands){
645  // create the signal and background pdfs defined by the user
646  for(unsigned int i=0; i<pdfCommands.size(); i++){
647  const std::string & command = pdfCommands[i];
648  if (command.find("#import ") == 0) {
649  TDirectory *here = gDirectory;
650  w->import(command.substr(8).c_str());
651  here->cd();
652  } else {
653  TDirectory *here = gDirectory;
654  w->factory(command.c_str());
655  here->cd();
656  }
657  }
658  // setup the simultaneous extended pdf
659 
660  w->factory("expr::nSignalPass('efficiency*fSigAll*numTot', efficiency, fSigAll[.9,0,1],numTot[1,0,1e10])");
661  w->factory("expr::nSignalFail('(1-efficiency)*fSigAll*numTot', efficiency, fSigAll,numTot)");
662  w->factory("expr::nBkgPass('effBkg*(1-fSigAll)*numTot', effBkg[.9,0,1],fSigAll,numTot)");
663  w->factory("expr::nBkgFail('(1-effBkg)*(1-fSigAll)*numTot', effBkg,fSigAll,numTot)");
664  TString sPass = "signal", sFail = "signal";
665  if (w->pdf("signalPass") != nullptr && w->pdf("signalFail") != nullptr) {
666  if (w->pdf("signal") != nullptr) throw std::logic_error("You must either define one 'signal' PDF or two PDFs ('signalPass', 'signalFail'), not both!");
667  sPass = "signalPass"; sFail = "signalFail";
668  } else if (w->pdf("signal") != nullptr) {
669  if (w->pdf("signalPass") != nullptr || w->pdf("signalFail") != nullptr) {
670  throw std::logic_error("You must either define one 'signal' PDF or two PDFs ('signalPass', 'signalFail'), not both!");
671  }
672  } else {
673  throw std::logic_error("You must either define one 'signal' PDF or two PDFs ('signalPass', 'signalFail')");
674  }
675  w->factory("SUM::pdfPass(nSignalPass*"+sPass+", nBkgPass*backgroundPass)"); //fBkgPass*
676  w->factory("SUM::pdfFail(nSignalFail*"+sFail+", nBkgFail*backgroundFail)"); //fBkgFail*
677 
678  w->factory("SIMUL::simPdf(_efficiencyCategory_, Passed=pdfPass, Failed=pdfFail)");
679  // signalFractionInPassing is not used in the fit just to set the initial values
680  if (w->pdf("simPdf") == nullptr) throw std::runtime_error("Could not create simultaneous fit pdf.");
681  if(w->var("signalFractionInPassing") == nullptr)
682  w->factory("signalFractionInPassing[0.9]");
683 }
684 
686  // calculate initial values
687  double signalEfficiency = w->var("efficiency")->getVal();
688  double signalFractionInPassing = w->var("signalFractionInPassing")->getVal();
689  double totPassing = w->data("data")->sumEntries("_efficiencyCategory_==_efficiencyCategory_::Passed");
690  double totFailinging = w->data("data")->sumEntries("_efficiencyCategory_==_efficiencyCategory_::Failed");
691  double numSignalAll = totPassing*signalFractionInPassing/signalEfficiency;
692 
693  //std::cout << "Number of probes: " << totPassing+totFailinging << std::endl;
694 
695  // check if this value is inconsistent on the failing side
696  if(numSignalAll*(1-signalEfficiency) > totFailinging)
697  numSignalAll = totFailinging;
698  // now set the values
699  w->var("numTot")->setVal(totPassing+totFailinging);
700  w->var("numTot")->setMax(2.0*(totPassing+totFailinging)+10); //wiggle room in case of 0 events in bin
701 
702  if (totPassing == 0) {
703  w->var("efficiency")->setVal(0.0);
704  w->var("efficiency")->setAsymError(0,1);
705  w->var("efficiency")->setConstant(false);
706  } else if (totFailinging == 0) {
707  w->var("efficiency")->setVal(1.0);
708  w->var("efficiency")->setAsymError(-1,0);
709  w->var("efficiency")->setConstant(false);
710  } else {
711  w->var("efficiency")->setConstant(false);
712  }
713 
714  // if signal fraction is 1 then set the number of background events to 0.
715  //RooRealVar* fBkgPass = w->var("numBackgroundPass");
716  //if(signalFractionInPassing==1.0) { fBkgPass->setVal(0.0); fBkgPass->setConstant(true); }
717 
718  // save initial state for reference
719  w->saveSnapshot("initialState",w->components());
720 }
721 
722 void TagProbeFitter::saveFitPlot(RooWorkspace* w){
723  // save refferences for convenience
724  RooCategory& efficiencyCategory = *w->cat("_efficiencyCategory_");
725  RooAbsData* dataAll = (binnedFit ? w->data("data_binned") : w->data("data") );
726  RooAbsData* dataPass = dataAll->reduce(Cut("_efficiencyCategory_==_efficiencyCategory_::Passed"));
727  RooAbsData* dataFail = dataAll->reduce(Cut("_efficiencyCategory_==_efficiencyCategory_::Failed"));
728  RooAbsPdf& pdf = *w->pdf("simPdf");
729  std::unique_ptr<RooArgSet> obs(pdf.getObservables(*dataAll));
730  RooRealVar* mass = nullptr;
731  RooLinkedListIter it = obs->iterator();
732  for(RooAbsArg* v = (RooAbsArg*)it.Next(); v!=nullptr; v = (RooAbsArg*)it.Next() ){
733  if(!v->InheritsFrom("RooRealVar")) continue;
734  mass = (RooRealVar*)v;
735  break;
736  }
737  if(!mass) return;
738  // make a 2x2 canvas
739  TCanvas canvas("fit_canvas");
740  canvas.Divide(2,2);
741  vector<RooPlot*> frames;
742  // plot the Passing Probes
743  canvas.cd(1);
744  if (massBins == 0) {
745  frames.push_back(mass->frame(Name("Passing"), Title("Passing Probes")));
746  frames.push_back(mass->frame(Name("Failing"), Title("Failing Probes")));
747  frames.push_back(mass->frame(Name("All"), Title("All Probes")));
748  } else {
749  frames.push_back(mass->frame(Name("Passing"), Title("Passing Probes"), Bins(massBins)));
750  frames.push_back(mass->frame(Name("Failing"), Title("Failing Probes"), Bins(massBins)));
751  frames.push_back(mass->frame(Name("All"), Title("All Probes"), Bins(massBins)));
752  }
753  dataPass->plotOn(frames[0]);
754  pdf.plotOn(frames[0], Slice(efficiencyCategory, "Passed"), ProjWData(*dataPass), LineColor(kGreen));
755  pdf.plotOn(frames[0], Slice(efficiencyCategory, "Passed"), ProjWData(*dataPass), LineColor(kGreen), Components("backgroundPass"), LineStyle(kDashed));
756  frames[0]->Draw();
757  // plot the Failing Probes
758  canvas.cd(2);
759  dataFail->plotOn(frames[1]);
760  pdf.plotOn(frames[1], Slice(efficiencyCategory, "Failed"), ProjWData(*dataFail), LineColor(kRed));
761  pdf.plotOn(frames[1], Slice(efficiencyCategory, "Failed"), ProjWData(*dataFail), LineColor(kRed), Components("backgroundFail"), LineStyle(kDashed));
762  frames[1]->Draw();
763  // plot the All Probes
764  canvas.cd(3);
765  dataAll->plotOn(frames.back());
766  pdf.plotOn(frames.back(), ProjWData(*dataAll), LineColor(kBlue));
767  pdf.plotOn(frames.back(), ProjWData(*dataAll), LineColor(kBlue), Components("backgroundPass,backgroundFail"), LineStyle(kDashed));
768  frames.back()->Draw();
769  // plot the Fit Results
770  canvas.cd(4);
771  frames.push_back(mass->frame(Name("Fit Results"), Title("Fit Results")));
772  pdf.paramOn(frames.back(), dataAll, "", 0, "NELU", 0.1, 0.9, 0.9);
773  // draw only the parameter box not the whole frame
774  frames.back()->findObject(Form("%s_paramBox",pdf.GetName()))->Draw();
775  //save and clean up
776  canvas.Draw();
777  canvas.Write();
778  for (size_t i=0; i<frames.size(); i++) {
779  delete frames[i];
780  }
781  delete dataPass;
782  delete dataFail;
783 }
784 
786  // save pointers to datasets to manage memory
787  RooAbsData* dataAll = w->data("data");
788  RooAbsData* dataPass = dataAll->reduce(Cut("_efficiencyCategory_==_efficiencyCategory_::Passed"));
789  RooAbsData* dataFail = dataAll->reduce(Cut("_efficiencyCategory_==_efficiencyCategory_::Failed"));
790 
791  const RooArgSet* vars = dataAll->get();
792  vector<RooRealVar*> reals;
793  RooLinkedListIter it = vars->iterator();
794  for(RooAbsArg* v = (RooAbsArg*)it.Next(); v!=nullptr; v = (RooAbsArg*)it.Next() ){
795  if(!v->InheritsFrom("RooRealVar")) continue;
796  reals.push_back((RooRealVar*)v);
797  }
798  TCanvas canvas("distributions_canvas");
799  canvas.Divide(3,reals.size());
800  vector<RooPlot*> frames;
801  for(unsigned int i=0; i<reals.size(); i++){
802  // plot the Passing Probes
803  canvas.cd(3*i+1);
804  frames.push_back(reals[i]->frame(Name("Passing"), Title("Passing Probes"), Bins(100)));
805  dataPass->plotOn(frames.back(), LineColor(kGreen));
806  dataPass->statOn(frames.back());
807  frames.back()->Draw();
808  // plot the Failing Probes
809  canvas.cd(3*i+2);
810  frames.push_back(reals[i]->frame(Name("Failing"), Title("Failing Probes"), Bins(100)));
811  dataFail->plotOn(frames.back(), LineColor(kRed));
812  dataFail->statOn(frames.back());
813  frames.back()->Draw();
814  // plot the All Probes
815  canvas.cd(3*i+3);
816  frames.push_back(reals[i]->frame(Name("All"), Title("All Probes"), Bins(100)));
817  dataAll->plotOn(frames.back(), LineColor(kBlue));
818  dataAll->statOn(frames.back());
819  frames.back()->Draw();
820  }
821  canvas.Draw();
822  canvas.Write();
823  for (size_t i=0; i<frames.size(); i++) {
824  delete frames[i];
825  }
826  delete dataPass;
827  delete dataFail;
828 }
829 
830 void TagProbeFitter::saveEfficiencyPlots(RooDataSet& eff, const TString& effName, RooArgSet& binnedVariables,RooArgSet& mappedCategories){
831  RooLinkedListIter v1it = binnedVariables.iterator();
832  bool isOnePoint = (eff.numEntries() == 1); // for datasets with > 1 entry, we don't make plots for variables with just one bin
833  for(RooRealVar* v1 = (RooRealVar*)v1it.Next(); v1!=nullptr; v1 = (RooRealVar*)v1it.Next() ){
834  RooArgSet binCategories1D;
835  if (v1->numBins() == 1 && !isOnePoint) continue;
836  RooLinkedListIter v2it = binnedVariables.iterator();
837  for(RooRealVar* v2 = (RooRealVar*)v2it.Next(); v2!=nullptr; v2 = (RooRealVar*)v2it.Next() ){
838  if(v2 == v1) continue;
839  if (v2->numBins() == 1 && !isOnePoint) continue;
840  binCategories1D.addClone( RooBinningCategory(TString(v2->GetName())+"_bins", TString(v2->GetName())+"_bins", *v2) );
841 
842  RooArgSet binCategories2D;
843  RooLinkedListIter v3it = binnedVariables.iterator();
844  for(RooRealVar* v3 = (RooRealVar*)v3it.Next(); v3!=nullptr; v3 = (RooRealVar*)v3it.Next() ){
845  if(v3 == v1 || v3 == v2) continue;
846  binCategories2D.addClone( RooBinningCategory(TString(v3->GetName())+"_bins", TString(v3->GetName())+"_bins", *v3) );
847  }
848  RooMultiCategory allCats2D("allCats2D", "allCats2D", RooArgSet(binCategories2D, mappedCategories));
849  if(allCats2D.numTypes()==0){
850  makeEfficiencyPlot2D(eff, *v1, *v2, TString::Format("%s_%s_PLOT", v1->GetName(), v2->GetName()), "", effName);
851  }else{
852  RooDataSet myEff(eff);
853  myEff.addColumn(allCats2D);
854  std::unique_ptr<TIterator> catIt(allCats2D.typeIterator());
855  for(RooCatType* t = (RooCatType*)catIt->Next(); t!=nullptr; t = (RooCatType*)catIt->Next() ){
856  TString catName = t->GetName();
857  if(catName.Contains("NotMapped")) continue;
858  catName.ReplaceAll("{","").ReplaceAll("}","").ReplaceAll(";","_&_");
859  makeEfficiencyPlot2D(myEff, *v1, *v2, TString::Format("%s_%s_PLOT_%s",v1->GetName(), v2->GetName(), catName.Data()), catName, effName, "allCats2D", t->getVal());
860  }
861  }
862  }
863  RooMultiCategory allCats1D("allCats1D", "allCats1D", RooArgSet(binCategories1D, mappedCategories));
864  if(allCats1D.numTypes()==0){
865  makeEfficiencyPlot1D(eff, *v1, TString::Format("%s_PLOT", v1->GetName()), "", effName);
866  }else{
867  RooDataSet myEff(eff);
868  myEff.addColumn(allCats1D);
869  std::unique_ptr<TIterator> catIt(allCats1D.typeIterator());
870  for(RooCatType* t = (RooCatType*)catIt->Next(); t!=nullptr; t = (RooCatType*)catIt->Next() ){
871  TString catName = t->GetName();
872  if(catName.Contains("NotMapped")) continue;
873  catName.ReplaceAll("{","").ReplaceAll("}","").ReplaceAll(";","_&_");
874  makeEfficiencyPlot1D(myEff, *v1, TString::Format("%s_PLOT_%s", v1->GetName(), catName.Data()), catName, effName, "allCats1D", t->getVal());
875  }
876  }
877  }
878 }
879 
880 void TagProbeFitter::makeEfficiencyPlot1D(RooDataSet& eff, RooRealVar& v, const TString& plotName, const TString& plotTitle, const TString& effName, const char *catName, int catIndex){
881  TGraphAsymmErrors *p = new TGraphAsymmErrors();
882  const RooArgSet *entry = eff.get();
883  const RooRealVar &vi = dynamic_cast<const RooRealVar &>(*entry->find(v.GetName()));
884  const RooRealVar &ei = dynamic_cast<const RooRealVar &>(*entry->find("efficiency"));
885  for (unsigned int i = 0, n = eff.numEntries(); i < n; ++i) {
886  entry = eff.get(i);
887  if (catName != nullptr && entry->getCatIndex(catName) != catIndex) continue;
888  int j = p->GetN(); p->Set(j+1);
889  p->SetPoint(j, vi.getVal(), ei.getVal() );
890  p->SetPointError(j, -vi.getAsymErrorLo(), vi.getAsymErrorHi(), -ei.getAsymErrorLo(), ei.getAsymErrorHi() );
891  }
892  TCanvas canvas(plotName);
893  TH1F *frame = new TH1F("frame", "Efficiency of "+effName, 1, v.getMin(), v.getMax()); frame->SetDirectory(nullptr);
894  p->SetNameTitle(Form("hxy_%s", eff.GetName()), "Efficiency of "+effName);
895  p->GetXaxis()->SetTitle(strlen(v.getUnit()) ? Form("%s (%s)", v.GetName(), v.getUnit()) : v.GetName());
896  p->GetYaxis()->SetTitle("Efficiency of "+effName);
897  frame->GetXaxis()->SetTitle(strlen(v.getUnit()) ? Form("%s (%s)", v.GetName(), v.getUnit()) : v.GetName());
898  frame->GetYaxis()->SetTitle("Efficiency of "+effName);
899  frame->GetYaxis()->SetRangeUser(0,1);
900  frame->Draw();
901  p->SetLineWidth(2); p->SetMarkerStyle(kFullCircle); p->SetMarkerSize(1.2);
902  p->Draw("P SAME");
903  canvas.Write();
904  delete frame;
905  delete p;
906 }
907 
908 void TagProbeFitter::makeEfficiencyPlot2D(RooDataSet& eff, RooRealVar& v1, RooRealVar& v2, const TString& plotName, const TString& plotTitle, const TString& effName, const char *catName, int catIndex){
909  TCanvas canvas(plotName);
910  canvas.SetRightMargin(0.15);
911  TH2F* h = new TH2F(plotName, plotName, v1.getBinning().numBins(), v1.getBinning().array(), v2.getBinning().numBins(), v2.getBinning().array());
912  const RooArgSet* set = eff.get();
913  RooRealVar* e = (RooRealVar*) set->find("efficiency");
914  RooRealVar* v1_ = (RooRealVar*) set->find(v1.GetName());
915  RooRealVar* v2_ = (RooRealVar*) set->find(v2.GetName());
916  h->SetTitle(TString::Format("%s;%s%s;%s%s;Efficiency of %s", plotTitle.Data(),
917  v1.GetTitle(), TString(v1.getUnit()).Length()==0?"":TString::Format(" (%s)", v1.getUnit()).Data(),
918  v2.GetTitle(), TString(v2.getUnit()).Length()==0?"":TString::Format(" (%s)", v2.getUnit()).Data(), effName.Data()));
919  h->SetOption("colztexte");
920  h->GetZaxis()->SetRangeUser(-0.001,1.001);
921  h->SetStats(kFALSE);
922  for(int i=0; i<eff.numEntries(); i++){
923  const RooArgSet *entry = eff.get(i);
924  if (catName != nullptr && entry->getCatIndex(catName) != catIndex) continue;
925  h->SetBinContent(h->FindBin(v1_->getVal(), v2_->getVal()), e->getVal());
926  h->SetBinError(h->FindBin(v1_->getVal(), v2_->getVal()), (e->getErrorHi()-e->getErrorLo())/2.);
927  }
928  h->Draw();
929  canvas.Draw();
930  canvas.Write();
931  delete h;
932 }
933 
934 void TagProbeFitter::doSBSEfficiency(RooWorkspace* w, RooRealVar& efficiency){
935 }
936 
937 void TagProbeFitter::doCntEfficiency(RooWorkspace* w, RooRealVar& efficiency){
938  int pass = w->data("data")->sumEntries("_efficiencyCategory_==_efficiencyCategory_::Passed");
939  int fail = w->data("data")->sumEntries("_efficiencyCategory_==_efficiencyCategory_::Failed");
940  double e = (pass+fail == 0) ? 0 : pass/double(pass+fail);
941  // Use Clopper-Pearson
942  double alpha = (1.0 - .68540158589942957)/2;
943  double lo = (pass == 0) ? 0.0 : ROOT::Math::beta_quantile( alpha, pass, fail+1 );
944  double hi = (fail == 0) ? 1.0 : ROOT::Math::beta_quantile( 1-alpha, pass+1, fail );
946  //double lob, hib;
947  //Efficiency( pass, pass+fail, .68540158589942957, e, lob, hib );
948  //std::cerr << "CNT " << pass << "/" << fail << ": Clopper Pearson [" << lo << ", " << hi << "], Bayes [" << lob << ", " << hib << "]" << std::endl;
949  efficiency.setVal(e);
950  efficiency.setAsymError(lo-e, hi-e);
951 }
952 
953 void TagProbeFitter::varFixer(RooWorkspace* w, bool fix){
954  std::vector<std::string>::const_iterator it;
955  for(it=fixVars.begin(); it<fixVars.end(); it++){
956  if(w->var((*it).c_str()))
957  w->var((*it).c_str())->setAttribute("Constant",fix);
958  else{
959  std::cout << "TagProbeFitter: " << "Can't find a variable to fix: " << *it;
960  }
961  }
962 }
963 
964 void TagProbeFitter::varSaver(RooWorkspace* w){
965  if(!fixVarValues.empty()){
966  std::cout << "attempt to save variables more than once!" << std::endl;
967  return;
968  }
969  std::vector<std::string>::const_iterator it;
970  for(it=fixVars.begin(); it<fixVars.end(); it++){
971  fixVarValues.push_back(w->var((*it).c_str())->getVal());
972  }
973 
974 }
975 
976 void TagProbeFitter::varRestorer(RooWorkspace* w){
977  if(fixVarValues.size()==fixVars.size())
978  for(unsigned int i=0; i< fixVars.size(); i++){
979  std::cout << "setting variable " << fixVars[i].c_str() << std::endl;
980  w->var(fixVars[i].c_str())->setVal(fixVarValues[i]);
981  }
982  else{
983  std::cout << "fixVars and fixVarValues are not of the same size!" << std::endl;
984  }
985 }
986 
void doCntEfficiency(RooWorkspace *w, RooRealVar &efficiency)
calculate the efficiecny by counting in the dataset found in the workspace
float alpha
Definition: AMPTWrapper.h:95
void makeEfficiencyPlot1D(RooDataSet &eff, RooRealVar &v, const TString &plotName, const TString &plotTitle, const TString &effName, const char *catName=nullptr, int catIndex=-1)
makes the 1D plot
const double w
Definition: UKUtility.cc:23
FWCore Framework interface EventSetupRecordImplementation h
Helper function to determine trigger accepts.
void addPdf(std::string pdfName, std::vector< std::string > &pdfCommands)
static PFTauRenderPlugin instance
void setWeightVar(const std::string &weight)
set a variable to be used as weight for a dataset. empty string means no weights. ...
std::string calculateEfficiency(std::string dirName, std::string efficiencyCategory, std::string efficiencyState, std::vector< std::string > &unbinnedVariables, std::map< std::string, std::vector< double > > &binnedReals, std::map< std::string, std::vector< std::string > > &binnedCategories, std::vector< std::string > &binToPDFmap)
calculate the efficiency for a particular binning of the data; it saves everything in the directory "...
static const int WARNING
void makeEfficiencyPlot2D(RooDataSet &eff, RooRealVar &v1, RooRealVar &v2, const TString &plotName, const TString &plotTitle, const TString &effName, const char *catName=nullptr, int catIndex=-1)
makes the 2D plot
bool addThresholdCategory(std::string categoryName, std::string title, std::string varName, double cutValue)
adds a new category based on a cut
bool ev
Definition: Electron.h:6
void setQuiet(bool quiet_=true)
suppress most of the output from RooFit and Minuit
TagProbeFitter(const std::vector< std::string > &inputFileNames, std::string inputDirectoryName, std::string inputTreeName, std::string outputFileName, int numCPU=1, bool saveWorkspace_=false, bool floatShapeParameters=true, const std::vector< std::string > &fixVars_=std::vector< std::string >())
construct the fitter with the inputFileName, inputDirectoryName, inputTreeName, outputFileName and sp...
def cat(path)
Definition: eostools.py:401
bool addExpression(std::string expressionName, std::string title, std::string expression, const std::vector< std::string > &arguments)
adds a new category based on a cut
void saveEfficiencyPlots(RooDataSet &eff, const TString &effName, RooArgSet &binnedVariables, RooArgSet &mappedCategories)
saves the efficiency plots
void varSaver(RooWorkspace *w)
store values in the vector
void varRestorer(RooWorkspace *w)
restore variables&#39;s values for fit starting point
void saveFitPlot(RooWorkspace *w)
saves the fit canvas
~TagProbeFitter()
destructor closes the files
void setInitialValues(RooWorkspace *w)
sets initial values of the PDF parameters based on the data available in the workspace ...
void saveDistributionsPlot(RooWorkspace *w)
saves the distributions canvas
void varFixer(RooWorkspace *w, bool fix)
fix or release variables selected by user
list command
Definition: mps_check.py:25
void setSplitMode(unsigned int nevents)
std::vector< std::vector< double > > tmp
Definition: MVATrainer.cc:100
TString units(TString variable, Char_t axis)
char data[epos_bytes_allocation]
Definition: EPOS_Wrapper.h:82
MultiGaussianState< N > multiState(const std::vector< MultiGaussianState< N >::Vector > &, const std::vector< MultiGaussianState< N >::Matrix > &, const std::vector< double > &)
col
Definition: cuy.py:1010
void setBinsForMassPlots(int bins)
set number of bins to use when making the plots; 0 = automatic
def canvas(sub, attr)
Definition: svgfig.py:482
void doSBSEfficiency(RooWorkspace *w, RooRealVar &efficiency)
calculate the efficiecny with side band substraction in the dataset found in the workspace ...
void createPdf(RooWorkspace *w, std::vector< std::string > &pdfCommands)
creates the simultaneous PDF in the workspace according to the "pdfCommands"
vars
Definition: DeepTauId.cc:77
void doFitEfficiency(RooWorkspace *w, std::string pdfName, RooRealVar &efficiency)
calculate the efficiecny with a simulataneous maximum likelihood fit in the dataset found in the work...
def fail(errstr="")
bool addCategory(std::string categoryName, std::string title, std::string expression)
adds a new category variable to the set of variables describing the data in the tree; "expression" is...
bool addVariable(std::string variableName, std::string title, double low, double hi, std::string units)
adds a new real variable to the set of variables describing the data in the tree
static const int ERROR