28 template<
class Iterator>
29 void FixDuplicateNames(Iterator begin, Iterator end) {
33 std::multimap<TString, int > parMap;
34 for (Iterator it = begin; it != end; ++it) {
35 parMap.insert( std::make_pair( *it, std::distance(begin,it) ) );
37 for (
auto & elem : parMap) {
38 TString name = elem.first;
39 int n = parMap.count( name);
41 std::pair <std::multimap<TString,int>::iterator, std::multimap<TString,int>::iterator> ret;
42 ret = parMap.equal_range(name);
44 for (std::multimap<TString,int>::iterator it=ret.first; it!=ret.second; ++it) {
45 *(begin+it->second) = TString::Format(
"%s%d",name.Data(),++i);
54 void TF1NormSum::InitializeDataMembers(
const std::vector<TF1 *> &functions,
const std::vector<Double_t> &coeffs,
60 fNOfFunctions = functions.size();
61 fCstIndexes = std::vector < Int_t > (fNOfFunctions);
62 fParNames = std::vector<TString> (fNOfFunctions);
63 fParNames.reserve(3*fNOfFunctions);
66 fFunctions = std::vector<std::unique_ptr<TF1>>(functions.size());
67 for (
unsigned int n = 0; n < fNOfFunctions; n++) {
70 TF1 * f = (TF1*) functions[n]->IsA()->New();
71 functions[n]->Copy(*f);
72 fFunctions[n] = std::unique_ptr<TF1>(f);
76 Fatal(
"InitializeDataMembers",
"Invalid input function -- abort");
78 fFunctions[n]->SetBit(TF1::kNotGlobal, kTRUE);
81 for (
unsigned int n=0; n < fNOfFunctions; n++)
83 int npar = fFunctions[n] -> GetNpar();
84 fCstIndexes[n] = fFunctions[n] -> GetParNumber(
"Constant");
85 fParNames[n] = TString::Format(
"Coeff%d",n);
86 if (fCstIndexes[n]!= -1)
88 fFunctions[n] -> FixParameter(fCstIndexes[n], 1.);
90 for (
int i=0; i<npar; i++)
92 if (i==fCstIndexes[n])
continue;
93 fParNames.push_back( fFunctions[n] -> GetParName(i) );
98 for (
int i=0; i < npar; i++)
100 fParNames.push_back( fFunctions[n] -> GetParName(i) );
104 if (!fFunctions[n] -> IsEvalNormalized()) fFunctions[n] -> SetNormalized(
true);
108 if (fNOfFunctions == 0) {
113 fFunctions[0]->GetRange(fXmin, fXmax);
114 if (fXmin >= fXmax) {
119 for (
unsigned int n = 1; n < fNOfFunctions; n++) {
120 fFunctions[n]->SetRange(fXmin, fXmax);
121 fFunctions[n]->Update();
125 FixDuplicateNames(fParNames.begin() + fNOfFunctions, fParNames.end());
130 TF1NormSum::TF1NormSum()
134 fFunctions = std::vector<std::unique_ptr<TF1>>(0);
135 fCoeffs = std::vector < Double_t >(0) ;
136 fCstIndexes = std::vector < Int_t > (0);
143 TF1NormSum::TF1NormSum(
const std::vector <TF1*> &functions,
const std::vector <Double_t> &coeffs, Double_t scale)
145 InitializeDataMembers(functions, coeffs, scale);
151 TF1NormSum::TF1NormSum(TF1* function1, TF1* function2, Double_t coeff1, Double_t coeff2, Double_t scale)
153 std::vector<TF1 *> functions(2);
154 std::vector < Double_t > coeffs(2);
156 functions = {function1, function2};
157 coeffs = {coeff1, coeff2};
159 InitializeDataMembers(functions, coeffs,scale);
165 TF1NormSum::TF1NormSum(TF1* function1, TF1* function2, TF1* function3, Double_t coeff1, Double_t coeff2, Double_t coeff3, Double_t scale)
167 std::vector<TF1 *> functions(3);
168 std::vector < Double_t > coeffs(3);
170 functions = {function1, function2, function3};
171 coeffs = {coeff1, coeff2, coeff3};
173 InitializeDataMembers(functions, coeffs,scale);
182 TF1NormSum::TF1NormSum(
const TString &formula, Double_t xmin, Double_t xmax)
184 TF1::InitStandardFunctions();
186 TObjArray *arrayall = formula.Tokenize(
"*+");
187 TObjArray *arraytimes = formula.Tokenize(
"*") ;
188 Int_t noffunctions = (formula.Tokenize(
"+")) -> GetEntries();
189 Int_t nofobj = arrayall -> GetEntries();
190 Int_t nofcoeffs = nofobj - noffunctions;
192 std::vector<TF1 *> functions(noffunctions);
193 std::vector < Double_t > coeffs(noffunctions);
194 std::vector < TString > funcstringall(nofobj);
195 std::vector < Int_t > indexsizetimes(nofcoeffs+1);
196 std::vector < Bool_t > isacoeff(nofobj);
198 for (
int i=0; i<nofobj; i++)
200 funcstringall[i] = ((TObjString*)((*arrayall)[i])) -> GetString();
201 funcstringall[i].ReplaceAll(
" ",
"");
207 for (
int i=0; i<nofcoeffs+1; i++)
209 indexsizetimes[i] = ( ( ( (TObjString*)(*arraytimes)[i] ) -> GetString() ).Tokenize(
"+") ) -> GetEntries();
210 while (k < indexsizetimes[i])
215 j = j+indexsizetimes[i];
216 if (j==nofobj) isacoeff[j-1] = 0;
217 else isacoeff[j-1] = 1;
221 Double_t old_xmin = 0.0, old_xmax = 0.0;
223 for (
int i=0; i<noffunctions; i++)
227 coeffs[i] = funcstringall[k].Atof();
234 functions[i] = (TF1 *)(gROOT->GetListOfFunctions()->FindObject(funcstringall[k]));
236 Error(
"TF1NormSum",
"Function %s does not exist", funcstringall[k].Data());
239 functions[i]->GetRange(old_xmin, old_xmax);
240 functions[i]->SetRange(xmin, xmax);
245 InitializeDataMembers(functions, coeffs,1.);
248 if (noffunctions > 0 && functions[0])
249 functions[0]->SetRange(old_xmin, old_xmax);
255 TF1NormSum::TF1NormSum(
const TF1NormSum &nsum)
257 nsum.Copy((TObject &)*
this);
263 TF1NormSum &TF1NormSum::operator=(
const TF1NormSum &rhs)
273 double TF1NormSum::operator()(
const Double_t *x,
const Double_t *p)
280 for (
unsigned int n=0; n<fNOfFunctions; n++)
281 sum += fCoeffs[n]*(fFunctions[n] -> EvalPar(x,0));
290 std::vector<double> TF1NormSum::GetParameters()
const {
291 std::vector<double> params(GetNpar() );
293 int nOfNonCstParams = 0;
294 for (
unsigned int n=0; n<fNOfFunctions; n++)
296 params[n] = fCoeffs[n];
297 offset += nOfNonCstParams;
299 for (
int j = 0; j < fFunctions[n]->GetNpar(); ++j) {
300 if (j != fCstIndexes[n]) {
301 params[k+fNOfFunctions+offset] = fFunctions[n]->GetParameter(j);
314 void TF1NormSum::SetParameters(
const Double_t *params)
316 for (
unsigned int n=0; n<fNOfFunctions; n++)
318 fCoeffs[n] = params[n];
322 for (
unsigned int n=0; n<fNOfFunctions; n++)
324 bool equalParams =
true;
325 Double_t * funcParams = fFunctions[n]->GetParameters();
326 int npar = fFunctions[n]->GetNpar();
329 for (
int i = 0; i < npar; ++i) {
331 if (i != fCstIndexes[n])
334 equalParams &= (funcParams[i] == params[k+fNOfFunctions+offset] );
335 funcParams[i] = params[k+fNOfFunctions+offset];
340 if (!equalParams) fFunctions[n]->Update();
351 void TF1NormSum::SetParameters(Double_t p0, Double_t p1, Double_t p2, Double_t p3, Double_t p4,
352 Double_t p5, Double_t p6, Double_t p7, Double_t p8, Double_t p9, Double_t p10)
354 const double params[] = {p0,p1,p2,p3,p4,p5,p6,p7,p8,p9,p10};
355 TF1NormSum::SetParameters(params);
362 Int_t TF1NormSum::GetNpar()
const
365 for (
unsigned int n=0; n<fNOfFunctions; ++n)
367 nofparams += fFunctions[n]->GetNpar();
368 if (fCstIndexes[n] >= 0) nofparams -= 1;
370 return nofparams + fNOfFunctions;
375 void TF1NormSum::SetRange(Double_t a, Double_t b)
378 Warning(
"SetRange",
"Invalid range: %f >= %f", a, b);
385 for (
unsigned int n = 0; n < fNOfFunctions; n++) {
386 fFunctions[n]->SetRange(a, b);
387 fFunctions[n]->Update();
393 void TF1NormSum::GetRange(Double_t &a, Double_t &b)
const
402 void TF1NormSum::Update()
404 for (
unsigned int n = 0; n < fNOfFunctions; n++)
405 fFunctions[n]->Update();
410 void TF1NormSum::Copy(TObject &obj)
const
412 ((TF1NormSum &)obj).fNOfFunctions = fNOfFunctions;
413 ((TF1NormSum &)obj).fScale = fScale;
414 ((TF1NormSum &)obj).fXmin = fXmin;
415 ((TF1NormSum &)obj).fXmax = fXmax;
416 ((TF1NormSum &)obj).fCoeffs = fCoeffs;
417 ((TF1NormSum &)obj).fCstIndexes = fCstIndexes;
418 ((TF1NormSum &)obj).fParNames = fParNames;
421 ((TF1NormSum &)obj).fFunctions = std::vector<std::unique_ptr<TF1>>(fNOfFunctions);
422 for (
unsigned int n = 0; n < fNOfFunctions; n++) {
423 TF1 * f = (TF1*) fFunctions[n]->IsA()->New();
424 fFunctions[n]->Copy(*f);
425 ((TF1NormSum &)obj).fFunctions[n] = std::unique_ptr<TF1>(f);