ATLAS Offline Software
Loading...
Searching...
No Matches
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
16namespace {
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
26namespace Muon{
27
29
30UTPCMMClusterBuilderTool::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
40StatusCode UTPCMMClusterBuilderTool::getClusters(const EventContext& /*ctx*/,
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
204StatusCode 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}
225StatusCode 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
242StatusCode 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
256StatusCode 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
277StatusCode 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
338StatusCode 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
348StatusCode 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
388StatusCode 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}
#define M_PI
#define ATH_CHECK
Evaluate an expression and check for errors.
#define ATH_MSG_VERBOSE(x)
#define ATH_MSG_DEBUG(x)
#define AmgVector(rows)
static Double_t a
static Double_t sc
AthAlgTool(const std::string &type, const std::string &name, const IInterface *parent)
Constructor with parameters:
MMClusterOnTrack::Author RIO_Author
Refinement of the cluster position after the cluster calibration loop is ran with a complete external...
Class to represent MM measurements.
Definition MMPrepData.h:22
StatusCode findAlphaMax(std::unique_ptr< TH2D > &h_hough, std::vector< std::tuple< double, double > > &maxPos) const
Gaudi::Property< double > m_alphaResolution
Gaudi::Property< double > m_driftRange
Gaudi::Property< bool > m_digiHasNegativeAngles
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
Gaudi::Property< double > m_outerChargeRatioCut
charge ratio cut to supress cross talk
virtual StatusCode initialize() override
standard initialize method
Gaudi::Property< double > m_selectionCut
UTPCMMClusterBuilderTool(const std::string &, const std::string &, const IInterface *)
Default constructor.
StatusCode transformParameters(double alpha, double d, double dRMS, double &slope, double &intercept, double &interceptRMS) const
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
StatusCode runHoughTrafo(const std::vector< Muon::MMPrepData > &mmPrd, std::vector< double > &xpos, std::vector< int > &flag, std::vector< int > &idx_selected) const
Gaudi::Property< unsigned > m_houghMinCounts
Gaudi::Property< bool > m_writeStripProperties
StatusCode applyCrossTalkCut(std::vector< int > &idxSelected, const std::vector< MMPrepData > &MMPrdsOfLayer, std::vector< int > &flag, int &nStripsCut) const
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.
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
Gaudi::Property< double > m_dResolution
StatusCode houghInitCummulator(std::unique_ptr< TH2D > &cummulator, double xmax, double xmin) const
StatusCode fillHoughTrafo(const std::vector< Muon::MMPrepData > &mmPrd, std::vector< double > &xpos, std::vector< int > &flag, std::unique_ptr< TH2D > &h_hough) const
ServiceHandle< Muon::IMuonIdHelperSvc > m_idHelperSvc
Muon Detector Descriptor.
std::array< std::vector< Muon::MMPrepData >, 8 > LaySortedPrds
double chi2(TH1 *h0, TH1 *h1)
double xmax
Definition listroot.cxx:61
double xmin
Definition listroot.cxx:60
std::string toString(const Translation3D &translation, int precision=4)
GeoPrimitvesToStringConverter.
Eigen::Matrix< double, Eigen::Dynamic, Eigen::Dynamic > MatrixX
Dynamic Matrix - dynamic allocation.
Eigen::Matrix< double, 2, 1 > Vector2D
Eigen::Matrix< double, 3, 1 > Vector3D
NRpcCablingAlg reads raw condition data and writes derived condition data to the condition store.
IMMClusterBuilderTool::RIO_Author RIO_Author
@ locX
Definition ParamDefs.h:37
void sort(typename DataModel_detail::iterator< DVL > beg, typename DataModel_detail::iterator< DVL > end)
Specialization of sort for DataVector/List.