273#include "TRestDataSetPlot.h"
276#include "TDirectory.h"
329 TiXmlElement* cutele =
GetElement(
"addCut", ele);
330 while (cutele !=
nullptr) {
332 if (!cutName.empty()) {
333 if (cut ==
nullptr) {
351 RESTWarning <<
"Plot metadata already initialized" <<
RESTendl;
355 while (panelele !=
nullptr) {
356 std::string active =
GetParameter(
"value", panelele,
"ON");
357 if (
ToUpper(active) !=
"ON")
continue;
363 panel.panelCut =
ReadCut(panel.panelCut, panelele);
365 TiXmlElement* labelele =
GetElement(
"variable", panelele);
366 while (labelele !=
nullptr) {
367 std::array<std::string, 3> label;
374 panel.variablePos.push_back(std::make_pair(label, TVector2(posX, posY)));
378 TiXmlElement* metadata =
GetElement(
"metadata", panelele);
379 while (metadata !=
nullptr) {
380 std::array<std::string, 3> label;
387 panel.metadataPos.push_back(std::make_pair(label, TVector2(posX, posY)));
391 TiXmlElement* observable =
GetElement(
"observable", panelele);
392 while (observable !=
nullptr) {
393 std::array<std::string, 3> label;
400 panel.obsPos.push_back(std::make_pair(label, TVector2(posX, posY)));
404 TiXmlElement* expression =
GetElement(
"expression", panelele);
405 while (expression !=
nullptr) {
406 std::array<std::string, 3> label;
413 panel.expPos.push_back(std::make_pair(label, TVector2(posX, posY)));
429 RESTWarning <<
"Plot metadata already initialized" <<
RESTendl;
434 while (plotele !=
nullptr) {
435 std::string active =
GetParameter(
"value", plotele,
"ON");
436 if (
ToUpper(active) !=
"ON")
continue;
441 plot.logX = StringToBool(
GetParameter(
"logX", plotele,
"false"));
442 plot.logY = StringToBool(
GetParameter(
"logY", plotele,
"false"));
443 plot.logZ = StringToBool(
GetParameter(
"logZ", plotele,
"false"));
444 plot.gridY = StringToBool(
GetParameter(
"gridY", plotele,
"false"));
445 plot.gridX = StringToBool(
GetParameter(
"gridX", plotele,
"false"));
454 plot.legendOn = StringToBool(
GetParameter(
"legend", plotele,
"OFF"));
455 plot.stackDrawOption =
GetParameter(
"stackOption", plotele,
"nostack");
459 plot.timeDisplay = StringToBool(
GetParameter(
"timeDisplay", plotele,
"OFF"));
462 TiXmlElement* histele =
GetElement(
"histo", plotele);
463 if (histele ==
nullptr) {
466 while (histele !=
nullptr) {
469 hist.drawOption =
GetParameter(
"option", histele,
"colz");
470 TiXmlElement* varele =
GetElement(
"variable", histele);
471 while (varele !=
nullptr) {
484 hist.statistics = StringToBool(
GetParameter(
"stats", histele,
"OFF"));
486 hist.histoCut =
ReadCut(hist.histoCut, histele);
487 plot.histos.push_back(hist);
489 if (histele == plotele) {
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) {
931 for (
auto& plots :
fPlots) {
932 for (
auto& hist : plots.histos) {
940 for (
auto& text : panel.text) {
953 if (in.find_first_not_of(
"0123456789") == std::string::npos) {
956 auto it = mapStr.find(in);
957 if (it != mapStr.end()) {
960 RESTWarning <<
"cannot find ID with name \"" << in <<
"\"" <<
RESTendl;
975 RESTMetadata <<
"Canvas divisions: (" << fCanvasDivisions.X() <<
" ," << fCanvasDivisions.Y() <<
")"
977 RESTMetadata <<
"-------------------" <<
RESTendl;
978 for (
const auto& plot :
fPlots) {
979 RESTMetadata <<
"-------------------" <<
RESTendl;
980 RESTMetadata <<
"Plot name/title: " << plot.name <<
" " << plot.title <<
RESTendl;
981 RESTMetadata <<
"Save string: " << plot.save <<
RESTendl;
982 RESTMetadata <<
"Set log X,Y,Z: " << plot.logX <<
", " << plot.logY <<
", " << plot.logZ <<
RESTendl;
983 RESTMetadata <<
"Stack draw Option: " << plot.stackDrawOption <<
RESTendl;
984 if (plot.legend) RESTMetadata <<
"Legend is ON" <<
RESTendl;
985 if (plot.timeDisplay) RESTMetadata <<
"Time display is ON" <<
RESTendl;
986 RESTMetadata <<
"Labels X,Y: " << plot.labelX <<
", " << plot.labelY <<
RESTendl;
987 for (
const auto& hist : plot.histos) {
988 RESTMetadata <<
"****************" <<
RESTendl;
989 RESTMetadata <<
"Histo name: " << hist.name <<
RESTendl;
990 RESTMetadata <<
"Draw Option: " << hist.drawOption <<
RESTendl;
991 RESTMetadata <<
"Histogram size: " << hist.variable.size() <<
" with parameters:" <<
RESTendl;
992 for (
size_t i = 0; i < hist.variable.size(); i++) {
993 RESTMetadata <<
"\t" << i <<
" " << hist.variable[i] <<
", " << hist.nBins[i] <<
", "
994 << hist.range[i].X() <<
", " << hist.range[i].Y() <<
RESTendl;
996 RESTMetadata <<
"****************" <<
RESTendl;
999 RESTMetadata <<
"-------------------" <<
RESTendl;
1001 RESTMetadata <<
"-------------------" <<
RESTendl;
1002 RESTMetadata <<
"Panel font size/precision " << panel.font_size <<
", " << panel.precision
1004 RESTMetadata <<
"****************" <<
RESTendl;
1005 for (
auto& [key, posLabel] : panel.variablePos) {
1006 auto&& [obs, label,
units] = key;
1007 RESTMetadata <<
"Label variable " << obs <<
", label " << label <<
", units " <<
units <<
" Pos ("
1008 << posLabel.X() <<
", " << posLabel.Y() <<
")" <<
RESTendl;
1010 RESTMetadata <<
"****************" <<
RESTendl;
1011 for (
auto& [key, posLabel] : panel.metadataPos) {
1012 auto&& [obs, label,
units] = key;
1013 RESTMetadata <<
"Label metadata " << obs <<
", label " << label <<
", units " <<
units <<
" Pos ("
1014 << posLabel.X() <<
", " << posLabel.Y() <<
")" <<
RESTendl;
1016 RESTMetadata <<
"****************" <<
RESTendl;
1017 for (
auto& [key, posLabel] : panel.obsPos) {
1018 auto&& [obs, label,
units] = key;
1019 RESTMetadata <<
"Label Observable " << obs <<
", label " << label <<
", units " <<
units
1020 <<
" Pos (" << posLabel.X() <<
", " << posLabel.Y() <<
")" <<
RESTendl;
1022 RESTMetadata <<
"****************" <<
RESTendl;
1023 for (
auto& [key, posLabel] : panel.expPos) {
1024 auto&& [obs, label,
units] = key;
1025 RESTMetadata <<
"Label Expression " << obs <<
", label " << label <<
", units " <<
units
1026 <<
" Pos (" << posLabel.X() <<
", " << posLabel.Y() <<
")" <<
RESTendl;
1028 RESTMetadata <<
"****************" <<
RESTendl;
1030 RESTMetadata <<
"-------------------" <<
RESTendl;
A class to help on cuts definitions. To be used with TRestAnalysisTree.
Perform the plot over datasets.
Int_t GetIDFromMapString(const std::map< std::string, int > &mapStr, const std::string &in)
This functions gets the ID from a map string that is passed by reference. It is used to translate col...
std::vector< PanelInfo > fPanels
Vector with panels/label options.
TRestCut * ReadCut(TRestCut *cut, TiXmlElement *ele=nullptr)
this function is used to add the different cuts provided in different metadata sections,...
void Initialize() override
Function to initialize input/output event members and define the section name.
void PlotCombinedCanvas()
This functions performs the plot of the combined canvas with the different panels and plots.
const std::map< std::string, int > LineStyleMap
LineStyleMap as enum "ELineStyle" defined in TAttLine.h.
std::string fDataSetName
Name of the dataset to be imported.
void ReadPlotInfo()
This function reads the config file plot info and stores it in a vector of PlotInfo.
void ReadPanelInfo()
This function reads the config file panel info and stores it in a vector of PanelInfo.
void GenerateDataSetFromFilePattern(TRestDataSet &dataSet)
This functions generates a dataSet based on the information of the rml file. A TRestDataSet is pased ...
Int_t fPaletteStyle
Palette style.
const std::map< std::string, int > FillStyleMap
FillStyleMap as enum "EFillStyle" defined in TAttFill.h.
TRestDataSetPlot()
Default constructor.
TRestCut * fCut
Global cut for the entire dataSet.
Bool_t fPreviewPlot
Preview plot.
const std::map< std::string, int > ColorIdMap
Maps for internal use only.
void PrintMetadata() override
Prints on screen the information about the metadata members of TRestDataSetPlot.
TVector2 fCanvasSize
Canvas options, size, divisions and margins.
std::string fOutputFileName
OutputFileName.
~TRestDataSetPlot()
Default destructor.
Double_t fLegendX1
Legend position and size.
std::vector< PlotInfo > fPlots
Vector with plots/pads options.
void InitFromConfigFile() override
Initialization of specific TRestDataSetPlot members through an RML file.
void CleanUp()
Clean up histos and text but note that the metadata is unchanged.
It allows to group a number of runs that satisfy given metadata conditions.
void Import(const std::string &fileName)
This function imports metadata from a root file it import metadata info from the previous dataSet whi...
Double_t GetTotalTimeInSeconds() const
It returns the accumulated run time in seconds.
ROOT::RDF::RNode MakeCut(const TRestCut *cut)
This function applies a TRestCut to the dataframe and returns a dataframe with the applied cuts....
void GenerateDataSet()
This function generates the data frame with the filelist and column names (or observables) that have ...
TTree * GetTree() const
Gives access to the tree.
@ REST_Info
+show most of the information for each steps
Int_t GetChar(std::string hint="Press a KEY to continue ...")
Helps to pause the program, printing a message before pausing.
Double_t StringToDouble(std::string in)
Gets a double from a string.
std::string ToUpper(std::string in)
Convert string to its upper case. Alternative of TString::ToUpper.
Int_t StringToInteger(std::string in)
Gets an integer from a string.
Int_t isAExpression(const std::string &in)
Returns 1 only if valid mathematical expression keywords (or numbers) are found in the string in....
std::string DoubleToString(Double_t d, std::string format="%8.6e")
Gets a string from a double.
TVector2 StringTo2DVector(std::string in)
Gets a 2D-vector from a string.
std::string EvaluateExpression(std::string exp)
Evaluates a complex numerical expression and returns the resulting value using TFormula.
Int_t isANumber(std::string in)
Returns 1 only if a valid number is found in the string in. If not it returns 0.
std::string RemoveWhiteSpaces(std::string in)
Returns the input string removing all white spaces.
std::string ToDateTimeString(time_t time)
Format time_t into string.
std::string Replace(std::string in, std::string thisString, std::string byThisString, size_t fromPosition=0, Int_t N=0)
Replace any occurences of thisSring by byThisString inside string in.
Nested classes for internal use only.
Auxiliary class for panels/labels.
Auxiliary struct for plots/pads.
std::string metadata
The associated metadata member used to register the relevant quantity.
std::string strategy
It determines how to produce the relevant quantity (accumulate/unique/last/max/min)