CbmRoot
Loading...
Searching...
No Matches
CbmRichRingFitterCOP.cxx
Go to the documentation of this file.
1/* Copyright (C) 2005-2012 GSI Helmholtzzentrum fuer Schwerionenforschung, Darmstadt
2 SPDX-License-Identifier: GPL-3.0-only
3 Authors: Alexander Ayriyan, Gennadi Ososkov, Semen Lebedev, Denis Bertini [committer] */
4
12
13#include "CbmRichRingLight.h"
14
15#include <cmath>
16#include <iostream>
17
18using namespace std;
19
21
23
25
27{
28 int nofHits = ring->GetNofHits();
29 if (nofHits < 3) {
30 ring->SetRadius(0.);
31 ring->SetCenterX(0.);
32 ring->SetCenterY(0.);
33 return;
34 }
35
36 if (nofHits >= MAX_NOF_HITS_IN_RING) {
37 cout << "-E- CbmRichRingFitterCOP::DoFit(), too many hits in the ring:" << nofHits << endl;
38 ring->SetRadius(0.);
39 ring->SetCenterX(0.);
40 ring->SetCenterY(0.);
41 return;
42 }
43 int iterMax = 4;
44 float Xi, Yi, Zi;
45 float M0, Mx, My, Mz, Mxy, Mxx, Myy, Mxz, Myz, Mzz, Mxz2, Myz2, Cov_xy;
46 float A0, A1, A2, A22;
47 float epsilon = 0.00001;
48 float Dy, xnew, xold, ynew, yold = 10000000.;
49
50 M0 = nofHits;
51 Mx = My = 0.;
52
53 // calculate center of gravity
54 for (int i = 0; i < nofHits; i++) {
55 Mx += ring->GetHit(i).fX;
56 My += ring->GetHit(i).fY;
57 }
58 Mx /= M0;
59 My /= M0;
60
61 // computing moments (note: all moments are normed, i.e. divided by N)
62 Mxx = Myy = Mxy = Mxz = Myz = Mzz = 0.;
63
64 for (int i = 0; i < nofHits; i++) {
65 // transform to center of gravity coordinate system
66 Xi = ring->GetHit(i).fX - Mx;
67 Yi = ring->GetHit(i).fY - My;
68 Zi = Xi * Xi + Yi * Yi;
69
70 Mxy += Xi * Yi;
71 Mxx += Xi * Xi;
72 Myy += Yi * Yi;
73 Mxz += Xi * Zi;
74 Myz += Yi * Zi;
75 Mzz += Zi * Zi;
76 }
77 Mxx /= M0;
78 Myy /= M0;
79 Mxy /= M0;
80 Mxz /= M0;
81 Myz /= M0;
82 Mzz /= M0;
83
84 //computing the coefficients of the characteristic polynomial
85 Mz = Mxx + Myy;
86 Cov_xy = Mxx * Myy - Mxy * Mxy;
87 Mxz2 = Mxz * Mxz;
88 Myz2 = Myz * Myz;
89
90 A2 = 4. * Cov_xy - 3. * Mz * Mz - Mzz;
91 A1 = Mzz * Mz + 4. * Cov_xy * Mz - Mxz2 - Myz2 - Mz * Mz * Mz;
92 A0 = Mxz2 * Myy + Myz2 * Mxx - Mzz * Cov_xy - 2. * Mxz * Myz * Mxy + Mz * Mz * Cov_xy;
93
94 A22 = A2 + A2;
95 xnew = 0.;
96
97 //Newton's method starting at x=0
98 int iter;
99 for (iter = 0; iter < iterMax; iter++) {
100 ynew = A0 + xnew * (A1 + xnew * (A2 + 4. * xnew * xnew));
101
102 if (fabs(ynew) > fabs(yold)) {
103 // printf("Newton2 goes wrong direction: ynew=%f yold=%f\n",ynew,yold);
104 xnew = 0.;
105 break;
106 }
107
108 Dy = A1 + xnew * (A22 + 16. * xnew * xnew);
109 xold = xnew;
110 xnew = xold - ynew / Dy;
111 //cout << " xnew = " << xnew ;
112 if (xnew == 0 || fabs((xnew - xold) / xnew) < epsilon) {
113 //cout << "iter = " << iter << " N = " << fNhits << endl;
114 break;
115 }
116 }
117
118 //if (iter == iterMax - 1) {
119 // printf("Newton2 does not converge in %d iterations\n",iterMax);
120 // xnew = 0.;
121 //}
122
123 float radius = 0.;
124 float centerX = 0.;
125 float centerY = 0.;
126
127 //computing the circle parameters
128 float GAM = -Mz - xnew - xnew;
129 float DET = xnew * xnew - xnew * Mz + Cov_xy;
130 if (DET != 0.) {
131 centerX = (Mxz * (Myy - xnew) - Myz * Mxy) / DET / 2.;
132 centerY = (Myz * (Mxx - xnew) - Mxz * Mxy) / DET / 2.;
133 radius = sqrt(centerX * centerX + centerY * centerY - GAM);
134 centerX += Mx;
135 centerY += My;
136 }
137
138 ring->SetRadius(radius);
139 ring->SetCenterX(centerX);
140 ring->SetCenterY(centerY);
141
142 CalcChi2(ring);
143}
Here the ring is fitted with the COP algorithm from A. Ayriyan/G. Ososkov.
friend fvec sqrt(const fvec &a)
static const int MAX_NOF_HITS_IN_RING
virtual void CalcChi2(CbmRichRingLight *ring)
Calculate chi2 for circle fitting algorithms.
CbmRichRingFitterCOP()
Standard constructor.
virtual void DoFit(CbmRichRingLight *ring)
Inherited from CbmRichRingFitterBase.
void FitRing(CbmRichRingLight *ring)
Execute ring fitting algorithm.
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)
Hash for CbmL1LinkKey.