CbmRoot
Loading...
Searching...
No Matches
CbmRichRingFitterRobustCOP.cxx
Go to the documentation of this file.
1/* Copyright (C) 2006-2012 GSI Helmholtzzentrum fuer Schwerionenforschung, Darmstadt
2 SPDX-License-Identifier: GPL-3.0-only
3 Authors: Alexander Ayriyan, Gennadi Ososkov, Claudia Hoehne, Semen Lebedev, Denis Bertini [committer] */
4
14
15#include <cmath>
16#include <iostream>
17
18using std::cout;
19using std::endl;
20using std::fabs;
21using std::sqrt;
22
24
26
28{
29 int nofHits = ring->GetNofHits();
30
31 double radius = 0.;
32 double centerX = 0.;
33 double centerY = 0.;
34
35 if (nofHits < 3) {
36 ring->SetCenterX(0.);
37 ring->SetCenterY(0.);
38 ring->SetRadius(0.);
39 return;
40 }
41
42 int iter, iterMax = 20;
43 int i_iter, i_max_Robust = 4;
44 const int MinNuberOfHits = 3;
45 const int MaxNuberOfHits = 2000;
46 double Xi, Yi, Zi;
47 double M0, Mx, My, Mz, Mxy, Mxx, Myy, Mxz, Myz, Mzz, Mxz2, Myz2,
48 Cov_xy; //,temp;
49 double A0, A1, A2, A22, epsilon = 0.000000000001;
50 double Dy, xnew, xold, ynew, yold = 100000000000.;
51 double GAM, DET;
52 double SumS1 = 0., SumS2 = 0.;
53 double sigma;
54 double ctsigma;
55 double sigma_min = 0.05;
56 double dx, dy;
57 double d[MaxNuberOfHits];
58 double w[MaxNuberOfHits];
59 double ct = 7.;
60
61 for (int i = 0; i < MaxNuberOfHits; i++)
62 w[i] = 1.;
63
64 Mx = My = 0.;
65 for (int i = 0; i < nofHits; i++) {
66 Mx += ring->GetHit(i).fX;
67 My += ring->GetHit(i).fY;
68 }
69
70 M0 = nofHits;
71 Mx /= M0;
72 My /= M0;
73
74 for (i_iter = 0; i_iter < i_max_Robust; i_iter++) {
75 sigma = sigma_min;
76 if (i_iter != 0) {
77 for (int i = 0; i < nofHits; i++) {
78 dx = Mx - ring->GetHit(i).fX;
79 dy = My - ring->GetHit(i).fY;
80 d[i] = sqrt(dx * dx + dy * dy) - radius;
81 SumS1 += w[i] * d[i] * d[i];
82 SumS2 += w[i];
83 }
84 if (SumS2 == 0.) {
85 sigma = sigma_min;
86 }
87 else {
88 sigma = sqrt(SumS1 / SumS2);
89 }
90 if (sigma < sigma_min) sigma = sigma_min;
91 ctsigma = ct * sigma;
92 SumS1 = 0.;
93 SumS2 = 0.;
94 for (int i = 0; i < nofHits; i++) {
95 if (d[i] <= ctsigma) {
96 w[i] = (1 - (d[i] / (ctsigma)) * (d[i] / (ctsigma))) * (1 - (d[i] / (ctsigma)) * (d[i] / (ctsigma)));
97 }
98 else {
99 w[i] = 0.;
100 }
101 }
102 }
103 //computing moments (note: all moments are normed, i.e. divided by N)
104 M0 = 0;
105 Mxx = Myy = Mxy = Mxz = Myz = Mzz = 0.;
106 for (int i = 0; i < nofHits; i++) {
107 if (w[i] != 0.) {
108 Xi = ring->GetHit(i).fX - Mx;
109 Yi = ring->GetHit(i).fY - My;
110 Zi = Xi * Xi + Yi * Yi;
111 Mxy += Xi * Yi;
112 Mxx += Xi * Xi;
113 Myy += Yi * Yi;
114 Mxz += Xi * Zi;
115 Myz += Yi * Zi;
116 Mzz += Zi * Zi;
117 M0++;
118 }
119 }
120 if (M0 < MinNuberOfHits) {
121 M0 = 0;
122 Mxx = Myy = Mxy = Mxz = Myz = Mzz = 0.;
123 M0 = 0;
124 for (int i = 0; i < nofHits; i++) {
125 Xi = ring->GetHit(i).fX - Mx;
126 Yi = ring->GetHit(i).fY - My;
127 Zi = Xi * Xi + Yi * Yi;
128 Mxy += Xi * Yi;
129 Mxx += Xi * Xi;
130 Myy += Yi * Yi;
131 Mxz += Xi * Zi;
132 Myz += Yi * Zi;
133 Mzz += Zi * Zi;
134 M0++;
135 }
136 }
137 Mxx /= M0;
138 Myy /= M0;
139 Mxy /= M0;
140 Mxz /= M0;
141 Myz /= M0;
142 Mzz /= M0;
143
144 //computing the coefficients of the characteristic polynomial
145 Mz = Mxx + Myy;
146 Cov_xy = Mxx * Myy - Mxy * Mxy;
147 Mxz2 = Mxz * Mxz;
148 Myz2 = Myz * Myz;
149
150 A2 = 4. * Cov_xy - 3. * Mz * Mz - Mzz;
151 A1 = Mzz * Mz + 4. * Cov_xy * Mz - Mxz2 - Myz2 - Mz * Mz * Mz;
152 A0 = Mxz2 * Myy + Myz2 * Mxx - Mzz * Cov_xy - 2. * Mxz * Myz * Mxy + Mz * Mz * Cov_xy;
153
154 A22 = A2 + A2;
155 iter = 0;
156 xnew = 0.;
157
158 //Newton's method starting at x=0
159 for (iter = 0; iter < iterMax; iter++) {
160 ynew = A0 + xnew * (A1 + xnew * (A2 + 4. * xnew * xnew));
161
162 if (fabs(ynew) > fabs(yold)) {
163 // printf("Newton2 goes wrong direction: ynew=%f yold=%f\n",ynew,yold);
164 xnew = 0.;
165 break;
166 }
167
168 Dy = A1 + xnew * (A22 + 16. * xnew * xnew);
169 xold = xnew;
170 xnew = xold - ynew / Dy;
171
172 if (fabs((xnew - xold) / xnew) < epsilon) break;
173 }
174
175 if (iter == iterMax - 1) {
176 //printf("Newton2 does not converge in %d iterations\n",iterMax);
177 xnew = 0.;
178 }
179 if (xnew < 0.) {
180 iter = 30;
181 //printf("Negative root: x=%f\n",xnew);
182 }
183
184 // computing the circle parameters
185 GAM = -Mz - xnew - xnew;
186 DET = xnew * xnew - xnew * Mz + Cov_xy;
187 centerX = (Mxz * (Myy - xnew) - Myz * Mxy) / DET / 2.;
188 centerY = (Myz * (Mxx - xnew) - Mxz * Mxy) / DET / 2.;
189 radius = sqrt(centerX * centerX + centerY * centerY - GAM);
190 centerX = centerX + Mx;
191 centerY = centerY + My;
192 Mx = centerX;
193 My = centerY;
194
195 if (DET == 0.) {
196 radius = 0.;
197 centerX = 0.;
198 centerY = 0.;
199 return;
200 }
201 }
202 ring->SetRadius(radius);
203 ring->SetCenterX(centerX);
204 ring->SetCenterY(centerY);
205
206 CalcChi2(ring);
207}
Here the ring is fitted with the RobustCOP algorithm from A. Ayriyan/G. Ososkov.
friend fvec sqrt(const fvec &a)
virtual void CalcChi2(CbmRichRingLight *ring)
Calculate chi2 for circle fitting algorithms.
virtual void DoFit(CbmRichRingLight *ring)
Inherited from CbmRichRingFitterBase.
virtual ~CbmRichRingFitterRobustCOP()
Destructor.
CbmRichRingFitterRobustCOP()
Default constructor.
void SetRadius(float r)
void SetCenterY(float y)
int GetNofHits() const
Return number of hits in ring.
CbmRichHitLight GetHit(int ind)
Return hit by the index.
void SetCenterX(float x)