445 cout << __func__ <<
' ' << slice <<
" start" << endl;
447 auto sysUncorr =
config.get_optional<fs::path>(
"unfolding.sysUncorr"),
448 Lmatrix =
config.get_optional<fs::path>(
"unfolding.TUnfold.regularisation.Lmatrix");
449 const bool applySyst = steering &
DT::syst;
451 cout << __LINE__ <<
"\tOpening input files" << endl;
452 auto fData = make_unique<TFile>(inputData.c_str(),
"READ"),
453 fMC = make_unique<TFile>(inputMC .c_str(),
"READ");
463 cout << __LINE__ <<
"\tPreparing output file" << endl;
468 for (
const auto&& objMC: *(fMC->GetListOfKeys())) {
472 auto keyMC =
dynamic_cast<TKey*
>(objMC);
473 const TString classname = keyMC->ReadObj()->ClassName();
481 if (!classname.Contains(
"TDirectory"))
continue;
483 const TString MCvar = objMC->GetName();
484 cout << __LINE__ <<
'\t' << MCvar << endl;
485 if (MCvar !=
"nominal" && !applySyst)
continue;
487 auto dirMC =
dynamic_cast<TDirectory*
>(keyMC->ReadObj());
490 cout << __LINE__ <<
"\tExtracting miss and fake counts" << endl;
491 map<TString, unique_ptr<TH1>> miss,
498 for (
const auto&& objMC2: *(dirMC->GetListOfKeys())) {
499 auto keyMC =
dynamic_cast<TKey*
>(objMC2);
500 if (!TString(keyMC->ReadObj()->ClassName()).Contains(
"TH") )
continue;
502 unique_ptr<TH1> h = ReadObj<TH1>(keyMC);
503 TString
name = h->GetName();
504 if (!
name.Contains(
"miss") && !
name.Contains(
"fake"))
continue;
505 if (h->GetEntries() == 0)
507 name.ReplaceAll(MCvar,
"");
508 h->SetDirectory(
nullptr);
509 if (
name.Contains(
"fake")) {
510 name.ReplaceAll(
"fake",
"");
511 cout << __LINE__ <<
"\tfake\t" <<
name << endl;
512 fake[
name] = move(h);
515 name.ReplaceAll(
"miss",
"");
516 cout << __LINE__ <<
"\tmiss\t" <<
name << endl;
517 miss[
name] = move(h);
521 cout << __LINE__ <<
"\tExtracting RM from MC" << endl;
522 auto RM = unique_ptr<TH2>(dirMC->Get<TH2>(
"RM"));
524 RM->SetDirectory(
nullptr);
526 auto genMC = unique_ptr<TH1>(dirMC->Get<TH1>(
"gen")),
527 recMC = unique_ptr<TH1>(dirMC->Get<TH1>(
"rec"));
528 genMC->SetName(
"genMC");
529 recMC->SetName(
"recMC");
530 genMC->SetDirectory(
nullptr);
531 recMC->SetDirectory(
nullptr);
534 PM->SetDirectory(
nullptr);
537 cout << __LINE__ <<
"\tCalculating miss and fake rates" << endl;
544 unique_ptr<TH1> genMC_noMiss = Clone(genMC,
"genMC_noMiss");
545 for (
auto&
f: fake)
f.second ->Divide(
f.second.get(), recMC.get(), 1, 1,
"b");
546 for (
auto& m: miss) genMC_noMiss->Add (m.second.get(), -1);
547 for (
auto& m: miss) m.second ->Divide(m.second.get(), genMC_noMiss.get(), 1, 1,
"b");
556 auto rec = unique_ptr<TH1>(fData->Get<TH1>(
"nominal/rec"));
558 for (
auto&
f: fake)
f.second->Multiply(rec.get());
565 cout << __LINE__ <<
"\tExtracting data variations and running unfolding" << endl;
568 for (
const auto&& objData: *(fData->GetListOfKeys())) {
570 auto keyData =
dynamic_cast<TKey*
>(objData);
571 const TString classname = keyData->ReadObj()->ClassName();
580 if (!classname.Contains(
"TDirectory"))
continue;
582 const TString DATAvar = objData->GetName();
583 if (DATAvar !=
"nominal") {
584 if (!applySyst)
continue;
585 if (MCvar !=
"nominal")
continue;
587 cout << __LINE__ <<
"\tvariation: " << DATAvar << endl;
588 TString var = MCvar ==
"nominal" ? DATAvar : MCvar;
590 if (var !=
"nominal" && MCvar == DATAvar)
591 cerr <<
orange <<
"The same variation has been found "
592 "in both data and MC.\n" <<
def;
597 if (slice.second != ivar % slice.first)
continue;
600 auto dirData =
dynamic_cast<TDirectory*
>(keyData->ReadObj());
603 auto recData = unique_ptr<TH1>(dirData->Get<TH1>(
"rec"));
604 recData->SetName(
"recData");
605 recData->SetTitle(
"detector level (" + var +
")");
606 recData->SetDirectory(
nullptr);
607 auto covInData = unique_ptr<TH2>(dirData->Get<TH2>(
"cov"));
608 covInData->SetName(
"covInData");
609 covInData->SetTitle(
"covariance matrix at detector level (" + var +
")");
610 covInData->SetDirectory(
nullptr);
611 auto covInMC = unique_ptr<TH2>(dirMC->Get<TH2>(
"cov"));
612 covInMC->SetName(
"covInMC");
613 covInMC->SetTitle(
"covariance matrix at detector level (" + var +
")");
614 covInMC->SetDirectory(
nullptr);
616 cout << __LINE__ <<
'\t' <<
"\e[1m" << DATAvar <<
"\e[0m" << endl;
618 if (DATAvar.Contains(
"nominal")) {
622 RM->SetTitle(Form(
"%.1f",condition));
631 cout << __LINE__ <<
"\tSetting up density & input (checking "
632 "and comparing the bin contents of data and MC)" << endl;
634 auto density = make_unique<MyTUnfoldDensity>(
636 TUnfold::kHistMapOutputHoriz,
637 TUnfold::kRegModeNone,
638 TUnfold::kEConstraintNone,
639 TUnfoldDensity::kDensityModeBinWidthAndUser);
642 density->SetEpsMatrix(1e-100);
644 int status = density->SetInput(
651 cerr << __LINE__ <<
'\t' <<
orange <<
"unfold status = " << status <<
'\n' <<
def;
655 cout << __LINE__ <<
"\tSubtract background" << endl;
656 auto fakeNormVar =
config.get_optional<
float>(
"unfolding.fakeNormVar").value_or(0.05);
657 cout << __LINE__ <<
"\tfakeNormVar = " << fakeNormVar << endl;
658 for (
auto&
f: fake) {
659 cout << __LINE__ <<
'\t' <<
f.first << endl;
660 density->SubtractBackground(
676 cout << __LINE__ <<
"\tAdding bin-to-bin uncertainty" << endl;
678 if (!fs::exists(*sysUncorr))
679 BOOST_THROW_EXCEPTION(fs::filesystem_error(
"File with systematic "
680 "bin-to-bin uncorrelated uncertainties was not found!",
681 make_error_code(errc::no_such_file_or_directory)));
683 auto fSys = make_unique<TFile>(sysUncorr->c_str(),
"READ");
684 auto hSysUncorr = unique_ptr<TH1>( fSys->GetDirectory(DATAvar)
685 ->Get<TH1>(
"sysUncorr1D") );
686 density->SubtractBackground(hSysUncorr.get(),
"sysUncorr", 1.0, 0.);
690 auto dOut = fOut->mkdir(var);
693 cout << __LINE__ <<
"\tUnfolding" << endl;
694 static auto tau =
config.get_optional<
float>(
"unfolding.TUnfold.regularisation.tau");
696 cout << __LINE__ <<
"\tFetching L-matrix" << endl;
698 if (!fs::exists(*Lmatrix))
699 BOOST_THROW_EXCEPTION(fs::filesystem_error(
"File with L-matrix not found!",
700 make_error_code(errc::no_such_file_or_directory)));
703 if (!tau && var ==
"nominal") {
708 cout << __LINE__ <<
"\tSaving shifts for variations of tau parameter" << endl;
710 "upper variation of regularisation", fOut, miss);
712 "lower variation of regularisation", fOut, miss);
716 cout << __LINE__ <<
"\ttau = " << tau << endl;
717 density->DoUnfold(tau.value_or(0));
722 cout << __LINE__ <<
"\tGetting output" << endl;
723 auto unf = unique_ptr<TH1>(density->GetOutput(
"unfold",
"particle level (" + var +
")"));
727 unf->SetDirectory(dOut);
728 unf->GetXaxis()->SetTitle(
"gen");
735 cout << __LINE__ <<
"\tCovariance matrix from measurement" << endl;
736 auto covOutData = unique_ptr<TH2>(density->GetEmatrixInput(
"covOutData",
737 "covariance matrix coming from input data distribution (" + var +
")"));
738 covOutData->SetDirectory(dOut);
739 covOutData->GetXaxis()->SetTitle(
"gen");
740 covOutData->GetYaxis()->SetTitle(
"gen");
743 cout << __LINE__ <<
"\tSaving correlation matrix from measurement" << endl;
744 SaveCorr(covInData ,
"corrInData" , dOut);
745 SaveCorr(covOutData,
"corrOutData", dOut);
749 cout << __LINE__ <<
"\tSaving response and probability matrices" << endl;
750 RM->SetDirectory(dOut);
752 RM->SetDirectory(
nullptr);
753 PM->SetDirectory(dOut);
756 cout << __LINE__ <<
"\tGetting backfolding" << endl;
757 auto backfolding = unique_ptr<TH1>(density->GetFoldedOutput(
759 "backfolded (detector level)",
762 backfolding->SetDirectory(dOut);
763 backfolding->GetXaxis()->SetTitle(
"rec");
764 backfolding->Write();
765 recData->Write(
"recData");
768 genMC->SetDirectory(dOut);
770 genMC->SetDirectory(
nullptr);
772 recMC->SetDirectory(dOut);
774 recMC->SetDirectory(
nullptr);
775 covInMC->SetDirectory(dOut);
778 cout << __LINE__ <<
"\tGetting systematic uncertainties from MC and from unfolding"
783 auto covOutUncor = Clone<TH2>(covOutData,
"covOutUncor");
784 covOutUncor->SetTitle(
"covariance matrix at particle level coming from the MC "
785 "(RM + miss + fake)");
786 covOutUncor->Reset();
788 auto dUncorr = dOut->mkdir(
"Uncorr");
790 cout << __LINE__ <<
"\tCovariance matrix from RM" << endl;
791 auto SysUncorr = unique_ptr<TH2>(density->GetEmatrixSysUncorr(
"RM",
792 "covariance matrix at particle level coming from the RM"));
793 SysUncorr->SetDirectory(dUncorr);
794 SysUncorr->GetXaxis()->SetTitle(
"gen");
796 covOutUncor->Add(SysUncorr.get());
797 cout << __LINE__ <<
"\tCovariance matrices from backgrounds" << endl;
798 for (
auto&
f: fake) {
799 auto SysBackgroundUncorr = unique_ptr<TH2>(density->GetEmatrixSysBackgroundUncorr(
802 Form(
"covariance matrix coming from %s",
f.second->GetTitle())
804 SysBackgroundUncorr->SetDirectory(dUncorr);
805 SysBackgroundUncorr->Write();
806 covOutUncor->Add(SysBackgroundUncorr.get());
810 cout << __LINE__ <<
"\tCovariance matrices from input bin-to-bin "
811 "uncorrelated systematic uncertainties." << endl;
812 auto SysBackgroundUncorr = unique_ptr<TH2>(
813 density->GetEmatrixSysBackgroundUncorr(
814 "sysUncorr",
"sysUncorr",
815 "covariance matrix from trigger and prefiring uncertainties"));
816 SysBackgroundUncorr->SetDirectory(dUncorr);
817 SysBackgroundUncorr->Write();
818 covOutUncor->Add(SysBackgroundUncorr.get());
820 cout << __LINE__ <<
"\tCovariance matrices from inefficiencies" << endl;
821 for (
const auto& m: miss) {
822 auto SysIneffUncorr = Clone<TH2>(SysUncorr,
"miss" + m.first);
823 SysIneffUncorr->Reset();
824 for (
int i = 1; i <= m.second->GetNbinsX(); ++i) {
825 double error = m.second->GetBinError(i) * ::abs(unf->GetBinContent(i));
826 SysIneffUncorr->SetBinContent(i, i, pow(error, 2));
828 SysIneffUncorr->SetDirectory(dUncorr);
829 SysIneffUncorr->Write();
830 covOutUncor->Add(SysIneffUncorr.get());
833 covOutUncor->SetDirectory(dOut);
834 covOutUncor->Write();
836 auto covOutTotal = Clone<TH2>(covOutData,
"covOutTotal");
837 covOutTotal->Add(covOutUncor.get());
838 covOutTotal->SetTitle(
"covariance matrix at particle level including "
839 "contributions from data and MC");
840 covOutTotal->SetDirectory(dOut);
841 covOutTotal->Write();
842 SaveCorr(covOutTotal,
"corrOutTotal", dOut);
844 cout << __LINE__ <<
"\tSaving estimates of fake counts" << endl;
845 for (
auto&
f: fake) {
846 TString
name =
"fake" +
f.first,
847 title =
f.second->GetTitle();
848 cout << __LINE__ <<
'\t' <<
name << endl;
851 f.second->SetDirectory(dOut);
852 f.second->SetTitle(title +
" (corrected)");
853 f.second->Write(
name);
854 f.second->SetDirectory(
nullptr);
857 if (var ==
"nominal" && applySyst) {
858 cout << __LINE__ <<
"\tSaving shifts from background variations "
859 "in parallel directories" << endl;
861 for (
auto&
f: fake) {
862 TString
name =
"fake" +
f.first,
863 title =
f.second->GetTitle();
864 cout << __LINE__ <<
'\t' <<
name << endl;
868 auto shift = unique_ptr<TH1>(density->GetDeltaSysBackgroundScale(
872 shift->Add(unf.get());
873 auto dOut = fOut->mkdir(
name +
SysUp,
"upper shift of " + title);
874 shift->SetDirectory(dOut);
876 shift->GetXaxis()->SetTitle(
"gen");
877 shift->Write(
"unfold");
883 auto shift = unique_ptr<TH1>(density->GetDeltaSysBackgroundScale(
888 shift->Add(unf.get());
889 auto dOut = fOut->mkdir(
name +
SysDown,
"lower shift of " + title);
890 shift->SetDirectory(dOut);
892 shift->GetXaxis()->SetTitle(
"gen");
893 shift->Write(
"unfold");
899 cout << __LINE__ <<
"\tSaving estimates of miss counts" << endl;
900 for (
auto& m: miss) {
901 TString
name =
"miss" + m.first,
902 title = m.second->GetTitle();
903 cout << __LINE__ <<
'\t' <<
name << endl;
905 auto M = Clone<TH1>(m.second,
name);
909 for (
int i = 1; i <= unf->GetNbinsX(); ++i) {
910 double u = unf->GetBinContent(i),
911 content = m.second->GetBinContent(i) * u ,
912 error = m.second->GetBinError (i) * ::abs(u);
913 M->SetBinContent(i, content);
914 M->SetBinError (i, error );
916 M->SetDirectory(dOut);
918 M->SetDirectory(
nullptr);
920 if (var ==
"nominal" && applySyst) {
921 cout << __LINE__ <<
"\tSaving shifts from inefficiency variations "
922 "in parallel directories" << endl;
925 auto missNormVar =
config.get_optional<
float>(
"unfolding.missNormVar").value_or(0.05);
926 cout << __LINE__ <<
"\tmissNormVar = " << missNormVar << endl;
930 auto shift = Clone<TH1>(M,
name +
SysUp);
931 shift->Scale(missNormVar);
932 shift->Add(unf.get());
933 auto dOut = fOut->mkdir(
name +
SysUp,
"lower shift of " + title);
934 shift->SetDirectory(dOut);
936 shift->GetXaxis()->SetTitle(
"gen");
937 shift->Write(
"unfold");
945 shift->Scale(missNormVar);
946 shift->Add(unf.get());
947 auto dOut = fOut->mkdir(
name +
SysDown,
"lower shift of " + title);
948 shift->SetDirectory(dOut);
950 shift->GetXaxis()->SetTitle(
"gen");
951 shift->Write(
"unfold");
960 cout << __LINE__ <<
"\tBottom line test" << endl;
962 int rebin = recMC->GetNbinsX()/genMC->GetNbinsX();
964 cout << __LINE__ <<
"\tDetector level (`rebin` = " << rebin <<
"): ";
967 cout << __LINE__ <<
"\tHadron level (with data unc. only): ";
970 cout << __LINE__ <<
"\tHadron level (with data + MC unc.): ";
976 cout << __func__ <<
' ' << slice <<
" stop" << endl;