ATLAS Offline Software
LhoodMM_tools.cxx
Go to the documentation of this file.
1 /*
2  Copyright (C) 2002-2022 CERN for the benefit of the ATLAS collaboration
3 */
4 
5 #include <iostream>
10 #include "FakeBkgTools/Database.h"
12 #include "TH1.h"
13 #include "TH2.h"
14 #include "TH3.h"
15 #include "TMatrixT.h"
16 #include "TMath.h"
17 #include "TFile.h"
18 #include "TTree.h"
19 #include "TChain.h"
20 #include "TTreeReader.h"
21 #include "TTreeReaderValue.h"
22 #include "TKey.h"
23 #include "TDirectory.h"
24 #include <chrono>
25 #include <memory>
26 
27 #ifndef FAKEBKGTOOLS_ATLAS_ENVIRONMENT
28 #define declareProperty(n, p, h) ExtraPropertyManager<LhoodMM_tools>::declareProperty(n, &LhoodMM_tools::p, h)
29 #endif
30 
31 using namespace CP;
34 using std::string;
35 using std::vector;
36 using Clock=std::chrono::high_resolution_clock;
37 
38 
40 
41 LhoodMM_tools::LhoodMM_tools(const std::string& name) :
43 {
44 
46 
47  //setup fixHistogramNormalization property
48  declareProperty("FixHistogramNormalization", m_fixNormalization, "Boolean to determine whether or not histograms are scaled such that their normalization is equal to the fake yield computed for the entire sample (true = yes, do the scaleing)");
49 
50  declareProperty("DoFakeFactorFit", m_doFakeFactor, "Give results corresponding to the fake factor method rather than the matrix method");
51 
52  // set everything to default values
53  reset();
54 }
55 
57 
58 }
59 
60 
61 
63 {
65 }
66 
67 
69 {
71 }
72 
74 
76 
77  m_prevSave = false;
78 
79  m_nfakes_std = 1.;
80  m_nfakes_std_err = 1.;
81 
82  m_maxWeight = 1.;
83 
84  m_printLevel = -1;
85 
87 
89 
90  m_fixNormalization = false;
91 
92  m_coeffs.clear();
93  m_coeffs.resize(s_nLepMax);
94 
95  for (int ilep = 0; ilep < s_nLepMax; ilep++) {
96  m_coeffs[ilep].clear();
97  m_coeffs[ilep].resize((0x1 << (ilep+1)) );
98  for (int ientry = 0; ientry < (0x1 << (ilep+1)); ientry++) {
99  m_coeffs[ilep][ientry].resize((0x1 << (ilep+1)) );
100  for (int jentry = 0; jentry < (0x1 << (ilep+1)); jentry++) {
101  m_coeffs[ilep][ientry][jentry] =0.;
102  }
103  }
104  }
105 
106  m_real_indices.clear();
107  m_real_indices.resize(s_nLepMax);
108  m_fake_indices.clear();
109  m_fake_indices.resize(s_nLepMax);
110 
111  m_maxnlep_loose = 0;
112 
113  m_requireSS = false;
114  m_requireOS = false;
115 
116  m_fsvec.clear();
117  m_fsvec.resize(s_nLepMax);
118 
119  m_OSfrac.clear();
120  m_OSfrac.resize(s_nLepMax);
121 
122  for (int ilep = 0; ilep <s_nLepMax; ilep++) {
123  m_OSfrac[ilep].resize(ilep);
124  }
125 
126  m_doFakeFactor = false;
127 
128  m_nrf_mat_vec.clear();
129  m_MMmatrix_vec.clear();
130  m_nrf_mat_vec.resize(s_nLepMax);
131  m_MMmatrix_vec.resize(s_nLepMax);
132  m_ntlpred_vec.clear();
133  m_ntlpred_vec.resize(s_nLepMax);
134  for (int ilep = 0; ilep < s_nLepMax; ilep++) {
135  m_nrf_mat_vec[ilep] = std::shared_ptr<TMatrixT<double>>(std::make_shared<TMatrixT<double>>(0x1 << (ilep+1),1) );
136  m_MMmatrix_vec[ilep] = std::shared_ptr<TMatrixT<double>>(std::make_shared<TMatrixT<double>> ((0x1 << (ilep+1)),(0x1 << (ilep+1))));
137  m_ntlpred_vec[ilep] = std::shared_ptr<TMatrixT<double>>(std::make_shared< TMatrixT<double>>(0x1 << (ilep+1),1));
138  }
139 
140  m_lastSaveIndex = 0;
141 
142  m_alreadyMerged = false;
143 
144 }
145 
147  if (ft == "FF") {
148  m_doFakeFactor = true;
149  return StatusCode::SUCCESS;
150  } else if (ft == "MM") {
151  m_doFakeFactor = false;
152  return StatusCode::SUCCESS;
153  } else {
154  ATH_MSG_ERROR("Error in LhoodMM_tools::setFitType: please specify \"MM\" for matrix method or \"FF\" for fake factor method");
155  return StatusCode::FAILURE;
156  }
157 }
158 
160 
162 
163  if(sc != StatusCode::SUCCESS) return sc;
164 
165 
166  auto currentMap = m_fitInfo_1dhisto_map.find(h1);
167  if (currentMap == m_fitInfo_1dhisto_map.end() ) {
169  // size all the vectors appropriately
170  int ncells = h1->GetNcells();
171  auto *fitinfovec = &m_fitInfo_1dhisto_map.find(h1)->second;
172  fitinfovec->resize(ncells);
173  ATH_MSG_VERBOSE("Just resized fitinfovec");
174  for (int icell = 0; icell < ncells; icell++) {
175  LhoodMMFitInfo* fitInfo = &(fitinfovec->at(icell));
176  fitInfo->reset();
177  }
178 
179  ATH_MSG_INFO("Registered a 1D histogram "<<h1->GetName());
180  } else {
181  ATH_MSG_ERROR("Error in LhoodMM_tools::register1DHistogram: histogram has already been registered");
182  return StatusCode::FAILURE;
183  }
184  return StatusCode::SUCCESS;
185 }
186 
187 StatusCode LhoodMM_tools::register2DHistogram(TH2* h2, const float *xval, const float *yval) {
188 
190 
191  if(sc != StatusCode::SUCCESS) return sc;
192 
193  auto currentMap = m_fitInfo_2dhisto_map.find(h2);
194  if (currentMap == m_fitInfo_2dhisto_map.end() ) {
196  // size all the vectors appropriately
197  int ncells = h2->GetNcells();
198  auto *fitinfovec = &m_fitInfo_2dhisto_map.find(h2)->second;
199  fitinfovec->resize(ncells);
200  for (int icell = 0; icell < ncells; icell++) {
201  LhoodMMFitInfo* fitInfo = &(fitinfovec->at(icell));
202  fitInfo->reset();
203  }
204  ATH_MSG_INFO("Registered a 2D histogram "<<h2->GetName());
205  } else {
206  ATH_MSG_ERROR("Error in LhoodMM_tools::register2DHistogram: histogram has already been registered");
207  return StatusCode::FAILURE;
208  }
209  return StatusCode::SUCCESS;
210 }
211 
212 StatusCode LhoodMM_tools::register3DHistogram(TH3* h3, const float *xval, const float *yval, const float *zval) {
213 
215 
216  if(sc != StatusCode::SUCCESS) return sc;
217 
218  auto currentMap = m_fitInfo_3dhisto_map.find(h3);
219  if (currentMap == m_fitInfo_3dhisto_map.end() ) {
221  // size all the vectors appropriately
222  int ncells = h3->GetNcells();
223  auto *fitinfovec = &m_fitInfo_3dhisto_map.find(h3)->second;
224  fitinfovec->resize(ncells);
225  for (int icell = 0; icell < ncells; icell++) {
226  LhoodMMFitInfo* fitInfo = &(fitinfovec->at(icell));
227  fitInfo->reset();
228  }
229  ATH_MSG_INFO("Registered a 3D histogram "<<h3->GetName());
230  } else {
231  ATH_MSG_ERROR("Error in LhoodMM_tools::register3DHistogram: histogram has already been registered");
232  return StatusCode::FAILURE;
233  }
234  return StatusCode::SUCCESS;
235 }
236 
237 StatusCode LhoodMM_tools::addEventCustom(const std::vector<bool>& isTight_vals,
238  const std::vector<Efficiency>& realEff_vals,
239  const std::vector<Efficiency>& fakeEff_vals,
240  const std::vector<int>& charges,
241  float extraweight) {
242 
243  if (extraweight > m_maxWeight) m_maxWeight = extraweight;
244 
245  int nlep = isTight_vals.size();
246 
247  m_needToResize = false;
248  if (nlep > m_maxnlep_loose) {
249  m_maxnlep_loose = nlep;
250  m_needToResize = true;
251  }
252 
253  LhoodMMEvent mmevt(nlep, realEff_vals, fakeEff_vals, isTight_vals, charges, extraweight);
254 
256 
257 
258  return StatusCode::SUCCESS;
259 
260 }
261 
263 
264  int nlep = m_particles.size();
265  if (nlep == 0) {
266  ATH_MSG_WARNING("Attempt to add an event with 0 leptons. This event will be ignored.");
267  return StatusCode::SUCCESS;
268  }
269  std::vector<bool> isTight_vals;
270  std::vector<Efficiency> realEff_vals;
271  std::vector<Efficiency> fakeEff_vals;
272  std::vector<int> charges;
273  std::vector<FakeBkgTools::ParticleData>::const_iterator particles_it;
274  for (particles_it = m_particles.begin(); particles_it != m_particles.end(); ++particles_it) {
275  const FakeBkgTools::ParticleData& p = *particles_it;
276  isTight_vals.push_back(p.tight);
277  realEff_vals.push_back(p.real_efficiency);
278  fakeEff_vals.push_back(p.fake_efficiency);
279  double r_eff = p.real_efficiency.value(this);
280  double f_eff = p.fake_efficiency.value(this);
281 
282  if (particles_it == m_particles.begin() ){
283 
284  for(const std::pair<short unsigned int, FakeBkgTools::Uncertainty> kv : p.real_efficiency.uncertainties)
285  {
286  ATH_MSG_DEBUG("real eff uncertainties for first lepton are " << kv.second.up << " " << kv.second.down);
287  }
288  for(const std::pair<short unsigned int, FakeBkgTools::Uncertainty> kv : p.fake_efficiency.uncertainties)
289  {
290  ATH_MSG_DEBUG("fake eff uncertainties for first lepton are " << kv.second.up << " " << kv.second.down);
291  }
292  }
293  charges.push_back(p.charge);
294  if ( r_eff < 0.01 && f_eff< 0.01) {
295  ATH_MSG_DEBUG("Found bad efficiency values");
296  }
297  }
298 
299  return addEventCustom( isTight_vals, realEff_vals, fakeEff_vals, charges, m_externalWeight);
300 }
301 
302 StatusCode LhoodMM_tools::getTotalYield(float& yield, float& statErrUp, float& statErrDown) {
303 
304  if (m_progressFileName != "none" && m_alreadyMerged == false) {
305  ATH_CHECK( mergeSubJobs() );
306  }
307 
308  //set output level according to debug flag, also check whether setPrintLevel was called directly
310 
311  Double_t poserr, negerr;
312 
314  yield = nfakes(&poserr,&negerr);
315 
316  ATH_MSG_DEBUG("Leaving getTotalYield with yield = " << yield);
317 
318  statErrUp = poserr;
319  statErrDown = -negerr;
320 
321  return fillHistograms();
322 }
323 
325 
326  int nlep = mmevt.nlep();
327  //increment global matrix
328  if (m_needToResize) {
330  }
331 
333 
334  // increment matrix terms for all registered histograms
335  // if size needs to increase, this must be done for all bins...
336 
337  for (auto map1_iter = m_values_1dhisto_map.begin(); map1_iter != m_values_1dhisto_map.end(); map1_iter++) {
338  const float* val = map1_iter->second;
339  TH1* h = map1_iter->first;
340  auto histoMap = m_fitInfo_1dhisto_map.find(map1_iter->first);
341  if (histoMap != m_fitInfo_1dhisto_map.end() ) {
342  int icell;
343  LhoodMMFitInfo *fitInfo;
344  if (m_needToResize) {
345  for (icell = 0; icell<h->GetNcells(); icell++) {
346  fitInfo = &histoMap->second[icell];
347  fitInfo->resizeVectors(nlep);
348  }
349  }
350  icell = h->FindBin(*val);
351  ATH_MSG_VERBOSE("fitInfo vector size is " << histoMap->second.size());
352  fitInfo = &histoMap->second[icell];
353  ATH_MSG_VERBOSE("icell is " << icell);
354  ATH_MSG_VERBOSE("fitInfo totEvents is " << fitInfo->totEvents);
355  ATH_MSG_VERBOSE("need to resize? " << m_needToResize);
356  ANA_CHECK(incrementOneMatrixSet(*fitInfo, mmevt));
357  ATH_MSG_VERBOSE("need to resize now? " << m_needToResize);
358  } else {
359  ATH_MSG_ERROR("Can not find entry for 1d histogram");
360  return StatusCode::FAILURE;
361  }
362  }
363 
364  std::map<TH2*, std::pair<const float*, const float*> >::iterator map2_iter;
365  for (map2_iter = m_values_2dhisto_map.begin(); map2_iter != m_values_2dhisto_map.end(); ++map2_iter) {
366  std::pair<const float*, const float*> val = map2_iter->second;
367  TH2* h = map2_iter->first;
368 
369  auto histoMap = m_fitInfo_2dhisto_map.find(map2_iter->first);
370  if (histoMap != m_fitInfo_2dhisto_map.end() ) {
371  int icell;
372  LhoodMMFitInfo *fitInfo;
373  if (m_needToResize) {
374  for (icell = 0; icell<h->GetNcells(); icell++) {
375  fitInfo = &histoMap->second[icell];
376  fitInfo->resizeVectors(nlep);
377  }
378  }
379  icell = h->FindBin(*(val.first), *(val.second));
380  fitInfo = &histoMap->second[icell];
381  ANA_CHECK(incrementOneMatrixSet(*fitInfo, mmevt));
382  } else {
383  ATH_MSG_ERROR("Can not find entry for 2d histogram");
384  return StatusCode::FAILURE;
385  }
386 
387  }
388 
389  std::map<TH3*, std::tuple<const float*, const float*, const float*> >::iterator map3_iter;
390  for (map3_iter = m_values_3dhisto_map.begin(); map3_iter != m_values_3dhisto_map.end(); ++map3_iter) {
391  std::tuple<const float*, const float*, const float*> val = map3_iter->second;
392  TH3* h = map3_iter->first;
393  auto histoMap = m_fitInfo_3dhisto_map.find(map3_iter->first);
394  if (histoMap != m_fitInfo_3dhisto_map.end() ) {
395  int icell;
396  LhoodMMFitInfo *fitInfo;
397  if (m_needToResize) {
398  for (icell = 0; icell<h->GetNcells(); icell++) {
399  fitInfo = &histoMap->second[icell];
400  fitInfo->resizeVectors(nlep);
401  }
402  }
403  icell = h->FindBin(*(std::get<0>(val)), *(std::get<1>(val)), *(std::get<2>(val)) );
404  fitInfo = &histoMap->second[icell];
405  ANA_CHECK(incrementOneMatrixSet(*fitInfo, mmevt));
406  } else {
407  ATH_MSG_ERROR("Can not find entry for 3d histogram");
408  return StatusCode::FAILURE;
409  }
410  }
411 
412  return StatusCode::SUCCESS;
413 }
414 
416  const LhoodMMEvent& mmevt) {
417 
418  int nlep = mmevt.nlep();
419  int lepidx = nlep-1;
420  int rank = 0x1 << nlep;
421 
422  fitInfo.totEvents++;
423  fitInfo.eventCount[lepidx]++;
424 
425 
426  if (nlep <= s_nLepMax) {
427  ATH_MSG_VERBOSE("In incrementMatrices, how many uncertainties? " << mmevt.realEffObj(0).uncertainties.size());
428  ATH_MSG_VERBOSE("In incrementMatrices, m_totEvents = " << fitInfo.totEvents);
429 
430  unsigned int catIndex = 0;
431  for (int jlep = 0; jlep < nlep; jlep++) {
432  catIndex += (!mmevt.isTight(jlep)) << jlep;
433  }
434  double weight = mmevt.weight();
435 
436  ATH_MSG_VERBOSE("event_cat.size() = " << fitInfo.event_cat.size());
437  ATH_MSG_VERBOSE("event_sumw2.size() = " << fitInfo.event_sumw2.size());
438 
439  ATH_MSG_VERBOSE("nlep= " << nlep);
440  ATH_MSG_VERBOSE("catIndex= " << catIndex);
441  ATH_MSG_VERBOSE("fitInfo.event_cat.at(nlep-1).size() = " << fitInfo.event_cat.at(lepidx).size());
442 
443  fitInfo.event_cat[lepidx][catIndex] +=weight;
444  fitInfo.event_sumw2[lepidx][catIndex]+=weight*weight;
445 
446  ATH_MSG_VERBOSE("Done updating event_cat and event_sumw2");
447 
448  //check to see if there is at least one OS pair...
449  for (int icomb = 0; icomb < (0x1 << nlep); icomb++) {
450  int totcharge = 0;
451  std::bitset<s_nLepMax+1> tights(icomb);
452  int ntight = tights.count();
453 
454  for (int jlep = 0; jlep < nlep; jlep++) {
455  if (tights[jlep]) {
456  totcharge += mmevt.charge(jlep);
457  }
458  }
459 
460  ATH_MSG_VERBOSE("Setting OSfrac_denom[" << lepidx << "][" << ntight << "]");
461  ATH_MSG_VERBOSE("size is " << fitInfo.OSfrac_denom.size() );
462  ATH_MSG_VERBOSE("size is " << fitInfo.OSfrac_denom[lepidx].size() );
463  ATH_MSG_VERBOSE("weight is " << weight );
464  fitInfo.OSfrac_denom[lepidx][ntight]+=weight;
465  ATH_MSG_VERBOSE("Setting OSfrac_num[" << lepidx << "][" << ntight << "]");
466  if ((TMath::Abs(totcharge) < ntight) || ntight == 1) fitInfo.OSfrac_num[lepidx][ntight]+=weight;
467  }
468 
469 
470  std::vector<std::vector<FakeBkgTools::Efficiency>> vals(2, std::vector<FakeBkgTools::Efficiency>(nlep));
471  for (int ilep = 0; ilep < nlep; ilep++) {
472  ATH_MSG_VERBOSE("1 vals[0].size() = " << vals[0].size());
473  ATH_MSG_VERBOSE("getting efficiency values for lepton " << ilep);
474  ATH_MSG_VERBOSE("how many leptons are there? " << mmevt.nlep());
475  ATH_MSG_VERBOSE("nlep-ilep-1 = " << nlep-ilep-1);
476  ATH_MSG_VERBOSE("2 vals[0].size() = " << vals[0].size());
477  ATH_MSG_VERBOSE("vals[1].size() = " << vals[1].size());
478  vals[0][ilep] = mmevt.realEffObj(ilep);
479  if (m_doFakeFactor) {
480  vals[0][ilep].setToConst(1.0);
481  }
482  vals[1][ilep] = mmevt.fakeEffObj(ilep);
483  ATH_MSG_VERBOSE("Real and fake efficiencies for lepton " << ilep << ": " << vals[0][nlep-ilep-1].value(this) << " " << vals[1][nlep-ilep-1].value(this));
484  ATH_MSG_VERBOSE("this is surely harmless");
485  ATH_MSG_VERBOSE("3 vals[0].size() = " << vals[0].size());
486  }
487 
488  FakeBkgTools::Efficiency curr_coeff_num;
489  ATH_MSG_VERBOSE("how many uncertainties in curr_coeff_num? " << curr_coeff_num.uncertainties.size());
490  for (int irf = 0; irf < rank; irf++) {
491  for (int itl = 0; itl < rank; itl++) {
492  curr_coeff_num.setToConst(1.);
493  for (int ilep = 0; ilep < nlep; ilep++) {
494  if (itl & (0x1 << ilep) ) {
495  if (irf & (0x1 << ilep)) {
496  FakeBkgTools::Efficiency tmpEff = vals[1][ilep];
497  curr_coeff_num.multiply(tmpEff.subFromOne());
498  } else {
499  FakeBkgTools::Efficiency tmpEff = vals[0][ilep];
500  curr_coeff_num.multiply(tmpEff.subFromOne());
501  }
502  } else {
503  if (irf & (0x1 << ilep) ) {
504  curr_coeff_num.multiply(vals[1][ilep]);
505  } else {
506  curr_coeff_num.multiply(vals[0][ilep]);
507  }
508  }
509  }
510  ATH_MSG_VERBOSE("about to set m_coeffs_num[" << lepidx << "][" << itl << "][" << irf << "]");
511  ATH_MSG_VERBOSE("setting normterm " << (itl<<nlep) + irf);
512  fitInfo.normterms[lepidx][(itl<<nlep) + irf].add(curr_coeff_num);
513  fitInfo.coeffs_num[lepidx][itl][irf].add(curr_coeff_num);
514  ATH_MSG_VERBOSE("how many uncertainties in coeffs_num? " << fitInfo.coeffs_num[lepidx][itl][irf].uncertainties.size());
515  ATH_MSG_VERBOSE("done setting normterm ");
516  }
517  }
518  return StatusCode::SUCCESS;
519  } else {
520  ATH_MSG_ERROR( "Error: can only handle " << s_nLepMax << " leptons; you tried " << nlep);
521  return StatusCode::FAILURE;
522  }
523 
524 }
525 
527 
528  m_current_lhoodMM_tool = this;
529 
530  for (int ilep = 0; ilep < m_maxnlep_loose; ilep++) {
531  for (int jlep = 0; jlep < ilep; jlep++) {
532  if (m_current_fitInfo->OSfrac_denom[ilep][jlep] > 0) {
533  m_OSfrac[ilep][jlep] = m_current_fitInfo->OSfrac_num[ilep][jlep]/m_current_fitInfo->OSfrac_denom[ilep][jlep];
534  } else {
535  m_OSfrac[ilep][jlep] = 1.;
536  }
537  }
538  }
539 
540  return StatusCode::SUCCESS;
541 }
542 
543 
544 double LhoodMM_tools::logPoisson(double obs, double pred) {
545 
546  double f = -(obs*TMath::Log(pred)-pred);
547  if (obs > 0) f += obs*TMath::Log(obs)-obs;
548  return f;
549 }
550 
551 #ifdef FAKEBKGTOOLS_ATLAS_ENVIRONMENT
552 #define ASG_MSG_VERBOSE(x) do { if ( m_current_lhoodMM_tool->msgLvl(MSG::VERBOSE)) m_current_lhoodMM_tool->msg(MSG::VERBOSE) << x << endmsg; } while(0)
553 #else
554 #define ASG_MSG_VERBOSE(x) do { if(m_current_lhoodMM_tool->msgLvl(MSG::VERBOSE)) std::cout << x << std::endl; } while (0)
555 #endif
556 
557 void LhoodMM_tools::fcn_minnlep_maxnlep(Int_t &npar, Double_t *gin, Double_t &f, Double_t *par, Int_t iflag)
558 {
559 
561 
562  const bool verbose = (l->m_printLevel > 0);
563 
564  if (verbose) {
565  ASG_MSG_VERBOSE("Parameters input to fcn_minnlep_maxnlep:" );
566  for (int ipar = 0; ipar < npar; ipar++) {
567  ASG_MSG_VERBOSE(ipar << ": " << par[ipar]);
568  }
569  }
570  int minnlep = l->m_minnlep;
571  int maxnlep_loose = l->m_maxnlep_loose;
572 
573  Double_t f_tot = 0.;
574 
575  Double_t rsq = par[0];
576 
577  Double_t sinterm_tot = 1.;
578 
579  int theta_nlep_index = 1 + maxnlep_loose -minnlep;
580  ASG_MSG_VERBOSE("theta_nlep_index initial = " << theta_nlep_index);
581  for (int ilep = minnlep; ilep <= maxnlep_loose; ilep++) {
582  theta_nlep_index += l->m_real_indices[ilep-1].size();
583  ASG_MSG_VERBOSE("theta_nlep_index for ilep = " << ilep << " = " << theta_nlep_index);
584  }
585 
586  Double_t pars_thisnlep[s_maxRank]; // a bit of a waste of memory, but avoids compiler warnings for variable-
587 
588  if(verbose) ASG_MSG_VERBOSE("theta_nlep_index = " << theta_nlep_index);
589 
590  int real_index = 1;
591  for (int ilep = minnlep; ilep <= maxnlep_loose; ilep++) {
592  if (l->m_current_fitInfo->eventCount[ilep-1] == 0) {
593  ASG_MSG_VERBOSE("m_real_indices[" << ilep-1 << "].size() = " << l->m_real_indices[ilep-1].size());
594  real_index += l->m_real_indices[ilep-1].size();
595  for (int ipar = 0; ipar < (int)l->m_fake_indices[ilep-1].size()-1; ipar++) {
596  theta_nlep_index++;
597  }
598  continue;
599  }
600  l->m_curr_nlep = ilep;
601  Int_t npar_thisnlep = 0x1 << ilep;
602 
603  int theta_tot_index = l->m_theta_tot_start_index+ilep-minnlep;
604  if(verbose) ASG_MSG_VERBOSE("theta_tot_index, npar = " << theta_tot_index << " " << npar);
605  if(verbose) ASG_MSG_VERBOSE("sinterm_tot, par[theta_tot_index] = " << sinterm_tot << " " << par[theta_tot_index]);
606  if (l->m_maxnlep_loose - minnlep > 0) {
607  double costerm;
608  if (ilep < l->m_maxnlep_loose ) {
609  costerm = TMath::Cos(par[theta_tot_index]);
610  } else {
611  costerm = 1.;
612  }
613  if(verbose) ASG_MSG_VERBOSE("r sinterm_tot costerm = " << rsq <<" " << sinterm_tot << " " << costerm);
614  pars_thisnlep[0] = rsq*sinterm_tot*costerm*sinterm_tot*costerm;
615  sinterm_tot *= TMath::Sin(par[theta_tot_index]);
616  } else {
617  pars_thisnlep[0] = rsq;
618  }
619  if(verbose) ASG_MSG_VERBOSE("pars_thisnlep[0] = " << pars_thisnlep[0]);
620  int par_index = 1;
621  ASG_MSG_VERBOSE("m_real_indices[ilep-1].size() = " << l->m_real_indices[ilep-1].size());
622  for (unsigned ipar = 0; ipar < l->m_real_indices[ilep-1].size(); ipar++) {
623  pars_thisnlep[par_index] = par[real_index+ipar];
624  if(verbose) ASG_MSG_VERBOSE("r pars_thisnlep[" << par_index << "] = " << pars_thisnlep[par_index]);
625  par_index++;
626  }
627 
628  for (int ipar = 0; ipar < (int)l->m_fake_indices[ilep-1].size()-1; ipar++) {
629  ASG_MSG_VERBOSE("theta_nlep_index = " << theta_nlep_index );
630  pars_thisnlep[par_index+ipar] = par[theta_nlep_index];
631  if(verbose) ASG_MSG_VERBOSE("f pars_thisnlep[" << par_index+ipar <<"] = " << pars_thisnlep[par_index+ipar]);
632  theta_nlep_index++;
633  }
634  fcn_nlep(npar_thisnlep, gin, f, pars_thisnlep, iflag);
635  f_tot += f;
636 
637  real_index += l->m_real_indices[ilep-1].size();
638  }
639 
640  f = f_tot;
641 }
642 
643 void LhoodMM_tools::fcn_nlep(Int_t &npar, Double_t *, Double_t &f, Double_t *par, Int_t)
644 {
645 
647 
648  const bool verbose = (l->m_printLevel > 0);
649 
650  int nlep = l->m_curr_nlep;
651  int lepidx = nlep-1;
652  int rank = 0x1 << nlep;
653 
654  if(verbose) {
655  ASG_MSG_VERBOSE("npar = " << npar);
656  for (int ipar = 0; ipar < npar; ipar++) {
657  ASG_MSG_VERBOSE("Parameter " << ipar << " = " << par[ipar]);
658  }
659  }
660 
661  if(verbose) {
662  std::string txt = "testing variable transform: angle pars in fcn: ";
663  for (int i = 0; i < npar; i++) {
664  txt += std::to_string(par[i]) + " ";
665  }
667  }
668 
669  // remaining parameters are the angles used to divide up the fakes contribution
670 
671  std::shared_ptr<TMatrixT<double>> nrf, MMmatrix, ntlpred;
672  nrf = l->m_nrf_mat_vec[lepidx];
673  if(verbose) {
674  ASG_MSG_VERBOSE("What does nrf look like?");
675  nrf->Print();
676  }
677  MMmatrix = l->m_MMmatrix_vec[lepidx];
678  ntlpred = l->m_ntlpred_vec[lepidx];
679 
680  (*nrf)(0,0) = par[0];
681  double rsq = TMath::Abs(par[0]);
682  if(verbose) ASG_MSG_VERBOSE("rsq = " << rsq);
683  int rsize = l->m_real_indices[lepidx].size();
684  int fsize = l->m_fake_indices[lepidx].size();
685 
686  for (int ipar = 0; ipar < rsize; ipar++) {
687  ASG_MSG_VERBOSE("In fcn, setting real par " << l->m_real_indices[lepidx][ipar] << " to " << par[ipar+1]);
688  (*nrf)(l->m_real_indices[lepidx][ipar], 0) = par[ipar+1];
689  }
690  double sinterm = 1.;
691 
692  if(verbose) ASG_MSG_VERBOSE("nrf[0] = " << (*nrf)(0,0));
693 
694  for (int ipar = 0; ipar < fsize; ipar++) {
695  if(verbose) ASG_MSG_VERBOSE("r, sinterm, par[ipar+1] " << rsq << " " << sinterm << " " << par[ipar+1]);
696  if (ipar < fsize-1 ) {
697  double costerm = TMath::Cos(par[rsize+ipar+1]);
698  if(verbose) ASG_MSG_VERBOSE("for setting fake parameter, sinterm = " << sinterm << " par index = " << l->m_real_indices[lepidx].size()+ipar+1);
699  (*nrf)(l->m_fake_indices[lepidx][ipar],0) = rsq*sinterm*costerm*sinterm*costerm;
700  } else {
701  (*nrf)(l->m_fake_indices[lepidx][ipar],0) = rsq*sinterm*sinterm;
702  }
703 
704  ASG_MSG_VERBOSE("nrf[" << ipar << "] = " << (*nrf)(ipar,0));
705  ASG_MSG_VERBOSE("In fcn, setting fake par " << l->m_fake_indices[lepidx][ipar] << " to " << (*nrf)(l->m_fake_indices[lepidx][ipar],0));
706 
707  sinterm *= TMath::Sin(par[rsize+ipar+1]);
708  }
709 
710  ASG_MSG_VERBOSE("Testing variable transform: nrf in fcn: ");
711  if(verbose) {
712  nrf->Print();
713  }
714 
715  *ntlpred = (*MMmatrix)*(*nrf);
716 
717  ASG_MSG_VERBOSE("Printing the matrix in fcn");
718  if(verbose) {
719  MMmatrix->Print();
720  nrf->Print();
721  }
722  f = 0;
723  int ipar_start;
724  if (l->m_doFakeFactor) {
725  ipar_start = 1;
726  } else {
727  ipar_start = 0;
728  }
729 
730  for (int ipar = ipar_start; ipar < rank; ipar++) {
731  if(verbose) ASG_MSG_VERBOSE("Comparing parameter " << ipar << ": " << l->m_current_fitInfo->event_cat.at(lepidx).at(ipar) << " to " << (*ntlpred)(ipar,0));
732  // following scaling for weighted events motivated by arXiv:1309.1287
733  int nobs = l->m_current_fitInfo->event_cat.at(lepidx).at(ipar);
734  double s = 1.;
735  if (nobs > 0) {
736  s= l->m_current_fitInfo->event_sumw2.at(lepidx).at(ipar)/nobs;
737  }
738  if (verbose) ASG_MSG_VERBOSE("s = " << s);
739  f += logPoisson(1.*nobs/s, (*ntlpred)(ipar,0)/s);
740  if (verbose) ASG_MSG_VERBOSE("f = " << f);
741  }
742 
743 }
744 
745 
746 double LhoodMM_tools::nfakes(Double_t *poserr, Double_t *negerr) {
747 
748  if (m_current_fitInfo->totEvents == 0) {
749  *poserr = 0.;
750  *negerr = 0.;
751  return 0.;
752  }
753 
754  m_fitStatus = 0;
755 
757  m_maxnlep = 0;
758 
759  m_requireSS = false;
760  m_requireOS = false;
761 
762  for (int ilep = 0; ilep < s_nLepMax; ilep++) {
763  string error;
764  // possible issue here -- reassigning vector elements?
765  m_fsvec[ilep].reset(new FakeBkgTools::FinalState(0, ilep+1, m_selection, m_process, error));
766  if (error.size() > 0) {
767  ATH_MSG_VERBOSE("Unable to parse selection " << m_selection << " with process " << m_process << " with " << ilep+1 << " leptons. Error is " << error);
768  continue; // unable to parse selection
769  }
770  if (m_fsvec[ilep]->hasSS() ) {
771  m_requireSS = true;
772  }
773  if (m_fsvec[ilep]->hasOS() ) {
774  m_requireOS = true;
775  }
776  m_fsvec[ilep]->setSS(false);
777  m_fsvec[ilep]->setOS(false);
778 
779  // charges will only give the charges of the leptons in the most recently
780  // added event. That's why the tricks with the hasSS, hasOS, setSS, and
781  // setOS functions are played above (so we don't actually have to care
782  // about the values here)
783  auto charges = m_fsvec[ilep]->retrieveCharges(m_particles);
784 
785  for (int icomb = 0; icomb < (0x1 << (ilep+1)); icomb++) {
786  FakeBkgTools::FSBitset tights(icomb);
787  ATH_MSG_VERBOSE("ilep " << ilep << " (0x1 << ilep) " << std::hex << (0x1 << ilep) << " icomb " << std::hex << icomb << std::dec);
788  ATH_MSG_VERBOSE("tights = " << std::hex << tights << std::dec);
789  ATH_MSG_VERBOSE("charges = " << std::hex << charges << std::dec);
790 
791  if (m_fsvec[ilep]->accept_selection(tights, charges)) {
792  int nlep = ilep+1;
793  ATH_MSG_VERBOSE("tights = " << std::hex << tights << std::dec << " nlep = " << nlep);
794  if (nlep > m_maxnlep) m_maxnlep = nlep;
795  if (nlep < m_minnlep) m_minnlep = nlep;
796  }
797  }
798 
799  }
800 
801  //protect against selection strings that don't explicitly require at least
802  //one lepton
803  if (m_minnlep < 1) m_minnlep = 1;
804 
805  ATH_MSG_VERBOSE("m_minnlep, m_maxnlep = " << m_minnlep << " " << m_maxnlep);
806  int minNlep_proc = m_maxnlep;
807  int maxNlep_proc = 0;
808  for (int n=m_minnlep;n<=m_maxnlep;++n) {
809  for(unsigned c=0;c<(1u<<n);++c) // loop on all possible n-particles tight/loose combinations; there are 2^n of them
810  {
811  FakeBkgTools::FSBitset fakes = c;
812  FakeBkgTools::FSBitset reals = 0;
813  FakeBkgTools::FSBitset tights = 0;
814  for (int ibit = 0; ibit < n; ibit++) {
815  reals.set(ibit, ~fakes[ibit]);
816  tights.set(ibit, 1);
817  }
818  if (m_fsvec[n-1]->accept_process(n, reals, tights) ) {
819  if(n < minNlep_proc) minNlep_proc = n; // minNlep set to "number of tight leptons in the combination with the least number fo tight leptons"
820  if (n > maxNlep_proc) {
821  maxNlep_proc = n;
822  }
823  ATH_MSG_VERBOSE("maxNlep_proc = "<< maxNlep_proc);
824  break;
825  }
826  }
827  }
828 
829  m_minnlep = minNlep_proc;
830  m_maxnlep = maxNlep_proc;
831 
832  if(setup() != StatusCode::SUCCESS) return 0.;
833 
834  if (m_maxnlep > m_maxnlep_loose) {
836  }
837 
838  if (m_maxnlep_loose < m_minnlep) {
839  ATH_MSG_WARNING("Selection requires more leptons than are in any event in the sample; returning nfakes = 0 +/- 0 " << m_maxnlep_loose);
840  *poserr = 0.;
841  *negerr = 0.;
842  return 0.;
843  }
844 
845  ATH_MSG_VERBOSE("In nfakes, m_minnlep, m_maxnlep, m_maxnlep_loose = " << m_minnlep << " " << m_maxnlep << " " << m_maxnlep_loose);
846 
847  double nfake_fit, nfake_fitErr;
848 
849  int npar = 0;
850  for (int ilep = m_minnlep; ilep <= m_maxnlep_loose; ilep++) {
851  npar += 0x1 << ilep;
852  }
853 
854  ATH_MSG_VERBOSE("In nfakes, npar = " << npar);
855 
856  std::unique_ptr<TMinuit_LHMM> lhoodFit(new TMinuit_LHMM(npar));
857  lhoodFit->SetPrintLevel(m_printLevel);
858  lhoodFit->SetFCN(fcn_minnlep_maxnlep);
859 
860 
861  Double_t arglist[10];
862  Int_t ierflg = 0;
863 
864  arglist[0] = 0.5;
865  lhoodFit->mnexcm("SET ERR", arglist ,1,ierflg);;
866 
867  m_nfakes_std = 0;
868  m_nfakes_std_err = 0;
869 
870  ATH_MSG_VERBOSE("About to initialize parameters");
871 
872  vector<double> init_pars;
873  init_pars.resize(npar);
874  int index = 0;
875  vector< vector <double> > loc_init_pars;
876  loc_init_pars.resize(m_maxnlep_loose);
877 
878  for (int ilep = m_minnlep; ilep <=m_maxnlep_loose; ilep++) {
879  loc_init_pars[ilep-1].resize(0x1 << ilep);
880  get_init_pars(loc_init_pars[ilep-1], ilep);
881  for (int ipar = 0; ipar < (0x1 << ilep); ipar++) {
882  init_pars[index+ipar] = loc_init_pars[ilep-1][ipar];
883  }
884  index+= 0x1 << ilep;
885  }
886 
887  Double_t step = TMath::Max(loc_init_pars[m_minnlep-1][0]/1000,0.001);
888  ATH_MSG_VERBOSE("parameters initialized OK");
889  ATH_MSG_VERBOSE("m_nfakes_std_err = " << m_nfakes_std_err);
890 
891  m_nfakes_std_err = TMath::Sqrt(m_nfakes_std_err);
892 
893  vector<TString> parameterName;
894  vector<int> nreal_start_indices;
895  nreal_start_indices.resize(m_maxnlep_loose);
896  parameterName.push_back("nfake_tot");
897  TString sreal = "nreal";
898  for (int ilep = m_minnlep; ilep<= m_maxnlep_loose; ilep++) {
899  char tmpchar[20];
900  sprintf(tmpchar, "_%i", ilep);
901  TString tmpstr = sreal;
902  tmpstr.Append(tmpchar);
903  for (unsigned isublep = 0; isublep < m_real_indices[ilep-1].size(); isublep++) {
904  TString locsreal = tmpstr;
905  char tmpchar2[20];
906  sprintf(tmpchar2, "_%u", isublep);
907  locsreal.Append(tmpchar2);
908  parameterName.push_back(locsreal);
909  if (isublep == 0) {
910  nreal_start_indices[ilep-1] = (parameterName.size());
911  ATH_MSG_VERBOSE("nreal_start_indices[" << ilep-1 << "] = " << nreal_start_indices[ilep-1]);
912  }
913  }
914  }
915 
916  TString stheta_tot = "theta_tot";
917  for (int ilep = m_minnlep; ilep<m_maxnlep_loose; ilep++) {
918  char tmpchar[20];
919  sprintf(tmpchar, "_%i", ilep-m_minnlep);
920  TString tmpstr = stheta_tot;
921  tmpstr.Append(tmpchar);
922  parameterName.push_back(tmpstr);
923  }
924 
925  for (int ilep = m_minnlep; ilep <= m_maxnlep_loose; ilep++) {
926  TString stheta = "theta_";
927  char tmpchar[20];
928  sprintf(tmpchar, "%i", ilep);
929  TString tmpstr = stheta;
930  tmpstr.Append(tmpchar);
931  tmpstr.Append("_");
932  ATH_MSG_VERBOSE("How many fake indices?" << m_fake_indices[ilep-1].size());
933  for(int jlep = 0; jlep < (int)m_fake_indices[ilep-1].size() - 1; jlep++) {
934  TString locstheta = tmpstr;
935  char tmpchar2[20];
936  sprintf(tmpchar2, "%i", jlep);
937  locstheta.Append(tmpchar2);
938  parameterName.push_back(locstheta);
939  }
940 
941  }
942 
943  vector<double> theta_tot;
944  ATH_MSG_VERBOSE("m_maxnlep_loose = " << m_maxnlep_loose << " m_minnlep = " << m_minnlep);
945  theta_tot.resize(m_maxnlep_loose-m_minnlep);
946  ATH_MSG_VERBOSE("theta_tot.size() = " << theta_tot.size());
947  ATH_MSG_VERBOSE("m_nfakes_std = " << m_nfakes_std);
948  if (m_nfakes_std > 0.) {
949  double sinterm = 1.;
950  int theta_index = 0;
951  for (int ilep = m_minnlep; ilep < m_maxnlep_loose; ilep++ ){
952  ATH_MSG_VERBOSE("nfakes for nlep = " << ilep << " used to find theta_tot = " << loc_init_pars[ilep-1][0]);
953  theta_tot[theta_index] = TMath::ACos(TMath::Sqrt(TMath::Max(loc_init_pars[ilep-1][0],0.)/(m_nfakes_std))/sinterm);
954  if (TMath::IsNaN( theta_tot[theta_index] ) ) {
955  theta_tot[theta_index] = s_piover4;
956  }
957  sinterm *= TMath::Sin(theta_tot[theta_index]);
958  theta_index++;
959  }
960  } else {
961  int theta_index = 0;
962  for (int ilep = m_minnlep; ilep < m_maxnlep_loose; ilep++ ){
963  theta_tot[theta_index] = s_piover4;
964  theta_index++;
965  }
966  }
967 
968  ATH_MSG_VERBOSE("About to set upper limits");
969  vector<double> upper_limits;
970  upper_limits.resize(npar);
971 
972  upper_limits[0] = TMath::Max(5.*m_maxWeight*m_current_fitInfo->totEvents, 0.01);
973 
974  int real_index = 1;
975  for (int ilep = m_minnlep; ilep <= m_maxnlep_loose; ilep++) {
976  for (unsigned isublep = 0; isublep < m_real_indices[ilep-1].size(); isublep++) {
977  upper_limits[real_index] = 5*m_maxWeight*m_current_fitInfo->eventCount[ilep-1];
978  real_index++;
979  }
980  }
981 
982  for (int ipar = real_index; ipar < npar; ipar++) {
983  upper_limits[ipar] = s_piover2;
984  }
985 
986  //re-organize from "per-lepton" parameters to global parameters
987  vector<double> init_par_values;
988  init_par_values.resize(npar);
989  ATH_MSG_VERBOSE("Setting parameter 0 to " << TMath::Max(m_nfakes_std,0.5));
990  init_par_values[0] = TMath::Max(m_nfakes_std,0.);
991  int init_index = 1;
992  int glob_index = 1;
993  for (int ilep= m_minnlep; ilep <= m_maxnlep_loose; ilep++) {
994  for (unsigned isublep = 0; isublep < m_real_indices[ilep-1].size(); isublep++) {
995  ATH_MSG_VERBOSE("Setting parameter " << glob_index << " to " << init_pars[init_index+isublep]);
996  init_par_values[glob_index] = init_pars[init_index+isublep];
997  glob_index++;
998  }
999  init_index+= pow(2,ilep);
1000  }
1001 
1003  for (int ilep = m_minnlep; ilep <= m_maxnlep_loose; ilep++) {
1004  m_theta_tot_start_index += m_real_indices[ilep-1].size();
1005  }
1006  vector<int> theta_start_indices;
1007  theta_start_indices.resize(m_maxnlep_loose);
1008  theta_start_indices[m_minnlep-1] = m_theta_tot_start_index+m_maxnlep_loose - m_minnlep;
1009  for (int i = m_minnlep; i < m_maxnlep_loose; i++) {
1010  theta_start_indices[i] = theta_start_indices[i-1] + m_fake_indices[i-1].size() - 1;
1011  }
1012 
1013  for (int ilep= m_minnlep; ilep < m_maxnlep_loose; ilep++) {
1014  ATH_MSG_VERBOSE("Setting parameter " << m_theta_tot_start_index+ilep-m_minnlep << " to " << theta_tot[ilep-m_minnlep]);
1015  init_par_values[m_theta_tot_start_index+ilep-m_minnlep] = theta_tot[ilep-m_minnlep];
1016  }
1017 
1018  ATH_MSG_VERBOSE( "all done!");
1019 
1021  index = 1;
1022  for (int ilep= m_minnlep; ilep <= m_maxnlep_loose; ilep++) {
1023  for (int ipar = 0; ipar < (int)m_fake_indices[ilep-1].size() - 1; ipar++) {
1024  ATH_MSG_VERBOSE("Setting parameter " << currpar << " to " << init_pars[index+m_real_indices[ilep-1].size()+ipar]);
1025  init_par_values[currpar] = init_pars[index+m_real_indices[ilep-1].size()+ipar];
1026  currpar++;
1027  }
1028  index+= 0x1 << ilep;
1029  }
1030  int ipar;
1031  for (ipar = 0; ipar < npar; ipar++) {
1032  lhoodFit->mnparm(ipar, parameterName[ipar], init_par_values[ipar], step, 0., upper_limits[ipar], ierflg);
1033  }
1034 
1035  ATH_MSG_VERBOSE("About to fix some parameters");
1036  ATH_MSG_VERBOSE("m_minnlep = " << m_minnlep);
1037  ATH_MSG_VERBOSE("m_maxnlep_loose = " << m_maxnlep_loose);
1038  // account for case where there may be no leptons of a given multiplicity
1039  // (or no fake leptons allowed by the process string) by
1040  // fixing the parameters that are relevant to that multiplicity.
1041  // Also check that at least one lepton multiplicity is valid
1042 
1043  int nGoodLeptonMult = 0;
1044 
1045  for (int ilep = m_minnlep; ilep <= m_maxnlep_loose; ilep++) {
1046  if (m_current_fitInfo->eventCount[ilep-1] == 0 ||
1047  m_fake_indices[ilep-1].size() == 0) {
1048  // start with the nreal parameters
1049  for (unsigned ipar = nreal_start_indices[ilep-1]; ipar < nreal_start_indices[ilep-1] + m_real_indices[ilep-1].size(); ipar++) {
1050  arglist[0] = ipar;
1051  arglist[1] = 0.;
1052  lhoodFit->mnexcm("SET PAR", arglist, 2, ierflg);
1053  lhoodFit->mnexcm("FIX PAR", arglist, 1, ierflg);
1054  }
1055  //now the theta_tot angle associated with this multiplicity
1056  arglist[0] = m_theta_tot_start_index + ilep - m_minnlep +1;
1057  arglist[1] = s_piover2;
1058  lhoodFit->mnexcm("SET PAR", arglist, 2, ierflg);
1059  lhoodFit->mnexcm("FIX PAR", arglist, 1, ierflg);
1060 
1061  //now all the angle parameters for this lepton multiplicity
1062  for (unsigned ipar = theta_start_indices[ilep-1]+1; ipar < theta_start_indices[ilep-1] + m_fake_indices[ilep-1].size() ; ipar++) {
1063  arglist[0] = ipar;
1064  arglist[1] = 0.;
1065  lhoodFit->mnexcm("SET PAR", arglist, 2, ierflg);
1066  lhoodFit->mnexcm("FIX PAR", arglist, 1, ierflg);
1067  }
1068  } else {
1069  nGoodLeptonMult++;
1070  }
1071  index += (0x1 << ilep) - 2;
1072  }
1073 
1074  if (nGoodLeptonMult == 0) {
1075  ATH_MSG_VERBOSE("No possible fake contribution for any lepton multiplicity");
1076  *poserr = 0;
1077  *negerr = 0;
1078  return 0;
1079  }
1080 
1081  arglist[0] = 5000;
1082  arglist[1] = 1.0;
1083  lhoodFit->mnexcm("MIGRAD", arglist ,2,ierflg);
1084  ATH_MSG_VERBOSE("ierflg = " << ierflg);
1085  lhoodFit->mnimpr();
1086 
1087  Double_t amin, edm, errdef;
1088  Int_t nvpar, nparx, icstat;
1089  lhoodFit->mnstat(amin,edm,errdef,nvpar,nparx,icstat);
1090 
1091  lhoodFit->GetParameter(0, nfake_fit, nfake_fitErr);
1092 
1093  Double_t gcc;
1094 
1095  if (poserr && negerr) {
1096  arglist[0] = 500;
1097  arglist[1] = 1.0;
1098  lhoodFit->mnexcm("MINOS", arglist ,2,ierflg);
1099  lhoodFit->mnerrs(0, *poserr, *negerr, nfake_fitErr, gcc);
1100 
1101  // re-retrieve fit values, since MINOS might have found a new minimum
1102  lhoodFit->mnstat(amin,edm,errdef,nvpar,nparx,icstat);
1103  lhoodFit->GetParameter(0, nfake_fit, nfake_fitErr);
1104 
1105  // check that MINOS succeeded. If not, fix it...
1106 
1107  if ( *poserr < 1.e-5) {
1108  *poserr = fixPosErr(nfake_fit, lhoodFit.get());
1109  }
1110  if (*negerr > -1.e-5 ) {
1111  *negerr = fixNegErr(nfake_fit, lhoodFit.get());
1112  }
1113  //resort to parabolic errors if all else fails
1114  if (*negerr > -1.e-5) {
1115  *negerr = -nfake_fitErr;
1116  // prevent negative error from extending below 0
1117  if (nfake_fit + *negerr < 0.) {
1118  *negerr = -nfake_fit;
1119  }
1120  }
1121 
1122  if (*poserr < 1.e-5) {
1123  *poserr = nfake_fitErr;
1124  }
1125 
1126  }
1127 
1128  return nfake_fit;
1129 
1130 }
1131 
1133 
1134  StatusCode status = StatusCode::SUCCESS;
1135 
1136  for (auto map1_iter=m_fitInfo_1dhisto_map.begin(); map1_iter != m_fitInfo_1dhisto_map.end(); map1_iter++) {
1137  auto & fitInfo_vec = map1_iter->second;
1138  TH1* histogram = map1_iter->first;
1139  status = fillHisto_internal(fitInfo_vec, histogram);
1140  }
1141 
1142  for (auto map2_iter=m_fitInfo_2dhisto_map.begin(); map2_iter != m_fitInfo_2dhisto_map.end(); map2_iter++) {
1143  auto& fitInfo_vec = map2_iter->second;
1144  TH2* histogram = (TH2*)map2_iter->first;
1145  status = fillHisto_internal(fitInfo_vec, histogram);
1146  ATH_MSG_VERBOSE("Inside fill code, mean = " << histogram->ProjectionX()->GetMean());
1147  }
1148 
1149  for (auto map3_iter=m_fitInfo_3dhisto_map.begin(); map3_iter != m_fitInfo_3dhisto_map.end(); map3_iter++) {
1150  auto& fitInfo_vec = map3_iter->second;
1151  TH3* histogram = (TH3*)map3_iter->first;
1152  status = fillHisto_internal(fitInfo_vec, histogram);
1153  ATH_MSG_VERBOSE("Inside fill code, mean = " << histogram->ProjectionX()->GetMean());
1154  }
1155 
1156  return status;
1157 }
1158 
1159 StatusCode LhoodMM_tools::fillHisto_internal(const std::vector< LhoodMMFitInfo>& fitInfo_vec, TH1* h) {
1160 
1161  // If fixNormalization is set to true, the fake yield for the entire sample
1162  // will be calculated first, and then the histogram will be scaled at the end
1163  // so that its normalization matches this yield. Otherwise, the sum of the
1164  // bin entries is not guaranteed to match yield calculated on the sample
1165  // as a whole.
1166 
1167  // As a general rule of thumb, if the histogram being created is the key one
1168  // for the analysis (e.g. used to set limits) then it's best to keep
1169  // fixNormalization false. On the other hand, if the analysis is based on
1170  // total yield, and the histogram is a control/validation plot, it's best
1171  // to set fixNormalization to true.
1172 
1173  int nbins = h->GetNcells();
1174 
1175  ATH_MSG_VERBOSE("nbins = " << nbins);
1176  Double_t nf, poserr, negerr, shift = 0.;
1177 
1178  for (int ibin = 0; ibin < nbins; ibin++) {
1179 
1180  m_current_fitInfo = &fitInfo_vec[ibin];
1181  int totEvents = m_current_fitInfo->totEvents;
1182  if (totEvents > 0) {
1183  ATH_MSG_VERBOSE("Filling bin " << ibin << " with " << totEvents << " events");
1184  nf = nfakes(&poserr, &negerr);
1185  h->SetBinContent(ibin, nf+shift);
1186  if (TMath::IsNaN(h->GetBinContent(ibin))) {
1187  h->SetBinContent(ibin,0.);
1188  h->SetBinError(ibin, 0.);
1189  } else {
1190  h->SetBinError(ibin,TMath::Max(poserr,-negerr));
1191  }
1192  } else {
1193  h->SetBinContent(ibin,0.);
1194  h->SetBinError(ibin, 0.);
1195  }
1196  ATH_MSG_VERBOSE("Result is " << h->GetBinContent(ibin) << " +/- " << h->GetBinError(ibin));
1197  }
1198 
1199 
1200  if (m_fixNormalization) {
1201  double poserr, negerr;
1202  double totFakes;
1203 
1205  totFakes = nfakes(&poserr, &negerr);
1206 
1207  // find total content of histogram, including under- and overflows
1208  double totHistContent = 0.;
1209  for (int ibin = 0; ibin < nbins; ibin++) {
1210  totHistContent += h->GetBinContent(ibin);
1211  }
1212 
1213  ATH_MSG_VERBOSE("totHistContent = " << totHistContent);
1214  ATH_MSG_VERBOSE("sum of weights = " << h->GetSumOfWeights());
1215 
1216  double scaleFactor;
1217  if (totHistContent > 0.) {
1218  scaleFactor = totFakes/totHistContent;
1219  } else {
1220  scaleFactor = 1.;
1221  }
1222  for (int ibin = 1; ibin <= nbins; ibin++) {
1223  h->SetBinContent(ibin, scaleFactor*h->GetBinContent(ibin));
1224  h->SetBinError(ibin, scaleFactor*h->GetBinError(ibin));
1225  }
1226  }
1227  return StatusCode::SUCCESS;
1228 }
1229 
1230 
1232 
1234  return m_nfakes_std;
1235 }
1236 
1238 
1241 }
1242 
1243 void LhoodMM_tools::get_init_pars(vector<double> &init_pars, int nlep) {
1244 
1245  ATH_MSG_VERBOSE("Setting initial parameters for nlep = " << nlep);
1246 
1247  int lepidx = nlep-1;
1248 
1249  vector<double> nrf;
1250  nrf.resize(0x1 <<nlep);
1251  get_analytic(nrf, nlep);
1252  m_real_indices[lepidx].clear();
1253  m_fake_indices[lepidx].clear();
1254 
1255  std::string txt = "Testing variable transform: Initial nrf: ";
1256  for (auto i = nrf.begin(); i != nrf.end(); ++i)
1257  txt += std::to_string(*i) + ' ';
1259 
1260  vector<double> init_angles;
1261 
1262  double nfakes_std_thisnlep = 0;
1263 
1264  ATH_MSG_VERBOSE("m_fsvec.size() = " << m_fsvec.size() );
1265  for (int ipar = 0; ipar < 0x1 <<nlep; ipar++) {
1266  ATH_MSG_VERBOSE("ipar = " << ipar );
1267  FakeBkgTools::FSBitset fakes = ipar;
1268  FakeBkgTools::FSBitset reals;
1269  for (int ibit = 0; ibit < nlep; ibit++) {
1270  reals.set(ibit, ~fakes[ibit]);
1271  }
1272  ATH_MSG_VERBOSE("reals set" );
1273  bool countsAsFake = false;
1274  for (int jpar = 0; jpar < 0x1 <<nlep; jpar++) {
1275  FakeBkgTools::FSBitset tights = jpar;
1276  for (int kpar = 0; kpar < 0x1 <<nlep; kpar++) {
1277  FakeBkgTools::FSBitset charges = kpar;
1278  if (!countsAsFake &&
1279  m_fsvec[lepidx]->accept_process(nlep, reals, tights) &&
1280  m_fsvec[lepidx]->accept_selection(tights, charges) ) {
1281  ATH_MSG_VERBOSE("accepted " << ipar);
1282  nfakes_std_thisnlep += nrf[ipar];
1283  m_fake_indices[lepidx].push_back(ipar);
1284  countsAsFake = true;
1285  break;
1286  }
1287  }
1288  }
1289  if (!countsAsFake) {
1290  ATH_MSG_VERBOSE("trying to push onto m_real_indices");
1291  ATH_MSG_VERBOSE("m_real_indices.size() = " << m_real_indices.size());
1292  m_real_indices[lepidx].push_back(ipar);
1293  }
1294  }
1295 
1296  init_pars[0] = nfakes_std_thisnlep;
1297  for (unsigned ipar = 1; ipar <= m_real_indices[lepidx].size(); ipar++) {
1298  init_pars[ipar] = nrf[m_real_indices[lepidx][ipar-1]];
1299  }
1300 
1301  if (nfakes_std_thisnlep > 0.5) {
1302  double sinterm = 1.;
1303  int ifake = 0;
1304  for (int ipar = m_real_indices[lepidx].size()+1; ipar < (0x1 << nlep); ipar++) {
1305  init_pars[ipar] = TMath::ACos(TMath::Sqrt(TMath::Max(nrf[m_fake_indices[lepidx][ifake] ], 0.)/(nfakes_std_thisnlep))/sinterm);
1306  sinterm *= TMath::Sin(init_pars[ipar]);
1307  ifake++;
1308  }
1309  } else {
1310  for (int ipar = m_real_indices[lepidx].size()+1; ipar < (0x1 << nlep); ipar++) {
1311  init_pars[ipar] = s_piover4;
1312  }
1313  }
1314 
1315  if (m_printLevel > 0) {
1316  txt = "testing variable transform: Initial pars: ";
1317  for (int i = 0; i < (0x1 << nlep); i++) {
1318  txt += std::to_string(init_pars[i]) + " ";
1319  }
1321  }
1322 
1323  // fix any nan's...
1324  for (int ipar = 2; ipar < (0x1 << nlep); ipar++) {
1325  if (TMath::IsNaN(init_pars[ipar])) {
1326  init_pars[ipar] = 0.;
1327  }
1328  ATH_MSG_VERBOSE("Setting angle parameter " << ipar << " to " << init_pars[ipar]);
1329  }
1330 }
1331 
1332 
1333 void LhoodMM_tools::get_analytic(vector<double>& nrf, const int nlep) {
1334 
1335  m_perfectFit = true;
1336  ATH_MSG_VERBOSE("just getting started with nlep = " << nlep);
1337 
1338  ATH_MSG_VERBOSE("m_minnlepreg = " << m_minnlep << " m_maxnlep = " << m_maxnlep);
1339 
1340 
1341  int lepidx = nlep-1;
1342 
1343  if (m_current_fitInfo->eventCount[lepidx] == 0) return;
1344 
1345  const int rank = 0x1 << nlep;
1346 
1347  std::vector<FakeBkgTools::Efficiency> coeff_denom(rank);
1348 
1349  ATH_MSG_VERBOSE("All set! ");
1350 
1351  FakeBkgTools::FSBitset charges = m_fsvec[lepidx]->retrieveCharges(m_particles);
1352  for (int irf = 0; irf < rank; irf++) {
1353  // add up all the relevant terms in the denominator to translate the
1354  // loose sample counts to tight sample counts within the required range of
1355  // tight lepton multiplicity
1356  coeff_denom[irf].setToConst(0.);
1357  coeff_denom[0] = m_current_fitInfo->coeffs_num[lepidx][0][0]; // don't care about this one, but it can't be 0
1358  float chargefactor ;
1359  FakeBkgTools::FSBitset fakes = irf;
1360  FakeBkgTools::FSBitset reals;
1361  for (int ibit = 0; ibit < nlep; ibit++) {
1362  reals.set(ibit, ~fakes[ibit]);
1363  }
1364  for (int itl = 0; itl < rank; itl++) {
1365  chargefactor = 1.0;
1366  FakeBkgTools::FSBitset antitights = itl;
1367  FakeBkgTools::FSBitset tights = 0;
1368  for (int ibit = 0; ibit < nlep; ibit++) {
1369  tights.set(ibit, ~antitights[ibit]);
1370  }
1371  ATH_MSG_VERBOSE("tights " << tights);
1372  ATH_MSG_VERBOSE("reals " << reals);
1373  ATH_MSG_VERBOSE("charges " << charges);
1374  if (m_fsvec[lepidx]->accept_selection(tights, charges)
1375  && m_fsvec[lepidx]->accept_process(nlep, reals, tights) ) {
1376  ATH_MSG_VERBOSE("Accepted in LhoodMM_tools " << irf);
1377  ATH_MSG_VERBOSE("index is " << (itl<<nlep) + irf);
1378  ATH_MSG_VERBOSE("Adding " << m_current_fitInfo->normterms[lepidx][(itl<<nlep) + irf].value(this) << " to " << irf);
1379  // assume that dilepton fakes are evenly split between OS and SS
1380  if (nlep > 2 && tights.count() == 2) {
1381  if (m_requireOS || m_requireSS) {
1382  chargefactor = 0.5;
1383  ATH_MSG_VERBOSE("Setting SSfactor ");
1384  }
1385  }
1386  if (nlep == 2 && tights.count() == 2) {
1387  if (m_requireOS || m_requireSS) {
1388  chargefactor = m_OSfrac[2][2];
1389  }
1390  }
1391  if (m_requireOS) {
1392  chargefactor = m_OSfrac[lepidx][tights.count()];
1393  }
1394  ATH_MSG_VERBOSE("chargefactor = " << chargefactor << " for nlep = " << nlep);
1395  ATH_MSG_VERBOSE("normterm = " << m_current_fitInfo->normterms[lepidx][(itl<<nlep) + irf].value(this));
1396  FakeBkgTools::Efficiency tmpEff = m_current_fitInfo->normterms[lepidx][(itl<<nlep) + irf];
1397  tmpEff.multiply(chargefactor);
1398  ATH_MSG_VERBOSE("how much space? " << coeff_denom.size());
1399  ATH_MSG_VERBOSE("irf = " << irf);
1400  coeff_denom[irf].add(tmpEff);
1401  ATH_MSG_VERBOSE("m_normterms[" << nlep << "][" << (itl<<nlep) + irf << "]= " << m_current_fitInfo->normterms[lepidx][(itl<<nlep) + irf].value(this));
1402  ATH_MSG_VERBOSE("chargefactor = " << chargefactor);
1403  ATH_MSG_VERBOSE("coeff_denom[" << irf << "] = " << coeff_denom[irf].value(this));
1404  }
1405  }
1406 
1407  // The following are "don't care" terms, but need to have non-zero
1408  // denominators
1409  if (coeff_denom[irf].nominal == 0.) {
1410  coeff_denom[irf] = m_current_fitInfo->coeffs_num[lepidx][0][irf];
1411  }
1412 
1413  for (int itl = 0; itl < rank; itl++) {
1414  ATH_MSG_VERBOSE("coeff_denom[" << irf << "] = " << coeff_denom[irf].value(this));
1415  m_coeffs[lepidx][itl][irf] = m_current_fitInfo->coeffs_num[lepidx][itl][irf].value(this)/coeff_denom[irf].value(this);
1416  }
1417  }
1418 
1419  ATH_MSG_VERBOSE("About to do matrix stuff");
1420  std::shared_ptr<TMatrixT<double>> MMmatrix;
1421  MMmatrix = m_MMmatrix_vec[lepidx];
1422 
1423  for (int i = 0; i < rank; i++) {
1424  for (int j = 0; j < rank; j++) {
1425  ATH_MSG_VERBOSE(i << " " << j << " " << m_current_fitInfo->coeffs_num[lepidx][i][j].value(this) << " " << coeff_denom[j].value(this) << " " << m_coeffs[lepidx][i][j]);
1426  (*MMmatrix)(i,j) = m_coeffs[lepidx][i][j];
1427  }
1428  }
1429 
1430  const bool verbose = this->msgLvl(MSG::VERBOSE);
1431  ATH_MSG_VERBOSE("Printing the matrix in get_analytic ");
1432  if(verbose) MMmatrix->Print();
1433 
1434  TMatrixT<double> MMmatrix_inv(rank,rank);
1435  MMmatrix_inv = *MMmatrix;
1436  MMmatrix_inv.Invert();
1437 
1438  TMatrixT<double> MMmatrix_sqr = MMmatrix_inv;
1439  for (int i = 0; i < rank; i++) {
1440  for (int j = 0; j < rank; j++) {
1441  MMmatrix_sqr(i,j) *= MMmatrix_sqr[i][j];
1442  }
1443  }
1444 
1445  TMatrixT<double> nevents_mat(rank,1), nfake_mat(rank,1), nfake_err_mat(rank,1);
1446  for (int i = 0; i < rank; i++) {
1447  nevents_mat(i,0) = m_current_fitInfo->event_cat.at(lepidx).at(i);
1448  }
1449 
1450  ATH_MSG_VERBOSE("Printing nevents matrix");
1451  if(verbose) nevents_mat.Print();
1452 
1453  nfake_mat = MMmatrix_inv*nevents_mat;
1454 
1455  ATH_MSG_VERBOSE("MMmatrix:");
1456  if(verbose) MMmatrix->Print();
1457  ATH_MSG_VERBOSE("nevents_lll_mat:");
1458  if(verbose) nevents_mat.Print();
1459  ATH_MSG_VERBOSE("nfake_mat:");
1460  if(verbose) nfake_mat.Print();
1461 
1462 
1463  nfake_err_mat = MMmatrix_sqr*nevents_mat;
1464 
1465  int n_proc_acc = 0;
1466  for (int ipar = 0; ipar < (0x1 <<nlep) ; ipar++) {
1467  nrf[ipar] = nfake_mat(ipar, 0);
1468  if (nrf[ipar] < 0) m_perfectFit = false;
1469  ATH_MSG_VERBOSE("nrf[" << ipar << "] = " << nrf[ipar]);
1470  FakeBkgTools::FSBitset fakes = ipar;
1471  FakeBkgTools::FSBitset reals;
1472  FakeBkgTools::FSBitset tights = 0;
1473  for (int ibit = 0; ibit < nlep; ibit++) {
1474  tights.set(ibit, 1);
1475  reals.set(ibit, ~fakes[ibit]);
1476  }
1477  if (m_fsvec[lepidx]->accept_process(nlep, reals, tights) && m_fsvec[lepidx]->accept_selection(tights, charges)) {
1478  ATH_MSG_VERBOSE("Adding " << nfake_mat(ipar,0) << " to m_nfakes_std");
1479  n_proc_acc++;
1480  m_nfakes_std += nfake_mat(ipar,0);
1481  m_nfakes_std_err += nfake_err_mat(ipar, 0);
1482  }
1483  }
1484 
1485  ATH_MSG_VERBOSE("Accepted " << n_proc_acc << " processes for nlep = " << nlep);
1486  ATH_MSG_VERBOSE("m_nfakes_std = " << m_nfakes_std);
1487 
1488 }
1489 
1490 double LhoodMM_tools::fixPosErr(double n_fake_fit, TMinuit_LHMM* lhoodFit) {
1491 
1492  ATH_MSG_VERBOSE("Trying to fix bad positive error");
1493 
1494  // get current value of -lnL
1495  Double_t f_from_fit, junk;
1496  Int_t ijunk;
1497 
1498  // do a binary search to find real value of positive error
1499  double n_fake_guess_hi = TMath::Max(n_fake_fit*5,1.);
1500  double n_fake_guess_lo = n_fake_fit;
1501  double n_fake_guess = n_fake_guess_hi;
1502  double f_with_guess;
1503 
1504  bool errFound = 0;
1505  bool stopSearch = 0;
1506 
1507  double convergeCriteria = 0.01;
1508 
1509  int nfake_tot_index = 1;
1510 
1511  Double_t arglist[10];
1512 
1513  int ierflg;
1514 
1515  arglist[0] = nfake_tot_index;
1516  arglist[1] = n_fake_fit;
1517  lhoodFit->mnexcm("SET PAR", arglist, 2, ierflg);
1518  lhoodFit->mnexcm("FIX PAR", arglist, 1, ierflg);
1519 
1520  arglist[0] = 10000;
1521  arglist[1] = 1.0;
1522  lhoodFit->mnexcm("MIGRAD", arglist ,2,ierflg);
1523  lhoodFit->mnimpr();
1524 
1525  lhoodFit->mnstat(f_from_fit, junk, junk, ijunk, ijunk, ijunk);
1526  ATH_MSG_VERBOSE("f_from_fit = " << f_from_fit);
1527 
1528  while (!stopSearch) {
1529  // fit with n_fake_tot fixed to guess value
1530  arglist[0] = nfake_tot_index;
1531  arglist[1] = n_fake_guess;
1532  lhoodFit->mnexcm("SET PAR", arglist, 2, ierflg);
1533  lhoodFit->mnexcm("FIX PAR", arglist, 1, ierflg);
1534 
1535  arglist[0] = 10000;
1536  arglist[1] = 1.0;
1537  lhoodFit->mnexcm("MIGRAD", arglist ,2,ierflg);
1538  lhoodFit->mnimpr();
1539 
1540  lhoodFit->mnstat(f_with_guess, junk, junk, ijunk, ijunk, ijunk);
1541 
1542  ATH_MSG_VERBOSE("nlep, n_fake_guess, n_fake_guess_lo, n_fake_guesss_hi, f_from_fit, f_with_guess: " << "?" << " " << n_fake_guess << " " << n_fake_guess_lo << " " << n_fake_guess_hi << " " << f_from_fit << " " << f_with_guess);
1543 
1544  if (TMath::IsNaN(f_with_guess)) {
1545  f_with_guess = f_from_fit + 1.;
1546  }
1547  if ((f_with_guess - f_from_fit) > 0.5) {
1548  n_fake_guess_hi = n_fake_guess;
1549  } else {
1550  n_fake_guess_lo = n_fake_guess;
1551  }
1552 
1553  n_fake_guess = 0.5*(n_fake_guess_lo+n_fake_guess_hi);
1554 
1555  ATH_MSG_VERBOSE( "n_fake_guess_lo, hi = " << n_fake_guess_hi << " " << n_fake_guess_lo);
1556  if ((n_fake_guess_hi - n_fake_guess_lo)/n_fake_guess_hi < convergeCriteria) {
1557  stopSearch = 1;
1558  ATH_MSG_VERBOSE("(n_fake_guess_lo, n_fake_fit = " << n_fake_guess_lo << " " << n_fake_fit);
1559  if (n_fake_guess_lo > n_fake_fit) {
1560  errFound = 1;
1561  }
1562 
1563  }
1564  }
1565 
1566  // reset nfakes to value found from original fit, so it's read out properly
1567  // later
1568  arglist[0] = nfake_tot_index;
1569  arglist[1] = n_fake_fit;
1570  lhoodFit->mnexcm("SET PAR", arglist, 2, ierflg);
1571 
1572  if (errFound) {
1573  return n_fake_guess - n_fake_fit;
1574  } else {
1575  ATH_MSG_VERBOSE("Setting fitStatus to 1 in fixPosErr");
1576  m_fitStatus = 1;
1577  return -1.;
1578  }
1579 }
1580 
1581 double LhoodMM_tools::fixNegErr(double n_fake_fit, TMinuit_LHMM* lhoodFit) {
1582 
1583  ATH_MSG_VERBOSE("Trying to fix bad negative error");
1584 
1585  // get current value of -lnL
1586  Double_t f_from_fit, junk;
1587  Int_t ijunk;
1588 
1589  lhoodFit->mnstat(f_from_fit, junk, junk, ijunk, ijunk, ijunk);
1590 
1591  // do a binary search to find real value of positive error
1592  double n_fake_guess_hi = n_fake_fit;
1593  double n_fake_guess_lo = 0.;
1594  double n_fake_guess = n_fake_guess_lo;
1595  double f_with_guess;
1596 
1597  bool errFound = 0;
1598  bool stopSearch = 0;
1599  double convergeCriteria = 0.01;
1600  double min_n_fake_guess = 0.05;
1601 
1602  int nfake_tot_index = 1;
1603 
1604  Double_t arglist[10];
1605 
1606  int ierflg;
1607 
1608  arglist[0] = nfake_tot_index;
1609  arglist[1] = n_fake_fit;
1610  lhoodFit->mnexcm("SET PAR", arglist, 2, ierflg);
1611  lhoodFit->mnexcm("FIX PAR", arglist, 1, ierflg);
1612 
1613  arglist[0] = 10000;
1614  arglist[1] = 1.0;
1615  lhoodFit->mnexcm("MIGRAD", arglist ,2,ierflg);
1616  lhoodFit->mnimpr();
1617 
1618  lhoodFit->mnstat(f_from_fit, junk, junk, ijunk, ijunk, ijunk);
1619 
1620  while (!stopSearch) {
1621  // fit with n_fake_tot fixed to guess value
1622 
1623 
1624  arglist[0] = nfake_tot_index;
1625  arglist[1] = n_fake_guess;
1626  lhoodFit->mnexcm("SET PAR", arglist, 2, ierflg);
1627  lhoodFit->mnexcm("FIX PAR", arglist, 1, ierflg);
1628 
1629  arglist[0] = 10000;
1630  arglist[1] = 1.0;
1631  lhoodFit->mnexcm("MIGRAD", arglist ,2,ierflg);
1632  lhoodFit->mnimpr();
1633  lhoodFit->mnstat(f_with_guess, junk, junk, ijunk, ijunk, ijunk);
1634 
1635  ATH_MSG_VERBOSE("nlep, n_fake_guess, n_fake_guess_lo, n_fake_guesss_hi, f_from_fit, f_with_guess: " << "?" << " " << n_fake_guess << " " << n_fake_guess_lo << " " << n_fake_guess_hi << " " << f_from_fit << " " << f_with_guess);
1636 
1637  if ((f_with_guess - f_from_fit) > 0.5) {
1638  n_fake_guess_lo = n_fake_guess;
1639  } else {
1640  n_fake_guess_hi = n_fake_guess;
1641  }
1642  n_fake_guess = 0.5*(n_fake_guess_lo+n_fake_guess_hi);
1643 
1644  if (((n_fake_guess_hi - n_fake_guess_lo)/n_fake_guess_hi < convergeCriteria) || (n_fake_guess_hi < min_n_fake_guess) ) {
1645  stopSearch = 1;
1646  if (n_fake_guess_hi < n_fake_fit) {
1647  errFound = 1;
1648  }
1649  }
1650  }
1651 
1652  // reset nfakes to value found from original fit, so it's read out properly
1653  // later
1654  arglist[0] = nfake_tot_index;
1655  arglist[1] = n_fake_fit;
1656  lhoodFit->mnexcm("SET PAR", arglist, 2, ierflg);
1657 
1658  if (errFound) {
1659  return n_fake_guess - n_fake_fit;
1660  } else {
1661  ATH_MSG_VERBOSE("Setting fitStatus to 1 in fixNegErr");
1662  m_fitStatus = 1;
1663  return 1.;
1664  }
1665 }
1666 
1668 
1669  ATH_MSG_VERBOSE("Saving progress");
1670 
1671  if (m_prevSave) {
1672  ATH_MSG_ERROR("Multiple calls to saveProgress are not supported");
1673  return StatusCode::FAILURE;
1674  }
1675 
1676  m_prevSave = true;
1677 
1678  std::unique_ptr<TTree> t(new TTree("LhoodMM_progress", "Stores current info from LhoodMM_toos"));
1679 
1680  std::unique_ptr<TTree> t_nlep(new TTree("LhoodMM_progress_nlep", "Stores minimum and maximum lepton multiplicities"));
1681 
1682  auto fitInfoBranch = t->Branch("glb_fitInfo", &m_global_fitInfo);
1683  ATH_MSG_VERBOSE("Branch split level is " << fitInfoBranch->GetSplitLevel() );
1684  t->Branch("fitInfo_1dhisto_map", &m_fitInfo_1dhisto_map);
1685  t->Branch("fitInfo_2dhisto_map", &m_fitInfo_2dhisto_map);
1686  t->Branch("fitInfo_3dhisto_map", &m_fitInfo_3dhisto_map);
1687 
1688  t_nlep->Branch("maxnlep", &m_maxnlep_loose);
1689 
1690  ATH_MSG_VERBOSE("Filling tree...");
1691  t->Fill();
1692  t_nlep->Fill();
1693  dir->cd();
1694  t->Write();
1695  t_nlep->Write();
1696 
1697  return StatusCode::SUCCESS;
1698 }
1699 
1701 
1702  ATH_MSG_VERBOSE("Merging sub jobs");
1703 
1704  m_alreadyMerged = true;
1706  std::unique_ptr<TFile> fin( new TFile(filename.c_str()));
1707  if (fin == nullptr) {
1708  ATH_MSG_ERROR("Unable to open merged input file " << filename );
1709  return StatusCode::FAILURE;
1710  }
1711  if(m_progressFileDirectory.length()) {
1712  if(!fin->cd(m_progressFileDirectory.c_str())) {
1713  ATH_MSG_ERROR("Unable to find the directory " << m_progressFileDirectory << " inside the file " << filename);
1714  return StatusCode::FAILURE;
1715  }
1716  }
1717 
1718  std::string prefix = (m_progressFileDirectory.length()? "/" + m_progressFileDirectory + "/" : "");
1719 
1720  TTree *t_nlep = (TTree*)fin->Get((prefix + "LhoodMM_progress_nlep").c_str());
1721  if (t_nlep == nullptr) {
1722  ATH_MSG_ERROR("Unable to find LhoodMM_progress_nlep tree in " << filename);
1723  return StatusCode::FAILURE;
1724  }
1725 
1726  int merged_maxnlep, merged_maxnlep_prev = -1;
1727  t_nlep->SetBranchAddress("maxnlep", &merged_maxnlep);
1728 
1729  TTree *t = (TTree*)fin->Get((prefix + "LhoodMM_progress").c_str());
1730  if (t == nullptr) {
1731  ATH_MSG_ERROR("Unable to find LhoodMM_progress tree in " << filename);
1732  return StatusCode::FAILURE;
1733  }
1734 
1735  // check that we are not trying to merge subjobs with inconsistent lepton
1736  // multiplicities
1737  Int_t nentries = (Int_t)t_nlep->GetEntries();
1738  for (Int_t ievt = 0; ievt < nentries; ievt++) {
1739  t_nlep->GetEntry(ievt);
1740  if (ievt > 0 && (merged_maxnlep != merged_maxnlep_prev)) {
1741  ATH_MSG_ERROR("Attempting to merge files with different lepton multiplicities. This is not supported.");
1742  return StatusCode::FAILURE;
1743  }
1744  merged_maxnlep_prev = merged_maxnlep;
1745  }
1746 
1747  m_maxnlep_loose = merged_maxnlep;
1748 
1749  std::unique_ptr<LhoodMMFitInfo> tmpFitInfo(new LhoodMMFitInfo);
1750 
1751  tmpFitInfo->resizeVectors(m_maxnlep_loose);
1753 
1754  LhoodMMFitInfo* fitInfoPtr = tmpFitInfo.get();
1755  t->SetBranchAddress("glb_fitInfo", &fitInfoPtr );
1756 
1757  ATH_MSG_VERBOSE("About to add LhoodMMFitInfos");
1758 
1759  // prepare to merge any histograms
1760 
1761  std::unique_ptr<std::map<TH1*, std::vector< LhoodMMFitInfo > > > tmp_fitInfo_1dhisto_map(new std::map<TH1*, std::vector< LhoodMMFitInfo > >);
1762  auto *tmp_fitInfo_1dhisto_map_ptr = tmp_fitInfo_1dhisto_map.get();
1763  t->SetBranchAddress("fitInfo_1dhisto_map", &tmp_fitInfo_1dhisto_map_ptr);
1764  std::unique_ptr<std::map<TH2*, std::vector< LhoodMMFitInfo > > > tmp_fitInfo_2dhisto_map(new std::map<TH2*, std::vector< LhoodMMFitInfo > >);
1765  auto *tmp_fitInfo_2dhisto_map_ptr = tmp_fitInfo_2dhisto_map.get();
1766  t->SetBranchAddress("fitInfo_2dhisto_map", &tmp_fitInfo_2dhisto_map_ptr);
1767  std::map<TH3*, std::vector< LhoodMMFitInfo > > *tmp_fitInfo_3dhisto_map = new std::map<TH3*, std::vector< LhoodMMFitInfo > >;
1768  t->SetBranchAddress("fitInfo_3dhisto_map", &tmp_fitInfo_3dhisto_map);
1769 
1770  nentries = (Int_t)t->GetEntries();
1771  for (Int_t ievt = 0; ievt < nentries; ievt++) {
1772  t->GetEntry(ievt);
1773  ATH_MSG_VERBOSE("Adding LhoodMMFitInto with " << (*tmpFitInfo).totEvents << " events, with m_maxnlep_loose = " << m_maxnlep_loose );
1774  m_global_fitInfo.add(*tmpFitInfo, m_maxnlep_loose);
1775  for (auto& hm : m_fitInfo_1dhisto_map) {
1776  TH1F* histogram = (TH1F*)hm.first;
1777  std::string hname = histogram->GetName();
1778  for (auto& im: *tmp_fitInfo_1dhisto_map) {
1779  ATH_MSG_VERBOSE("Found a matching histogram");
1780  TH1F* ihistogram = (TH1F*)im.first;
1781  std::string iname = ihistogram->GetName();
1782  if (hname == iname) {
1783  int ncells = histogram->GetNcells();
1784  for (int icell = 0; icell<ncells; icell++) {
1785  hm.second[icell].resizeVectors(m_maxnlep_loose);
1786  hm.second[icell].add(im.second[icell], m_maxnlep_loose);
1787  }
1788  }
1789  }
1790  }
1791  for (auto& hm : m_fitInfo_2dhisto_map) {
1792  TH1F* histogram = (TH1F*)hm.first;
1793  std::string hname = histogram->GetName();
1794  for (auto& im: *tmp_fitInfo_2dhisto_map) {
1795  ATH_MSG_VERBOSE("Found a matching histogram");
1796  TH1F* ihistogram = (TH1F*)im.first;
1797  std::string iname = ihistogram->GetName();
1798  if (hname == iname) {
1799  int ncells = histogram->GetNcells();
1800  for (int icell = 0; icell<ncells; icell++) {
1801  hm.second[icell].resizeVectors(m_maxnlep_loose);
1802  hm.second[icell].add(im.second[icell], m_maxnlep_loose);
1803  }
1804  }
1805  }
1806  }
1807  for(auto& hm : m_fitInfo_3dhisto_map){
1808  TH1F* histogram = (TH1F*)hm.first;
1809  std::string hname = histogram->GetName();
1810  for (auto& im: *tmp_fitInfo_3dhisto_map){
1811  ATH_MSG_VERBOSE("Found a matching histogram");
1812  TH1F* ihistogram = (TH1F*)im.first;
1813  std::string iname = ihistogram->GetName();
1814  if (hname == iname) {
1815  int ncells = histogram->GetNcells();
1816  for (int icell = 0; icell<ncells; icell++) {
1817  hm.second[icell].resizeVectors(m_maxnlep_loose);
1818  hm.second[icell].add(im.second[icell], m_maxnlep_loose);
1819  }
1820  }
1821  }
1822  }
1823 
1824  ATH_MSG_VERBOSE("Added " << ievt);
1825 
1826  }
1827 
1828 
1829  ATH_MSG_VERBOSE("Merged totEvents is " << m_global_fitInfo.totEvents);
1830  for (int ilep = 0; ilep < m_maxnlep_loose; ilep++) {
1831  ATH_MSG_VERBOSE("Merged event count is " << m_global_fitInfo.eventCount[ilep]);
1832  }
1833 
1834  return StatusCode::SUCCESS;
1835 }
1836 
1837 
1838 
1839 
CP::LhoodMM_tools::m_nfakes_std_err_perEventWeight
double m_nfakes_std_err_perEventWeight
Definition: LhoodMM_tools.h:123
CP::BaseFakeBkgTool::register1DHistogram
virtual StatusCode register1DHistogram(TH1 *h1, const float *val) override
associates a 1D histogram to the tool, to obtain a binned estimate of the fake lepton background the ...
Definition: BaseFakeBkgTool.cxx:240
CP::LhoodMM_tools::s_piover4
static const double s_piover4
Definition: LhoodMM_tools.h:139
CP::LhoodMMFitInfo::totEvents
int totEvents
Definition: LhoodMMFitInfo.h:23
CP::LhoodMM_tools::setFitType
StatusCode setFitType(const std::string &ft)
Definition: LhoodMM_tools.cxx:146
CP::LhoodMM_tools::m_perfectFit
bool m_perfectFit
Definition: LhoodMM_tools.h:83
plotBeamSpotCompare.x1
x1
Definition: plotBeamSpotCompare.py:216
CP::LhoodMMFitInfo::OSfrac_denom
std::vector< std::vector< double > > OSfrac_denom
Definition: LhoodMMFitInfo.h:22
CP::BaseFakeBkgTool
Definition: BaseFakeBkgTool.h:42
python.CaloRecoConfig.f
f
Definition: CaloRecoConfig.py:127
CP::LhoodMM_tools::fcn_minnlep_maxnlep
static void fcn_minnlep_maxnlep(Int_t &npar, Double_t *gin, Double_t &f, Double_t *par, Int_t iflag)
Definition: LhoodMM_tools.cxx:557
CP::LhoodMM_tools::fillHistograms
StatusCode fillHistograms()
Definition: LhoodMM_tools.cxx:1132
PlotCalibFromCool.ft
ft
Definition: PlotCalibFromCool.py:329
python.SystemOfUnits.s
int s
Definition: SystemOfUnits.py:131
CP::LhoodMM_tools::addEventCustom
virtual StatusCode addEventCustom() override
Definition: LhoodMM_tools.cxx:262
python.PerfMonSerializer.p
def p
Definition: PerfMonSerializer.py:743
Clock
std::chrono::high_resolution_clock Clock
Definition: LhoodMM_tools.cxx:36
TMinuit_LHMM.h
WriteCellNoiseToCool.icell
icell
Definition: WriteCellNoiseToCool.py:339
ATH_MSG_INFO
#define ATH_MSG_INFO(x)
Definition: AthMsgStreamMacros.h:31
FakeBkgTools::Efficiency::multiply
Efficiency & multiply(const Efficiency &rhs, float weight=1.f)
the first version of multiply() takes the product of two Efficiencies, setting the up and down variat...
Definition: FakeBkgInternals.h:222
CaloCellPos2Ntuple.int
int
Definition: CaloCellPos2Ntuple.py:24
CP::LhoodMM_tools::m_real_indices
std::vector< std::vector< int > > m_real_indices
Definition: LhoodMM_tools.h:95
CP::LhoodMM_tools::LhoodMM_tools
LhoodMM_tools(const std::string &name)
Definition: LhoodMM_tools.cxx:41
FakeBkgTools::Efficiency
a structure to hold an efficiency together with a variable number of uncertainties
Definition: FakeBkgInternals.h:40
CP::LhoodMM_tools::m_needToResize
bool m_needToResize
Definition: LhoodMM_tools.h:98
dqt_zlumi_pandas.hname
string hname
Definition: dqt_zlumi_pandas.py:272
CP::LhoodMM_tools::getTotalYield
virtual StatusCode getTotalYield(float &yield, float &statErrUp, float &statErrDown) override final
returns the accumulated fake lepton background yield (or compute it, in the case of the likelihood ma...
Definition: LhoodMM_tools.cxx:302
index
Definition: index.py:1
AthCommonDataStore< AthCommonMsg< AlgTool > >::declareProperty
Gaudi::Details::PropertyBase & declareProperty(Gaudi::Property< T > &t)
Definition: AthCommonDataStore.h:145
CP::LhoodMM_tools::fixNegErr
double fixNegErr(double n_fake_fit, TMinuit_LHMM *lhoodFit)
Definition: LhoodMM_tools.cxx:1581
conifer::pow
constexpr int pow(int x)
Definition: conifer.h:20
CP::LhoodMM_tools::logPoisson
static double logPoisson(double obs, double pred)
Definition: LhoodMM_tools.cxx:544
CP::LhoodMMFitInfo::add
void add(LhoodMMFitInfo &rhs, int nLepMax)
Definition: LhoodMMFitInfo.cxx:35
CP::LhoodMM_tools::m_alreadyMerged
bool m_alreadyMerged
Definition: LhoodMM_tools.h:106
CP::LhoodMM_tools::m_nrf_mat_vec
std::vector< std::shared_ptr< TMatrixT< double > > > m_nrf_mat_vec
Definition: LhoodMM_tools.h:131
FakeBkgTools::Client
Client
Definition: FakeBkgInternals.h:141
CP::LhoodMM_tools::nfakes_std_perEventWeight
double nfakes_std_perEventWeight(double *error)
Definition: LhoodMM_tools.cxx:1237
python.atlas_oh.im
im
Definition: atlas_oh.py:167
CP::BaseFakeBkgTool::initialize
virtual StatusCode initialize() override
Dummy implementation of the initialisation function.
Definition: BaseFakeBkgTool.cxx:63
AthCommonMsg< AlgTool >::msgLvl
bool msgLvl(const MSG::Level lvl) const
Definition: AthCommonMsg.h:30
LhoodMMEvent::isTight
bool isTight(unsigned ilep) const
Definition: LhoodMMEvent.cxx:101
athena.value
value
Definition: athena.py:122
python.sizes.txt
string txt
Definition: sizes.py:141
ANA_CHECK
#define ANA_CHECK(EXP)
check whether the given expression was successful
Definition: Control/AthToolSupport/AsgMessaging/AsgMessaging/MessageCheck.h:324
UploadAMITag.l
list l
Definition: UploadAMITag.larcaf.py:158
FakeBkgTools::ParticleData
Definition: FakeBkgInternals.h:85
CP::LhoodMM_tools::m_fsvec
std::vector< std::unique_ptr< FakeBkgTools::FinalState > > m_fsvec
Definition: LhoodMM_tools.h:88
read_hist_ntuple.t
t
Definition: read_hist_ntuple.py:5
CP::LhoodMM_tools::m_ntlpred_vec
std::vector< std::shared_ptr< TMatrixT< double > > > m_ntlpred_vec
Definition: LhoodMM_tools.h:133
ATH_MSG_VERBOSE
#define ATH_MSG_VERBOSE(x)
Definition: AthMsgStreamMacros.h:28
CP::LhoodMMFitInfo::resizeVectors
void resizeVectors(unsigned nlep)
Definition: LhoodMMFitInfo.cxx:73
FakeBkgTools::Client::MATRIX_METHOD
@ MATRIX_METHOD
read_hist_ntuple.h1
h1
Definition: read_hist_ntuple.py:21
CP::LhoodMM_tools::m_requireSS
bool m_requireSS
Definition: LhoodMM_tools.h:96
CP::LhoodMM_tools::~LhoodMM_tools
~LhoodMM_tools()
Definition: LhoodMM_tools.cxx:56
CP
Select isolated Photons, Electrons and Muons.
Definition: Control/xAODRootAccess/xAODRootAccess/TEvent.h:48
CP::LhoodMM_tools::register3DHistogram
virtual StatusCode register3DHistogram(TH3 *h3, const float *xval, const float *yval, const float *zval) override
associates a 3D histogram to the tool, to obtain a binned estimate of the fake lepton background
Definition: LhoodMM_tools.cxx:212
Trk::u
@ u
Enums for curvilinear frames.
Definition: ParamDefs.h:83
CP::LhoodMM_tools::initialize
virtual StatusCode initialize() override
Dummy implementation of the initialisation function.
Definition: LhoodMM_tools.cxx:68
AthenaPoolTestRead.sc
sc
Definition: AthenaPoolTestRead.py:27
CP::LhoodMM_tools::nfakes
double nfakes(Double_t *poserr, Double_t *negerr)
Definition: LhoodMM_tools.cxx:746
CP::LhoodMM_tools::m_requireOS
bool m_requireOS
Definition: LhoodMM_tools.h:96
CP::LhoodMM_tools::m_fitInfo_1dhisto_map
std::map< TH1 *, std::vector< LhoodMMFitInfo > > m_fitInfo_1dhisto_map
Definition: LhoodMM_tools.h:114
dqt_zlumi_pandas.weight
int weight
Definition: dqt_zlumi_pandas.py:200
CP::LhoodMMFitInfo::eventCount
std::vector< double > eventCount
Definition: LhoodMMFitInfo.h:24
SCT_CalibAlgs::nbins
@ nbins
Definition: SCT_CalibNumbers.h:10
python.setupRTTAlg.size
int size
Definition: setupRTTAlg.py:39
CP::BaseFakeBkgTool::register3DHistogram
virtual StatusCode register3DHistogram(TH3 *h3, const float *xval, const float *yval, const float *zval) override
associates a 3D histogram to the tool, to obtain a binned estimate of the fake lepton background
Definition: BaseFakeBkgTool.cxx:300
ASG_MSG_VERBOSE
#define ASG_MSG_VERBOSE(x)
Definition: LhoodMM_tools.cxx:554
CP::LhoodMM_tools::m_printLevel
Int_t m_printLevel
Definition: LhoodMM_tools.h:129
PlotCalibFromCool.nentries
nentries
Definition: PlotCalibFromCool.py:798
CP::LhoodMM_tools::m_minnlep
int m_minnlep
Definition: LhoodMM_tools.h:93
ATH_MSG_ERROR
#define ATH_MSG_ERROR(x)
Definition: AthMsgStreamMacros.h:33
CP::LhoodMM_tools::m_coeffs
std::vector< std::vector< std::vector< double > > > m_coeffs
Definition: LhoodMM_tools.h:112
CP::LhoodMM_tools::setup
StatusCode setup()
Definition: LhoodMM_tools.cxx:526
lumiFormat.i
int i
Definition: lumiFormat.py:92
h
CP::LhoodMMFitInfo::OSfrac_num
std::vector< std::vector< double > > OSfrac_num
Definition: LhoodMMFitInfo.h:21
beamspotman.n
n
Definition: beamspotman.py:731
LhoodMMEvent::realEffObj
const FakeBkgTools::Efficiency & realEffObj(unsigned ilep) const
Definition: LhoodMMEvent.cxx:82
Analysis::Uncertainty
Uncertainty
specification of type information requested by the user
Definition: CalibrationDataInterfaceROOT.h:70
CP::LhoodMM_tools::get_analytic
void get_analytic(std::vector< double > &nrf, const int nlep)
Definition: LhoodMM_tools.cxx:1333
EL::StatusCode
::StatusCode StatusCode
StatusCode definition for legacy code.
Definition: PhysicsAnalysis/D3PDTools/EventLoop/EventLoop/StatusCode.h:22
vector< double >
ATH_MSG_DEBUG
#define ATH_MSG_DEBUG(x)
Definition: AthMsgStreamMacros.h:29
CP::LhoodMM_tools::m_MMmatrix_vec
std::vector< std::shared_ptr< TMatrixT< double > > > m_MMmatrix_vec
Definition: LhoodMM_tools.h:132
CP::LhoodMM_tools::m_maxWeight
float m_maxWeight
Definition: LhoodMM_tools.h:104
CP::LhoodMMFitInfo::event_sumw2
std::vector< std::vector< double > > event_sumw2
Definition: LhoodMMFitInfo.h:20
CP::LhoodMM_tools::m_global_fitInfo
LhoodMMFitInfo m_global_fitInfo
Definition: LhoodMM_tools.h:81
CP::BaseFakeBkgTool::m_progressFileDirectory
std::string m_progressFileDirectory
property ProgressFileDirectory
Definition: BaseFakeBkgTool.h:139
top::nominal
@ nominal
Definition: ScaleFactorRetriever.h:29
CP::LhoodMMFitInfo::event_cat
std::vector< std::vector< double > > event_cat
Definition: LhoodMMFitInfo.h:19
CP::LhoodMM_tools::mergeSubJobs
StatusCode mergeSubJobs()
Definition: LhoodMM_tools.cxx:1700
CP::LhoodMM_tools::fcn_nlep
static void fcn_nlep(Int_t &npar, Double_t *gin, Double_t &f, Double_t *par, Int_t iflag)
Definition: LhoodMM_tools.cxx:643
TH3
Definition: rootspy.cxx:440
checkCorrelInHIST.prefix
dictionary prefix
Definition: checkCorrelInHIST.py:391
CP::LhoodMM_tools::get_init_pars
void get_init_pars(std::vector< double > &init_pars, int nlep)
Definition: LhoodMM_tools.cxx:1243
plotting.yearwise_efficiency.yval
float yval
Definition: yearwise_efficiency.py:43
ATH_CHECK
#define ATH_CHECK
Definition: AthCheckMacros.h:40
add
bool add(const std::string &hname, TKey *tobj)
Definition: fastadd.cxx:55
CP::LhoodMM_tools::m_fitStatus
Int_t m_fitStatus
Definition: LhoodMM_tools.h:127
CP::BaseFakeBkgTool::m_process
std::string m_process
'process' settings used to compute the total yield / fill histograms
Definition: BaseFakeBkgTool.h:118
CP::BaseFakeBkgTool::register2DHistogram
virtual StatusCode register2DHistogram(TH2 *h2, const float *xval, const float *yval) override
associates a 2D histogram to the tool, to obtain a binned estimate of the fake lepton background the ...
Definition: BaseFakeBkgTool.cxx:270
CP::LhoodMM_tools::m_maxnlep_loose
int m_maxnlep_loose
Definition: LhoodMM_tools.h:93
CP::BaseFakeBkgTool::m_unlimitedSystematicVariations
bool m_unlimitedSystematicVariations
used to prevent multiple calls to applySystematicVariation() when unsupported set to true in a partic...
Definition: BaseFakeBkgTool.h:170
CP::LhoodMM_tools::m_prevSave
bool m_prevSave
Definition: LhoodMM_tools.h:82
CP::LhoodMM_tools::m_fitInfo_2dhisto_map
std::map< TH2 *, std::vector< LhoodMMFitInfo > > m_fitInfo_2dhisto_map
Definition: LhoodMM_tools.h:115
CP::LhoodMMFitInfo::coeffs_num
std::vector< std::vector< std::vector< FakeBkgTools::Efficiency > > > coeffs_num
Definition: LhoodMMFitInfo.h:17
LhoodMMEvent::charge
int charge(unsigned ilep) const
Definition: LhoodMMEvent.cxx:110
plotting.yearwise_efficiency.xval
float xval
Definition: yearwise_efficiency.py:42
CP::LhoodMM_tools::m_doFakeFactor
bool m_doFakeFactor
Definition: LhoodMM_tools.h:100
CP::BaseFakeBkgTool::m_values_1dhisto_map
std::map< TH1 *, const float * > m_values_1dhisto_map
Definition: BaseFakeBkgTool.h:108
beamspotman.dir
string dir
Definition: beamspotman.py:623
FakeBkgTools::Efficiency::setToConst
Efficiency & setToConst(float value=1.f)
setToConst() sets the nominal and all varied values to the same constant
Definition: FakeBkgInternals.h:252
CP::LhoodMMFitInfo
Definition: LhoodMMFitInfo.h:13
CP::LhoodMM_tools::clientForDB
virtual FakeBkgTools::Client clientForDB() override final
This indicates which type of efficiencies/fake factor need to be filled.
Definition: LhoodMM_tools.cxx:62
CP::LhoodMM_tools::m_lastSaveIndex
unsigned m_lastSaveIndex
Definition: LhoodMM_tools.h:135
PathResolver.h
Database.h
CP::LhoodMM_tools::m_fixNormalization
bool m_fixNormalization
Definition: LhoodMM_tools.h:102
name
std::string name
Definition: Control/AthContainers/Root/debug.cxx:192
createCoolChannelIdFile.par
par
Definition: createCoolChannelIdFile.py:29
LhoodMMEvent
Definition: LhoodMMEvent.h:11
ActsTrk::to_string
std::string to_string(const DetectorType &type)
Definition: GeometryDefs.h:34
FakeBkgInternals.h
LhoodMMFitInfo.h
CP::BaseFakeBkgTool::m_externalWeight
float m_externalWeight
Definition: BaseFakeBkgTool.h:95
CP::LhoodMM_tools::m_fitInfo_3dhisto_map
std::map< TH3 *, std::vector< LhoodMMFitInfo > > m_fitInfo_3dhisto_map
Definition: LhoodMM_tools.h:116
CP::BaseFakeBkgTool::m_particles
std::vector< FakeBkgTools::ParticleData > m_particles
Definition: BaseFakeBkgTool.h:85
python.AtlRunQueryLib.rsq
rsq
Definition: AtlRunQueryLib.py:380
CP::LhoodMM_tools::s_maxRank
static const int s_maxRank
Definition: LhoodMM_tools.h:109
FakeBkgTools::FinalState
Definition: FakeBkgInternals.h:98
FakeBkgTools::Efficiency::subFromOne
Efficiency & subFromOne()
subFromOne() sets nominal and varied values to 1 - previous value.
Definition: FakeBkgInternals.h:265
PathResolverFindDataFile
std::string PathResolverFindDataFile(const std::string &logical_file_name)
Definition: PathResolver.cxx:379
CP::LhoodMM_tools::nfakes_std
double nfakes_std(double *error)
Definition: LhoodMM_tools.cxx:1231
compileRPVLLRates.nf
nf
Definition: compileRPVLLRates.py:89
CP::LhoodMM_tools::m_current_lhoodMM_tool
static LhoodMM_tools * m_current_lhoodMM_tool
Definition: LhoodMM_tools.h:79
DiTauMassTools::MaxHistStrategyV2::e
e
Definition: PhysicsAnalysis/TauID/DiTauMassTools/DiTauMassTools/HelperFunctions.h:26
ATH_MSG_WARNING
#define ATH_MSG_WARNING(x)
Definition: AthMsgStreamMacros.h:32
CP::LhoodMM_tools::m_maxnlep
int m_maxnlep
Definition: LhoodMM_tools.h:93
CP::LhoodMMFitInfo::reset
void reset()
Definition: LhoodMMFitInfo.cxx:17
Pythia8_RapidityOrderMPI.val
val
Definition: Pythia8_RapidityOrderMPI.py:14
CP::LhoodMM_tools::incrementMatrices
StatusCode incrementMatrices(const LhoodMMEvent &mmevt)
Definition: LhoodMM_tools.cxx:324
python.TriggerHandler.verbose
verbose
Definition: TriggerHandler.py:297
DEBUG
#define DEBUG
Definition: page_access.h:11
CP::LhoodMM_tools::s_nLepMax
static const int s_nLepMax
Definition: LhoodMM_tools.h:108
CP::LhoodMM_tools::fillHisto_internal
StatusCode fillHisto_internal(const std::vector< LhoodMMFitInfo > &fitInfo_vec, TH1 *h)
Definition: LhoodMM_tools.cxx:1159
CaloCellTimeCorrFiller.filename
filename
Definition: CaloCellTimeCorrFiller.py:24
CP::LhoodMM_tools
Definition: LhoodMM_tools.h:29
CP::LhoodMM_tools::reset
virtual void reset()
Definition: LhoodMM_tools.cxx:73
CP::BaseFakeBkgTool::m_selection
std::string m_selection
'selection' settings used to compute the total yield / fill histograms
Definition: BaseFakeBkgTool.h:115
CP::LhoodMM_tools::fixPosErr
double fixPosErr(double n_fake_fit, TMinuit_LHMM *lhoodFit)
Definition: LhoodMM_tools.cxx:1490
LArCellBinning.step
step
Definition: LArCellBinning.py:158
compute_lumi.fin
fin
Definition: compute_lumi.py:19
merge.status
status
Definition: merge.py:17
xAOD::JetConstituentVector::iterator
Definition: JetConstituentVector.h:121
CP::BaseFakeBkgTool::m_values_2dhisto_map
std::map< TH2 *, std::pair< const float *, const float * > > m_values_2dhisto_map
Definition: BaseFakeBkgTool.h:109
python.TrigEgammaMonitorHelper.TH1F
def TH1F(name, title, nxbins, bins_par2, bins_par3=None, path='', **kwargs)
Definition: TrigEgammaMonitorHelper.py:24
CP::LhoodMM_tools::incrementOneMatrixSet
StatusCode incrementOneMatrixSet(LhoodMMFitInfo &fitInfo, const LhoodMMEvent &mmevt)
Definition: LhoodMM_tools.cxx:415
python.Constants.VERBOSE
int VERBOSE
Definition: Control/AthenaCommon/python/Constants.py:14
CP::LhoodMM_tools::register2DHistogram
virtual StatusCode register2DHistogram(TH2 *h2, const float *xval, const float *yval) override
associates a 2D histogram to the tool, to obtain a binned estimate of the fake lepton background the ...
Definition: LhoodMM_tools.cxx:187
CP::LhoodMM_tools::m_theta_tot_start_index
int m_theta_tot_start_index
Definition: LhoodMM_tools.h:94
CP::LhoodMM_tools::m_fake_indices
std::vector< std::vector< int > > m_fake_indices
Definition: LhoodMM_tools.h:95
LhoodMMEvent::weight
float weight() const
Definition: LhoodMMEvent.h:28
CP::LhoodMM_tools::m_OSfrac
std::vector< std::vector< double > > m_OSfrac
Definition: LhoodMM_tools.h:119
get_generator_info.error
error
Definition: get_generator_info.py:40
LhoodMMEvent::nlep
unsigned nlep() const
Definition: LhoodMMEvent.h:19
CP::LhoodMM_tools::saveProgress
virtual StatusCode saveProgress(TDirectory *dir) override
Definition: LhoodMM_tools.cxx:1667
FakeBkgTools::FSBitset
std::bitset< maxCombinations()> FSBitset
Definition: FakeBkgInternals.h:95
CP::LhoodMM_tools::m_nfakes_std_perEventWeight
double m_nfakes_std_perEventWeight
Definition: LhoodMM_tools.h:123
error
Definition: IImpactPoint3dEstimator.h:70
CP::BaseFakeBkgTool::m_values_3dhisto_map
std::map< TH3 *, std::tuple< const float *, const float *, const float * > > m_values_3dhisto_map
Definition: BaseFakeBkgTool.h:110
CP::BaseFakeBkgTool::m_progressFileName
std::string m_progressFileName
property ProgressFileName
Definition: BaseFakeBkgTool.h:136
CP::LhoodMM_tools::m_current_fitInfo
const LhoodMMFitInfo * m_current_fitInfo
Definition: LhoodMM_tools.h:85
LhoodMM_tools.h
python.compressB64.c
def c
Definition: compressB64.py:93
CP::LhoodMM_tools::m_do_std_perEventWeight
bool m_do_std_perEventWeight
Definition: LhoodMM_tools.h:125
CP::LhoodMM_tools::s_piover2
static const double s_piover2
Definition: LhoodMM_tools.h:138
CP::LhoodMM_tools::m_nfakes_std
double m_nfakes_std
Definition: LhoodMM_tools.h:121
LhoodMMEvent::fakeEffObj
const FakeBkgTools::Efficiency & fakeEffObj(unsigned ilep) const
Definition: LhoodMMEvent.cxx:91
TMinuit_LHMM
Definition: TMinuit_LHMM.h:12
histogram
std::string histogram
Definition: chains.cxx:52
FakeBkgTools::Efficiency::uncertainties
std::map< uint16_t, FakeBkgTools::Uncertainty > uncertainties
Definition: FakeBkgInternals.h:43
CP::LhoodMM_tools::m_nfakes_std_err
double m_nfakes_std_err
Definition: LhoodMM_tools.h:121
PlotCalibFromCool.vals
vals
Definition: PlotCalibFromCool.py:474
CP::LhoodMMFitInfo::normterms
std::vector< std::vector< FakeBkgTools::Efficiency > > normterms
Definition: LhoodMMFitInfo.h:18
CP::LhoodMM_tools::register1DHistogram
virtual StatusCode register1DHistogram(TH1 *h1, const float *val) override
associates a 1D histogram to the tool, to obtain a binned estimate of the fake lepton background the ...
Definition: LhoodMM_tools.cxx:159