REST-for-Physics  v2.3
Rare Event Searches ToolKit for Physics
Loading...
Searching...
No Matches
TRestDataSetPlot.cxx
1/*************************************************************************
2 * This file is part of the REST software framework. *
3 * *
4 * Copyright (C) 2016 GIFNA/TREX (University of Zaragoza) *
5 * For more information see https://gifna.unizar.es/trex *
6 * *
7 * REST is free software: you can redistribute it and/or modify *
8 * it under the terms of the GNU General Public License as published by *
9 * the Free Software Foundation, either version 3 of the License, or *
10 * (at your option) any later version. *
11 * *
12 * REST is distributed in the hope that it will be useful, *
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
15 * GNU General Public License for more details. *
16 * *
17 * You should have a copy of the GNU General Public License along with *
18 * REST in $REST_PATH/LICENSE. *
19 * If not, see https://www.gnu.org/licenses/. *
20 * For the list of contributors see $REST_PATH/CREDITS. *
21 *************************************************************************/
22
293
294#include "TRestDataSetPlot.h"
295
296#include "TCanvas.h"
297#include "TDirectory.h"
298#include "TStyle.h"
299
300ClassImp(TRestDataSetPlot);
301
306
310TRestDataSetPlot::TRestDataSetPlot(const char* configFilename, std::string name)
311 : TRestMetadata(configFilename) {
312 Initialize();
315}
316
321
326void TRestDataSetPlot::Initialize() { SetSectionName(this->ClassName()); }
327
333
334 if (fDataSetName == "") fDataSetName = GetParameter("inputFileName", "");
335 if (fOutputFileName == "") fOutputFileName = GetParameter("outputFileName", "");
336
337 fCut = ReadCut(fCut);
338
339 ReadPlotInfo();
341}
342
349TRestCut* TRestDataSetPlot::ReadCut(TRestCut* cut, TiXmlElement* ele) {
350 TiXmlElement* cutele = GetElement("addCut", ele);
351 while (cutele != nullptr) {
352 std::string cutName = GetParameter("name", cutele, "");
353 if (!cutName.empty()) {
354 if (cut == nullptr) {
355 cut = (TRestCut*)InstantiateChildMetadata("TRestCut", cutName);
356 } else {
357 cut->AddCut((TRestCut*)InstantiateChildMetadata("TRestCut", cutName));
358 }
359 }
360 cutele = GetNextElement(cutele);
361 }
362
363 return cut;
364}
365
371 if (!fPanels.empty()) {
372 RESTWarning << "Plot metadata already initialized" << RESTendl;
373 }
374
375 TiXmlElement* panelele = GetElement("panel");
376 while (panelele != nullptr) {
377 std::string active = GetParameter("value", panelele, "ON");
378 if (ToUpper(active) != "ON") continue;
379
380 PanelInfo panel;
381 panel.font_size = StringToDouble(GetParameter("font_size", panelele, "0.1"));
382 panel.precision = StringToInteger(GetParameter("precision", panelele, "2"));
383 panel.delimiter = GetParameter("delimiter", panelele, ": ");
384
385 panel.panelCut = ReadCut(panel.panelCut, panelele);
386
387 TiXmlElement* labelele = GetElement("variable", panelele);
388 while (labelele != nullptr) {
389 std::array<std::string, 3> label;
390 label[0] = GetParameter("value", labelele, "");
391 label[1] = GetParameter("label", labelele, "");
392 label[2] = GetParameter("units", labelele, "");
393 double posX = StringToDouble(GetParameter("x", labelele, "0.1"));
394 double posY = StringToDouble(GetParameter("y", labelele, "0.1"));
395
396 panel.variablePos.push_back(std::make_pair(label, TVector2(posX, posY)));
397
398 labelele = GetNextElement(labelele);
399 }
400 TiXmlElement* metadata = GetElement("metadata", panelele);
401 while (metadata != nullptr) {
402 std::array<std::string, 3> label;
403 label[0] = GetParameter("value", metadata, "");
404 label[1] = GetParameter("label", metadata, "");
405 label[2] = GetParameter("units", metadata, "");
406 double posX = StringToDouble(GetParameter("x", metadata, "0.1"));
407 double posY = StringToDouble(GetParameter("y", metadata, "0.1"));
408
409 panel.metadataPos.push_back(std::make_pair(label, TVector2(posX, posY)));
410
411 metadata = GetNextElement(metadata);
412 }
413 TiXmlElement* observable = GetElement("observable", panelele);
414 while (observable != nullptr) {
415 std::array<std::string, 3> label;
416 label[0] = GetParameter("value", observable, "");
417 label[1] = GetParameter("label", observable, "");
418 label[2] = GetParameter("units", observable, "");
419 double posX = StringToDouble(GetParameter("x", observable, "0.1"));
420 double posY = StringToDouble(GetParameter("y", observable, "0.1"));
421
422 panel.obsPos.push_back(std::make_pair(label, TVector2(posX, posY)));
423
424 observable = GetNextElement(observable);
425 }
426 TiXmlElement* expression = GetElement("expression", panelele);
427 while (expression != nullptr) {
428 std::array<std::string, 4> label;
429 label[0] = GetParameter("value", expression, "");
430 label[1] = GetParameter("label", expression, "");
431 label[2] = GetParameter("units", expression, "");
432 label[3] = GetParameter("precision", expression, IntegerToString(panel.precision));
433 double posX = StringToDouble(GetParameter("x", expression, "0.1"));
434 double posY = StringToDouble(GetParameter("y", expression, "0.1"));
435
436 panel.expPos.push_back(std::make_pair(label, TVector2(posX, posY)));
437
438 expression = GetNextElement(expression);
439 }
440
441 fPanels.push_back(panel);
442 panelele = GetNextElement(panelele);
443 }
444}
445
451 if (!fPlots.empty()) {
452 RESTWarning << "Plot metadata already initialized" << RESTendl;
453 return;
454 }
455
456 TiXmlElement* plotele = GetElement("plot");
457 while (plotele != nullptr) {
458 std::string active = GetParameter("value", plotele, "ON");
459 if (ToUpper(active) != "ON") continue;
460 int N = fPlots.size();
461 PlotInfo plot;
462 plot.name = RemoveWhiteSpaces(GetParameter("name", plotele, "plot_" + ToString(N)));
463 plot.title = GetParameter("title", plotele, plot.name);
464 plot.logX = StringToBool(GetParameter("logX", plotele, "false"));
465 plot.logY = StringToBool(GetParameter("logY", plotele, "false"));
466 plot.logZ = StringToBool(GetParameter("logZ", plotele, "false"));
467 plot.gridY = StringToBool(GetParameter("gridY", plotele, "false"));
468 plot.gridX = StringToBool(GetParameter("gridX", plotele, "false"));
469 plot.normalize = StringToDouble(GetParameter("norm", plotele, ""));
470 plot.scale = GetParameter("scale", plotele, "");
471 plot.labelX = GetParameter("xlabel", plotele, "");
472 plot.labelY = GetParameter("ylabel", plotele, "");
473 plot.marginBottom = StringToDouble(GetParameter("marginBottom", plotele, "0.15"));
474 plot.marginTop = StringToDouble(GetParameter("marginTop", plotele, "0.07"));
475 plot.marginLeft = StringToDouble(GetParameter("marginLeft", plotele, "0.25"));
476 plot.marginRight = StringToDouble(GetParameter("marginRight", plotele, "0.1"));
477 plot.legendOn = StringToBool(GetParameter("legend", plotele, "OFF"));
478 plot.stackDrawOption = GetParameter("stackOption", plotele, "nostack");
479 // plot.annotationOn = StringToBool(GetParameter("annotation", plotele, "OFF"));
480 plot.xOffset = StringToDouble(GetParameter("xOffset", plotele, "0"));
481 plot.yOffset = StringToDouble(GetParameter("yOffset", plotele, "0"));
482 plot.timeDisplay = StringToBool(GetParameter("timeDisplay", plotele, "OFF"));
483 plot.save = RemoveWhiteSpaces(GetParameter("save", plotele, ""));
484
485 TiXmlElement* histele = GetElement("histo", plotele);
486 if (histele == nullptr) {
487 histele = plotele;
488 }
489 while (histele != nullptr) {
490 HistoInfo hist;
491 hist.name = RemoveWhiteSpaces(GetParameter("name", histele, plot.name));
492 hist.drawOption = GetParameter("option", histele, "colz");
493 TiXmlElement* varele = GetElement("variable", histele);
494 while (varele != nullptr) {
495 hist.variable.push_back(GetParameter("name", varele));
496 std::string rangeStr = GetParameter("range", varele);
497 hist.range.push_back(StringTo2DVector(rangeStr));
498 hist.nBins.push_back(StringToInteger(GetParameter("nbins", varele)));
499 varele = GetNextElement(varele);
500 }
501
502 hist.lineColor = GetIDFromMapString(ColorIdMap, GetParameter("lineColor", histele, "602"));
503 hist.lineWidth = StringToInteger(GetParameter("lineWidth", histele, "1"));
504 hist.lineStyle = GetIDFromMapString(LineStyleMap, GetParameter("lineStyle", histele, "1"));
505 hist.fillStyle = GetIDFromMapString(FillStyleMap, GetParameter("fillStyle", histele, "1001"));
506 hist.fillColor = GetIDFromMapString(ColorIdMap, GetParameter("fillColor", histele, "0"));
507 hist.statistics = StringToBool(GetParameter("stats", histele, "OFF"));
508 // hist.weight = GetParameter("weight", histele, "");
509 hist.histoCut = ReadCut(hist.histoCut, histele);
510 plot.histos.push_back(hist);
511
512 if (histele == plotele) {
513 break;
514 }
515 histele = GetNextElement(histele);
516 }
517
518 fPlots.push_back(plot);
519 plotele = GetNextElement(plotele);
520 }
521}
522
529 std::vector<std::string> obsList;
530
531 // Add obserbables from global cut
532 if (fCut != nullptr) {
533 const auto paramCut = fCut->GetParamCut();
534 for (const auto& [param, condition] : paramCut) {
535 obsList.push_back(param);
536 }
537 }
538
539 // Add obserbables from plot info, both variables and cuts
540 for (const auto& plots : fPlots) {
541 for (const auto& hist : plots.histos) {
542 for (const auto& var : hist.variable) {
543 obsList.push_back(var);
544 }
545 if (hist.histoCut == nullptr) continue;
546 const auto paramCut = hist.histoCut->GetParamCut();
547 for (const auto& [param, condition] : paramCut) {
548 obsList.push_back(param);
549 }
550 }
551 }
552
553 std::map<std::string, TRestDataSet::RelevantQuantity> quantity;
554
555 for (auto& panel : fPanels) {
556 // Add metadata and observables from expression key from panel info
557 for (auto& [key, posLabel] : panel.expPos) {
558 // look for metadata which are surrounded by [] but not [[]] (variables)
559 auto&& [exp, label, units, precision] = key;
560 std::string text = exp;
561 while (text.find_last_of('[') != std::string::npos) {
562 int squareBracketCorrector = 0;
563 size_t posOpen = text.find_last_of('[');
564 size_t posClose = text.find_first_of(']', posOpen);
565 if (posOpen != 0) {
566 if (text[posOpen - 1] == '[') {
567 squareBracketCorrector = 1;
568 }
569 }
570 std::string varOrMeta = text.substr(posOpen - squareBracketCorrector,
571 posClose + 1 - posOpen + 2 * squareBracketCorrector);
572 if (squareBracketCorrector == 0) {
573 // Here varOrMeta is a metadata
574 // Add metadata to relevant quantity from the panel info
576 quant.metadata = varOrMeta;
577 quant.strategy = "unique";
578 quantity[label] = quant;
579 }
580 text = Replace(text, varOrMeta, "1");
581 }
582
583 // look for observables (characterized by having a _ in the name)
584 while (text.find("_") != std::string::npos) {
585 size_t pos_ = text.find("_");
586 size_t beginning = text.find_last_of(" -+*/)(^%", pos_) + 1;
587 size_t end = text.find_first_of(" -+*/)(^%", pos_);
588 std::string obs = text.substr(beginning, end - beginning);
589 text = Replace(text, obs, "1");
590 obsList.push_back(obs);
591 }
592
593 if (!(isAExpression(text) || isANumber(text)))
594 RESTWarning << "The expression " << exp
595 << " has not been correctly parsed into variables, metadata and observables"
596 << RESTendl;
597 }
598
599 // Add observables from observable key of panel info
600 for (auto& [key, posLabel] : panel.obsPos) {
601 auto&& [obs, label, units] = key;
602 obsList.push_back(obs);
603 }
604 // Add relevant quantity to metadata from the panel info
605 for (auto& [key, posLabel] : panel.metadataPos) {
606 auto&& [metadata, label, units] = key;
608 quant.metadata = metadata;
609 quant.strategy = "unique";
610 quantity[label] = quant;
611 }
612 }
613
614 // Remove duplicated observables if any
615 std::sort(obsList.begin(), obsList.end());
616 obsList.erase(std::unique(obsList.begin(), obsList.end()), obsList.end());
617 dataSet.SetFilePattern(fDataSetName);
618 dataSet.SetObservablesList(obsList);
619 dataSet.SetQuantity(quantity);
620 dataSet.GenerateDataSet();
621}
622
628 TRestDataSet dataSet;
629 dataSet.EnableMultiThreading(true);
630
631 // Import dataSet
632 dataSet.Import(fDataSetName);
633
634 // If dataSet is not valid, try to generate it, but note that this is deprecated
635 if (dataSet.GetTree() == nullptr) {
636 RESTWarning << "Cannot import dataSet, trying to generate it with pattern " << fDataSetName
637 << RESTendl;
638 RESTWarning << "Note that the generation of a dataSet inside TRestDataSetPlot is deplecated. Check "
639 "TRestDataSet documentation to generate a dataSet"
640 << RESTendl;
642 if (dataSet.GetTree() == nullptr) {
643 RESTError << "Cannot generate dataSet " << RESTendl;
644 exit(1);
645 }
646 }
647
648 // Perform the global cut over the dataSet
649 dataSet.SetDataFrame(dataSet.MakeCut(fCut));
650
651 TCanvas combinedCanvas(this->GetName(), this->GetName(), 0, 0, fCanvasSize.X(), fCanvasSize.Y());
652 combinedCanvas.Divide((Int_t)fCanvasDivisions.X(), (Int_t)fCanvasDivisions.Y(),
653 fCanvasDivisionMargins.X(), fCanvasDivisionMargins.Y());
654
655 gStyle->SetPalette(fPaletteStyle);
656
657 const double duration = dataSet.GetTotalTimeInSeconds();
658 const double startTime = dataSet.GetStartTime();
659 const double endTime = dataSet.GetEndTime();
660
661 // Fill general variables for the panel
662 std::map<std::string, std::string> paramMap;
663 paramMap["[[startTime]]"] = ToDateTimeString(startTime);
664 paramMap["[[endTime]]"] = ToDateTimeString(endTime);
665
666 // DataSet quantity is used to replace metadata parameters
667 const auto quantity = dataSet.GetQuantity();
668
669 int canvasIndex = 1;
670
671 for (auto& panel : fPanels) {
672 combinedCanvas.cd(canvasIndex);
673 // Gets a dataFrame with the panel cut
674 auto dataFrame = dataSet.MakeCut(panel.panelCut);
675 const int entries = *dataFrame.Count();
676 const double meanRate = entries / duration;
677 const double runLength = duration / 3600.;
678 paramMap["[[runLength]]"] = DoubleToString(runLength, "%.9e");
679 paramMap["[[entries]]"] = IntegerToString(entries);
680 paramMap["[[meanRate]]"] = DoubleToString(meanRate, "%.9e");
681
682 paramMap["[[cutNames]]"] = "";
683 paramMap["[[cuts]]"] = "";
684 if (fCut) {
685 for (const auto& cut : fCut->GetCuts()) {
686 if (paramMap["[[cutNames]]"].empty())
687 paramMap["[[cutNames]]"] += cut.GetName();
688 else
689 paramMap["[[cutNames]]"] += "," + (std::string)cut.GetName();
690 if (paramMap["[[cuts]]"].empty())
691 paramMap["[[cuts]]"] += cut.GetTitle();
692 else
693 paramMap["[[cuts]]"] += " && " + (std::string)cut.GetTitle();
694 }
695 }
696
697 paramMap["[[panelCutNames]]"] = "";
698 paramMap["[[panelCuts]]"] = "";
699 if (panel.panelCut) {
700 for (const auto& cut : panel.panelCut->GetCuts()) {
701 if (paramMap["[[panelCutNames]]"].empty())
702 paramMap["[[panelCutNames]]"] += cut.GetName();
703 else
704 paramMap["[[panelCutNames]]"] += "," + (std::string)cut.GetName();
705 if (paramMap["[[panelCuts]]"].empty())
706 paramMap["[[panelCuts]]"] += cut.GetTitle();
707 else
708 paramMap["[[panelCuts]]"] += " && " + (std::string)cut.GetTitle();
709 }
710 }
711
712 RESTInfo << "Global cuts: " << paramMap["[[cuts]]"] << RESTendl;
713 if (!paramMap["[[panelCuts]]"].empty())
714 RESTInfo << "Additional panel cuts: " << paramMap["[[panelCuts]]"] << RESTendl;
715
716 // Replace panel variables and generate a TLatex label
717 for (const auto& [key, posLabel] : panel.variablePos) {
718 auto&& [variable, label, units] = key;
719 bool found = false;
720 std::string var = variable;
721 if (!var.empty()) {
722 for (const auto& [param, val] : paramMap) {
723 if (var == param) {
724 size_t pos = 0;
725 var = Replace(var, param, val, pos);
726 found = true;
727 break;
728 }
729 }
730 if (!found) RESTWarning << "Variable " << variable << " not found" << RESTendl;
731 }
732 if (isANumber(var)) { // if it is a number, convert it to number to apply precision
733 if (var.find('.') == std::string::npos) {
734 int dblVar = StringToInteger(var);
735 var = StringWithPrecision(dblVar, panel.precision);
736 } else {
737 double dblVar = StringToDouble(var);
738 var = StringWithPrecision(dblVar, panel.precision);
739 }
740 }
741 std::string lab =
742 label + panel.delimiter.Data() + StringWithPrecision(var, panel.precision) + " " + units;
743 panel.text.emplace_back(new TLatex(posLabel.X(), posLabel.Y(), lab.c_str()));
744 }
745
746 // Replace metadata variables and generate a TLatex label
747 for (const auto& [key, posLabel] : panel.metadataPos) {
748 auto&& [metadata, label, units] = key;
749 std::string value = "";
750
751 for (const auto& [name, quant] : quantity) {
752 if (quant.metadata == metadata) value = quant.value;
753 }
754
755 if (value.empty()) {
756 RESTWarning << "Metadata quantity " << metadata << " not found in dataSet" << RESTendl;
757 continue;
758 }
759
760 std::string lab =
761 label + panel.delimiter.Data() + StringWithPrecision(value, panel.precision) + " " + units;
762 panel.text.emplace_back(new TLatex(posLabel.X(), posLabel.Y(), lab.c_str()));
763 }
764
765 // Replace observable variables and generate a TLatex label
766 for (const auto& [key, posLabel] : panel.obsPos) {
767 auto&& [obs, label, units] = key;
768 auto value = *dataFrame.Mean(obs);
769
770 std::string lab =
771 label + panel.delimiter.Data() + StringWithPrecision(value, panel.precision) + " " + units;
772 panel.text.emplace_back(new TLatex(posLabel.X(), posLabel.Y(), lab.c_str()));
773 }
774
775 // Replace any expression and generate TLatex label
776 for (const auto& [key, posLabel] : panel.expPos) {
777 auto&& [text, label, units, precision] = key;
778 std::string var = text;
779
780 // find and split the text into subtexts which are surrounded by {}
781 std::vector<std::string> subtexts;
782 while (var.find_last_of('{') != std::string::npos) {
783 size_t posOpen = var.find_last_of('{');
784 size_t posClose = var.find_first_of('}', posOpen);
785 if (posClose == std::string::npos) {
786 RESTWarning << "Unmatched { in expression: " << var << RESTendl;
787 break;
788 }
789 std::string subtext = var.substr(posOpen + 1, posClose - posOpen - 1);
790 subtexts.push_back(subtext);
791 // get rid of "{"+subtext+"}" from the var
792 var.erase(posOpen, posClose - posOpen + 1);
793 }
794 var = text; // reset var to the original text
795
796 // get precision formatting
797 std::vector<std::string> precisionParts;
798 for (const auto& part : Split(precision, ",", false, true)) {
799 precisionParts.push_back(part);
800 }
801 if (precisionParts.size() != subtexts.size()) {
802 RESTDebug << "Not enough precision values provided for the expression: `" << text
803 << "`. Using " << precisionParts.back() << " for last subtexts." << RESTendl;
804 precisionParts.resize(subtexts.size(), precisionParts.back()); // fill with last value
805 }
806
807 size_t precisionIndex = precisionParts.size() - 1;
808 for (const auto& subtext : subtexts) {
809 std::string subVar = subtext;
810 // replace variables
811 for (const auto& [param, val] : paramMap) {
812 subVar = Replace(subVar, param, val);
813 }
814 // replace metadata
815 for (const auto& [name, quant] : quantity) {
816 subVar = Replace(subVar, "[" + name + "]", quant.value); // metadata are surrounded by []
817 subVar = Replace(subVar, name, quant.value); // just in case ?
818 }
819 // replace observables
820 for (const auto& obs : dataFrame.GetColumnNames()) {
821 if (var.find(obs) == std::string::npos) continue;
822 // here there should be a checking that the mean(obs) can be calculated
823 // (checking obs data type?)
824 double value = *dataFrame.Mean(obs);
825 subVar = Replace(subVar, obs, DoubleToString(value));
826 }
827 subVar = Replace(subVar, "[", "(");
828 subVar = Replace(subVar, "]", ")");
829 subVar = EvaluateExpression(subVar);
830 if (isANumber(subVar)) {
831 double value = StringToDouble(subVar);
832 std::string prec = precisionParts[precisionIndex--];
833 if (prec.find('%') != std::string::npos) { // it is a format e.g. %.2f
834 subVar = DoubleToString(value, prec);
835 } else if (isANumber(prec)) { // it is a number
836 subVar = StringWithPrecision(value, StringToInteger(prec));
837 } else {
838 RESTWarning << "Unknown precision format: " << prec
839 << ". Using panels precision: " << panel.precision << RESTendl;
840 subVar = StringWithPrecision(value, panel.precision);
841 }
842 }
843 var = Replace(var, "{" + subtext + "}", subVar);
844 }
845
846 std::string lab = label + panel.delimiter.Data() + var + " " + units;
847 panel.text.emplace_back(new TLatex(posLabel.X(), posLabel.Y(), lab.c_str()));
848 }
849
850 // Draw the labels inside the pad
851 for (const auto& text : panel.text) {
852 text->SetTextColor(1);
853 text->SetTextSize(panel.font_size);
854 text->Draw("same");
855 }
856 canvasIndex++;
857 }
858
859 for (auto& plots : fPlots) {
860 // Histograms are added to a THStack and will be ploted later on
861 combinedCanvas.cd(canvasIndex);
862 plots.hs = new THStack(plots.name.c_str(), plots.title.c_str());
863 if (plots.legendOn) plots.legend = new TLegend(fLegendX1, fLegendY1, fLegendX2, fLegendY2);
865 for (auto& hist : plots.histos) {
866 auto dataFrame = dataSet.MakeCut(hist.histoCut);
867 if (hist.variable.front() == "timeStamp") {
868 hist.range.front().SetX(startTime);
869 hist.range.front().SetY(endTime);
870 }
871 // 1-D Histograms
872 if (hist.variable.size() == 1) {
873 auto histo = dataFrame.Histo1D({hist.name.c_str(), hist.name.c_str(), hist.nBins.front(),
874 hist.range.front().X(), hist.range.front().Y()},
875 hist.variable.front());
876 hist.histo = static_cast<TH1*>(histo->DrawClone());
877 // 2-D Histograms
878 } else if (hist.variable.size() == 2) {
879 auto histo = dataFrame.Histo2D(
880 {hist.name.c_str(), hist.name.c_str(), hist.nBins.front(), hist.range.front().X(),
881 hist.range.front().Y(), hist.nBins.back(), hist.range.back().X(), hist.range.back().Y()},
882 hist.variable.front(), hist.variable.back());
883 hist.histo = static_cast<TH1*>(histo->DrawClone());
884 } else {
885 RESTError << "Only 1D or 2D histograms are supported " << RESTendl;
886 continue;
887 }
888 hist.histo->SetLineColor(hist.lineColor);
889 hist.histo->SetLineWidth(hist.lineWidth);
890 hist.histo->SetLineStyle(hist.lineStyle);
891 hist.histo->SetFillColor(hist.fillColor);
892 hist.histo->SetFillStyle(hist.fillStyle);
893 // If stats are on histos must we drawn
894 if (hist.statistics) {
895 hist.histo->SetStats(true);
896 hist.histo->Draw();
897 combinedCanvas.Update();
898 } else {
899 hist.histo->SetStats(false);
900 }
901 // Normalize histos
902 if (plots.normalize > 0) {
903 const double integral = hist.histo->Integral();
904 if (integral > 0) hist.histo->Scale(plots.normalize / integral);
905 }
906 // Scale histos
907 if (plots.scale != "") {
908 std::string inputScale = plots.scale;
909 double binSize = hist.histo->GetXaxis()->GetBinWidth(1);
910 double entries = hist.histo->GetEntries();
911 double runLength = dataSet.GetTotalTimeInSeconds() / 3600.; // in hours
912 double integral = hist.histo->Integral("width");
913
914 inputScale = Replace(inputScale, "binSize", DoubleToString(binSize));
915 inputScale = Replace(inputScale, "entries", DoubleToString(entries));
916 inputScale = Replace(inputScale, "runLength", DoubleToString(runLength));
917 inputScale = Replace(inputScale, "integral", DoubleToString(integral));
918
919 std::string scale = "1./(" + inputScale + ")";
920 hist.histo->Scale(StringToDouble(EvaluateExpression(scale))); // -1 if 'scale' isn't valid
921 }
922
923 // Add histos to the THStack
924 plots.hs->Add(hist.histo, hist.drawOption.c_str());
925 // Add histos to the legend
926 if (plots.legend != nullptr) plots.legend->AddEntry(hist.histo, hist.histo->GetName(), "lf");
927 }
928 }
929
930 // This function do the actual drawing of the THStack with the different options
931 for (auto& plots : fPlots) {
932 if (plots.hs == nullptr) continue;
933 // TPad parameters
934 TPad* targetPad = (TPad*)combinedCanvas.cd(canvasIndex);
935 targetPad->SetLogx(plots.logX);
936 targetPad->SetLogy(plots.logY);
937 targetPad->SetLogz(plots.logZ);
938 targetPad->SetGridx(plots.gridX);
939 targetPad->SetGridy(plots.gridY);
940 targetPad->SetLeftMargin(plots.marginLeft);
941 targetPad->SetRightMargin(plots.marginRight);
942 targetPad->SetBottomMargin(plots.marginBottom);
943 targetPad->SetTopMargin(plots.marginTop);
944
945 // HStack draw parameters
946 plots.hs->Draw(plots.stackDrawOption.c_str());
947 plots.hs->GetXaxis()->SetTitle(plots.labelX.c_str());
948 plots.hs->GetYaxis()->SetTitle(plots.labelY.c_str());
949 plots.hs->GetXaxis()->SetLabelSize(1.1 * plots.hs->GetXaxis()->GetLabelSize());
950 plots.hs->GetYaxis()->SetLabelSize(1.1 * plots.hs->GetYaxis()->GetLabelSize());
951 plots.hs->GetXaxis()->SetTitleSize(1.1 * plots.hs->GetXaxis()->GetTitleSize());
952 plots.hs->GetYaxis()->SetTitleSize(1.1 * plots.hs->GetYaxis()->GetTitleSize());
953
954 if (plots.timeDisplay) plots.hs->GetXaxis()->SetTimeDisplay(1);
955 if (plots.legend != nullptr) plots.legend->Draw();
956
957 targetPad->Update();
958 combinedCanvas.Update();
959 canvasIndex++;
960 }
961
962 // Preview plot. User can make some changed before saving
963 if (!REST_Display_CompatibilityMode && fPreviewPlot) {
964 combinedCanvas.Resize();
965 GetChar();
966 }
967
968 // Save single pads if save is marked
969 for (auto& plots : fPlots) {
970 if (plots.save.empty()) continue;
971 std::unique_ptr<TCanvas> canvas(new TCanvas());
972 canvas->SetLogx(plots.logX);
973 canvas->SetLogy(plots.logY);
974 canvas->SetLogz(plots.logZ);
975 canvas->SetGridx(plots.gridX);
976 canvas->SetGridy(plots.gridY);
977 canvas->SetLeftMargin(plots.marginLeft);
978 canvas->SetRightMargin(plots.marginRight);
979 canvas->SetBottomMargin(plots.marginBottom);
980 canvas->SetTopMargin(plots.marginTop);
981 plots.hs->Draw(plots.stackDrawOption.c_str());
982 canvas->Print(plots.save.c_str());
983 }
984
985 // Save combined canvas
986 if (!fOutputFileName.empty()) {
987 for (const auto& [name, quant] : quantity) {
988 size_t pos = 0;
989 fOutputFileName = Replace(fOutputFileName, quant.metadata, quant.value, pos);
990 }
991 combinedCanvas.Print(fOutputFileName.c_str());
992 // In case of root file save also the histograms
994 std::unique_ptr<TFile> f(TFile::Open(fOutputFileName.c_str(), "UPDATE"));
995 for (auto& plots : fPlots) {
996 for (auto& hist : plots.histos) {
997 hist.histo->Write();
998 }
999 }
1000 this->Write();
1001 }
1002 }
1003
1004 CleanUp();
1005}
1006
1012 for (auto& plots : fPlots) {
1013 for (auto& hist : plots.histos) {
1014 delete hist.histo;
1015 }
1016 delete plots.hs;
1017 delete plots.legend;
1018 }
1019
1020 for (auto& panel : fPanels) {
1021 for (auto& text : panel.text) {
1022 delete text;
1023 }
1024 panel.text.clear();
1025 }
1026}
1027
1033Int_t TRestDataSetPlot::GetIDFromMapString(const std::map<std::string, int>& mapStr, const std::string& in) {
1034 if (in.find_first_not_of("0123456789") == std::string::npos) {
1035 return StringToInteger(in);
1036 }
1037 auto it = mapStr.find(in);
1038 if (it != mapStr.end()) {
1039 return it->second;
1040 } else {
1041 RESTWarning << "cannot find ID with name \"" << in << "\"" << RESTendl;
1042 }
1043 return -1;
1044}
1045
1051
1052 RESTMetadata << "DataSet name: " << fDataSetName << RESTendl;
1053 RESTMetadata << "PaletteStyle: " << fPaletteStyle << RESTendl;
1054 if (fPreviewPlot) RESTMetadata << "Preview plot is ACTIVE" << RESTendl;
1055 RESTMetadata << "Canvas size: (" << fCanvasSize.X() << " ," << fCanvasSize.Y() << ")" << RESTendl;
1056 RESTMetadata << "Canvas divisions: (" << fCanvasDivisions.X() << " ," << fCanvasDivisions.Y() << ")"
1057 << RESTendl;
1058 RESTMetadata << "-------------------" << RESTendl;
1059 for (const auto& plot : fPlots) {
1060 RESTMetadata << "-------------------" << RESTendl;
1061 RESTMetadata << "Plot name/title: " << plot.name << " " << plot.title << RESTendl;
1062 RESTMetadata << "Save string: " << plot.save << RESTendl;
1063 RESTMetadata << "Set log X,Y,Z: " << plot.logX << ", " << plot.logY << ", " << plot.logZ << RESTendl;
1064 RESTMetadata << "Stack draw Option: " << plot.stackDrawOption << RESTendl;
1065 if (plot.legend) RESTMetadata << "Legend is ON" << RESTendl;
1066 if (plot.timeDisplay) RESTMetadata << "Time display is ON" << RESTendl;
1067 RESTMetadata << "Labels X,Y: " << plot.labelX << ", " << plot.labelY << RESTendl;
1068 for (const auto& hist : plot.histos) {
1069 RESTMetadata << "****************" << RESTendl;
1070 RESTMetadata << "Histo name: " << hist.name << RESTendl;
1071 RESTMetadata << "Draw Option: " << hist.drawOption << RESTendl;
1072 RESTMetadata << "Histogram size: " << hist.variable.size() << " with parameters:" << RESTendl;
1073 for (size_t i = 0; i < hist.variable.size(); i++) {
1074 RESTMetadata << "\t" << i << " " << hist.variable[i] << ", " << hist.nBins[i] << ", "
1075 << hist.range[i].X() << ", " << hist.range[i].Y() << RESTendl;
1076 }
1077 RESTMetadata << "****************" << RESTendl;
1078 }
1079 }
1080 RESTMetadata << "-------------------" << RESTendl;
1081 for (auto& panel : fPanels) {
1082 RESTMetadata << "-------------------" << RESTendl;
1083 RESTMetadata << "Panel font size/precision " << panel.font_size << ", " << panel.precision
1084 << RESTendl;
1085 RESTMetadata << "****************" << RESTendl;
1086 for (auto& [key, posLabel] : panel.variablePos) {
1087 auto&& [obs, label, units] = key;
1088 RESTMetadata << "Label variable " << obs << ", label " << label << ", units " << units << " Pos ("
1089 << posLabel.X() << ", " << posLabel.Y() << ")" << RESTendl;
1090 }
1091 RESTMetadata << "****************" << RESTendl;
1092 for (auto& [key, posLabel] : panel.metadataPos) {
1093 auto&& [obs, label, units] = key;
1094 RESTMetadata << "Label metadata " << obs << ", label " << label << ", units " << units << " Pos ("
1095 << posLabel.X() << ", " << posLabel.Y() << ")" << RESTendl;
1096 }
1097 RESTMetadata << "****************" << RESTendl;
1098 for (auto& [key, posLabel] : panel.obsPos) {
1099 auto&& [obs, label, units] = key;
1100 RESTMetadata << "Label Observable " << obs << ", label " << label << ", units " << units
1101 << " Pos (" << posLabel.X() << ", " << posLabel.Y() << ")" << RESTendl;
1102 }
1103 RESTMetadata << "****************" << RESTendl;
1104 for (auto& [key, posLabel] : panel.expPos) {
1105 auto&& [obs, label, units, precision] = key;
1106 RESTMetadata << "Label Expression " << obs << ", label " << label << ", units " << units
1107 << ", precision " << precision << " Pos (" << posLabel.X() << ", " << posLabel.Y()
1108 << ")" << RESTendl;
1109 }
1110 RESTMetadata << "****************" << RESTendl;
1111 }
1112 RESTMetadata << "-------------------" << RESTendl;
1113
1114 RESTMetadata << RESTendl;
1115}
A class to help on cuts definitions. To be used with TRestAnalysisTree.
Definition TRestCut.h:31
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.
A base class for any REST metadata class.
virtual void PrintMetadata()
Implemented it in the derived metadata class to print out specific metadata information.
endl_t RESTendl
Termination flag object for TRestStringOutput.
TiXmlElement * GetElement(std::string eleDeclare, TiXmlElement *e=nullptr)
Get an xml element from a given parent element, according to its declaration.
Int_t LoadConfigFromFile(const std::string &configFilename, const std::string &sectionName="")
Give the file name, find out the corresponding section. Then call the main starter.
TRestMetadata * InstantiateChildMetadata(int index, std::string pattern="")
This method will retrieve a new TRestMetadata instance of a child element of the present TRestMetadat...
virtual void InitFromConfigFile()
To make settings from rml file. This method must be implemented in the derived class.
TRestStringOutput::REST_Verbose_Level GetVerboseLevel()
returns the verboselevel in type of REST_Verbose_Level enumerator
void SetSectionName(std::string sName)
set the section name, clear the section content
std::string fConfigFileName
Full name of the rml file.
virtual Int_t Write(const char *name=nullptr, Int_t option=0, Int_t bufsize=0)
overwriting the write() method with fStore considered
TiXmlElement * GetNextElement(TiXmlElement *e)
Get the next sibling xml element of this element, with same eleDeclare.
std::string GetParameter(std::string parName, TiXmlElement *e, TString defaultValue=PARAMETER_NOT_FOUND_STR)
Returns the value for the parameter named parName in the given section.
@ REST_Info
+show most of the information for each steps
static std::string GetFileNameExtension(const std::string &fullname)
Gets the file extension as the substring found after the latest ".".
Int_t GetChar(std::string hint="Press a KEY to continue ...")
Helps to pause the program, printing a message before pausing.
std::string IntegerToString(Int_t n, std::string format="%d")
Gets a string from an integer.
std::vector< std::string > Split(std::string in, std::string separator, bool allowBlankString=false, bool removeWhiteSpaces=false, int startPos=-1)
Split the input string according to the given separator. Returning a vector of fragments.
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)