diff --git a/hist/hist/inc/TF1.h b/hist/hist/inc/TF1.h index ea3f36c1b0862..ba5d6eaf9a145 100644 --- a/hist/hist/inc/TF1.h +++ b/hist/hist/inc/TF1.h @@ -36,6 +36,8 @@ #include "Math/Types.h" #include "Math/ParamFunctor.h" +#include + class TF1; class TH1; class TAxis; @@ -109,9 +111,8 @@ class TF1Parameters { { std::copy(params, params + fParameters.size(), fParameters.begin()); } - void SetParameters(Double_t p0, Double_t p1, Double_t p2 = 0, Double_t p3 = 0, Double_t p4 = 0, - Double_t p5 = 0, Double_t p6 = 0, Double_t p7 = 0, Double_t p8 = 0, - Double_t p9 = 0, Double_t p10 = 0); + template + void SetParameters(Double_t arg1, Args &&... args); void SetParameter(const char *name, Double_t value) { @@ -122,12 +123,8 @@ class TF1Parameters { if (!CheckIndex(iparam)) return; fParNames[iparam] = std::string(name); } - void SetParNames(const char *name0 = "p0", const char *name1 = "p1", const char *name2 = "p2", - const char *name3 = "p3", const char *name4 = "p4", const char *name5 = "p5", - const char *name6 = "p6", const char *name7 = "p7", const char *name8 = "p8", - const char *name9 = "p9", const char *name10 = "p10"); - - + template + void SetParNames(Args &&... args); ClassDef(TF1Parameters, 1) // The Parameters of a parameteric function private: @@ -141,6 +138,28 @@ class TF1Parameters { std::vector fParNames; // parameter names }; +/// Set parameter values. +/// NaN values will be skipped, meaning that the corresponding parameters will not be changed. +template +void TF1Parameters::SetParameters(Double_t arg1, Args &&...args) +{ + int i = 0; + for (double val : {arg1, static_cast(args)...}) { + if(!TMath::IsNaN(val)) SetParameter(i++, val); + } +} + +/// Set parameter names. +/// Empty strings will be skipped, meaning that the corresponding name will not be changed. +template +void TF1Parameters::SetParNames(Args &&...args) +{ + int i = 0; + for (auto name : {static_cast(args)...}) { + if(!name.empty()) SetParName(i++, name.c_str()); + } +} + namespace ROOT { namespace Internal { /// %Internal class used by TF1 for defining @@ -651,19 +670,27 @@ class TF1 : public TNamed, public TAttLine, public TAttFill, public TAttMarker { (fFormula) ? fFormula->SetParameters(params) : fParams->SetParameters(params); Update(); } - virtual void SetParameters(double p0, double p1 = 0.0, double p2 = 0.0, double p3 = 0.0, double p4 = 0.0, - double p5 = 0.0, double p6 = 0.0, double p7 = 0.0, double p8 = 0.0, - double p9 = 0.0, double p10 = 0.0) - { + /// Set parameter values. + /// NaN values will be skipped, meaning that the corresponding parameters will not be changed. + virtual void SetParameters(double p0, double p1 = TMath::QuietNaN(), double p2 = TMath::QuietNaN(), + double p3 = TMath::QuietNaN(), double p4 = TMath::QuietNaN(), double p5 = TMath::QuietNaN(), + double p6 = TMath::QuietNaN(), double p7 = TMath::QuietNaN(), double p8 = TMath::QuietNaN(), + double p9 = TMath::QuietNaN(), double p10 = TMath::QuietNaN()) + { + // Note: this is not made a variadic template method because it would + // presumably break the context menu in the TBrowser. Also, probably this + // method should not be virtual, because if the user wants to change + // parameter setting behavior, the SetParameter() method can be + // overridden. if (fFormula) fFormula->SetParameters(p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10); else fParams->SetParameters(p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10); Update(); } // *MENU* virtual void SetParName(Int_t ipar, const char *name); - virtual void SetParNames(const char *name0 = "p0", const char *name1 = "p1", const char *name2 = "p2", - const char *name3 = "p3", const char *name4 = "p4", const char *name5 = "p5", - const char *name6 = "p6", const char *name7 = "p7", const char *name8 = "p8", - const char *name9 = "p9", const char *name10 = "p10"); // *MENU* + virtual void SetParNames(const char *name0 = "", const char *name1 = "", const char *name2 = "", + const char *name3 = "", const char *name4 = "", const char *name5 = "", + const char *name6 = "", const char *name7 = "", const char *name8 = "", + const char *name9 = "", const char *name10 = ""); // *MENU* virtual void SetParError(Int_t ipar, Double_t error); virtual void SetParErrors(const Double_t *errors); virtual void SetParLimits(Int_t ipar, Double_t parmin, Double_t parmax); diff --git a/hist/hist/inc/TFormula.h b/hist/hist/inc/TFormula.h index c0dea4f2eb302..6ad9f7b670093 100644 --- a/hist/hist/inc/TFormula.h +++ b/hist/hist/inc/TFormula.h @@ -15,13 +15,15 @@ #include "TNamed.h" #include "TBits.h" #include "TInterpreter.h" +#include "TMath.h" +#include + +#include #include -#include #include #include #include -#include -#include +#include class TMethodCall; @@ -274,18 +276,42 @@ class TFormula : public TNamed void SetParameter(Int_t param, Double_t value); void SetParameters(const Double_t *params); //void SetParameters(const pair *params, const Int_t size); - void SetParameters(Double_t p0,Double_t p1,Double_t p2=0,Double_t p3=0,Double_t p4=0, - Double_t p5=0,Double_t p6=0,Double_t p7=0,Double_t p8=0, - Double_t p9=0,Double_t p10=0); // *MENU* + template + void SetParameters(Double_t arg1, Args &&... args); void SetParName(Int_t ipar, const char *name); - void SetParNames(const char *name0="p0",const char *name1="p1",const char - *name2="p2",const char *name3="p3",const char - *name4="p4", const char *name5="p5",const char *name6="p6",const char *name7="p7",const char - *name8="p8",const char *name9="p9",const char *name10="p10"); // *MENU* + template + void SetParNames(Args &&... args); void SetVariable(const TString &name, Double_t value); void SetVariables(const std::pair *vars, const Int_t size); void SetVectorized(Bool_t vectorized); ClassDefOverride(TFormula,13) }; + +//////////////////////////////////////////////////////////////////////////////// +/// Set a list of parameters. +/// The order is by default the alphabetic order given to the parameters, +/// apart if the users has defined explicitly the parameter names. +/// NaN values will be skipped, meaning that the corresponding parameters will not be changed. + +template +void TFormula::SetParameters(Double_t arg1, Args &&...args) +{ + int i = 0; + for (double val : {arg1, static_cast(args)...}) { + if(!TMath::IsNaN(val)) SetParameter(i++, val); + } +} + +//////////////////////////////////////////////////////////////////////////////// +/// Set parameter names. +/// Empty strings will be skipped, meaning that the corresponding name will not be changed. +template +void TFormula::SetParNames(Args &&...args) +{ + int i = 0; + for (auto name : {static_cast(args)...}) { + if(!name.empty()) SetParName(i++, name.c_str()); + } +} #endif diff --git a/hist/hist/src/TF1.cxx b/hist/hist/src/TF1.cxx index daa06a0ce45f2..1d5093060f4a7 100644 --- a/hist/hist/src/TF1.cxx +++ b/hist/hist/src/TF1.cxx @@ -3455,11 +3455,17 @@ void TF1::SetParName(Int_t ipar, const char *name) } //////////////////////////////////////////////////////////////////////////////// -/// Set up to 10 parameter names +/// Set up to 10 parameter names. +/// Empty strings will be skipped, meaning that the corresponding name will not be changed. void TF1::SetParNames(const char *name0, const char *name1, const char *name2, const char *name3, const char *name4, const char *name5, const char *name6, const char *name7, const char *name8, const char *name9, const char *name10) { + // Note: this is not made a variadic template method because it would + // presumably break the context menu in the TBrowser. Also, probably this + // method should not be virtual, because if the user wants to change + // parameter name setting behavior, the SetParName() method can be + // overridden. if (fFormula) fFormula->SetParNames(name0, name1, name2, name3, name4, name5, name6, name7, name8, name9, name10); else @@ -3813,45 +3819,3 @@ Int_t TF1Parameters::GetParNumber(const char *name) const } return -1; } - -//////////////////////////////////////////////////////////////////////////////// -/// Set parameter values - -void TF1Parameters::SetParameters(Double_t p0, Double_t p1, Double_t p2, Double_t p3, Double_t p4, - Double_t p5, Double_t p6, Double_t p7, Double_t p8, - Double_t p9, Double_t p10) -{ - unsigned int npar = fParameters.size(); - if (npar > 0) fParameters[0] = p0; - if (npar > 1) fParameters[1] = p1; - if (npar > 2) fParameters[2] = p2; - if (npar > 3) fParameters[3] = p3; - if (npar > 4) fParameters[4] = p4; - if (npar > 5) fParameters[5] = p5; - if (npar > 6) fParameters[6] = p6; - if (npar > 7) fParameters[7] = p7; - if (npar > 8) fParameters[8] = p8; - if (npar > 9) fParameters[9] = p9; - if (npar > 10) fParameters[10] = p10; -} - -//////////////////////////////////////////////////////////////////////////////// -/// Set parameter names - -void TF1Parameters::SetParNames(const char *name0, const char *name1, const char *name2, const char *name3, - const char *name4, const char *name5, const char *name6, const char *name7, - const char *name8, const char *name9, const char *name10) -{ - unsigned int npar = fParNames.size(); - if (npar > 0) fParNames[0] = name0; - if (npar > 1) fParNames[1] = name1; - if (npar > 2) fParNames[2] = name2; - if (npar > 3) fParNames[3] = name3; - if (npar > 4) fParNames[4] = name4; - if (npar > 5) fParNames[5] = name5; - if (npar > 6) fParNames[6] = name6; - if (npar > 7) fParNames[7] = name7; - if (npar > 8) fParNames[8] = name8; - if (npar > 9) fParNames[9] = name9; - if (npar > 10) fParNames[10] = name10; -} diff --git a/hist/hist/src/TFormula.cxx b/hist/hist/src/TFormula.cxx index dfbf336d11205..a5f4f0c0b0daf 100644 --- a/hist/hist/src/TFormula.cxx +++ b/hist/hist/src/TFormula.cxx @@ -12,7 +12,6 @@ #include "TROOT.h" #include "TBuffer.h" #include "TMethod.h" -#include "TMath.h" #include "TF1.h" #include "TMethodCall.h" #include @@ -25,7 +24,6 @@ #include "ROOT/StringUtils.hxx" #include -#include #include #include #include @@ -2974,30 +2972,9 @@ void TFormula::SetParameters(const Double_t *params) } //////////////////////////////////////////////////////////////////////////////// -/// Set a list of parameters. -/// The order is by default the alphabetic order given to the parameters -/// apart if the users has defined explicitly the parameter names - -void TFormula::SetParameters(Double_t p0, Double_t p1, Double_t p2, Double_t p3, Double_t p4, Double_t p5, Double_t p6, - Double_t p7, Double_t p8, Double_t p9, Double_t p10) -{ - if(fNpar >= 1) SetParameter(0,p0); - if(fNpar >= 2) SetParameter(1,p1); - if(fNpar >= 3) SetParameter(2,p2); - if(fNpar >= 4) SetParameter(3,p3); - if(fNpar >= 5) SetParameter(4,p4); - if(fNpar >= 6) SetParameter(5,p5); - if(fNpar >= 7) SetParameter(6,p6); - if(fNpar >= 8) SetParameter(7,p7); - if(fNpar >= 9) SetParameter(8,p8); - if(fNpar >= 10) SetParameter(9,p9); - if(fNpar >= 11) SetParameter(10,p10); -} - -//////////////////////////////////////////////////////////////////////////////// -/// Set a parameter given a parameter index -/// The parameter index is by default the alphabetic order given to the parameters -/// apart if the users has defined explicitly the parameter names +/// Set a parameter given a parameter index. +/// The parameter index is by default the alphabetic order given to the parameters, +/// apart if the users has defined explicitly the parameter names. void TFormula::SetParameter(Int_t param, Double_t value) { @@ -3008,35 +2985,6 @@ void TFormula::SetParameter(Int_t param, Double_t value) // SetParameter(name,value); } -//////////////////////////////////////////////////////////////////////////////// -void TFormula::SetParNames(const char *name0, const char *name1, const char *name2, const char *name3, - const char *name4, const char *name5, const char *name6, const char *name7, - const char *name8, const char *name9, const char *name10) -{ - if (fNpar >= 1) - SetParName(0, name0); - if (fNpar >= 2) - SetParName(1, name1); - if (fNpar >= 3) - SetParName(2, name2); - if (fNpar >= 4) - SetParName(3, name3); - if (fNpar >= 5) - SetParName(4, name4); - if (fNpar >= 6) - SetParName(5, name5); - if (fNpar >= 7) - SetParName(6, name6); - if (fNpar >= 8) - SetParName(7, name7); - if (fNpar >= 9) - SetParName(8, name8); - if (fNpar >= 10) - SetParName(9, name9); - if (fNpar >= 11) - SetParName(10, name10); -} - //////////////////////////////////////////////////////////////////////////////// void TFormula::SetParName(Int_t ipar, const char * name) {