506 std::vector<std::string> obsList;
509 if (
fCut !=
nullptr) {
510 const auto paramCut =
fCut->GetParamCut();
511 for (
const auto& [param, condition] : paramCut) {
512 obsList.push_back(param);
517 for (
const auto& plots :
fPlots) {
518 for (
const auto& hist : plots.histos) {
519 for (
const auto& var : hist.variable) {
520 obsList.push_back(var);
522 if (hist.histoCut ==
nullptr)
continue;
523 const auto paramCut = hist.histoCut->GetParamCut();
524 for (
const auto& [param, condition] : paramCut) {
525 obsList.push_back(param);
530 std::map<std::string, TRestDataSet::RelevantQuantity> quantity;
534 for (
auto& [key, posLabel] : panel.expPos) {
536 auto&& [exp, label,
units] = key;
537 std::string text = exp;
538 while (text.find_last_of(
'[') != std::string::npos) {
539 int squareBracketCorrector = 0;
540 size_t posOpen = text.find_last_of(
'[');
541 size_t posClose = text.find_first_of(
']', posOpen);
543 if (text[posOpen - 1] ==
'[') {
544 squareBracketCorrector = 1;
547 std::string varOrMeta = text.substr(posOpen - squareBracketCorrector,
548 posClose + 1 - posOpen + 2 * squareBracketCorrector);
549 if (squareBracketCorrector == 0) {
555 quantity[label] = quant;
557 text =
Replace(text, varOrMeta,
"1");
561 while (text.find(
"_") != std::string::npos) {
562 size_t pos_ = text.find(
"_");
563 size_t beginning = text.find_last_of(
" -+*/)(^%", pos_) + 1;
564 size_t end = text.find_first_of(
" -+*/)(^%", pos_);
565 std::string obs = text.substr(beginning, end - beginning);
566 text =
Replace(text, obs,
"1");
567 obsList.push_back(obs);
571 RESTWarning <<
"The expression " << exp
572 <<
" has not been correctly parsed into variables, metadata and observables"
577 for (
auto& [key, posLabel] : panel.obsPos) {
578 auto&& [obs, label,
units] = key;
579 obsList.push_back(obs);
582 for (
auto& [key, posLabel] : panel.metadataPos) {
583 auto&& [metadata, label,
units] = key;
587 quantity[label] = quant;
592 std::sort(obsList.begin(), obsList.end());
593 obsList.erase(std::unique(obsList.begin(), obsList.end()), obsList.end());
595 dataSet.SetObservablesList(obsList);
596 dataSet.SetQuantity(quantity);
606 dataSet.EnableMultiThreading(
true);
612 if (dataSet.
GetTree() ==
nullptr) {
613 RESTWarning <<
"Cannot import dataSet, trying to generate it with pattern " <<
fDataSetName
615 RESTWarning <<
"Note that the generation of a dataSet inside TRestDataSetPlot is deplecated. Check "
616 "TRestDataSet documentation to generate a dataSet"
619 if (dataSet.
GetTree() ==
nullptr) {
620 RESTError <<
"Cannot generate dataSet " <<
RESTendl;
629 combinedCanvas.Divide((Int_t)fCanvasDivisions.X(), (Int_t)fCanvasDivisions.Y(),
630 fCanvasDivisionMargins.X(), fCanvasDivisionMargins.Y());
635 const double startTime = dataSet.GetStartTime();
636 const double endTime = dataSet.GetEndTime();
639 std::map<std::string, std::string> paramMap;
644 const auto quantity = dataSet.GetQuantity();
649 combinedCanvas.cd(canvasIndex);
651 auto dataFrame = dataSet.
MakeCut(panel.panelCut);
652 const int entries = *dataFrame.Count();
653 const double meanRate = entries / duration;
654 const double runLength = duration / 3600.;
655 paramMap[
"[[runLength]]"] = StringWithPrecision(runLength, panel.precision);
656 paramMap[
"[[entries]]"] = StringWithPrecision(entries, panel.precision);
657 paramMap[
"[[meanRate]]"] = StringWithPrecision(meanRate, panel.precision);
659 paramMap[
"[[cutNames]]"] =
"";
660 paramMap[
"[[cuts]]"] =
"";
662 for (
const auto& cut :
fCut->GetCuts()) {
663 if (paramMap[
"[[cutNames]]"].empty())
664 paramMap[
"[[cutNames]]"] += cut.GetName();
666 paramMap[
"[[cutNames]]"] +=
"," + (std::string)cut.GetName();
667 if (paramMap[
"[[cuts]]"].empty())
668 paramMap[
"[[cuts]]"] += cut.GetTitle();
670 paramMap[
"[[cuts]]"] +=
" && " + (std::string)cut.GetTitle();
674 paramMap[
"[[panelCutNames]]"] =
"";
675 paramMap[
"[[panelCuts]]"] =
"";
676 if (panel.panelCut) {
677 for (
const auto& cut : panel.panelCut->GetCuts()) {
678 if (paramMap[
"[[panelCutNames]]"].empty())
679 paramMap[
"[[panelCutNames]]"] += cut.GetName();
681 paramMap[
"[[panelCutNames]]"] +=
"," + (std::string)cut.GetName();
682 if (paramMap[
"[[panelCuts]]"].empty())
683 paramMap[
"[[panelCuts]]"] += cut.GetTitle();
685 paramMap[
"[[panelCuts]]"] +=
" && " + (std::string)cut.GetTitle();
689 RESTInfo <<
"Global cuts: " << paramMap[
"[[cuts]]"] <<
RESTendl;
690 if (!paramMap[
"[[panelCuts]]"].empty())
691 RESTInfo <<
"Additional panel cuts: " << paramMap[
"[[panelCuts]]"] <<
RESTendl;
694 for (
const auto& [key, posLabel] : panel.variablePos) {
695 auto&& [variable, label,
units] = key;
697 std::string var = variable;
699 for (
const auto& [param, val] : paramMap) {
702 var =
Replace(var, param, val, pos);
707 if (!found) RESTWarning <<
"Variable " << variable <<
" not found" <<
RESTendl;
709 std::string lab = label +
": " + StringWithPrecision(var, panel.precision) +
" " +
units;
710 panel.text.emplace_back(
new TLatex(posLabel.X(), posLabel.Y(), lab.c_str()));
714 for (
const auto& [key, posLabel] : panel.metadataPos) {
715 auto&& [metadata, label,
units] = key;
716 std::string value =
"";
718 for (
const auto& [name, quant] : quantity) {
719 if (quant.metadata == metadata) value = quant.value;
723 RESTWarning <<
"Metadata quantity " << metadata <<
" not found in dataSet" <<
RESTendl;
727 std::string lab = label +
": " + StringWithPrecision(value, panel.precision) +
" " +
units;
728 panel.text.emplace_back(
new TLatex(posLabel.X(), posLabel.Y(), lab.c_str()));
732 for (
const auto& [key, posLabel] : panel.obsPos) {
733 auto&& [obs, label,
units] = key;
734 auto value = *dataFrame.Mean(obs);
736 std::string lab = label +
": " + StringWithPrecision(value, panel.precision) +
" " +
units;
737 panel.text.emplace_back(
new TLatex(posLabel.X(), posLabel.Y(), lab.c_str()));
741 for (
const auto& [key, posLabel] : panel.expPos) {
742 auto&& [text, label,
units] = key;
743 std::string var = text;
746 for (
const auto& [param, val] : paramMap) {
747 var =
Replace(var, param, val);
750 for (
const auto& [name, quant] : quantity) {
751 var =
Replace(var, name, quant.value);
754 for (
const auto& obs : dataFrame.GetColumnNames()) {
755 if (var.find(obs) == std::string::npos)
continue;
758 double value = *dataFrame.Mean(obs);
765 std::string lab = label +
": " + var +
" " +
units;
766 panel.text.emplace_back(
new TLatex(posLabel.X(), posLabel.Y(), lab.c_str()));
770 for (
const auto& text : panel.text) {
771 text->SetTextColor(1);
772 text->SetTextSize(panel.font_size);
778 for (
auto& plots :
fPlots) {
780 combinedCanvas.cd(canvasIndex);
781 plots.hs =
new THStack(plots.name.c_str(), plots.title.c_str());
782 if (plots.legendOn) plots.legend =
new TLegend(
fLegendX1, fLegendY1, fLegendX2, fLegendY2);
784 for (
auto& hist : plots.histos) {
785 auto dataFrame = dataSet.
MakeCut(hist.histoCut);
786 if (hist.variable.front() ==
"timeStamp") {
787 hist.range.front().SetX(startTime);
788 hist.range.front().SetY(endTime);
791 if (hist.variable.size() == 1) {
792 auto histo = dataFrame.Histo1D({hist.name.c_str(), hist.name.c_str(), hist.nBins.front(),
793 hist.range.front().X(), hist.range.front().Y()},
794 hist.variable.front());
795 hist.histo =
static_cast<TH1*
>(histo->DrawClone());
797 }
else if (hist.variable.size() == 2) {
798 auto histo = dataFrame.Histo2D(
799 {hist.name.c_str(), hist.name.c_str(), hist.nBins.front(), hist.range.front().X(),
800 hist.range.front().Y(), hist.nBins.back(), hist.range.back().X(), hist.range.back().Y()},
801 hist.variable.front(), hist.variable.back());
802 hist.histo =
static_cast<TH1*
>(histo->DrawClone());
804 RESTError <<
"Only 1D or 2D histograms are supported " <<
RESTendl;
807 hist.histo->SetLineColor(hist.lineColor);
808 hist.histo->SetLineWidth(hist.lineWidth);
809 hist.histo->SetLineStyle(hist.lineStyle);
810 hist.histo->SetFillColor(hist.fillColor);
811 hist.histo->SetFillStyle(hist.fillStyle);
813 if (hist.statistics) {
814 hist.histo->SetStats(
true);
816 combinedCanvas.Update();
818 hist.histo->SetStats(
false);
821 if (plots.normalize > 0) {
822 const double integral = hist.histo->Integral();
823 if (integral > 0) hist.histo->Scale(plots.normalize / integral);
826 if (plots.scale !=
"") {
827 std::string inputScale = plots.scale;
828 double binSize = hist.histo->GetXaxis()->GetBinWidth(1);
829 double entries = hist.histo->GetEntries();
831 double integral = hist.histo->Integral(
"width");
838 std::string scale =
"1./(" + inputScale +
")";
843 plots.hs->Add(hist.histo, hist.drawOption.c_str());
845 if (plots.legend !=
nullptr) plots.legend->AddEntry(hist.histo, hist.histo->GetName(),
"lf");
850 for (
auto& plots :
fPlots) {
851 if (plots.hs ==
nullptr)
continue;
853 TPad* targetPad = (TPad*)combinedCanvas.cd(canvasIndex);
854 targetPad->SetLogx(plots.logX);
855 targetPad->SetLogy(plots.logY);
856 targetPad->SetLogz(plots.logZ);
857 targetPad->SetGridx(plots.gridX);
858 targetPad->SetGridy(plots.gridY);
859 targetPad->SetLeftMargin(plots.marginLeft);
860 targetPad->SetRightMargin(plots.marginRight);
861 targetPad->SetBottomMargin(plots.marginBottom);
862 targetPad->SetTopMargin(plots.marginTop);
865 plots.hs->Draw(plots.stackDrawOption.c_str());
866 plots.hs->GetXaxis()->SetTitle(plots.labelX.c_str());
867 plots.hs->GetYaxis()->SetTitle(plots.labelY.c_str());
868 plots.hs->GetXaxis()->SetLabelSize(1.1 * plots.hs->GetXaxis()->GetLabelSize());
869 plots.hs->GetYaxis()->SetLabelSize(1.1 * plots.hs->GetYaxis()->GetLabelSize());
870 plots.hs->GetXaxis()->SetTitleSize(1.1 * plots.hs->GetXaxis()->GetTitleSize());
871 plots.hs->GetYaxis()->SetTitleSize(1.1 * plots.hs->GetYaxis()->GetTitleSize());
873 if (plots.timeDisplay) plots.hs->GetXaxis()->SetTimeDisplay(1);
874 if (plots.legend !=
nullptr) plots.legend->Draw();
877 combinedCanvas.Update();
883 combinedCanvas.Resize();
888 for (
auto& plots :
fPlots) {
889 if (plots.save.empty())
continue;
890 std::unique_ptr<TCanvas> canvas(
new TCanvas());
891 canvas->SetLogx(plots.logX);
892 canvas->SetLogy(plots.logY);
893 canvas->SetLogz(plots.logZ);
894 canvas->SetGridx(plots.gridX);
895 canvas->SetGridy(plots.gridY);
896 canvas->SetLeftMargin(plots.marginLeft);
897 canvas->SetRightMargin(plots.marginRight);
898 canvas->SetBottomMargin(plots.marginBottom);
899 canvas->SetTopMargin(plots.marginTop);
900 plots.hs->Draw(plots.stackDrawOption.c_str());
901 canvas->Print(plots.save.c_str());
906 for (
const auto& [name, quant] : quantity) {
913 std::unique_ptr<TFile> f(TFile::Open(
fOutputFileName.c_str(),
"UPDATE"));
914 for (
auto& plots :
fPlots) {
915 for (
auto& hist : plots.histos) {