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