Logo ROOT  
Reference Guide
 
Loading...
Searching...
No Matches
TF1NormSum.cxx
Go to the documentation of this file.
1// @(#)root/hist:$Id$
2// Authors: Lorenzo Moneta, Aurélie Flandi 27/08/14
3//
4/**********************************************************************
5 * *
6 * Copyright (c) 2015 ROOT Team, CERN/PH-SFT *
7 * *
8 * *
9 **********************************************************************/
10
11#include "TROOT.h"
12#include "TClass.h"
13#include "TObjString.h"
14#include "TObjArray.h"
15#include "TF1NormSum.h"
17#include "Math/WrappedTF1.h"
18
19
20/** \class TF1NormSum
21 \ingroup Functions
22Class adding two functions: c1*f1+c2*f2
23*/
24
25////////////////////////////////////////////////////////////////////////////////
26/// Function to find and rename duplicate parameters with the same name
27
28template<class Iterator>
29void FixDuplicateNames(Iterator begin, Iterator end) {
30
31 // make a map of values
32
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) ) );
36 }
37 for ( auto & elem : parMap) {
38 TString name = elem.first;
39 int n = parMap.count( name);
40 if (n > 1 ) {
41 std::pair <std::multimap<TString,int>::iterator, std::multimap<TString,int>::iterator> ret;
42 ret = parMap.equal_range(name);
43 int i = 0;
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);
46 }
47 }
48 }
49
50}
51
52////////////////////////////////////////////////////////////////////////////////
53
54void TF1NormSum::InitializeDataMembers(const std::vector<TF1 *> &functions, const std::vector<Double_t> &coeffs,
56{
57
58 fScale = scale;
60 fNOfFunctions = functions.size();
61 fCstIndexes = std::vector < Int_t > (fNOfFunctions);
62 fParNames = std::vector<TString> (fNOfFunctions);
63 fParNames.reserve(3*fNOfFunctions); // enlarge capacity for function parameters
64
65 // fill fFunctions with unique_ptr's
66 fFunctions = std::vector<std::unique_ptr<TF1>>(functions.size());
67 for (unsigned int n = 0; n < fNOfFunctions; n++) {
68 // use TF1::Copy and not clone to copy the TF1 pointers
69 // and use IsA()::New() in case we have base class pointers
70 TF1 * f = (TF1*) functions[n]->IsA()->New();
71 functions[n]->Copy(*f);
72 fFunctions[n] = std::unique_ptr<TF1>(f);
73
74
75 if (!fFunctions[n])
76 Fatal("InitializeDataMembers", "Invalid input function -- abort");
77
79 }
80
81 for (unsigned int n=0; n < fNOfFunctions; n++)
82 {
83 int npar = fFunctions[n] -> GetNpar();
84 fCstIndexes[n] = fFunctions[n] -> GetParNumber("Constant");//return -1 if there is no constant parameter
85 fParNames[n] = TString::Format("Coeff%d",n);
86 if (fCstIndexes[n]!= -1) //if there exists a constant parameter
87 {
88 fFunctions[n] -> FixParameter(fCstIndexes[n], 1.); // fixes the parameters called "Constant" to 1
89 for (int i=0; i<npar; i++) // go through all the parameter to
90 {
91 if (i==fCstIndexes[n]) continue; // go to next step if this is the constant parameter
92 fParNames.push_back( fFunctions[n] -> GetParName(i) );
93 }
94 }
95 else {
96 for (int i=0; i < npar; i++) //go through all the parameter to
97 {
98 fParNames.push_back( fFunctions[n] -> GetParName(i) );
99 }
100 }
101 //normalize the functions if it is not already done (do at the end so constant parameter is not zero)
102 if (!fFunctions[n] -> IsEvalNormalized()) fFunctions[n] -> SetNormalized(true);
103 }
104
105 // Set range
106 if (fNOfFunctions == 0) {
107 fXmin = 0.;
108 fXmax = 1.;
109 // Info("InitializeDataMembers", "Initializing empty TF1NormSum with default [0,1] range");
110 } else {
111 fFunctions[0]->GetRange(fXmin, fXmax);
112 if (fXmin >= fXmax) {
113 fXmin = 0.;
114 fXmax = 1.;
115 // Info("InitializeDataMembers", "Initializing empty TF1NormSum with default [0,1] range");
116 }
117 for (unsigned int n = 1; n < fNOfFunctions; n++) {
118 fFunctions[n]->SetRange(fXmin, fXmax);
119 fFunctions[n]->Update();
120 }
121 }
122
124}
125
126////////////////////////////////////////////////////////////////////////////////
127
129{
130 fNOfFunctions = 0;
131 fScale = 1.;
132 fFunctions = std::vector<std::unique_ptr<TF1>>(0); // Vector of size fNOfFunctions containing TF1 functions
133 fCoeffs = std::vector < Double_t >(0) ; // Vector of size fNOfFunctions containing coefficients in front of each function
134 fCstIndexes = std::vector < Int_t > (0);
135 fXmin = 0; // Dummy values of xmin and xmax
136 fXmax = 1;
137}
138
139////////////////////////////////////////////////////////////////////////////////
140
141TF1NormSum::TF1NormSum(const std::vector <TF1*> &functions, const std::vector <Double_t> &coeffs, Double_t scale)
142{
144}
145
146////////////////////////////////////////////////////////////////////////////////
147/// TF1NormSum constructor taking 2 functions, and 2 coefficients (if not equal to 1)
148
150{
151 std::vector<TF1 *> functions(2);
152 std::vector < Double_t > coeffs(2);
153
155 coeffs = {coeff1, coeff2};
156
158}
159
160////////////////////////////////////////////////////////////////////////////////
161/// TF1NormSum constructor taking 3 functions, and 3 coefficients (if not equal to 1)
162
173
174////////////////////////////////////////////////////////////////////////////////
175/// TF1NormSum constructor taking any addition of formulas with coefficient or not
176///
177/// - example 1 : 2.*expo + gauss + 0.5* gauss
178/// - example 2 : expo + 0.3*f1 if f1 is defined in the list of functions
179
181{
183
184 TObjArray *arrayall = formula.Tokenize("*+");
185 TObjArray *arraytimes = formula.Tokenize("*") ;
186 Int_t noffunctions = (formula.Tokenize("+")) -> GetEntries();
187 Int_t nofobj = arrayall -> GetEntries();
189
190 std::vector<TF1 *> functions(noffunctions);
191 std::vector < Double_t > coeffs(noffunctions);
192 std::vector < TString > funcstringall(nofobj);
193 std::vector < Int_t > indexsizetimes(nofcoeffs+1);
194 std::vector < Bool_t > isacoeff(nofobj);//1 is it is a coeff, 0 if it is a functions
195
196 for (int i=0; i<nofobj; i++)
197 {
198 funcstringall[i] = ((TObjString*)((*arrayall)[i])) -> GetString();
199 funcstringall[i].ReplaceAll(" ","");
200 }
201 //algorithm to determine which object is a coefficient and which is a function
202 //uses the fact that the last item of funcstringtimes[i].Tokenize("+") is always a coeff.
203 Int_t j = 0;
204 Int_t k = 1;
205 for (int i=0; i<nofcoeffs+1; i++)
206 {
207 indexsizetimes[i] = ( ( ( (TObjString*)(*arraytimes)[i] ) -> GetString() ).Tokenize("+") ) -> GetEntries();
208 while (k < indexsizetimes[i])
209 {
210 isacoeff[k+j-1] = false;
211 k++;
212 }
213 j = j+indexsizetimes[i];
214 if (j==nofobj) isacoeff[j-1] = false; //the last one is never a coeff
215 else isacoeff[j-1] = true;
216 k = 1;
217 }
218
219 Double_t old_xmin = 0.0, old_xmax = 0.0;
220 k = 0; // index of term in funcstringall
221 for (int i=0; i<noffunctions; i++)
222 {
223 // first, handle coefficient
224 if (isacoeff[k]) {
225 coeffs[i] = funcstringall[k].Atof();
226 k++;
227 } else {
228 coeffs[i] = 1.;
229 }
230
231 // then, handle function
232 functions[i] = (TF1 *)(gROOT->GetListOfFunctions()->FindObject(funcstringall[k]));
233 if (!functions[i])
234 Error("TF1NormSum", "Function %s does not exist", funcstringall[k].Data());
235 // (set range for first function, which determines range of whole TF1NormSum)
236 else if (i == 0) {
237 functions[i]->GetRange(old_xmin, old_xmax);
238 functions[i]->SetRange(xmin, xmax);
239 }
240
241 k++;
242 }
244
245 // Set range of first function back to original state
246 if (noffunctions > 0 && functions[0])
247 functions[0]->SetRange(old_xmin, old_xmax);
248}
249
250////////////////////////////////////////////////////////////////////////////////
251/// Copy constructor (necessary to hold unique_ptr as member variable)
252
254{
255 nsum.TF1NormSum::Copy(*this);
256}
257
258////////////////////////////////////////////////////////////////////////////////
259/// Operator =
260
262{
263 if (this != &rhs)
264 rhs.TF1NormSum::Copy(*this);
265 return *this;
266}
267
268////////////////////////////////////////////////////////////////////////////////
269/// Overload the parenthesis to add the functions
270
272{
273 // first refresh the parameters
274 if (p != nullptr)
276
277 Double_t sum = 0.;
278 for (unsigned int n=0; n<fNOfFunctions; n++)
279 sum += fCoeffs[n]*(fFunctions[n] -> EvalPar(x,nullptr));
280
281 // normalize by a scale parameter (typically the bin width)
282 return fScale * sum;
283}
284
285////////////////////////////////////////////////////////////////////////////////
286/// Return array of parameters
287
288std::vector<double> TF1NormSum::GetParameters() const {
289 std::vector<double> params(GetNpar() );
290 int offset = 0;
291 int nOfNonCstParams = 0;
292 for (unsigned int n=0; n<fNOfFunctions; n++)
293 {
294 params[n] = fCoeffs[n]; // copy the coefficients
295 offset += nOfNonCstParams; // offset to go along the list of parameters
296 int k = 0;
297 for (int j = 0; j < fFunctions[n]->GetNpar(); ++j) {
298 if (j != fCstIndexes[n]) {
299 params[k+fNOfFunctions+offset] = fFunctions[n]->GetParameter(j);
300 k++;
301 }
302 }
303 nOfNonCstParams = k;
304 }
305 return params;
306}
307////////////////////////////////////////////////////////////////////////////////
308/// Initialize array of all parameters.
309///
310/// double *params must contains first an array of the coefficients, then an array of the parameters.
311
312void TF1NormSum::SetParameters(const Double_t *params) // params should have the size [fNOfFunctions][fNOfNonCstParams]
313{
314 for (unsigned int n=0; n<fNOfFunctions; n++) //initialization of the coefficients
315 {
316 fCoeffs[n] = params[n];
317 }
318 Int_t offset = 0;
319 int k = 0; // k indicates the number of non-constant parameter per function
320 for (unsigned int n=0; n<fNOfFunctions; n++)
321 {
322 bool equalParams = true;
323 Double_t * funcParams = fFunctions[n]->GetParameters();
324 int npar = fFunctions[n]->GetNpar();
325 offset += k; // offset to go along the list of parameters
326 k = 0; // reset k value for next function
327 for (int i = 0; i < npar; ++i) {
328 // constant parameters can be only one
329 if (i != fCstIndexes[n])
330 {
331 // check if they are equal
332 equalParams &= (funcParams[i] == params[k+fNOfFunctions+offset] );
333 funcParams[i] = params[k+fNOfFunctions+offset];
334 k++;
335 }
336 }
337 // update function integral if not equal
338 if (!equalParams) fFunctions[n]->Update();
339
340 }
341}
342
343////////////////////////////////////////////////////////////////////////////////
344/// Initialize array of all parameters.
345///
346/// Overload the TF1::SetParameters() method.
347/// A maximum of 10 parameters must be used, with first the coefficients, then the parameters
348
356
357////////////////////////////////////////////////////////////////////////////////
358/// Return the number of (non constant) parameters including the coefficients: for 2 functions: c1,c2,p0,p1,p2,p3...
359
361{
362 Int_t nofparams = 0;
363 for (unsigned int n=0; n<fNOfFunctions; ++n)
364 {
365 nofparams += fFunctions[n]->GetNpar();
366 if (fCstIndexes[n] >= 0) nofparams -= 1;
367 }
368 return nofparams + fNOfFunctions; //fNOfFunctions for the coefficients
369}
370
371////////////////////////////////////////////////////////////////////////////////
372
374{
375 if (a >= b) {
376 Warning("SetRange", "Invalid range: %f >= %f", a, b);
377 return;
378 }
379
380 fXmin = a;
381 fXmax = b;
382
383 for (unsigned int n = 0; n < fNOfFunctions; n++) {
384 fFunctions[n]->SetRange(a, b);
385 fFunctions[n]->Update();
386 }
387}
388
389////////////////////////////////////////////////////////////////////////////////
390
392{
393 a = fXmin;
394 b = fXmax;
395}
396
397////////////////////////////////////////////////////////////////////////////////
398/// Update the component functions of the normalized sum
399
401{
402 for (unsigned int n = 0; n < fNOfFunctions; n++)
403 fFunctions[n]->Update();
404}
405
406////////////////////////////////////////////////////////////////////////////////
407
408void TF1NormSum::Copy(TObject &obj) const
409{
410 ((TF1NormSum &)obj).fNOfFunctions = fNOfFunctions;
411 ((TF1NormSum &)obj).fScale = fScale;
412 ((TF1NormSum &)obj).fXmin = fXmin;
413 ((TF1NormSum &)obj).fXmax = fXmax;
414 ((TF1NormSum &)obj).fCoeffs = fCoeffs;
415 ((TF1NormSum &)obj).fCstIndexes = fCstIndexes;
416 ((TF1NormSum &)obj).fParNames = fParNames;
417
418 // Clone objects in unique_ptr's
419 ((TF1NormSum &)obj).fFunctions = std::vector<std::unique_ptr<TF1>>(fNOfFunctions);
420 for (unsigned int n = 0; n < fNOfFunctions; n++) {
421 TF1 * f = (TF1*) fFunctions[n]->IsA()->New();
422 fFunctions[n]->Copy(*f);
423 ((TF1NormSum &)obj).fFunctions[n] = std::unique_ptr<TF1>(f);
424 }
425}
#define b(i)
Definition RSha256.hxx:100
#define f(i)
Definition RSha256.hxx:104
#define a(i)
Definition RSha256.hxx:99
constexpr Bool_t kTRUE
Definition RtypesCore.h:107
ROOT::Detail::TRangeCast< T, true > TRangeDynCast
TRangeDynCast is an adapter class that allows the typed iteration through a TCollection.
void FixDuplicateNames(Iterator begin, Iterator end)
Function to find and rename duplicate parameters with the same name.
winID h TVirtualViewer3D TVirtualGLPainter p
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t Int_t Int_t Window_t TString Int_t GCValues_t GetPrimarySelectionOwner GetDisplay GetScreen GetColormap GetNativeEvent const char const char dpyName wid window const char font_name cursor keysym reg const char only_if_exist regb h Point_t winding char text const char depth char const char Int_t count const char ColorStruct_t color const char Pixmap_t Pixmap_t PictureAttributes_t attr const char char ret_data h unsigned char height h offset
char name[80]
Definition TGX11.cxx:110
float xmin
float xmax
#define gROOT
Definition TROOT.h:411
void * New(ENewType defConstructor=kClassNew, Bool_t quiet=kFALSE) const
Return a pointer to a newly allocated object of this class.
Definition TClass.cxx:5017
Class adding two functions: c1*f1+c2*f2.
Definition TF1NormSum.h:19
void Copy(TObject &obj) const override
Copy this to obj.
Double_t fScale
Fixed Scale parameter to normalize function (e.g. bin width)
Definition TF1NormSum.h:23
const char * GetParName(Int_t ipar) const
Definition TF1NormSum.h:66
void GetRange(Double_t &a, Double_t &b) const
TF1NormSum & operator=(const TF1NormSum &rhs)
Operator =.
TClass * IsA() const override
Definition TF1NormSum.h:78
Double_t fXmax
Maximal bound of range of NormSum.
Definition TF1NormSum.h:25
std::vector< TString > fParNames
Parameter names.
Definition TF1NormSum.h:29
void SetRange(Double_t a, Double_t b) override
Double_t fXmin
Minimal bound of range of NormSum.
Definition TF1NormSum.h:24
std::vector< double > GetParameters() const
Return array of parameters.
double operator()(const Double_t *x, const Double_t *p) override
Overload the parenthesis to add the functions.
void Update() override
Update the component functions of the normalized sum.
std::vector< std::unique_ptr< TF1 > > fFunctions
Vector of size fNOfFunctions containing TF1 functions.
Definition TF1NormSum.h:26
void InitializeDataMembers(const std::vector< TF1 * > &functions, const std::vector< Double_t > &coeffs, Double_t scale)
void SetParameters(const Double_t *params) override
Initialize array of all parameters.
std::vector< Double_t > fCoeffs
Vector of size afNOfFunctions containing coefficients in front of each function.
Definition TF1NormSum.h:27
Int_t GetNpar() const
Return the number of (non constant) parameters including the coefficients: for 2 functions: c1,...
unsigned int fNOfFunctions
Number of functions to add.
Definition TF1NormSum.h:22
std::vector< Int_t > fCstIndexes
Vector with size of fNOfFunctions containing the index of the constant parameter/ function (the remov...
Definition TF1NormSum.h:28
1-Dim function class
Definition TF1.h:182
static void InitStandardFunctions()
Create the basic function objects.
Definition TF1.cxx:2522
@ kNotGlobal
Definition TF1.h:296
An array of TObjects.
Definition TObjArray.h:31
Collectable string class.
Definition TObjString.h:28
Mother of all ROOT objects.
Definition TObject.h:41
virtual void Warning(const char *method, const char *msgfmt,...) const
Issue warning message.
Definition TObject.cxx:1057
virtual void Error(const char *method, const char *msgfmt,...) const
Issue error message.
Definition TObject.cxx:1071
virtual void Fatal(const char *method, const char *msgfmt,...) const
Issue fatal error message.
Definition TObject.cxx:1099
Basic string class.
Definition TString.h:138
TObjArray * Tokenize(const TString &delim) const
This function is used to isolate sequential tokens in a TString.
Definition TString.cxx:2270
static TString Format(const char *fmt,...)
Static method which formats a string using a printf style format descriptor and return a TString.
Definition TString.cxx:2384
Double_t x[n]
Definition legend1.C:17
const Int_t n
Definition legend1.C:16
static uint64_t sum(uint64_t i)
Definition Factory.cxx:2339