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] = std::move(h);
515 name.ReplaceAll(
"miss",
"");
516 cout << __LINE__ <<
"\tmiss\t" <<
name << endl;
517 miss[
name] = std::move(h);
521 cout << __LINE__ <<
"\tExtracting RM from MC" << endl;
522 auto RM = unique_ptr<TH2>(dirMC->Get<TH2>(
"RM"));
526 RM->SetDirectory(
nullptr);
528 auto genMC = unique_ptr<TH1>(dirMC->Get<TH1>(
"gen")),
529 recMC = unique_ptr<TH1>(dirMC->Get<TH1>(
"rec"));
532 "histogram", *dirMC) );
533 genMC->SetName(
"genMC");
534 recMC->SetName(
"recMC");
535 genMC->SetDirectory(
nullptr);
536 recMC->SetDirectory(
nullptr);
539 PM->SetDirectory(
nullptr);
542 cout << __LINE__ <<
"\tCalculating miss and fake rates" << endl;
549 unique_ptr<TH1> genMC_noMiss = Clone(genMC,
"genMC_noMiss");
550 for (
auto&
f: fake)
f.second ->Divide(
f.second.get(), recMC.get(), 1, 1,
"b");
551 for (
auto& m: miss) genMC_noMiss->Add (m.second.get(), -1);
552 for (
auto& m: miss) m.second ->Divide(m.second.get(), genMC_noMiss.get(), 1, 1,
"b");
561 auto rec = unique_ptr<TH1>(fData->Get<TH1>(
"nominal/rec"));
563 for (
auto&
f: fake)
f.second->Multiply(rec.get());
570 cout << __LINE__ <<
"\tExtracting data variations and running unfolding" << endl;
573 for (
const auto&& objData: *(fData->GetListOfKeys())) {
575 auto keyData =
dynamic_cast<TKey*
>(objData);
576 const TString classname = keyData->ReadObj()->ClassName();
585 if (!classname.Contains(
"TDirectory"))
continue;
587 const TString DATAvar = objData->GetName();
588 if (DATAvar !=
"nominal") {
589 if (!applySyst)
continue;
590 if (MCvar !=
"nominal")
continue;
592 cout << __LINE__ <<
"\tvariation: " << DATAvar << endl;
593 TString var = MCvar ==
"nominal" ? DATAvar : MCvar;
595 if (var !=
"nominal" && MCvar == DATAvar)
596 cerr <<
orange <<
"The same variation has been found "
597 "in both data and MC.\n" <<
def;
602 if (slice.second != ivar % slice.first)
continue;
605 auto dirData =
dynamic_cast<TDirectory*
>(keyData->ReadObj());
608 auto recData = unique_ptr<TH1>(dirData->Get<TH1>(
"rec"));
609 recData->SetName(
"recData");
610 recData->SetTitle(
"detector level (" + var +
")");
611 recData->GetXaxis()->SetTitle(
"rec");
612 recData->SetDirectory(
nullptr);
613 auto covInData = unique_ptr<TH2>(dirData->Get<TH2>(
"cov"));
614 covInData->SetName(
"covInData");
615 covInData->SetTitle(
"covariance matrix at detector level (" + var +
")");
616 covInData->GetXaxis()->SetTitle(
"rec");
617 covInData->GetYaxis()->SetTitle(
"rec");
618 covInData->SetDirectory(
nullptr);
619 auto covInMC = unique_ptr<TH2>(dirMC->Get<TH2>(
"cov"));
620 covInMC->SetName(
"covInMC");
621 covInMC->SetTitle(
"covariance matrix at detector level (" + var +
")");
622 covInMC->GetXaxis()->SetTitle(
"rec");
623 covInMC->GetYaxis()->SetTitle(
"rec");
624 covInMC->SetDirectory(
nullptr);
626 cout << __LINE__ <<
'\t' <<
"\e[1m" << DATAvar <<
"\e[0m" << endl;
628 if (DATAvar.Contains(
"nominal")) {
632 RM->SetTitle(Form(
"%.1f",condition));
641 cout << __LINE__ <<
"\tSetting up density & input (checking "
642 "and comparing the bin contents of data and MC)" << endl;
644 auto density = make_unique<MyTUnfoldDensity>(
646 TUnfold::kHistMapOutputHoriz,
647 TUnfold::kRegModeNone,
648 TUnfold::kEConstraintNone,
649 TUnfoldDensity::kDensityModeBinWidthAndUser);
652 density->SetEpsMatrix(1e-100);
654 int status = density->SetInput(
661 cerr << __LINE__ <<
'\t' <<
orange <<
"unfold status = " << status <<
'\n' <<
def;
665 cout << __LINE__ <<
"\tSubtract background" << endl;
666 auto fakeNormVar =
config.get_optional<
float>(
"unfolding.fakeNormVar").value_or(0.05);
667 cout << __LINE__ <<
"\tfakeNormVar = " << fakeNormVar << endl;
668 for (
auto&
f: fake) {
669 cout << __LINE__ <<
'\t' <<
f.first << endl;
670 density->SubtractBackground(
686 cout << __LINE__ <<
"\tAdding bin-to-bin uncertainty" << endl;
688 if (!fs::exists(*sysUncorr))
689 BOOST_THROW_EXCEPTION(fs::filesystem_error(
"File with systematic "
690 "bin-to-bin uncorrelated uncertainties was not found!",
691 make_error_code(errc::no_such_file_or_directory)));
693 auto fSys = make_unique<TFile>(sysUncorr->c_str(),
"READ");
694 auto hSysUncorr = unique_ptr<TH1>( fSys->GetDirectory(DATAvar)
695 ->Get<TH1>(
"sysUncorr1D") );
696 density->SubtractBackground(hSysUncorr.get(),
"sysUncorr", 1.0, 0.);
700 if (fOut->GetDirectory(var))
continue;
701 auto dOut = fOut->mkdir(var);
704 cout << __LINE__ <<
"\tUnfolding" << endl;
705 static auto tau =
config.get_optional<
float>(
"unfolding.TUnfold.regularisation.tau");
707 cout << __LINE__ <<
"\tFetching L-matrix" << endl;
709 if (!fs::exists(*Lmatrix))
710 BOOST_THROW_EXCEPTION(fs::filesystem_error(
"File with L-matrix not found!",
711 make_error_code(errc::no_such_file_or_directory)));
714 if (!tau && var ==
"nominal") {
719 cout << __LINE__ <<
"\tSaving shifts for variations of tau parameter" << endl;
721 "upper variation of regularisation", fOut, miss);
723 "lower variation of regularisation", fOut, miss);
727 cout << __LINE__ <<
"\ttau = " << tau << endl;
728 density->DoUnfold(tau.value_or(0));
733 cout << __LINE__ <<
"\tGetting output" << endl;
734 auto unf = unique_ptr<TH1>(density->GetOutput(
"unfold",
"particle level (" + var +
")"));
738 unf->SetDirectory(dOut);
739 unf->GetXaxis()->SetTitle(
"gen");
746 cout << __LINE__ <<
"\tCovariance matrix from measurement" << endl;
747 auto covOutData = unique_ptr<TH2>(density->GetEmatrixInput(
"covOutData",
748 "covariance matrix coming from input data distribution (" + var +
")"));
749 covOutData->SetDirectory(dOut);
750 covOutData->GetXaxis()->SetTitle(
"gen");
751 covOutData->GetYaxis()->SetTitle(
"gen");
754 cout << __LINE__ <<
"\tSaving correlation matrix from measurement" << endl;
755 SaveCorr(covInData ,
"corrInData" , dOut);
756 SaveCorr(covOutData,
"corrOutData", dOut);
760 cout << __LINE__ <<
"\tSaving response and probability matrices" << endl;
761 RM->SetDirectory(dOut);
763 RM->SetDirectory(
nullptr);
764 PM->SetDirectory(dOut);
767 cout << __LINE__ <<
"\tGetting backfolding" << endl;
768 auto backfolding = unique_ptr<TH1>(density->GetFoldedOutput(
770 "backfolded (detector level)",
773 backfolding->SetDirectory(dOut);
774 backfolding->GetXaxis()->SetTitle(
"rec");
775 backfolding->Write();
776 recData->Write(
"recData");
779 genMC->SetDirectory(dOut);
781 genMC->SetDirectory(
nullptr);
783 recMC->SetDirectory(dOut);
785 recMC->SetDirectory(
nullptr);
786 covInMC->SetDirectory(dOut);
789 cout << __LINE__ <<
"\tGetting systematic uncertainties from MC and from unfolding"
794 auto covOutUncor = Clone<TH2>(covOutData,
"covOutUncor");
795 covOutUncor->SetTitle(
"covariance matrix at particle level coming from the MC "
796 "(RM + miss + fake)");
797 covOutUncor->Reset();
799 auto dUncorr = dOut->mkdir(
"Uncorr");
801 cout << __LINE__ <<
"\tCovariance matrix from RM" << endl;
802 auto SysUncorr = unique_ptr<TH2>(density->GetEmatrixSysUncorr(
"RM",
803 "covariance matrix at particle level coming from the RM"));
804 SysUncorr->SetDirectory(dUncorr);
805 SysUncorr->GetXaxis()->SetTitle(
"gen");
807 covOutUncor->Add(SysUncorr.get());
808 cout << __LINE__ <<
"\tCovariance matrices from backgrounds" << endl;
809 for (
auto&
f: fake) {
810 auto SysBackgroundUncorr = unique_ptr<TH2>(density->GetEmatrixSysBackgroundUncorr(
813 Form(
"covariance matrix coming from %s",
f.second->GetTitle())
815 SysBackgroundUncorr->SetDirectory(dUncorr);
816 SysBackgroundUncorr->Write();
817 covOutUncor->Add(SysBackgroundUncorr.get());
821 cout << __LINE__ <<
"\tCovariance matrices from input bin-to-bin "
822 "uncorrelated systematic uncertainties." << endl;
823 auto SysBackgroundUncorr = unique_ptr<TH2>(
824 density->GetEmatrixSysBackgroundUncorr(
825 "sysUncorr",
"sysUncorr",
826 "covariance matrix from trigger and prefiring uncertainties"));
827 SysBackgroundUncorr->SetDirectory(dUncorr);
828 SysBackgroundUncorr->Write();
829 covOutUncor->Add(SysBackgroundUncorr.get());
831 cout << __LINE__ <<
"\tCovariance matrices from inefficiencies" << endl;
832 for (
const auto& m: miss) {
833 auto SysIneffUncorr = Clone<TH2>(SysUncorr,
"miss" + m.first);
834 SysIneffUncorr->Reset();
835 for (
int i = 1; i <= m.second->GetNbinsX(); ++i) {
836 double error = m.second->GetBinError(i) * ::abs(unf->GetBinContent(i));
837 SysIneffUncorr->SetBinContent(i, i, pow(error, 2));
839 SysIneffUncorr->SetDirectory(dUncorr);
840 SysIneffUncorr->Write();
841 covOutUncor->Add(SysIneffUncorr.get());
844 covOutUncor->SetDirectory(dOut);
845 covOutUncor->Write();
847 auto covOutTotal = Clone<TH2>(covOutData,
"covOutTotal");
848 covOutTotal->Add(covOutUncor.get());
849 covOutTotal->SetTitle(
"covariance matrix at particle level including "
850 "contributions from data and MC");
851 covOutTotal->SetDirectory(dOut);
852 covOutTotal->Write();
853 SaveCorr(covOutTotal,
"corrOutTotal", dOut);
855 cout << __LINE__ <<
"\tSaving estimates of fake counts" << endl;
856 for (
auto&
f: fake) {
857 TString
name =
"fake" +
f.first,
858 title =
f.second->GetTitle();
859 cout << __LINE__ <<
'\t' <<
name << endl;
862 f.second->SetDirectory(dOut);
863 f.second->SetTitle(title +
" (corrected)");
864 f.second->Write(
name);
865 f.second->SetDirectory(
nullptr);
868 if (var ==
"nominal" && applySyst) {
869 cout << __LINE__ <<
"\tSaving shifts from background variations "
870 "in parallel directories" << endl;
872 for (
auto&
f: fake) {
873 TString
name =
"fake" +
f.first,
874 title =
f.second->GetTitle();
875 cout << __LINE__ <<
'\t' <<
name << endl;
879 auto shift = unique_ptr<TH1>(density->GetDeltaSysBackgroundScale(
883 shift->Add(unf.get());
884 auto dOut = fOut->mkdir(
name +
SysUp,
"upper shift of " + title);
885 shift->SetDirectory(dOut);
887 shift->GetXaxis()->SetTitle(
"gen");
888 shift->Write(
"unfold");
894 auto shift = unique_ptr<TH1>(density->GetDeltaSysBackgroundScale(
899 shift->Add(unf.get());
900 auto dOut = fOut->mkdir(
name +
SysDown,
"lower shift of " + title);
901 shift->SetDirectory(dOut);
903 shift->GetXaxis()->SetTitle(
"gen");
904 shift->Write(
"unfold");
910 cout << __LINE__ <<
"\tSaving estimates of miss counts" << endl;
911 for (
auto& m: miss) {
912 TString
name =
"miss" + m.first,
913 title = m.second->GetTitle();
914 cout << __LINE__ <<
'\t' <<
name << endl;
916 auto M = Clone<TH1>(m.second,
name);
920 for (
int i = 1; i <= unf->GetNbinsX(); ++i) {
921 double u = unf->GetBinContent(i),
922 content = m.second->GetBinContent(i) * u ,
923 error = m.second->GetBinError (i) * ::abs(u);
924 M->SetBinContent(i, content);
925 M->SetBinError (i, error );
927 M->SetDirectory(dOut);
929 M->SetDirectory(
nullptr);
931 if (var ==
"nominal" && applySyst) {
932 cout << __LINE__ <<
"\tSaving shifts from inefficiency variations "
933 "in parallel directories" << endl;
936 auto missNormVar =
config.get_optional<
float>(
"unfolding.missNormVar").value_or(0.05);
937 cout << __LINE__ <<
"\tmissNormVar = " << missNormVar << endl;
941 auto shift = Clone<TH1>(M,
name +
SysUp);
942 shift->Scale(missNormVar);
943 shift->Add(unf.get());
944 auto dOut = fOut->mkdir(
name +
SysUp,
"lower shift of " + title);
945 shift->SetDirectory(dOut);
947 shift->GetXaxis()->SetTitle(
"gen");
948 shift->Write(
"unfold");
956 shift->Scale(missNormVar);
957 shift->Add(unf.get());
958 auto dOut = fOut->mkdir(
name +
SysDown,
"lower shift of " + title);
959 shift->SetDirectory(dOut);
961 shift->GetXaxis()->SetTitle(
"gen");
962 shift->Write(
"unfold");
971 cout << __LINE__ <<
"\tBottom line test" << endl;
973 int rebin = recMC->GetNbinsX()/genMC->GetNbinsX();
975 cout << __LINE__ <<
"\tDetector level (`rebin` = " << rebin <<
"): ";
978 cout << __LINE__ <<
"\tHadron level (with data unc. only): ";
981 cout << __LINE__ <<
"\tHadron level (with data + MC unc.): ";
987 cout << __func__ <<
' ' << slice <<
" stop" << endl;