ATLAS Offline Software
Loading...
Searching...
No Matches
CurvedPatRec.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2021 CERN for the benefit of the ATLAS collaboration
3*/
4
6
7#include <TString.h> // for Form
8
10#include "GaudiKernel/MsgStream.h"
13#include "cmath"
14#include "time.h"
15using namespace MuonCalib;
17
18CurvedPatRec::CurvedPatRec(const double road_width) { m_road_width = road_width; }
19
20double CurvedPatRec::roadWidth() const { return m_road_width; }
21void CurvedPatRec::setRoadWidth(const double r_road_width) { m_road_width = r_road_width; }
22void CurvedPatRec::setTimeOut(const double time_out) { m_time_out = time_out; }
23bool CurvedPatRec::fit(MuonCalibSegment &r_segment) const {
24 // select all hits //
26 // call the other fit function //
27 return fit(r_segment, selection);
28}
29bool CurvedPatRec::fit(MuonCalibSegment &r_segment, HitSelection r_selection) const {
30 CurvedLine curved_track;
31 return fit(r_segment, r_selection, curved_track);
32}
33bool CurvedPatRec::fit(MuonCalibSegment &r_segment, HitSelection r_selection, CurvedLine &curved_track) const {
35 // VARIABLES //
37 std::unique_ptr<StraightPatRec> sfitter = std::make_unique<StraightPatRec>();
38 time_t start, end; // start and end times (needed for time-out)
39 double diff; // difference of start and end time (needed for time-out)
40 Combination combination;
41 std::vector<unsigned int> hit_index; // hit indices for a given combination
42 unsigned int try_nb_hits; // try to find a segment with try_nb_hits hits
43 bool segment_found(false); // flag indicating the a segment has been found
44 MdtHitVec cand_track_hits; // vector of the track hits
45 // found so far
46 CurvedLine aux_line; // memory for reconstructed curved lines
47 Amg::Vector3D null(0.0, 0.0, 0.0);
48 Amg::Vector3D xhat(1.0, 0.0, 0.0);
49 std::vector<Amg::Vector3D> points; // hit points for the track fit
50 MdtHitVec loc_track_hits; // track hit store
51
53 // RESETS //
55 time(&start);
56
58 // CHECK SIZE OF THE SELECTION VECTOR //
60
61 if (r_selection.size() != r_segment.mdtHitsOnTrack()) {
62 throw std::runtime_error(
63 Form("File: %s, Line: %d\nCurvedPatRec::fit - Size of selection vector does not match the number of hits on track!", __FILE__,
64 __LINE__));
65 }
66
68 // PREPARATORY WORK //
70
71 // perform a straight track fit to get an estimate of the incidence angle //
72 Amg::Vector3D est_dir(0.0, 0.0, 1.0);
73 sfitter->setRoadWidth(2.0 * m_road_width);
74 sfitter->setTimeOut(0.5 * m_time_out);
75 MTStraightLine track;
76 if (sfitter->fit(r_segment, r_selection, track)) { est_dir = track.directionVector(); }
77
78 // store track hits //
79 unsigned int k = 0;
80 for (const MuonCalibSegment::MdtHitPtr &hit : r_segment.mdtHOT()) {
81 if (r_selection[k] == 0 && hit->sigmaDriftRadius() < 100) { loc_track_hits.push_back(hit); };
82 ++k;
83 }
84
85 // return, if there are too few hits //
86 if (loc_track_hits.size() < 4) { return false; }
88 // PATTERN RECOGNITION //
90
91 // try to find a segment with as many hits on it as possible //
92 try_nb_hits = loc_track_hits.size();
93
94 MdtHitVec stored_track_hits;
95 double chi2 = -1.;
96
97 while (!segment_found && try_nb_hits > 3) {
98 // loop over the combinations //
99 combination.setNewParameters(loc_track_hits.size(), try_nb_hits);
100 for (unsigned int cb = 0; cb < combination.numberOfCombinations(); cb++) {
101 // time-out //
102 time(&end);
103 diff = difftime(end, start);
104 if (diff > m_time_out) {
105 MsgStream log(Athena::getMessageSvc(), "CurvedPatRec");
106 log << MSG::WARNING << "Class CurvedPatRec, method fit: time-out for track finding after " << m_time_out << " seconds!"
107 << endmsg;
108 return false;
109 }
110
111 // analyse the hit combination //
112 if (cb == 0) {
113 combination.currentCombination(hit_index);
114 } else {
115 combination.nextCombination(hit_index);
116 }
117 MdtHitVec track_hits;
118 for (unsigned int k = 0; k < try_nb_hits; ++k) { track_hits.push_back(loc_track_hits[hit_index[k] - 1]); }
119
120 // find candidates //
121 CurvedCandidateFinder finder(track_hits);
122 const std::vector<CurvedLine> candidates(finder.getCandidates(m_road_width, est_dir));
123 if (candidates.empty()) { continue; }
124
125 segment_found = true;
126
127 for (const auto & candidate : candidates) {
128 std::vector<Amg::Vector3D> errors(track_hits.size());
129 for (unsigned int k = 0; k < errors.size(); k++) {
130 if (track_hits[k]->sigmaDriftRadius() > 0.0) {
131 errors[k] = Amg::Vector3D(1.0, track_hits[k]->sigmaDriftRadius(), 0.0);
132 } else {
133 errors[k] = Amg::Vector3D(1.0, 1.0, 0.0);
134 }
135 }
136
137 // get hit points //
138 points = getHitPoints(track_hits, candidate);
139
140 // fit a curved line through the points //
141 aux_line = CurvedLine(points, errors);
142
143 // calculate chi^2 //
144 double tmp_chi2(0.0);
145 for (auto & track_hit : track_hits) {
146 MTStraightLine tang(curved_track.getTangent((track_hit->localPosition()).z()));
147 MTStraightLine wire(Amg::Vector3D(0.0, track_hit->localPosition().y(), track_hit->localPosition().z()), xhat,
148 null, null);
149 double d(std::abs(tang.signDistFrom(wire)));
150 if (track_hit->sigma2DriftRadius() != 0) {
151 tmp_chi2 = tmp_chi2 + std::pow(d - track_hit->driftRadius(), 2) / track_hit->sigma2DriftRadius();
152 } else {
153 tmp_chi2 = tmp_chi2 + std::pow(d - track_hit->driftRadius(), 2) / 0.01;
154 }
155 }
156
157 // compare chi^2 with chi^2 values found so far //
158 if (chi2 < 0 || tmp_chi2 < chi2) {
159 chi2 = tmp_chi2;
160 curved_track = aux_line;
161 // store the track hits //
162 stored_track_hits = track_hits;
163 }
164 }
165 }
166
167 try_nb_hits = try_nb_hits - 1;
168 }
169
170 if (!segment_found) { return false; }
171
173 // SECOND REFINED CURVED FIT //
175
176 // get hit points //
177 points = getHitPoints(stored_track_hits, curved_track);
178 std::vector<Amg::Vector3D> errors(stored_track_hits.size());
179 for (unsigned int k = 0; k < errors.size(); k++) {
180 if (stored_track_hits[k]->sigmaDriftRadius() > 0.0) {
181 errors[k] = Amg::Vector3D(1.0, stored_track_hits[k]->sigmaDriftRadius(), 0.0);
182 } else {
183 errors[k] = Amg::Vector3D(1.0, 1.0, 0.0);
184 }
185 }
186
187 // fit a curved line through the points //
188 curved_track = CurvedLine(points, errors);
189
191 // CALCULATE CHI^2 //
193
194 chi2 = 0.0;
195 for (auto & stored_track_hit : stored_track_hits) {
196 MTStraightLine tang(curved_track.getTangent((stored_track_hit->localPosition()).z()));
197 MTStraightLine wire(Amg::Vector3D(0.0, stored_track_hit->localPosition().y(), stored_track_hit->localPosition().z()), xhat,
198 null, null);
199 double d(std::abs(tang.signDistFrom(wire)));
200 if (stored_track_hit->sigma2DriftRadius() != 0) {
201 chi2 += std::pow(d - stored_track_hit->driftRadius(), 2) / stored_track_hit->sigma2DriftRadius();
202 } else {
203 chi2 += std::pow(d - stored_track_hit->driftRadius(), 2) / 0.01;
204 }
205 }
206
208 // UPDATE HIT RESIDUALS //
210
211 for (const MdtHitPtr& hit : r_segment.mdtHOT()) {
212 Amg::Vector3D pos(0.0, hit->localPosition().y(), hit->localPosition().z());
213 MTStraightLine aux_line(pos, xhat, null, null);
214
215 MTStraightLine tang(curved_track.getTangent(pos.z()));
216
217 double dist(tang.signDistFrom(aux_line)); // track distance
218 double dist_err(1.0); // unknown error of the track distance
219 hit->setDistanceToTrack(dist, dist_err);
220 }
221
222 if (std::isnan(chi2)) { chi2 = 1.0e6; }
223
225 // UPDATE SEGMENT POSITION, DIRECTION, CHI^2 //
227
228 MTStraightLine tangent(curved_track.getTangent((r_segment.position()).z()));
229 r_segment.set(chi2 / (stored_track_hits.size() - 3), tangent.positionVector(), tangent.directionVector());
230 curved_track.setChi2(chi2);
231 curved_track.setNumberOfTrackHits(stored_track_hits.size());
232 curved_track.setUsedHits(stored_track_hits);
233 return true;
234}
235
236Amg::Vector3D CurvedPatRec::getHitPoint(const MdtHitPtr &hit, const MTStraightLine &straight_track) const {
238 // CALCULATE HIT POINT //
240
241 Amg::Vector3D point = straight_track.positionVector() +
242 (straight_track.directionVector().unit().dot(hit->localPosition() - straight_track.positionVector())) *
243 straight_track.directionVector().unit();
244 Amg::Vector3D point_2 = hit->localPosition() + hit->driftRadius() * (point - hit->localPosition()).unit();
245
246 return point_2;
247}
248
249std::vector<Amg::Vector3D> CurvedPatRec::getHitPoints(const MdtHitVec &track_hits, const MTStraightLine &straight_track) const {
251 // VARIABLES //
253
254 std::vector<Amg::Vector3D> hit_vec;
255
257 // FILL HIT VECTOR //
259
260 for (const auto & track_hit : track_hits) { hit_vec.emplace_back(getHitPoint(track_hit, straight_track)); }
261
263 // RETURN THE HIT VECTOR //
265
266 return hit_vec;
267}
268
269std::vector<Amg::Vector3D> CurvedPatRec::getHitPoints(const MdtHitVec &track_hits, const CurvedLine &curved_track) const {
271 // VARIABLES //
273
274 std::vector<Amg::Vector3D> hit_vec;
275
277 // FILL HIT VECTOR //
279
280 for (const auto & track_hit : track_hits) {
281 hit_vec.emplace_back(getHitPoint(track_hit, curved_track.getTangent((track_hit->localPosition()).z())));
282 }
283
285 // RETURN THE HIT VECTOR //
287
288 return hit_vec;
289}
const PlainObject unit() const
This is a plugin that makes Eigen look like CLHEP & defines some convenience methods.
#define endmsg
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
void currentCombination(std::vector< unsigned int > &index_array) const
get the current combination; the result is stored in the vector index_array
unsigned int numberOfCombinations() const
get the number of combinations
void setNewParameters(const unsigned int &nb_elements, const unsigned int &wh_class)
set the number of elements = nb_elements; set the class of which the combination is = wh_class
void nextCombination(std::vector< unsigned int > &index_array)
get the next combination; the results is stored in the array index_array
void setChi2(double chi2)
Cache the chi2.
MTStraightLine getTangent(const double loc_z) const
get the tangent to the line a the local z coordinate "loc_z"
void setUsedHits(const MdtHitVec &hits)
void setNumberOfTrackHits(unsigned int n_hits)
cache the number of track hits
Amg::Vector3D getHitPoint(const MdtHitPtr &hit, const MTStraightLine &straight_track) const
MuonCalibSegment::MdtHitPtr MdtHitPtr
void setTimeOut(const double time_out)
set the time-out for the track finding to time_out (in seconds)
std::vector< Amg::Vector3D > getHitPoints(const MdtHitVec &track_hits, const MTStraightLine &straight_track) const
CurvedPatRec()
Default constructor: road width of 0.5 mm is used.
double roadWidth() const
get the road width used in the pattern recognition [mm]
void setRoadWidth(const double r_road_width)
set the road width [mm] 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...
MuonCalibSegment::MdtHitVec MdtHitVec
std::vector< unsigned int > HitSelection
Amg::Vector3D directionVector() const
get the direction vector of the straight line
Amg::Vector3D positionVector() const
get the position vector of the straight line
double signDistFrom(const MTStraightLine &h) const
get the signed distance of two lines (if both are parallel, dist>0)
float driftRadius() const
retrieve the radius of the drift circle
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
std::shared_ptr< MdtCalibHitBase > MdtHitPtr
typedef for a collection of MdtCalibHitBase s
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)
double chi2(TH1 *h0, TH1 *h1)
const std::string selection
singleton-like access to IMessageSvc via open function and helper
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