56 TVectorD fit_ellipse(TGraph *g)
60 if (!g)
return ellipse;
61 if (g->GetN() < 6)
return ellipse;
67 Double_t xmin, xmax, ymin, ymax, X0, Y0;
68 g->ComputeRange(xmin, ymin, xmax, ymax);
70 X0 = (xmax + xmin) / 2.0;
71 Y0 = (ymax + ymin) / 2.0;
79 for (i = 0; i < N; i++) {
80 Double_t x = (g->GetX())[i] - X0;
81 Double_t y = (g->GetY())[i] - Y0;
91 TMatrixD S1(TMatrixD::kAtA, D1);
93 TMatrixD S2(D1, TMatrixD::kTransposeMult, D2);
95 TMatrixD S3(TMatrixD::kAtA, D2);
96 S3.Invert(&tmp); S3 *= -1.0;
98 std::cout <<
"fit_ellipse : linear part of the scatter matrix is singular!" << std::endl;
102 TMatrixD T(S3, TMatrixD::kMultTranspose, S2);
104 TMatrixD M(S2, TMatrixD::kMult, T); M += S1;
106 for (i = 0; i < 3; i++) {
108 M[0][i] = M[2][i] / 2.0;
113 TMatrixDEigen eig(M);
114 const TMatrixD &evec = eig.GetEigenVectors();
116 if ((eig.GetEigenValuesIm()).Norm2Sqr() != 0.0) {
117 std::cout <<
"fit_ellipse : eigenvalues have nonzero imaginary parts!" << std::endl;
121 for (i = 0; i < 3; i++) {
122 tmp = 4.0 * evec[0][i] * evec[2][i] - evec[1][i] * evec[1][i];
123 if (tmp > 0.0)
break;
126 std::cout <<
"fit_ellipse : no min. pos. eigenvalue found!" << std::endl;
131 TVectorD a1(TMatrixDColumn_const(evec, i));
134 a1 *= 1.0 / std::sqrt(tmp);
136 std::cout <<
"fit_ellipse : eigenvector for min. pos. eigenvalue is NULL!" << std::endl;
184 TVectorD ConicToParametric(
const TVectorD &conic)
188 if (conic.GetNrows() != 8) {
189 std::cout <<
"ConicToParametric : improper input vector length!" << std::endl;
193 Double_t a, b, theta;
194 Double_t x0 = conic[0];
195 Double_t y0 = conic[1];
198 Double_t A = conic[2];
199 Double_t B = conic[3] / 2.0;
200 Double_t C = conic[4];
201 Double_t D = conic[5] / 2.0;
202 Double_t F = conic[6] / 2.0;
203 Double_t G = conic[7];
205 Double_t J = B * B - A * C;
206 Double_t Delta = A * F * F + C * D * D + J * G - 2.0 * B * D * F;
207 Double_t I = - (A + C);
210 if (!( (Delta != 0.0) && (J < 0.0) && (I != 0.0) && (Delta / I < 0.0) )) {
211 std::cout <<
"ConicToParametric : ellipse (real) specific constraints not met!" << std::endl;
215 x0 += (C * D - B * F) / J;
216 y0 += (A * F - B * D) / J;
218 Double_t tmp = std::sqrt((A - C) * (A - C) + 4.0 * B * B);
219 a = std::sqrt(2.0 * Delta / J / (I + tmp));
220 b = std::sqrt(2.0 * Delta / J / (I - tmp));
224 tmp = (A - C) / 2.0 / B;
225 theta = -45.0 * (std::atan(tmp) / TMath::PiOver2());
226 if (tmp < 0.0) { theta -= 45.0; }
else { theta += 45.0; }
227 if (A > C) theta += 90.0;
228 }
else if (A > C) theta = 90.0;
231 if (a < b) { tmp = a; a = b; b = tmp; theta -= 90.0; }
233 if (theta < -45.0) theta += 180.0;
234 if (theta > 135.0) theta -= 180.0;
250 TGraph *TestGraphDLSF(Bool_t randomize = kFALSE) {
258 Double_t theta = 100;
262 x0 = 10.0 - 20.0 * gRandom->Rndm();
263 y0 = 10.0 - 20.0 * gRandom->Rndm();
264 a = 0.5 + 4.5 * gRandom->Rndm();
265 b = 0.5 + 4.5 * gRandom->Rndm();
266 theta = 180.0 - 360.0 * gRandom->Rndm();
271 Double_t dt = TMath::TwoPi() / Double_t(n);
273 theta *= TMath::PiOver2() / 90.0;
274 for (i = 0; i < n; i++) {
275 x[i] = a * (std::cos(dt * Double_t(i)) + 0.1 * gRandom->Rndm() - 0.05);
276 y[i] = b * (std::sin(dt * Double_t(i)) + 0.1 * gRandom->Rndm() - 0.05);
279 x[i] = x[i] * std::cos(theta) - y[i] * std::sin(theta);
280 y[i] = y[i] * std::cos(theta) + tmp * std::sin(theta);
287 TGraph *g = ((TGraph *)(gROOT->FindObject(
"g")));
289 g =
new TGraph(n, x, y);
290 g->SetNameTitle(
"g",
"test ellipse");
298 void fitEllipseTGraphDLSF(TGraph *g = ((TGraph *)0))
300 if (!g) g = TestGraphDLSF(kTRUE);
303 TVectorD conic = fit_ellipse(g);
304 TVectorD ellipse = ConicToParametric(conic);
307 if ( ellipse.GetNrows() == 5 ) {
308 std::cout << std::endl;
309 std::cout <<
"x0 = " << ellipse[0] << std::endl;
310 std::cout <<
"y0 = " << ellipse[1] << std::endl;
311 std::cout <<
"a = " << ellipse[2] << std::endl;
312 std::cout <<
"b = " << ellipse[3] << std::endl;
313 std::cout <<
"theta = " << ellipse[4] << std::endl;
314 std::cout << std::endl;
320 TCanvas *c = ((TCanvas *)(gROOT->GetListOfCanvases()->FindObject(
"c")));
321 if (c) { c->Clear(); }
else { c =
new TCanvas(
"c",
"c"); }
324 if ( ellipse.GetNrows() == 5 ) {
325 TEllipse *e =
new TEllipse(ellipse[0], ellipse[1],
326 ellipse[2], ellipse[3],
332 c->Modified(); c->Update();