21#include "TTreeReader.h"
22#include "TTreeReaderValue.h"
24#include "TDirectory.h"
33using Clock=std::chrono::high_resolution_clock;
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)");
54 "Give results corresponding to the fake factor method rather than the matrix method");
99 for (
int ilep = 0; ilep <
s_nLepMax; ilep++) {
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++) {
126 for (
int ilep = 0; ilep <
s_nLepMax; ilep++) {
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));
153 return StatusCode::SUCCESS;
154 }
else if (ft ==
"MM") {
156 return StatusCode::SUCCESS;
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;
167 if(
sc != StatusCode::SUCCESS)
return sc;
174 int ncells = h1->GetNcells();
176 fitinfovec->resize(ncells);
178 for (
int icell = 0; icell < ncells; icell++) {
183 ATH_MSG_INFO(
"Registered a 1D histogram "<<h1->GetName());
185 ATH_MSG_ERROR(
"Error in LhoodMM_tools::register1DHistogram: histogram has already been registered");
186 return StatusCode::FAILURE;
188 return StatusCode::SUCCESS;
195 if(
sc != StatusCode::SUCCESS)
return sc;
201 int ncells = h2->GetNcells();
203 fitinfovec->resize(ncells);
204 for (
int icell = 0; icell < ncells; icell++) {
208 ATH_MSG_INFO(
"Registered a 2D histogram "<<h2->GetName());
210 ATH_MSG_ERROR(
"Error in LhoodMM_tools::register2DHistogram: histogram has already been registered");
211 return StatusCode::FAILURE;
213 return StatusCode::SUCCESS;
220 if(
sc != StatusCode::SUCCESS)
return sc;
226 int ncells = h3->GetNcells();
228 fitinfovec->resize(ncells);
229 for (
int icell = 0; icell < ncells; icell++) {
233 ATH_MSG_INFO(
"Registered a 3D histogram "<<h3->GetName());
235 ATH_MSG_ERROR(
"Error in LhoodMM_tools::register3DHistogram: histogram has already been registered");
236 return StatusCode::FAILURE;
238 return StatusCode::SUCCESS;
242 const std::vector<Efficiency>& realEff_vals,
243 const std::vector<Efficiency>& fakeEff_vals,
244 const std::vector<int>& charges,
249 int nlep = isTight_vals.size();
257 LhoodMMEvent mmevt(nlep, realEff_vals, fakeEff_vals, isTight_vals, charges, extraweight);
262 return StatusCode::SUCCESS;
270 ATH_MSG_WARNING(
"Attempt to add an event with 0 leptons. This event will be ignored.");
271 return StatusCode::SUCCESS;
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;
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);
288 for(
const std::pair<short unsigned int, FakeBkgTools::Uncertainty> kv : p.real_efficiency.uncertainties)
290 ATH_MSG_DEBUG(
"real eff uncertainties for first lepton are " << kv.second.up <<
" " << kv.second.down);
292 for(
const std::pair<short unsigned int, FakeBkgTools::Uncertainty> kv : p.fake_efficiency.uncertainties)
294 ATH_MSG_DEBUG(
"fake eff uncertainties for first lepton are " << kv.second.up <<
" " << kv.second.down);
297 charges.push_back(p.charge);
298 if ( r_eff < 0.01 && f_eff< 0.01) {
315 Double_t poserr, negerr;
318 yield =
nfakes(&poserr,&negerr);
320 ATH_MSG_DEBUG(
"Leaving getTotalYield with yield = " << yield);
323 statErrDown = -negerr;
330 int nlep = mmevt.
nlep();
342 const float* val = map1_iter->second;
343 TH1*
h = map1_iter->first;
349 for (icell = 0; icell<
h->GetNcells(); icell++) {
350 fitInfo = &histoMap->second[icell];
354 icell =
h->FindBin(*val);
356 fitInfo = &histoMap->second[icell];
364 return StatusCode::FAILURE;
368 std::map<TH2*, std::pair<const float*, const float*> >
::iterator map2_iter;
370 std::pair<const float*, const float*> val = map2_iter->second;
371 TH2*
h = map2_iter->first;
378 for (icell = 0; icell<
h->GetNcells(); icell++) {
379 fitInfo = &histoMap->second[icell];
383 icell =
h->FindBin(*(val.first), *(val.second));
384 fitInfo = &histoMap->second[icell];
388 return StatusCode::FAILURE;
393 std::map<TH3*, std::tuple<const float*, const float*, const float*> >
::iterator map3_iter;
395 std::tuple<const float*, const float*, const float*> val = map3_iter->second;
396 TH3*
h = map3_iter->first;
402 for (icell = 0; icell<
h->GetNcells(); icell++) {
403 fitInfo = &histoMap->second[icell];
407 icell =
h->FindBin(*(std::get<0>(val)), *(std::get<1>(val)), *(std::get<2>(val)) );
408 fitInfo = &histoMap->second[icell];
412 return StatusCode::FAILURE;
416 return StatusCode::SUCCESS;
422 int nlep = mmevt.
nlep();
424 int rank = 0x1 << nlep;
434 unsigned int catIndex = 0;
435 for (
int jlep = 0; jlep < nlep; jlep++) {
436 catIndex += (!mmevt.
isTight(jlep)) << jlep;
438 double weight = mmevt.
weight();
447 fitInfo.
event_cat[lepidx][catIndex] +=weight;
448 fitInfo.
event_sumw2[lepidx][catIndex]+=weight*weight;
453 for (
int icomb = 0; icomb < (0x1 << nlep); icomb++) {
455 std::bitset<s_nLepMax+1> tights(icomb);
456 int ntight = tights.count();
458 for (
int jlep = 0; jlep < nlep; jlep++) {
460 totcharge += mmevt.
charge(jlep);
464 ATH_MSG_VERBOSE(
"Setting OSfrac_denom[" << lepidx <<
"][" << ntight <<
"]");
469 ATH_MSG_VERBOSE(
"Setting OSfrac_num[" << lepidx <<
"][" << ntight <<
"]");
470 if ((TMath::Abs(totcharge) < ntight) || ntight == 1) fitInfo.
OSfrac_num[lepidx][ntight]+=weight;
474 std::vector<std::vector<FakeBkgTools::Efficiency>> vals(2, std::vector<FakeBkgTools::Efficiency>(nlep));
475 for (
int ilep = 0; ilep < nlep; ilep++) {
484 vals[0][ilep].setToConst(1.0);
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));
494 for (
int irf = 0; irf < rank; irf++) {
495 for (
int itl = 0; itl < rank; itl++) {
497 for (
int ilep = 0; ilep < nlep; ilep++) {
498 if (itl & (0x1 << ilep) ) {
499 if (irf & (0x1 << ilep)) {
507 if (irf & (0x1 << ilep) ) {
508 curr_coeff_num.
multiply(vals[1][ilep]);
510 curr_coeff_num.
multiply(vals[0][ilep]);
514 ATH_MSG_VERBOSE(
"about to set m_coeffs_num[" << lepidx <<
"][" << itl <<
"][" << irf <<
"]");
516 fitInfo.
normterms[lepidx][(itl<<nlep) + irf].
add(curr_coeff_num);
517 fitInfo.
coeffs_num[lepidx][itl][irf].add(curr_coeff_num);
522 return StatusCode::SUCCESS;
525 return StatusCode::FAILURE;
535 for (
int jlep = 0; jlep < ilep; jlep++) {
544 return StatusCode::SUCCESS;
550 double f = -(obs*TMath::Log(pred)-pred);
551 if (obs > 0) f += obs*TMath::Log(obs)-obs;
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)
558#define ASG_MSG_VERBOSE(x) do { if(m_current_lhoodMM_tool->msgLvl(MSG::VERBOSE)) std::cout << x << std::endl; } while (0)
566 const bool verbose = (l->m_printLevel > 0);
570 for (
int ipar = 0; ipar < npar; ipar++) {
574 int minnlep = l->m_minnlep;
575 int maxnlep_loose = l->m_maxnlep_loose;
579 Double_t rsq = par[0];
581 Double_t sinterm_tot = 1.;
583 int theta_nlep_index = 1 + maxnlep_loose -minnlep;
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);
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++) {
604 l->m_curr_nlep = ilep;
605 Int_t npar_thisnlep = 0x1 << ilep;
607 int theta_tot_index = l->m_theta_tot_start_index+ilep-minnlep;
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) {
613 costerm = TMath::Cos(par[theta_tot_index]);
618 pars_thisnlep[0] = rsq*sinterm_tot*costerm*sinterm_tot*costerm;
619 sinterm_tot *= TMath::Sin(par[theta_tot_index]);
621 pars_thisnlep[0] = rsq;
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];
632 for (
int ipar = 0; ipar < (
int)l->m_fake_indices[ilep-1].size()-1; ipar++) {
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]);
638 fcn_nlep(npar_thisnlep, gin, f, pars_thisnlep, iflag);
641 real_index += l->m_real_indices[ilep-1].size();
652 const bool verbose = (l->m_printLevel > 0);
654 int nlep = l->m_curr_nlep;
656 int rank = 0x1 << nlep;
660 for (
int ipar = 0; ipar < npar; ipar++) {
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]) +
" ";
675 std::shared_ptr<TMatrixT<double>> nrf, MMmatrix, ntlpred;
676 nrf = l->m_nrf_mat_vec[lepidx];
681 MMmatrix = l->m_MMmatrix_vec[lepidx];
682 ntlpred = l->m_ntlpred_vec[lepidx];
684 (*nrf)(0,0) = par[0];
685 double rsq = TMath::Abs(par[0]);
687 int rsize = l->m_real_indices[lepidx].size();
688 int fsize = l->m_fake_indices[lepidx].size();
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];
698 for (
int ipar = 0; ipar < fsize; ipar++) {
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;
705 (*nrf)(l->m_fake_indices[lepidx][ipar],0) = rsq*sinterm*sinterm;
709 ASG_MSG_VERBOSE(
"In fcn, setting fake par " << l->m_fake_indices[lepidx][ipar] <<
" to " << (*nrf)(l->m_fake_indices[lepidx][ipar],0));
711 sinterm *= TMath::Sin(par[rsize+ipar+1]);
719 *ntlpred = (*MMmatrix)*(*nrf);
728 if (l->m_doFakeFactor) {
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));
737 int nobs = l->m_current_fitInfo->event_cat.at(lepidx).at(ipar);
740 s= l->m_current_fitInfo->event_sumw2.at(lepidx).at(ipar)/nobs;
743 f +=
logPoisson(1.*nobs/s, (*ntlpred)(ipar,0)/s);
770 for (
int ilep = 0; ilep <
s_nLepMax; ilep++) {
774 if (
error.size() > 0) {
793 for (
int icomb = 0; icomb < (0x1 << (ilep+1)); icomb++) {
795 ATH_MSG_VERBOSE(
"ilep " << ilep <<
" (0x1 << ilep) " << std::hex << (0x1 << ilep) <<
" icomb " << std::hex << icomb << std::dec);
799 if (
m_fsvec[ilep]->accept_selection(tights, charges)) {
801 ATH_MSG_VERBOSE(
"tights = " << std::hex << tights << std::dec <<
" nlep = " << nlep);
815 int maxNlep_proc = 0;
817 for(
unsigned c=0;c<(1u<<n);++c)
822 for (
int ibit = 0; ibit < n; ibit++) {
823 reals.set(ibit, ~fakes[ibit]);
826 if (
m_fsvec[n-1]->accept_process(n, reals, tights) ) {
827 if(n < minNlep_proc) minNlep_proc = n;
828 if (n > maxNlep_proc) {
839 if(
setup() != StatusCode::SUCCESS)
return 0.;
854 double nfake_fit, nfake_fitErr;
863 std::unique_ptr<TMinuit_LHMM> lhoodFit(
new TMinuit_LHMM(npar));
868 Double_t arglist[10];
872 lhoodFit->mnexcm(
"SET ERR", arglist ,1,ierflg);;
879 vector<double> init_pars;
880 init_pars.resize(npar);
882 vector< vector <double> > loc_init_pars;
886 loc_init_pars[ilep-1].resize(0x1 << ilep);
888 for (
int ipar = 0; ipar < (0x1 << ilep); ipar++) {
889 init_pars[
index+ipar] = loc_init_pars[ilep-1][ipar];
894 Double_t step = TMath::Max(loc_init_pars[
m_minnlep-1][0]/1000,0.001);
900 vector<TString> parameterName;
901 vector<int> nreal_start_indices;
903 parameterName.push_back(
"nfake_tot");
904 TString sreal =
"nreal";
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;
913 sprintf(tmpchar2,
"_%u", isublep);
914 locsreal.Append(tmpchar2);
915 parameterName.push_back(locsreal);
917 nreal_start_indices[ilep-1] = (parameterName.size());
918 ATH_MSG_VERBOSE(
"nreal_start_indices[" << ilep-1 <<
"] = " << nreal_start_indices[ilep-1]);
923 TString stheta_tot =
"theta_tot";
927 TString tmpstr = stheta_tot;
928 tmpstr.Append(tmpchar);
929 parameterName.push_back(tmpstr);
933 TString stheta =
"theta_";
935 sprintf(tmpchar,
"%i", ilep);
936 TString tmpstr = std::move(stheta);
937 tmpstr.Append(tmpchar);
941 TString locstheta = tmpstr;
943 sprintf(tmpchar2,
"%i", jlep);
944 locstheta.Append(tmpchar2);
945 parameterName.push_back(locstheta);
950 vector<double> theta_tot;
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] ) ) {
964 sinterm *= TMath::Sin(theta_tot[theta_index]);
976 vector<double> upper_limits;
977 upper_limits.resize(npar);
983 for (
unsigned isublep = 0; isublep <
m_real_indices[ilep-1].size(); isublep++) {
989 for (
int ipar = real_index; ipar < npar; ipar++) {
994 vector<double> init_par_values;
995 init_par_values.resize(npar);
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];
1006 init_index+=
pow(2,ilep);
1013 vector<int> theta_start_indices;
1017 theta_start_indices[i] = theta_start_indices[i-1] +
m_fake_indices[i-1].size() - 1;
1035 index+= 0x1 << ilep;
1038 for (ipar = 0; ipar < npar; ipar++) {
1039 lhoodFit->mnparm(ipar, parameterName[ipar], init_par_values[ipar], step, 0., upper_limits[ipar], ierflg);
1050 int nGoodLeptonMult = 0;
1056 for (
unsigned ipar = nreal_start_indices[ilep-1]; ipar < nreal_start_indices[ilep-1] +
m_real_indices[ilep-1].size(); ipar++) {
1059 lhoodFit->mnexcm(
"SET PAR", arglist, 2, ierflg);
1060 lhoodFit->mnexcm(
"FIX PAR", arglist, 1, ierflg);
1065 lhoodFit->mnexcm(
"SET PAR", arglist, 2, ierflg);
1066 lhoodFit->mnexcm(
"FIX PAR", arglist, 1, ierflg);
1069 for (
unsigned ipar = theta_start_indices[ilep-1]+1; ipar < theta_start_indices[ilep-1] +
m_fake_indices[ilep-1].size() ; ipar++) {
1072 lhoodFit->mnexcm(
"SET PAR", arglist, 2, ierflg);
1073 lhoodFit->mnexcm(
"FIX PAR", arglist, 1, ierflg);
1078 index += (0x1 << ilep) - 2;
1081 if (nGoodLeptonMult == 0) {
1082 ATH_MSG_VERBOSE(
"No possible fake contribution for any lepton multiplicity");
1090 lhoodFit->mnexcm(
"MIGRAD", arglist ,2,ierflg);
1094 Double_t amin, edm, errdef;
1095 Int_t nvpar, nparx, icstat;
1096 lhoodFit->mnstat(amin,edm,errdef,nvpar,nparx,icstat);
1098 lhoodFit->GetParameter(0, nfake_fit, nfake_fitErr);
1102 if (poserr && negerr) {
1105 lhoodFit->mnexcm(
"MINOS", arglist ,2,ierflg);
1106 lhoodFit->mnerrs(0, *poserr, *negerr, nfake_fitErr, gcc);
1109 lhoodFit->mnstat(amin,edm,errdef,nvpar,nparx,icstat);
1110 lhoodFit->GetParameter(0, nfake_fit, nfake_fitErr);
1114 if ( *poserr < 1.e-5) {
1115 *poserr =
fixPosErr(nfake_fit, lhoodFit.get());
1117 if (*negerr > -1.e-5 ) {
1118 *negerr =
fixNegErr(nfake_fit, lhoodFit.get());
1121 if (*negerr > -1.e-5) {
1122 *negerr = -nfake_fitErr;
1124 if (nfake_fit + *negerr < 0.) {
1125 *negerr = -nfake_fit;
1129 if (*poserr < 1.e-5) {
1130 *poserr = nfake_fitErr;
1141 StatusCode status = StatusCode::SUCCESS;
1144 auto & fitInfo_vec = map1_iter->second;
1150 auto& fitInfo_vec = map2_iter->second;
1151 TH2*
histogram = (TH2*)map2_iter->first;
1157 auto& fitInfo_vec = map3_iter->second;
1158 TH3*
histogram = (TH3*)map3_iter->first;
1180 int nbins =
h->GetNcells();
1183 Double_t nf, poserr, negerr, shift = 0.;
1185 for (
int ibin = 0; ibin < nbins; ibin++) {
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.);
1197 h->SetBinError(ibin,TMath::Max(poserr,-negerr));
1200 h->SetBinContent(ibin,0.);
1201 h->SetBinError(ibin, 0.);
1203 ATH_MSG_VERBOSE(
"Result is " <<
h->GetBinContent(ibin) <<
" +/- " <<
h->GetBinError(ibin));
1208 double poserr, negerr;
1212 totFakes =
nfakes(&poserr, &negerr);
1215 double totHistContent = 0.;
1216 for (
int ibin = 0; ibin < nbins; ibin++) {
1217 totHistContent +=
h->GetBinContent(ibin);
1224 if (totHistContent > 0.) {
1225 scaleFactor = totFakes/totHistContent;
1229 for (
int ibin = 1; ibin <= nbins; ibin++) {
1230 h->SetBinContent(ibin, scaleFactor*
h->GetBinContent(ibin));
1231 h->SetBinError(ibin, scaleFactor*
h->GetBinError(ibin));
1234 return StatusCode::SUCCESS;
1254 int lepidx = nlep-1;
1257 nrf.resize(0x1 <<nlep);
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) +
' ';
1267 vector<double> init_angles;
1269 double nfakes_std_thisnlep = 0;
1272 for (
int ipar = 0; ipar < 0x1 <<nlep; ipar++) {
1276 for (
int ibit = 0; ibit < nlep; ibit++) {
1277 reals.set(ibit, ~fakes[ibit]);
1280 bool countsAsFake =
false;
1281 for (
int jpar = 0; jpar < 0x1 <<nlep; jpar++) {
1283 for (
int kpar = 0; kpar < 0x1 <<nlep; kpar++) {
1285 if (!countsAsFake &&
1286 m_fsvec[lepidx]->accept_process(nlep, reals, tights) &&
1287 m_fsvec[lepidx]->accept_selection(tights, charges) ) {
1289 nfakes_std_thisnlep += nrf[ipar];
1291 countsAsFake =
true;
1296 if (!countsAsFake) {
1303 init_pars[0] = nfakes_std_thisnlep;
1304 for (
unsigned ipar = 1; ipar <=
m_real_indices[lepidx].size(); ipar++) {
1308 if (nfakes_std_thisnlep > 0.5) {
1309 double sinterm = 1.;
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]);
1317 for (
int ipar =
m_real_indices[lepidx].size()+1; ipar < (0x1 << nlep); ipar++) {
1323 txt =
"testing variable transform: Initial pars: ";
1324 for (
int i = 0; i < (0x1 << nlep); i++) {
1325 txt += std::to_string(init_pars[i]) +
" ";
1331 for (
int ipar = 2; ipar < (0x1 << nlep); ipar++) {
1332 if (TMath::IsNaN(init_pars[ipar])) {
1333 init_pars[ipar] = 0.;
1335 ATH_MSG_VERBOSE(
"Setting angle parameter " << ipar <<
" to " << init_pars[ipar]);
1348 int lepidx = nlep-1;
1352 const int rank = 0x1 << nlep;
1354 std::vector<FakeBkgTools::Efficiency> coeff_denom(rank);
1359 for (
int irf = 0; irf < rank; irf++) {
1363 coeff_denom[irf].setToConst(0.);
1365 float chargefactor ;
1368 for (
int ibit = 0; ibit < nlep; ibit++) {
1369 reals.set(ibit, ~fakes[ibit]);
1371 for (
int itl = 0; itl < rank; itl++) {
1375 for (
int ibit = 0; ibit < nlep; ibit++) {
1376 tights.set(ibit, ~antitights[ibit]);
1381 if (
m_fsvec[lepidx]->accept_selection(tights, charges)
1382 &&
m_fsvec[lepidx]->accept_process(nlep, reals, tights) ) {
1387 if (nlep > 2 && tights.count() == 2) {
1393 if (nlep == 2 && tights.count() == 2) {
1399 chargefactor =
m_OSfrac[lepidx][tights.count()];
1401 ATH_MSG_VERBOSE(
"chargefactor = " << chargefactor <<
" for nlep = " << nlep);
1407 coeff_denom[irf].add(tmpEff);
1410 ATH_MSG_VERBOSE(
"coeff_denom[" << irf <<
"] = " << coeff_denom[irf].value(
this));
1416 if (coeff_denom[irf].nominal == 0.) {
1420 for (
int itl = 0; itl < rank; itl++) {
1421 ATH_MSG_VERBOSE(
"coeff_denom[" << irf <<
"] = " << coeff_denom[irf].value(
this));
1427 std::shared_ptr<TMatrixT<double>> MMmatrix;
1430 for (
int i = 0; i < rank; i++) {
1431 for (
int j = 0; j < rank; j++) {
1433 (*MMmatrix)(i,j) =
m_coeffs[lepidx][i][j];
1439 if(
verbose) MMmatrix->Print();
1441 TMatrixT<double> MMmatrix_inv(rank,rank);
1442 MMmatrix_inv = *MMmatrix;
1443 MMmatrix_inv.Invert();
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];
1452 TMatrixT<double> nevents_mat(rank,1), nfake_mat(rank,1), nfake_err_mat(rank,1);
1453 for (
int i = 0; i < rank; i++) {
1458 if(
verbose) nevents_mat.Print();
1460 nfake_mat = MMmatrix_inv*nevents_mat;
1463 if(
verbose) MMmatrix->Print();
1465 if(
verbose) nevents_mat.Print();
1467 if(
verbose) nfake_mat.Print();
1470 nfake_err_mat = MMmatrix_sqr*nevents_mat;
1473 for (
int ipar = 0; ipar < (0x1 <<nlep) ; ipar++) {
1474 nrf[ipar] = nfake_mat(ipar, 0);
1480 for (
int ibit = 0; ibit < nlep; ibit++) {
1481 tights.set(ibit, 1);
1482 reals.set(ibit, ~fakes[ibit]);
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");
1492 ATH_MSG_VERBOSE(
"Accepted " << n_proc_acc <<
" processes for nlep = " << nlep);
1502 Double_t f_from_fit, junk;
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;
1512 bool stopSearch = 0;
1514 double convergeCriteria = 0.01;
1516 int nfake_tot_index = 1;
1518 Double_t arglist[10];
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);
1529 lhoodFit->mnexcm(
"MIGRAD", arglist ,2,ierflg);
1532 lhoodFit->mnstat(f_from_fit, junk, junk, ijunk, ijunk, ijunk);
1535 while (!stopSearch) {
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);
1544 lhoodFit->mnexcm(
"MIGRAD", arglist ,2,ierflg);
1547 lhoodFit->mnstat(f_with_guess, junk, junk, ijunk, ijunk, ijunk);
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);
1551 if (TMath::IsNaN(f_with_guess)) {
1552 f_with_guess = f_from_fit + 1.;
1554 if ((f_with_guess - f_from_fit) > 0.5) {
1555 n_fake_guess_hi = n_fake_guess;
1557 n_fake_guess_lo = n_fake_guess;
1560 n_fake_guess = 0.5*(n_fake_guess_lo+n_fake_guess_hi);
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) {
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) {
1575 arglist[0] = nfake_tot_index;
1576 arglist[1] = n_fake_fit;
1577 lhoodFit->mnexcm(
"SET PAR", arglist, 2, ierflg);
1580 return n_fake_guess - n_fake_fit;
1593 Double_t f_from_fit, junk;
1596 lhoodFit->mnstat(f_from_fit, junk, junk, ijunk, ijunk, ijunk);
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;
1605 bool stopSearch = 0;
1606 double convergeCriteria = 0.01;
1607 double min_n_fake_guess = 0.05;
1609 int nfake_tot_index = 1;
1611 Double_t arglist[10];
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);
1622 lhoodFit->mnexcm(
"MIGRAD", arglist ,2,ierflg);
1625 lhoodFit->mnstat(f_from_fit, junk, junk, ijunk, ijunk, ijunk);
1627 while (!stopSearch) {
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);
1638 lhoodFit->mnexcm(
"MIGRAD", arglist ,2,ierflg);
1640 lhoodFit->mnstat(f_with_guess, junk, junk, ijunk, ijunk, ijunk);
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);
1644 if ((f_with_guess - f_from_fit) > 0.5) {
1645 n_fake_guess_lo = n_fake_guess;
1647 n_fake_guess_hi = n_fake_guess;
1649 n_fake_guess = 0.5*(n_fake_guess_lo+n_fake_guess_hi);
1651 if (((n_fake_guess_hi - n_fake_guess_lo)/n_fake_guess_hi < convergeCriteria) || (n_fake_guess_hi < min_n_fake_guess) ) {
1653 if (n_fake_guess_hi < n_fake_fit) {
1661 arglist[0] = nfake_tot_index;
1662 arglist[1] = n_fake_fit;
1663 lhoodFit->mnexcm(
"SET PAR", arglist, 2, ierflg);
1666 return n_fake_guess - n_fake_fit;
1679 ATH_MSG_ERROR(
"Multiple calls to saveProgress are not supported");
1680 return StatusCode::FAILURE;
1685 std::unique_ptr<TTree> t(
new TTree(
"LhoodMM_progress",
"Stores current info from LhoodMM_toos"));
1687 std::unique_ptr<TTree> t_nlep(
new TTree(
"LhoodMM_progress_nlep",
"Stores minimum and maximum lepton multiplicities"));
1690 ATH_MSG_VERBOSE(
"Branch split level is " << fitInfoBranch->GetSplitLevel() );
1704 return StatusCode::SUCCESS;
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;
1721 return StatusCode::FAILURE;
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;
1733 int merged_maxnlep, merged_maxnlep_prev = -1;
1734 t_nlep->SetBranchAddress(
"maxnlep", &merged_maxnlep);
1736 TTree *t = (TTree*)fin->Get((prefix +
"LhoodMM_progress").c_str());
1738 ATH_MSG_ERROR(
"Unable to find LhoodMM_progress tree in " << filename);
1739 return StatusCode::FAILURE;
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;
1751 merged_maxnlep_prev = merged_maxnlep;
1762 t->SetBranchAddress(
"glb_fitInfo", &fitInfoPtr );
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);
1777 nentries = (Int_t)t->GetEntries();
1778 for (Int_t ievt = 0; ievt < nentries; ievt++) {
1784 std::string hname =
histogram->GetName();
1785 for (
auto& im: *tmp_fitInfo_1dhisto_map) {
1787 TH1F* ihistogram = (TH1F*)im.first;
1788 std::string iname = ihistogram->GetName();
1789 if (hname == iname) {
1791 for (
int icell = 0; icell<ncells; icell++) {
1800 std::string hname =
histogram->GetName();
1801 for (
auto& im: *tmp_fitInfo_2dhisto_map) {
1803 TH1F* ihistogram = (TH1F*)im.first;
1804 std::string iname = ihistogram->GetName();
1805 if (hname == iname) {
1807 for (
int icell = 0; icell<ncells; icell++) {
1816 std::string hname =
histogram->GetName();
1817 for (
auto& im: *tmp_fitInfo_3dhisto_map){
1819 TH1F* ihistogram = (TH1F*)im.first;
1820 std::string iname = ihistogram->GetName();
1821 if (hname == iname) {
1823 for (
int icell = 0; icell<ncells; icell++) {
1841 return StatusCode::SUCCESS;
#define ATH_CHECK
Evaluate an expression and check for errors.
#define ATH_MSG_VERBOSE(x)
#define ATH_MSG_WARNING(x)
std::chrono::high_resolution_clock Clock
std::string PathResolverFindDataFile(const std::string &logical_file_name)
constexpr int pow(int base, int exp) noexcept
Gaudi::Details::PropertyBase & declareProperty(Gaudi::Property< T, V, H > &t)
bool msgLvl(const MSG::Level lvl) const
const FakeBkgTools::Efficiency & fakeEffObj(unsigned ilep) const
int charge(unsigned ilep) const
bool isTight(unsigned ilep) const
const FakeBkgTools::Efficiency & realEffObj(unsigned ilep) const
bool add(const std::string &hname, TKey *tobj)
Select isolated Photons, Electrons and Muons.
JetConstituentVector::iterator iterator
std::vector< std::vector< std::vector< FakeBkgTools::Efficiency > > > coeffs_num
void resizeVectors(unsigned nlep)
std::vector< double > eventCount
std::vector< std::vector< FakeBkgTools::Efficiency > > normterms
std::vector< std::vector< double > > OSfrac_denom
std::vector< std::vector< double > > event_sumw2
std::vector< std::vector< double > > OSfrac_num
std::vector< std::vector< double > > event_cat