42 std::function<double(
const std::vector<double> &,
const std::vector<double> &)>
LinkErrorFunction;
46 std::shared_ptr<HistBase>
CloneVirtual(
const TString &name)
override;
50 template <
typename... Args>
51 void Fill(Args &&...args) {
FillHist->Fill(std::forward<Args>(args)...); }
67 auto titleguard =
MSGUser()->StartTitleWithGuard(
"NGHist::GetFinalHist");
68 MSGUser()->MSG_WARNING(
"Plot ",
GetResultName(),
" has not been processed, please call NGHist::Process. Returning nullptr");
78 auto titleguard =
MSGUser()->StartTitleWithGuard(
"NGHist::GetCovariance");
79 MSGUser()->MSG_WARNING(
"Plot ",
GetResultName(),
" has not been processed, please call NGHist::Process. Returning nullptr");
89 auto titleguard =
MSGUser()->StartTitleWithGuard(
"NGHist::GetCorrelation");
90 MSGUser()->MSG_WARNING(
"Plot ",
GetResultName(),
" has not been processed, please call NGHist::Process. Returning nullptr");
96 template <
typename... Args>
99 template <
typename... Args>
102 template <
typename... Args>
105 template <
typename... Args>
108 template <
typename... Args>
112 template <
typename... Args>
115 if (
Final !=
nullptr)
116 return Final->GetBinError(std::forward<Args>(args)...);
118 return Nominal->GetBinError(std::forward<Args>(args)...);
122 template <
typename... Args>
125 if (
Final !=
nullptr)
126 return Final->GetBinError(std::forward<Args>(args)...);
128 return Nominal->GetBinError(std::forward<Args>(args)...);
132 template <
typename... Args>
135 if (
Final !=
nullptr)
137 double finalerror =
Final->GetBinError(std::forward<Args>(args)...);
138 double staterror =
Nominal->GetBinError(std::forward<Args>(args)...);
139 return std::sqrt(finalerror * finalerror - staterror * staterror);
166 if (name ==
"Nominal")
174 auto guard =
MSGUser()->StartTitleWithGuard(
"NGHist::GetVariation");
175 MSGUser()->MSG_WARNING(
"NGHist ",
GetResultName(),
" does not have variation ", name,
", returning nullptr");
190 auto guard =
MSGUser()->StartTitleWithGuard(
"NGHist::GetVariation");
191 MSGUser()->MSG_WARNING(
"NGHist ",
GetResultName(),
" does not have variation ", index,
", returning nullptr");
206 auto guard =
MSGUser()->StartTitleWithGuard(
"NGHist::GetVariationCorrelationFactor");
207 MSGUser()->MSG_ERROR(
"NGHist ",
GetResultName(),
" does not have variation ", name,
", returning zero");
234 template <
typename... Args>
235 NGHist(std::shared_ptr<MSGTool> MSG, std::shared_ptr<ConfigTool> c,
const TString &name,
const TString &filename,
const Args &...args);
237 NGHist(std::shared_ptr<MSGTool> MSG, std::shared_ptr<ConfigTool> c,
const TString &name);
241 std::shared_ptr<NGHist<HistType>>
Rebin(
const TString &name,
int rebinnum);
242 std::shared_ptr<NGHist<HistType>>
Rebin2D(
const TString &name,
int rebinnum_x,
int rebinum_y);
243 std::shared_ptr<NGHist<HistType>>
Rebin3D(
const TString &name,
int rebinnum_x,
int rebinum_y,
int rebinum_z);
244 std::shared_ptr<NGHist<HistType>>
Rebin(
const TString &name, std::vector<double> bindiv);
245 std::shared_ptr<NGHist<HistType>>
Rebin2D(
const TString &name, std::vector<double> bindiv_x, std::vector<double> bindiv_y);
246 std::shared_ptr<NGHist<HistType>>
Rebin3D(
const TString &name, std::vector<double> bindiv_x, std::vector<double> bindiv_y, std::vector<double> bindiv_z);
253 std::shared_ptr<NGHist<HistType>>
Clone(
const TString &name);
254 void Combine(std::shared_ptr<Result> result)
override;
263 bool Recover(TFile *file)
override;
264 bool Recover(
const TString &filename)
override;
265 bool Recover(std::shared_ptr<TFileHelper>)
override;
269 void Reset()
override;
270 void Scale(
double)
override;
271 void SetLinkPlot(uint64_t index, std::shared_ptr<HistBase> subplot)
override;
273 void SetLinkType(std::function<
double(
const std::vector<double> &)>, std::function<
double(
const std::vector<double> &,
const std::vector<double> &)>)
override;
274 void SetLinkType(std::function<
void(
const std::vector<TH1 *> &, TH1 *)>)
override;
278 void Write()
override;
282 static double Variance(
const std::vector<double> &v)
288 double mean_square = 0;
290 for (
auto &value : v)
293 mean_square += value * value;
297 mean_square /= v.size();
299 return (mean_square - mean * mean);
388 auto titleguard = MSGUser()->StartTitleWithGuard(
"NGHist::GetPartialCovariance");
391 bool is_contain_nominal =
false;
392 std::vector<size_t> inputsystindices;
393 for (
size_t i = 0; i < systlist.size(); i++)
395 auto findresult = SystematicIndexMap.find(systlist[i]);
396 if (findresult != SystematicIndexMap.end())
397 inputsystindices.emplace_back(findresult->second);
398 else if (systlist[i] !=
"Nominal")
399 MSGUser()->MSG_WARNING(
"Syst ", systlist[i],
" does not exist in plot ", GetResultName(),
", will skip that.");
401 is_contain_nominal =
true;
404 findresult = SystematicVariationBackup.find(systlist[i]);
405 if (findresult != SystematicVariationBackup.end())
406 MSGUser()->MSG_WARNING(
"Syst ", systlist[i],
" is in the backup list of plot ", GetResultName(),
", will skip that.");
410 std::sort(inputsystindices.begin(), inputsystindices.end());
411 auto last = std::unique(inputsystindices.begin(), inputsystindices.end());
412 inputsystindices.erase(last, inputsystindices.end());
415 std::vector<std::vector<size_t>> input_syst_indices;
416 std::vector<SystPolicy> input_syst_policies;
418 for (
auto &indices : this->SystematicVariationIndices)
420 for (
auto &index : indices)
421 if (std::binary_search(inputsystindices.begin(), inputsystindices.end(), index))
423 input_syst_indices.emplace_back(indices);
424 input_syst_policies.emplace_back(SystematicVariationPolicies[systcount]);
431 int Nbins = Nominal->GetNbinsX() * Nominal->GetNbinsY() * Nominal->GetNbinsY();
432 auto histtool = ToolkitUser()->template GetTool<HistTool>();
433 auto convert2vector = [=](TH1 *h)
435 std::vector<double> content;
436 content.reserve(Nbins);
437 for (
int i = 1; i <= h->GetXaxis()->GetNbins(); i++)
438 for (
int j = 1; j <= h->GetYaxis()->GetNbins(); j++)
439 for (
int k = 1; k <= h->GetZaxis()->GetNbins(); k++)
440 content.emplace_back(h->GetBinContent(i, j, k));
444 std::vector<std::vector<double>> cov(Nbins, std::vector<double>(Nbins, 0));
445 std::vector<double> nominal_content = convert2vector(Nominal);
448 for (
auto &indices : input_syst_indices)
450 double corr = CorrelationFactors[indices[0]];
451 SystPolicy policy = input_syst_policies[systcount];
452 std::vector<std::vector<double>> syst_contents;
453 for (
auto &index : indices)
454 syst_contents.emplace_back(convert2vector(SystematicVariations[index]));
456 std::vector<double> vdeltai(indices.size());
457 std::vector<double> vdeltaj(indices.size());
458 std::vector<double> vsystcontenti(indices.size());
459 std::vector<double> vsystcontentj(indices.size());
461 for (
int i = 0; i < Nbins; i++)
463 for (
int j = 0; j < Nbins; j++)
465 double deltai, deltaj;
466 int signi = syst_contents[0][i] - nominal_content[i] > 0 ? 1 : -1;
467 int signj = syst_contents[0][j] - nominal_content[j] > 0 ? 1 : -1;
468 for (
int k = 0; k < indices.size(); k++)
470 vdeltai[k] = fabs(syst_contents[k][i] - nominal_content[i]);
471 vdeltaj[k] = fabs(syst_contents[k][j] - nominal_content[j]);
472 vsystcontenti[k] = syst_contents[k][i];
473 vsystcontentj[k] = syst_contents[k][j];
476 if (policy == SystPolicy::Maximum)
478 deltai = *std::max_element(vdeltai.begin(), vdeltai.end());
479 deltaj = *std::max_element(vdeltaj.begin(), vdeltaj.end());
481 else if (policy == SystPolicy::Average)
483 deltai = std::accumulate(vdeltai.begin(), vdeltai.end(), (
double)0) / indices.size();
484 deltaj = std::accumulate(vdeltaj.begin(), vdeltaj.end(), (
double)0) / indices.size();
486 else if (policy == SystPolicy::Variance)
488 deltai = std::sqrt(std::fabs(Variance(vsystcontenti)));
489 deltaj = std::sqrt(std::fabs(Variance(vsystcontentj)));
491 else if (policy == SystPolicy::CTEQ)
493 deltai = (vsystcontenti[0] - vsystcontenti[1]) / 2;
494 deltaj = (vsystcontentj[0] - vsystcontentj[1]) / 2;
500 cov[i][j] += signi * signj * deltai * deltaj * corr;
502 cov[i][j] += signi * signj * deltai * deltaj;
510 if (is_contain_nominal)
512 std::vector<double> nominal_error;
513 nominal_error.reserve(Nbins);
514 for (
int i = 1; i <= Nominal->GetXaxis()->GetNbins(); i++)
515 for (
int j = 1; j <= Nominal->GetYaxis()->GetNbins(); j++)
516 for (
int k = 1; k <= Nominal->GetZaxis()->GetNbins(); k++)
517 nominal_error.emplace_back(Nominal->GetBinError(i, j, k));
519 for (
int i = 0; i < Nbins; i++)
520 cov[i][i] += nominal_error[i] * nominal_error[i];
681 inline std::shared_ptr<NGHist<HistType>>
NGHist<HistType>::Rebin2D(
const TString &name, std::vector<double> bindiv_x, std::vector<double> bindiv_y)
683 static_assert(!std::is_base_of<TH1, HistType>::value || std::is_base_of<TH2, HistType>::value,
"NGHist : function Rebin2D is not supported for 1D histograms");
684 static_assert(!std::is_base_of<TH3, HistType>::value,
"NGHist : function Rebin2D is not supported for 3D histograms");
686 auto titleguard = MSGUser()->StartTitleWithGuard(
"NGHist::Rebin2D");
688 if (bindiv_x.size() == 0 && bindiv_y.size() == 0)
690 MSGUser()->MSG_ERROR(
"No bin division is given, will do nothing for plot ", GetResultName());
694 bool fixX =
false, fixY =
false;
695 double minX, maxX, minY, maxY;
696 if (bindiv_x.size() == 0)
698 auto bindivarr = Nominal->GetXaxis()->GetXbins()->GetArray();
699 nbinX = Nominal->GetXaxis()->GetNbins();
701 bindiv_x = std::vector<double>(bindivarr, bindivarr + nbinX + 1);
704 minX = Nominal->GetXaxis()->GetBinLowEdge(1);
705 maxX = Nominal->GetXaxis()->GetBinUpEdge(nbinX);
709 if (bindiv_y.size() == 0)
711 auto bindivarr = Nominal->GetYaxis()->GetXbins()->GetArray();
712 nbinY = Nominal->GetYaxis()->GetNbins();
714 bindiv_y = std::vector<double>(bindivarr, bindivarr + nbinY + 1);
717 minY = Nominal->GetYaxis()->GetBinLowEdge(1);
718 maxY = Nominal->GetYaxis()->GetBinUpEdge(nbinY);
725 for (
int newX = 0, oldX = 1; newX < bindiv_x.size(); newX++)
727 if (bindiv_x.at(newX) < Nominal->GetXaxis()->GetBinLowEdge(1))
729 if (bindiv_x.at(newX) > Nominal->GetXaxis()->GetBinUpEdge(Nominal->GetXaxis()->GetNbins()))
731 if (!TMath::AreEqualAbs(Nominal->GetXaxis()->GetBinLowEdge(oldX), bindiv_x.at(newX), TMath::Max(1.E-8 * Nominal->GetXaxis()->GetBinWidth(oldX), 1.E-16)) && Nominal->GetXaxis()->GetBinLowEdge(oldX) > bindiv_x.at(newX))
732 MSGUser()->MSG_WARNING(
"Bin X edge ", newX + 1,
" of rebinned histogram does not match any bin edges of the old histogram. Result can be inconsistent");
737 for (
int newY = 0, oldY = 1; newY < bindiv_y.size(); newY++)
739 if (bindiv_y.at(newY) < Nominal->GetYaxis()->GetBinLowEdge(1))
741 if (bindiv_y.at(newY) > Nominal->GetYaxis()->GetBinUpEdge(Nominal->GetYaxis()->GetNbins()))
743 if (!TMath::AreEqualAbs(Nominal->GetYaxis()->GetBinLowEdge(oldY), bindiv_y.at(newY), TMath::Max(1.E-8 * Nominal->GetYaxis()->GetBinWidth(oldY), 1.E-16)) && Nominal->GetYaxis()->GetBinLowEdge(oldY) > bindiv_y.at(newY))
744 MSGUser()->MSG_WARNING(
"Bin Y edge ", newY + 1,
" of rebinned histogram does not match any bin edges of the old histogram. Result can be inconsistent");
753 auto Rebin = [](HistType *in, HistType *out)
755 auto xAxis = in->GetXaxis();
756 auto yAxis = in->GetYaxis();
757 for (
int i = 1; i <= xAxis->GetNbins(); i++)
758 for (
int j = 1; j <= yAxis->GetNbins(); j++)
760 double binCenterX = xAxis->GetBinCenter(i);
761 double binCenterY = yAxis->GetBinCenter(j);
762 int binX = out->GetXaxis()->FindBin(binCenterX);
763 int binY = out->GetYaxis()->FindBin(binCenterY);
764 out->SetBinContent(binX, binY, out->GetBinContent(binX, binY) + in->GetBinContent(i, j));
765 out->SetBinError(binX, binY,
Uncertainty::AplusB(out->GetBinError(binX, binY), in->GetBinError(i, j)));
769 std::shared_ptr<NGHist<HistType>> newPlot;
771 newPlot = std::make_shared<NGHist<HistType>>(MSGUser(), ConfigUser(), name, GetOutputFileName(), nbinX, minX, maxX, bindiv_y.size() - 1, bindiv_y.data());
773 newPlot = std::make_shared<NGHist<HistType>>(MSGUser(), ConfigUser(), name, GetOutputFileName(), bindiv_x.size() - 1, bindiv_x.data(), nbinY, minY, maxY);
775 newPlot = std::make_shared<NGHist<HistType>>(MSGUser(), ConfigUser(), name, GetOutputFileName(), bindiv_x.size() - 1, bindiv_x.data(), bindiv_y.size() - 1, bindiv_y.data());
777 Rebin(this->Nominal, newPlot->Nominal);
778 newPlot->FillHist = newPlot->Nominal;
781 newPlot->SystematicIndexMap = this->SystematicIndexMap;
782 newPlot->SystematicVariationNames = this->SystematicVariationNames;
783 newPlot->CorrelationFactors = this->CorrelationFactors;
784 newPlot->SystematicVariationIndices = this->SystematicVariationIndices;
785 newPlot->SystematicVariationPolicies = this->SystematicVariationPolicies;
786 newPlot->SystematicVariationBackup = this->SystematicVariationBackup;
788 newPlot->SystematicVariations.resize(this->SystematicVariations.size());
789 for (
int i = 0; i < this->SystematicVariationNames.size(); i++)
790 Rebin(this->SystematicVariations.at(i), newPlot->SystematicVariations.at(i));
804 inline std::shared_ptr<NGHist<HistType>>
NGHist<HistType>::Rebin3D(
const TString &name, std::vector<double> bindiv_x, std::vector<double> bindiv_y, std::vector<double> bindiv_z)
806 static_assert(!std::is_base_of<TH1, HistType>::value || std::is_base_of<TH3, HistType>::value,
"NGHist : function Rebin3D is not supported for 1D histograms");
807 static_assert(!std::is_base_of<TH2, HistType>::value || std::is_base_of<TH3, HistType>::value,
"NGHist : function Rebin3D is not supported for 2D histograms");
809 auto titleguard = MSGUser()->StartTitleWithGuard(
"NGHist::Rebin3D");
811 if (bindiv_x.size() == 0 && bindiv_y.size() == 0 && bindiv_z.size() == 0)
813 MSGUser()->MSG_ERROR(
"No bin division is given, will do nothing for plot ", GetResultName());
816 if (bindiv_x.size() == 0)
818 auto bindivarr = Nominal->GetXaxis()->GetXbins()->GetArray();
819 int size = Nominal->GetXaxis()->GetNbins() + 1;
820 bindiv_x = std::vector<double>(bindivarr, bindivarr + size);
822 if (bindiv_y.size() == 0)
824 auto bindivarr = Nominal->GetYaxis()->GetXbins()->GetArray();
825 int size = Nominal->GetYaxis()->GetNbins() + 1;
826 bindiv_y = std::vector<double>(bindivarr, bindivarr + size);
828 if (bindiv_z.size() == 0)
830 auto bindivarr = Nominal->GetZaxis()->GetXbins()->GetArray();
831 int size = Nominal->GetZaxis()->GetNbins() + 1;
832 bindiv_z = std::vector<double>(bindivarr, bindivarr + size);
835 int oldX = 1, oldY = 1, oldZ = 1;
836 for (
int newX = 0; newX < bindiv_x.size(); newX++)
838 if (bindiv_x.at(newX) < Nominal->GetXaxis()->GetBinLowEdge(1))
840 if (bindiv_x.at(newX) > Nominal->GetXaxis()->GetBinUpEdge(Nominal->GetXaxis()->GetNbins()))
842 if (!TMath::AreEqualAbs(Nominal->GetXaxis()->GetBinLowEdge(oldX), bindiv_x.at(newX), TMath::Max(1.E-8 * Nominal->GetXaxis()->GetBinWidth(oldX), 1.E-16)) && Nominal->GetXaxis()->GetBinLowEdge(oldX) > bindiv_x.at(newX))
843 MSGUser()->MSG_WARNING(
"Bin X edge ", newX + 1,
" of rebinned histogram does not match any bin edges of the old histogram. Result can be inconsistent");
847 for (
int newY = 0; newY < bindiv_y.size(); newY++)
849 if (bindiv_y.at(newY) < Nominal->GetYaxis()->GetBinLowEdge(1))
851 if (bindiv_y.at(newY) > Nominal->GetYaxis()->GetBinUpEdge(Nominal->GetYaxis()->GetNbins()))
853 if (!TMath::AreEqualAbs(Nominal->GetYaxis()->GetBinLowEdge(oldY), bindiv_y.at(newY), TMath::Max(1.E-8 * Nominal->GetYaxis()->GetBinWidth(oldY), 1.E-16)) && Nominal->GetYaxis()->GetBinLowEdge(oldY) > bindiv_y.at(newY))
854 MSGUser()->MSG_WARNING(
"Bin Y edge ", newY + 1,
" of rebinned histogram does not match any bin edges of the old histogram. Result can be inconsistent");
858 for (
int newZ = 0; newZ < bindiv_z.size(); newZ++)
860 if (bindiv_z.at(newZ) < Nominal->GetZaxis()->GetBinLowEdge(1))
862 if (bindiv_z.at(newZ) > Nominal->GetZaxis()->GetBinUpEdge(Nominal->GetZaxis()->GetNbins()))
864 if (!TMath::AreEqualAbs(Nominal->GetZaxis()->GetBinLowEdge(oldZ), bindiv_z.at(newZ), TMath::Max(1.E-8 * Nominal->GetZaxis()->GetBinWidth(oldZ), 1.E-16)) && Nominal->GetZaxis()->GetBinLowEdge(oldZ) > bindiv_z.at(newZ))
865 MSGUser()->MSG_WARNING(
"Bin Z edge ", newZ + 1,
" of rebinned histogram does not match any bin edges of the old histogram. Result can be inconsistent");
874 auto Rebin = [](HistType *in, HistType *out)
876 auto xAxis = in->GetXaxis();
877 auto yAxis = in->GetYaxis();
878 auto zAxis = in->GetZaxis();
879 for (
int i = 1; i <= xAxis->GetNbins(); i++)
880 for (
int j = 1; j <= yAxis->GetNbins(); j++)
881 for (
int k = 1; k <= zAxis->GetNbins(); k++)
883 double binCenterX = xAxis->GetBinCenter(i);
884 double binCenterY = yAxis->GetBinCenter(j);
885 double binCenterZ = zAxis->GetBinCenter(k);
886 int binX = out->GetXaxis()->FindBin(binCenterX);
887 int binY = out->GetYaxis()->FindBin(binCenterY);
888 int binZ = out->GetZaxis()->FindBin(binCenterZ);
889 out->SetBinContent(binX, binY, binZ, out->GetBinContent(binX, binY, binZ) + in->GetBinContent(i, j, k));
890 out->SetBinError(binX, binY, binZ,
Uncertainty::AplusB(out->GetBinError(binX, binY, binZ), in->GetBinError(i, j, k)));
894 std::shared_ptr<NGHist<HistType>> newPlot = std::make_shared<NGHist<HistType>>(MSGUser(), ConfigUser(), name, GetOutputFileName(), bindiv_x.size() - 1, bindiv_x.data(), bindiv_y.size() - 1, bindiv_y.data(), bindiv_z.size() - 1, bindiv_z.data());
895 Rebin(this->Nominal, newPlot->Nominal);
896 newPlot->FillHist = newPlot->Nominal;
899 newPlot->SystematicIndexMap = this->SystematicIndexMap;
900 newPlot->SystematicVariationNames = this->SystematicVariationNames;
901 newPlot->CorrelationFactors = this->CorrelationFactors;
902 newPlot->SystematicVariationIndices = this->SystematicVariationIndices;
903 newPlot->SystematicVariationPolicies = this->SystematicVariationPolicies;
904 newPlot->SystematicVariationBackup = this->SystematicVariationBackup;
906 newPlot->SystematicVariations.resize(this->SystematicVariations.size());
907 for (
int i = 0; i < this->SystematicVariationNames.size(); i++)
908 Rebin(this->SystematicVariations.at(i), newPlot->SystematicVariations.at(i));
1160 auto titleguard = MSGUser()->StartTitleWithGuard(
"NGHist::Process");
1161 auto histtool = ToolkitUser()->template GetTool<HistTool>();
1162 if (LinkedPlots.size() > 0)
1164 for (
size_t i = 0; i < LinkedPlots.size(); i++)
1165 LinkedPlots[i]->Process();
1168 bool systCompatible =
true;
1169 for (
size_t i = 0; i < LinkedPlots.size(); i++)
1170 for (
auto &[varnames, corr_factor, policy] : LinkedPlots[i]->GetVariationTypes())
1171 if (SystematicIndexMap.find(varnames[0]) == SystematicIndexMap.end() && SystematicVariationBackup.find(varnames[0]) == SystematicVariationBackup.end())
1173 systCompatible = this->BookSystematicVariation(varnames, corr_factor, policy);
1175 if (!systCompatible)
1177 MSGUser()->MSG_ERROR(
"the systematic variations of plot ", GetResultName(),
" are not compatible with those of the linked plots");
1182 std::vector<TH1 *> LinkedHists;
1183 for (
size_t i = 0; i < LinkedPlots.size(); i++)
1185 if (LinkedPlots[i] ==
nullptr)
1186 LinkedHists.emplace_back(
nullptr);
1188 LinkedHists.emplace_back(LinkedPlots[i]->GetNominalHistVirtual());
1191 histtool->ProcessHistLink(LinkType, LinkedHists, GetNominalHist());
1192 else if (LinkContentFunction && LinkErrorFunction)
1193 histtool->ProcessHistLink(LinkContentFunction, LinkErrorFunction, LinkedHists, GetNominalHist());
1194 else if (LinkHistFunction)
1195 histtool->ProcessHistLink(LinkHistFunction, LinkedHists, GetNominalHist());
1198 MSGUser()->MSG_ERROR(
"Link type is not set for plot ", GetResultName(),
" the hist link will not be processed");
1201 LinkedHists.clear();
1203 for (
size_t i = 1; i <= GetNVariations(); i++)
1205 TString vname = GetVariationName(i);
1206 auto level = MSGUser()->Level();
1208 size_t linkSystCount = 0;
1209 for (
size_t j = 0; j < LinkedPlots.size(); j++)
1211 if (LinkedPlots[j] ==
nullptr)
1212 LinkedHists.emplace_back(
nullptr);
1215 auto varh = LinkedPlots[j]->GetVariationVirtual(vname);
1217 LinkedHists.emplace_back(LinkedPlots[j]->GetNominalHistVirtual());
1220 LinkedHists.emplace_back(varh);
1225 MSGUser()->SetOutputLevel(level);
1227 if (linkSystCount == 0)
1228 MSGUser()->MSG_WARNING(
"No variation ", vname,
" is found in all linked plots for plot ", GetResultName(),
", will use nominal instead.");
1231 histtool->ProcessHistLink(LinkType, LinkedHists, GetVariation(vname));
1232 else if (LinkContentFunction && LinkErrorFunction)
1233 histtool->ProcessHistLink(LinkContentFunction, LinkErrorFunction, LinkedHists, GetVariation(vname));
1234 else if (LinkHistFunction)
1235 histtool->ProcessHistLink(LinkHistFunction, LinkedHists, GetVariation(vname));
1237 LinkedHists.clear();
1242 TString fname =
"Final_" + GetResultName();
1243 Final = (HistType *)Nominal->Clone(fname.TString::Data());
1244 Final->SetDirectory(0);
1245 Final->SetTitle(fname.TString::Data());
1247 int Nbins = Nominal->GetXaxis()->GetNbins() * Nominal->GetYaxis()->GetNbins() * Nominal->GetZaxis()->GetNbins();
1250 for (
int i = 1; i <= Nominal->GetXaxis()->GetNbins(); i++)
1251 for (
int j = 1; j <= Nominal->GetYaxis()->GetNbins(); j++)
1252 for (
int k = 1; k <= Nominal->GetZaxis()->GetNbins(); k++)
1254 double val = Nominal->GetBinContent(i, j, k);
1255 double unc = Nominal->GetBinError(i, j, k);
1257 for (
size_t ivar = 0; ivar < SystematicVariationIndices.size(); ivar++)
1259 std::vector<double> deltas(SystematicVariationIndices[ivar].size());
1260 std::vector<double> systcontents(SystematicVariationIndices[ivar].size());
1262 std::transform(SystematicVariationIndices[ivar].begin(), SystematicVariationIndices[ivar].end(), deltas.begin(), [=](
size_t index)
1263 { return std::fabs(SystematicVariations[index]->GetBinContent(i, j, k) - val); });
1264 std::transform(SystematicVariationIndices[ivar].begin(), SystematicVariationIndices[ivar].end(), systcontents.begin(), [=](
size_t index)
1265 { return SystematicVariations[index]->GetBinContent(i, j, k); });
1267 if (SystematicVariationPolicies[ivar] == SystPolicy::Average)
1268 unc =
Uncertainty::AplusB(unc, std::accumulate(deltas.begin(), deltas.end(), (
double)0) / (
double)(deltas.size()));
1269 if (SystematicVariationPolicies[ivar] == SystPolicy::Maximum)
1271 if (SystematicVariationPolicies[ivar] == SystPolicy::Variance)
1273 if (SystematicVariationPolicies[ivar] == SystPolicy::CTEQ)
1277 Final->SetBinContent(i, j, k, val);
1278 Final->SetBinError(i, j, k, unc);
1283 if (SystematicVariations.size() > 0 && Nbins <= 1e3)
1285 fname =
"Correlation_" + GetResultName();
1286 Correlation =
new TH2D(fname.TString::Data(), fname.TString::Data(),
1289 Correlation->SetDirectory(0);
1290 Correlation->Sumw2();
1292 fname =
"Covariance_" + GetResultName();
1293 Covariance =
new TH2D(fname.TString::Data(), fname.TString::Data(),
1296 Covariance->SetDirectory(0);
1297 Covariance->Sumw2();
1299 histtool->ConvertCovToCorr(Covariance, Correlation);
1301 std::vector<std::vector<double>> cov(Nbins, std::vector<double>(Nbins, 0));
1303 auto convert2vector = [=](TH1 *h)
1305 std::vector<double> content;
1306 content.reserve(Nbins);
1307 for (
int i = 1; i <= h->GetXaxis()->GetNbins(); i++)
1308 for (
int j = 1; j <= h->GetYaxis()->GetNbins(); j++)
1309 for (
int k = 1; k <= h->GetZaxis()->GetNbins(); k++)
1310 content.emplace_back(h->GetBinContent(i, j, k));
1314 auto converterror2vector = [=](TH1 *h)
1316 std::vector<double> error;
1317 error.reserve(Nbins);
1318 for (
int i = 1; i <= h->GetXaxis()->GetNbins(); i++)
1319 for (
int j = 1; j <= h->GetYaxis()->GetNbins(); j++)
1320 for (
int k = 1; k <= h->GetZaxis()->GetNbins(); k++)
1321 error.emplace_back(h->GetBinError(i, j, k));
1325 std::vector<double> nominal_content = convert2vector(Nominal);
1326 std::vector<double> nominal_error = converterror2vector(Nominal);
1329 for (
auto &indices : this->SystematicVariationIndices)
1331 double corr = CorrelationFactors[indices[0]];
1332 SystPolicy policy = SystematicVariationPolicies[systcount];
1333 std::vector<std::vector<double>> syst_contents;
1334 for (
auto &index : indices)
1335 syst_contents.emplace_back(convert2vector(SystematicVariations[index]));
1337 std::vector<double> vdeltai(indices.size());
1338 std::vector<double> vdeltaj(indices.size());
1339 std::vector<double> vsystcontenti(indices.size());
1340 std::vector<double> vsystcontentj(indices.size());
1342 for (
int i = 0; i < Nbins; i++)
1344 for (
int j = 0; j < Nbins; j++)
1346 double deltai, deltaj;
1347 int signi = syst_contents[0][i] - nominal_content[i] > 0 ? 1 : -1;
1348 int signj = syst_contents[0][j] - nominal_content[j] > 0 ? 1 : -1;
1349 for (
int k = 0; k < indices.size(); k++)
1351 vdeltai[k] = fabs(syst_contents[k][i] - nominal_content[i]);
1352 vdeltaj[k] = fabs(syst_contents[k][j] - nominal_content[j]);
1353 vsystcontenti[k] = syst_contents[k][i];
1354 vsystcontentj[k] = syst_contents[k][j];
1357 if (policy == SystPolicy::Maximum)
1359 deltai = *std::max_element(vdeltai.begin(), vdeltai.end());
1360 deltaj = *std::max_element(vdeltaj.begin(), vdeltaj.end());
1362 else if (policy == SystPolicy::Average)
1364 deltai = std::accumulate(vdeltai.begin(), vdeltai.end(), (
double)0) / indices.size();
1365 deltaj = std::accumulate(vdeltaj.begin(), vdeltaj.end(), (
double)0) / indices.size();
1367 else if (policy == SystPolicy::Variance)
1369 deltai = std::sqrt(Variance(vsystcontenti));
1370 deltaj = std::sqrt(Variance(vsystcontentj));
1372 else if (policy == SystPolicy::CTEQ)
1374 deltai = (vsystcontenti[0] - vsystcontenti[1]) / 2;
1375 deltaj = (vsystcontentj[0] - vsystcontentj[1]) / 2;
1381 cov[i][j] += signi * signj * deltai * deltaj * corr;
1383 cov[i][j] += signi * signj * deltai * deltaj;
1391 for (
int i = 0; i < Nbins; i++)
1392 cov[i][i] += nominal_error[i] * nominal_error[i];
1395 histtool->ConvertVectorToTH2D(Covariance, cov);
1396 histtool->ConvertCovToCorr(Covariance, Correlation);
1398 else if (SystematicVariations.size() > 0 && Nbins > 1e3)
1400 MSGUser()->MSG_WARNING(
"NGHist ", GetResultName(),
" has too many bins, can not effectively generate a covariance matrix");
1414 auto titleguard = MSGUser()->StartTitleWithGuard(
"NGHist::Recover");
1417 MSGUser()->MSG_ERROR(
"input file does not exist for plot ", GetResultName());
1421 HistType *nominal_backup =
nullptr;
1424 nominal_backup = Nominal;
1428 Nominal = (HistType *)file->Get(GetResultName());
1432 Nominal = nominal_backup;
1433 MSGUser()->MSG_ERROR(
"Hist ", GetResultName(),
" does not exist in file ", file->GetName(),
" will keep the original one.");
1438 Nominal->SetDirectory(0);
1439 delete nominal_backup;
1444 TTree *infotree = (TTree *)file->Get(GetResultName() +
"_SystInfoTree");
1445 if (infotree !=
nullptr)
1447 std::vector<std::string> *systnames =
nullptr;
1451 bool doindexcheck =
false;
1453 infotree->SetBranchAddress(
"SystNames", &systnames);
1454 infotree->SetBranchAddress(
"Policy", &policy);
1455 infotree->SetBranchAddress(
"CorrFactor", &corrfactor);
1457 if (infotree->SetBranchAddress(
"Index", &index) != TTree::ESetBranchAddressStatus::kMissingBranch)
1458 doindexcheck =
true;
1460 for (
int i = 0; i < infotree->GetEntries(); i++)
1462 infotree->GetEntry(i);
1464 if (doindexcheck && index != i)
1466 std::vector<TString> tstring_systnames;
1467 for (
int j = 0; j < systnames->size(); j++)
1468 tstring_systnames.emplace_back(systnames->at(j));
1470 this->BookSystematicVariation(tstring_systnames, corrfactor,
static_cast<SystPolicy>(policy));
1474 for (
size_t i = 0; i < SystematicVariationNames.size(); i++)
1476 TString SystHistName = GetResultName() +
"_Syst_" + SystematicVariationNames[i];
1477 if (SystematicVariations[i])
1479 delete SystematicVariations[i];
1480 SystematicVariations[i] =
nullptr;
1482 SystematicVariations[i] = (HistType *)file->Get(SystHistName.TString::Data());
1483 if (!SystematicVariations[i])
1484 MSGUser()->MSG_ERROR(
"Hist ", SystHistName,
" does not exist");
1486 SystematicVariations[i]->SetDirectory(0);
1498 Covariance =
nullptr;
1503 Correlation =
nullptr;
1505 Final = (HistType *)file->Get(
"Final_" + GetResultName());
1506 Covariance = (TH2D *)file->Get(
"Covariance_" + GetResultName());
1507 Correlation = (TH2D *)file->Get(
"Correlation_" + GetResultName());
1510 Final->SetDirectory(0);
1512 Covariance->SetDirectory(0);
1514 Correlation->SetDirectory(0);
1528 auto titleguard = MSGUser()->StartTitleWithGuard(
"NGHist::Recover");
1532 MSGUser()->MSG_ERROR(
"input file does not exist for plot ", GetResultName());
1536 HistType *nominal_backup =
nullptr;
1539 nominal_backup = Nominal;
1543 Nominal = (HistType *)infile->Get(GetResultName().Data());
1547 Nominal = nominal_backup;
1552 Nominal->SetDirectory(0);
1553 delete nominal_backup;
1558 TTree *infotree = infile->GetTree((GetResultName() +
"_SystInfoTree").Data());
1559 if (infotree !=
nullptr)
1561 std::vector<std::string> *systnames =
nullptr;
1565 bool doindexcheck =
false;
1567 infotree->SetBranchAddress(
"SystNames", &systnames);
1568 infotree->SetBranchAddress(
"Policy", &policy);
1569 infotree->SetBranchAddress(
"CorrFactor", &corrfactor);
1571 if (infotree->SetBranchAddress(
"Index", &index) != TTree::ESetBranchAddressStatus::kMissingBranch)
1572 doindexcheck =
true;
1574 for (
int i = 0; i < infotree->GetEntries(); i++)
1576 infotree->GetEntry(i);
1578 if (doindexcheck && index != i)
1581 std::vector<TString> tstring_systnames;
1582 for (
int j = 0; j < systnames->size(); j++)
1583 tstring_systnames.emplace_back(systnames->at(j));
1585 this->BookSystematicVariation(tstring_systnames, corrfactor,
static_cast<SystPolicy>(policy));
1592 for (
size_t i = 0; i < SystematicVariationNames.size(); i++)
1594 TString SystHistName = GetResultName() +
"_Syst_" + SystematicVariationNames[i];
1595 if (SystematicVariations[i])
1597 delete SystematicVariations[i];
1598 SystematicVariations[i] =
nullptr;
1601 SystematicVariations[i] = (HistType *)infile->Get(SystHistName.Data());
1613 Covariance =
nullptr;
1618 Correlation =
nullptr;
1621 TString finalname =
"Final_" + GetResultName();
1622 Final = (HistType *)infile->Get(finalname.Data());
1626 if (Nominal->GetNbinsX() * Nominal->GetNbinsY() * Nominal->GetNbinsZ() <= 1e3 && SystematicVariations.size() > 0)
1628 TString covname =
"Covariance_" + GetResultName();
1629 TString corrname =
"Correlation_" + GetResultName();
1630 Covariance = (TH2D *)infile->Get(covname.Data());
1631 Correlation = (TH2D *)infile->Get(corrname.Data());