CbmRoot
Loading...
Searching...
No Matches
CbmRichRingFitterEllipseMinuit.cxx
Go to the documentation of this file.
1/* Copyright (C) 2011-2020 UGiessen/JINR-LIT, Giessen/Dubna
2 SPDX-License-Identifier: GPL-3.0-only
3 Authors: Semen Lebedev [committer], Florian Uhlig */
4
13
14#include "Minuit2/Minuit2Minimizer.h"
15
16#include <Logger.h>
17
18using std::cout;
19using std::endl;
20
22
24
26{
27 int nofHits = ring->GetNofHits();
28
29 if (nofHits <= 5) {
30 ring->SetXYABP(-1., -1., -1., -1., -1.);
31 ring->SetRadius(-1.);
32 return;
33 }
34
35 vector<double> hitX;
36 vector<double> hitY;
37 hitX.clear();
38 hitY.clear();
39 for (int i = 0; i < nofHits; i++) {
40 hitX.push_back(ring->GetHit(i).fX);
41 hitY.push_back(ring->GetHit(i).fY);
42 }
43
44 vector<double> fpar = DoFit(hitX, hitY);
45
46 TransformToRichRing(ring, fpar);
47
48 CalcChi2(ring);
49}
50
52{
53 // calculate center of the ellipse
54 double xc = (fpar[0] + fpar[2]) / 2.;
55 double yc = (fpar[1] + fpar[3]) / 2.;
56 // calculate length of b axes
57 double p1 = (fpar[0] - fpar[2]) * (fpar[0] - fpar[2]) + (fpar[1] - fpar[3]) * (fpar[1] - fpar[3]);
58 if (p1 < 0.) {
59 ring->SetXYABP(-1., -1., -1., -1., -1.);
60 ring->SetRadius(-1.);
61 return;
62 }
63
64 double c = sqrt(p1) / 2.;
65 double p2 = fpar[4] * fpar[4] - c * c;
66 if (p2 < 0.) {
67 ring->SetXYABP(-1., -1., -1., -1., -1.);
68 ring->SetRadius(-1.);
69 return;
70 }
71 double b = sqrt(p2);
72 // calculate angle
73 double p3 = fpar[2] - fpar[0];
74 if (p3 == 0.) {
75 ring->SetXYABP(-1., -1., -1., -1., -1.);
76 ring->SetRadius(-1.);
77 return;
78 }
79 double k = (fpar[3] - fpar[1]) / (fpar[2] - fpar[0]);
80 double ang = atan(k);
81
82 ring->SetXYABP(xc, yc, fpar[4], b, ang);
83 ring->SetRadius((b + fpar[4]) / 2.);
84}
85
86vector<double> CbmRichRingFitterEllipseMinuit::DoFit(const vector<double>& x, const vector<double>& y)
87{
88
89 // Create initial starting values for parameters
90 double xf1 = 0.;
91 double yf1 = 0.;
92 for (unsigned int i = 0; i < x.size(); i++) {
93 xf1 += x[i];
94 yf1 += y[i];
95 }
96 double a = 5.;
97 xf1 = xf1 / x.size() - a;
98 yf1 = yf1 / x.size();
99 double xf2 = xf1 + a;
100 double yf2 = yf1;
101
102
103 ROOT::Minuit2::Minuit2Minimizer min;
104
105
106 FCNEllipse2* theFCN = new FCNEllipse2(x, y);
107
108 min.SetMaxFunctionCalls(1000000);
109 min.SetMaxIterations(100000);
110 min.SetTolerance(0.001);
111
112 min.SetFunction(*theFCN);
113
114 // Set the free variables to be minimized!
115 min.SetVariable(0, "xf1", xf1, 0.1);
116 min.SetVariable(1, "yf1", yf1, 0.1);
117 min.SetVariable(2, "xf2", xf2, 0.1);
118 min.SetVariable(3, "yf2", yf2, 0.1);
119 min.SetVariable(4, "a", a, 0.1);
120
121 min.Minimize();
122
123 const double* xs = min.X();
124
125 vector<double> fpar;
126 fpar.clear();
127 for (int i = 0; i < 5; i++) {
128 fpar.push_back(xs[i]);
129 }
130 return fpar;
131}
This is the implementation of ellipse fitting using MINUIT.
friend fvec sqrt(const fvec &a)
friend fscal min(fscal x, fscal y)
virtual void CalcChi2(CbmRichRingLight *ring)
Calculate chi2 of the ellipse fit.
virtual void DoFit(CbmRichRingLight *ring)
Inherited from CbmRichRingFitterBase.
virtual ~CbmRichRingFitterEllipseMinuit()
Standard destructor.
void TransformToRichRing(CbmRichRingLight *ring, const vector< double > &par)
Transform obtained parameters from MINUIT to CbmRichRingLight.
void SetXYABP(float x, float y, float a, float b, float p)
Set all 5 ellipse parameters.
void SetRadius(float r)
int GetNofHits() const
Return number of hits in ring.
CbmRichHitLight GetHit(int ind)
Return hit by the index.