diff --git a/quickstats/components/workspaces/xml_ws_modifier.py b/quickstats/components/workspaces/xml_ws_modifier.py index 35e3eca13188614ba19caefab3da4c67a4183ee8..5b9539e433a9d38b4b46046d027436f71fa0c9ba 100644 --- a/quickstats/components/workspaces/xml_ws_modifier.py +++ b/quickstats/components/workspaces/xml_ws_modifier.py @@ -270,7 +270,7 @@ class XMLWSModifier(XMLWSBase): if len(self.actions['rename']['model_config']) > 1: raise RuntimeError("model config is renamed more than once") - def correcct_formula(self,ws_orig, ws_tmp, rename_map): + def correct_formula(self,ws_orig, ws_tmp, rename_map): old_var_expr = ",".join(list(rename_map.keys())) new_var_expr = ",".join(list(rename_map.values())) tested_vars = [] @@ -360,7 +360,7 @@ class XMLWSModifier(XMLWSBase): actual_rename_map = self.get_actual_rename_map(rename_map, ws_orig, ws_tmp) # In case the variable exist in RooFormulaVar - self.correcct_formula(ws_orig, ws_tmp, rename_map) + self.correct_formula(ws_orig, ws_tmp, rename_map) self.rename_variables(mc_orig, ws_tmp, rename_map) if not rename_map: diff --git a/quickstats/macros/QuickStatsCore/RooFitExt.cxx b/quickstats/macros/QuickStatsCore/RooFitExt.cxx index c8f1eee6f51ed59d6fccd482f55af45446245c03..5945ec648a9ca221ea5071aa7290c38c5353e510 100644 --- a/quickstats/macros/QuickStatsCore/RooFitExt.cxx +++ b/quickstats/macros/QuickStatsCore/RooFitExt.cxx @@ -91,30 +91,48 @@ namespace RooFitExt{ } } - std::string getReconstructedFormulaStr(const RooFormula &formula) { - std::string formula_str = formula.formulaString(); - const RooArgSet dependents = formula.actualDependents(); - for (unsigned int i = 0; i < dependents.size(); ++i) { - const auto& var = dependents[i]; - std::stringstream regexStr; - regexStr << "x\\[" << i << "\\]|@" << i; - std::regex regex(regexStr.str()); - std::string replacement = var->GetName(); - formula_str = std::regex_replace(formula_str, regex, replacement); - } - return formula_str; - } std::string formatFunctionStr(const std::string class_name, const std::string name, const std::string formula_str){ std::string ret = class_name + "::" + name + "[ " + formula_str + " ]"; return ret; } - std::string getFunctionStrRepr(RooFormulaVar &formula_var){ - // - const std::string formula_str = getReconstructedFormulaStr(formula_var.formula()); - std::string ret = formatFunctionStr(formula_var.ClassName(), formula_var.GetName(), formula_str ); - return ret; - } + #if ROOT_VERSION_CODE < ROOT_VERSION(6,29,02) + std::string getReconstructedFormulaStr(const RooFormula &formula) { + std::string formula_str = formula.formulaString(); + const RooArgSet dependents = formula.actualDependents(); + for (unsigned int i = 0; i < dependents.size(); ++i) { + const auto& var = dependents[i]; + std::stringstream regexStr; + regexStr << "x\\[" << i << "\\]|@" << i; + std::regex regex(regexStr.str()); + std::string replacement = var->GetName(); + formula_str = std::regex_replace(formula_str, regex, replacement); + } + return formula_str; + } + std::string getFunctionStrRepr(RooFormulaVar &formula_var){ + // + const std::string formula_str = getReconstructedFormulaStr(formula_var.formula()); + std::string ret = formatFunctionStr(formula_var.ClassName(), formula_var.GetName(), formula_str ); + return ret; + } + #else + std::string getFunctionStrRepr(RooFormulaVar &formula_var){ + // + std::string formula_str = formula_var.expression(); + const RooArgSet dependents = formula_var.dependents(); + for (unsigned int i = 0; i < dependents.size(); ++i) { + const auto& var = dependents[i]; + std::stringstream regexStr; + regexStr << "x\\[" << i << "\\]|@" << i; + std::regex regex(regexStr.str()); + std::string replacement = var->GetName(); + formula_str = std::regex_replace(formula_str, regex, replacement); + } + std::string ret = formatFunctionStr(formula_var.ClassName(), formula_var.GetName(), formula_str ); + return ret; + } + #endif std::string getFunctionStrRepr(RooProduct &product_func){ const RooArgList components = product_func.components(); std::string formula_str = ""; @@ -131,8 +149,8 @@ namespace RooFitExt{ std::string getCorrectPrintArgs(RooFormulaVar& arg){ std::string dependent_str = ""; - std::string formula_str = arg.formula().formulaString(); - const RooArgSet dependents = arg.formula().actualDependents(); + std::string formula_str = arg.expression(); + const RooArgSet dependents = arg.dependents(); unsigned int n_dependent = dependents.size(); for (unsigned int i = 0; i < n_dependent; ++i) { const auto& var = dependents[i]; diff --git a/quickstats/macros/QuickStatsCore/RooFitExt.h b/quickstats/macros/QuickStatsCore/RooFitExt.h index 2f95383eb2bef4d054f81c45918b0fbcc07f4c61..ae34de2cfd1734232b5f27eaef670870efa4654f 100644 --- a/quickstats/macros/QuickStatsCore/RooFitExt.h +++ b/quickstats/macros/QuickStatsCore/RooFitExt.h @@ -15,12 +15,15 @@ #include "RooProdPdf.h" #include "RooProduct.h" #include "RooDataSet.h" -#include "RooFormula.h" #include "RooFormulaVar.h" #include "RooPrintable.h" #include "RooListProxy.h" #include "RooHistFunc.h" #include "RooStats/HistFactory/FlexibleInterpVar.h" +#include "RVersion.h" +#if ROOT_VERSION_CODE < ROOT_VERSION(6,29,02) + #include "RooFormula.h" +#endif namespace RooFitExt{ @@ -64,7 +67,9 @@ namespace RooFitExt{ const std::vector<std::string>constrPdfClsList=kConstrPdfClsList, int recursion_count=0, const int& recursion_limit=50, const bool &stripDisconnected=false); - std::string getReconstructedFormulaStr(const RooFormula &formula); + #if ROOT_VERSION_CODE < ROOT_VERSION(6,29,02) + std::string getReconstructedFormulaStr(const RooFormula &formula); + #endif std::string getFunctionStrRepr(RooFormulaVar &formula_var); std::string getFunctionStrRepr(RooProduct &product_func); std::string getCorrectPrintArgs(RooHistFunc& arg); diff --git a/setup.sh b/setup.sh index d7a0d20aeaa7a7caeb698de2c84e93fbfb7487b5..41eb974456a570f9726e562f9fe4a0d6b2485490 100644 --- a/setup.sh +++ b/setup.sh @@ -29,8 +29,7 @@ ulimit -S -s unlimited if [ "$EnvironmentName" = "default" ]; #Default is python3 then setupATLAS - #lsetup "views LCG_101 x86_64-centos7-gcc8-opt" - lsetup "views LCG_102a x86_64-centos7-gcc11-opt" + lsetup "views LCG_102a x86_64-centos7-gcc11-opt" export PATH=${DIR}/bin:${PATH} export PYTHONPATH=${DIR}:${PYTHONPATH} elif [[ "$EnvironmentName" = "dev" ]]; diff --git a/tests/correct_RooFormulaVar.ipynb b/tests/correct_RooFormulaVar.ipynb new file mode 100644 index 0000000000000000000000000000000000000000..3ee5c49a90b28e83611d72736e5c87fd21824ec0 --- /dev/null +++ b/tests/correct_RooFormulaVar.ipynb @@ -0,0 +1,191 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 1, + "metadata": { + "execution": { + "iopub.execute_input": "2024-02-02T21:51:21.020023Z", + "iopub.status.busy": "2024-02-02T21:51:21.019666Z", + "iopub.status.idle": "2024-02-02T21:51:26.402268Z", + "shell.execute_reply": "2024-02-02T21:51:26.401846Z" + } + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Welcome to JupyROOT 6.26/08\n", + "\n", + "\u001b[1mRooFit v3.60 -- Developed by Wouter Verkerke and David Kirkby\u001b[0m \n", + " Copyright (C) 2000-2013 NIKHEF, University of California & Stanford University\n", + " All rights reserved, please read http://roofit.sourceforge.net/license.txt\n", + "\n", + "[INFO] Set stack size to unlimited\n", + "[INFO] Loaded extension module \"RooTwoSidedCBShape\"\n", + "[INFO] Loaded extension module \"ResponseFunction\"\n", + "\n", + "RooWorkspace(original) original contents\n", + "\n", + "variables\n", + "---------\n", + "(cate_orig,mean,sigma,x,y)\n", + "\n", + "p.d.f.s\n", + "-------\n", + "RooGaussian::gauss_pdf[ x=formula_var mean=mean sigma=sigma ] = 1\n", + "RooSimultaneous::pdf_orig[ indexCat=cate_orig cat=gauss_pdf ] = 1\n", + "\n", + "functions\n", + "--------\n", + "RooFormulaVar::formula_var[ actualVars=(x,y) formula=\"x+y\" ] = 0\n", + "\n", + "named sets\n", + "----------\n", + "ModelConfig_NuisParams:(mean,sigma,y)\n", + "\n", + "generic objects\n", + "---------------\n", + "RooStats::ModelConfig::ModelConfig\n", + "\n" + ] + } + ], + "source": [ + "import ROOT\n", + "from quickstats.components.workspaces import XMLWSModifier\n", + "\n", + "ws_orig = ROOT.RooWorkspace('original')\n", + "\n", + "x = ROOT.RooRealVar(\"x\", \"x\", -10, 10)\n", + "y = ROOT.RooRealVar(\"y\", \"y\", -10, 10)\n", + "formula_var = ROOT.RooFormulaVar(\"formula_var\", \"x+y\", ROOT.RooArgList(x, y))\n", + "\n", + "mean = ROOT.RooRealVar(\"mean\", \"Mean of Gaussian\", 0, -10, 10)\n", + "sigma = ROOT.RooRealVar(\"sigma\", \"Width of Gaussian\", 1, 0.1, 10)\n", + "gauss_pdf = ROOT.RooGaussian(\"gauss_pdf\", \"Gaussian PDF\", formula_var, mean, sigma)\n", + "cate_orig = ROOT.RooCategory(\"cate_orig\", \"cate_orig\")\n", + "cate_orig.defineType(\"cat\")\n", + "pdf_orig = ROOT.RooSimultaneous(\"pdf_orig\", \"Simultaneous PDF\", cate_orig)\n", + "pdf_orig.addPdf(gauss_pdf, \"cat\")\n", + "\n", + "mc_orig = ROOT.RooStats.ModelConfig(\"ModelConfig\", ws_orig)\n", + "mc_orig.SetPdf(pdf_orig)\n", + "mc_orig.SetNuisanceParameters(ROOT.RooArgSet(mean, sigma, y))\n", + "ws_orig.Import(mc_orig)\n", + "\n", + "\n", + "modifier = XMLWSModifier(source={})\n", + "rename_map = {'y': 'y_new'}\n", + "\n", + "ws_orig.Print()" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": { + "execution": { + "iopub.execute_input": "2024-02-02T21:51:26.473523Z", + "iopub.status.busy": "2024-02-02T21:51:26.413290Z", + "iopub.status.idle": "2024-02-02T21:51:26.580145Z", + "shell.execute_reply": "2024-02-02T21:51:26.579818Z" + } + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[INFO] Renamed variables\n", + "\n", + " \u001b[91my\u001b[0m -> \u001b[92my\u001b[0m_new\n", + "\n", + "RooWorkspace(final1) final1 contents\n", + "\n", + "variables\n", + "---------\n", + "(cate_orig,mean,sigma,x,y_new)\n", + "\n", + "p.d.f.s\n", + "-------\n", + "RooGaussian::gauss_pdf[ x=formula_var mean=mean sigma=sigma ] = 1\n", + "RooSimultaneous::pdf_orig[ indexCat=cate_orig cat=gauss_pdf ] = 1\n", + "\n", + "functions\n", + "--------\n", + "RooFormulaVar::formula_var[ actualVars=(x,y_new) formula=\"x+y\" ] = 0\n", + "\n" + ] + } + ], + "source": [ + "ws_final1 = ROOT.RooWorkspace('final1')\n", + "modifier.rename_variables(mc_orig, ws_final1, rename_map)\n", + "ws_final1.Print()" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": { + "execution": { + "iopub.execute_input": "2024-02-02T21:51:26.603926Z", + "iopub.status.busy": "2024-02-02T21:51:26.582101Z", + "iopub.status.idle": "2024-02-02T21:51:26.822351Z", + "shell.execute_reply": "2024-02-02T21:51:26.822635Z" + } + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[INFO] Renamed variables\n", + "\n", + " \u001b[91my\u001b[0m -> \u001b[92my\u001b[0m_new\n", + "\n", + "RooWorkspace(final) final contents\n", + "\n", + "variables\n", + "---------\n", + "(cate_orig,mean,sigma,x,y_new)\n", + "\n", + "p.d.f.s\n", + "-------\n", + "RooGaussian::gauss_pdf[ x=formula_var mean=mean sigma=sigma ] = 1\n", + "RooSimultaneous::pdf_orig[ indexCat=cate_orig cat=gauss_pdf ] = 1\n", + "\n", + "functions\n", + "--------\n", + "RooFormulaVar::formula_var[ actualVars=(x,y_new) formula=\"@0+@1\" ] = 0\n", + "\n" + ] + } + ], + "source": [ + "ws_final2 = ROOT.RooWorkspace('final')\n", + "modifier.correct_formula(ws_orig, ws_final2, rename_map)\n", + "modifier.rename_variables(mc_orig, ws_final2, rename_map)\n", + "ws_final2.Print()" + ] + } + ], + "metadata": { + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.9.12" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/tests/cpp/Print_RooFormulaVar.cxx b/tests/cpp/Print_RooFormulaVar.cxx new file mode 100644 index 0000000000000000000000000000000000000000..6cf17fb51f371c45caebdce93f12d4c9f8b001c0 --- /dev/null +++ b/tests/cpp/Print_RooFormulaVar.cxx @@ -0,0 +1,54 @@ +#include <RooRealVar.h> +#include <RooFormulaVar.h> +#include <RooArgSet.h> +#include <iostream> +#include <string> + +std::string formatFunctionStr(const std::string class_name, const std::string name, + const std::string formula_str){ + std::string ret = class_name + "::" + name + "[ " + formula_str + " ]"; + return ret; +} +std::string getFunctionStrRepr(RooFormulaVar &formula_var){ + // + std::string formula_str = formula_var.expression(); + const RooArgSet dependents = formula_var.dependents(); + for (unsigned int i = 0; i < dependents.size(); ++i) { + const auto& var = dependents[i]; + std::stringstream regexStr; + regexStr << "x\\[" << i << "\\]|@" << i; + std::regex regex(regexStr.str()); + std::string replacement = var->GetName(); + formula_str = std::regex_replace(formula_str, regex, replacement); + } + std::string ret = formatFunctionStr(formula_var.ClassName(), formula_var.GetName(), formula_str ); + return ret; +} + +int Print_RooFormulaVar() { + RooRealVar x("x", "Variable x", 1.0); + RooRealVar y("y", "Variable y", 2.0); + + std::string formulaStr = "@0+@1"; + + RooFormulaVar formulaVar("formulaVar", "Test Formula", formulaStr.c_str(), RooArgSet(x, y)); + + std::string result = getFunctionStrRepr(formulaVar); + std::cout << "Reconstructed Formula String: " << result << std::endl; + + formulaStr = "x[0]+x[1]"; + + RooFormulaVar formulaVar1("formulaVar", "Test Formula", formulaStr.c_str(), RooArgSet(x, y)); + + result = getFunctionStrRepr(formulaVar1); + std::cout << "Reconstructed Formula String: " << result << std::endl; + + formulaStr = "x+y"; + + RooFormulaVar formulaVar2("formulaVar", "Test Formula", formulaStr.c_str(), RooArgSet(x, y)); + + result = getFunctionStrRepr(formulaVar2); + std::cout << "Reconstructed Formula String: " << result << std::endl; + + return 0; +} \ No newline at end of file