EIC Software
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
CbmRichRingFitterCOP.cxx
Go to the documentation of this file. Or view the newest version in sPHENIX GitHub for file CbmRichRingFitterCOP.cxx
1 
7 #include "CbmRichRingFitterCOP.h"
8 #include "CbmRichRingLight.h"
9 
10 #include <iostream>
11 #include <cmath>
12 
13 using namespace std;
14 
16 {
17 
18 }
19 
21 {
22 
23 }
24 
26  CbmRichRingLight *ring)
27 {
28  FitRing(ring);
29 }
30 
32  CbmRichRingLight* ring)
33 {
34  int nofHits = ring->GetNofHits();
35  if (nofHits < 3) {
36  ring->SetRadius(0.);
37  ring->SetCenterX(0.);
38  ring->SetCenterY(0.);
39  return;
40  }
41 
42  if (nofHits >= MAX_NOF_HITS_IN_RING) {
43  cout << "-E- CbmRichRingFitterCOP::DoFit(), too many hits in the ring:" << nofHits <<endl;
44  ring->SetRadius(0.);
45  ring->SetCenterX(0.);
46  ring->SetCenterY(0.);
47  return;
48  }
49  int iterMax = 4;
50  float Xi, Yi, Zi;
51  float M0, Mx, My, Mz, Mxy, Mxx, Myy, Mxz, Myz, Mzz, Mxz2, Myz2, Cov_xy;
52  float A0, A1, A2, A22;
53  float epsilon = 0.00001;
54  float Dy, xnew, xold, ynew, yold = 10000000.;
55 
56  M0 = nofHits;
57  Mx = My = 0.;
58 
59  // calculate center of gravity
60  for (int i = 0; i < nofHits; i++) {
61  Mx += ring->GetHit(i).fX;
62  My += ring->GetHit(i).fY;
63  }
64  Mx /= M0;
65  My /= M0;
66 
67  // computing moments (note: all moments are normed, i.e. divided by N)
68  Mxx = Myy = Mxy = Mxz = Myz = Mzz = 0.;
69 
70  for (int i = 0; i < nofHits; i++) {
71  // transform to center of gravity coordinate system
72  Xi = ring->GetHit(i).fX - Mx;
73  Yi = ring->GetHit(i).fY - My;
74  Zi = Xi * Xi + Yi * Yi;
75 
76  Mxy += Xi * Yi;
77  Mxx += Xi * Xi;
78  Myy += Yi * Yi;
79  Mxz += Xi * Zi;
80  Myz += Yi * Zi;
81  Mzz += Zi * Zi;
82  }
83  Mxx /= M0;
84  Myy /= M0;
85  Mxy /= M0;
86  Mxz /= M0;
87  Myz /= M0;
88  Mzz /= M0;
89 
90  //computing the coefficients of the characteristic polynomial
91  Mz = Mxx + Myy;
92  Cov_xy = Mxx * Myy - Mxy * Mxy;
93  Mxz2 = Mxz * Mxz;
94  Myz2 = Myz * Myz;
95 
96  A2 = 4. * Cov_xy - 3. * Mz * Mz - Mzz;
97  A1 = Mzz * Mz + 4. * Cov_xy * Mz - Mxz2 - Myz2 - Mz * Mz * Mz;
98  A0 = Mxz2 * Myy + Myz2 * Mxx - Mzz * Cov_xy - 2. * Mxz * Myz * Mxy + Mz
99  * Mz * Cov_xy;
100 
101  A22 = A2 + A2;
102  xnew = 0.;
103 
104  //Newton's method starting at x=0
105  int iter;
106  for (iter = 0; iter < iterMax; iter++) {
107  ynew = A0 + xnew * (A1 + xnew * (A2 + 4. * xnew * xnew));
108 
109  if (fabs(ynew) > fabs(yold)) {
110  // printf("Newton2 goes wrong direction: ynew=%f yold=%f\n",ynew,yold);
111  xnew = 0.;
112  break;
113  }
114 
115  Dy = A1 + xnew * (A22 + 16. * xnew * xnew);
116  xold = xnew;
117  xnew = xold - ynew / Dy;
118  //cout << " xnew = " << xnew ;
119  if (xnew == 0 || fabs((xnew - xold) / xnew) < epsilon){
120  //cout << "iter = " << iter << " N = " << fNhits << endl;
121  break;
122  }
123  }
124 
125  //if (iter == iterMax - 1) {
126  // printf("Newton2 does not converge in %d iterations\n",iterMax);
127  // xnew = 0.;
128  //}
129 
130  float radius = 0.;
131  float centerX = 0.;
132  float centerY = 0.;
133 
134  //computing the circle parameters
135  float GAM = -Mz - xnew - xnew;
136  float DET = xnew * xnew - xnew * Mz + Cov_xy;
137  if (DET != 0.) {
138  centerX = (Mxz * (Myy - xnew) - Myz * Mxy) / DET / 2.;
139  centerY = (Myz * (Mxx - xnew) - Mxz * Mxy) / DET / 2.;
140  radius = sqrt(centerX * centerX + centerY * centerY - GAM);
141  centerX += Mx;
142  centerY += My;
143  }
144 
145  ring->SetRadius(radius);
146  ring->SetCenterX(centerX);
147  ring->SetCenterY(centerY);
148 
149  CalcChi2(ring);
150 }