ATLAS Offline Software
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):
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 
42 double TrigL2MuonSA::TgcFit::LinStats::eval(double fX) const
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");
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");
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 // --------------------------------------------------------------------------------
TrigL2MuonSA::TgcFit::TgcFit
TgcFit(const std::string &type, const std::string &name, const IInterface *parent)
Definition: TgcFit.cxx:20
TrigL2MuonSA::TgcFitResult::tgcMidPhiN
int tgcMidPhiN
Definition: TgcFitResult.h:52
TrigL2MuonSA::TgcFitResult::tgcMidRhoNin
int tgcMidRhoNin
Definition: TgcFitResult.h:48
mean
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="")
Definition: dependence.cxx:254
TrigL2MuonSA::TgcFit::SimpleStats::fMean
double fMean
Mean.
Definition: TgcFit.h:94
python.PerfMonSerializer.p
def p
Definition: PerfMonSerializer.py:743
TrigL2MuonSA::TgcFitResult::tgcMidPhiNin
int tgcMidPhiNin
Definition: TgcFitResult.h:51
phi
Scalar phi() const
phi method
Definition: AmgMatrixBasePlugin.h:64
TrigL2MuonSA::TgcFit::runTgcInner
Status runTgcInner(PointArray &stripPoints, PointArray &wirePoints, TgcFitResult &fitResult) const
Definition: TgcFit.cxx:318
AthMsgStreamMacros.h
TrigL2MuonSA::TgcFit::countUniqueStations
size_t countUniqueStations(const TrigL2MuonSA::TgcFit::PointArray &) const
Definition: TgcFit.cxx:188
TrigL2MuonSA::TgcFit::Status
Status
Definition: TgcFit.h:25
TrigL2MuonSA::TgcFitResult
Definition: TgcFitResult.h:11
TrigL2MuonSA::TgcFit::LinStats::fIntercept
double fIntercept
Intercept of the fit line.
Definition: TgcFit.h:121
M_PI
#define M_PI
Definition: ActiveFraction.h:11
TgcFit.h
TrigL2MuonSA::TgcFitResult::tgcMidRhoN
int tgcMidRhoN
Definition: TgcFitResult.h:49
TrigL2MuonSA::TgcFitResult::tgcInnRhoN
int tgcInnRhoN
Definition: TgcFitResult.h:58
TrigL2MuonSA::TgcFit::LinStats::fChi2
double fChi2
Total Chi2.
Definition: TgcFit.h:125
trigbs_dumpHLTContentInBS.stats
stats
Definition: trigbs_dumpHLTContentInBS.py:91
x
#define x
Amg::setPhi
Amg::RotationMatrix3D setPhi(Amg::RotationMatrix3D mat, double angle, int convention=0)
Definition: EulerAnglesHelpers.h:102
TrigL2MuonSA::TgcFit::SimpleStats::fStd
double fStd
Standard deviation.
Definition: TgcFit.h:95
TrigL2MuonSA::TgcFit::SimpleStats::n
int n
Number of valid points.
Definition: TgcFit.h:93
TrigL2MuonSA::TgcFit::Point
Definition: TgcFit.h:35
TrigL2MuonSA::TgcFitResult::tgcMid2
float tgcMid2[4]
Definition: TgcFitResult.h:46
ATH_MSG_DEBUG
#define ATH_MSG_DEBUG(x)
Definition: AthMsgStreamMacros.h:29
TrigL2MuonSA::TgcFitResult::intercept
float intercept
Definition: TgcFitResult.h:66
TrigL2MuonSA::TgcFit::LinStats
Definition: TgcFit.h:119
TrigL2MuonSA::TgcFitResult::tgcInnRhoNin
int tgcInnRhoNin
Definition: TgcFitResult.h:57
TrigL2MuonSA::TgcFit::LinStats::fSlope
double fSlope
Slope of the fit line.
Definition: TgcFit.h:122
test_pyathena.parent
parent
Definition: test_pyathena.py:15
TrigL2MuonSA::TgcFitResult::tgcMid1
float tgcMid1[4]
Definition: TgcFitResult.h:45
TrigL2MuonSA::TgcFitResult::tgcInnPhiN
int tgcInnPhiN
Definition: TgcFitResult.h:61
TrigL2MuonSA::TgcFitResult::tgcInnRhoStd
float tgcInnRhoStd
Definition: TgcFitResult.h:56
TrigL2MuonSA::TgcFitResult::slope
float slope
Definition: TgcFitResult.h:65
lumiFormat.array
array
Definition: lumiFormat.py:98
TrigL2MuonSA::TgcFitResult::tgcMidRhoChi2
float tgcMidRhoChi2
Definition: TgcFitResult.h:47
name
std::string name
Definition: Control/AthContainers/Root/debug.cxx:192
TrigL2MuonSA::TgcFit::linReg
void linReg(PointArray &points, LinStats &stats) const
Definition: TgcFit.cxx:114
TrigL2MuonSA::TgcFit::setFitParameters
void setFitParameters(double CHI2_TEST, unsigned MIN_WIRE_POINTS, unsigned MIN_STRIP_POINTS)
Definition: TgcFit.cxx:30
TrigL2MuonSA::TgcFitResult::tgcInn
float tgcInn[4]
Definition: TgcFitResult.h:55
Amg::Vector3D
Eigen::Matrix< double, 3, 1 > Vector3D
Definition: GeoPrimitives.h:47
TrigL2MuonSA::TgcFit::SimpleStatistics
void SimpleStatistics(PointArray &points, SimpleStats &stats) const
Definition: TgcFit.cxx:54
TrigL2MuonSA::TgcFit::LinStats::eval
double eval(double fX) const
Definition: TgcFit.cxx:42
Prompt::Def::Pt
@ Pt
Definition: VarHolder.h:76
y
#define y
python.CaloScaleNoiseConfig.type
type
Definition: CaloScaleNoiseConfig.py:78
TrigL2MuonSA::TgcFit::runTgcMiddle
Status runTgcMiddle(PointArray &stripPoints, PointArray &wirePoints, TgcFitResult &fitResult) const
Definition: TgcFit.cxx:200
TrigL2MuonSA::TgcFit::LinStats::n
int n
Number of points.
Definition: TgcFit.h:120
TrigL2MuonSA::TgcFit::PointArray
std::vector< Point > PointArray
Definition: TgcFit.h:86
merge.status
status
Definition: merge.py:17
ATLAS_THREAD_SAFE
#define ATLAS_THREAD_SAFE
Definition: checker_macros.h:211
TrigL2MuonSA::TgcFit::SimpleStats
A structure to hold simple statisitcs.
Definition: TgcFit.h:92
AthAlgTool
Definition: AthAlgTool.h:26
python.IoTestsLib.w
def w
Definition: IoTestsLib.py:200
TrigL2MuonSA::TgcFitResult::tgcInnPhiNin
int tgcInnPhiNin
Definition: TgcFitResult.h:60
TrigL2MuonSA::TgcFitResult::tgcMidPhiChi2
float tgcMidPhiChi2
Definition: TgcFitResult.h:50
checker_macros.h
Define macros for attributes used to control the static checker.
TrigL2MuonSA::TgcFitResult::tgcInnPhiStd
float tgcInnPhiStd
Definition: TgcFitResult.h:59