StRoot  1
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
StFmsClusterFitter.cxx
Go to the documentation of this file.
1 // $Id: StFmsClusterFitter.cxx,v 1.10 2019/06/26 16:49:53 akio Exp $
2 //
3 // $Log: StFmsClusterFitter.cxx,v $
4 // Revision 1.10 2019/06/26 16:49:53 akio
5 // shower shape scaling for all shapes
6 //
7 // Revision 1.9 2018/03/26 15:55:37 akio
8 // removing some print outs
9 //
10 // Revision 1.8 2018/03/02 20:27:29 akio
11 // Big update from Zhanwen Zhu with new shower shape and six z slices
12 //
13 // Revision 1.7 2018/01/04 17:35:44 smirnovd
14 // [Cosmetic] Remove StRoot/ from include path
15 //
16 // $STAR/StRoot is already in the default path search
17 //
18 // Revision 1.6 2015/11/05 17:54:57 akio
19 // Adding option to scale up shower shape function for large cells
20 //
21 // Revision 1.5 2015/10/30 21:33:56 akio
22 // fix parameter initialization
23 // adding new cluster categorization method
24 //
25 // Revision 1.4 2015/10/29 21:14:55 akio
26 // increase max number of clusters
27 // a bug fixes in valley tower association
28 // removing some debug comments
29 //
30 // Revision 1.3 2015/10/21 15:58:04 akio
31 // Code speed up (~x2) by optimizing minimization fuctions and showershape function
32 // Add option to merge small cells to large, so that it finds cluster at border
33 // Add option to perform 1photon fit when 2photon fit faield
34 // Add option to turn on/off global refit
35 // Moment analysis done without ECUTOFF when no tower in cluster exceed ECUTOFF=0.5GeV
36 //
37 // Revision 1.2 2015/09/02 15:01:32 akio
38 // Removing StFmsGeometry class, and now it uses StFmsDbMaker to get appropriate parameters.
39 //
40 // Revision 1.1 2015/03/10 14:38:54 jeromel
41 // First version of FmsUtil from Yuxi Pan - reviewd 2015/02
42 //
52 #include "StFmsClusterFitter.h"
53 #include "StFmsDbMaker/StFmsDbMaker.h"
54 
55 #include <algorithm> // For std::max()
56 #include <array>
57 #include <cmath>
58 #include <numeric>
59 #include <vector>
60 
61 #include "TF2.h"
62 #include "TMath.h"
63 #include "TString.h"
64 
65 #include "St_base/StMessMgr.h"
66 #include "StEvent/StFmsHit.h"
67 
68 //#include "StFmsGeometry.h"
69 #include "StFmsTower.h"
70 #include "StFmsConstant.h"
71 
72 namespace {
73 const Int_t kMaxNPhotons = 7; // Maximum number of photons that can be fitted
74 
75 
76 int mshowershapewithangle=1;// for static func
77 int mmerge=1;// for static func
78 int vertexz=0;
79 void setOption(int v1, int v2 , double v3){
80  mshowershapewithangle=v1;
81  mmerge=v2;
82  vertexz=v3;
83 }
84 
85 //Yuxi's
86 double unused=0.0;
87 double a11=0.998438; double a12=0.222782; double a13=-0.22122;double b11=0.177028;double b12=0.000473222;double b13=0.178897;double w1 = 0.0372556;
88 double a21=1.07711 ; double a22=-0.0281385;double a23=-0.0489747;double b21=0.199964;double b22=3.5021;double b23=2.35246;double w2 = 0.202699;
89 double a31=1.07901 ; double a32=0.0650143; double a33=-0.144025;double b31=0.446845;double b32=0.00544512;double b33=1.64565;double w3 = 0.293878;
90 double a41=0.922174; double a42=0.0778254; double a43=1.07474e-07;double b41=0.593804;double b42=0.6199;double b43=3.49798;double w4 = 0.236854;
91 double a51=0.999849; double a52=0.000151185;double a53=2.20244e-07;double b51=0.949953;double b52=1.84451;double b53=3.40799;double w5 = 0.146041;
92 double a61=0.997454; double a62=0.00254497;double a63=1.02127e-06;double b61=1.43387;double b62=2.91155;double b63=3.4484;double w6 = 0.0832717;
93 
94 
95 //Zhanwen's small 45GeV new
96 double a1S[6]={0.0303644,0.212191,0.277429,0.0370035,0.0524404,0.00844062};
97 double a2S[6]={0.00122867,0.105355,0.10538,0.152656,0.00664331,0.0108688};
98 double b1S[6]={0.403493,0.514546,0.672826,1.82344,0.727991,1.48785};
99 double b2S[6]={0.270492,0.514593,0.672655,0.644871,4.32003,0.25};
100 
101 
102 //large 45GeV new
103 double a1L[6]={0.0275364,0.200363,0.277157,0.0391611,0.0590757,0.0101089};
104 double a2L[6]={0.000429808,0.0991777,0.104781,0.161916,0.00764026,0.012653};
105 double b1L[6]={0.515974,0.661722,0.865167,2.35237,0.932038,1.87933};
106 double b2L[6]={0.53531,0.661519,0.865226,0.828017,5.49041,0.321139};
107 
108 double a1[6]={0. , 0 , 0. , 0. , 0. , 0. };
109 double a2[6]={0. , 0 , 0. , 0. , 0. , 0. };
110 double b1[6]={0. , 0. , 0. , 0. , 0. , 0. };
111 double b2[6]={0. , 0. , 0. , 0. , 0. , 0. };
112 double a3[6]={0. , 0 , 0. , 0. , 0. , 0. };
113 double b3[6]={0. , 0. , 0. , 0. , 0. , 0. };
114 double w[6]={1. , 1. , 1. , 1. , 1. , 1. };
115 
116 std::array<double,60 > fitParameters;
117 void clear_fitParameters(){
118  for (int i=0 ; i<60 ; i++) { fitParameters[i]=0 ; }
119 }
120 
121 void choose_fitParameters(int detID, float scl=1.0){
122  if (detID<=9) {unused=5;} //large cell
123  else {unused=3;} //small cell
124  if ( mshowershapewithangle==2 ) {
125  fitParameters= {unused, a11, a12, a13, b11*scl, b12*scl, b13*scl, w1 ,unused, unused,
126  unused, a21, a22, a23, b21*scl, b22*scl, b23*scl, w2 ,unused, unused,
127  unused, a31, a32, a33, b31*scl, b32*scl, b33*scl, w3 ,unused, unused,
128  unused, a41, a42, a43, b41*scl, b42*scl, b43*scl, w4 ,unused, unused,
129  unused, a51, a52, a53, b51*scl, b52*scl, b53*scl, w5 ,unused, unused,
130  unused, a61, a62, a63, b61*scl, b62*scl, b63*scl, w6 ,unused, unused };
131  } else if ( mshowershapewithangle==1 ) {
132  if (detID>9) {//small cell
133  for (int i=0 ; i<6 ; i++) {
134  a1[i]=a1S[i];
135  a2[i]=a2S[i];
136  b1[i]=b1S[i]*scl;
137  b2[i]=b2S[i]*scl;
138  }
139  }else{//large cell
140  for (int i=0 ; i<6 ; i++) {
141  a1[i]=a1L[i];
142  a2[i]=a2L[i];
143  b1[i]=b1L[i]*scl;
144  b2[i]=b2L[i]*scl;
145  }
146  }
147  fitParameters= { unused, a1[0], a2[0], a3[0], b1[0], b2[0], b3[0], w[0] ,unused, unused,
148  unused, a1[1], a2[1], a3[1], b1[1], b2[1], b3[1], w[1] ,unused, unused,
149  unused, a1[2], a2[2], a3[2], b1[2], b2[2], b3[2], w[2] ,unused, unused,
150  unused, a1[3], a2[3], a3[3], b1[3], b2[3], b3[3], w[3] ,unused, unused,
151  unused, a1[4], a2[4], a3[4], b1[4], b2[4], b3[4], w[4] ,unused, unused,
152  unused, a1[5], a2[5], a3[5], b1[5], b2[5], b3[5], w[5] ,unused, unused};
153  }else if( mshowershapewithangle==0 ) {
154  fitParameters[1] = SS_A1;
155  fitParameters[2] = SS_A2;
156  fitParameters[3] = SS_A3;
157  fitParameters[4] = SS_B1 * scl;
158  fitParameters[5] = SS_B2 * scl;
159  fitParameters[6] = SS_B3 * scl;
160  }
161 }
162 
163 TF2 showerShapeFitFunction("showerShapeFitFunction",
165  -25.0, 25.0, -25.0, 25.0, fitParameters.size());
166 /*
167  Compose Minuit step size in each fit variable.
168  The first value is for the number of photons.
169  Each subsequent triplet is for the (x, y, E) of a photon, up to kMaxNPhotons.
170  */
171 std::vector<double> defaultMinuitStepSizes() {
172  std::vector<double> steps(1, 0.); // Initialise with nPhoton step
173  // Append default (x, y, E) steps for each photon
174  for (int i(0); i < kMaxNPhotons; ++i) {
175  steps.insert(steps.end(), {0.1, 0.1, 0.2});
176  } // for
177  return steps;
178 }
179 
180 std::vector<double> towerWidths; // Tower (x, y) width in cm
181 
182 // Helper function for accumulating tower energies
183 double addTowerEnergy(double energy, const FMSCluster::StFmsTower* tower) {
184  return energy + tower->hit()->energy();
185 }
186 
187 } // unnamed namespace
188 
189 namespace FMSCluster {
190 // Instantiate static members
191 StFmsTowerCluster::Towers* StFmsClusterFitter::mTowers(nullptr);
192 Double_t StFmsClusterFitter::mEnergySum(0.0);
193 
194 StFmsClusterFitter::StFmsClusterFitter( //const StFmsGeometry* geometry,
195  Int_t detectorId, Float_t xw, Float_t yw,
196  Float_t scaleShowerShapeLarge , Float_t scaleShowerShapeSmall,
197  Int_t ShowerShapeWithAngle, Int_t MergeSmallToLarge, double vertexZ)
198  : mMinuit(3 * kMaxNPhotons + 1),
199  mScaleShowerShapeLarge(scaleShowerShapeLarge), mScaleShowerShapeSmall(scaleShowerShapeSmall),
200  mShowerShapeWithAngle(ShowerShapeWithAngle) , mMergeSmallToLarge(MergeSmallToLarge){
201  // Set tower (x, y) widths for this detector
202  towerWidths.clear();
203  towerWidths.push_back(xw);
204  towerWidths.push_back(yw);
205 
206  setOption(mShowerShapeWithAngle,mMergeSmallToLarge ,vertexZ);
207  clear_fitParameters();
208  choose_fitParameters(detectorId);
209  showerShapeFitFunction.SetParameters(fitParameters.data());
210  mMinuit.SetPrintLevel(-1); // Quiet, including suppression of warnings (change to 0 for more info)
211 }
212 
214 
216  return &showerShapeFitFunction;
217 }
218 
219 Double_t StFmsClusterFitter::fitNPhoton(const std::vector<double>& parameters,
220  const std::vector<double>& steps,
221  const std::vector<double>& lower,
222  const std::vector<double>& upper,
223  PhotonList* photons) {
224  Double_t chiSquare(-1.); // Return value
225  // Check that there is a pointer to TObjArray of towers
226  if (!StFmsClusterFitter::mTowers) {
227  LOG_ERROR << "no tower data available! return -1!" << endm;
228  return chiSquare;
229  } // if
230  mMinuit.SetFCN(minimizationFunctionNPhoton);
231  int nPhotons = parameters.size() / 3;
232  if (nPhotons < 1 || nPhotons > kMaxNPhotons) {
233  LOG_ERROR << "Number of photons must be between 1 and " << kMaxNPhotons <<
234  "not " << nPhotons << " for fit. Setting it to be 1..." << endm;
235  nPhotons = 1;
236  } // if
237  mMinuit.mncler(); // Clear old parameters so we can define the new parameters
238  // The first parameter tells Minuit how many photons to fit!
239  // It should be a fixed parameter, and between 1 and the max number of photons
240  setMinuitParameter(0, "nph", parameters, steps, lower, upper);
241  // Set the rest of parameters: 3 parameters per photon
242  for (Int_t i = 0; i < nPhotons; i++) {
243  Int_t j = 3 * i + 1; // Need to set 3 parameters per photon
244  setMinuitParameter(j++, Form("x%d", i), parameters, steps, lower, upper);
245  setMinuitParameter(j++, Form("y%d", i), parameters, steps, lower, upper);
246  setMinuitParameter(j++, Form("E%d", i), parameters, steps, lower, upper);
247  } // if
248 
249  //ZZ never change energy!!!!!
250  if (nPhotons==1) {mMinuit.FixParameter(3) ; } // fix Energy during 1P fit
251  if (nPhotons==2) {mMinuit.FixParameter(3) ; mMinuit.FixParameter(6); } // fix Energy during 2P fit
252 
253  runMinuitMinimization();
254  // Populate the list of photons from the fit results
255  if (mMinuit.GetStatus() == 0) {
256  // Get the fit results and errors
257  std::vector<double> params(parameters.size(), 0.);
258  std::vector<double> errors(parameters.size(), 0.);
259  readMinuitParameters(params, errors);
260  for (unsigned i(1); i < parameters.size(); i += 3) {
261  photons->emplace_back(params.at(i), params.at(i + 1), params.at(i + 2));
262  } // for
263  // Evaluate chi-square (*not* chi-square per degree of freedom)
264  mMinuit.Eval(photons->size(), nullptr, chiSquare, params.data(), 1);
265  } // for
266  return chiSquare;
267 }
268 
269 Double_t StFmsClusterFitter::fitNPhoton(const std::vector<double>& parameters,
270  const std::vector<double>& lower,
271  const std::vector<double>& upper,
272  PhotonList* photons) {
273  return fitNPhoton(parameters, defaultMinuitStepSizes(),
274  lower, upper, photons);
275 }
276 
277 /*
278  A different set of parameters for 2-photon clusters only:
279  0: still a constant parameter, should be set to 2 for 2-photon fitting
280  1: xPi, x-position of pi^0
281  2: yPi, y-position of pi^0
282  3: d_gg, distance between 2 photons
283  4: theta, angle of displacement vector from photon 2 to photon 1
284  5: z_gg, can go from -1 to +1, so we do not set E1 > E2
285  6: E_gg, total energy of two photons
286  Thus, in the more conventional fitNPhoton() parameterization:
287  E1 = E_gg * (1 + z_gg) / 2
288  E2 = E_gg * (1 - z_gg) / 2
289  x1 = xPi + cos(theta) * d_gg * (1 - z_gg) / 2
290  y1 = yPi + sin(theta) * d_gg * (1 - z_gg) / 2
291  x2 = xPi - cos(theta) * d_gg * (1 + z_gg) / 2
292  y2 = yPi - sin(theta) * d_gg * (1 + z_gg) / 2
293 
294  The advantage of this parameterization is that for 2-photon cluster fitting
295  we can ensure that the two photons never get to close. The old parameterization
296  suffers from this shortcoming if we let the parameters vary freely.
297 
298  What we already know about the limits of the new parameters:
299  xPi and yPi: rarely do they go beyond 0.3 unit of lgd
300  theta: have a narrow theta range (for r = sigmaMax / sigmaMax,
301  |theta| < 0.5 * r / 0.65 when r < 0.65, and linear increase
302  from 0.5 to pi/2 for 0.65 < r < 1)
303  E_gg: given by Ec (+/- 20% or less)
304  z_gg: should just let it vary from -1 to 1
305  d_gg: a lower bound is given by r = sqrt(sigmaX^2 + sigmaY^2).
306  d_gg > Max(2.5 * (r - 0.6), 0.5)
307  */
308 Int_t StFmsClusterFitter::fit2Photon(const std::array<double, 7>& parameters,
309  const std::array<double, 7>& steps,
310  const std::array<double, 7>& lower,
311  const std::array<double, 7>& upper,
312  PhotonList* photons) {
313  Double_t chiSquare(-1.); // Return value
314  if (!StFmsClusterFitter::mTowers) {
315  LOG_ERROR << "no tower data available! return -1!" << endm;
316  return chiSquare;
317  } // if
318  mMinuit.SetFCN(minimizationFunction2Photon);
319  mMinuit.mncler(); // Clear old parameters so we can define the new parameters
320  const std::vector<TString> names = {
321  "nph", "xPi", "yPi", "d_gg", "theta", "z_gg", "E_gg"
322  };
323  for (unsigned i = 0; i < names.size(); ++i) {
324  setMinuitParameter(i, names.at(i), parameters, steps, lower, upper);
325  } // for
326  // Fix E_total and theta, we don't want these to be free parameters
327  mMinuit.FixParameter(4);
328  mMinuit.FixParameter(6);
329  runMinuitMinimization();
330  if (mMinuit.GetStatus() == 0) {
331  // Get the fit results for starting positions and errors
332  // 3 * nPhotons + 1 parameters = 7 for 2 photons
333  std::vector<double> param(parameters.size(), 0.);
334  std::vector<double> error(parameters.size(), 0.);
335  readMinuitParameters(param, error);
336  // Put the fit result back in "clust". Need to translate the special
337  // parameters for 2-photon fit into x, y, E, which looks a bit complicated!
338  // First photon
339  double x = param[1] + cos(param[4]) * param[3] * (1 - param[5]) / 2.0;
340  double y = param[2] + sin(param[4]) * param[3] * (1 - param[5]) / 2.0;
341  double E = param[6] * (1 + param[5]) / 2.0;
342  photons->emplace_back(x, y, E);
343  // Second photon
344  x = param[1] - cos(param[4]) * param[3] * (1 + param[5]) / 2.0;
345  y = param[2] - sin(param[4]) * param[3] * (1 + param[5]) / 2.0;
346  E = param[6] * (1 - param[5]) / 2.0;
347  photons->emplace_back(x, y, E);
348  // Evaluate the chi-square function
349  mMinuit.Eval(7, nullptr, chiSquare, param.data(), 1);
350  } // if
351  return chiSquare;
352 }
353 
355  Double_t* parameters) {
356  // Calculate the energy deposited in a tower by evaluating
357  // energyDepositionDistribution() at x+/-d/2 and y+/-d/2, for tower
358  // width d. The double-loop below is equivalent to
359  // F(x+d/2, y+d/2) + F(x-d/2, y-d/2) - F(x-d/2, y+d/2) - F(x+d/2, y-d/2)
360  Double_t energy=0.0;
361 
362  if(mshowershapewithangle==0){
363  double w = parameters[0];
364  for (int ix = 0; ix < 2; ++ix) {
365  for (int iy = 0; iy < 2; ++iy) {
366  double signX = std::pow(-1., ix); // 1 or -1
367  double signY = std::pow(-1., iy); // 1 or -1
368  std::array<double, 2> s{ {xy[0] + signX * w / 2., // x +/- d/2
369  xy[1] + signY * w / 2.} }; // y +/- d/2
370  energy += signX * signY * energyDepositionDistribution(s.data(),
371  parameters);
372  } // for
373  } // for
374  //cout<<"we are calling the OLD energyDepositionInTower(Double_t* xy,Double_t* parameters"<<endl;
375  }else{
376  Double_t *Zc;
377  Double_t ZcS[6] = {720.45,727.95,735.45,742.95,750.45,757.95};
378  Double_t ZcL[6] = {722.98,733.01,743.04,753.07,763.10,773.13};
379  Double_t Zmax,xoff,yoff;
380  if (parameters[0]>4) {
381  yoff=98.8; Zmax=735.45; xoff=0.3; Zc=ZcL;
382  }else{
383  yoff=46.5; Zmax=735.45; xoff=0.93; Zc=ZcS;
384  }
385  if (mmerge >0) yoff=98.8; // large cells always 98.8
386 
387  Double_t tany = ( yoff - xy[3]) / (Zmax - vertexz);
388  Double_t tanx = ( xy[1]- xoff ) / (Zmax - vertexz); //ZZ just in case
389 
390  for(Int_t i = 0; i < 6; i++){
391  Double_t xc = xy[1] + tanx*(Zc[i] - Zmax);
392  Double_t yc = xy[3] - tany*(Zc[i] - Zmax); //large (positive) tany corresponds to smaller row # (yc)
393  Int_t istart = i*10;
394  energy += energyDepositionInTowerSingleLayer(xy[0]-xc,xy[2]-yc,&parameters[istart]) * parameters[istart+7] ;
395  }
396  }
397  return energy;
398 }
399 
401  return kMaxNPhotons;
402 }
403 
404 int StFmsClusterFitter::runMinuitMinimization() {
405  std::vector<double> arguments = {1000., 1.}; // Max calls and tolerance
406  int errorFlag = -1;
407  mMinuit.mnexcm("MIGRAD", arguments.data(), arguments.size(), errorFlag);
408  // Free fixed parameters before next use of mMinuit. Wrap in if() to avoid
409  // noisy warning messages in case of no fixed parameters.
410  if (mMinuit.GetNumFixedPars() > 0) {
411  mMinuit.mnfree(0);
412  } // if
413  return errorFlag;
414 }
415 
416 // Calculate fractional photon energy deposition in a tower based on its (x, y)
417 // position relative to the tower center
418 Double_t StFmsClusterFitter::energyDepositionDistribution(
419  Double_t* xy,
420  Double_t* parameters) {
421  double f = 0;
422  // The parameter array has 10 elements, but we only use 6 here
423  // 1 to 6 are a1, a2, a3, b1, b2, b3 as defined in
424  // https://drupal.star.bnl.gov/STAR/blog/leun/2010/aug/02/fms-meeting-20100802
425  for (int i = 1; i < 4; i++) { // 1, 2, 3
426  f += showerShapeComponent(xy[0], xy[1], parameters[i], parameters[i + 3]);
427  } // for
428  return f / TMath::TwoPi();;
429 }
430 
431 // Uses the signature needed for TMinuit interface:
432 // http://root.cern.ch/root/htmldoc/TMinuit.html#TMinuit:SetFCN
433 void StFmsClusterFitter::minimizationFunctionNPhoton(Int_t& npara,
434  Double_t* grad,
435  Double_t& fval,
436  Double_t* para,
437  Int_t /* not used */) {
438  //mEnergySum was already calcurated in setTowers()
439  //const double energySum = std::accumulate(mTowers->begin(), mTowers->end(),0., addTowerEnergy);
440  fval = 0; // Stores sum of chi2 over each tower
441  const int nPhotons = static_cast<int>(para[0]);
442  // for (auto i = mTowers->begin(); i != mTowers->end(); ++i) {
443  for (auto i = mTowers->begin(), e = mTowers->end(); i!=e; ++i){
444  const StFmsTower* tower = *i;
445  // The shower shape function expects the centers of towers in units of cm
446  // Tower centers are stored in row/column i.e. local coordinates
447  // Therefore convert to cm, remembering to subtract 0.5 from row/column to
448  // get centres not edges
449  /* Stop getting xy here. Already in tower StFmsTower class
450  Double_t x, y;
451  if(tower->hit()->detectorId()<10){
452  x = tower->column() - 0.5;
453  y = tower->row() - 0.5;
454  }else{
455  x = (tower->column()-0.5)*2.0/3.0;
456  y = (tower->row() - 0.5)*2.0/3.0 + 9.0;
457  }
458  //const double x = towerWidths.at(0) * (tower->column() - 0.5);
459  //const double y = towerWidths.at(1) * (tower->row() - 0.5);
460  x *= towerWidths.at(0);
461  y *= towerWidths.at(1);
462  */
463  Double_t x=tower->x();
464  Double_t y=tower->y();
465  fitParameters.front() = tower->w();
466  // Add expected energy in tower from each photon, according to shower-shape
467  double expected = 0;
468  for (int j = 0; j < nPhotons; ++j) { // Recall there are 3 paras per photon
469  int k = 3 * j;
470 
471  if(mshowershapewithangle>0 ){ expected += para[k + 3] *
472  energyDepositionInTower(x , y ,para[k+1] , para[k+2], fitParameters.data(),mmerge,vertexz);
473  }
474  if(mshowershapewithangle==0 ){ expected += para[k + 3] *
475  energyDepositionInTowerOLD(x - para[k + 1], y - para[k + 2], fitParameters.data());
476  }
477 
478  }
479  //const double measured = tower->hit()->energy();
480  const double measured = tower->e();
481  const double deviation = measured - expected;
482  // Larisa's chi2 function definition
483  /*
484  const Double_t err = 0.03 *
485  pow(measured / energySum, 1. - 0.001 * energySum) *
486  pow(1 - measured / energySum, 1. - 0.007 * energySum) *
487  energySum + 0.01;
488  */
489  const Double_t ratio = measured / mEnergySum;
490  // const double err = 0.03 * measured * (1 - ratio) + 0.01;
491  const Double_t err = 0.03 *
492  pow(ratio, 1. - 0.001 * mEnergySum) *
493  pow(1. - ratio, 1. - 0.007 * mEnergySum) *
494  mEnergySum + 0.01;
495  //fval += pow(deviation, 2.) / err;
496  fval += deviation * deviation / err;
497  //cout << Form("n=%1d x=%6.2f y=%6.2f e=%6.2f exp=%6.2f diff=%6.2f sum=%6.2f err=%6.2f fval=%6.2f",
498  // nPhotons,x,y,measured,expected,deviation,mEnergySum,err,deviation*deviation/err)<<endl;
499  } // for
500  fval = std::max(fval, 0.); // require that the fraction be positive
501  //cout << Form("nPhotons=%d fval=%6.2f",nPhotons,fval)<<endl;
502 }
503 
504 // Uses the signature needed for TMinuit interface:
505 // http://root.cern.ch/root/htmldoc/TMinuit.html#TMinuit:SetFCN
506 void StFmsClusterFitter::minimizationFunction2Photon(Int_t& nparam,
507  Double_t* grad,
508  Double_t& fval,
509  Double_t* param,
510  Int_t /* not used */) {
511  // Only need to translate into the old parameterization
512  const double dgg = param[3];
513  const double zgg = param[5];
514  const double angle = param[4];
515  std::array<double, 7> oldParam{ {
516  param[0], // Number of photons, unchanged
517  param[1] + cos(angle) * dgg * (1 - zgg) / 2.0, // x 1
518  param[2] + sin(angle) * dgg * (1 - zgg) / 2.0, // y 1
519  param[6] * (1 + zgg) / 2.0, // Energy 1
520  param[1] - cos(angle) * dgg * (1 + zgg) / 2.0, // x 2
521  param[2] - sin(angle) * dgg * (1 + zgg) / 2.0, // y 2
522  param[6] * (1 - zgg) / 2.0 // Energy 2
523  } };
524  // Now call the regular minimization function with the translated parameters
525  minimizationFunctionNPhoton(nparam, grad, fval, oldParam.data(), 0);
526 }
527 
528 template<class Container>
529 int StFmsClusterFitter::setMinuitParameter(int index, const TString& name,
530  const Container& params,
531  const Container& steps,
532  const Container& lower,
533  const Container& upper) {
534  int error = 0;
535  mMinuit.mnparm(index, name, params.at(index), steps.at(index),
536  lower.at(index), upper.at(index), error);
537  return error;
538 }
539 
540 int StFmsClusterFitter::readMinuitParameters(std::vector<double>& parameters,
541  std::vector<double>& errors) {
542  errors.resize(parameters.size(), 0.);
543  for (int i = 0, size = parameters.size(); i != size; ++i) {
544  mMinuit.GetParameter(i, parameters.at(i), errors.at(i));
545  } // for
546  return parameters.size();
547 }
548 
550  mTowers = towers;
551  mEnergySum = std::accumulate(mTowers->begin(), mTowers->end(), 0., addTowerEnergy);
552  //if mScaleShowerShape is on, and if top cell is in large cell, scale shower shape up
553  //if(mScaleShowerShape ==1 && mShowerShapeWithAngle==0){
554  int d=mTowers->front()->hit()->detectorId();
555  if(d <= 9){
556  choose_fitParameters(d,mScaleShowerShapeLarge);
557  }else{
558  choose_fitParameters(d,mScaleShowerShapeSmall);
559  }
560  showerShapeFitFunction.SetParameters(fitParameters.data());
561 }
562 
563 } // namespace FMSCluster
Declaration of StFmsClusterFitter, shower-shape fitting routine.
Int_t fit2Photon(const std::array< double, 7 > &parameters, const std::array< double, 7 > &steps, const std::array< double, 7 > &lower, const std::array< double, 7 > &upper, PhotonList *photons)
const StFmsHit * hit() const
Definition: StFmsTower.h:90
static Double_t energyDepositionInTowerOLD(Double_t x, Double_t y, Double_t *par)
Declaration of StFmsTower, a simple FMS tower wrapper.
std::list< StFmsTower * > Towers
Shorthand for tower collection.
static Double_t energyDepositionInTower(Double_t *x, Double_t *par)
Double_t fitNPhoton(const std::vector< double > &parameteres, const std::vector< double > &steps, const std::vector< double > &lower, const std::vector< double > &up, PhotonList *photons)
void setTowers(StFmsTowerCluster::Towers *towers)