21 #include "TTreeReader.h"
22 #include "TTreeReaderValue.h"
24 #include "TDirectory.h"
33 using 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++) {
102 for (
int ientry = 0; ientry < (0x1 << (ilep+1)); ientry++) {
103 m_coeffs[ilep][ientry].resize((0
x1 << (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);
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);
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);
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;
350 fitInfo = &histoMap->second[
icell];
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;
379 fitInfo = &histoMap->second[
icell];
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;
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;
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);
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 & (0
x1 << ilep) ) {
499 if (irf & (0
x1 << ilep)) {
507 if (irf & (0
x1 << 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;
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;
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++) {
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;
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 << (0
x1 << 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<(1
u<<
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);;
880 init_pars.resize(npar);
882 vector< vector <double> > loc_init_pars;
886 loc_init_pars[ilep-1].resize(0
x1 << 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;
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);
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]);
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++) {
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);
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;
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(0
x1 <<nlep);
1262 std::string txt =
"Testing variable transform: Initial nrf: ";
1263 for (
auto i = nrf.begin();
i != nrf.end(); ++
i)
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.;
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]);
1323 txt =
"testing variable transform: Initial pars: ";
1324 for (
int i = 0;
i < (0x1 << nlep);
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);
1416 if (coeff_denom[irf].nominal == 0.) {
1420 for (
int itl = 0; itl < rank; itl++) {
1427 std::shared_ptr<TMatrixT<double>> MMmatrix;
1430 for (
int i = 0;
i < rank;
i++) {
1431 for (
int j = 0; j < rank; 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) {
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) {
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());
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);
1778 for (Int_t ievt = 0; ievt <
nentries; ievt++) {
1785 for (
auto&
im: *tmp_fitInfo_1dhisto_map) {
1788 std::string iname = ihistogram->GetName();
1789 if (
hname == iname) {
1801 for (
auto&
im: *tmp_fitInfo_2dhisto_map) {
1804 std::string iname = ihistogram->GetName();
1805 if (
hname == iname) {
1817 for (
auto&
im: *tmp_fitInfo_3dhisto_map){
1820 std::string iname = ihistogram->GetName();
1821 if (
hname == iname) {
1841 return StatusCode::SUCCESS;