FdDoubleBumpFinderKG/ProfileFitter.cc
Go to the documentation of this file.
1 #include "ProfileFitter.h"
2 using namespace profileFit;
3 
4 #include <TMinuit.h>
5 
6 #include <stdexcept>
7 #include <iostream>
8 #include <sstream>
9 #include <algorithm>
10 using namespace std;
11 
12 unsigned int ProfileFitter::fNdof=0;
13 double ProfileFitter::fVariance=-1;
15 vector<double> ProfileFitter::fDepth;
16 vector<double> ProfileFitter::fSize;
17 vector<double> ProfileFitter::fSizeError;
20 
22  fVerbosity(-1)
23 {
24 
25 }
26 
28 {
29 
30 }
31 
32 bool
34 {
35 
36  if (fSizeError.empty() && fVariance < 0)
37  {
38  ostringstream errorMsg;
39 
40  if (fVerbosity > -1)
41  {
42  errorMsg << " ProfileFitter::Fit() "
43  << " ERROR: variance is not initialized, exit!";
44  cerr << errorMsg.str() << endl;
45  }
46  throw std::runtime_error(errorMsg.str());
47  }
48 
49  fIsConstrained=true;
50 
51  switch ( fFunctionType ) {
52  case eGaisserHillas:
53  return GHFit();
55  fIsConstrained=false;
56  return GHFit();
58  return DoubleGHFit();
59  case eGaussInAge:
60  return GaussInAgeFit();
61  case eDoubleGaussInAge:
62  return GaussInAgeFit();
63  }
64 
65  fStartParameters.clear();
66  fStepParameters.clear();
67 
68  return false;
69 
70 }
71 
72 bool
74 {
75 
76  const unsigned int nPar = eNGHpars;
77  TMinuit theMinuit(nPar);
78  theMinuit.SetFCN(ProfileFitter::GHFitFunction);
79  InitMinuit(theMinuit);
80 
81  if ( fStartParameters.size() != nPar ) {
82  pair<double, double> theMax = FindMaximum();
83  const double xMax = theMax.first;
84  const double nMax = theMax.second;
85 
86  int ierflag;
87  theMinuit.mnparm(eGHnMax,"nMax", nMax, nMax*5e-2,0,0,ierflag);
88  theMinuit.mnparm(eGHXmax,"xMax", xMax, 10.,0,0,ierflag);
89  theMinuit.mnparm(eGHX0, "x0",-100., 10.,-1000,500.,ierflag);
90  theMinuit.mnparm(eGHLambda,"lamb", 60., 5.,10.,150.,ierflag);
91  }
92  else
93  UserStartInit(theMinuit);
94 
95  return Minimize(theMinuit);
96 
97 }
98 
99 bool
101 {
102 
103  const unsigned int nPar=eNGiApars;
104  TMinuit theMinuit(nPar);
105  theMinuit.SetFCN(ProfileFitter::GaussInAgeFitFunction);
106  InitMinuit(theMinuit);
107 
108  if ( fStartParameters.size() != nPar ) {
109  pair<double, double> theMax = FindMaximum();
110  const double xMax = theMax.first;
111  const double nMax = theMax.second;
112 
113  int ierflag;
114  theMinuit.mnparm(eGiAnMax,"nMax", nMax,nMax*5e-2,0,0,ierflag);
115  theMinuit.mnparm(eGiAXmax,"xMax", xMax, 10.,0,0,ierflag);
116  theMinuit.mnparm(eGiASigma1,"sig1", 0.2, .05,0.,.5,ierflag);
117  theMinuit.mnparm(eGiASigma2,"sig2", 0.2, .05,0.,.5,ierflag);
118 
119  if ( fFunctionType == eGaussInAge )
120  theMinuit.FixParameter(eGiASigma2);
121 
122  }
123  else
124  UserStartInit(theMinuit);
125 
126  return Minimize(theMinuit);
127 
128 }
129 
130 bool
132 {
133 
134  const unsigned int nPar=eNDGHpars;
135  TMinuit theMinuit(nPar);
136  theMinuit.SetFCN(ProfileFitter::DoubleGHFitFunction);
137  InitMinuit(theMinuit);
138 
139 
140  if ( fStartParameters.size() != nPar ) {
141 
142  pair<double, double> theMax = FindMaximum();
143  const double nMax = theMax.second;
144  const double xMax = theMax.first;
145 
146  double leftSum=0.;
147  double rightSum=0.;
148  for ( unsigned int i=0;i<fDepth.size(); i++ ) {
149  if ( fDepth[i] < xMax )
150  leftSum+=fSize[i];
151  else
152  rightSum+=fSize[i];
153  }
154 
155  double deltaX = 50.;
156  if ( leftSum > rightSum )
157  deltaX*= (-1);
158 
159  int ierflag;
160  theMinuit.mnparm(eDGHnMax1, "nMax1", nMax*0.5, nMax*1e-1, 0., 0., ierflag);
161  theMinuit.mnparm(eDGHXmax1, "xMax1", xMax-deltaX, 10., 0., 0., ierflag);
162  theMinuit.mnparm(eDGHX01, "x01", -100., 10., -1000., 500., ierflag);
163  theMinuit.mnparm(eDGHLambda1, "lamb1", 61., 5., 10., 150., ierflag);
164 
165  theMinuit.mnparm(eDGHnMax2, "nMax2", nMax*0.5, nMax*1e-1, 0., 0., ierflag);
166  theMinuit.mnparm(eDGHXmax2, "xMax2", xMax+deltaX, 10., 0., 0., ierflag);
167  theMinuit.mnparm(eDGHX02, "x02", -100.+deltaX, 10., -1000., 500., ierflag);
168  theMinuit.mnparm(eDGHLambda2, "lamb2", 61., 5., 10., 150., ierflag);
169  }
170  else
171  UserStartInit(theMinuit);
172 
173  return Minimize(theMinuit);
174 
175 }
176 
177 
178 std::pair<double, double>
180  const
181 {
182 
183  vector<double>::const_iterator maximum = max_element(fSize.begin(),
184  fSize.end());
185 
186  const double nMax = *maximum;
187  const int iMax = (maximum-fSize.begin());
188  const double xMax = fDepth[iMax];
189 
190  return pair<double,double>(xMax,nMax);
191 
192 }
193 
194 
195 void
196 ProfileFitter::GHFitFunction(int& /*npar*/, double* const /*gin*/,
197  double& value, double* const par,
198  const int /*iFlag*/)
199 {
200 
201  double chi2 = 0.;
202  const double nMax = par[eGHnMax];
203  const double xMax = par[eGHXmax];
204  const double x0 = par[eGHX0];
205  const double lambda = par[eGHLambda];
206 
207  fNdof=0;
208 
209  for ( unsigned int i=0;i<fDepth.size();i++ ) {
210 
211  const double y = fSize[i];
212 
213  if ( fSizeError.size() || y > fThreshold ) {
214 
215  const double x = fDepth[i];
216  const double fx = (x>x0)?GHFunction(x,x0,lambda,xMax,nMax):0.;
217  const double vy = fSizeError.empty()?fVariance:pow(fSizeError[i],2);
218 
219  chi2 += pow(y-fx,2)/vy;
220  fNdof++;
221 
222  }
223  }
224 
225  // constraints a la FdProfileReconstructor
226  if ( fIsConstrained ) {
227  const double fdefX0 = -121.;
228  const double rmsX0 = 172.;
229  chi2+=(x0-fdefX0)*(x0-fdefX0)/rmsX0/rmsX0;
230  const double fdefLambda = 61.;
231  const double rmsLambda = 13.;
232  chi2+=(lambda-fdefLambda)*(lambda-fdefLambda)/rmsLambda/rmsLambda;
233 
234  fNdof-=2;
235  }
236 
237  value = chi2;
238 }
239 
240 void
241 ProfileFitter::GaussInAgeFitFunction(int& /*npar*/, double* const /*gin*/,
242  double& value, double* const par,
243  const int /*iFlag*/)
244 {
245 
246  double chi2 = 0.;
247  const double nMax = par[eGiAnMax];
248  const double xMax = par[eGiAXmax];
249  const double sigma1 = par[eGiASigma1];
250  const double sigma2 = (fFunctionType == eGaussInAge )?
251  // par[eGiASigma1]:
252  // Giller ICRC 2005
253  0.0340 + 0.7682*par[eGiASigma1]:par[eGiASigma2];
254 
255  fNdof=0;
256 
257  for ( unsigned int i=0;i<fDepth.size();i++ ) {
258 
259  const double y = fSize[i];
260 
261  if ( y > fThreshold ) {
262 
263  const double x = fDepth[i];
264  const double fx = GaussInAgeFunction(x,nMax,xMax,sigma1,sigma2);
265  const double vy = fSizeError.empty()?fVariance:pow(fSizeError[i],2);
266  chi2 += pow(y-fx,2)/vy;
267  fNdof++;
268 
269  }
270  }
271 
272  if ( fFunctionType == eDoubleGaussInAge ) {
273  // constraints a la FdProfileReconstructor
274  const double meanSigma1 = 0.2;
275  const double vSigma1 = pow(0.03,2);
276  const double meanSigma2 = 0.2;
277  const double vSigma2 = pow(0.03,2);
278  chi2+=pow(sigma1-meanSigma1,2)/vSigma1;
279  chi2+=pow(sigma2-meanSigma2,2)/vSigma2;
280  }
281 
282  fNdof-=2;
283 
284  value = chi2;
285 
286 }
287 
288 void
289 ProfileFitter::DoubleGHFitFunction(int& /*npar*/, double* const /*gin*/,
290  double& value, double* const par,
291  const int /*iFlag*/)
292 {
293  double chi2 = 0.;
294  const double nMax1 = par[eDGHnMax1];
295  const double xMax1 = par[eDGHXmax1];
296  const double x01 = par[eDGHX01];
297  const double lambda1 = par[eDGHLambda1];
298  const double nMax2 = par[eDGHnMax2];
299  const double xMax2 = par[eDGHXmax2];
300  const double x02 = par[eDGHX02];
301  const double lambda2 = par[eDGHLambda2];
302 
303  fNdof=0;
304 
305  for (unsigned int i = 0; i < fDepth.size(); i++) {
306 
307  const double y = fSize[i];
308 
309  if ( y > fThreshold ) {
310 
311  const double x = fDepth[i];
312  const double fx1 = (x>x01)?GHFunction(x,x01,lambda1,xMax1,nMax1):0.;
313  const double fx2 = (x>x02)?GHFunction(x,x02,lambda2,xMax2,nMax2):0.;
314  const double vy = fSizeError.empty()?fVariance:pow(fSizeError[i],2);
315 
316  chi2 += pow(y-fx1-fx2,2)/vy;
317  fNdof++;
318 
319  }
320  }
321 
322  // constraints a la FdProfileReconstructor but with constraint to X0-Xmax stead of X0 to comply with double GH fit
323 
324  const double fdefX0_minus_Xmax = -816.;
325  const double rmsX0_minus_Xmax = 183.;
326  chi2+=(x01-xMax1-fdefX0_minus_Xmax)*(x01-xMax1-fdefX0_minus_Xmax)/rmsX0_minus_Xmax/rmsX0_minus_Xmax;
327  chi2+=(x02-xMax2-fdefX0_minus_Xmax)*(x02-xMax2-fdefX0_minus_Xmax)/rmsX0_minus_Xmax/rmsX0_minus_Xmax;
328 
329  const double fdefLambda = 61.;
330  const double rmsLambda = 13.;
331  chi2+=(lambda1-fdefLambda)*(lambda1-fdefLambda)/rmsLambda/rmsLambda;
332  chi2+=(lambda2-fdefLambda)*(lambda2-fdefLambda)/rmsLambda/rmsLambda;
333 
334  fNdof-=4;
335 
336  //only positive dEdX values. This circumvents problem with limits in TMinuit
337  if ( nMax1<0. || nMax2<0.)
338  chi2+=1e99;
339 
340  value = chi2;
341 }
342 
343 
344 
345 bool
346 ProfileFitter::Minimize(TMinuit& theMinuit)
347 {
348 
349  int ierflag;
350  double arglist[2]={100000, 1.};
351  theMinuit.mnexcm("MIGRAD", arglist, 2, ierflag);
352 
353  if (ierflag) {
354  if (fVerbosity > -1)
355  cerr << " MIGRAD failed. Error: " << ierflag << endl;
356  return false;
357  }
358 
359  theMinuit.mnexcm("HESSE", arglist, 2, ierflag);
360 
361  double amin, edm, errdef;
362  int nvpar, nparx, icstat;
363  theMinuit.mnstat(amin, edm, errdef, nvpar, nparx, icstat);
364  fStatus = icstat;
365  fChi2 = amin;
366 
367  fFitParameters.resize(nparx);
368  fFitErrors.resize(nparx);
369  for ( int i=0;i<nparx;i++ )
370  theMinuit.GetParameter(i, fFitParameters[i], fFitErrors[i]);
371 
372  return true;
373 }
374 
375 
376 void
377 ProfileFitter::InitMinuit(TMinuit& theMinuit)
378  const
379 {
380 
381  int ierflag;
382  if(fVerbosity==2)
383  theMinuit.SetPrintLevel(0);
384  else if (fVerbosity>=3)
385  theMinuit.SetPrintLevel(fVerbosity);
386  else {
387  theMinuit.SetPrintLevel(-1);
388  theMinuit.mnexcm("SET NOW", 0 ,0,ierflag);
389  }
390 
391  double arglist=1.;
392  theMinuit.mnexcm("SET ERR",&arglist,1,ierflag);
393 
394 }
395 
396 void
397 ProfileFitter::UserStartInit(TMinuit& theMinuit) {
398 
399  int ierflag;
400  for ( unsigned int i=0;i<fStartParameters.size();i++ ) {
401  ostringstream name;
402  name << "p" << i;
403  if(fLimitsUp.size()!=fStartParameters.size() || fLimitsDown.size()!=fStartParameters.size())
404  {
405  theMinuit.mnparm(i,name.str().c_str(),
406  fStartParameters[i],
407  fStepParameters[i],0,0,ierflag);
408  if(fVerbosity>0) cout << "no limits set" << fLimitsUp.size()<< " " << fStartParameters.size()<<endl;
409  }
410  else
411  theMinuit.mnparm(i,name.str().c_str(),
412  fStartParameters[i],
413  fStepParameters[i],fLimitsDown[i],fLimitsUp[i],ierflag);
414  }
415 }
static void GaussInAgeFitFunction(int &, double *const, double &, double *const, const int)
double pow(const double x, const unsigned int i)
static void DoubleGHFitFunction(int &, double *const, double &, double *const, const int)
double GaussInAgeFunction(const double X, const double nMax, const double xMax, const double sigma1, const double sigma2)
std::pair< double, double > FindMaximum() const
double GHFunction(const double X, const double x0, const double lambda, const double xMax, const double nMax)
static void GHFitFunction(int &, double *const, double &, double *const, const int)
const int nPar
Definition: GeomAsym.h:37

, generated on Tue Sep 26 2023.