ATLAS Offline Software
UTPCMMClusterBuilderTool.cxx
Go to the documentation of this file.
1 /*
2  Copyright (C) 2002-2023 CERN for the benefit of the ATLAS collaboration
3 */
4 
6 
7 #include <cmath>
8 #include <numeric>
9 
10 #include "GaudiKernel/SystemOfUnits.h"
11 
12 #define DEFINE_VECTOR(dType, varName, nEles) \
13  std::vector<dType> varName{}; \
14  varName.reserve(nEles);
15 
16 namespace {
17 
18  bool sortTracks(std::tuple<int, double>& a, std::tuple<int, double>& b) {
19  if (std::get<0>(a) != std::get<0>(b)) {
20  return std::get<0>(a) < std::get<0>(b);
21  }
22  return std::get<1>(a) < std::get<1>(b);
23  }
24 } // namespace
25 
26 namespace Muon{
27 
29 
30 UTPCMMClusterBuilderTool::UTPCMMClusterBuilderTool(const std::string& t, const std::string& n, const IInterface* p) :
31  AthAlgTool(t, n, p) {
32  declareInterface<IMMClusterBuilderTool>(this);
33 }
34 
36  ATH_CHECK(m_idHelperSvc.retrieve());
37  return StatusCode::SUCCESS;
38 }
39 
41  std::vector<MMPrepData>&& MMprds,
42  std::vector<std::unique_ptr<MMPrepData>>& clustersVect) const {
43 
44  LaySortedPrds MMprdsPerLayer{};
45  for (MMPrepData& MMprd : MMprds) {
46  Identifier id = MMprd.identify();
47  int layer = 4 * (m_idHelperSvc->mmIdHelper().multilayer(id) - 1) + (m_idHelperSvc->mmIdHelper().gasGap(id) - 1);
48  ATH_MSG_DEBUG("Sorting PRD into layer layer: " << layer << " gas_gap " << m_idHelperSvc->mmIdHelper().gasGap(id) << "multilayer "
49  << m_idHelperSvc->mmIdHelper().multilayer(id));
50  MMprdsPerLayer.at(layer).push_back(std::move(MMprd));
51  }
52 
53  // sort MMPrds by channel
54  for (std::vector<MMPrepData>& prdInLay : MMprdsPerLayer) {
55  std::sort(prdInLay.begin(), prdInLay.end(), [this](const MMPrepData& a, const MMPrepData& b) {
56  return m_idHelperSvc->mmIdHelper().channel(a.identify()) < m_idHelperSvc->mmIdHelper().channel(b.identify());
57  });
58  }
59 
60  for (std::vector<MMPrepData>& MMprdsOfLayer : MMprdsPerLayer) {
61  std::vector<double> stripsLocalPosX;
62  stripsLocalPosX.reserve(MMprdsOfLayer.size());
63 
64  for (MMPrepData& MMprd : MMprdsOfLayer) {
65  Identifier id_prd = MMprd.identify();
66  int gasGap = m_idHelperSvc->mmIdHelper().gasGap(id_prd);
67  stripsLocalPosX.push_back(
68  ((gasGap % 2 == 0 && m_digiHasNegativeAngles) ? -1 : 1) *
69  MMprd.localPosition().x()); // flip local positions for even gas gaps to reduce hough space to positiv angles
70 
71  // determine angle to IP for debug reasons
72  double globalR = MMprd.globalPosition().perp();
73  double Tan = globalR / MMprd.globalPosition().z();
74  double angleToIp = std::atan(Tan) / Gaudi::Units::degree;
75 
76  ATH_MSG_DEBUG("Hit channel: " << m_idHelperSvc->toString(id_prd) << " time " << MMprd.time() << " drift dist "
77  << MMprd.driftDist() << " localPosX " <<Amg::toString(MMprd.localPosition())
78  << " angleToIp " << angleToIp);
79  }
80  if (MMprdsOfLayer.size() < 2) continue;
81 
82  // move hits to the origin of the coordinate system to exclude extrapolation error and to keep the size of the hough space small
83  double meanX = std::accumulate(stripsLocalPosX.begin(), stripsLocalPosX.end(), 0.0) / stripsLocalPosX.size();
84  ATH_MSG_DEBUG("Got mean element " << meanX);
85  std::for_each(stripsLocalPosX.begin(), stripsLocalPosX.end(), [meanX](double& d) { d -= meanX; });
86  ATH_MSG_VERBOSE(stripsLocalPosX);
87 
88  // vector of 0s, ones and twos to indicate if strip was already used (0=unused;1=used;2=rejected as cross talk)
89  std::vector<int> flag = std::vector<int>(MMprdsOfLayer.size(), 0);
90 
91  while (true) {
92  ATH_MSG_DEBUG("while true");
93  std::vector<int> idx_goodStrips;
94  StatusCode sc = runHoughTrafo(MMprdsOfLayer, stripsLocalPosX, flag, idx_goodStrips);
95 
96  ATH_MSG_DEBUG("Hough done");
97  // if(sc.isFailure()) break;
98  if (idx_goodStrips.size() < 3 || sc.isFailure()) {
99  // break; // should be already catched in runHough but for safety once more here
100  idx_goodStrips.clear();
101  for (size_t i_hit = 0; i_hit < MMprdsOfLayer.size(); i_hit++) {
102  if (flag.at(i_hit) == 0) idx_goodStrips.push_back(i_hit);
103  }
104  ATH_MSG_DEBUG("Hough Trafo failed, try to fit everything");
105  }
106 
107  // remove strips induced by crosstalk till no more strip was removed
108  int nStripsCutByCrosstalk = 0;
109  while (!applyCrossTalkCut(idx_goodStrips, MMprdsOfLayer, flag, nStripsCutByCrosstalk).isFailure()) {}
110  ATH_MSG_DEBUG("After cutting CT idx_goddStrips " << idx_goodStrips << " flag " << flag);
111 
112  std::vector<Identifier> stripsOfCluster;
113  std::vector<uint16_t> stripsOfClusterChannels;
114  std::vector<short int> stripsOfClusterTimes;
115  std::vector<int> stripsOfClusterCharges;
116  std::vector<float> stripsOfClusterDriftDists;
117  std::vector<AmgVector(2)> stripsOfClusterDriftDistErrors;
118  std::vector<float> stripsOfClusterLocalPos; // needed for the final fit function
119  stripsOfCluster.reserve(idx_goodStrips.size());
120  if (m_writeStripProperties) { stripsOfClusterChannels.reserve(idx_goodStrips.size()); }
121  stripsOfClusterTimes.reserve(idx_goodStrips.size());
122  stripsOfClusterCharges.reserve(idx_goodStrips.size());
123  stripsOfClusterDriftDists.reserve(idx_goodStrips.size());
124  stripsOfClusterDriftDistErrors.reserve(idx_goodStrips.size());
125  stripsOfClusterLocalPos.reserve(idx_goodStrips.size());
126 
127  ATH_MSG_DEBUG("Found good Strips: " << idx_goodStrips.size());
128 
129  for (int idx : idx_goodStrips) {
130  ATH_MSG_DEBUG("Setting good strip: " << idx << " size of strips flag: " << flag.size());
131  flag.at(idx) = 1;
132  ATH_MSG_DEBUG("Set Good strips");
133  stripsOfCluster.push_back(MMprdsOfLayer.at(idx).identify());
135  stripsOfClusterChannels.push_back(m_idHelperSvc->mmIdHelper().channel(MMprdsOfLayer.at(idx).identify()));
136  stripsOfClusterTimes.push_back(MMprdsOfLayer.at(idx).time());
137  stripsOfClusterCharges.push_back(MMprdsOfLayer.at(idx).charge());
138  }
139  stripsOfClusterDriftDists.push_back(MMprdsOfLayer.at(idx).driftDist());
140  const Amg::MatrixX cov{MMprdsOfLayer.at(idx).localCovariance()};
141  stripsOfClusterDriftDistErrors.emplace_back(cov(0,0), cov(1,1));
142  stripsOfClusterLocalPos.push_back(MMprdsOfLayer.at(idx).localPosition().x());
143  }
144 
145  double localClusterPosition = -9999;
146  double sigmaLocalClusterPosition = 0;
147  double finalFitAngle, finalFitChiSqProb;
148 
149  sc = finalFit(stripsOfCluster, stripsOfClusterLocalPos, stripsOfClusterDriftDists, stripsOfClusterDriftDistErrors,
150  localClusterPosition, sigmaLocalClusterPosition, finalFitAngle, finalFitChiSqProb);
151 
152  ATH_MSG_DEBUG("final fit done");
153 
154  if (sc.isFailure()) break;
155  ATH_MSG_DEBUG("Did final fit successfull");
156 
157  auto covN = Amg::MatrixX(1, 1);
158  covN.coeffRef(0, 0) = sigmaLocalClusterPosition;
159  ATH_MSG_DEBUG("Did set covN Matrix");
160  int idx = idx_goodStrips[0];
161  ATH_MSG_DEBUG("idx_goodStrips[0]: " << idx << " size: " << MMprdsOfLayer.size());
162  Amg::Vector2D localClusterPositionV(localClusterPosition,
163  MMprdsOfLayer.at(idx).localPosition().y()); // y position is the same for all strips
164  ATH_MSG_DEBUG("Did set local position");
165 
166  float driftDist = 0.0;
167 
168  std::unique_ptr<MMPrepData> prdN = std::make_unique<MMPrepData>(MMprdsOfLayer.at(idx).identify(),
169  MMprdsOfLayer.at(idx).collectionHash(),
170  std::move(localClusterPositionV),
171  std::move(stripsOfCluster),
172  std::move(covN),
173  MMprdsOfLayer.at(idx).detectorElement(),
174  0,
175  std::accumulate(stripsOfClusterCharges.begin(), stripsOfClusterCharges.end(), 0),
176  driftDist,
177  std::move(stripsOfClusterChannels),
178  std::move(stripsOfClusterTimes),
179  std::move(stripsOfClusterCharges));
180 
181  ATH_MSG_DEBUG("Did create new prd");
182 
183  ATH_MSG_DEBUG("Setting prd angle: " << finalFitAngle << " chi2 Prob: " << finalFitChiSqProb);
184 
186  prdN->setDriftDist(std::move(stripsOfClusterDriftDists), std::move(stripsOfClusterDriftDistErrors));
187 
188  prdN->setMicroTPC(finalFitAngle, finalFitChiSqProb);
189  ATH_MSG_DEBUG("Reading back prd angle: " << prdN->angle() << " chi2 Prob: " << prdN->chisqProb());
190  clustersVect.push_back(std::move(prdN));
191  ATH_MSG_DEBUG("pushedBack prdN");
192  int leftOverStrips = 0;
193  for (auto f : flag) {
194  if (f == 0) leftOverStrips++;
195  }
196  if (leftOverStrips < 3) break;
197  }
198  ATH_MSG_DEBUG("End of get clusters layer");
199  }
200  ATH_MSG_DEBUG("End of get clusters");
201  return StatusCode::SUCCESS;
202 }
203 
204 StatusCode UTPCMMClusterBuilderTool::runHoughTrafo(const std::vector<MMPrepData>& mmPrd, std::vector<double>& xpos,
205  std::vector<int>& flag, std::vector<int>& idx_selected) const {
206  ATH_MSG_DEBUG("beginning of runHoughTrafo() with: " << xpos.size() << " hits");
207  double maxX = *std::max_element(xpos.begin(), xpos.end());
208  double minX = *std::min_element(xpos.begin(), xpos.end());
209  std::unique_ptr<TH2D> h_hough = nullptr;
210  StatusCode sc = houghInitCummulator(h_hough, maxX, minX);
211 
212  if (sc.isFailure()) return sc;
213  sc = fillHoughTrafo(mmPrd, xpos, flag, h_hough);
214  ATH_MSG_DEBUG("filled Hough");
215  if (sc.isFailure()) return sc;
216 
217  std::vector<std::tuple<double, double>> houghPeaks;
218  sc = findAlphaMax(h_hough, houghPeaks);
219  if (sc.isFailure()) return sc;
220  ATH_MSG_DEBUG("Found HoughPeaks");
221  sc = selectTrack(mmPrd, xpos, flag, houghPeaks, idx_selected);
222  if (sc.isFailure()) return sc;
223  return StatusCode::SUCCESS;
224 }
225 StatusCode UTPCMMClusterBuilderTool::houghInitCummulator(std::unique_ptr<TH2D>& h_hough, double xmax, double xmin) const {
226  ATH_MSG_VERBOSE("xmax: " << xmax << " xmin: " << xmin << " m_dResolution " << m_dResolution << " m_alphaMin " << m_alphaMin
227  << " m_alphaMax: " << m_alphaMax << " m_alphaResolution: " << m_alphaResolution);
228  double dmax = std::max(std::fabs(xmin), std::fabs(xmax));
229  dmax = std::sqrt(std::pow(dmax, 2) +
230  std::pow(m_driftRange, 2)); // rspace =sqrt(xmax*xmax+driftrange*driftrange) where driftrange is assumed to be 6mm
231  int nbinsd = static_cast<int>(1.0 * dmax * 2 / m_dResolution);
232  int nbinsa = static_cast<int>((1.0 * m_alphaMax - m_alphaMin) / m_alphaResolution);
233 
234  ATH_MSG_VERBOSE("Hough Using nBinsA " << nbinsa << " nBinsd " << nbinsd << " dmax " << dmax);
235 
236  h_hough = std::make_unique<TH2D>("h_hough", "h_hough", nbinsa, m_alphaMin * Gaudi::Units::degree, m_alphaMax * Gaudi::Units::degree,
237  nbinsd, -dmax, dmax);
238 
239  return StatusCode::SUCCESS;
240 }
241 
242 StatusCode UTPCMMClusterBuilderTool::fillHoughTrafo(const std::vector<MMPrepData>& mmPrd, std::vector<double>& xpos,
243  std::vector<int>& flag, std::unique_ptr<TH2D>& h_hough) const {
244  for (size_t i_hit = 0; i_hit < mmPrd.size(); i_hit++) {
245  if (flag.at(i_hit) != 0) continue; // skip hits which have been already used or been rejected as cross talk
246  for (int i_alpha = 1; i_alpha < h_hough->GetNbinsX(); i_alpha++) {
247  double alpha = h_hough->GetXaxis()->GetBinCenter(i_alpha);
248  double d = xpos.at(i_hit) * std::cos(alpha) - mmPrd.at(i_hit).driftDist() * std::sin(alpha);
249  ATH_MSG_VERBOSE("Fill Hough alpha: " << alpha << " d " << d << " x " << xpos.at(i_hit) << " y " << mmPrd.at(i_hit).driftDist());
250  h_hough->Fill(alpha, d);
251  }
252  }
253  return StatusCode::SUCCESS;
254 }
255 
256 StatusCode UTPCMMClusterBuilderTool::findAlphaMax(std::unique_ptr<TH2D>& h_hough,
257  std::vector<std::tuple<double, double>>& maxPos) const {
258  unsigned int cmax = h_hough->GetMaximum();
259  if (cmax < m_houghMinCounts) {
260  ATH_MSG_DEBUG("cmax " << cmax << "smaller then m_houghMinCounts " << m_houghMinCounts);
261  return StatusCode::FAILURE;
262  }
263 
264  for (int i_binX = 0; i_binX <= h_hough->GetNbinsX(); i_binX++) {
265  for (int i_binY = 0; i_binY <= h_hough->GetNbinsY(); i_binY++) {
266  if (h_hough->GetBinContent(i_binX, i_binY) == cmax) {
267  ATH_MSG_DEBUG("Find Max Alpha: BinX "
268  << i_binX << " Alpha: " << h_hough->GetXaxis()->GetBinCenter(i_binX) / Gaudi::Units::degree
269  << " BinY: " << i_binY << " over threshold: " << h_hough->GetBinContent(i_binX, i_binY));
270  maxPos.emplace_back(h_hough->GetXaxis()->GetBinCenter(i_binX), h_hough->GetYaxis()->GetBinCenter(i_binY));
271  }
272  }
273  }
274  return StatusCode::SUCCESS;
275 }
276 
277 StatusCode UTPCMMClusterBuilderTool::selectTrack(const std::vector<MMPrepData>& mmPrd, std::vector<double>& xpos,
278  std::vector<int>& flag, std::vector<std::tuple<double, double>>& tracks,
279  std::vector<int>& idxGoodStrips) const {
280  std::vector<double> chi2;
281  std::vector<std::vector<int>> allGoodStrips;
282  std::vector<int> ngoodStrips;
283  std::vector<std::tuple<int, double>> trackQuality; // touble holding the number of good strips and the chi2 for each track
284  for (auto track : tracks) {
285  double houghAngle = std::get<0>(track);
286  double houghD = std::get<1>(track);
287  double slope, intercept;
288  double interceptRMS;
289  double aRMS = 0;
290  StatusCode sc = transformParameters(houghAngle, houghD, aRMS, slope, intercept, interceptRMS);
291  if (sc.isFailure()) { return sc; }
292  std::vector<double> dist;
293  std::vector<int> indexUsedForDist, goodStrips;
294  for (size_t i_hit = 0; i_hit < xpos.size(); i_hit++) {
295  if (flag.at(i_hit) != 1) {
296  dist.push_back(mmPrd.at(i_hit).driftDist() - slope * xpos.at(i_hit) - intercept);
297  indexUsedForDist.push_back(i_hit);
298  }
299  }
300  ATH_MSG_VERBOSE("indexUsedForDist " << indexUsedForDist);
301  ATH_MSG_VERBOSE("distVec: " << dist);
302  dist.clear();
303  for (size_t i_hit : indexUsedForDist) {
304  double d = mmPrd.at(i_hit).driftDist() - slope * xpos.at(i_hit) - intercept;
305  ATH_MSG_VERBOSE("dist: " << d << " for index " << i_hit);
306  if (std::fabs(d) < m_selectionCut) {
307  dist.push_back(d * d / mmPrd.at(i_hit).localCovariance()(1, 1)); // determine chi2
308  goodStrips.push_back(i_hit);
309  }
310  }
311  {
312  ATH_MSG_DEBUG("Angle estimate =" << std::get<0>(track) << " " << std::get<0>(track) / Gaudi::Units::degree);
313 
314  ATH_MSG_DEBUG("restimate =" << std::get<1>(track));
315 
316  ATH_MSG_DEBUG("slope estimate =" << slope);
317 
318  ATH_MSG_DEBUG("intercept estimate =" << intercept);
319 
320  ATH_MSG_DEBUG("good strips =" << goodStrips);
321 
322  ATH_MSG_DEBUG("n good points =" << goodStrips.size());
323 
324  ATH_MSG_DEBUG("chi2 =" << std::accumulate(dist.begin(), dist.end(), 0.0) / (dist.size() - 2));
325  }
326  if (!goodStrips.empty()) {
327  allGoodStrips.push_back(goodStrips);
328  chi2.push_back(std::accumulate(dist.begin(), dist.end(), 0.0) / (dist.size() - 2));
329  trackQuality.emplace_back(goodStrips.size(), std::accumulate(dist.begin(), dist.end(), 0.0) / (dist.size() - 2));
330  }
331  }
332  if (chi2.empty()) return StatusCode::FAILURE;
333  int trackIndex = std::min_element(trackQuality.begin(), trackQuality.end(), sortTracks) - trackQuality.begin();
334  idxGoodStrips = allGoodStrips.at(trackIndex);
335  return StatusCode::SUCCESS;
336 }
337 
338 StatusCode UTPCMMClusterBuilderTool::transformParameters(double alpha, double d, double dRMS, double& slope, double& intercept,
339  double& interceptRMS) const {
340  slope = 1. / std::tan(alpha);
341  intercept = -d / std::sin(alpha);
342  interceptRMS = std::fabs(dRMS);
343  ATH_MSG_VERBOSE("transformParameters alpha: " << alpha << " d: " << d << " dRMS: " << dRMS << " slope: " << slope
344  << " intercept: " << intercept);
345  return StatusCode::SUCCESS;
346 }
347 
348 StatusCode UTPCMMClusterBuilderTool::applyCrossTalkCut(std::vector<int>& idxSelected, const std::vector<MMPrepData>& MMPrdsOfLayer,
349  std::vector<int>& flag, int& nStripsCut) const {
350  int N = idxSelected.size();
351  bool removedStrip = false;
352  ATH_MSG_DEBUG("starting to remove cross talk strips " << idxSelected << " flag " << flag);
353  if (N < 3 || nStripsCut >= m_maxStripsCut) {
354  ATH_MSG_DEBUG("first cut failed");
355  return StatusCode::FAILURE;
356  }
357  // reject outer strip for fit if charge ratio to second outer strip indicates strip charge is created by crosstalk only
358  double ratioLastStrip = 1.0 * MMPrdsOfLayer.at(idxSelected.at(N - 1)).charge() / MMPrdsOfLayer.at(idxSelected.at(N - 2)).charge();
359  double ratioFirstStrip = 1.0 * MMPrdsOfLayer.at(idxSelected.at(0)).charge() / MMPrdsOfLayer.at(idxSelected.at(1)).charge();
360  ATH_MSG_DEBUG("ratioLastStrip " << ratioLastStrip << " ratioFirstStrip " << ratioFirstStrip);
361  if (ratioLastStrip < m_outerChargeRatioCut) {
362  flag.at(idxSelected.at(N - 1)) = 2;
363  idxSelected.erase(idxSelected.begin() + (N - 1));
364  removedStrip = true;
365  nStripsCut++;
366  ATH_MSG_DEBUG("cutting last strip nStripCuts: " << nStripsCut << " flag " << flag << " idxSelected " << idxSelected);
367  }
368  if (idxSelected.size() < 3 || nStripsCut >= m_maxStripsCut) {
369  ATH_MSG_DEBUG("first cut failed");
370  return StatusCode::FAILURE;
371  }
372 
373  if (ratioFirstStrip < m_outerChargeRatioCut) {
374  flag.at(idxSelected.at(0)) = 2;
375  idxSelected.erase(idxSelected.begin() + 0);
376  removedStrip = true;
377  nStripsCut++;
378  ATH_MSG_DEBUG("cutting first strip nStripCuts: " << nStripsCut << " flag " << flag << " idxSelected " << idxSelected);
379  }
380  if (nStripsCut >= m_maxStripsCut) {
381  ATH_MSG_DEBUG("first cut failed");
382  return StatusCode::FAILURE;
383  }
384  ATH_MSG_DEBUG("return value " << (!removedStrip ? "FAILURE" : "SUCCESS"));
385  return (!removedStrip ? StatusCode::FAILURE : StatusCode::SUCCESS); // return success if at least one strip was removed
386 }
387 
388 StatusCode UTPCMMClusterBuilderTool::finalFit(const std::vector<Identifier>& ids, const std::vector<float>& stripsPos,
389  const std::vector<float>& driftDists, const std::vector<AmgVector(2)>& driftDistErrors,
390  double& x0, double& sigmaX0, double& fitAngle, double& chiSqProb) const {
391  std::unique_ptr<TGraphErrors> fitGraph = std::make_unique<TGraphErrors>();
392  std::unique_ptr<TF1> ffit = std::make_unique<TF1>("ffit", "pol1");
393 
394  double xmin = 5000;
395  double xmax = -5000;
396  double xmean = std::accumulate(stripsPos.begin(), stripsPos.end(), 0.0) / stripsPos.size(); // get mean x value
397 
398  std::unique_ptr<TLinearFitter> lf = std::make_unique<TLinearFitter>(1, "1++x");
399 
400  for (size_t idx = 0; idx < stripsPos.size(); idx++) {
401  double xpos = stripsPos.at(idx) - xmean; // substract mean value from x to center fit around 0
402  if (xmin > xpos)
403  xmin = xpos;
404  else if (xmax < xpos)
405  xmax = xpos;
406  lf->AddPoint(&xpos, driftDists.at(idx));
407  fitGraph->SetPoint(fitGraph->GetN(), xpos, driftDists.at(idx));
408  fitGraph->SetPointError(fitGraph->GetN() - 1, std::sqrt(driftDistErrors.at(idx)[0]), std::sqrt(driftDistErrors.at(idx)[1]));
409  }
410  lf->Eval();
411 
412  if (m_idHelperSvc->mmIdHelper().gasGap(ids.at(0)) % 2 == 1 || !m_digiHasNegativeAngles) {
413  ffit->SetParLimits(1, -11.5, -0.15); // 5 to 81 degree
414  } else {
415  ffit->SetParLimits(1, 0.15, 11.5); // 5 to 81 degree
416  }
417  ffit->SetParameters(lf->GetParameter(0), lf->GetParameter(1));
418  TFitResultPtr s = fitGraph->Fit("ffit", "SMQ", "", xmin - .5, xmax + .5);
419 
420  double cov = (s->GetCovarianceMatrix())(0, 1);
421  ATH_MSG_DEBUG("covariance is: " << cov);
422  double fitSlope = ffit->GetParameter(1);
423  double dHalfGap = 2.52; // half the thickness of the gas gap
424  double interceptCorr = dHalfGap - ffit->GetParameter(0);
425  x0 = interceptCorr / fitSlope;
426  sigmaX0 =
427  (std::pow(ffit->GetParError(0) / interceptCorr, 2) + std::pow(ffit->GetParError(1) / fitSlope, 2) - 2. / (fitSlope * interceptCorr) * cov) *
428  std::pow(x0, 2);
429  x0 += xmean; // adding back mean value after error was calculated
430  fitAngle = std::tan(-1 / fitSlope);
431  chiSqProb = ffit->GetProb();
432 
433  {
434  ATH_MSG_DEBUG("==========uTPC fit Summary==============");
435 
436  ATH_MSG_DEBUG("Fit slope: " << ffit->GetParameter(1));
437 
438  ATH_MSG_DEBUG("Fit intercept:" << ffit->GetParameter(0));
439 
440  ATH_MSG_DEBUG("Fit status: " << s);
441 
442  ATH_MSG_DEBUG("Cluster position " << x0 << " +- " << sigmaX0);
443 
444  ATH_MSG_DEBUG("Fit angle: " << fitAngle << " " << fitAngle * 180. / M_PI);
445 
446  ATH_MSG_DEBUG("ChisSqProb" << chiSqProb);
447  ATH_MSG_DEBUG("nStrips:" << stripsPos.size());
448  ATH_MSG_DEBUG("gas gap:" << m_idHelperSvc->mmIdHelper().gasGap(ids.at(0)));
449  }
450  if (s != 0 && s != 4000) { // 4000 means fit succesfull but error optimization by minos failed; fit is still usable.
451  ATH_MSG_DEBUG("Final fit failed with error code " << s);
452  return StatusCode::FAILURE;
453  }
454  if ((m_idHelperSvc->mmIdHelper().gasGap(ids.at(0)) % 2 == 1 || !m_digiHasNegativeAngles) &&
455  (ffit->GetParameter(1) <= -11.49 || ffit->GetParameter(1) >= -0.151))
456  return StatusCode::FAILURE; // fit should have negativ slope for odd gas gaps
457  if (m_idHelperSvc->mmIdHelper().gasGap(ids.at(0)) % 2 == 0 && m_digiHasNegativeAngles &&
458  (ffit->GetParameter(1) >= 11.49 || ffit->GetParameter(1) <= 0.151))
459  return StatusCode::FAILURE; // fit should have positiv slope for even gas gaps
460  return StatusCode::SUCCESS;
461 }
462 
464  const std::vector<NSWCalib::CalibratedStrip>& calibratedStrips,
465  const Amg::Vector3D& /*directionEstimate*/,
466  Amg::Vector2D& clusterLocalPosition,
467  Amg::MatrixX& covMatrix) const {
468 
469  std::vector<Identifier> ids;
470  std::vector<float> stripsPos;
471  std::vector<float> driftDists;
472  std::vector<AmgVector(2)> driftDistErrors;
473 
474  for (const NSWCalib::CalibratedStrip& strip : calibratedStrips) {
475  ids.push_back(strip.identifier);
476  stripsPos.push_back(strip.locPos.x());
477  driftDists.push_back(strip.distDrift);
478  driftDistErrors.emplace_back(strip.resTransDistDrift, strip.resLongDistDrift);
479  }
480 
481  double localClusterPosition = -9999;
482  double sigmaLocalClusterPosition = 0;
483  double finalFitAngle, finalFitChiSqProb;
484 
485  StatusCode sc = finalFit(ids, stripsPos, driftDists, driftDistErrors, localClusterPosition, sigmaLocalClusterPosition, finalFitAngle,
486  finalFitChiSqProb);
487  if (sc == StatusCode::FAILURE) return RIO_Author::unKnownAuthor;
488 
489  clusterLocalPosition[Trk::locX] = localClusterPosition;
490 
491  Amg::MatrixX covN(1, 1);
492  covN.coeffRef(0, 0) = sigmaLocalClusterPosition;
493  covMatrix = covN;
494  return RIO_Author::uTPCClusterBuilder;
495 }
496 }
Muon::UTPCMMClusterBuilderTool::m_alphaMax
Gaudi::Property< double > m_alphaMax
Definition: UTPCMMClusterBuilderTool.h:57
Muon::UTPCMMClusterBuilderTool::m_writeStripProperties
Gaudi::Property< bool > m_writeStripProperties
Definition: UTPCMMClusterBuilderTool.h:53
Muon::UTPCMMClusterBuilderTool::m_dResolution
Gaudi::Property< double > m_dResolution
Definition: UTPCMMClusterBuilderTool.h:62
Muon::UTPCMMClusterBuilderTool::applyCrossTalkCut
StatusCode applyCrossTalkCut(std::vector< int > &idxSelected, const std::vector< MMPrepData > &MMPrdsOfLayer, std::vector< int > &flag, int &nStripsCut) const
Definition: UTPCMMClusterBuilderTool.cxx:348
dumpTgcDigiDeadChambers.gasGap
list gasGap
Definition: dumpTgcDigiDeadChambers.py:33
Muon::MMPrepData
Class to represent MM measurements.
Definition: MMPrepData.h:22
python.SystemOfUnits.s
int s
Definition: SystemOfUnits.py:131
Amg::MatrixX
Eigen::Matrix< double, Eigen::Dynamic, Eigen::Dynamic > MatrixX
Dynamic Matrix - dynamic allocation.
Definition: EventPrimitives.h:27
Muon::UTPCMMClusterBuilderTool::m_driftRange
Gaudi::Property< double > m_driftRange
Definition: UTPCMMClusterBuilderTool.h:63
max
#define max(a, b)
Definition: cfImp.cxx:41
Muon::UTPCMMClusterBuilderTool::finalFit
StatusCode finalFit(const std::vector< Identifier > &ids, const std::vector< float > &stripsPos, const std::vector< float > &driftDists, const std::vector< AmgVector(2)> &driftDistErrors, double &x0, double &sigmaX0, double &fitAngle, double &chiSqProb) const
Definition: UTPCMMClusterBuilderTool.cxx:388
Trk::locX
@ locX
Definition: ParamDefs.h:37
Muon::UTPCMMClusterBuilderTool::m_idHelperSvc
ServiceHandle< Muon::IMuonIdHelperSvc > m_idHelperSvc
Muon Detector Descriptor.
Definition: UTPCMMClusterBuilderTool.h:51
Amg::Vector2D
Eigen::Matrix< double, 2, 1 > Vector2D
Definition: GeoPrimitives.h:48
hist_file_dump.d
d
Definition: hist_file_dump.py:137
accumulate
bool accumulate(AccumulateMap &map, std::vector< module_t > const &modules, FPGATrackSimMatrixAccumulator const &acc)
Accumulates an accumulator (e.g.
Definition: FPGATrackSimMatrixAccumulator.cxx:22
conifer::pow
constexpr int pow(int x)
Definition: conifer.h:20
plotBeamSpotVxVal.cov
cov
Definition: plotBeamSpotVxVal.py:201
Muon::RIO_Author
IMMClusterBuilderTool::RIO_Author RIO_Author
Definition: ClusterTimeProjectionMMClusterBuilderTool.cxx:21
M_PI
#define M_PI
Definition: ActiveFraction.h:11
Muon::UTPCMMClusterBuilderTool::LaySortedPrds
std::array< std::vector< Muon::MMPrepData >, 8 > LaySortedPrds
Definition: UTPCMMClusterBuilderTool.h:49
JetTiledMap::N
@ N
Definition: TiledEtaPhiMap.h:44
Muon::MMPrepData::Author::uTPCClusterBuilder
@ uTPCClusterBuilder
python.TriggerAPI.TriggerAPISession.lf
lf
Definition: TriggerAPISession.py:390
read_hist_ntuple.t
t
Definition: read_hist_ntuple.py:5
drawFromPickle.cos
cos
Definition: drawFromPickle.py:36
ATH_MSG_VERBOSE
#define ATH_MSG_VERBOSE(x)
Definition: AthMsgStreamMacros.h:28
Muon
This class provides conversion from CSC RDO data to CSC Digits.
Definition: TrackSystemController.h:45
Muon::UTPCMMClusterBuilderTool::m_houghMinCounts
Gaudi::Property< unsigned > m_houghMinCounts
Definition: UTPCMMClusterBuilderTool.h:64
Muon::UTPCMMClusterBuilderTool::transformParameters
StatusCode transformParameters(double alpha, double d, double dRMS, double &slope, double &intercept, double &interceptRMS) const
Definition: UTPCMMClusterBuilderTool.cxx:338
drawFromPickle.atan
atan
Definition: drawFromPickle.py:36
Muon::IMMClusterBuilderTool::RIO_Author
MMClusterOnTrack::Author RIO_Author
Refinement of the cluster position after the cluster calibration loop is ran with a complete external...
Definition: IMMClusterBuilderTool.h:48
AthenaPoolTestRead.sc
sc
Definition: AthenaPoolTestRead.py:27
Muon::UTPCMMClusterBuilderTool::selectTrack
StatusCode selectTrack(const std::vector< Muon::MMPrepData > &mmPrd, std::vector< double > &xpos, std::vector< int > &flag, std::vector< std::tuple< double, double >> &tracks, std::vector< int > &idxGoodStrips) const
Definition: UTPCMMClusterBuilderTool.cxx:277
python.utils.AtlRunQueryDQUtils.p
p
Definition: AtlRunQueryDQUtils.py:210
Amg::toString
std::string toString(const Translation3D &translation, int precision=4)
GeoPrimitvesToStringConverter.
Definition: GeoPrimitivesToStringConverter.h:40
Muon::UTPCMMClusterBuilderTool::m_alphaMin
Gaudi::Property< double > m_alphaMin
Definition: UTPCMMClusterBuilderTool.h:56
Muon::UTPCMMClusterBuilderTool::m_selectionCut
Gaudi::Property< double > m_selectionCut
Definition: UTPCMMClusterBuilderTool.h:59
xmin
double xmin
Definition: listroot.cxx:60
beamspotman.n
n
Definition: beamspotman.py:731
EL::StatusCode
::StatusCode StatusCode
StatusCode definition for legacy code.
Definition: PhysicsAnalysis/D3PDTools/EventLoop/EventLoop/StatusCode.h:22
ATH_MSG_DEBUG
#define ATH_MSG_DEBUG(x)
Definition: AthMsgStreamMacros.h:29
xAOD::covMatrix
covMatrix
Definition: TrackMeasurement_v1.cxx:19
AmgVector
AmgVector(4) T2BSTrackFilterTool
Definition: T2BSTrackFilterTool.cxx:114
TRT::Hit::layer
@ layer
Definition: HitInfo.h:79
master.flag
bool flag
Definition: master.py:29
Muon::UTPCMMClusterBuilderTool::getClusters
virtual StatusCode getClusters(const EventContext &ctx, std::vector< Muon::MMPrepData > &&stripsVect, std::vector< std::unique_ptr< Muon::MMPrepData >> &clustersVect) const override
Standard Interface to produce Micromega clusters from raw Input hits without external contstaint.
Definition: UTPCMMClusterBuilderTool.cxx:40
Muon::UTPCMMClusterBuilderTool::UTPCMMClusterBuilderTool
UTPCMMClusterBuilderTool(const std::string &, const std::string &, const IInterface *)
Default constructor.
Definition: UTPCMMClusterBuilderTool.cxx:30
chi2
double chi2(TH1 *h0, TH1 *h1)
Definition: comparitor.cxx:522
ATH_CHECK
#define ATH_CHECK
Definition: AthCheckMacros.h:40
hist_file_dump.f
f
Definition: hist_file_dump.py:135
drawFromPickle.tan
tan
Definition: drawFromPickle.py:36
NSWCalib::CalibratedStrip
Definition: INSWCalibTool.h:20
TRT::Hit::globalR
@ globalR
Definition: HitInfo.h:37
Muon::UTPCMMClusterBuilderTool::findAlphaMax
StatusCode findAlphaMax(std::unique_ptr< TH2D > &h_hough, std::vector< std::tuple< double, double >> &maxPos) const
Definition: UTPCMMClusterBuilderTool.cxx:256
Muon::UTPCMMClusterBuilderTool::m_alphaResolution
Gaudi::Property< double > m_alphaResolution
Definition: UTPCMMClusterBuilderTool.h:58
python.subdetectors.mmg.ids
ids
Definition: mmg.py:8
plotBeamSpotMon.b
b
Definition: plotBeamSpotMon.py:77
Muon::UTPCMMClusterBuilderTool::m_outerChargeRatioCut
Gaudi::Property< double > m_outerChargeRatioCut
charge ratio cut to supress cross talk
Definition: UTPCMMClusterBuilderTool.h:67
Amg::Vector3D
Eigen::Matrix< double, 3, 1 > Vector3D
Definition: GeoPrimitives.h:47
UTPCMMClusterBuilderTool.h
a
TList * a
Definition: liststreamerinfos.cxx:10
Muon::UTPCMMClusterBuilderTool::fillHoughTrafo
StatusCode fillHoughTrafo(const std::vector< Muon::MMPrepData > &mmPrd, std::vector< double > &xpos, std::vector< int > &flag, std::unique_ptr< TH2D > &h_hough) const
Definition: UTPCMMClusterBuilderTool.cxx:242
xmax
double xmax
Definition: listroot.cxx:61
LArNewCalib_DelayDump_OFC_Cali.idx
idx
Definition: LArNewCalib_DelayDump_OFC_Cali.py:69
xAOD::track
@ track
Definition: TrackingPrimitives.h:512
drawFromPickle.sin
sin
Definition: drawFromPickle.py:36
Muon::UTPCMMClusterBuilderTool::m_maxStripsCut
Gaudi::Property< int > m_maxStripsCut
Definition: UTPCMMClusterBuilderTool.h:69
AthAlgTool
Definition: AthAlgTool.h:26
Muon::UTPCMMClusterBuilderTool::houghInitCummulator
StatusCode houghInitCummulator(std::unique_ptr< TH2D > &cummulator, double xmax, double xmin) const
Definition: UTPCMMClusterBuilderTool.cxx:225
Muon::UTPCMMClusterBuilderTool::getCalibratedClusterPosition
virtual RIO_Author getCalibratedClusterPosition(const EventContext &ctx, const std::vector< NSWCalib::CalibratedStrip > &calibratedStrips, const Amg::Vector3D &directionEstimate, Amg::Vector2D &clusterLocalPosition, Amg::MatrixX &covMatrix) const override
Definition: UTPCMMClusterBuilderTool.cxx:463
Muon::UTPCMMClusterBuilderTool::m_digiHasNegativeAngles
Gaudi::Property< bool > m_digiHasNegativeAngles
Definition: UTPCMMClusterBuilderTool.h:71
Muon::MMClusterOnTrack::Author
Author
Definition: MMClusterOnTrack.h:89
Muon::UTPCMMClusterBuilderTool::initialize
virtual StatusCode initialize() override
standard initialize method
Definition: UTPCMMClusterBuilderTool.cxx:35
python.SystemOfUnits.degree
tuple degree
Definition: SystemOfUnits.py:106
Muon::UTPCMMClusterBuilderTool::runHoughTrafo
StatusCode runHoughTrafo(const std::vector< Muon::MMPrepData > &mmPrd, std::vector< double > &xpos, std::vector< int > &flag, std::vector< int > &idx_selected) const
Definition: UTPCMMClusterBuilderTool.cxx:204
tauRecTools::sortTracks
bool sortTracks(const ElementLink< xAOD::TauTrackContainer > &l1, const ElementLink< xAOD::TauTrackContainer > &l2)
Definition: Reconstruction/tauRecTools/Root/HelperFunctions.cxx:54
Identifier
Definition: IdentifierFieldParser.cxx:14