ATLAS Offline Software
Loading...
Searching...
No Matches
QuasianalyticLineReconstruction.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2026 CERN for the benefit of the ATLAS collaboration
3*/
4
6
7#include <TString.h> // for Form
8
10#include "CLHEP/GenericFunctions/CumulativeChiSquare.hh"
11#include "CLHEP/Units/PhysicalConstants.h"
12#include "CLHEP/Units/SystemOfUnits.h"
13#include "GaudiKernel/MsgStream.h"
14#include "time.h"
15#include <cmath>
16#include <fstream>
17#include <iostream>
18
19using namespace MuonCalib;
20
22 init(0.5 * CLHEP::mm); // default road width = 0.5 CLHEP::mm
23 return;
24}
25void QuasianalyticLineReconstruction::init(const double r_road_width) {
26 //::::::::::::::::::
27 //:: SET TIME-OUT ::
28 //::::::::::::::::::
29
30 m_time_out = 10.0;
31
32 //::::::::::::::::::::::::::::
33 //:: SET THE MAXIMUM RADIUS ::
34 //::::::::::::::::::::::::::::
35
36 m_r_max = 14.6;
37
38 //::::::::::::::::::::::::
39 //:: SET THE ROAD WIDTH ::
40 //::::::::::::::::::::::::
41
42 m_road_width = r_road_width;
43
44 return;
45}
46MTStraightLine QuasianalyticLineReconstruction::tangent(const Amg::Vector3D& r_w1, const double r_r1, const double r_sigma12,
47 const Amg::Vector3D& r_w2, const double r_r2, const double r_sigma22,
48 const int& r_case) const {
49 //:::::::::::::::
50 //:: VARIABLES ::
51 //:::::::::::::::
52
53 double sinalpha; // auxiliary sinus of an angle
54 double cosalpha; // auxiliary sinus of an angle
55 Amg::Vector3D e2prime(0., 0., 0.), e3prime(0., 0., 0.); // auxiliary direction vectors
56 MTStraightLine tang; // tangent to drift circles of a hit pair
57 Amg::Vector3D p1(0., 0., 0.), p2(0., 0., 0.); // hit points defining a tangent
58 Amg::Vector3D null_vec(0.0, 0.0, 0.0); // auxiliary 0 vector
59 double mx1=0, bx1=0, mx2=0, bx2=0; // auxiliary track parameters
60
61 //::::::::::::::::::::::::::::::::::::::::::::
62 //:: CHECK WHETHER THE SELECTED CASE EXISTS ::
63 //::::::::::::::::::::::::::::::::::::::::::::
64
65 if (r_case < 1 || r_case > 4) {
66 throw std::runtime_error(
67 Form("File: %s, Line: %d\nQuasianalyticLineReconstruction::tangent() - Illegal case %i, must be 1,2,3, or 4.", __FILE__,
68 __LINE__, r_case));
69 }
70
71 //:::::::::::::::::::::::::::::::::::::
72 //:: CALCULATE THE REQUESTED TANGENT ::
73 //:::::::::::::::::::::::::::::::::::::
74
75 // local coordinate axis vectors //
76 e3prime = (r_w2 - r_w1).unit();
77 e2prime = Amg::Vector3D(0.0, e3prime.z(), -e3prime.y());
78
79 // case 1 and 2 //
80 if (r_case == 1 || r_case == 2) {
81 sinalpha = std::abs(r_r2 - r_r1) / (r_w2 - r_w1).mag();
82 cosalpha = std::sqrt(1.0 - sinalpha * sinalpha);
83
84 // case 1 //
85 if (r_case == 1) {
86 p1 = r_w1 + ((1 && r_r2 >= r_r1) - (1 && r_r2 < r_r1)) * r_r1 * (cosalpha * e2prime - sinalpha * e3prime);
87 p2 = r_w2 + ((1 && r_r2 >= r_r1) - (1 && r_r2 < r_r1)) * r_r2 * (cosalpha * e2prime - sinalpha * e3prime);
88 }
89
90 // case 2 //
91 if (r_case == 2) {
92 p1 = r_w1 - ((1 && r_r2 >= r_r1) - (1 && r_r2 < r_r1)) * r_r1 * (cosalpha * e2prime + sinalpha * e3prime);
93 p2 = r_w2 - ((1 && r_r2 >= r_r1) - (1 && r_r2 < r_r1)) * r_r2 * (cosalpha * e2prime + sinalpha * e3prime);
94 }
95 }
96
97 // case 3 and 4 //
98 if (r_case == 3 || r_case == 4) {
99 sinalpha = (r_r1 + r_r2) / (r_w2 - r_w1).mag();
100 cosalpha = std::sqrt(1.0 - sinalpha * sinalpha);
101
102 // case 3 //
103 if (r_case == 3) {
104 p1 = r_w1 + r_r1 * (cosalpha * e2prime + sinalpha * e3prime);
105 p2 = r_w2 - r_r2 * (cosalpha * e2prime + sinalpha * e3prime);
106 }
107
108 // case 4 //
109 if (r_case == 4) {
110 p1 = r_w1 - r_r1 * (cosalpha * e2prime - sinalpha * e3prime);
111 p2 = r_w2 + r_r2 * (cosalpha * e2prime - sinalpha * e3prime);
112 }
113 }
114
115 // calculation of the tangent and estimation of its errors //
116 if ((p2 - p1).z() != 0.0) {
117 tang = MTStraightLine(p1, p2 - p1, null_vec, null_vec);
118 } else {
119 Amg::Vector3D direction(p2 - p1);
120 direction[2] = 1.0e-99;
121 tang = MTStraightLine(p1, direction, null_vec, null_vec);
122 }
123 mx1 = tang.a_x1();
124 bx1 = tang.b_x1();
125 mx2 = tang.a_x2();
126 bx2 = tang.b_x2();
127 tang = MTStraightLine(mx1, bx1, mx2, bx2, 1.0, 1.0, std::sqrt(r_sigma12 + r_sigma22) / std::abs(p2.z() - p1.z()),
128 std::sqrt(r_sigma12 + p1.z() * p1.z() * (r_sigma12 + r_sigma22) / std::pow(p2.z() - p1.z(), 2)));
129 // errors in mx1 and bx1 are arbitrary since they are
130 // not used at a later stage.
131
132 return tang;
133}
134MTStraightLine QuasianalyticLineReconstruction::track_candidate(const IndexSet& r_index_set, const int& r_k_cand, const int& r_l_cand,
135 const int& r_cand_case, const std::vector<Amg::Vector3D>& r_w,
136 const std::vector<double>& r_r, const std::vector<double>& r_sigma2,
137 double& r_chi2) const {
138 //:::::::::::::::
139 //:: VARIABLES ::
140 //:::::::::::::::
141
142 int nb_hits(r_index_set.size()); // number of hits used in the track
143 // reconstruction
144 int nb_tangents(0); // number of tangents used in the track
145 // reconstruction
146 std::vector<double> mx1, bx1, mx2, bx2; // slopes and intercepts of the
147 // tangents building the track
148 std::vector<double> mx1_err, bx1_err, mx2_err, bx2_err; // their errors
149 MTStraightLine aux_track; // auxiliary straight line
150 MTStraightLine tang; // tangent to drift circles of a hit pair
151 Amg::Vector3D d1(0.0, 0.0, 0.0), d2(0.0, 0.0, 0.0); // auxiliary distance vectors
152 Amg::Vector3D e2prime(0.0, 0.0, 0.0), e3prime(0.0, 0.0, 0.0); // auxiliary basis vectors
153 Amg::Vector3D a(0.0, 0.0, 0.0), u(0.0, 0.0, 0.0); // position and direction vector of the candidate
154 // tangent
155 double sinalpha; // auxiliary sinus of an angle
156 double cosalpha; // auxiliary sinus of an angle
157 Amg::Vector3D p1(0.0, 0.0, 0.0), p2(0.0, 0.0, 0.0); // hit points defining a tangent
158 Amg::Vector3D null_vec(0.0, 0.0, 0.0); // auxiliary 0 vector
159 double sum[4]; // auxiliary summation variables
160
161 //:::::::::::::::::::::
162 //:: GET THE TANGENT ::
163 //:::::::::::::::::::::
164
165 // calculate the tangent //
166 aux_track = tangent(r_w[r_k_cand], r_r[r_k_cand], r_sigma2[r_k_cand], r_w[r_l_cand], r_r[r_l_cand], r_sigma2[r_l_cand], r_cand_case);
167 a = aux_track.positionVector();
168 u = (aux_track.directionVector()).unit();
169
170 // store the parameters of this tangent //
171 mx1.push_back(aux_track.a_x1());
172 mx1_err.push_back(aux_track.a_x1_error());
173 bx1.push_back(aux_track.b_x1());
174 bx1_err.push_back(aux_track.b_x1_error());
175 mx2.push_back(aux_track.a_x2());
176 mx2_err.push_back(aux_track.a_x2_error());
177 bx2.push_back(aux_track.b_x2());
178 bx2_err.push_back(aux_track.b_x2_error());
179
180 //:::::::::::::::::::::::::::::::::::::::::::::::::::::
181 //:: LOOP OVER THE OTHER HITS AND CALCULATE TANGENTS :: //
182 //:::::::::::::::::::::::::::::::::::::::::::::::::::::
183
184 for (int kk = 0; kk < nb_hits - 1; kk++) {
185 for (int ll = kk + 1; ll < nb_hits; ll++) {
186 int k(r_index_set[kk]);
187 int l(r_index_set[ll]);
188
189 if (k == r_k_cand && l == r_l_cand) { continue; }
190
191 // local coordinate axis vectors //
192 e3prime = (r_w[l] - r_w[k]).unit();
193 e2prime = Amg::Vector3D(0.0, e3prime.z(), -e3prime.y());
194
195 // distance vectors //
196 d1 = (r_w[k] - a).dot(u) * u - (r_w[k] - a);
197 d1[0] = (0.0);
198 d2 = (r_w[l] - a).dot(u) * u - (r_w[l] - a);
199 d2[0] = (0.0);
200
201 // one must distinguish 2 cases //
202
203 // case 1: candidate tangent passes both wires on the same side //
204 if (d1.dot(d2) >= 0) {
205 sinalpha = std::abs(r_r[l] - r_r[k]) / (r_w[l] - r_w[k]).mag();
206 cosalpha = std::sqrt(1.0 - sinalpha * sinalpha);
207
208 if (d1.dot(e2prime) >= 0) {
209 if (r_r[k] <= r_r[l]) {
210 p1 = r_w[k] + r_r[k] * (cosalpha * e2prime - sinalpha * e3prime);
211 } else {
212 p1 = r_w[k] + r_r[k] * (cosalpha * e2prime + sinalpha * e3prime);
213 }
214 } else {
215 if (r_r[k] >= r_r[l]) {
216 p1 = r_w[k] - r_r[k] * (cosalpha * e2prime - sinalpha * e3prime);
217 } else {
218 p1 = r_w[k] - r_r[k] * (cosalpha * e2prime + sinalpha * e3prime);
219 }
220 }
221
222 if (d2.dot(e2prime) >= 0) {
223 if (r_r[k] <= r_r[l]) {
224 p2 = r_w[l] + r_r[l] * (cosalpha * e2prime - sinalpha * e3prime);
225 } else {
226 p2 = r_w[l] + r_r[l] * (cosalpha * e2prime + sinalpha * e3prime);
227 }
228 } else {
229 if (r_r[k] >= r_r[l]) {
230 p2 = r_w[l] - r_r[l] * (cosalpha * e2prime - sinalpha * e3prime);
231 } else {
232 p2 = r_w[l] - r_r[l] * (cosalpha * e2prime + sinalpha * e3prime);
233 }
234 }
235 }
236
237 // case 2: candidate tangent passes both wires on opposite sides //
238 if (d1.dot(d2) < 0) {
239 sinalpha = (r_r[l] + r_r[k]) / (r_w[l] - r_w[k]).mag();
240 cosalpha = std::sqrt(1.0 - sinalpha * sinalpha);
241
242 // case 2(a) //
243 if (d1.dot(e2prime) >= 0 && d2.dot(e2prime) <= 0) {
244 p1 = r_w[k] + r_r[k] * (cosalpha * e2prime + sinalpha * e3prime);
245 p2 = r_w[l] - r_r[l] * (cosalpha * e2prime + sinalpha * e3prime);
246 }
247
248 // case 2(b) //
249 if (d1.dot(e2prime) < 0 && d2.dot(e2prime) >= 0) {
250 p1 = r_w[k] - r_r[k] * (cosalpha * e2prime - sinalpha * e3prime);
251 p2 = r_w[l] + r_r[l] * (cosalpha * e2prime - sinalpha * e3prime);
252 }
253 }
254
255 // get the slope and intercept of the new tangents and error estimates //
256 if ((p2 - p1).z() != 0.0) {
257 tang = MTStraightLine(p1, p2 - p1, null_vec, null_vec);
258 } else {
259 Amg::Vector3D direction(p2 - p1);
260 direction[2] = (1.0e-99);
261 tang = MTStraightLine(p1, direction, null_vec, null_vec);
262 }
263 mx1.push_back(tang.a_x1());
264 bx1.push_back(tang.b_x1());
265 mx2.push_back(tang.a_x2());
266 bx2.push_back(tang.b_x2());
267
268 mx1_err.push_back(1.0);
269 bx1_err.push_back(1.0);
270
271 mx2_err.push_back((r_sigma2[k] + r_sigma2[l]) / std::pow(p2.z() - p1.z(), 2));
272 bx2_err.push_back(r_sigma2[k] + p1.z() * p1.z() * (r_sigma2[k] + r_sigma2[l]) / std::pow(p2.z() - p1.z(), 2));
273 // errors in x1 and x2 are arbitrary since they are not
274 // used at a later stage.
275
276 // increase the number of tangents //
277 nb_tangents = nb_tangents + 1;
278 }
279 }
280
281 //::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
282 //:: CALCULATE A WEIGHTED AVERAGE OVER THE TANGENTS AND THE chi^2 FOR ::
283 //:: THE RECONSTRUCTED TRAJECTORY ::
284 //::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
285
286 sum[0] = 0.0;
287 sum[1] = 0.0;
288 sum[2] = 0.0;
289 sum[3] = 0.0;
290 for (int k = 0; k < nb_tangents; k++) {
291 if (mx2_err[k] > 0) {
292 sum[0] = sum[0] + mx2[k] / mx2_err[k];
293 sum[1] = sum[1] + 1.0 / mx2_err[k];
294 } else {
295 sum[0] = sum[0] + mx2[k];
296 sum[1] = sum[1] + 1.0;
297 }
298 if (bx2_err[k] > 0) {
299 sum[2] = sum[2] + bx2[k] / bx2_err[k];
300 sum[3] = sum[3] + 1.0 / bx2_err[k];
301 } else {
302 sum[2] = sum[2] + bx2[k];
303 sum[3] = sum[3] + 1.0;
304 }
305 }
306
307 aux_track = MTStraightLine(0.0, 0.0, sum[0] / sum[1], sum[2] / sum[3], 0.0, 1.0, std::sqrt(1.0 / sum[1]), std::sqrt(1.0 / sum[3]));
308
309 r_chi2 = 0.0;
310 for (int k = 0; k < nb_hits; k++) {
311 r_chi2 = r_chi2 + std::pow(aux_track.distFromLine(r_w[r_index_set[k]]) - r_r[r_index_set[k]], 2) / r_sigma2[k];
312 }
313
314 return aux_track;
315}
316
318void QuasianalyticLineReconstruction::setRoadWidth(const double r_road_width) { m_road_width = std::abs(r_road_width); }
319void QuasianalyticLineReconstruction::setTimeOut(const double time_out) { m_time_out = time_out; }
321 if (maxR < 7 || maxR > 15)
322 throw std::runtime_error(Form(
323 "File: %s, Line: %d\nQuasianalyticLineReconstruction::setMaxRadius() - given radius %.3f not supported, neither MDT nor sMDT",
324 __FILE__, __LINE__, maxR));
325 m_r_max = maxR;
326}
328 // select all hits //
329 HitSelection selection(r_segment.mdtHitsOnTrack(), 0);
330
331 // call the other fit function //
332 return fit(r_segment, std::move(selection));
333}
335 MTStraightLine final_track;
336 return fit(r_segment, std::move(r_selection), final_track);
337}
338bool QuasianalyticLineReconstruction::fit(MuonCalibSegment& r_segment, HitSelection r_selection, MTStraightLine& final_track) const {
340 // VARIABLES //
342
343 time_t start, end; // start and end time (needed for time-out)
344 time(&start);
345 double diff; // difference of start and end time (needed for time-out)
346 unsigned int nb_selected_hits(0); // number of selected hits
347 MdtHitVec selected_hits; // vector of pointers to the
348 // selected hits
349 std::vector<unsigned> selected_hits_index(r_selection.size());
350 // vector containing the indices
351 // of the selected hits (needed
352 // a requested refit)
353 std::vector<Amg::Vector3D> w; // wire coordinates
354 std::vector<double> r; // drift CLHEP::radii of the selected hits
355 std::vector<double> sigma2; // sigma(r)^2 (spatial resolution in r)
356 unsigned int counter1{0}, counter2{0}, counter3{0}; // auxiliary counters
357 unsigned int max_cand_hits{0}; // the maximum number of hits on a track candidate
358 // found so far
359 int max_cand_HOTs{0}; // the maximum number of hit tubes on a track
360 // candidate found so far
361 int nb_candidates; // number of candidate tracks
362 std::vector<int> k_cand, l_cand; // candidate track index
363 std::vector<int> cand_case; // tangent case for the candidate
364 std::vector<int> nb_HOTs; // number of hits on a candidate
365 int candidate{0}; // index of the candidate which becomes the track
366 IndexSet aux_set; // auxiliary index set
367 std::vector<IndexSet> index_set; // index set for the storage of the hits
368 // forming a track
369 std::vector<double> intercept; // intercepts of track candidates
370 MTStraightLine tangents[4]; // the four tangents to the drift circles of a
371 // hit pair
372 MTStraightLine aux_track; // auxiliary track
373 double aux_chi2; // auxiliary chi^2 variable
374 Amg::Vector3D null(0.0, 0.0, 0.0);
375 Amg::Vector3D xhat(1.0, 0.0, 0.0);
376 MTStraightLine initial_track(r_segment.position(), r_segment.direction(), null, null);
377 // initial track stored in the segment
378 Amg::Vector3D aux_pos, aux_dir; // auxiliary position and direction vectors
379
381 // GET THE NUMBER OF SELECTED HITS //
383 if (r_segment.mdtHitsOnTrack() != r_selection.size()) {
384 MsgStream log(Athena::getMessageSvc(), "QuasianalyticLineReconstruction");
385 log << MSG::WARNING
386 << "Class QuasianalyticLineReconstruction, method fit: Vector with selected hits unequal to the number of hits on the segment! "
387 "The user selection will be ignored!"
388 << endmsg;
389 r_selection.clear();
390 r_selection.assign(r_segment.hitsOnTrack(), 0);
391 } else {
392 for (unsigned int k : r_selection) {
393 if (k == 0) { nb_selected_hits = nb_selected_hits + 1; }
394 }
395 }
396
398 // FIX POTENTIAL SECOND-COORDINATE PROBLEM OF THE INITIAL TRACK SEGMENT //
400
401 if (r_segment.direction().z() == 0.0) {
402 Amg::Vector3D dir(r_segment.direction().x(), r_segment.direction().y(), 1.0);
403 initial_track = MTStraightLine(r_segment.position(), dir, null, null);
404 }
405
407 // RETURN, IF THERE ARE LESS THAN 3 HITS, I.E. THE TRACK IS NOT UNIQUELY //
408 // DEFINED BY THE HITS. //
410
411 if (nb_selected_hits < 3) {
412 MsgStream log(Athena::getMessageSvc(), "QuasianalyticLineReconstruction");
413 log << MSG::WARNING << "Class QuasianalyticLineReconstruction, method fit: Too few hits for the track reconstructions!" << endmsg;
414 return false;
415 }
416
418 // COPY THE WIRE COORDINATES TO A LOCAL VECTOR //
420
421 // vector assignments //
422 selected_hits.clear(); // = vector<const MdtCalibHitBase*>(nb_selected_hits);
423 w.clear(); // = vector<Amg::Vector3D>(nb_selected_hits);
424 r.clear(); // = vector<double>(nb_selected_hits);
425 sigma2.clear(); // = vector<double>(nb_selected_hits);
426 selected_hits_index.clear(); //
427 // vector filling //
428 counter2 = 0;
429 for (unsigned int k = 0; k < r_segment.mdtHitsOnTrack(); k++) {
430 // skip the hit, if it has not been selected //
431 const MuonCalibSegment::MdtHitPtr hit = (r_segment.mdtHOT())[k];
432 if (r_selection[k] == 1 || hit->sigmaDriftRadius() > 100.0) { continue; }
433
434 // copy the hit information into local vectors //
435 selected_hits.push_back(hit);
436 selected_hits_index.push_back(k);
437 w.push_back(Amg::Vector3D(0.0, (hit->localPosition()).y(), (hit->localPosition()).z()));
438 r.push_back(std::abs(hit->driftRadius()));
439 sigma2.push_back(hit->sigma2DriftRadius());
440 // if the spatial resolution has not been set, set it to 0.1 CLHEP::mm //
441 if (sigma2[counter2] == 0) { sigma2[counter2] = std::pow(0.1 * CLHEP::mm, 2); }
442
443 counter2 = counter2 + 1;
444 }
445 nb_selected_hits = selected_hits.size();
446 if (nb_selected_hits < 3) return false;
448 // TRACK RECONSTRUCTION //
450
451 // reset counters //
452 max_cand_hits = 0;
453 max_cand_HOTs = 0;
454 nb_candidates = 0;
455 // 1st step: loop over all hit pairs and determine a track candidate //
456 for (unsigned int k = 0; k < nb_selected_hits; k++) {
457 for (unsigned int l = k + 1; l < nb_selected_hits; l++) {
458 // time-out //
459 time(&end);
460 diff = difftime(end, start);
461 if (diff > m_time_out) {
462 MsgStream log(Athena::getMessageSvc(), "QuasianalyticLineReconstruction");
463 log << MSG::WARNING << "Class QuasianalyticLineReconstruction, method fit: time-out for track finding after " << m_time_out
464 << " seconds!" << endmsg;
465 return false;
466 }
467
468 // 2nd step: determine all four tangents to the drift circles of the hit pair //
469 for (unsigned int r_case = 1; r_case < 5; r_case++) {
470 tangents[r_case - 1] = tangent(w[l], r[l], sigma2[l], w[k], r[k], sigma2[k], r_case);
471 }
472
473 // 3rd step: determine additional track points within the road width around //
474 // the four tangents //
475 for (unsigned int r_case = 1; r_case < 5; r_case++) {
476 bool same(false);
477 counter1 = 0;
478 counter3 = 0;
479 std::vector<int> indices; // indices of the hits forming a
480 // track
481 for (unsigned int n = 0; n < nb_selected_hits; n++) {
482 MTStraightLine aux_line(w[n], xhat, null, null);
483 if (std::abs(std::abs(tangents[r_case - 1].signDistFrom(aux_line)) - r[n]) < m_r_max) { counter3++; }
484 if (std::abs(std::abs(tangents[r_case - 1].signDistFrom(aux_line)) - r[n]) <= m_road_width) {
485 counter1 = counter1 + 1;
486 indices.push_back(n);
487 }
488 }
489 if (counter1 > 2) {
490 aux_set = IndexSet(counter1, indices);
491 aux_set.sort();
492 for (int ca = 0; ca < nb_candidates; ca++) {
493 if (aux_set == index_set[ca] && std::abs(intercept[ca] - tangents[r_case - 1].b_x2()) < m_road_width) {
494 same = true;
495 break;
496 }
497 }
498 if (same) { continue; }
499 nb_candidates = nb_candidates + 1;
500 k_cand.push_back(k);
501 l_cand.push_back(l);
502 cand_case.push_back(r_case);
503 index_set.push_back(aux_set);
504 intercept.push_back(tangents[r_case - 1].b_x2());
505 nb_HOTs.push_back(counter3);
506 if (counter1 > max_cand_hits) { max_cand_hits = counter1; }
507 }
508 }
509 }
510 }
511
512 // 4th step: reconstruct a straight-line trajectory for all candidates with //
513 // the maximum number of hits, keep the one with the smallest chi^2 //
514
515 // m_nb_track_hits = max_cand_hits;
516 double chi2 = -1;
517 if (max_cand_hits < 3) { return false; }
518
519 candidate = 0;
520 for (int ca = 0; ca < nb_candidates; ca++) {
521 if (index_set[ca].size() < max_cand_hits) { continue; }
522
523 aux_track = track_candidate(index_set[ca], k_cand[ca], l_cand[ca], cand_case[ca], w, r, sigma2, aux_chi2);
524 if (nb_HOTs[ca] >= max_cand_HOTs) {
525 max_cand_HOTs = nb_HOTs[ca];
526 if (chi2 == -1.0 || chi2 > aux_chi2) {
527 chi2 = aux_chi2;
528 final_track = aux_track;
529 candidate = ca;
530 }
531 }
532 }
533
534 MdtHitVec final_track_hits(max_cand_hits);
535 for (unsigned int k = 0; k < max_cand_hits; k++) { final_track_hits[k] = selected_hits[index_set[candidate][k]]; }
536
537 // make the segment in rphi as the initial segment //
538 aux_pos = Amg::Vector3D(initial_track.b_x1(), final_track.b_x2(), 0);
539 aux_dir = Amg::Vector3D(initial_track.a_x1(), final_track.a_x2(), 1.0);
540 final_track = MTStraightLine(aux_pos, aux_dir, null, null);
541
542 // 5th step: update the segment//
543 if (std::isnan(chi2)) { chi2 = 1.0e6; }
544 r_segment.set(chi2 / (max_cand_hits - 2), final_track.positionVector(), final_track.directionVector());
545
546 std::vector<unsigned int> refit_hit_selection(r_selection.size(), 1);
547 for (unsigned int k = 0; k < max_cand_hits; k++) { refit_hit_selection[selected_hits_index[index_set[candidate][k]]] = 0; }
548 if (!m_refit && m_refine_segment) { r_segment.refineMdtSelection(refit_hit_selection); }
549
550 // chi^2 refit, if requested //
551 if (m_refit) {
552 if (m_nfitter.fit(r_segment, refit_hit_selection)) {
553 Amg::Vector3D dir(r_segment.direction());
554 if (dir.z() == 0.0) { dir[2] = (1.0e-99); }
555 MTStraightLine aux_line(r_segment.position(), dir, Amg::Vector3D(0.0, 0.0, 0.0), Amg::Vector3D(0.0, 0.0, 0.0));
556 double a_err(final_track.a_x2_error());
557 double b_err(final_track.b_x2_error());
558 final_track = MTStraightLine(0.0, 0.0, aux_line.a_x2(), aux_line.b_x2(), 0.0, 0.0, a_err, b_err);
559 aux_pos = Amg::Vector3D(initial_track.b_x1(), final_track.b_x2(), 0);
560 aux_dir = Amg::Vector3D(initial_track.a_x1(), final_track.a_x2(), 1.0);
561 final_track = MTStraightLine(aux_pos, aux_dir, null, null);
562 // recompute chi^2 because of different convention in DCSLFitter //
563 chi2 = 0.0;
564 for (unsigned int k = 0; k < max_cand_hits; k++) {
565 MTStraightLine wire(Amg::Vector3D(0.0, final_track_hits[k]->localPosition().y(), final_track_hits[k]->localPosition().z()),
566 xhat, null, null);
567 double d(std::abs(final_track.signDistFrom(wire)));
568 double r(std::abs(final_track_hits[k]->driftRadius()));
569 chi2 += std::pow(d - r, 2) / final_track_hits[k]->sigma2DriftRadius();
570 }
571 if (std::isnan(chi2)) { chi2 = 1.0e6; }
572
573 r_segment.set(chi2 / (max_cand_hits - 2), final_track.positionVector(), final_track.directionVector());
574 if (m_refine_segment) { r_segment.refineMdtSelection(refit_hit_selection); }
575 return true;
576 }
577 return false;
578 }
579
580 // finish the update (necessary, if no refit has been performed) //
581 for (MdtHitPtr& mdt_hit : r_segment.mdtHOT()) {
582 MdtCalibHitBase& hit = *mdt_hit;
583
584 Amg::Vector3D pos(0.0, (hit.localPosition()).y(), (hit.localPosition()).z());
585 // wire position
586 MTStraightLine aux_line(pos, xhat, null, null);
587 double dist(final_track.signDistFrom(aux_line)); // track distance
588 double dist_err(std::hypot(pos.z() * final_track.a_x2_error(), final_track.b_x2_error()));
589 // approximate error of the track distance
590 hit.setDistanceToTrack(dist, dist_err);
591 }
592 final_track.setUsedHits(final_track_hits);
593 final_track.setChi2(chi2);
594
595 return true;
596}
const std::string r_r
Scalar mag() const
mag method
#define endmsg
detray::unit< scalar_t > unit
std::vector< std::vector< int64_t > > indices
bool hit(const Container &ids, int pdgId)
static Double_t a
size_t size() const
Number of registered mappings.
void diff(const TrigCaloCluster &a, const TrigCaloCluster &b, std::map< std::string, double > &varChange)
#define y
#define z
std::vector< unsigned int > HitSelection
void sort()
sort the indices in ascending order
Definition IndexSet.cxx:137
unsigned int size() const
get the number of indices
Definition IndexSet.cxx:82
Amg::Vector3D directionVector() const
get the direction vector of the straight line
double distFromLine(const Amg::Vector3D &point) const
get the distance of point point from straight line
double b_x2() const
get the intercept of the straight line in the x2-x3 plane
double b_x1_error() const
get the error on the intercept of the straight line in the x1-x3 plane
double a_x2() const
get the slope of the straight line in the x2-x3 plane
double b_x1() const
get the intercept of the straight line in the x1-x3 plane
Amg::Vector3D positionVector() const
get the position vector of the straight line
double a_x1() const
get the slope of the straight line in the x1-x3 plane
double b_x2_error() const
get the slope of the intercept of the straight line in the x2-x3 plane
double a_x1_error() const
get the error on the slope of the straight line in the x1-x3 plane
void setUsedHits(const MdtHitVec &hits)
double signDistFrom(const MTStraightLine &h) const
get the signed distance of two lines (if both are parallel, dist>0)
double a_x2_error() const
get the error on the slope of the straight line in the x2-x3 plane
void setChi2(double chi2)
Cache the chi2.
Athena-independent part of the MdtCalibHit.
A MuonCalibSegment is a reconstructed three dimensional track segment in the MuonSpectrometer.
unsigned int mdtHitsOnTrack() const
retrieve the number of MdtCalibHitBase s assigned to this segment
void refineMdtSelection(const std::vector< unsigned int > &new_selection)
move trck hits to close hits
const Amg::Vector3D & direction() const
retrieve local direction of segment (on station level) retrieve the transformation from local chamber...
std::shared_ptr< MdtCalibHitBase > MdtHitPtr
typedef for a collection of MdtCalibHitBase s
unsigned int hitsOnTrack() const
retrieve the sum of all XxxCalibHits assigned to the MuonCalibSegment
const MdtHitVec & mdtHOT() const
retrieve the full set of MdtCalibHitBase s assigned to this segment
void set(double chi2, const Amg::Vector3D &pos, const Amg::Vector3D &dir)
const Amg::Vector3D & position() const
retrieve local position of segment (on station level)
MTStraightLine tangent(const Amg::Vector3D &r_w1, const double r_r1, const double r_sigma12, const Amg::Vector3D &r_w2, const double r_r2, const double r_sigma22, const int &r_case) const
void setMaxRadius(const double maxR)
set the max innerRadius, default for MDT sMDT 7.1mm, MDT 14.6mm
double roadWidth() const
get the road width used in the pattern recognition
void setRoadWidth(const double r_road_width)
set the road width for the pattern recognition = r_road_width
bool fit(MuonCalibSegment &r_segment) const
reconstruction of the track using all hits in the segment "r_segment", returns true in case of succes...
void setTimeOut(const double time_out)
set the time-out for the track finding to time_out (in seconds)
MTStraightLine track_candidate(const IndexSet &r_index_set, const int &r_k_cand, const int &r_l_cand, const int &r_cand_case, const std::vector< Amg::Vector3D > &r_w, const std::vector< double > &r_r, const std::vector< double > &r_sigma2, double &r_chi2) const
double chi2(TH1 *h0, TH1 *h1)
const std::string selection
singleton-like access to IMessageSvc via open function and helper
int r
Definition globals.cxx:22
Eigen::Matrix< double, 3, 1 > Vector3D
IMessageSvc * getMessageSvc(bool quiet=false)
CscCalcPed - algorithm that finds the Cathode Strip Chamber pedestals from an RDO.
Definition dot.py:1