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 if (fOut->GetDirectory(var))
continue;
691 auto dOut = fOut->mkdir(var);
694 cout << __LINE__ <<
"\tUnfolding" << endl;
695 static auto tau =
config.get_optional<
float>(
"unfolding.TUnfold.regularisation.tau");
697 cout << __LINE__ <<
"\tFetching L-matrix" << endl;
699 if (!fs::exists(*Lmatrix))
700 BOOST_THROW_EXCEPTION(fs::filesystem_error(
"File with L-matrix not found!",
701 make_error_code(errc::no_such_file_or_directory)));
704 if (!tau && var ==
"nominal") {
709 cout << __LINE__ <<
"\tSaving shifts for variations of tau parameter" << endl;
711 "upper variation of regularisation", fOut, miss);
713 "lower variation of regularisation", fOut, miss);
717 cout << __LINE__ <<
"\ttau = " << tau << endl;
718 density->DoUnfold(tau.value_or(0));
723 cout << __LINE__ <<
"\tGetting output" << endl;
724 auto unf = unique_ptr<TH1>(density->GetOutput(
"unfold",
"particle level (" + var +
")"));
728 unf->SetDirectory(dOut);
729 unf->GetXaxis()->SetTitle(
"gen");
736 cout << __LINE__ <<
"\tCovariance matrix from measurement" << endl;
737 auto covOutData = unique_ptr<TH2>(density->GetEmatrixInput(
"covOutData",
738 "covariance matrix coming from input data distribution (" + var +
")"));
739 covOutData->SetDirectory(dOut);
740 covOutData->GetXaxis()->SetTitle(
"gen");
741 covOutData->GetYaxis()->SetTitle(
"gen");
744 cout << __LINE__ <<
"\tSaving correlation matrix from measurement" << endl;
745 SaveCorr(covInData ,
"corrInData" , dOut);
746 SaveCorr(covOutData,
"corrOutData", dOut);
750 cout << __LINE__ <<
"\tSaving response and probability matrices" << endl;
751 RM->SetDirectory(dOut);
753 RM->SetDirectory(
nullptr);
754 PM->SetDirectory(dOut);
757 cout << __LINE__ <<
"\tGetting backfolding" << endl;
758 auto backfolding = unique_ptr<TH1>(density->GetFoldedOutput(
760 "backfolded (detector level)",
763 backfolding->SetDirectory(dOut);
764 backfolding->GetXaxis()->SetTitle(
"rec");
765 backfolding->Write();
766 recData->Write(
"recData");
769 genMC->SetDirectory(dOut);
771 genMC->SetDirectory(
nullptr);
773 recMC->SetDirectory(dOut);
775 recMC->SetDirectory(
nullptr);
776 covInMC->SetDirectory(dOut);
779 cout << __LINE__ <<
"\tGetting systematic uncertainties from MC and from unfolding"
784 auto covOutUncor = Clone<TH2>(covOutData,
"covOutUncor");
785 covOutUncor->SetTitle(
"covariance matrix at particle level coming from the MC "
786 "(RM + miss + fake)");
787 covOutUncor->Reset();
789 auto dUncorr = dOut->mkdir(
"Uncorr");
791 cout << __LINE__ <<
"\tCovariance matrix from RM" << endl;
792 auto SysUncorr = unique_ptr<TH2>(density->GetEmatrixSysUncorr(
"RM",
793 "covariance matrix at particle level coming from the RM"));
794 SysUncorr->SetDirectory(dUncorr);
795 SysUncorr->GetXaxis()->SetTitle(
"gen");
797 covOutUncor->Add(SysUncorr.get());
798 cout << __LINE__ <<
"\tCovariance matrices from backgrounds" << endl;
799 for (
auto&
f: fake) {
800 auto SysBackgroundUncorr = unique_ptr<TH2>(density->GetEmatrixSysBackgroundUncorr(
803 Form(
"covariance matrix coming from %s",
f.second->GetTitle())
805 SysBackgroundUncorr->SetDirectory(dUncorr);
806 SysBackgroundUncorr->Write();
807 covOutUncor->Add(SysBackgroundUncorr.get());
811 cout << __LINE__ <<
"\tCovariance matrices from input bin-to-bin "
812 "uncorrelated systematic uncertainties." << endl;
813 auto SysBackgroundUncorr = unique_ptr<TH2>(
814 density->GetEmatrixSysBackgroundUncorr(
815 "sysUncorr",
"sysUncorr",
816 "covariance matrix from trigger and prefiring uncertainties"));
817 SysBackgroundUncorr->SetDirectory(dUncorr);
818 SysBackgroundUncorr->Write();
819 covOutUncor->Add(SysBackgroundUncorr.get());
821 cout << __LINE__ <<
"\tCovariance matrices from inefficiencies" << endl;
822 for (
const auto& m: miss) {
823 auto SysIneffUncorr = Clone<TH2>(SysUncorr,
"miss" + m.first);
824 SysIneffUncorr->Reset();
825 for (
int i = 1; i <= m.second->GetNbinsX(); ++i) {
826 double error = m.second->GetBinError(i) * ::abs(unf->GetBinContent(i));
827 SysIneffUncorr->SetBinContent(i, i, pow(error, 2));
829 SysIneffUncorr->SetDirectory(dUncorr);
830 SysIneffUncorr->Write();
831 covOutUncor->Add(SysIneffUncorr.get());
834 covOutUncor->SetDirectory(dOut);
835 covOutUncor->Write();
837 auto covOutTotal = Clone<TH2>(covOutData,
"covOutTotal");
838 covOutTotal->Add(covOutUncor.get());
839 covOutTotal->SetTitle(
"covariance matrix at particle level including "
840 "contributions from data and MC");
841 covOutTotal->SetDirectory(dOut);
842 covOutTotal->Write();
843 SaveCorr(covOutTotal,
"corrOutTotal", dOut);
845 cout << __LINE__ <<
"\tSaving estimates of fake counts" << endl;
846 for (
auto&
f: fake) {
847 TString
name =
"fake" +
f.first,
848 title =
f.second->GetTitle();
849 cout << __LINE__ <<
'\t' <<
name << endl;
852 f.second->SetDirectory(dOut);
853 f.second->SetTitle(title +
" (corrected)");
854 f.second->Write(
name);
855 f.second->SetDirectory(
nullptr);
858 if (var ==
"nominal" && applySyst) {
859 cout << __LINE__ <<
"\tSaving shifts from background variations "
860 "in parallel directories" << endl;
862 for (
auto&
f: fake) {
863 TString
name =
"fake" +
f.first,
864 title =
f.second->GetTitle();
865 cout << __LINE__ <<
'\t' <<
name << endl;
869 auto shift = unique_ptr<TH1>(density->GetDeltaSysBackgroundScale(
873 shift->Add(unf.get());
874 auto dOut = fOut->mkdir(
name +
SysUp,
"upper shift of " + title);
875 shift->SetDirectory(dOut);
877 shift->GetXaxis()->SetTitle(
"gen");
878 shift->Write(
"unfold");
884 auto shift = unique_ptr<TH1>(density->GetDeltaSysBackgroundScale(
889 shift->Add(unf.get());
890 auto dOut = fOut->mkdir(
name +
SysDown,
"lower shift of " + title);
891 shift->SetDirectory(dOut);
893 shift->GetXaxis()->SetTitle(
"gen");
894 shift->Write(
"unfold");
900 cout << __LINE__ <<
"\tSaving estimates of miss counts" << endl;
901 for (
auto& m: miss) {
902 TString
name =
"miss" + m.first,
903 title = m.second->GetTitle();
904 cout << __LINE__ <<
'\t' <<
name << endl;
906 auto M = Clone<TH1>(m.second,
name);
910 for (
int i = 1; i <= unf->GetNbinsX(); ++i) {
911 double u = unf->GetBinContent(i),
912 content = m.second->GetBinContent(i) * u ,
913 error = m.second->GetBinError (i) * ::abs(u);
914 M->SetBinContent(i, content);
915 M->SetBinError (i, error );
917 M->SetDirectory(dOut);
919 M->SetDirectory(
nullptr);
921 if (var ==
"nominal" && applySyst) {
922 cout << __LINE__ <<
"\tSaving shifts from inefficiency variations "
923 "in parallel directories" << endl;
926 auto missNormVar =
config.get_optional<
float>(
"unfolding.missNormVar").value_or(0.05);
927 cout << __LINE__ <<
"\tmissNormVar = " << missNormVar << endl;
931 auto shift = Clone<TH1>(M,
name +
SysUp);
932 shift->Scale(missNormVar);
933 shift->Add(unf.get());
934 auto dOut = fOut->mkdir(
name +
SysUp,
"lower shift of " + title);
935 shift->SetDirectory(dOut);
937 shift->GetXaxis()->SetTitle(
"gen");
938 shift->Write(
"unfold");
946 shift->Scale(missNormVar);
947 shift->Add(unf.get());
948 auto dOut = fOut->mkdir(
name +
SysDown,
"lower shift of " + title);
949 shift->SetDirectory(dOut);
951 shift->GetXaxis()->SetTitle(
"gen");
952 shift->Write(
"unfold");
961 cout << __LINE__ <<
"\tBottom line test" << endl;
963 int rebin = recMC->GetNbinsX()/genMC->GetNbinsX();
965 cout << __LINE__ <<
"\tDetector level (`rebin` = " << rebin <<
"): ";
968 cout << __LINE__ <<
"\tHadron level (with data unc. only): ";
971 cout << __LINE__ <<
"\tHadron level (with data + MC unc.): ";
977 cout << __func__ <<
' ' << slice <<
" stop" << endl;