From 42afd58af1d7ca4d7485b61a420afc602c4b9f52 Mon Sep 17 00:00:00 2001 From: Jonas Rembser Date: Tue, 21 Apr 2026 11:18:49 +0200 Subject: [PATCH] [RF] Remove features that were deprecated in ROOT 6.40 Remove features that were deprecated in ROOT 6.40 and mention it in the 6.42 release notes. --- README/ReleaseNotes/v642/index.md | 16 + roofit/roofitcore/CMakeLists.txt | 2 - roofit/roofitcore/inc/RooAbsReal.h | 27 -- roofit/roofitcore/inc/RooErrorVar.h | 6 +- roofit/roofitcore/inc/RooGlobalFunc.h | 6 +- roofit/roofitcore/inc/RooMinimizer.h | 6 +- roofit/roofitcore/inc/RooRealVar.h | 7 +- roofit/roofitcore/src/FitHelpers.cxx | 123 ++---- roofit/roofitcore/src/FitHelpers.h | 3 +- roofit/roofitcore/src/RooAbsPdf.cxx | 6 - roofit/roofitcore/src/RooAbsReal.cxx | 90 ---- roofit/roofitcore/src/RooErrorVar.cxx | 8 - roofit/roofitcore/src/RooGlobalFunc.cxx | 8 +- roofit/roofitcore/src/RooMinimizer.cxx | 13 +- roofit/roofitcore/src/RooRealVar.cxx | 4 - roofit/roofitcore/src/RooXYChi2Var.cxx | 387 ------------------ roofit/roofitcore/src/RooXYChi2Var.h | 87 ---- roofit/roofitcore/test/stressRooFit.cxx | 1 - roofit/roofitcore/test/stressRooFit_tests.h | 71 ---- roofit/roofitcore/test/testTestStatistics.cxx | 61 --- roofit/roostats/CMakeLists.txt | 2 - roofit/roostats/inc/LinkDef.h | 1 - roofit/roostats/inc/RooStats/HybridPlot.h | 129 ------ roofit/roostats/inc/RooStats/HybridResult.h | 3 - roofit/roostats/src/HybridPlot.cxx | 370 ----------------- roofit/roostats/src/HybridResult.cxx | 33 -- 26 files changed, 73 insertions(+), 1397 deletions(-) delete mode 100644 roofit/roofitcore/src/RooXYChi2Var.cxx delete mode 100644 roofit/roofitcore/src/RooXYChi2Var.h delete mode 100644 roofit/roostats/inc/RooStats/HybridPlot.h delete mode 100644 roofit/roostats/src/HybridPlot.cxx diff --git a/README/ReleaseNotes/v642/index.md b/README/ReleaseNotes/v642/index.md index 561ca789851c0..fde7245cdb151 100644 --- a/README/ReleaseNotes/v642/index.md +++ b/README/ReleaseNotes/v642/index.md @@ -39,6 +39,10 @@ The following people have contributed to this new version: ## Deprecation and Removal +* The method `RooRealVar::removeRange()` and the corresponding method in `RooErrorVar` that were deprecated in ROOT 6.40 are now removed. +* The overloads of `RooAbsReal::createChi2()` and `RooAbsReal::chi2FitTo()` that take unbinned **RooDataSet** data objects were deprecated in ROOT 6.40 and are now removed. +* The **RooStats::HybridPlot** class and the related **HybridResult::GetPlot** method were deprecated in ROOT 6.40 and are now removed. + ## Python Interface ## I/O @@ -51,6 +55,18 @@ The following people have contributed to this new version: ## RooFit +### Removal of the the constant term optimization for legacy test statistic classes + +The **RooFit::Optimize()** option (constant term optimization) has been deprecated in ROOT 6.40 its functionality was now removed. +The `RooFit::Optimize()` and `RooMinimizer::optimizeConst()` methods are kept for API consistency across ROOT versions, but they have no effect anymore. + +This option only affected the `legacy` evaluation backend. + +The default vectorized CPU evaluation backend (introduced in ROOT 6.32) already performs these optimizations automatically and is not affected by this change. +Users are strongly encouraged to switch to the vectorized CPU backend if they are still using the legacy backend. + +If the vectorized backend does not work for a given use case, **please report it by opening an issue on the ROOT GitHub repository**. + ## Graphics and GUI ## Geometry diff --git a/roofit/roofitcore/CMakeLists.txt b/roofit/roofitcore/CMakeLists.txt index a638e0267b2d0..6bf5ab9289408 100644 --- a/roofit/roofitcore/CMakeLists.txt +++ b/roofit/roofitcore/CMakeLists.txt @@ -30,7 +30,6 @@ if(roofit_legacy_eval_backend) src/RooChi2Var.cxx src/RooNLLVar.cxx src/RooRealMPFE.cxx - src/RooXYChi2Var.cxx ) endif() @@ -471,7 +470,6 @@ ROOT_STANDARD_LIBRARY_PACKAGE(RooFitCore ) # The following definitions are PUBLIC so they can also be used in ROOT-internal tests -target_compile_definitions(RooFitCore PUBLIC ROOFIT_BUILDS_ITSELF) if(roofit_legacy_eval_backend) target_compile_definitions(RooFitCore PUBLIC ROOFIT_LEGACY_EVAL_BACKEND) diff --git a/roofit/roofitcore/inc/RooAbsReal.h b/roofit/roofitcore/inc/RooAbsReal.h index 9164031d6abfe..18ca28e276d5d 100644 --- a/roofit/roofitcore/inc/RooAbsReal.h +++ b/roofit/roofitcore/inc/RooAbsReal.h @@ -192,33 +192,6 @@ class RooAbsReal : public RooAbsArg { return RooFit::makeOwningPtr(createChi2Impl(data, *RooFit::Detail::createCmdList(&cmdArgs...))); } - // Chi^2 fits to X-Y datasets - virtual RooFit::OwningPtr chi2FitTo(RooDataSet& xydata, const RooCmdArg& arg1={}, const RooCmdArg& arg2={}, - const RooCmdArg& arg3={}, const RooCmdArg& arg4={}, const RooCmdArg& arg5={}, - const RooCmdArg& arg6={}, const RooCmdArg& arg7={}, const RooCmdArg& arg8={}) -#ifndef ROOFIT_BUILDS_ITSELF - R__DEPRECATED(6, 42, "To fit 2D data with errors in and `x` and `y`, use specialized tools like TGraphErrors::Fit(), or build an explicit likelihood model with RooFit.") -#endif -; - virtual RooFit::OwningPtr chi2FitTo(RooDataSet& xydata, const RooLinkedList& cmdList) -#ifndef ROOFIT_BUILDS_ITSELF - R__DEPRECATED(6, 42, "To fit 2D data with errors in and `x` and `y`, use specialized tools like TGraphErrors::Fit(), or build an explicit likelihood model with RooFit.") -#endif -; - - virtual RooFit::OwningPtr createChi2(RooDataSet& data, const RooLinkedList& cmdList) -#ifndef ROOFIT_BUILDS_ITSELF - R__DEPRECATED(6, 42, "To fit 2D data with errors in and `x` and `y`, use specialized tools like TGraphErrors::Fit(), or build an explicit likelihood model with RooFit.") -#endif -; - virtual RooFit::OwningPtr createChi2(RooDataSet& data, const RooCmdArg& arg1={}, const RooCmdArg& arg2={}, - const RooCmdArg& arg3={}, const RooCmdArg& arg4={}, const RooCmdArg& arg5={}, - const RooCmdArg& arg6={}, const RooCmdArg& arg7={}, const RooCmdArg& arg8={}) -#ifndef ROOFIT_BUILDS_ITSELF - R__DEPRECATED(6, 42, "To fit 2D data with errors in and `x` and `y`, use specialized tools like TGraphErrors::Fit(), or build an explicit likelihood model with RooFit.") -#endif -; - virtual RooFit::OwningPtr createProfile(const RooArgSet& paramsOfInterest) ; diff --git a/roofit/roofitcore/inc/RooErrorVar.h b/roofit/roofitcore/inc/RooErrorVar.h index 2b35f8be518a1..dd10d27319ed2 100644 --- a/roofit/roofitcore/inc/RooErrorVar.h +++ b/roofit/roofitcore/inc/RooErrorVar.h @@ -83,11 +83,7 @@ class RooErrorVar : public RooAbsRealLValue { // Set infinite fit range limits void removeMin(const char* name=nullptr); - void removeMax(const char* name=nullptr); - void removeRange(const char *name = nullptr) - R__DEPRECATED(6, 42, - "\"removeRange\" was a misleading name." - " Please use \"removeMin()\" and \"removeMax()\" instead, for the same effect."); + void removeMax(const char *name = nullptr); using RooAbsRealLValue::operator= ; using RooAbsRealLValue::setVal ; diff --git a/roofit/roofitcore/inc/RooGlobalFunc.h b/roofit/roofitcore/inc/RooGlobalFunc.h index 1a8f22a138445..5232b00b7f2ea 100644 --- a/roofit/roofitcore/inc/RooGlobalFunc.h +++ b/roofit/roofitcore/inc/RooGlobalFunc.h @@ -253,11 +253,7 @@ RooCmdArg IntegrateBins(double precision); // RooAbsPdf::fitTo arguments RooCmdArg PrefitDataFraction(double data_ratio = 0.0) ; -RooCmdArg Optimize(Int_t flag=2) -#ifndef ROOFIT_BUILDS_ITSELF - R__DEPRECATED(6, 42, "Please use the default \"cpu\" likelihood evaluation backend if you want all optimizations.") -#endif - ; +RooCmdArg Optimize(Int_t flag = 2); class EvalBackend : public RooCmdArg { public: diff --git a/roofit/roofitcore/inc/RooMinimizer.h b/roofit/roofitcore/inc/RooMinimizer.h index fcf2dfe960a64..facb7d81de74a 100644 --- a/roofit/roofitcore/inc/RooMinimizer.h +++ b/roofit/roofitcore/inc/RooMinimizer.h @@ -145,11 +145,7 @@ class RooMinimizer : public TObject { void setPrintLevel(int newLevel); // Setters on _fcn - void optimizeConst(int flag) -#ifndef ROOFIT_BUILDS_ITSELF - R__DEPRECATED(6, 42, "Please use the default \"cpu\" likelihood evaluation backend if you want all optimizations.") -#endif - ; + void optimizeConst(int flag); void setEvalErrorWall(bool flag) { _cfg.doEEWall = flag; } void setRecoverFromNaNStrength(double strength); void setOffsetting(bool flag); diff --git a/roofit/roofitcore/inc/RooRealVar.h b/roofit/roofitcore/inc/RooRealVar.h index 971c5b906d7ae..82d4498c20f4b 100644 --- a/roofit/roofitcore/inc/RooRealVar.h +++ b/roofit/roofitcore/inc/RooRealVar.h @@ -98,12 +98,7 @@ class RooRealVar : public RooAbsRealLValue { /// Remove lower range limit for binning with given name. Empty name means default range. void removeMin(const char* name=nullptr); /// Remove upper range limit for binning with given name. Empty name means default range. - void removeMax(const char* name=nullptr); - /// Remove range limits for binning with given name. Empty name means default range. - void removeRange(const char* name=nullptr) - R__DEPRECATED(6, 42, - "\"removeRange\" was a misleading name." - " Please use \"removeMin()\" and \"removeMax()\" instead, for the same effect."); + void removeMax(const char *name = nullptr); // I/O streaming interface (machine readable) bool readFromStream(std::istream& is, bool compact, bool verbose=false) override ; diff --git a/roofit/roofitcore/src/FitHelpers.cxx b/roofit/roofitcore/src/FitHelpers.cxx index d8aed33788cab..3b3df1f873586 100644 --- a/roofit/roofitcore/src/FitHelpers.cxx +++ b/roofit/roofitcore/src/FitHelpers.cxx @@ -48,7 +48,6 @@ #ifdef ROOFIT_LEGACY_EVAL_BACKEND #include "RooChi2Var.h" #include "RooNLLVar.h" -#include "RooXYChi2Var.h" #endif using RooFit::Detail::RooNLLVarNew; @@ -921,11 +920,9 @@ std::unique_ptr createNLL(RooAbsPdf &pdf, RooAbsData &data, const Ro return nll; } -std::unique_ptr createChi2(RooAbsReal &real, RooAbsData &data, const RooLinkedList &cmdList) +std::unique_ptr createChi2(RooAbsReal &real, RooDataHist &data, const RooLinkedList &cmdList) { #ifdef ROOFIT_LEGACY_EVAL_BACKEND - const bool isDataHist = dynamic_cast(&data); - RooCmdConfig pc("createChi2(" + std::string(real.GetName()) + ")"); pc.defineInt("numcpu", "NumCPU", 0, 1); @@ -934,92 +931,53 @@ std::unique_ptr createChi2(RooAbsReal &real, RooAbsData &data, const RooAbsTestStatistic::Configuration cfg; - if (isDataHist) { - // Construct Chi2 - RooAbsReal::setEvalErrorLoggingMode(RooAbsReal::CollectErrors); - std::string baseName = "chi2_" + std::string(real.GetName()) + "_" + data.GetName(); - - // Clear possible range attributes from previous fits. - real.removeStringAttribute("fitrange"); - - pc.defineInt("etype", "DataError", 0, (Int_t)RooDataHist::Auto); - pc.defineInt("extended", "Extended", 0, extendedFitDefault); - pc.defineInt("split_range", "SplitRange", 0, 0); - pc.defineDouble("integrate_bins", "IntegrateBins", 0, -1); - pc.defineString("addCoefRange", "SumCoefRange", 0, ""); - pc.allowUndefined(); - - pc.process(cmdList); - if (!pc.ok(true)) { - return nullptr; - } - - bool extended = false; - if (auto pdf = dynamic_cast(&real)) { - extended = interpretExtendedCmdArg(*pdf, pc.getInt("extended")); - } + // Construct Chi2 + RooAbsReal::setEvalErrorLoggingMode(RooAbsReal::CollectErrors); + std::string baseName = "chi2_" + std::string(real.GetName()) + "_" + data.GetName(); - RooDataHist::ErrorType etype = static_cast(pc.getInt("etype")); + // Clear possible range attributes from previous fits. + real.removeStringAttribute("fitrange"); - const char *rangeName = pc.getString("rangeName", nullptr, true); - const char *addCoefRangeName = pc.getString("addCoefRange", nullptr, true); - int splitRange = pc.getInt("splitRange"); + pc.defineInt("etype", "DataError", 0, (Int_t)RooDataHist::Auto); + pc.defineInt("extended", "Extended", 0, extendedFitDefault); + pc.defineInt("split_range", "SplitRange", 0, 0); + pc.defineDouble("integrate_bins", "IntegrateBins", 0, -1); + pc.defineString("addCoefRange", "SumCoefRange", 0, ""); + pc.allowUndefined(); - // Set the fitrange attribute of th PDF, add observables ranges for plotting - resetFitrangeAttributes(real, data, baseName, rangeName, splitRange); + pc.process(cmdList); + if (!pc.ok(true)) { + return nullptr; + } - cfg.rangeName = rangeName ? rangeName : ""; - cfg.nCPU = pc.getInt("numcpu"); - cfg.interleave = RooFit::Interleave; - cfg.verbose = static_cast(pc.getInt("verbose")); - cfg.cloneInputData = false; - cfg.integrateOverBinsPrecision = pc.getDouble("integrate_bins"); - cfg.addCoefRangeName = addCoefRangeName ? addCoefRangeName : ""; - cfg.splitCutRange = static_cast(splitRange); - auto chi2 = std::make_unique(baseName.c_str(), baseName.c_str(), real, - static_cast(data), extended, etype, cfg); + bool extended = false; + if (auto pdf = dynamic_cast(&real)) { + extended = interpretExtendedCmdArg(*pdf, pc.getInt("extended")); + } - RooAbsReal::setEvalErrorLoggingMode(RooAbsReal::PrintErrors); + RooDataHist::ErrorType etype = static_cast(pc.getInt("etype")); - return chi2; - } else { - pc.defineInt("integrate", "Integrate", 0, 0); - pc.defineObject("yvar", "YVar", 0, nullptr); - pc.defineInt("interleave", "NumCPU", 1, 0); - - // Process and check varargs - pc.process(cmdList); - if (!pc.ok(true)) { - return nullptr; - } + const char *rangeName = pc.getString("rangeName", nullptr, true); + const char *addCoefRangeName = pc.getString("addCoefRange", nullptr, true); + int splitRange = pc.getInt("splitRange"); - // Decode command line arguments - bool integrate = pc.getInt("integrate"); - RooRealVar *yvar = static_cast(pc.getObject("yvar")); - const char *rangeName = pc.getString("rangeName", nullptr, true); - Int_t numcpu = pc.getInt("numcpu"); - Int_t numcpu_strategy = pc.getInt("interleave"); - // strategy 3 works only for RooSimultaneous. - if (numcpu_strategy == 3 && !real.InheritsFrom("RooSimultaneous")) { - oocoutW(&real, Minimization) << "Cannot use a NumCpu Strategy = 3 when the pdf is not a RooSimultaneous, " - "falling back to default strategy = 0" - << std::endl; - numcpu_strategy = 0; - } - RooFit::MPSplit interl = (RooFit::MPSplit)numcpu_strategy; - bool verbose = pc.getInt("verbose"); + // Set the fitrange attribute of th PDF, add observables ranges for plotting + resetFitrangeAttributes(real, data, baseName, rangeName, splitRange); - cfg.rangeName = rangeName ? rangeName : ""; - cfg.nCPU = numcpu; - cfg.interleave = interl; - cfg.verbose = verbose; - cfg.verbose = false; + cfg.rangeName = rangeName ? rangeName : ""; + cfg.nCPU = pc.getInt("numcpu"); + cfg.interleave = RooFit::Interleave; + cfg.verbose = static_cast(pc.getInt("verbose")); + cfg.cloneInputData = false; + cfg.integrateOverBinsPrecision = pc.getDouble("integrate_bins"); + cfg.addCoefRangeName = addCoefRangeName ? addCoefRangeName : ""; + cfg.splitCutRange = static_cast(splitRange); + auto chi2 = std::make_unique(baseName.c_str(), baseName.c_str(), real, static_cast(data), + extended, etype, cfg); - std::string name = "chi2_" + std::string(real.GetName()) + "_" + data.GetName(); + RooAbsReal::setEvalErrorLoggingMode(RooAbsReal::PrintErrors); - return std::make_unique(name.c_str(), name.c_str(), real, static_cast(data), yvar, - integrate, cfg); - } + return chi2; #else throw std::runtime_error("createChi2() is not supported without the legacy evaluation backend"); return nullptr; @@ -1109,8 +1067,9 @@ std::unique_ptr fitTo(RooAbsReal &real, RooAbsData &data, const Ro std::unique_ptr nll; if (chi2) { - nll = std::unique_ptr{isDataHist ? real.createChi2(static_cast(data), nllCmdList) - : real.createChi2(static_cast(data), nllCmdList)}; + if (isDataHist) { + nll = std::unique_ptr{real.createChi2(static_cast(data), nllCmdList)}; + } } else { nll = std::unique_ptr{dynamic_cast(real).createNLL(data, nllCmdList)}; } diff --git a/roofit/roofitcore/src/FitHelpers.h b/roofit/roofitcore/src/FitHelpers.h index bfad9f03e7127..7e6c1a6a5fc96 100644 --- a/roofit/roofitcore/src/FitHelpers.h +++ b/roofit/roofitcore/src/FitHelpers.h @@ -18,6 +18,7 @@ #include class RooAbsData; +class RooDataHist; class RooAbsPdf; class RooAbsReal; class RooCmdConfig; @@ -32,7 +33,7 @@ void defineMinimizationOptions(RooCmdConfig &pc); std::unique_ptr minimize(RooAbsReal &model, RooAbsReal &nll, RooAbsData const &data, RooCmdConfig const &pc); std::unique_ptr createNLL(RooAbsPdf &pdf, RooAbsData &data, const RooLinkedList &cmdList); -std::unique_ptr createChi2(RooAbsReal &real, RooAbsData &data, const RooLinkedList &cmdList); +std::unique_ptr createChi2(RooAbsReal &real, RooDataHist &data, const RooLinkedList &cmdList); std::unique_ptr fitTo(RooAbsReal &pdf, RooAbsData &data, const RooLinkedList &cmdList, bool chi2); diff --git a/roofit/roofitcore/src/RooAbsPdf.cxx b/roofit/roofitcore/src/RooAbsPdf.cxx index 7aad2f55d3b9f..aea212e2d3e60 100644 --- a/roofit/roofitcore/src/RooAbsPdf.cxx +++ b/roofit/roofitcore/src/RooAbsPdf.cxx @@ -867,9 +867,6 @@ double RooAbsPdf::extendedTerm(RooAbsData const& data, bool weightSquared, bool * **codegen_no_grad** **Experimental** - Same as **codegen**, but doesn't generate and compile the gradient code and use the regular numerical differentiation instead. * This is expected to be slower, but useful for debugging problems with the analytic gradient. * - * `Optimize(bool flag)` Activate constant term optimization. - * Only relevant for `legacy` evaluation backend and off by default, as the default `cpu` backend already includes this optimization unconditionally. - * \warning Deprecated option that will be removed in ROOT 6.42! * `SplitRange(bool flag)` Use separate fit ranges in a simultaneous fit. Actual range name for each subsample is assumed to * be `rangeName_indexState`, where `indexState` is the state of the master index category of the simultaneous fit. * Using `Range("range"), SplitRange()` as switches, different ranges could be set like this: @@ -980,9 +977,6 @@ std::unique_ptr RooAbsPdf::createNLLImpl(RooAbsData &data, const Roo * * * `InitialHesse(bool flag)` Flag controls if HESSE before MIGRAD as well, off by default - * `Optimize(bool flag)` Activate constant term optimization of test statistic during minimization. - * Only relevant for `legacy` evaluation backend and off by default, as the default `cpu` backend already includes this optimization unconditionally. - * \warning Deprecated option that will be removed in ROOT 6.42! * `Hesse(bool flag)` Flag controls if HESSE is run after MIGRAD, on by default * `Minos(bool flag)` Flag controls if MINOS is run after HESSE, off by default * `Minos(const RooArgSet& set)` Only run MINOS on given subset of arguments diff --git a/roofit/roofitcore/src/RooAbsReal.cxx b/roofit/roofitcore/src/RooAbsReal.cxx index b6e5a1f901749..03a3c5c42b81b 100644 --- a/roofit/roofitcore/src/RooAbsReal.cxx +++ b/roofit/roofitcore/src/RooAbsReal.cxx @@ -3979,9 +3979,6 @@ double RooAbsReal::findRoot(RooRealVar& x, double xmin, double xmax, double yval /// `Range(double lo, double hi)` Fit only data inside given range. A range named "fit" is created on the fly on all observables. /// Multiple comma separated range names can be specified. /// `NumCPU(int num)` Parallelize NLL calculation on num CPUs -/// `Optimize(bool flag)` Activate constant term optimization. -/// Only relevant for `legacy` evaluation backend and off by default, as the default `cpu` backend already includes this optimization unconditionally. -/// \warning Deprecated option that will be removed in ROOT 6.42! /// `IntegrateBins()` Integrate PDF within each bin. This sets the desired precision. /// `Verbose()` Verbose output of GOF framework /// `SumCoefRange()` Set the range in which to interpret the coefficients of RooAddPdf components @@ -4067,93 +4064,6 @@ std::unique_ptr RooAbsReal::createChi2Impl(RooDataHist& data, const return RooFit::FitHelpers::createChi2(*this, data, cmdList); } -//////////////////////////////////////////////////////////////////////////////// -/// Perform a 2-D \f$ \chi^2 \f$ fit using a series of x and y values stored in the dataset `xydata`. -/// The y values can either be the event weights, or can be another column designated -/// by the YVar() argument. The y value must have errors defined for the \f$ \chi^2 \f$ to -/// be well defined. -/// -/// -///
Options to control construction of the chi-square -///
`YVar(RooRealVar& yvar)` Designate given column in dataset as Y value -///
`Integrate(bool flag)` Integrate function over range specified by X errors -/// rather than take value at bin center. -/// -///
Options to control flow of fit procedure -///
`InitialHesse(bool flag)` Flag controls if HESSE before MIGRAD as well, off by default -///
`Hesse(bool flag)` Flag controls if HESSE is run after MIGRAD, on by default -///
`Minos(bool flag)` Flag controls if MINOS is run after HESSE, on by default -///
`Minos(const RooArgSet& set)` Only run MINOS on given subset of arguments -///
`Save(bool flag)` Flag controls if RooFitResult object is produced and returned, off by default -///
`Strategy(Int_t flag)` Set Minuit strategy (0 through 2, default is 1) -/// -///
Options to control informational output -///
`Verbose(bool flag)` Flag controls if verbose output is printed (NLL, parameter changes during fit -///
`Timer(bool flag)` Time CPU and wall clock consumption of fit steps, off by default -///
`PrintLevel(Int_t level)` Set Minuit print level (-1 through 3, default is 1). At -1 all RooFit informational -/// messages are suppressed as well -///
`Warnings(bool flag)` Enable or disable MINUIT warnings (enabled by default) -///
`PrintEvalErrors(Int_t numErr)` Control number of p.d.f evaluation errors printed per likelihood evaluation. A negative -/// value suppress output completely, a zero value will only print the error count per p.d.f component, -/// a positive value is will print details of each error up to numErr messages per p.d.f component. -///
-/// -/// \deprecated Will be removed in ROOT 6.42. To fit 2D data with errors in and `x` and `y`, use specialized tools like TGraphErrors::Fit(), or build an explicit likelihood model with RooFit. - -RooFit::OwningPtr RooAbsReal::chi2FitTo(RooDataSet& xydata, const RooCmdArg& arg1, const RooCmdArg& arg2, - const RooCmdArg& arg3, const RooCmdArg& arg4, const RooCmdArg& arg5, - const RooCmdArg& arg6, const RooCmdArg& arg7, const RooCmdArg& arg8) -{ - CREATE_CMD_LIST; - return chi2FitTo(xydata,l) ; -} - - -//////////////////////////////////////////////////////////////////////////////// -/// \copydoc RooAbsReal::chi2FitTo(RooDataSet&,const RooCmdArg&,const RooCmdArg&,const RooCmdArg&,const RooCmdArg&,const RooCmdArg&,const RooCmdArg&,const RooCmdArg&,const RooCmdArg&) - -RooFit::OwningPtr RooAbsReal::chi2FitTo(RooDataSet &xydata, const RooLinkedList &cmdList) -{ - return RooFit::makeOwningPtr(RooFit::FitHelpers::fitTo(*this, xydata, cmdList, true)); -} - - -//////////////////////////////////////////////////////////////////////////////// -/// Create a \f$ \chi^2 \f$ from a series of x and y values stored in a dataset. -/// The y values can either be the event weights (default), or can be another column designated -/// by the YVar() argument. The y value must have errors defined for the \f$ \chi^2 \f$ to -/// be well defined. -/// -/// The following named arguments are supported -/// -/// | | Options to control construction of the \f$ \chi^2 \f$ -/// |-|----------------------------------------- -/// | `YVar(RooRealVar& yvar)` | Designate given column in dataset as Y value -/// | `Integrate(bool flag)` | Integrate function over range specified by X errors rather than take value at bin center. -/// -/// \deprecated Will be removed in ROOT 6.42. To fit 2D data with errors in and `x` and `y`, use specialized tools like TGraphErrors::Fit(), or build an explicit likelihood model with RooFit. - -RooFit::OwningPtr RooAbsReal::createChi2(RooDataSet& data, const RooCmdArg& arg1, const RooCmdArg& arg2, - const RooCmdArg& arg3, const RooCmdArg& arg4, const RooCmdArg& arg5, - const RooCmdArg& arg6, const RooCmdArg& arg7, const RooCmdArg& arg8) -{ - CREATE_CMD_LIST; - return createChi2(data,l) ; -} - - -//////////////////////////////////////////////////////////////////////////////// -/// See RooAbsReal::createChi2(RooDataSet&,const RooCmdArg&,const RooCmdArg&,const RooCmdArg&,const RooCmdArg&,const RooCmdArg&,const RooCmdArg&,const RooCmdArg&,const RooCmdArg&) -/// -/// \deprecated Will be removed in ROOT 6.42. To fit 2D data with errors in and `x` and `y`, use specialized tools like TGraphErrors::Fit(), or build an explicit likelihood model with RooFit. - -RooFit::OwningPtr RooAbsReal::createChi2(RooDataSet &data, const RooLinkedList &cmdList) -{ - return RooFit::makeOwningPtr(RooFit::FitHelpers::createChi2(*this, data, cmdList)); -} - - - //////////////////////////////////////////////////////////////////////////////// /// Return current evaluation error logging mode. diff --git a/roofit/roofitcore/src/RooErrorVar.cxx b/roofit/roofitcore/src/RooErrorVar.cxx index 68c44a1173e5b..af83a963f229e 100644 --- a/roofit/roofitcore/src/RooErrorVar.cxx +++ b/roofit/roofitcore/src/RooErrorVar.cxx @@ -152,14 +152,6 @@ void RooErrorVar::removeMax(const char* name) { getBinning(name).setMax(RooNumber::infinity()) ; } - -/// Remove both upper and lower bounds from named binning, or -/// default binning if name is null -void RooErrorVar::removeRange(const char* name) { - getBinning(name).setRange(-RooNumber::infinity(),RooNumber::infinity()) ; -} - - //////////////////////////////////////////////////////////////////////////////// /// Store given binning with this variable under the given name diff --git a/roofit/roofitcore/src/RooGlobalFunc.cxx b/roofit/roofitcore/src/RooGlobalFunc.cxx index bc0422d3b7d19..1ed27e1a2d82c 100644 --- a/roofit/roofitcore/src/RooGlobalFunc.cxx +++ b/roofit/roofitcore/src/RooGlobalFunc.cxx @@ -636,9 +636,13 @@ RooCmdArg PrefitDataFraction(double data_ratio) { return RooCmdArg("Prefit", 0, 0, data_ratio, 0, nullptr, nullptr, nullptr, nullptr); } -RooCmdArg Optimize(Int_t flag) + +/// \deprecated Has no effect anymore. Functionality was removed in ROOT 6.42, +/// and this function is kept as an empty shell that does nothing (for API +/// compatibility between different ROOT versions). +RooCmdArg Optimize(Int_t /*flag*/) { - return RooCmdArg("Optimize", flag); + return RooCmdArg{}; } RooCmdArg Verbose(bool flag) { diff --git a/roofit/roofitcore/src/RooMinimizer.cxx b/roofit/roofitcore/src/RooMinimizer.cxx index 718a13880ac2b..b30f6cb5013d7 100644 --- a/roofit/roofitcore/src/RooMinimizer.cxx +++ b/roofit/roofitcore/src/RooMinimizer.cxx @@ -539,16 +539,11 @@ int RooMinimizer::getPrintLevel() } //////////////////////////////////////////////////////////////////////////////// -/// If flag is true, perform constant term optimization on -/// function being minimized. -/// -/// \deprecated Will be removed in ROOT 6.42, as this functionality only affects the legacy evalution backend. -/// The default `cpu` backend already includes this optimization unconditionally. +/// \deprecated Has no effect anymore. Functionality was removed in ROOT 6.42, +/// and this function is kept as an empty shell that does nothing (for API +/// compatibility between different ROOT versions). -void RooMinimizer::optimizeConst(int flag) -{ - _fcn->setOptimizeConst(flag); -} +void RooMinimizer::optimizeConst(int /*flag*/) {} //////////////////////////////////////////////////////////////////////////////// /// Save and return a RooFitResult snapshot of current minimizer status. diff --git a/roofit/roofitcore/src/RooRealVar.cxx b/roofit/roofitcore/src/RooRealVar.cxx index 6e15aca664d08..4eea5cbc85ff9 100644 --- a/roofit/roofitcore/src/RooRealVar.cxx +++ b/roofit/roofitcore/src/RooRealVar.cxx @@ -469,10 +469,6 @@ void RooRealVar::removeMin(const char* name) { void RooRealVar::removeMax(const char* name) { getBinning(name).setMax(RooNumber::infinity()); } -void RooRealVar::removeRange(const char* name) { - getBinning(name).setRange(-RooNumber::infinity(),RooNumber::infinity()); -} - //////////////////////////////////////////////////////////////////////////////// /// Create a uniform binning under name 'name' for this variable. diff --git a/roofit/roofitcore/src/RooXYChi2Var.cxx b/roofit/roofitcore/src/RooXYChi2Var.cxx deleted file mode 100644 index ef133614bc984..0000000000000 --- a/roofit/roofitcore/src/RooXYChi2Var.cxx +++ /dev/null @@ -1,387 +0,0 @@ -/// \cond ROOFIT_INTERNAL - -/***************************************************************************** - * Project: RooFit * - * Package: RooFitCore * - * @(#)root/roofitcore:$Id$ - * Authors: * - * WV, Wouter Verkerke, UC Santa Barbara, verkerke@slac.stanford.edu * - * DK, David Kirkby, UC Irvine, dkirkby@uci.edu * - * * - * Copyright (c) 2000-2005, Regents of the University of California * - * and Stanford University. All rights reserved. * - * * - * Redistribution and use in source and binary forms, * - * with or without modification, are permitted according to the terms * - * listed in LICENSE (http://roofit.sourceforge.net/license.txt) * - *****************************************************************************/ - -////////////////////////////////////////////////////////////////////////////// -/// \class RooXYChi2Var -/// RooXYChi2Var implements a simple chi^2 calculation from an unbinned -/// dataset with values x,y with errors on y (and optionally on x) and a function. -/// The function can be either a RooAbsReal, or an extended RooAbsPdf where -/// the function value is calculated as the probability density times the -/// expected number of events. -/// The chi^2 is calculated as -/// ``` -/// -/// / (Data[y]-) - func \+2 -/// Sum[point] | ------------------ | -/// \ Data[ErrY] / -/// ``` -/// - -#include "RooXYChi2Var.h" -#include "RooDataSet.h" -#include "RooAbsReal.h" - -#include "Riostream.h" - -#include "RooRealVar.h" - -#include "RooAbsDataStore.h" -#include "RooRealBinding.h" -#include "RooNumIntFactory.h" - -using std::endl; - -namespace { - RooAbsTestStatistic::Configuration makeRooAbsTestStatisticCfg() { - RooAbsTestStatistic::Configuration cfg; - cfg.verbose = false; - return cfg; - } -} - - -//////////////////////////////////////////////////////////////////////////////// -/// -/// RooXYChi2Var constructor with function and X-Y values dataset -/// -/// If the function is a pdf, it must be extendable. in this case, hhe value of -/// the function that defines the chi^2 in this form is takes as the p.d.f. -/// times the expected number of events -/// -/// An X-Y dataset is a weighted dataset with one or more observables X where the weight is interpreted -/// as the Y value and the weight error is interpreted as the Y value error. The weight must have an -/// non-zero error defined at each point for the chi^2 calculation to be meaningful. -/// -/// To store errors associated with the x and y values in a RooDataSet, call RooRealVar::setAttribute("StoreError") -/// on each X-type observable for which the error should be stored and add datapoints to the dataset as follows -/// -/// RooDataSet::add(xset,yval,yerr) where xset is the RooArgSet of x observables (with or without errors) and yval and yerr -/// are the double values that correspond to the Y and its error -/// - -RooXYChi2Var::RooXYChi2Var(const char *name, const char *title, RooAbsReal &func, RooDataSet &xydata, bool integrate) - : RooXYChi2Var{name, title, func, xydata, nullptr, integrate, makeRooAbsTestStatisticCfg()} -{ -} - -//////////////////////////////////////////////////////////////////////////////// -/// -/// RooXYChi2Var constructor with function and X-Y values dataset. -/// -/// If the function is a pdf, it must be extendable. in this case, hhe value of -/// the function that defines the chi^2 in this form is takes as the p.d.f. -/// times the expected number of events -/// -/// An X-Y dataset is a weighted dataset with one or more observables X where given yvar is interpreted -/// as the Y value. The Y variable must have a non-zero error defined at each point for the chi^2 calculation to be meaningful. -/// -/// To store errors associated with the x and y values in a RooDataSet, call RooRealVar::setAttribute("StoreError") -/// on each X-type observable for which the error should be stored and add datapoints to the dataset as follows -/// -/// RooDataSet::add(xset,yval,yerr) where xset is the RooArgSet of x observables (with or without errors) and yval and yerr -/// are the double values that correspond to the Y and its error -/// - -RooXYChi2Var::RooXYChi2Var(const char *name, const char *title, RooAbsReal &func, RooDataSet &xydata, RooRealVar &yvar, - bool integrate) - : RooXYChi2Var{name, title, func, xydata, &yvar, integrate, makeRooAbsTestStatisticCfg()} -{ -} - - -/// \cond ROOFIT_INTERNAL -// For internal use in RooAbsReal::createChi2(). -RooXYChi2Var::RooXYChi2Var(const char *name, const char *title, RooAbsReal &func, RooAbsData &data, RooRealVar *yvar, - bool integrate, RooAbsTestStatistic::Configuration const &cfg) - : RooAbsOptTestStatistic(name, title, func, data, RooArgSet(), cfg), - _integrate(integrate), - _intConfig(*defaultIntegratorConfig()) -{ - bool isPdf = dynamic_cast(&func) != nullptr; - - if (isPdf) { - auto &extPdf = static_cast(func); - if (!extPdf.canBeExtended()) { - throw std::runtime_error( - Form("RooXYChi2Var::RooXYChi2Var(%s) ERROR: Input p.d.f. must be extendable", GetName())); - } - } - - _extended = isPdf; - _yvar = yvar ? static_cast(_dataClone->get()->find(yvar->GetName())) : nullptr; - - initialize(); -} -/// \endcond ROOFIT_INTERNAL - - -//////////////////////////////////////////////////////////////////////////////// -/// Copy constructor - -RooXYChi2Var::RooXYChi2Var(const RooXYChi2Var &other, const char *name) - : RooAbsOptTestStatistic(other, name), - _extended(other._extended), - _integrate(other._integrate), - _yvar(other._yvar ? static_cast(_dataClone->get()->find(other._yvar->GetName())) : nullptr), - _intConfig(other._intConfig) -{ - - initialize() ; - -} - - -//////////////////////////////////////////////////////////////////////////////// -/// Common constructor initialization - -void RooXYChi2Var::initialize() -{ - // If this tests statistic is not a "Slave" in the RooAbsOptTestStatistic - // framework, it doesn't do any actual computation and no initialization is - // needed. It would not even work, because _funcObsSet would be a nullptr. - if(operMode() != Slave) return; - - for(RooAbsArg * arg : *_funcObsSet) { - if (auto* var = dynamic_cast(arg)) { - _rrvArgs.add(*var) ; - } - } - if (_yvar) { - _rrvArgs.add(*_yvar) ; - } - - // Define alternate numeric integrator configuration for bin integration - // We expect bin contents to very only very slowly so a non-adaptive - // Gauss-Kronrod integrator is expected to perform well (if RooFitMore is available) - _intConfig.setEpsRel(1e-7) ; - _intConfig.setEpsAbs(1e-7) ; -#ifdef R__HAS_MATHMORE - _intConfig.method1D().setLabel("RooGaussKronrodIntegrator1D") ; -#endif - _intConfig.methodND().setLabel("RooAdaptiveIntegratorND") ; - - initIntegrator() ; - -} - - - -//////////////////////////////////////////////////////////////////////////////// -/// Initialize bin content integrator - -void RooXYChi2Var::initIntegrator() -{ - if (!_funcInt) { - _funcInt = std::unique_ptr{_funcClone->createIntegral(_rrvArgs,_rrvArgs,_intConfig,"bin")}; - for(auto * x : static_range_cast(_rrvArgs)) { - _binList.push_back(&x->getBinning("bin",false,true)) ; - } - } - -} - - -RooXYChi2Var::~RooXYChi2Var() = default; - - -//////////////////////////////////////////////////////////////////////////////// -/// Calculate contribution to internal error due to error on 'x' coordinates -/// at point i - -double RooXYChi2Var::xErrorContribution(double ydata) const -{ - double ret(0) ; - - for(auto * var : static_range_cast(_rrvArgs)) { - - if (var->hasAsymError()) { - - // Get value at central X - double cxval = var->getVal() ; - double xerrLo = -var->getAsymErrorLo() ; - double xerrHi = var->getAsymErrorHi() ; - double xerr = (xerrLo+xerrHi)/2 ; - - // Get value at X-eps - var->setVal(cxval - xerr/100) ; - double fxmin = fy() ; - - // Get value at X+eps - var->setVal(cxval + xerr/100) ; - double fxmax = fy() ; - - // Calculate slope - double slope = (fxmax-fxmin)/(2*xerr/100.) ; - -// std::cout << "xerrHi = " << xerrHi << " xerrLo = " << xerrLo << " slope = " << slope << std::endl ; - - // Asymmetric X error, decide which one to use - if ((ydata>cxval && fxmax>fxmin) || (ydata<=cxval && fxmax<=fxmin)) { - // Use right X error - ret += pow(xerrHi*slope,2) ; - } else { - // Use left X error - ret += pow(xerrLo*slope,2) ; - } - - } else if (var->hasError()) { - - // Get value at central X - double cxval = var->getVal() ; - double xerr = var->getError() ; - - // Get value at X-eps - var->setVal(cxval - xerr/100) ; - double fxmin = fy() ; - - // Get value at X+eps - var->setVal(cxval + xerr/100) ; - double fxmax = fy() ; - - // Calculate slope - double slope = (fxmax-fxmin)/(2*xerr/100.) ; - -// std::cout << var << " " ; -// var->Print() ; - -// std::cout << var->GetName() << " xerr = " << xerr << " slope = " << slope << std::endl ; - - // Symmetric X error - ret += pow(xerr*slope,2) ; - } - } - return ret ; -} - - - - -//////////////////////////////////////////////////////////////////////////////// -/// Return function value requested bu present configuration -/// -/// If integration is required, the function value integrated -/// over the bin volume divided by the bin volume is returned, -/// otherwise the value at the bin center is returned. -/// The bin volume is defined by the error on the 'X' coordinates -/// -/// If an extended p.d.f. is used as function, its value is -/// also multiplied by the expected number of events here - -double RooXYChi2Var::fy() const -{ - // Get function value - double yfunc ; - if (!_integrate) { - yfunc = _funcClone->getVal(_dataClone->get()) ; - } else { - double volume(1) ; - auto rrvIter = _rrvArgs.begin(); - for (auto iter = _binList.begin() ; iter != _binList.end() ; ++iter) { - auto* x = static_cast(*rrvIter); - double xmin = x->getVal() + x->getErrorLo() ; - double xmax = x->getVal() + x->getErrorHi() ; - (*iter)->setRange(xmin,xmax) ; - x->setShapeDirty() ; - volume *= (xmax - xmin) ; - ++rrvIter; - } - double ret = _funcInt->getVal() ; - return ret / volume ; - } - if (_extended) { - RooAbsPdf* pdf = static_cast(_funcClone) ; - // Multiply with expected number of events - yfunc *= pdf->expectedEvents(_dataClone->get()) ; - } - return yfunc ; -} - - - -//////////////////////////////////////////////////////////////////////////////// -/// Calculate chi^2 in partition from firstEvent to lastEvent using given stepSize - -double RooXYChi2Var::evaluatePartition(std::size_t firstEvent, std::size_t lastEvent, std::size_t stepSize) const -{ - double result(0); - double carry(0); - - // Loop over bins of dataset - RooDataSet* xydata = static_cast(_dataClone) ; - - for (auto i=firstEvent ; iget(i); - - // Get function value - double yfunc = fy() ; - - // Get data value and error - double ydata ; - double eylo; - double eyhi; - if (_yvar) { - ydata = _yvar->getVal() ; - eylo = -1*_yvar->getErrorLo() ; - eyhi = _yvar->getErrorHi() ; - } else { - ydata = xydata->weight() ; - xydata->weightError(eylo,eyhi) ; - } - - // Calculate external error - double eExt = yfunc-ydata ; - - // Pick upper or lower error bar depending on sign of external error - double eInt = (eExt>0) ? eyhi : eylo ; - - // Add contributions due to error in x coordinates - double eIntX2 = _integrate ? 0 : xErrorContribution(ydata) ; - -// std::cout << "fy = " << yfunc << " eExt = " << eExt << " eInt = " << eInt << " eIntX2 = " << eIntX2 << std::endl ; - - // Return 0 if eInt=0, special handling in MINUIT will follow - if (eInt==0.) { - coutE(Eval) << "RooXYChi2Var::RooXYChi2Var(" << GetName() << ") INFINITY ERROR: data point " << i - << " has zero error, but function is not zero (f=" << yfunc << ")" << std::endl ; - return 0 ; - } - - // Add chi2 term - double term = eExt*eExt/(eInt*eInt+ eIntX2); - double y = term - carry; - double t = result + y; - carry = (t - result) - y; - result = t; - } - - _evalCarry = carry; - return result ; -} - - - -RooArgSet RooXYChi2Var::requiredExtraObservables() const -{ - // Inform base class that observable yvar cannot be optimized away from the dataset - if (_yvar) return RooArgSet(*_yvar) ; - return RooArgSet() ; -} - -/// \endcond diff --git a/roofit/roofitcore/src/RooXYChi2Var.h b/roofit/roofitcore/src/RooXYChi2Var.h deleted file mode 100644 index 8c488647261f3..0000000000000 --- a/roofit/roofitcore/src/RooXYChi2Var.h +++ /dev/null @@ -1,87 +0,0 @@ -/// \cond ROOFIT_INTERNAL - -/* - * Project: RooFit - * - * Copyright (c) 2024, CERN - * - * Redistribution and use in source and binary forms, - * with or without modification, are permitted according to the terms - * listed in LICENSE (http://roofit.sourceforge.net/license.txt) - */ - -#ifndef ROO_XY_CHI2_VAR -#define ROO_XY_CHI2_VAR - -#include "RooAbsOptTestStatistic.h" -#include "RooDataSet.h" -#include "RooAbsPdf.h" -#include "RooNumIntConfig.h" -#include -class RooAbsIntegrator ; - - -class RooXYChi2Var : public RooAbsOptTestStatistic { -public: - - // Constructors, assignment etc - RooXYChi2Var(const char *name, const char* title, RooAbsReal& func, RooDataSet& data, bool integrate=false) ; - RooXYChi2Var(const char *name, const char* title, RooAbsReal& func, RooDataSet& data, RooRealVar& yvar, bool integrate=false) ; - /// \cond ROOFIT_INTERNAL - // For internal use in RooAbsReal::createChi2(). - RooXYChi2Var(const char *name, const char *title, RooAbsReal& func, RooAbsData& data, RooRealVar *yvar, bool integrate, - RooAbsTestStatistic::Configuration const& cfg); - /// \endcond ROOFIT_INTERNAL - - RooXYChi2Var(const RooXYChi2Var& other, const char* name=nullptr); - TObject* clone(const char* newname=nullptr) const override { return new RooXYChi2Var(*this,newname); } - - RooAbsTestStatistic* create(const char *name, const char *title, RooAbsReal& pdf, RooAbsData& adata, - const RooArgSet&, RooAbsTestStatistic::Configuration const&) override { - // Virtual constructor - return new RooXYChi2Var(name,title,pdf,(RooDataSet&)adata) ; - } - - ~RooXYChi2Var() override; - - double defaultErrorLevel() const override { - // The default error level for MINUIT error analysis for a chi^2 is 1.0 - return 1.0 ; - } - - RooNumIntConfig& binIntegratorConfig() { return _intConfig ; } - const RooNumIntConfig& binIntegratorConfig() const { return _intConfig ; } - -protected: - - bool allowFunctionCache() override { - // Disable function (component) caching if integration is requested as the function - // will be evaluated at coordinates other than the points in the dataset - return !_integrate ; - } - - RooArgSet requiredExtraObservables() const override ; - - double fy() const ; - - bool _extended ; ///< Is the input function and extended p.d.f. - bool _integrate ; ///< Is integration over the bin volume requested - - RooRealVar* _yvar ; ///< Y variable if so designated - RooArgSet _rrvArgs ; ///< Set of real-valued observables - - void initialize() ; - void initIntegrator() ; - double xErrorContribution(double ydata) const ; - - double evaluatePartition(std::size_t firstEvent, std::size_t lastEvent, std::size_t stepSize) const override ; - - RooNumIntConfig _intConfig ; ///< Numeric integrator configuration for integration of function over bin - std::unique_ptr _funcInt; /// _binList ; ///Gaus()); - y.setError(sqrt(y.getVal())); - - dxy.add(RooArgSet(x, y)); - } - - // P e r f o r m c h i 2 f i t t o X + / - d x a n d Y + / - d Y v a l u e s - // --------------------------------------------------------------------------------------- - - // Make fit function - RooRealVar a("a", "a", 0.0, -10, 10); - RooRealVar b("b", "b", 0.0, -100, 100); - RooRealVar c("c", "c", 0.0, -100, 100); - RooPolyVar f("f", "f", x, RooArgList(b, a, c)); - - // Plot dataset in X-Y interpretation - RooPlot *frame = x.frame(Title("Chi^2 fit of function set of (X#pmdX,Y#pmdY) values")); - dxy.plotOnXY(frame, YVar(y)); - - // Fit chi^2 using X and Y errors - std::unique_ptr fit1{f.chi2FitTo(dxy, YVar(y), Save(), PrintLevel(-1))}; - - // Overlay fitted function - f.plotOn(frame); - - // Alternative: fit chi^2 integrating f(x) over ranges defined by X errors, rather - // than taking point at center of bin - std::unique_ptr fit2{f.chi2FitTo(dxy, YVar(y), Save(), PrintLevel(-1), Integrate(true))}; - - // Overlay alternate fit result - f.plotOn(frame, LineStyle(kDashed), LineColor(kRed), Name("alternate")); - - regPlot(frame, "rf609_frame"); - - return true; - } -}; - // Unbinned maximum likelihood fit of an efficiency eff(x) function to // a dataset D(x,cut), where cut is a category encoding a selection, of which // the efficiency as function of x should be described by eff(x). diff --git a/roofit/roofitcore/test/testTestStatistics.cxx b/roofit/roofitcore/test/testTestStatistics.cxx index 47b19daa86bb4..3b0af995d8529 100644 --- a/roofit/roofitcore/test/testTestStatistics.cxx +++ b/roofit/roofitcore/test/testTestStatistics.cxx @@ -389,67 +389,6 @@ TEST(RooNLLVar, CopyRangedNLL) } #endif -/// When using the Integrate() command argument in chi2FitTo, the result should -/// be identical to a fit without bin integration if the fit function is -/// linear. This is a good cross check to see if the integration works. -/// Inspired by the rf609_xychi2fit tutorial. -TEST(RooXYChi2Var, IntegrateLinearFunction) -{ - RooHelpers::LocalChangeMsgLevel changeMsgLvl(RooFit::WARNING); - - using namespace RooFit; - - // Make weighted XY dataset with asymmetric errors stored The StoreError() - // argument is essential as it makes the dataset store the error in addition - // to the values of the observables. If errors on one or more observables - // are asymmetric, one can store the asymmetric error using the - // StoreAsymError() argument - RooRealVar x("x", "x", -11, 11); - RooRealVar y("y", "y", -10, 200); - RooDataSet dxy("dxy", "dxy", {x, y}, StoreError({x, y})); - - const double aTrue = 0.1; - const double bTrue = 10.0; - - // Fill an example dataset with X,err(X),Y,err(Y) values - for (int i = 0; i <= 10; i++) { - - // Set X value and error - x = -10 + 2 * i; - x.setError(i < 5 ? 0.5 / 1. : 1.0 / 1.); - - // Set Y value and error - y = aTrue * x.getVal() + bTrue; - y.setError(std::sqrt(y.getVal())); - - dxy.add({x, y}); - } - - // Make linear fit function - RooRealVar a("a", "a", 0.0, -10, 10); - RooRealVar b("b", "b", 0.0, -100, 100); - RooArgList coefs{b, a}; - RooPolyVar f("f", "f", x, coefs); - - RooArgSet savedValues; - coefs.snapshot(savedValues); - - // Fit chi^2 using X and Y errors - std::unique_ptr fit1{f.chi2FitTo(dxy, YVar(y), Save(), PrintLevel(-1), Optimize(0))}; - - coefs.assign(savedValues); - // Alternative: fit chi^2 integrating f(x) over ranges defined by X errors, - // rather than taking point at center of bin - std::unique_ptr fit2{f.chi2FitTo(dxy, YVar(y), Integrate(true), Save(), PrintLevel(-1), Optimize(0))}; - - // Verify that the fit result is compatible with true values within the error - EXPECT_NEAR(getVal("a", fit1->floatParsFinal()), aTrue, getErr("a", fit1->floatParsFinal())); - EXPECT_NEAR(getVal("b", fit1->floatParsFinal()), bTrue, getErr("b", fit1->floatParsFinal())); - - EXPECT_NEAR(getVal("a", fit2->floatParsFinal()), aTrue, getErr("a", fit2->floatParsFinal())); - EXPECT_NEAR(getVal("b", fit2->floatParsFinal()), bTrue, getErr("b", fit2->floatParsFinal())); -} - class OffsetBinTest : public testing::TestWithParam> { public: OffsetBinTest() : _evalBackend{RooFit::EvalBackend::Legacy()} {} diff --git a/roofit/roostats/CMakeLists.txt b/roofit/roostats/CMakeLists.txt index 6d81e76646138..b51d6b718a8c8 100644 --- a/roofit/roostats/CMakeLists.txt +++ b/roofit/roostats/CMakeLists.txt @@ -29,7 +29,6 @@ ROOT_STANDARD_LIBRARY_PACKAGE(RooStats RooStats/FrequentistCalculator.h RooStats/Heaviside.h RooStats/HybridCalculator.h - RooStats/HybridPlot.h RooStats/HybridResult.h RooStats/HypoTestCalculatorGeneric.h RooStats/HypoTestCalculator.h @@ -83,7 +82,6 @@ ROOT_STANDARD_LIBRARY_PACKAGE(RooStats src/FrequentistCalculator.cxx src/Heaviside.cxx src/HybridCalculator.cxx - src/HybridPlot.cxx src/HybridResult.cxx src/HypoTestCalculatorGeneric.cxx src/HypoTestInverter.cxx diff --git a/roofit/roostats/inc/LinkDef.h b/roofit/roostats/inc/LinkDef.h index 788bbada6cb36..228d8a3671d60 100644 --- a/roofit/roostats/inc/LinkDef.h +++ b/roofit/roostats/inc/LinkDef.h @@ -49,7 +49,6 @@ #pragma link C++ class RooStats::HybridCalculator+; #pragma link C++ class RooStats::FrequentistCalculator+; #pragma link C++ class RooStats::AsymptoticCalculator+; -#pragma link C++ class RooStats::HybridPlot+; #pragma link C++ class RooStats::HybridResult+; #pragma link C++ class RooStats::DetailedOutputAggregator+; diff --git a/roofit/roostats/inc/RooStats/HybridPlot.h b/roofit/roostats/inc/RooStats/HybridPlot.h deleted file mode 100644 index b80b51bc55113..0000000000000 --- a/roofit/roostats/inc/RooStats/HybridPlot.h +++ /dev/null @@ -1,129 +0,0 @@ -// @(#)root/roostats:$Id$ - -/************************************************************************* - * Project: RooStats * - * Package: RooFit/RooStats * - * Authors: * - * Kyle Cranmer, Lorenzo Moneta, Gregory Schott, Wouter Verkerke * - ************************************************************************* - * Copyright (C) 1995-2008, Rene Brun and Fons Rademakers. * - * All rights reserved. * - * * - * For the licensing terms see $ROOTSYS/LICENSE. * - * For the list of contributors see $ROOTSYS/README/CREDITS. * - *************************************************************************/ - -#ifndef ROOSTATS_HybridPlot -#define ROOSTATS_HybridPlot - -#include -#include - -#include "TNamed.h" - -// these should be maybe forward declared -// by moving implementations in source file - -#include "TH1.h" - -class TLine; -class TLegend; -class TH1; -class TVirtualPad; - -namespace RooStats { - - class HybridPlot : public TNamed { - - public: - - /// Constructor - HybridPlot(const char* name, - const char* title, - const std::vector & sb_values, - const std::vector & b_values, - double testStat_data, - int n_bins, - bool verbosity=true); - - /// Destructor - ~HybridPlot() override; - - /// Draw on current pad - void Draw (const char* options="") override; - - /// All the objects are written to rootfile - void DumpToFile (const char* RootFileName, const char* options); - - /// Get B histo mean - double GetBmean(){return fB_histo->GetMean();}; - - /// Get B histo RMS - double GetBrms(){return fB_histo->GetRMS();}; - - /// Get B histo - TH1F * GetBhisto(){return fB_histo;} - - /// Get B histo center - double GetBCenter(double n_sigmas=1, bool display=false) - {return GetHistoCenter(fB_histo,n_sigmas,display);}; - - /// Get B histo integration extremes to obtain the requested area fraction - /// call delete [] res to release memory - double* GetBIntExtremes(double frac) - {return GetHistoPvals(fB_histo,frac);}; - - /// Get SB histo mean - double GetSBmean(){return fSb_histo->GetMean();}; - - /// Get SB histo center - double GetSBCenter(double n_sigmas=1, bool display=false) - {return GetHistoCenter(fSb_histo,n_sigmas,display);}; - - /// Get SB histo RMS - double GetSBrms(){return fSb_histo->GetRMS();}; - - /// Get SB histo integration extremes to obtain the requested area fraction - /// call delete [] res to release memory - double* GetSBIntExtremes(double frac) - {return GetHistoPvals(fSb_histo,frac);}; - - /// Get B histo - TH1F* GetSBhisto(){return fSb_histo;} - - /// Get the pad (or canvas) where it has been drawn - TVirtualPad * GetCanvas() { return fPad; } - - /// Write an image on disk - void DumpToImage (const char* filename); - - - /// Get the center of the histo - double GetHistoCenter(TH1* histo, double n_rms=1,bool display_result=false); - - /// Get the "effective sigmas" of the histo, call delete [] res to release memory - double* GetHistoPvals (TH1* histo, double percentage); - - /// Get the median of an histogram - double GetMedian(TH1* histo); - - private: - - TH1F* fSb_histo; ///< The sb Histo - TH1F* fSb_histo_shaded; ///< The sb Histo shaded - TH1F* fB_histo; ///< The b Histo - TH1F* fB_histo_shaded; ///< The b Histo shaded - TLine* fData_testStat_line; ///< The line for the data value of the test statistic - TLegend* fLegend; ///< The legend of the plot - TVirtualPad * fPad; ///< The pad where it has been drawn - bool fVerbose; ///< verbosity flag - - ClassDefOverride(HybridPlot,0) // Provides the plots for an HybridResult - } -#ifndef ROOFIT_BUILDS_ITSELF - R__DEPRECATED(6, 42, "Please write your own ROOT-based plotting code, possibly based on the source code of the deprecated HybridPlot class.") -#endif - ; -} - -#endif diff --git a/roofit/roostats/inc/RooStats/HybridResult.h b/roofit/roostats/inc/RooStats/HybridResult.h index ebdeeab6bb5cf..8761889fe7a14 100644 --- a/roofit/roostats/inc/RooStats/HybridResult.h +++ b/roofit/roostats/inc/RooStats/HybridResult.h @@ -45,9 +45,6 @@ namespace RooStats { void Add(HybridResult* other); - HybridPlot* GetPlot(const char* name,const char* title, int n_bins) - R__DEPRECATED(6, 42, "Please write your own ROOT-based plotting code, possibly based on the source code of the deprecated HybridPlot class."); - void PrintMore(const char* options); /// Get test statistics values for the sb model diff --git a/roofit/roostats/src/HybridPlot.cxx b/roofit/roostats/src/HybridPlot.cxx deleted file mode 100644 index 9ecb4bff900cb..0000000000000 --- a/roofit/roostats/src/HybridPlot.cxx +++ /dev/null @@ -1,370 +0,0 @@ -// @(#)root/hist:$Id$ - -/** \class RooStats::HybridPlot - \ingroup Roostats - -This class provides the plots for the result of a study performed with the -HybridCalculatorOriginal class. - -Authors: D. Piparo, G. Schott - Universitaet Karlsruhe - -An example plot is available here: -http://www-ekp.physik.uni-karlsruhe.de/~schott/roostats/hybridplot_example.png -*/ - -#include -#include -#include -#include - -#include "RooStats/HybridPlot.h" -#include "RooMsgService.h" -#include "TStyle.h" -#include "TF1.h" -#include "TAxis.h" -#include "TH1.h" -#include "TLine.h" -#include "TLegend.h" -#include "TFile.h" -#include "TVirtualPad.h" - -#include - -/// To build the THtml documentation - - -using namespace RooStats; - -//////////////////////////////////////////////////////////////////////////////// -/// HybridPlot constructor - -HybridPlot::HybridPlot(const char* name, - const char* title, - const std::vector & sb_vals, - const std::vector & b_vals, - double testStat_data, - int n_bins, - bool verbosity): - TNamed(name,title), - fSb_histo(nullptr), - fSb_histo_shaded(nullptr), - fB_histo(nullptr), - fB_histo_shaded(nullptr), - fData_testStat_line(nullptr), - fLegend(nullptr), - fPad(nullptr), - fVerbose(verbosity) -{ - int nToysSB = sb_vals.size(); - int nToysB = sb_vals.size(); - assert (nToysSB >0); - assert (nToysB >0); - - // Get the max and the min of the plots - double min = *std::min_element(sb_vals.begin(), sb_vals.end()); - double max = *std::max_element(sb_vals.begin(), sb_vals.end()); - - double min_b = *std::min_element(b_vals.begin(), b_vals.end()); - double max_b = *std::max_element(b_vals.begin(), b_vals.end()); - - - if ( min_b < min) min = min_b; - if ( max_b > max) max = max_b; - - if (testStat_datamax) max = testStat_data; - - min *= 1.1; - max *= 1.1; - - // Build the histos - - fSb_histo = new TH1F ("SB_model",title,n_bins,min,max); - fSb_histo->SetTitle(fSb_histo->GetTitle()); - fSb_histo->SetLineColor(kBlue); - fSb_histo->GetXaxis()->SetTitle("test statistics"); - fSb_histo->SetLineWidth(2); - - fB_histo = new TH1F ("B_model",title,n_bins,min,max); - fB_histo->SetTitle(fB_histo->GetTitle()); - fB_histo->SetLineColor(kRed); - fB_histo->GetXaxis()->SetTitle("test statistics"); - fB_histo->SetLineWidth(2); - - for (int i=0;iFill(sb_vals[i]); - for (int i=0;iFill(b_vals[i]); - - double histos_max_y = fSb_histo->GetMaximum(); - double lineHeight = histos_max_y/nToysSB; - if (histos_max_yGetMaximum()) histos_max_y = fB_histo->GetMaximum()/nToysB; - - // Build the line of the measured -2lnQ - fData_testStat_line = new TLine(testStat_data,0,testStat_data,lineHeight); - fData_testStat_line->SetLineWidth(3); - fData_testStat_line->SetLineColor(kBlack); - - // The legend - double golden_section = (std::sqrt(5.)-1)/2; - - fLegend = new TLegend(0.75,0.95-0.2*golden_section,0.95,0.95); - TString title_leg="test statistics distributions "; - title_leg+=sb_vals.size(); - title_leg+=" toys"; - fLegend->SetName(title_leg.Data()); - fLegend->AddEntry(fSb_histo,"SB toy datasets"); - fLegend->AddEntry(fB_histo,"B toy datasets"); - fLegend->AddEntry((TLine*)fData_testStat_line,"test statistics on data","L"); - fLegend->SetFillColor(0); -} - -//////////////////////////////////////////////////////////////////////////////// -/// destructor - -HybridPlot::~HybridPlot() -{ - - if (fSb_histo) delete fSb_histo; - if (fB_histo) delete fB_histo; - if (fSb_histo_shaded) delete fSb_histo_shaded; - if (fB_histo_shaded) delete fB_histo_shaded; - if (fData_testStat_line) delete fData_testStat_line; - if (fLegend) delete fLegend; -} - -//////////////////////////////////////////////////////////////////////////////// -/// draw the S+B and B histogram in the current canvas - -void HybridPlot::Draw(const char* ) -{ - // We don't want the statistics of the histos - gStyle->SetOptStat(0); - - // The histos - - if (fSb_histo->GetMaximum()>fB_histo->GetMaximum()){ - fSb_histo->DrawNormalized(); - fB_histo->DrawNormalized("same"); - } - else{ - fB_histo->DrawNormalized(); - fSb_histo->DrawNormalized("same"); - } - - // Shaded - fB_histo_shaded = static_cast(fB_histo->Clone("b_shaded")); - fB_histo_shaded->SetFillStyle(3005); - fB_histo_shaded->SetFillColor(kRed); - - fSb_histo_shaded = static_cast(fSb_histo->Clone("sb_shaded")); - fSb_histo_shaded->SetFillStyle(3004); - fSb_histo_shaded->SetFillColor(kBlue); - - // Empty the bins according to the data -2lnQ - double data_m2lnq= fData_testStat_line->GetX1(); - for (int i=1;i<=fSb_histo->GetNbinsX();++i){ - if (fSb_histo->GetBinCenter(i)SetBinContent(i,0); - fB_histo_shaded->SetBinContent(i,fB_histo->GetBinContent(i)/fB_histo->GetSumOfWeights()); - } - else{ - fB_histo_shaded->SetBinContent(i,0); - fSb_histo_shaded->SetBinContent(i,fSb_histo->GetBinContent(i)/fSb_histo->GetSumOfWeights()); - } - } - - // Draw the shaded histos - fB_histo_shaded->Draw("same"); - fSb_histo_shaded->Draw("same"); - - // The line - fData_testStat_line->Draw("same"); - - // The legend - fLegend->Draw("same"); - - if (gPad) { - gPad->SetName(GetName()); - gPad->SetTitle(GetTitle() ); - } - - fPad = gPad; - -} - -//////////////////////////////////////////////////////////////////////////////// -/// All the objects are written to rootfile - -void HybridPlot::DumpToFile (const char* RootFileName, const char* options) -{ - - TFile ofile(RootFileName,options); - ofile.cd(); - - // The histos - fSb_histo->Write(); - fB_histo->Write(); - - // The shaded histos - if (fB_histo_shaded!=nullptr && fSb_histo_shaded!=nullptr){ - fB_histo_shaded->Write(); - fSb_histo_shaded->Write(); - } - - // The line - fData_testStat_line->Write("Measured test statistics line tag"); - - // The legend - fLegend->Write(); - - ofile.Close(); - -} - -//////////////////////////////////////////////////////////////////////////////// - -void HybridPlot::DumpToImage(const char * filename) { - if (!fPad) { - Error("HybridPlot","Hybrid plot has not yet been drawn "); - return; - } - fPad->Print(filename); -} - -//////////////////////////////////////////////////////////////////////////////// -/// Perform 2 times a gaussian fit to fetch the center of the histo. -/// To get the second fit range get an interval that tries to keep into account -/// the skewness of the distribution. - -double HybridPlot::GetHistoCenter(TH1* histo_orig, double n_rms, bool display_result){ - // Get the center of the histo - - TString optfit = "Q0"; - if (display_result) optfit = "Q"; - - TH1F* histo = static_cast(histo_orig->Clone()); - - // get the histo x extremes - double x_min = histo->GetXaxis()->GetXmin(); - double x_max = histo->GetXaxis()->GetXmax(); - - // First fit! - - TF1* gauss = new TF1("mygauss", "gauss", x_min, x_max); - - gauss->SetParameter("Constant",histo->GetEntries()); - gauss->SetParameter("Mean",histo->GetMean()); - gauss->SetParameter("Sigma",histo->GetRMS()); - - histo->Fit(gauss,optfit); - - // Second fit! - double sigma = gauss->GetParameter("Sigma"); - double mean = gauss->GetParameter("Mean"); - - delete gauss; - - coutI(Eval) << "Center is 1st pass = " << mean << std::endl; - - double skewness = histo->GetSkewness(); - - x_min = mean - n_rms*sigma - sigma*skewness/2; - x_max = mean + n_rms*sigma - sigma*skewness/2; - - TF1* gauss2 = new TF1("mygauss2", "gauss", x_min, x_max); - gauss2->SetParameter("Mean",mean); - - // second fit : likelihood fit - optfit += "L"; - histo->Fit(gauss2,optfit,"", x_min, x_max); - - - double center = gauss2->GetParameter("Mean"); - - if (display_result) { - histo->Draw(); - gauss2->Draw("same"); - } - else { - delete histo; - } - delete gauss2; - - return center; - - -} - -//////////////////////////////////////////////////////////////////////////////// -/// We let an horizontal bar go down and we stop when we have the integral -/// equal to the desired one. - -double* HybridPlot::GetHistoPvals (TH1* histo, double percentage){ - - if (percentage>1){ - coutE(InputArguments) << "Percentage greater or equal to 1!\n"; - return nullptr; - } - - // Get the integral of the histo - double* h_integral=histo->GetIntegral(); - - // Start the iteration - std::map extremes_map; - - for (int i=0;iGetNbinsX();++i){ - for (int j=0;jGetNbinsX();++j){ - double integral = h_integral[j]-h_integral[i]; - if (integral>percentage){ - extremes_map[i]=j; - break; - } - } - } - - // Now select the couple of extremes which have the lower bin content diff - std::map::iterator it; - int a; - int b; - double left_bin_center(0.); - double right_bin_center(0.); - double diff=10e40; - double current_diff; - for (it = extremes_map.begin();it != extremes_map.end();++it){ - a=it->first; - b=it->second; - current_diff=std::abs(histo->GetBinContent(a)-histo->GetBinContent(b)); - if (current_diff @@ -241,38 +240,6 @@ void HybridResult::Add(HybridResult* other) return; } -//////////////////////////////////////////////////////////////////////////////// -/// prepare a plot showing a result and return a pointer to a HybridPlot object -/// the needed arguments are: an object name, a title and the number of bins in the plot - -HybridPlot* HybridResult::GetPlot(const char* name,const char* title, int n_bins) -{ - // default plot name - TString plot_name; - if ( TString(name)=="" ) { - plot_name += GetName(); - plot_name += "_plot"; - } else plot_name = name; - - // default plot title - TString plot_title; - if ( TString(title)=="" ) { - plot_title += GetTitle(); - plot_title += "_plot ("; - plot_title += fTestStat_b.size(); - plot_title += " toys)"; - } else plot_title = title; - - HybridPlot* plot = new HybridPlot( plot_name.Data(), - plot_title.Data(), - fTestStat_sb, - fTestStat_b, - fTestStat_data, - n_bins, - true ); - return plot; -} - //////////////////////////////////////////////////////////////////////////////// /// Print out some information about the results