GeometryFitter.cc
Go to the documentation of this file.
1 #include "GeometryFitter.h"
2 #include "GeometryChi2.h"
3 #include "SphericalShowerFront.h"
4 #include "PlaneShowerFront.h"
5 
6 #include <utl/ErrorLogger.h>
7 #include <utl/PhysicalConstants.h>
8 #include <utl/Math.h>
9 
10 #include <TMatrixD.h>
11 
12 #include <Minuit2/MnUserCovariance.h>
13 #include <Minuit2/MnMigrad.h>
14 #include <Minuit2/FunctionMinimum.h>
15 #include <Minuit2/MnUserParameters.h>
16 #include <Minuit2/MnPrint.h>
17 
18 
19 using std::cout;
20 using std::endl;
21 
22 namespace MdGeometryFitterAG {
23 
25  {
26 
27  // Here goes the definition of the fit parameters
28  // They are always referenced by the names defined here
29  parSeed.Add("u", 0, .01);
30  parSeed.Add("v", 0, .01);
31  parSeed.Add("ct0", 0, 10);
32  parSeed.Add("radius", 7500, 500);
33  parSeed.Add("xcore", 0, 100);
34  parSeed.Add("ycore", 0, 100);
35  parSeed.Add("zcore", 0, 0);
36 
37  nParameters = 7; // must match the number of parameters defined above
38 
39  // Only the axis and core time are free by default
40  parSeed.Fix("radius");
41  parSeed.Fix("xcore");
42  parSeed.Fix("ycore");
43  parSeed.Fix("zcore");
44 
45  }
46 
47  void
48  GeometryFitter::AddDetector(int id, TVector3 pos, double time, double sigma)
49  {
50  TimeData detector = { id, pos, time, sigma };
51  timeData.push_back( detector );
52  }
53 
54  void
55  GeometryFitter::SetCore(const TVector3 &core)
56  {
57  parSeed.SetValue("xcore", core.x());
58  parSeed.SetValue("ycore", core.y());
59  parSeed.SetValue("zcore", core.z());
60  }
61 
62  void
64  {
65  parSeed.Release("xcore");
66  parSeed.Release("ycore"); // zcore is always fixed
67  }
68 
69  void
71  {
72  parSeed.Fix("xcore");
73  parSeed.Fix("ycore");
74  parSeed.Fix("zcore");
75  }
76 
77  int
78  GeometryFitter::FitPlane(double &u, double &v, double &ct0)
79  const
80  {
81 
82  double s1 = 0;
83  double sx = 0;
84  double sy = 0;
85  double st = 0;
86  double sxx = 0;
87  double sxy = 0;
88  double syy = 0;
89  double sxt = 0;
90  double syt = 0;
91  //double stt = 0;
92 
93  for (std::vector<TimeData>::const_iterator it=timeData.begin(); it!=timeData.end(); ++it) {
94  const double sigma = it->sigma;
95  const TVector3& pos = it->pos;
96  const double invSigma2 = 1./(sigma*sigma);
97  s1 += invSigma2;
98  const double x_s = pos.x() * invSigma2;
99  sx += x_s;
100  sxx += pos.x() * x_s;
101  sxy += pos.y() * x_s;
102  sxt += (it->time) * x_s;
103  const double y_s = pos.y() * invSigma2;
104  sy += y_s;
105  syy += pos.y() * y_s;
106  syt += (it->time) * y_s;
107  st += (it->time) * invSigma2;
108  //stt += t*t;
109  }
110 
111  st *= utl::kSpeedOfLight;
112  sxt *= utl::kSpeedOfLight;
113  syt *= utl::kSpeedOfLight;
114  //stt *= utl::kSpeedOfLight*utl::kSpeedOfLight;
115 
116  TMatrixDSym mat(3);
117  mat(0,0) = sxx;
118  mat(0,1) = sxy;
119  mat(0,2) = -sx;
120  mat(1,1) = syy;
121  mat(1,2) = -sy;
122  mat(2,2) = s1;
123 
124  double det;
125  mat.InvertFast(&det);
126 
127  if (det==0) {
128  INFO("Matrix inversion failed.");
129  return EXIT_FAILURE;
130  }
131 
132  TMatrixD k(3,1);
133  k(0,0) = -sxt;
134  k(1,0) = -syt;
135  k(2,0) = st;
136 
137  const TMatrixD p = TMatrixD(mat,TMatrixD::kMult,k);
138 
139  const double w2 = 1 - utl::Sqr(p(0,0)) - utl::Sqr(p(1,0));
140 
141  if (w2 < 0) {
142  INFO("Unphysical direction cosines");
143  return EXIT_FAILURE;
144  }
145 
146  // Return fit results
147  u = p(0,0);
148  v = p(1,0);
149  ct0 = p(2,0);
150 
151  return EXIT_SUCCESS;
152  }
153 
154  int
156  {
157 
158  double uplane, vplane; // Seeds of the axis direction cosines
159  double ct0plane; // Seed of the 'core time' times the speed of light
160 
161  // Fit a plane shower front to set the seeds for u, v, and ct0
162  if (FitPlane(uplane, vplane, ct0plane)!=EXIT_SUCCESS) {
163  return EXIT_FAILURE;
164  }
165 
166  // Initializing the cosine directors and the core time with the output from the plane fit
167  parSeed.SetValue("u", uplane);
168  parSeed.SetValue("v", vplane);
169  parSeed.SetValue("ct0", ct0plane);
170 
171  GeometryChi2 weightFunction(timeData); // Create the minimization function
172 
173  ROOT::Minuit2::MnMigrad migrad(weightFunction, parSeed); // Create the minimizer
174 
175  ROOT::Minuit2::FunctionMinimum min = migrad(); // minimize
176 
177  if (minuitOutput==true) {
178  cout << min;
179  }
180 
181  // check that the minimization converged
182  if ( !min.IsValid() || !min.HasValidCovariance() || min.HesseFailed() || min.HasReachedCallLimit() ) {
183  ERROR("Minuit minimize error");
184  return EXIT_FAILURE;
185  }
186 
187  // Retrieve fit parameters
188  const ROOT::Minuit2::MnUserParameterState &parameters0 = min.UserParameters();
189 
190  // Check that the director cosines are normalised
191  const double utemp = parameters0.Parameter(0).Value();
192  const double vtemp = parameters0.Parameter(1).Value();
193  const double w2 = 1 - utl::Sqr(utemp) - utl::Sqr(vtemp);
194  if (w2 < 0) {
195  ERROR(" Fit failed due to unphysical angle cosines.");
196  return EXIT_FAILURE;
197  }
198 
199  // Save the fitted parameters and their covariance matrix
200  parFitted = ParameterPtr( new ROOT::Minuit2::MnUserParameters( min.UserParameters() ) );
201  covariance = CovariancePtr( new ROOT::Minuit2::MnUserCovariance( min.UserCovariance() ) );
202 
203  return EXIT_SUCCESS;
204  }
205 
206 
207  double
209  const
210  {
211 
212  for (std::vector<TimeData>::const_iterator it=timeData.begin(); it!=timeData.end(); ++it) {
213  if (it->id==detectorId) {
214  return GetTimeResidual(*it);
215  }
216  }
217 
218  ERROR("Detector not found");
219  exit(-1); // stop execution
220 
221  }
222 
223  double
225  const
226  {
227 
228  for (std::vector<TimeData>::const_iterator it=timeData.begin(); it!=timeData.end(); ++it) {
229  if (it->id==detectorId) {
230  return GetPlaneFrontDelay(*it);
231  }
232  }
233 
234  ERROR("Detector not found");
235  exit(-1); // stop execution
236 
237  }
238 
239  double
241  const
242  {
243 
244  for (std::vector<TimeData>::const_iterator it=timeData.begin(); it!=timeData.end(); ++it) {
245  if (it->id==detectorId) {
246  return it->sigma;
247  }
248  }
249 
250  ERROR("Detector not found");
251  exit(-1); // stop execution
252 
253  }
254 
255  bool
257  const
258  {
259 
260  for (std::vector<TimeData>::const_iterator it=timeData.begin(); it!=timeData.end(); ++it) {
261  if (it->id==detectorId) {
262  return true;
263  }
264  }
265 
266  return false;
267  }
268 
269  double
271  const
272  {
273 
274  const double t0 = GetCt0() / utl::kSpeedOfLight;
275 
276  SphericalShowerFront showerFront(GetAxis(), t0, GetRadius(), GetCore());
277 
278  const double residual = data.time - showerFront(data.pos);
279 
280  return residual;
281  }
282 
283  double
285  const
286  {
287 
288  const double t0 = GetCt0() / utl::kSpeedOfLight;
289 
290  PlaneShowerFront showerFront(GetAxis(), t0, GetCore());
291 
292  const double deviance = data.time - showerFront(data.pos);
293 
294  return deviance;
295  }
296 
297  double
299  const
300  {
301 
302  double sum = 0;
303  for (std::vector<TimeData>::const_iterator it=timeData.begin(); it!=timeData.end(); ++it) {
304  sum += GetTimeResidual(*it);
305  }
306 
307  int n = timeData.size();
308  double meanResidual = sum / n;
309 
310  return meanResidual;
311  }
312 
313  double
315  const
316  {
317 
318  double chi2 = 0;
319  for (std::vector<TimeData>::const_iterator it=timeData.begin(); it!=timeData.end(); ++it) {
320  const double residual = GetTimeResidualSigmas(*it);
321  chi2 += utl::Sqr(residual);
322  }
323 
324  return chi2;
325  }
326 
327  double
329  const
330  {
331 
332  int nDetectors = GetNDetectors();
333 
334  int nFreeParameters(0);
335  for(int i=0; i<nParameters; ++i) {
336  if (parSeed.Parameter(i).IsFixed()==false) {
337  nFreeParameters++;
338  }
339  }
340 
341  int ndof = nDetectors - nFreeParameters;
342 
343  return ndof;
344  }
345 
346  double
348  const
349  {
350  double chi2 = GetChi2();
351  int n = timeData.size();
352  double spread = sqrt(chi2/(n - 1));
353  return spread;
354  }
355 
356  TVector3
358  const
359  {
360  return TVector3 (GetU(), GetV(), GetW());
361  }
362 
363  double
365  const
366  {
367 
368  double thetaError, phiError, thetaPhiCorrelation;
369  const utl::Vector::Triple axis (GetU(), GetV(), GetW());
370  const utl::Vector::Triple cova ((*covariance)(0,0), (*covariance)(0,1), (*covariance)(1,1));
371 
372  utl::PropagateAxisErrors(axis, cova, thetaError, phiError, thetaPhiCorrelation);
373 
374  return thetaError;
375  }
376 
377  double
379  const
380  {
381 
382  double thetaError, phiError, thetaPhiCorrelation;
383  const utl::Vector::Triple axis (GetU(), GetV(), GetW());
384  const utl::Vector::Triple cova ((*covariance)(0,0), (*covariance)(0,1), (*covariance)(1,1));
385 
386  utl::PropagateAxisErrors(axis, cova, thetaError, phiError, thetaPhiCorrelation);
387 
388  return phiError;
389  }
390 
391  double
393  const
394  {
395 
396  double thetaError, phiError, thetaPhiCorrelation;
397  const utl::Vector::Triple axis (GetU(), GetV(), GetW());
398  const utl::Vector::Triple cova ((*covariance)(0,0), (*covariance)(0,1), (*covariance)(1,1));
399 
400  utl::PropagateAxisErrors(axis, cova, thetaError, phiError, thetaPhiCorrelation);
401 
402  return thetaPhiCorrelation;
403  }
404 
405  TVector3
407  const
408  {
409  double x = parFitted->Value("xcore");
410  double y = parFitted->Value("ycore");
411  double z = parFitted->Value("zcore");
412 
413  TVector3 core(x, y, z);
414 
415  return core;
416  }
417 
419  const
420  {
421  if (IsCurvatureFix()) {
422  return 0;
423  } else {
424  return parFitted->Error("radius");
425  }
426  }
427 
429  const
430  {
431  unsigned int i = parSeed.Index("radius");
432  return parSeed.Parameter(i).IsFixed();
433  }
434 
436  const
437  {
438  unsigned int i = parSeed.Index("xcore");
439  return parSeed.Parameter(i).IsFixed();
440  }
441 
442 } // end namespace MdGeometryFitterAG
void SetCore(const TVector3 &core)
constexpr T Sqr(const T &x)
double GetTimeResidual(int detectorId) const
boost::tuple< double, double, double > Triple
Coordinate triple for easy getting or setting of coordinates.
Definition: BasicVector.h:147
bool HasDetector(int detectorId) const
#define INFO(message)
Macro for logging informational messages.
Definition: ErrorLogger.h:161
double GetPlaneFrontDelay(int detectorId) const
int exit
Definition: dump1090.h:237
std::unique_ptr< ROOT::Minuit2::MnUserCovariance > CovariancePtr
double GetTimeResidualSigmas(const TimeData &data) const
void PropagateAxisErrors(const Vector::Triple &u_v_w, const Vector::Triple &sigma_u2_uv_v2, double &thetaError, double &phiError, double &thetaPhiCorrelation)
std::unique_ptr< ROOT::Minuit2::MnUserParameters > ParameterPtr
constexpr double kSpeedOfLight
ROOT::Minuit2::MnUserParameters parSeed
uint16_t * data
Definition: dump1090.h:228
double GetTimeError(int detectorId) const
int FitPlane(double &u, double &v, double &ct0) const
std::vector< TimeData > timeData
#define ERROR(message)
Macro for logging error messages.
Definition: ErrorLogger.h:165
void AddDetector(int id, TVector3 pos, double time, double sigma)
Note about vectors The TVector3 class is used here instead of the utl::Vector and utl::Point classses...

, generated on Tue Sep 26 2023.