diff --git a/roofit/roofitcore/inc/RooAbsRealLValue.h b/roofit/roofitcore/inc/RooAbsRealLValue.h index 38b27cb402285..849a33509d47d 100644 --- a/roofit/roofitcore/inc/RooAbsRealLValue.h +++ b/roofit/roofitcore/inc/RooAbsRealLValue.h @@ -67,9 +67,9 @@ class RooAbsRealLValue : public RooAbsReal, public RooAbsLValue { // Get fit range limits /// Retrieve binning configuration with given name or default binning. - virtual const RooAbsBinning& getBinning(const char* name=nullptr, bool verbose=true, bool createOnTheFly=false) const = 0 ; + virtual const RooAbsBinning& getBinning(const char* name=nullptr, bool verbose=true, bool createOnTheFly=false, bool shared=true) const = 0 ; /// Retrieve binning configuration with given name or default binning. - virtual RooAbsBinning& getBinning(const char* name=nullptr, bool verbose=true, bool createOnTheFly=false) = 0 ; + virtual RooAbsBinning& getBinning(const char* name=nullptr, bool verbose=true, bool createOnTheFly=false, bool shared=true) = 0 ; /// Check if binning with given name has been defined. virtual bool hasBinning(const char* name) const = 0 ; bool inRange(const char* name) const override ; diff --git a/roofit/roofitcore/inc/RooErrorVar.h b/roofit/roofitcore/inc/RooErrorVar.h index 086a9f2fe6c97..2b35f8be518a1 100644 --- a/roofit/roofitcore/inc/RooErrorVar.h +++ b/roofit/roofitcore/inc/RooErrorVar.h @@ -76,8 +76,8 @@ class RooErrorVar : public RooAbsRealLValue { void setBins(Int_t nBins); void setBinning(const RooAbsBinning& binning, const char* name=nullptr) ; - const RooAbsBinning& getBinning(const char* name=nullptr, bool verbose=true, bool createOnTheFly=false) const override ; - RooAbsBinning& getBinning(const char* name=nullptr, bool verbose=true, bool createOnTheFly=false) override ; + const RooAbsBinning& getBinning(const char* name=nullptr, bool verbose=true, bool createOnTheFly=false, bool shared=true) const override ; + RooAbsBinning& getBinning(const char* name=nullptr, bool verbose=true, bool createOnTheFly=false, bool shared=true) override ; bool hasBinning(const char* name) const override ; std::list getBinningNames() const override ; diff --git a/roofit/roofitcore/inc/RooLinearVar.h b/roofit/roofitcore/inc/RooLinearVar.h index 720d7f6008f5b..1170e32ffa80b 100644 --- a/roofit/roofitcore/inc/RooLinearVar.h +++ b/roofit/roofitcore/inc/RooLinearVar.h @@ -40,8 +40,8 @@ class RooLinearVar : public RooAbsRealLValue { // Jacobian and limits bool hasBinning(const char* name) const override ; - const RooAbsBinning& getBinning(const char* name=nullptr, bool verbose=true, bool createOnTheFly=false) const override ; - RooAbsBinning& getBinning(const char* name=nullptr, bool verbose=true, bool createOnTheFly=false) override ; + const RooAbsBinning& getBinning(const char* name=nullptr, bool verbose=true, bool createOnTheFly=false, bool shared=true) const override ; + RooAbsBinning& getBinning(const char* name=nullptr, bool verbose=true, bool createOnTheFly=false, bool shared=true) override ; std::list getBinningNames() const override; double jacobian() const override ; diff --git a/roofit/roofitcore/inc/RooRealVar.h b/roofit/roofitcore/inc/RooRealVar.h index 3261b18d632ee..971c5b906d7ae 100644 --- a/roofit/roofitcore/inc/RooRealVar.h +++ b/roofit/roofitcore/inc/RooRealVar.h @@ -71,10 +71,10 @@ class RooRealVar : public RooAbsRealLValue { RooErrorVar* errorVar() const ; // Set/get finite fit range limits - void setMin(const char* name, double value) ; - void setMax(const char* name, double value) ; - void setRange(const char* name, double min, double max) ; - void setRange(const char* name, RooAbsReal& min, RooAbsReal& max) ; + void setMin(const char* name, double value, bool shared=true) ; + void setMax(const char* name, double value, bool shared=true) ; + void setRange(const char* name, double min, double max, bool shared=true) ; + void setRange(const char* name, RooAbsReal& min, RooAbsReal& max, bool shared=true) ; inline void setMin(double value) { setMin(nullptr,value) ; } inline void setMax(double value) { setMax(nullptr,value) ; } /// Set the limits of the default range. @@ -82,13 +82,13 @@ class RooRealVar : public RooAbsRealLValue { /// Set parameterised limits of the default range. See setRange(const char*, RooAbsReal&, RooAbsReal&). inline void setRange(RooAbsReal& min, RooAbsReal& max) { setRange(nullptr,min,max) ; } - void setBins(Int_t nBins, const char* name=nullptr); - void setBinning(const RooAbsBinning& binning, const char* name=nullptr) ; + void setBins(Int_t nBins, const char* name=nullptr, bool shared=true); + void setBinning(const RooAbsBinning& binning, const char* name=nullptr, bool shared=true) ; // RooAbsRealLValue implementation bool hasBinning(const char* name) const override ; - const RooAbsBinning& getBinning(const char* name=nullptr, bool verbose=true, bool createOnTheFly=false) const override ; - RooAbsBinning& getBinning(const char* name=nullptr, bool verbose=true, bool createOnTheFly=false) override ; + const RooAbsBinning& getBinning(const char* name=nullptr, bool verbose=true, bool createOnTheFly=false, bool shared=true) const override ; + RooAbsBinning& getBinning(const char* name=nullptr, bool verbose=true, bool createOnTheFly=false, bool shared=true) override ; std::list getBinningNames() const override ; /// remove a named binning (or a named range, which are stored internally as binnings) diff --git a/roofit/roofitcore/src/RooErrorVar.cxx b/roofit/roofitcore/src/RooErrorVar.cxx index fb6f2a6063fc5..68c44a1173e5b 100644 --- a/roofit/roofitcore/src/RooErrorVar.cxx +++ b/roofit/roofitcore/src/RooErrorVar.cxx @@ -86,9 +86,9 @@ bool RooErrorVar::hasBinning(const char* name) const /// Return binning with given name. If no binning exists with such a name, clone the default /// binning on the fly if so requested -const RooAbsBinning& RooErrorVar::getBinning(const char* name, bool verbose, bool createOnTheFly) const +const RooAbsBinning& RooErrorVar::getBinning(const char* name, bool verbose, bool createOnTheFly, bool shared) const { - return const_cast(this)->getBinning(name,verbose,createOnTheFly) ; + return const_cast(this)->getBinning(name,verbose,createOnTheFly, shared) ; } @@ -97,7 +97,7 @@ const RooAbsBinning& RooErrorVar::getBinning(const char* name, bool verbose, boo /// Return binning with given name. If no binning exists with such a name, clone the default /// binning on the fly if so requested -RooAbsBinning& RooErrorVar::getBinning(const char* name, bool /*verbose*/, bool createOnTheFly) +RooAbsBinning& RooErrorVar::getBinning(const char* name, bool /*verbose*/, bool createOnTheFly, bool) { // Return default (normalization) binning and range if no name is specified if (name==nullptr) { diff --git a/roofit/roofitcore/src/RooLinearVar.cxx b/roofit/roofitcore/src/RooLinearVar.cxx index 8ac0d36104a5c..07bae788acb4f 100644 --- a/roofit/roofitcore/src/RooLinearVar.cxx +++ b/roofit/roofitcore/src/RooLinearVar.cxx @@ -202,7 +202,7 @@ void RooLinearVar::writeToStream(std::ostream& os, bool compact) const /// binning exists on the input variable, it will also exist on this linear transformation, /// and a binning adaptor object is created on the fly. - RooAbsBinning& RooLinearVar::getBinning(const char* name, bool verbose, bool createOnTheFly) + RooAbsBinning& RooLinearVar::getBinning(const char* name, bool verbose, bool createOnTheFly, bool) { // Normalization binning if (name==nullptr) { @@ -234,7 +234,7 @@ void RooLinearVar::writeToStream(std::ostream& os, bool compact) const //////////////////////////////////////////////////////////////////////////////// /// Const version of getBinning() -const RooAbsBinning& RooLinearVar::getBinning(const char* name, bool verbose, bool createOnTheFly) const +const RooAbsBinning& RooLinearVar::getBinning(const char* name, bool verbose, bool createOnTheFly, bool) const { return const_cast(this)->getBinning(name,verbose,createOnTheFly) ; } diff --git a/roofit/roofitcore/src/RooRealVar.cxx b/roofit/roofitcore/src/RooRealVar.cxx index 3044763dc6b84..6e15aca664d08 100644 --- a/roofit/roofitcore/src/RooRealVar.cxx +++ b/roofit/roofitcore/src/RooRealVar.cxx @@ -350,7 +350,7 @@ RooErrorVar* RooRealVar::errorVar() const bool RooRealVar::hasBinning(const char* name) const { - return sharedProp()->_altBinning.find(name) != sharedProp()->_altBinning.end(); + return sharedProp()->_altBinning.find(name) != sharedProp()->_altBinning.end() || _altNonSharedBinning.find(name) != _altNonSharedBinning.end(); } @@ -361,9 +361,9 @@ bool RooRealVar::hasBinning(const char* name) const /// a reference to the default binning is returned. If verbose is true a message /// is printed if a binning is created on the fly. -const RooAbsBinning& RooRealVar::getBinning(const char* name, bool verbose, bool createOnTheFly) const +const RooAbsBinning& RooRealVar::getBinning(const char* name, bool verbose, bool createOnTheFly, bool shared) const { - return const_cast(this)->getBinning(name, verbose, createOnTheFly) ; + return const_cast(this)->getBinning(name, verbose, createOnTheFly, shared) ; } @@ -374,7 +374,7 @@ const RooAbsBinning& RooRealVar::getBinning(const char* name, bool verbose, bool /// a reference to the default binning is returned. If verbose is true a message /// is printed if a binning is created on the fly. -RooAbsBinning& RooRealVar::getBinning(const char* name, bool verbose, bool createOnTheFly) +RooAbsBinning& RooRealVar::getBinning(const char* name, bool verbose, bool createOnTheFly, bool shared) { // Return default (normalization) binning and range if no name is specified if (name==nullptr) { @@ -410,7 +410,11 @@ RooAbsBinning& RooRealVar::getBinning(const char* name, bool verbose, bool creat coutI(Eval) << "RooRealVar::getBinning(" << GetName() << ") new range named '" << name << "' created with default bounds" << std::endl ; } - sharedProp()->_altBinning[name] = binning; + if(shared) { + sharedProp()->_altBinning[name] = binning; + } else { + _altNonSharedBinning[name].reset(binning); + } return *binning ; } @@ -474,14 +478,14 @@ void RooRealVar::removeRange(const char* name) { /// Create a uniform binning under name 'name' for this variable. /// \param[in] nBins Number of bins. The limits are taken from the currently set limits. /// \param[in] name Optional name. If name is null, install as default binning. -void RooRealVar::setBins(Int_t nBins, const char* name) { - setBinning(RooUniformBinning(getMin(name),getMax(name),nBins),name); +void RooRealVar::setBins(Int_t nBins, const char* name, bool shared) { + setBinning(RooUniformBinning(getMin(name),getMax(name),nBins),name,shared); } //////////////////////////////////////////////////////////////////////////////// /// Add given binning under name 'name' with this variable. If name is null, /// the binning is installed as the default binning. -void RooRealVar::setBinning(const RooAbsBinning& binning, const char* name) +void RooRealVar::setBinning(const RooAbsBinning& binning, const char* name, bool shared) { std::unique_ptr newBinning( binning.clone() ); @@ -500,7 +504,7 @@ void RooRealVar::setBinning(const RooAbsBinning& binning, const char* name) newBinning->SetName(name) ; newBinning->SetTitle(name) ; newBinning->insertHook(*this) ; - if (newBinning->isShareable()) { + if (newBinning->isShareable() && shared) { sharedProp()->_altBinning[name] = newBinning.release(); } else { _altNonSharedBinning[name] = std::move(newBinning); @@ -514,10 +518,10 @@ void RooRealVar::setBinning(const RooAbsBinning& binning, const char* name) /// Set minimum of name range to given value. If name is null /// minimum of default range is set -void RooRealVar::setMin(const char* name, double value) +void RooRealVar::setMin(const char* name, double value, bool shared) { // Set new minimum of fit range - RooAbsBinning& binning = getBinning(name,true,true) ; + RooAbsBinning& binning = getBinning(name,true,true,shared) ; // Check if new limit is consistent if (value >= getMax()) { @@ -544,10 +548,10 @@ void RooRealVar::setMin(const char* name, double value) /// Set maximum of name range to given value. If name is null /// maximum of default range is set -void RooRealVar::setMax(const char* name, double value) +void RooRealVar::setMax(const char* name, double value, bool shared) { // Set new maximum of fit range - RooAbsBinning& binning = getBinning(name,true,true) ; + RooAbsBinning& binning = getBinning(name,true,true,shared) ; // Check if new limit is consistent if (value < getMin()) { @@ -579,12 +583,12 @@ void RooRealVar::setMax(const char* name, double value) /// plotting). If the name is `nullptr`, the function sets the limits of the default range. /// \param[in] min Miniminum of the range. /// \param[in] max Maximum of the range. -void RooRealVar::setRange(const char* name, double min, double max) +void RooRealVar::setRange(const char* name, double min, double max, bool shared) { - bool exists = name == nullptr || sharedProp()->_altBinning.count(name) > 0; + bool exists = name == nullptr || sharedProp()->_altBinning.count(name) > 0 || _altNonSharedBinning.count(name) > 0; // Set new fit range - RooAbsBinning& binning = getBinning(name,false,true) ; + RooAbsBinning& binning = getBinning(name,false,true,shared) ; // Check if new limit is consistent if (min>max) { @@ -610,10 +614,10 @@ void RooRealVar::setRange(const char* name, double min, double max) /// Set or modify a parameterised range, i.e., a range the varies in dependence /// of parameters. /// See setRange() for more details. -void RooRealVar::setRange(const char* name, RooAbsReal& min, RooAbsReal& max) +void RooRealVar::setRange(const char* name, RooAbsReal& min, RooAbsReal& max, bool shared) { RooParamBinning pb(min,max,100) ; - setBinning(pb,name) ; + setBinning(pb,name,shared) ; } diff --git a/roofit/roofitcore/test/testRooRealVar.cxx b/roofit/roofitcore/test/testRooRealVar.cxx index 54f398e1124be..281d8aeca9f07 100644 --- a/roofit/roofitcore/test/testRooRealVar.cxx +++ b/roofit/roofitcore/test/testRooRealVar.cxx @@ -52,6 +52,18 @@ TEST(RooRealVar, AlternativeBinnings) var.removeBinning("uniform"); EXPECT_FALSE( var.hasBinning("uniform") ); + // test creating and removing non-shared binnings/ranges + EXPECT_FALSE( var.hasRange("myRange") ); + var.setRange("myRange",0,1,false); + EXPECT_TRUE( var.hasRange("myRange") ); + std::unique_ptr var2(dynamic_cast(var.clone())); + var2->setRange("myRange",1,2); + EXPECT_EQ( var.getMin("myRange"), 0. ); // still has old range, because not shared + EXPECT_EQ( var2->getMin("myRange"), 1. ); + var2->removeBinning("myRange"); + EXPECT_FALSE( var2->hasRange("myRange") ); + EXPECT_TRUE( var.hasRange("myRange") ); + } /// ROOT-10781