ATLAS Offline Software
Loading...
Searching...
No Matches
TgcFit.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2023 CERN for the benefit of the ATLAS collaboration
3*/
4
5#include "TgcFit.h"
6#include "gsl/gsl_statistics.h"
7#include "gsl/gsl_fit.h"
8#include <float.h>
9#include <iostream>
10#include <cmath>
11#include <sstream>
12
13
16
17// --------------------------------------------------------------------------------
18// --------------------------------------------------------------------------------
19
21 const std::string& name,
22 const IInterface* parent):
23 AthAlgTool(type, name, parent)
24{
25}
26
27// --------------------------------------------------------------------------------
28// --------------------------------------------------------------------------------
29
31 unsigned MIN_WIRE_POINTS,
32 unsigned MIN_STRIP_POINTS)
33{
34 m_CHI2_TEST = CHI2_TEST;
35 m_MIN_WIRE_POINTS = MIN_WIRE_POINTS;
36 m_MIN_STRIP_POINTS = MIN_STRIP_POINTS;
37}
38
39// --------------------------------------------------------------------------------
40// --------------------------------------------------------------------------------
41
43{
44 double fY, fYerr;
45 // suppress thread-checker warning about unchecked code (gsl is thread-safe)
46 int status [[maybe_unused]] ATLAS_THREAD_SAFE =
47 gsl_fit_linear_est(fX, fIntercept, fSlope, fCov00, fCov01, fCov11, &fY, &fYerr);
48 return fY;
49}
50
51// --------------------------------------------------------------------------------
52// --------------------------------------------------------------------------------
53
55{
56 double *y = new double[points.size()];
57 double *w = new double[points.size()];
58 for (;;)
59 {
60 stats.clear();
61 for (const TrigL2MuonSA::TgcFit::Point& Pt : points)
62 {
63 // Exclude outliers.
64 if (!Pt.bOutlier)
65 {
66 y[stats.n] = Pt.fY;
67 w[stats.n] = Pt.fW;
68 stats.n++;
69 }
70 }
71 if (stats.n == 0)
72 break;
73
74 // Calculate mean and standard deviation.
75 // suppress thread-checker warning about unchecked code (gsl is thread-safe)
76 const double mean ATLAS_THREAD_SAFE = gsl_stats_wmean(w, 1, y, 1, stats.n);
77 stats.fMean = mean;
78 if (stats.n == 1)
79 break;
80 const double stddev ATLAS_THREAD_SAFE = gsl_stats_wsd (w, 1, y, 1, stats.n);
81 stats.fStd = stddev;
82 double fMaxChi2 = 0.0;
83 int iPtMax = -1;
84 for (unsigned iPt = 0; iPt < points.size(); iPt++)
85 {
86 if (!points[iPt].bOutlier)
87 {
88 double fDiff = points[iPt].fY - stats.fMean;
89 points[iPt].fChi2 = points[iPt].fW * fDiff * fDiff;
90 stats.fChi2 += points[iPt].fChi2;
91 if (fMaxChi2 < points[iPt].fChi2)
92 {
93 fMaxChi2 = points[iPt].fChi2;
94 iPtMax = iPt;
95 }
96 }
97 }
98 // Print results.
99 ATH_MSG_DEBUG( "SimpleStatistics:"
100 << " n=" << stats.n << " Mean=" << stats.fMean
101 << " Std=" << stats.fStd << " Chi2=" << stats.fChi2);
102
103 if (iPtMax == -1 || fMaxChi2 < m_CHI2_TEST)
104 break;
105 points[iPtMax].bOutlier = true;
106 }
107 delete [] y;
108 delete [] w;
109}
110
111// --------------------------------------------------------------------------------
112// --------------------------------------------------------------------------------
113
115{
116 double *x = new double[points.size()];
117 double *y = new double[points.size()];
118 double *w = new double[points.size()];
119 for (;;)
120 {
121 stats.clear();
122 for (const TrigL2MuonSA::TgcFit::Point& Pt : points)
123 {
124 if (!Pt.bOutlier)
125 {
126 x[stats.n] = Pt.fX;
127 y[stats.n] = Pt.fY;
128 w[stats.n] = Pt.fW;
129 stats.n++;
130 }
131 }
132 if (stats.n < 2)
133 break;
134
135 // suppress thread-checker warning about unchecked code (gsl is thread-safe)
136 int status [[maybe_unused]] ATLAS_THREAD_SAFE = gsl_fit_wlinear(x, 1,
137 w, 1,
138 y, 1,
139 stats.n,
140 &stats.fIntercept, &stats.fSlope,
141 &stats.fCov00, &stats.fCov01, &stats.fCov11,
142 &stats.fChi2);
143 ATH_MSG_DEBUG("Y=" << stats.fIntercept << "+X*" << stats.fSlope
144 << ", N=" << stats.n << ", Chi2=" << stats.fChi2);
145
146 double fMaxChi2 = 0.0;
147 int iPtMax = -1;
148 for (unsigned iPt = 0; iPt < points.size(); iPt++)
149 {
150 if (!points[iPt].bOutlier)
151 {
152 double fDiff = points[iPt].fY - stats.eval(points[iPt].fX);
153 points[iPt].fChi2 = points[iPt].fW * fDiff * fDiff;
154 if (fMaxChi2 < points[iPt].fChi2)
155 {
156 fMaxChi2 = points[iPt].fChi2;
157 iPtMax = iPt;
158 }
159 }
160 }
161 if (iPtMax == -1 || fMaxChi2 < m_CHI2_TEST || stats.n <= 2)
162 break;
163 points[iPtMax].bOutlier = true;
164 }
165
166 delete [] x;
167 delete [] y;
168 delete [] w;
169
170 // Print results
171 for (const TrigL2MuonSA::TgcFit::Point& Pt : points)
172 {
173 if (!Pt.bOutlier)
174 {
175 ATH_MSG_DEBUG("Idx=" << Pt.nIdx
176 << ", x=" << Pt.fX
177 << ", y=" << Pt.fY
178 << ", w=" << Pt.fW
179 << ", Y=" << stats.eval(Pt.fX)
180 << ", chi2=" << Pt.fChi2);
181 }
182 }
183}
184
185// --------------------------------------------------------------------------------
186// --------------------------------------------------------------------------------
187
189 std::vector<int> Stations;
190 Stations.reserve(array.size());
191 for (const TrigL2MuonSA::TgcFit::Point& wirePt : array)
192 {
193 Stations.push_back(wirePt.nStation);
194 }
195 std::sort(Stations.begin(), Stations.end());
196 Stations.erase( std::unique( Stations.begin(), Stations.end() ), Stations.end() );
197 return Stations.size();
198}
199
202 TrigL2MuonSA::TgcFitResult& tgcFitResult) const
203{
204 ATH_MSG_DEBUG("TrigL2MuonSA::TgcFit::runTgcMiddle stripPoints=" << stripPoints.size()
205 << " wirePoints=" << wirePoints.size());
206
207 tgcFitResult.tgcMidRhoNin = wirePoints.size();
208 tgcFitResult.tgcMidPhiNin = stripPoints.size();
209
210 if (stripPoints.empty() || wirePoints.empty())
211 return FIT_NONE;
212
213 Status status = FIT_NONE;
214 LinStats stripStats;
215 LinStats wireStats;
216 const int wireStationsCount = countUniqueStations(wirePoints);
217 const int stripStationsCount = countUniqueStations(stripPoints);
218
219
220 if (wireStationsCount == 1 || wirePoints.size() < m_MIN_WIRE_POINTS)
221 {
222 status = FIT_POINT;
223 printDebug("runTgcMiddle: Wires fit point");
224 SimpleStats stats;
225 SimpleStatistics(wirePoints, stats);
226 wireStats.fIntercept = stats.fMean;
227 wireStats.n = stats.n;
228 wireStats.fChi2 = stats.fChi2;
229
230 printDebug("runTgcMiddle: Strips fit point");
231 SimpleStatistics(stripPoints, stats);
232 stripStats.fIntercept = stats.fMean;
233 stripStats.n = stats.n;
234 stripStats.fChi2 = stats.fChi2;
235 }
236 else
237 {
238 status = FIT_LINE;
239 printDebug("runTgcMiddle: Wires fit line");
240 linReg(wirePoints, wireStats);
241 if (stripStationsCount == 1 || stripPoints.size() < m_MIN_STRIP_POINTS)
242 {
243 printDebug("runTgcMiddle: Strips fit point");
244 SimpleStats stats;
245 SimpleStatistics(stripPoints, stats);
246 stripStats.fIntercept = stats.fMean;
247 stripStats.n = stats.n;
248 stripStats.fChi2 = stats.fChi2;
249 }
250 else
251 {
252 printDebug("runTgcMiddle: Strips fit line");
253 linReg(stripPoints, stripStats);
254 }
255 }
256
257 tgcFitResult.intercept = wireStats.fIntercept;
258 tgcFitResult.slope = wireStats.fSlope;
259
260 // Create low and high points
261 double lowZ = 30000.0, highZ = 0.0;
262 int iLow = -1, iHigh = -1;
263 for (unsigned iPt = 0; iPt < wirePoints.size(); iPt++)
264 {
265 if (!wirePoints[iPt].bOutlier)
266 {
267 if (lowZ > std::abs(wirePoints[iPt].fX))
268 {
269 lowZ = std::abs(wirePoints[iPt].fX);
270 iLow = iPt;
271 }
272 if (highZ < std::abs(wirePoints[iPt].fX))
273 {
274 highZ = std::abs(wirePoints[iPt].fX);
275 iHigh = iPt;
276 }
277 }
278 }
279 if (iLow > -1 && iLow < (int)wirePoints.size()) lowZ = wirePoints[iLow].fX;
280 if (iHigh > -1 && iHigh < (int)wirePoints.size()) highZ = wirePoints[iHigh].fX;
281 Amg::Vector3D p1(wireStats.eval(lowZ), 0.0, lowZ);
282 double phi = stripStats.eval(lowZ);
283 if( phi > M_PI ) phi -= M_PI*2;
284 if( phi < -M_PI ) phi += M_PI*2;
285 Amg::setPhi(p1, phi);
286 Amg::Vector3D p2(wireStats.eval(highZ), 0.0, highZ);
287 phi = stripStats.eval(highZ);
288 if( phi > M_PI ) phi -= M_PI*2;
289 if( phi < -M_PI ) phi += M_PI*2;
290 Amg::setPhi(p2, phi);
291 {
292 ATH_MSG_DEBUG("runTgcMiddle: Point1 eta=" << p1.eta()
293 << ",phi=" << p1.phi() << ",perp=" << p1.perp() << ",z=" << p1.z());
294 }
295 {
296 ATH_MSG_DEBUG("runTgcMiddle: Point2 eta=" << p2.eta()
297 << ",phi=" << p2.phi() << ",perp=" << p2.perp() << ",z=" << p2.z());
298 }
299 tgcFitResult.tgcMid1[0] = p1.eta();
300 tgcFitResult.tgcMid1[1] = p1.phi();
301 tgcFitResult.tgcMid1[2] = p1.perp();
302 tgcFitResult.tgcMid1[3] = p1.z();
303 tgcFitResult.tgcMid2[0] = p2.eta();
304 tgcFitResult.tgcMid2[1] = p2.phi();
305 tgcFitResult.tgcMid2[2] = p2.perp();
306 tgcFitResult.tgcMid2[3] = p2.z();
307 tgcFitResult.tgcMidRhoChi2 = wireStats.fChi2;
308 tgcFitResult.tgcMidRhoN = wireStats.n;
309 tgcFitResult.tgcMidPhiChi2 = stripStats.fChi2;
310 tgcFitResult.tgcMidPhiN = stripStats.n;
311
312 return status;
313}
314
315// --------------------------------------------------------------------------------
316// --------------------------------------------------------------------------------
317
320 TrigL2MuonSA::TgcFitResult& tgcFitResult) const
321{
322 Status status = FIT_NONE;
323 SimpleStats stripStats;
324 SimpleStats wireStats;
325
326 tgcFitResult.tgcInnRhoNin = wirePoints.size();
327 tgcFitResult.tgcInnPhiNin = stripPoints.size();
328
329 ATH_MSG_DEBUG("runTgcInner: stripPoints.size()=" << stripPoints.size()
330 << ", wirePoints.size()=" << wirePoints.size());
331
332 if (stripPoints.size() > 1 && wirePoints.size() > 1)
333 {
334 status = FIT_POINT;
335 printDebug("runTgcInner: Wires fit point");
336 SimpleStatistics(wirePoints, wireStats);
337
338 printDebug("runTgcInner: Strips fit point");
339 SimpleStatistics(stripPoints, stripStats);
340
341 Amg::Vector3D p(wireStats.fMean, 0.0, wirePoints[0].fX);
342 double phi = stripStats.fMean;
343 if( phi > M_PI ) phi -= M_PI*2;
344 if( phi < -M_PI ) phi += M_PI*2;
345 Amg::setPhi(p, phi);
346
347 ATH_MSG_DEBUG("runTgcInner: Point eta=" << p.eta()
348 << ",phi=" << p.phi() << ",perp=" << p.perp() << ",z=" << p.z());
349
350 tgcFitResult.tgcInn[0] = p.eta();
351 tgcFitResult.tgcInn[1] = p.phi();
352 tgcFitResult.tgcInn[2] = p.perp();
353 tgcFitResult.tgcInn[3] = p.z();
354 tgcFitResult.tgcInnRhoStd = wireStats.fStd;
355 tgcFitResult.tgcInnRhoN = wireStats.n;
356 tgcFitResult.tgcInnPhiStd = stripStats.fStd;
357 tgcFitResult.tgcInnPhiN = stripStats.n;
358 }
359 return status;
360}
361
362// --------------------------------------------------------------------------------
363// --------------------------------------------------------------------------------
#define M_PI
Scalar phi() const
phi method
#define ATH_MSG_DEBUG(x)
#define y
#define x
Define macros for attributes used to control the static checker.
#define ATLAS_THREAD_SAFE
AthAlgTool(const std::string &type, const std::string &name, const IInterface *parent)
Constructor with parameters:
void SimpleStatistics(PointArray &points, SimpleStats &stats) const
Definition TgcFit.cxx:54
TgcFit(const std::string &type, const std::string &name, const IInterface *parent)
Definition TgcFit.cxx:20
void linReg(PointArray &points, LinStats &stats) const
Definition TgcFit.cxx:114
unsigned m_MIN_WIRE_POINTS
Test for outliers: w * (value - mean)^2 > CHI2_TEST.
Definition TgcFit.h:196
std::vector< Point > PointArray
Definition TgcFit.h:86
void printDebug(const std::string &str) const
Definition TgcFit.h:199
Status runTgcMiddle(PointArray &stripPoints, PointArray &wirePoints, TgcFitResult &fitResult) const
Definition TgcFit.cxx:200
Status runTgcInner(PointArray &stripPoints, PointArray &wirePoints, TgcFitResult &fitResult) const
Definition TgcFit.cxx:318
size_t countUniqueStations(const TrigL2MuonSA::TgcFit::PointArray &) const
Definition TgcFit.cxx:188
unsigned m_MIN_STRIP_POINTS
Minimum number of strip points for linear fit.
Definition TgcFit.h:197
void setFitParameters(double CHI2_TEST, unsigned MIN_WIRE_POINTS, unsigned MIN_STRIP_POINTS)
Definition TgcFit.cxx:30
void mean(std::vector< double > &bins, std::vector< double > &values, const std::vector< std::string > &files, const std::string &histname, const std::string &tplotname, const std::string &label="")
Amg::RotationMatrix3D setPhi(Amg::RotationMatrix3D mat, double angle, int convention=0)
Eigen::Matrix< double, 3, 1 > Vector3D
DataModel_detail::iterator< DVL > unique(typename DataModel_detail::iterator< DVL > beg, typename DataModel_detail::iterator< DVL > end)
Specialization of unique for DataVector/List.
void sort(typename DataModel_detail::iterator< DVL > beg, typename DataModel_detail::iterator< DVL > end)
Specialization of sort for DataVector/List.
double fIntercept
Intercept of the fit line.
Definition TgcFit.h:121
int n
Number of points.
Definition TgcFit.h:120
double fChi2
Total Chi2.
Definition TgcFit.h:125
double fSlope
Slope of the fit line.
Definition TgcFit.h:122
double eval(double fX) const
Definition TgcFit.cxx:42
A structure to hold simple statisitcs.
Definition TgcFit.h:92
int n
Number of valid points.
Definition TgcFit.h:93
double fStd
Standard deviation.
Definition TgcFit.h:95