diff --git a/source/framework/core/inc/TRestAnalysisPlot.h b/source/framework/core/inc/TRestAnalysisPlot.h index 0b95d9156..c85329760 100644 --- a/source/framework/core/inc/TRestAnalysisPlot.h +++ b/source/framework/core/inc/TRestAnalysisPlot.h @@ -44,13 +44,14 @@ const std::map FillStyleMap{ class TRestAnalysisPlot : public TRestMetadata { public: - struct Histo_Info_Set { + struct HistoInfoSet { std::string name; // will be shown in the legend std::string range; // output histo std::string for TTree::Draw(), e.g. name+range = htemp(100,0,1000) Bool_t status; std::string plotString; // draw std::string for TTree::Draw() std::string cutString; // cut std::string for TTree::Draw() + std::string weight; std::map classifyMap; // select the input files to draw the histogram, if their // TRestRun::Get() returns the assumed std::string @@ -66,7 +67,7 @@ class TRestAnalysisPlot : public TRestMetadata { TH3F* operator->() { return ptr; } }; - struct Plot_Info_Set { + struct PlotInfoSet { std::string name; std::string title; @@ -102,11 +103,12 @@ class TRestAnalysisPlot : public TRestMetadata { std::string save; - std::vector histos; + std::vector histos; }; - struct Panel_Info { + struct PanelInfo { Float_t font_size; + Int_t precision; std::vector posX; std::vector posY; @@ -116,7 +118,7 @@ class TRestAnalysisPlot : public TRestMetadata { private: void InitFromConfigFile() override; - Histo_Info_Set SetupHistogramFromConfigFile(TiXmlElement* ele, Plot_Info_Set info); + HistoInfoSet SetupHistogramFromConfigFile(TiXmlElement* ele, PlotInfoSet info); Int_t fNFiles; // canvas option @@ -140,8 +142,8 @@ class TRestAnalysisPlot : public TRestMetadata { Double_t fLegendY2 = 0.88; // plots information - std::vector fPlots; - std::vector fPanels; + std::vector fPlots; + std::vector fPanels; std::vector fPlotNamesCheck; //! diff --git a/source/framework/core/inc/TRestMetadata.h b/source/framework/core/inc/TRestMetadata.h index 02ecc3d19..e1e1910ef 100644 --- a/source/framework/core/inc/TRestMetadata.h +++ b/source/framework/core/inc/TRestMetadata.h @@ -270,7 +270,7 @@ class TRestMetadata : public TNamed { std::string GetDataMemberValue(std::string memberName); - std::vector GetDataMemberValues(std::string memberName); + std::vector GetDataMemberValues(std::string memberName, Int_t precision = 0); TString GetVersion(); // *MENU* diff --git a/source/framework/core/inc/TRestRun.h b/source/framework/core/inc/TRestRun.h index f741e5b22..41c03c977 100644 --- a/source/framework/core/inc/TRestRun.h +++ b/source/framework/core/inc/TRestRun.h @@ -62,7 +62,7 @@ class TRestRun : public TRestMetadata { void InitFromConfigFile() override; private: - std::string ReplaceMetadataMember(const std::string& instr); + std::string ReplaceMetadataMember(const std::string& instr, Int_t precision = 0); public: /// REST run class @@ -172,7 +172,7 @@ class TRestRun : public TRestMetadata { inline int GetNumberOfMetadataStructures() const { return fMetadata.size(); } inline std::string GetMetadataMember(const std::string& instr) { return ReplaceMetadataMember(instr); } - std::string ReplaceMetadataMembers(const std::string& instr); + std::string ReplaceMetadataMembers(const std::string& instr, Int_t precision = 2); Bool_t EvaluateMetadataMember(const std::string& instr); diff --git a/source/framework/core/src/TRestAnalysisPlot.cxx b/source/framework/core/src/TRestAnalysisPlot.cxx index e20b12a9b..d123168f6 100644 --- a/source/framework/core/src/TRestAnalysisPlot.cxx +++ b/source/framework/core/src/TRestAnalysisPlot.cxx @@ -242,7 +242,7 @@ void TRestAnalysisPlot::InitFromConfigFile() { << RESTendl; exit(1); } - Plot_Info_Set plot; + PlotInfoSet plot; plot.name = RemoveWhiteSpaces(GetParameter("name", plotele, "plot_" + ToString(N))); plot.title = GetParameter("title", plotele, plot.name); plot.logY = StringToBool(GetParameter("logscale", plotele, "false")); @@ -259,7 +259,7 @@ void TRestAnalysisPlot::InitFromConfigFile() { plot.ticksY = StringToInteger(GetParameter("yticks", plotele, "510")); plot.marginBottom = StringToDouble(GetParameter("marginBottom", plotele, "0.15")); plot.marginTop = StringToDouble(GetParameter("marginTop", plotele, "0.07")); - plot.marginLeft = StringToDouble(GetParameter("marginLeft", plotele, "0.18")); + plot.marginLeft = StringToDouble(GetParameter("marginLeft", plotele, "0.25")); plot.marginRight = StringToDouble(GetParameter("marginRight", plotele, "0.1")); plot.legendOn = StringToBool(GetParameter("legend", plotele, "OFF")); plot.staticsOn = StringToBool(GetParameter("stats", plotele, "OFF")); @@ -275,7 +275,7 @@ void TRestAnalysisPlot::InitFromConfigFile() { histele = plotele; } while (histele != nullptr) { - Histo_Info_Set hist = SetupHistogramFromConfigFile(histele, plot); + HistoInfoSet hist = SetupHistogramFromConfigFile(histele, plot); // add global cut for (unsigned int i = 0; i < globalCuts.size(); i++) { if (i > 0 || hist.cutString != "") hist.cutString += " && "; @@ -283,10 +283,7 @@ void TRestAnalysisPlot::InitFromConfigFile() { cout << "Adding global cut : " << globalCuts[i] << endl; hist.cutString += globalCuts[i]; } - //// add "SAME" option - // if (plot.histos.size() > 0) { - // hist.drawOption += " SAME"; - //} + hist.weight = GetParameter("weight", histele, ""); if (hist.plotString == "") { RESTWarning << "No variables or histograms defined in the plot, skipping!" << RESTendl; @@ -321,8 +318,9 @@ void TRestAnalysisPlot::InitFromConfigFile() { exit(1); } - Panel_Info panel; + PanelInfo panel; panel.font_size = StringToDouble(GetParameter("font_size", panelele, "0.1")); + panel.precision = StringToInteger(GetParameter("precision", panelele, "2")); TiXmlElement* labelele = GetElement("label", panelele); while (labelele != nullptr) { @@ -349,9 +347,9 @@ void TRestAnalysisPlot::InitFromConfigFile() { } #pragma endregion -TRestAnalysisPlot::Histo_Info_Set TRestAnalysisPlot::SetupHistogramFromConfigFile(TiXmlElement* histele, - Plot_Info_Set plot) { - Histo_Info_Set hist; +TRestAnalysisPlot::HistoInfoSet TRestAnalysisPlot::SetupHistogramFromConfigFile(TiXmlElement* histele, + PlotInfoSet plot) { + HistoInfoSet hist; hist.name = RemoveWhiteSpaces(GetParameter("name", histele, plot.name)); hist.drawOption = GetParameter("option", histele, "colz"); @@ -686,7 +684,7 @@ void TRestAnalysisPlot::PlotCombinedCanvas() { label = Replace(label, "<>", Form("%5.2lf", meanRate), pos); auto run = GetRunInfo(fRunInputFileName[0]); - label = run->ReplaceMetadataMembers(label); + label = run->ReplaceMetadataMembers(label, fPanels[n].precision); TLatex* texxt = new TLatex(fPanels[n].posX[m], fPanels[n].posY[m], label.c_str()); texxt->SetTextColor(1); @@ -698,7 +696,7 @@ void TRestAnalysisPlot::PlotCombinedCanvas() { // start drawing plots vector histCollectionAll; for (unsigned int n = 0; n < fPlots.size(); n++) { - Plot_Info_Set& plot = fPlots[n]; + PlotInfoSet& plot = fPlots[n]; TPad* targetPad = (TPad*)fCombinedCanvas->cd(n + 1 + fPanels.size()); targetPad->SetLogx(plot.logX); @@ -713,7 +711,7 @@ void TRestAnalysisPlot::PlotCombinedCanvas() { // draw each histogram in the pad for (unsigned int i = 0; i < plot.histos.size(); i++) { - Histo_Info_Set& hist = plot.histos[i]; + HistoInfoSet& hist = plot.histos[i]; TString plotString = hist.plotString; TString nameString = hist.name; @@ -725,6 +723,11 @@ void TRestAnalysisPlot::PlotCombinedCanvas() { rangeString = Replace((string)rangeString, "MIN_TIME", (string)Form("%9f", startTime), pos); rangeString = Replace((string)rangeString, "MAX_TIME", (string)Form("%9f", endTime), pos); + if (cutString == "") + cutString = hist.weight; + else if (hist.weight != "") + cutString = "(" + cutString + ") * " + hist.weight; + if (GetVerboseLevel() >= TRestStringOutput::REST_Verbose_Level::REST_Debug) { cout << endl; cout << "--------------------------------------" << endl; @@ -816,12 +819,12 @@ void TRestAnalysisPlot::PlotCombinedCanvas() { hTotal->GetXaxis()->SetTitle(plot.labelX.c_str()); hTotal->GetYaxis()->SetTitle(plot.labelY.c_str()); - hTotal->GetXaxis()->SetLabelSize(fTicksScaleX * hTotal->GetXaxis()->GetLabelSize()); - hTotal->GetYaxis()->SetLabelSize(fTicksScaleY * hTotal->GetYaxis()->GetLabelSize()); - hTotal->GetXaxis()->SetTitleSize(fLabelScaleX * hTotal->GetXaxis()->GetTitleSize()); - hTotal->GetYaxis()->SetTitleSize(fLabelScaleY * hTotal->GetYaxis()->GetTitleSize()); - hTotal->GetXaxis()->SetTitleOffset(fLabelOffsetX * hTotal->GetXaxis()->GetTitleOffset()); - hTotal->GetYaxis()->SetTitleOffset(fLabelOffsetY * hTotal->GetYaxis()->GetTitleOffset()); + hTotal->GetXaxis()->SetLabelSize(1.1 * hTotal->GetXaxis()->GetLabelSize()); + hTotal->GetYaxis()->SetLabelSize(1.1 * hTotal->GetYaxis()->GetLabelSize()); + hTotal->GetXaxis()->SetTitleSize(1.1 * hTotal->GetXaxis()->GetTitleSize()); + hTotal->GetYaxis()->SetTitleSize(1.1 * hTotal->GetYaxis()->GetTitleSize()); + hTotal->GetXaxis()->SetTitleOffset(1 * hTotal->GetXaxis()->GetTitleOffset()); + hTotal->GetYaxis()->SetTitleOffset(1 * hTotal->GetYaxis()->GetTitleOffset()); hTotal->GetXaxis()->SetNdivisions(plot.ticksX); hTotal->GetYaxis()->SetNdivisions(plot.ticksY); @@ -903,7 +906,7 @@ void TRestAnalysisPlot::PlotCombinedCanvas() { // draw the remaining histo if (plot.histos[i].ptr == nullptr) continue; if (i != maxID) { - plot.histos[i]->Draw((plot.histos[maxID].drawOption + "same").c_str()); + plot.histos[i]->Draw((plot.histos[i].drawOption + "same").c_str()); } } @@ -927,6 +930,9 @@ void TRestAnalysisPlot::PlotCombinedCanvas() { } // save pad + targetPad->SetRightMargin(plot.marginRight); + targetPad->SetLeftMargin(plot.marginLeft); + targetPad->SetBottomMargin(plot.marginBottom); targetPad->Update(); if (plot.save != "") targetPad->Print(plot.save.c_str()); @@ -975,6 +981,9 @@ void TRestAnalysisPlot::SavePlotToPDF(TString fileName, Int_t n) { } TPad* pad = (TPad*)fCombinedCanvas->GetPad(n); + pad->SetRightMargin(fPlots[n - 1].marginRight); + pad->SetLeftMargin(fPlots[n - 1].marginLeft); + pad->SetBottomMargin(fPlots[n - 1].marginBottom); TCanvas* c = new TCanvas(fPlots[n - 1].name.c_str(), fPlots[n - 1].name.c_str(), 800, 600); pad->DrawClone(); diff --git a/source/framework/core/src/TRestEventProcess.cxx b/source/framework/core/src/TRestEventProcess.cxx index 670fad3e9..2fd7b7f7b 100644 --- a/source/framework/core/src/TRestEventProcess.cxx +++ b/source/framework/core/src/TRestEventProcess.cxx @@ -191,7 +191,8 @@ Bool_t TRestEventProcess::OpenInputFiles(vector files) { return false; } Int_t TRestEventProcess::LoadSectionMetadata() { TRestMetadata::LoadSectionMetadata(); - if (ToUpper(GetParameter("observable", "")) == "ALL") { + if (ToUpper(GetParameter("observable", "")) == "ALL" || + ToUpper(GetParameter("observables", "")) == "ALL") { fDynamicObs = true; } @@ -288,11 +289,11 @@ TRestEventProcess* TRestEventProcess::GetFriendLive(string nameortype) { /// \brief Get a list of parallel processes from this process /// /// Parallel process means the process in other threads. It differs from "friend process" -/// in another dimension. For example, we set up the process chain with one +/// in another dimension. For example, we set up the process chain with one /// `TRestRawSignalAnalysisProcess` and one `TRestRawToSignalProcess`, and calls 2 threads to -/// run the data. Then, for `TRestRawSignalAnalysisProcess` in thread 1, it has a parallel -/// process `TRestRawSignalAnalysisProcess` from thread 2, and a friend process -/// `TRestRawToSignalProcess` from thread 1. +/// run the data. Then, for `TRestRawSignalAnalysisProcess` in thread 1, it has a parallel +/// process `TRestRawSignalAnalysisProcess` from thread 2, and a friend process +/// `TRestRawToSignalProcess` from thread 1. TRestEventProcess* TRestEventProcess::GetParallel(int i) { if (i >= 0 && i < fParallelProcesses.size()) { return fParallelProcesses[i]; diff --git a/source/framework/core/src/TRestMetadata.cxx b/source/framework/core/src/TRestMetadata.cxx index 01e4aec78..f847d0f43 100644 --- a/source/framework/core/src/TRestMetadata.cxx +++ b/source/framework/core/src/TRestMetadata.cxx @@ -1128,10 +1128,10 @@ void TRestMetadata::ReplaceForLoopVars(TiXmlElement* e, map forL } } - e->SetAttribute( - name, ReplaceMathematicalExpressions( - outputBuffer, "Please, check parameter name: " + parName + " (ReplaceForLoopVars)") - .c_str()); + e->SetAttribute(name, ReplaceMathematicalExpressions( + outputBuffer, 0, + "Please, check parameter name: " + parName + " (ReplaceForLoopVars)") + .c_str()); } attr = attr->Next(); @@ -1484,7 +1484,7 @@ string TRestMetadata::GetParameter(std::string parName, TiXmlElement* e, TString } } - return ReplaceMathematicalExpressions(ReplaceConstants(ReplaceVariables(result)), + return ReplaceMathematicalExpressions(ReplaceConstants(ReplaceVariables(result)), 0, "Please, check parameter name: " + parName); } @@ -2308,13 +2308,21 @@ string TRestMetadata::GetDataMemberValue(string memberName) { /// /// All kinds of data member can be found, including non-streamed /// data member and base-class data member -std::vector TRestMetadata::GetDataMemberValues(string memberName) { +/// +/// If precision value is higher than 0, then the resulting values will be +/// truncated after finding ".". This can be used to define a float precision. +/// +std::vector TRestMetadata::GetDataMemberValues(string memberName, Int_t precision) { string result = GetDataMemberValue(memberName); result = Replace(result, "{", ""); result = Replace(result, "}", ""); - return Split(result, ","); + std::vector results = REST_StringHelper::Split(result, ","); + + for (auto& x : results) x = REST_StringHelper::CropWithPrecision(x, precision); + + return results; } /////////////////////////////////////////////// diff --git a/source/framework/core/src/TRestRun.cxx b/source/framework/core/src/TRestRun.cxx index 4a19258e7..d8bae4679 100644 --- a/source/framework/core/src/TRestRun.cxx +++ b/source/framework/core/src/TRestRun.cxx @@ -278,43 +278,12 @@ void TRestRun::InitFromConfigFile() { "is not given!" << RESTendl; } - } else if (keydeclare == "addProcess") { - bool active = StringToBool(GetParameter("value", e, "")); - if (!active) { - e = e->NextSiblingElement(); - continue; - } - string processName = GetParameter("name", e, ""); - string processType = GetParameter("type", e, ""); - if (processType == "") { - RESTWarning << "Bad expression of addProcess" << RESTendl; - } else if (processName == "") { - RESTWarning << "Event process " << processType << " has no name, it will be skipped" - << RESTendl; - } - TRestEventProcess* pc = REST_Reflection::Assembly(processType); - if (!pc->isExternal()) { - RESTWarning << "This is not an external file process!" << RESTendl; - } else { - pc->LoadConfigFromElement(e, fElementGlobal); - pc->SetRunInfo(this); - pc->SetHostmgr(fHostmgr); - - SetExtProcess(pc); - } } else if (Count(keydeclare, "TRest") > 0) { if (e->Attribute("file") != nullptr && TRestTools::isRootFile(e->Attribute("file"))) { RESTWarning << "TRestRun: A root file is being included in section <" << keydeclare << " ! To import metadata from this file, use Attribute("file") != nullptr && (string)e->Attribute("file") == "server") { - // // read meta-sections from database - // auto url = gDataBase->query_data(DBEntry(fRunNumber, "META_RML", e->Value())).value; - // string file = TRestTools::DownloadRemoteFile(url); - // e->SetAttribute("file", file.c_str()); - // ExpandIncludeFile(e); - //} TRestMetadata* meta = REST_Reflection::Assembly(keydeclare); if (meta == nullptr) { @@ -1650,7 +1619,7 @@ std::vector TRestRun::GetMetadataStructureTitles() { /// /// \return The string with data members replaced /// -string TRestRun::ReplaceMetadataMembers(const string& instr) { +string TRestRun::ReplaceMetadataMembers(const string& instr, Int_t precision) { if (instr.find("[", 0) == (int)string::npos) return instr; string outstring = instr; @@ -1682,7 +1651,7 @@ string TRestRun::ReplaceMetadataMembers(const string& instr) { outstring = Replace(outstring, "<<", "["); outstring = Replace(outstring, ">>", "]"); - return outstring; + return REST_StringHelper::ReplaceMathematicalExpressions(outstring, precision); } /////////////////////////////////////////////// @@ -1701,7 +1670,7 @@ string TRestRun::ReplaceMetadataMembers(const string& instr) { /// /// \return The corresponding class data member value in string format. /// -string TRestRun::ReplaceMetadataMember(const string& instr) { +string TRestRun::ReplaceMetadataMember(const string& instr, Int_t precision) { if (instr.find("::") == string::npos && instr.find("->") == string::npos) { return "<<" + instr + ">>"; } @@ -1722,21 +1691,22 @@ string TRestRun::ReplaceMetadataMember(const string& instr) { } if (GetMetadata(results[0])) { - if (index >= this->GetMetadata(results[0])->GetDataMemberValues(results[1]).size()) { + if (index >= this->GetMetadata(results[0])->GetDataMemberValues(results[1], precision).size()) { RESTWarning << "TRestRun::ReplaceMetadataMember. Index out of range!" << RESTendl; RESTWarning << "Returning the first element" << RESTendl; index = 0; } - return this->GetMetadata(results[0])->GetDataMemberValues(results[1])[index]; + return this->GetMetadata(results[0])->GetDataMemberValues(results[1], precision)[index]; } if (GetMetadataClass(results[0])) { - if (index >= this->GetMetadataClass(results[0])->GetDataMemberValues(results[1]).size()) { + if (index >= + this->GetMetadataClass(results[0])->GetDataMemberValues(results[1], precision).size()) { RESTWarning << "TRestRun::ReplaceMetadataMember. Index out of range!" << RESTendl; RESTWarning << "Returning the first element" << RESTendl; index = 0; } - return this->GetMetadataClass(results[0])->GetDataMemberValues(results[1])[index]; + return this->GetMetadataClass(results[0])->GetDataMemberValues(results[1], precision)[index]; } } else diff --git a/source/framework/tools/inc/TRestStringHelper.h b/source/framework/tools/inc/TRestStringHelper.h index 2123fdd9f..81eeecd48 100644 --- a/source/framework/tools/inc/TRestStringHelper.h +++ b/source/framework/tools/inc/TRestStringHelper.h @@ -27,7 +27,9 @@ namespace REST_StringHelper { Int_t GetChar(std::string hint = "Press a KEY to continue ..."); Int_t isANumber(std::string in); Int_t isAExpression(const std::string& in); -std::string ReplaceMathematicalExpressions(std::string buffer, std::string errorMessage = ""); +std::string CropWithPrecision(std::string in, Int_t precision); +std::string ReplaceMathematicalExpressions(std::string buffer, Int_t precision = 0, + std::string errorMessage = ""); std::string EvaluateExpression(std::string exp); Float_t StringToFloat(std::string in); Double_t StringToDouble(std::string in); diff --git a/source/framework/tools/src/TRestStringHelper.cxx b/source/framework/tools/src/TRestStringHelper.cxx index 48bc17a4b..52c878af6 100644 --- a/source/framework/tools/src/TRestStringHelper.cxx +++ b/source/framework/tools/src/TRestStringHelper.cxx @@ -24,6 +24,7 @@ using namespace std; /// 123456789 --> not expression, It is a pure number that can be directly parsed. /// ./123 --> not expression, it is a path /// 333/555 --> is expression. But it may also be a path. We should avoid using paths like that +/// Int_t REST_StringHelper::isAExpression(const string& in) { bool symbol = false; @@ -69,13 +70,50 @@ Int_t REST_StringHelper::isAExpression(const string& in) { return 0; } +/////////////////////////////////////////////// +/// \brief It crops a floating number given inside the string `in` with the given precision. +/// I.e. CropWithPrecision("3.48604", 2) will return "3.48". +/// +/// It will not round the number. Perhaps on the next update of this method. +/// +std::string REST_StringHelper::CropWithPrecision(std::string in, Int_t precision) { + if (precision == 0) return in; + if (REST_StringHelper::isANumber(in) && in.find(".") != string::npos) { + std::string rootStr; + if (in.find("e") != string::npos) rootStr = in.substr(in.find("e"), -1); + return in.substr(0, in.find(".") + precision + 1) + rootStr; + } + return in; +} + /////////////////////////////////////////////// /// \brief Evaluates and replaces valid mathematical expressions found in the /// input string **buffer**. /// -std::string REST_StringHelper::ReplaceMathematicalExpressions(std::string buffer, std::string errorMessage) { +/// The buffer string may define sub-expressions that will be evaluated by using single quotes. +/// +/// I.e. The sentence "The following operation 3 x 4 is '3*4'" will be translated to +/// "The following operatin 3 x 4 is 12". +/// +std::string REST_StringHelper::ReplaceMathematicalExpressions(std::string buffer, Int_t precision, + std::string errorMessage) { buffer = Replace(buffer, " AND ", " && "); buffer = Replace(buffer, " OR ", " || "); + + if (buffer.find("'") != string::npos && std::count(buffer.begin(), buffer.end(), '\'') % 2 == 0) { + size_t pos1 = buffer.find("'"); + size_t pos2 = buffer.find("'", pos1 + 1); + string expr = buffer.substr(pos1 + 1, pos2 - pos1 - 1); + + if (!isAExpression(expr)) return buffer; + + std::string evalExpr = ReplaceMathematicalExpressions(expr, precision); + expr = "'" + expr + "'"; + std::string newbuff = Replace(buffer, expr, evalExpr); + + return ReplaceMathematicalExpressions(newbuff, precision, errorMessage); + } + // we spilt the unit part and the expresstion part int pos = buffer.find_last_of("1234567890()."); @@ -112,6 +150,7 @@ std::string REST_StringHelper::ReplaceMathematicalExpressions(std::string buffer if (erased) { result = "(" + result + ")"; } + result = CropWithPrecision(result, precision); return result + unit; }