From daa8a63a44febb66a653e0f105ab451a1b343187 Mon Sep 17 00:00:00 2001 From: Jonas Rembser Date: Tue, 19 Sep 2023 03:59:38 +0200 Subject: [PATCH] [RF] Implement `Offset("bin")` also for RooDataSet fits Fully implement the `Offset("bin")` feature also for RooDataSet, both with CPU/CUDA BatchMode and the legacy tests statistics. This is done now by introducing a new element in the computation graph: an "offset pdf" that is created as a RooHistPdf from the observed data, and it is used to get the counterterm in each bin. It was validated with the `rf614` tutorial that this binwise offsetting is indeed fixing the convergense problems that the simple offsetting by the initial NLL value can't fix. Closes #11965. --- roofit/batchcompute/inc/RooBatchCompute.h | 11 ++- roofit/batchcompute/src/RooBatchCompute.cu | 31 ++++---- roofit/batchcompute/src/RooBatchCompute.cxx | 14 ++-- roofit/roofitcore/inc/RooNLLVar.h | 13 ++-- .../roofitcore/src/BatchModeDataHelpers.cxx | 21 +---- roofit/roofitcore/src/BatchModeHelpers.cxx | 2 - roofit/roofitcore/src/RooAbsPdf.cxx | 6 -- roofit/roofitcore/src/RooAddition.cxx | 2 +- roofit/roofitcore/src/RooNLLVar.cxx | 64 ++++++++++----- roofit/roofitcore/src/RooNLLVarNew.cxx | 77 +++++++++++++++++-- roofit/roofitcore/src/RooNLLVarNew.h | 9 +-- roofit/roofitcore/test/testTestStatistics.cxx | 43 ++++++----- tutorials/roofit/rf614_binned_fit_problems.C | 3 +- tutorials/roofit/rf614_binned_fit_problems.py | 3 +- 14 files changed, 173 insertions(+), 126 deletions(-) diff --git a/roofit/batchcompute/inc/RooBatchCompute.h b/roofit/batchcompute/inc/RooBatchCompute.h index b7b651960ae04..0dfae706c9d38 100644 --- a/roofit/batchcompute/inc/RooBatchCompute.h +++ b/roofit/batchcompute/inc/RooBatchCompute.h @@ -151,9 +151,8 @@ class RooBatchComputeInterface { } virtual double reduceSum(Config const &cfg, InputArr input, size_t n) = 0; - virtual ReduceNLLOutput reduceNLL(Config const &cfg, std::span probas, - std::span weightSpan, std::span weights, - double weightSum, std::span binVolumes) = 0; + virtual ReduceNLLOutput reduceNLL(Config const &cfg, std::span probas, std::span weights, + std::span offsetProbas) = 0; virtual Architecture architecture() const = 0; virtual std::string architectureName() const = 0; @@ -207,12 +206,12 @@ inline double reduceSum(Config cfg, InputArr input, size_t n) return dispatch->reduceSum(cfg, input, n); } -inline ReduceNLLOutput reduceNLL(Config cfg, std::span probas, std::span weightSpan, - std::span weights, double weightSum, std::span binVolumes) +inline ReduceNLLOutput reduceNLL(Config cfg, std::span probas, std::span weights, + std::span offsetProbas) { init(); auto dispatch = cfg.useCuda() ? dispatchCUDA : dispatchCPU; - return dispatch->reduceNLL(cfg, probas, weightSpan, weights, weightSum, binVolumes); + return dispatch->reduceNLL(cfg, probas, weights, offsetProbas); } } // End namespace RooBatchCompute diff --git a/roofit/batchcompute/src/RooBatchCompute.cu b/roofit/batchcompute/src/RooBatchCompute.cu index 932ab57f80d10..cbf73de2fbf0b 100644 --- a/roofit/batchcompute/src/RooBatchCompute.cu +++ b/roofit/batchcompute/src/RooBatchCompute.cu @@ -155,8 +155,7 @@ public: /// Return the sum of an input array double reduceSum(RooBatchCompute::Config const &cfg, InputArr input, size_t n) override; ReduceNLLOutput reduceNLL(RooBatchCompute::Config const &cfg, std::span probas, - std::span weightSpan, std::span weights, double weightSum, - std::span binVolumes) override; + std::span weights, std::span offsetProbas) override; }; // End class RooBatchComputeClass inline __device__ void kahanSumUpdate(double &sum, double &carry, double a, double otherCarry) @@ -220,8 +219,8 @@ __global__ void kahanSum(const double *__restrict__ input, const double *__restr kahanSumReduction(shared, n, result, carry_index); } -__global__ void kahanSumWeighted(const double *__restrict__ input, const double *__restrict__ weights, size_t n, - double *__restrict__ result) +__global__ void nllSumKernel(const double *__restrict__ probas, const double *__restrict__ weights, + const double *__restrict__ offsetProbas, size_t n, double *__restrict__ result) { int thIdx = threadIdx.x; int gthIdx = thIdx + blockIdx.x * blockSize; @@ -237,7 +236,11 @@ __global__ void kahanSumWeighted(const double *__restrict__ input, const double for (int i = gthIdx; i < n; i += nThreadsTotal) { // Note: it does not make sense to use the nll option and provide at the // same time external carries. - double val = -std::log(input[i]) * weights[i]; + double val = -std::log(probas[i]); + if (offsetProbas) + val += std::log(offsetProbas[i]); + if (weights) + val = weights[i] * val; kahanSumUpdate(sum, carry, val, 0.0); } @@ -264,8 +267,7 @@ double RooBatchComputeClass::reduceSum(RooBatchCompute::Config const &cfg, Input } ReduceNLLOutput RooBatchComputeClass::reduceNLL(RooBatchCompute::Config const &cfg, std::span probas, - std::span weightSpan, std::span /*weights*/, - double /*weightSum*/, std::span binVolumes) + std::span weights, std::span offsetProbas) { ReduceNLLOutput out; const int gridSize = getGridSize(probas.size()); @@ -273,12 +275,9 @@ ReduceNLLOutput RooBatchComputeClass::reduceNLL(RooBatchCompute::Config const &c cudaStream_t stream = *cfg.cudaStream(); constexpr int shMemSize = 2 * blockSize * sizeof(double); - if (weightSpan.size() == 1) { - kahanSum<<>>(probas.data(), nullptr, probas.size(), devOut.data(), 1); - } else { - kahanSumWeighted<<>>(probas.data(), weightSpan.data(), probas.size(), - devOut.data()); - } + nllSumKernel<<>>( + probas.data(), weights.size() == 1 ? nullptr : weights.data(), + offsetProbas.empty() ? nullptr : offsetProbas.data(), probas.size(), devOut.data()); kahanSum<<<1, blockSize, shMemSize, stream>>>(devOut.data(), devOut.data() + gridSize, gridSize, devOut.data(), 0); @@ -287,9 +286,9 @@ ReduceNLLOutput RooBatchComputeClass::reduceNLL(RooBatchCompute::Config const &c CudaInterface::copyDeviceToHost(devOut.data(), &tmpSum, 1, cfg.cudaStream()); CudaInterface::copyDeviceToHost(devOut.data() + 1, &tmpCarry, 1, cfg.cudaStream()); - if (weightSpan.size() == 1) { - tmpSum *= weightSpan[0]; - tmpCarry *= weightSpan[0]; + if (weights.size() == 1) { + tmpSum *= weights[0]; + tmpCarry *= weights[0]; } out.nllSum = ROOT::Math::KahanSum{tmpSum, tmpCarry}; diff --git a/roofit/batchcompute/src/RooBatchCompute.cxx b/roofit/batchcompute/src/RooBatchCompute.cxx index cc49927ed0ef9..cceba40750bc7 100644 --- a/roofit/batchcompute/src/RooBatchCompute.cxx +++ b/roofit/batchcompute/src/RooBatchCompute.cxx @@ -179,9 +179,8 @@ class RooBatchComputeClass : public RooBatchComputeInterface { } /// Return the sum of an input array double reduceSum(Config const &, InputArr input, size_t n) override; - ReduceNLLOutput reduceNLL(Config const &, std::span probas, std::span weightSpan, - std::span weights, double weightSum, - std::span binVolumes) override; + ReduceNLLOutput reduceNLL(Config const &, std::span probas, std::span weights, + std::span offsetProbas) override; }; // End class RooBatchComputeClass namespace { @@ -213,8 +212,7 @@ double RooBatchComputeClass::reduceSum(Config const &, InputArr input, size_t n) } ReduceNLLOutput RooBatchComputeClass::reduceNLL(Config const &, std::span probas, - std::span weightSpan, std::span weights, - double weightSum, std::span binVolumes) + std::span weights, std::span offsetProbas) { ReduceNLLOutput out; @@ -222,7 +220,7 @@ ReduceNLLOutput RooBatchComputeClass::reduceNLL(Config const &, std::span 1 ? weightSpan[i] : weightSpan[0]; + const double eventWeight = weights.size() > 1 ? weights[i] : weights[0]; if (0. == eventWeight) continue; @@ -231,8 +229,8 @@ ReduceNLLOutput RooBatchComputeClass::reduceNLL(Config const &, std::span #include -class RooRealSumPdf ; - class RooNLLVar : public RooAbsOptTestStatistic { public: @@ -53,15 +51,15 @@ class RooNLLVar : public RooAbsOptTestStatistic { double defaultErrorLevel() const override { return 0.5 ; } - void enableBinOffsetting(bool on = true) { - _doBinOffset = on; - } + void enableBinOffsetting(bool on = true); using ComputeResult = std::pair, double>; static RooNLLVar::ComputeResult computeScalarFunc(const RooAbsPdf *pdfClone, RooAbsData *dataClone, RooArgSet *normSet, bool weightSq, std::size_t stepSize, std::size_t firstEvent, - std::size_t lastEvent, bool doBinOffset=false); + std::size_t lastEvent, RooAbsPdf const* offsetPdf = nullptr); + + bool setData(RooAbsData& data, bool cloneData=true) override; protected: @@ -80,7 +78,8 @@ class RooNLLVar : public RooAbsOptTestStatistic { ROOT::Math::KahanSum _offsetSaveW2{0.0}; /// _binw ; /// _offsetPdf; /// -#include #include #include "RooNLLVarNew.h" #include @@ -96,26 +95,10 @@ getSingleDataSpans(RooAbsData const &data, std::string_view rangeName, std::stri assignSpan(weight, {buffer.data(), nNonZeroWeight}); assignSpan(weightSumW2, {bufferSumW2.data(), nNonZeroWeight}); } - using namespace ROOT::Experimental; insert(RooNLLVarNew::weightVarName, weight); insert(RooNLLVarNew::weightVarNameSumW2, weightSumW2); } - // Add also bin volume information if we are dealing with a RooDataHist - if (auto dataHist = dynamic_cast(&data)) { - buffers.emplace(); - auto &buffer = buffers.top(); - buffer.reserve(nNonZeroWeight); - - for (std::size_t i = 0; i < nEvents; ++i) { - if (!hasZeroWeight[i]) { - buffer.push_back(dataHist->binVolume(i)); - } - } - - insert("_bin_volume", {buffer.data(), buffer.size()}); - } - // Get the real-valued batches and cast the also to double branches to put in // the data map for (auto const &item : data.getBatches(0, nEvents)) { @@ -203,9 +186,7 @@ getSingleDataSpans(RooAbsData const &data, std::string_view rangeName, std::stri /// Spans with the weights and squared weights will be also stored in the map, /// keyed with the names `_weight` and the `_weight_sumW2`. If the dataset is /// unweighted, these weight spans will only contain the single value `1.0`. -/// Entries with zero weight will be skipped. If the input dataset is a -/// RooDataHist, the output map will also contain an item for the key -/// `_bin_volume` with the bin volumes. +/// Entries with zero weight will be skipped. /// /// \return A `std::map` with spans keyed to name pointers. /// \param[in] data The input dataset. diff --git a/roofit/roofitcore/src/BatchModeHelpers.cxx b/roofit/roofitcore/src/BatchModeHelpers.cxx index 51e7989134385..e3848045a69af 100644 --- a/roofit/roofitcore/src/BatchModeHelpers.cxx +++ b/roofit/roofitcore/src/BatchModeHelpers.cxx @@ -25,8 +25,6 @@ #include -using ROOT::Experimental::RooNLLVarNew; - namespace { std::unique_ptr createSimultaneousNLL(RooSimultaneous const &simPdf, bool isExtended, diff --git a/roofit/roofitcore/src/RooAbsPdf.cxx b/roofit/roofitcore/src/RooAbsPdf.cxx index 6941ca38869d8..52fa2c29bcd72 100644 --- a/roofit/roofitcore/src/RooAbsPdf.cxx +++ b/roofit/roofitcore/src/RooAbsPdf.cxx @@ -1076,12 +1076,6 @@ RooFit::OwningPtr RooAbsPdf::createNLL(RooAbsData& data, const RooLi Int_t cloneData = pc.getInt("cloneData") ; auto offset = static_cast(pc.getInt("doOffset")); - if(offset == RooFit::OffsetMode::Bin && dynamic_cast(&data)) { - coutE(Minimization) << "The Offset(\"bin\") option doesn't support fits to RooDataSet yet, only to RooDataHist." - " Falling back to no offsetting." << endl; - offset = RooFit::OffsetMode::None; - } - // If no explicit cloneData command is specified, cloneData is set to true if optimization is activated if (cloneData==2) { cloneData = optConst ; diff --git a/roofit/roofitcore/src/RooAddition.cxx b/roofit/roofitcore/src/RooAddition.cxx index 9221c391ee21e..e3d3a37a06529 100644 --- a/roofit/roofitcore/src/RooAddition.cxx +++ b/roofit/roofitcore/src/RooAddition.cxx @@ -240,7 +240,7 @@ double RooAddition::defaultErrorLevel() const std::unique_ptr comps{getComponents()}; for(RooAbsArg * arg : *comps) { - if (dynamic_cast(arg) || dynamic_cast(arg)) { + if (dynamic_cast(arg) || dynamic_cast(arg)) { nllArg = (RooAbsReal*)arg ; } if (dynamic_cast(arg)) { diff --git a/roofit/roofitcore/src/RooNLLVar.cxx b/roofit/roofitcore/src/RooNLLVar.cxx index 170cb579f34c8..f377a1b43c704 100644 --- a/roofit/roofitcore/src/RooNLLVar.cxx +++ b/roofit/roofitcore/src/RooNLLVar.cxx @@ -28,19 +28,20 @@ In extended mode, a \f$ N_\mathrm{expect} - N_\mathrm{observed}*log(N_\mathrm{expect}) \f$ term is added. **/ -#include "RooNLLVar.h" - -#include "RooAbsData.h" -#include "RooAbsPdf.h" -#include "RooCmdConfig.h" -#include "RooMsgService.h" -#include "RooAbsDataStore.h" -#include "RooRealMPFE.h" -#include "RooRealSumPdf.h" -#include "RooRealVar.h" -#include "RooProdPdf.h" -#include "RooNaNPacker.h" -#include "RooDataHist.h" +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include #ifdef ROOFIT_CHECK_CACHED_VALUES #include @@ -316,34 +317,30 @@ double RooNLLVar::evaluatePartition(std::size_t firstEvent, std::size_t lastEven RooNLLVar::ComputeResult RooNLLVar::computeScalar(std::size_t stepSize, std::size_t firstEvent, std::size_t lastEvent) const { auto pdfClone = static_cast(_funcClone); - return computeScalarFunc(pdfClone, _dataClone, _normSet, _weightSq, stepSize, firstEvent, lastEvent, _doBinOffset); + return computeScalarFunc(pdfClone, _dataClone, _normSet, _weightSq, stepSize, firstEvent, lastEvent, _offsetPdf.get()); } // static function, also used from TestStatistics::RooUnbinnedL RooNLLVar::ComputeResult RooNLLVar::computeScalarFunc(const RooAbsPdf *pdfClone, RooAbsData *dataClone, RooArgSet *normSet, bool weightSq, std::size_t stepSize, - std::size_t firstEvent, std::size_t lastEvent, bool doBinOffset) + std::size_t firstEvent, std::size_t lastEvent, RooAbsPdf const* offsetPdf) { ROOT::Math::KahanSum kahanWeight; ROOT::Math::KahanSum kahanProb; RooNaNPacker packedNaN(0.f); - const double logSumW = std::log(dataClone->sumEntries()); - - auto* dataHist = doBinOffset ? static_cast(dataClone) : nullptr; for (auto i=firstEvent; iget(i) ; double weight = dataClone->weight(); //FIXME - const double ni = weight; if (0. == weight * weight) continue ; if (weightSq) weight = dataClone->weightSquared() ; double logProba = pdfClone->getLogVal(normSet); - if(doBinOffset) { - logProba -= std::log(ni) - std::log(dataHist->binVolume(i)) - logSumW; + if(offsetPdf) { + logProba -= offsetPdf->getLogVal(normSet); } const double term = -weight * logProba; @@ -360,3 +357,28 @@ RooNLLVar::ComputeResult RooNLLVar::computeScalarFunc(const RooAbsPdf *pdfClone, return {kahanProb, kahanWeight.Sum()}; } + +bool RooNLLVar::setData(RooAbsData &data, bool cloneData) +{ + bool ret = RooAbsOptTestStatistic::setData(data, cloneData); + // To re-create the data template pdf if necessary + _offsetPdf.reset(); + enableBinOffsetting(_doBinOffset); + return ret; +} + +void RooNLLVar::enableBinOffsetting(bool on) +{ + if (on && !_offsetPdf) { + std::string name = std::string{GetName()} + "_offsetPdf"; + std::unique_ptr dataTemplate; + if (auto dh = dynamic_cast(_dataClone)) { + dataTemplate = std::make_unique(*dh); + } else { + dataTemplate = std::unique_ptr(static_cast(*_dataClone).binnedClone()); + } + _offsetPdf = std::make_unique(name.c_str(), name.c_str(), *_funcObsSet, std::move(dataTemplate)); + _offsetPdf->setOperMode(ADirty); + } + _doBinOffset = on; +} diff --git a/roofit/roofitcore/src/RooNLLVarNew.cxx b/roofit/roofitcore/src/RooNLLVarNew.cxx index 44c5457167aac..2052d22f63040 100644 --- a/roofit/roofitcore/src/RooNLLVarNew.cxx +++ b/roofit/roofitcore/src/RooNLLVarNew.cxx @@ -23,10 +23,13 @@ computation times. #include "RooNLLVarNew.h" +#include #include +#include #include #include #include +#include #include "RooFit/Detail/Buffers.h" #include @@ -39,8 +42,6 @@ computation times. #include #include -using namespace ROOT::Experimental; - // Declare constexpr static members to make them available if odr-used in C++14. constexpr const char *RooNLLVarNew::weightVarName; constexpr const char *RooNLLVarNew::weightVarNameSumW2; @@ -60,6 +61,60 @@ RooConstVar *dummyVar(const char *name) return new RooConstVar(name, name, 1.0); } +// Helper class to represent a template pdf based on the fit dataset. +class RooOffsetPdf : public RooAbsPdf { +public: + RooOffsetPdf(const char *name, const char *title, RooArgSet const &observables, RooAbsReal &weightVar) + : RooAbsPdf(name, title), + _observables("!observables", "List of observables", this), + _weightVar{"!weightVar", "weightVar", this, weightVar, true, false} + { + for (RooAbsArg *obs : observables) { + _observables.add(*obs); + } + } + RooOffsetPdf(const RooOffsetPdf &other, const char *name = nullptr) + : RooAbsPdf(other, name), + _observables("!servers", this, other._observables), + _weightVar{"!weightVar", this, other._weightVar} + { + } + TObject *clone(const char *newname) const override { return new RooOffsetPdf(*this, newname); } + + void computeBatch(double *output, size_t nEvents, RooFit::Detail::DataMap const &dataMap) const override + { + std::span weights = dataMap.at(_weightVar); + + // Create the template histogram from the data. This operation is very + // expensive, but since the offset only depends on the observables it + // only has to be done once. + + RooDataHist dataHist{"data", "data", _observables}; + // Loop over events to fill the histogram + for (std::size_t i = 0; i < nEvents; ++i) { + for (auto *var : static_range_cast(_observables)) { + var->setVal(dataMap.at(var)[i]); + } + dataHist.add(_observables, weights[weights.size() == 1 ? 0 : i]); + } + + // Lookup bin weights via RooHistPdf + RooHistPdf pdf{"offsetPdf", "offsetPdf", _observables, dataHist}; + for (std::size_t i = 0; i < nEvents; ++i) { + for (auto *var : static_range_cast(_observables)) { + var->setVal(dataMap.at(var)[i]); + } + output[i] = pdf.getVal(_observables); + } + } + +private: + double evaluate() const override { return 0.0; } // should never be called + + RooSetProxy _observables; + RooTemplateProxy _weightVar; +}; + } // namespace /** Construct a RooNLLVarNew @@ -75,7 +130,6 @@ RooNLLVarNew::RooNLLVarNew(const char *name, const char *title, RooAbsPdf &pdf, _pdf{"pdf", "pdf", this, pdf}, _weightVar{"weightVar", "weightVar", this, *dummyVar(weightVarName), true, false, true}, _weightSquaredVar{weightVarNameSumW2, weightVarNameSumW2, this, *dummyVar("weightSquardVar"), true, false, true}, - _binVolumeVar{"binVolumeVar", "binVolumeVar", this, *dummyVar("_bin_volume"), true, false, true}, _binnedL{pdf.getAttribute("BinnedLikelihoodActive")} { RooArgSet obs{getObs(pdf, observables)}; @@ -99,6 +153,12 @@ RooNLLVarNew::RooNLLVarNew(const char *name, const char *title, RooAbsPdf &pdf, resetWeightVarNames(); enableOffsetting(offsetMode == RooFit::OffsetMode::Initial); enableBinOffsetting(offsetMode == RooFit::OffsetMode::Bin); + + if (_doBinOffset) { + auto offsetPdf = std::make_unique("_offset_pdf", "_offset_pdf", observables, *_weightVar); + _offsetPdf = std::make_unique>("offsetPdf", "offsetPdf", this, *offsetPdf); + addOwnedComponents(std::move(offsetPdf)); + } } RooNLLVarNew::RooNLLVarNew(const RooNLLVarNew &other, const char *name) @@ -210,9 +270,8 @@ void RooNLLVarNew::computeBatch(double *output, size_t /*nOut*/, RooFit::Detail: : RooBatchCompute::reduceSum(config, weightsSumW2.data(), weightsSumW2.size()); } - auto nllOut = - RooBatchCompute::reduceNLL(config, probas, _weightSquared ? weightsSumW2 : weights, weights, _sumWeight, - _doBinOffset ? dataMap.at(_binVolumeVar) : std::span{}); + auto nllOut = RooBatchCompute::reduceNLL(config, probas, _weightSquared ? weightsSumW2 : weights, + _doBinOffset ? dataMap.at(*_offsetPdf) : std::span{}); if (nllOut.nLargeValues > 0) { oocoutW(&*_pdf, Eval) << "RooAbsPdf::getLogVal(" << _pdf->GetName() @@ -236,7 +295,7 @@ void RooNLLVarNew::computeBatch(double *output, size_t /*nOut*/, RooFit::Detail: void RooNLLVarNew::getParametersHook(const RooArgSet * /*nset*/, RooArgSet *params, bool /*stripDisconnected*/) const { // strip away the special variables - params->remove(RooArgList{*_weightVar, *_weightSquaredVar, *_binVolumeVar}, true, true); + params->remove(RooArgList{*_weightVar, *_weightSquaredVar}, true, true); } //////////////////////////////////////////////////////////////////////////////// @@ -254,7 +313,9 @@ void RooNLLVarNew::resetWeightVarNames() { _weightVar->SetName((_prefix + weightVarName).c_str()); _weightSquaredVar->SetName((_prefix + weightVarNameSumW2).c_str()); - _binVolumeVar->SetName((_prefix + "_bin_volume").c_str()); + if (_offsetPdf) { + _offsetPdf->SetName((_prefix + "_offset_pdf").c_str()); + } } //////////////////////////////////////////////////////////////////////////////// diff --git a/roofit/roofitcore/src/RooNLLVarNew.h b/roofit/roofitcore/src/RooNLLVarNew.h index 58d5c0a8b54aa..3bd072c1e604f 100644 --- a/roofit/roofitcore/src/RooNLLVarNew.h +++ b/roofit/roofitcore/src/RooNLLVarNew.h @@ -21,9 +21,6 @@ #include -namespace ROOT { -namespace Experimental { - class RooNLLVarNew : public RooAbsReal { public: @@ -31,7 +28,6 @@ class RooNLLVarNew : public RooAbsReal { static constexpr const char *weightVarName = "_weight"; static constexpr const char *weightVarNameSumW2 = "_weight_sumW2"; - RooNLLVarNew() {} RooNLLVarNew(const char *name, const char *title, RooAbsPdf &pdf, RooArgSet const &observables, bool isExtended, RooFit::OffsetMode offsetMode); RooNLLVarNew(const RooNLLVarNew &other, const char *name = nullptr); @@ -68,8 +64,8 @@ class RooNLLVarNew : public RooAbsReal { RooTemplateProxy _pdf; RooTemplateProxy _weightVar; RooTemplateProxy _weightSquaredVar; - RooTemplateProxy _binVolumeVar; std::unique_ptr> _expectedEvents; + std::unique_ptr> _offsetPdf; mutable double _sumWeight = 0.0; //! mutable double _sumWeight2 = 0.0; //! bool _weightSquared = false; @@ -83,7 +79,4 @@ class RooNLLVarNew : public RooAbsReal { }; // end class RooNLLVar -} // end namespace Experimental -} // end namespace ROOT - #endif diff --git a/roofit/roofitcore/test/testTestStatistics.cxx b/roofit/roofitcore/test/testTestStatistics.cxx index ce9d0406d8bc4..4de8a271f5f6c 100644 --- a/roofit/roofitcore/test/testTestStatistics.cxx +++ b/roofit/roofitcore/test/testTestStatistics.cxx @@ -2,20 +2,20 @@ // Authors: Stephan Hageboeck, CERN 10/2020 // Jonas Rembser, CERN 10/2022 -#include #include #include #include #include +#include #include #include #include #include #include -#include #include #include #include +#include #include #include #include @@ -456,7 +456,7 @@ TEST_P(OffsetBinTest, CrossCheck) // Create template PDF based on data RooHistPdf histPdf{"histPdf", "histPdf", x, *hist}; - RooAddPdf extHistPdf("extHistPdf", "extHistPdf", histPdf, nEvents); + RooExtendPdf extHistPdf("extHistPdf", "extHistPdf", histPdf, nEvents); RooAbsData *fitData = _binned ? static_cast(hist.get()) : static_cast(data.get()); @@ -535,25 +535,30 @@ TEST_P(TestStatisticTest, BinnedLikelihood) EXPECT_DOUBLE_EQ(prodNllVal, simNllVal); } -INSTANTIATE_TEST_SUITE_P(RooNLLVar, TestStatisticTest, testing::Values("Off", "Cpu"), +#ifdef R__HAS_CUDA +#define BATCH_MODE_VALS "Off", "Cpu", "Cuda" +#else +#define BATCH_MODE_VALS "Off", "Cpu" +#endif + +INSTANTIATE_TEST_SUITE_P(RooNLLVar, TestStatisticTest, testing::Values(BATCH_MODE_VALS), [](testing::TestParamInfo const ¶mInfo) { std::stringstream ss; ss << "BatchMode" << std::get<0>(paramInfo.param); return ss.str(); }); -INSTANTIATE_TEST_SUITE_P( - RooNLLVar, OffsetBinTest, - testing::Combine(testing::Values("Off", "Cpu"), // BatchMode - testing::Values(true), // unbinned or binned (we don't support unbinned fits yet) - testing::Values(false, true), // extended fit - testing::Values(false, true) // use sumW2 - ), - [](testing::TestParamInfo const ¶mInfo) { - std::stringstream ss; - ss << "BatchMode" << std::get<0>(paramInfo.param); - ss << (std::get<1>(paramInfo.param) ? "Binned" : "Unbinned"); - ss << (std::get<2>(paramInfo.param) ? "Extended" : ""); - ss << (std::get<3>(paramInfo.param) ? "SumW2" : ""); - return ss.str(); - }); +INSTANTIATE_TEST_SUITE_P(RooNLLVar, OffsetBinTest, + testing::Combine(testing::Values(BATCH_MODE_VALS), // BatchMode + testing::Values(false, true), // unbinned or binned + testing::Values(false, true), // extended fit + testing::Values(false, true) // use sumW2 + ), + [](testing::TestParamInfo const ¶mInfo) { + std::stringstream ss; + ss << "BatchMode" << std::get<0>(paramInfo.param); + ss << (std::get<1>(paramInfo.param) ? "Binned" : "Unbinned"); + ss << (std::get<2>(paramInfo.param) ? "Extended" : ""); + ss << (std::get<3>(paramInfo.param) ? "SumW2" : ""); + return ss.str(); + }); diff --git a/tutorials/roofit/rf614_binned_fit_problems.C b/tutorials/roofit/rf614_binned_fit_problems.C index 16ec253231b97..060a3a3c4196f 100644 --- a/tutorials/roofit/rf614_binned_fit_problems.C +++ b/tutorials/roofit/rf614_binned_fit_problems.C @@ -184,8 +184,7 @@ void rf614_binned_fit_problems() // initial model is not extremely off. Proving this mathematically is left // as an excercise to the reader. - // This counterterms can be enabled in RooFit if you use a binned - // RooDataHist to do your fit and pass the Offset("bin") option to + // This counterterms can be enabled by passing the Offset("bin") option to // RooAbsPdf::fitTo() or RooAbsPdf::createNLL(). std::unique_ptr fit7{ diff --git a/tutorials/roofit/rf614_binned_fit_problems.py b/tutorials/roofit/rf614_binned_fit_problems.py index 70f56661bed1b..8ccd0c8d3fade 100644 --- a/tutorials/roofit/rf614_binned_fit_problems.py +++ b/tutorials/roofit/rf614_binned_fit_problems.py @@ -188,8 +188,7 @@ def disableBinIntegrator(func): # initial model is not extremely off. Proving this mathematically is left # as an excercise to the reader. -# This counterterms can be enabled in RooFit if you use a binned -# RooDataHist to do your fit and pass the Offset("bin") option to +# This counterterms can be enabled by passing the Offset("bin") option to # RooAbsPdf::fitTo() or RooAbsPdf::createNLL(). fit7 = model.fitTo(model_data, Offset="bin", Save=True, PrintLevel=-1, SumW2Error=False)