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