ATLAS Offline Software
Loading...
Searching...
No Matches
AFPSiDLinRegTool.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2022 CERN for the benefit of the ATLAS collaboration
3*/
4
10
11
13
14
16 const std::string& name,
17 const IInterface* parent ) :
18 base_class( type, name, parent )
19{
20}
21
22
24{
25 if(m_trackSelection=="loose" || m_trackSelection=="Loose")
26 {
27 m_selectionFunction = [](const std::vector<const xAOD::AFPSiHitsCluster*>&) { return true; };
28 }
29 else if(m_trackSelection=="medium" || m_trackSelection=="Medium")
30 {
31 m_selectionFunction = [this](const std::vector<const xAOD::AFPSiHitsCluster*>& t) {
32 std::vector<int> plane{0, 0, 0, 0};
33
34 for (auto&& cluster : t) {
35 const int p = cluster->pixelLayerID();
36 plane[p]++;
37 }
38
39 auto HasAnyClusters = [](int n) { return n > 0; };
40
41 return std::count_if(plane.begin(), plane.end(), HasAnyClusters) >= m_minimalNumberOfPlanesInTrack;
42 };
43 }
44 else if(m_trackSelection=="tight" || m_trackSelection=="Tight")
45 {
46 m_selectionFunction = [this](const std::vector<const xAOD::AFPSiHitsCluster*>& t) {
47 std::vector<int> plane{0, 0, 0, 0};
48
49 for (auto&& cluster : t) {
50 const int p = cluster->pixelLayerID();
51 plane[p]++;
52 }
53
54 auto HasMultipleClusters = [](int n) { return n > 1; };
55
56 if (std::any_of(plane.begin(), plane.end(), HasMultipleClusters)) { return false; }
57
58 // Check number of planes (cluster/plane == 1)
59 if (t.size() < m_minimalNumberOfPlanesInTrack) { return false; }
60
61 return true;
62 };
63 }
64 else
65 {
66 ATH_MSG_ERROR("unknown trackSelection "<<m_trackSelection<<", allowed values are \"Loose\", \"Medium\", or \"Tight\" ");
67 return StatusCode::FAILURE;
68 }
69
70 CHECK( m_hitsClusterContainerKey.initialize() );
71
72 return StatusCode::SUCCESS;
73}
74
75
77{
78 // All clusters should be in same station, so no need for checking
79
80 const double xa = a->xLocal();
81 const double ya = a->yLocal();
82
83 const double xb = b->xLocal();
84 const double yb = b->yLocal();
85
86 const double dx = xa - xb;
87 const double dy = ya - yb;
89 return dx * dx + dy * dy <= maxDistanceSq;
90}
91
92
93std::vector<const xAOD::AFPSiHitsCluster*> AFPSiDLinRegTool::findClusterAroundElement(std::list<const xAOD::AFPSiHitsCluster*>& toJoin, const xAOD::AFPSiHitsCluster* init) const
94{
95 // Push initial cluster
96 std::vector<const xAOD::AFPSiHitsCluster*> track;
97 track.push_back(init);
98
99 std::vector<const xAOD::AFPSiHitsCluster*> newNeighbours;
100
101 // Repeat while new neighbours are found
102 do {
103 newNeighbours.clear();
104 for (auto&& b : toJoin) {
105 bool isNew = false;
106 for (auto&& a : track) {
107 if (areNeighbours(a, b)) { isNew = true; }
108 }
109
110 if (isNew) {
111 newNeighbours.push_back(b);
112 track.push_back(b);
113 }
114 }
115
116 // Clustered clusters are taken out from "clusters" container
117 for (auto& t : newNeighbours) {
118 toJoin.remove(t);
119 }
120
121 } while (!newNeighbours.empty());
122
123 return track;
124}
125
126
127std::pair<double, double> AFPSiDLinRegTool::linearRegression(const std::vector<std::pair<double, double>>& YX) const
128{
129 // here, "x" is Z axis and "y" is X or Y axis
130
131 double meanx = 0, meany = 0;
132 for (const auto& [y, x] : YX) {
133 meany += y;
134 meanx += x;
135 }
136 meanx /= YX.size();
137 meany /= YX.size();
138
139 double numerator = 0, denominator = 0;
140 for (const auto& [y, x] : YX) {
141 const double dy = y - meany;
142 const double dx = x - meanx;
143
144 numerator += dx * dy;
145 denominator += dx * dx;
146 }
147
148 const double slope = numerator / denominator;
149 const double position = meany - slope * meanx;
150
151 return {position, slope};
152}
153
154
155StatusCode AFPSiDLinRegTool::reconstructTracks(std::unique_ptr<xAOD::AFPTrackContainer>& outputContainer, const EventContext& ctx) const
156{
158 if(!clusters.isValid())
159 {
160 // this is allowed, there might be no AFP data in the input
161 return StatusCode::SUCCESS;
162 }
163
164 // Select clusters in given station
165 std::list<const xAOD::AFPSiHitsCluster*> clustersInStation;
166 std::copy_if(clusters->begin(), clusters->end(), std::back_inserter(clustersInStation),
167 [this](auto cluster) { return cluster->stationID() == m_stationID; });
168
169 ATH_MSG_DEBUG("clusters in " << m_stationID << " size: " << clustersInStation.size());
170
171
172 // Loop until all clusters are used
173 while (!clustersInStation.empty())
174 {
175 // Take first element from the list...
176 const auto *const initialCluster = clustersInStation.front();
177 clustersInStation.pop_front();
178
179 // ...and find other clusters around it
180 const auto clusterOfClusters = findClusterAroundElement(clustersInStation, initialCluster);
181
182 // If track candidate does not pass chosen selection, skip it
183 if (!m_selectionFunction(clusterOfClusters)) {
184 ATH_MSG_DEBUG("track candidate of size " << clusterOfClusters.size() << " did not pass selection.");
185 continue;
186 }
187
188 auto *track = outputContainer->push_back(std::make_unique<xAOD::AFPTrack>());
189
190 // Set stationID
191 track->setStationID(m_stationID);
192
193 // Add links to clusters
194 for (const auto *const cluster : clusterOfClusters) {
196 clusterLink.toContainedElement(*clusters, cluster);
197 track->addCluster(clusterLink);
198 }
199
200 const int nClusters = track->clusters().size();
201
202 if(nClusters>0)
203 {
204 track->setNClusters(nClusters);
205 }
206 else
207 {
208 ATH_MSG_DEBUG("track candidate has 0 clusters, erasing ");
209 outputContainer->pop_back();
210 continue;
211 }
212
213 // Fit the clusters with a line in X and Y direction along Z
214 double x = 0.;
215 double y = 0.;
216 double xSlope = 0.;
217 double ySlope = 0.;
218 double chi2 = 0.;
219
220 if (nClusters == 1) {
221 x = (*(track->clusters().at(0)))->xLocal();
222 y = (*(track->clusters().at(0)))->yLocal();
223 }
224 else
225 {
226 std::vector<std::pair<double, double>> XZ;
227 std::vector<std::pair<double, double>> YZ;
228
229 for (int i = 0; i < nClusters; i++) {
230 const xAOD::AFPSiHitsCluster* cluster = *(track->clusters().at(i));
231
232 XZ.emplace_back(cluster->xLocal(), cluster->zLocal());
233 YZ.emplace_back(cluster->yLocal(), cluster->zLocal());
234 }
235
236 auto linregx = linearRegression(XZ);
237 auto linregy = linearRegression(YZ);
238
239 std::tie(x, xSlope) = linregx;
240 std::tie(y, ySlope) = linregy;
241
242 for (int i = 0; i < nClusters; i++) {
243 const xAOD::AFPSiHitsCluster* cluster = *(track->clusters().at(i));
244
245 const double z = cluster->zLocal();
246 const double ex = cluster->xLocalErr();
247 const double ey = cluster->yLocalErr();
248
249 const double dx = cluster->xLocal() - (x + xSlope * z);
250 const double dy = cluster->yLocal() - (y + ySlope * z);
251
252 chi2 += dx * dx / (ex * ex);
253 chi2 += dy * dy / (ey * ey);
254 }
255 }
256
257 // Set track properties
258 track->setChi2(chi2);
259 track->setXLocal(x);
260 track->setXSlope(xSlope);
261 track->setYLocal(y);
262 track->setYSlope(ySlope);
263 track->setZLocal(0.); // because positions of x/y are calculated at z=0
264
265 track->setAlgID(xAOD::AFPTrackRecoAlgID::linReg);
266
267 std::vector<int> clustersPlane{0, 0, 0, 0};
268 for (const auto& cl : track->clusters()) {
269 ++clustersPlane[(*cl)->pixelLayerID()];
270 }
271 auto HasNoClusters = [](int n) { return n == 0; };
272 track->setNHoles(std::count_if(clustersPlane.begin(), clustersPlane.end(), HasNoClusters));
273
274
275 ATH_MSG_DEBUG("new track with " << track->clusters().size() << " clusters, x: " << track->xLocal()
276 << ", y: " << track->yLocal() << ", sx: " << track->xSlope()
277 << ", sy: " << track->ySlope() << ", chi2: " << track->chi2());
278 for (auto&& cluster : track->clusters())
279 {
280 ATH_MSG_DEBUG('\t' << (*cluster)->xLocal() << " " << (*cluster)->yLocal() << " " << (*cluster)->zLocal());
281 }
282 }
283
284 return StatusCode::SUCCESS;
285}
Header file for AFPSiDLinRegTool used in tracks reconstruction. Adapted from AfpAnalysisToolbox.
#define ATH_MSG_ERROR(x)
#define ATH_MSG_DEBUG(x)
#define CHECK(...)
Evaluate an expression and check for errors.
static Double_t a
#define y
#define x
#define z
Gaudi::Property< unsigned int > m_minimalNumberOfPlanesInTrack
Minimal numer of planes required for track candidate.
StatusCode reconstructTracks(std::unique_ptr< xAOD::AFPTrackContainer > &outputContainer, const EventContext &ctx) const override
Reconstructs tracks properties from track candidates.
SG::ReadHandleKey< xAOD::AFPSiHitsClusterContainer > m_hitsClusterContainerKey
Name of the xAOD container with clusters to be used in track reconstruction.
virtual StatusCode initialize() override
Read parameters from job options and print tool configuration.
bool areNeighbours(const xAOD::AFPSiHitsCluster *a, const xAOD::AFPSiHitsCluster *b) const
Checks if clusters are neighbours Compares distance between them to m_allowedDistanceBetweenClustersI...
std::pair< double, double > linearRegression(const std::vector< std::pair< double, double > > &YX) const
Simple linear regression Used to calculate track postions and slopes.
std::function< bool(const std::vector< const xAOD::AFPSiHitsCluster * > &)> m_selectionFunction
Gaudi::Property< int > m_stationID
AFP station ID for which tracks will be reconstructed.
Gaudi::Property< std::string > m_trackSelection
Track selection type:
AFPSiDLinRegTool(const std::string &type, const std::string &name, const IInterface *parent)
std::vector< const xAOD::AFPSiHitsCluster * > findClusterAroundElement(std::list< const xAOD::AFPSiHitsCluster * > &toJoin, const xAOD::AFPSiHitsCluster *init) const
Looks for cluster around init cluster.
Gaudi::Property< double > m_allowedDistanceBetweenClustersInTrack
Maximum allowed distance between clusters to be considered coming from the same proton.
float zLocal() const
Cluster position along Z axis in station local coordinate system.
float yLocalErr() const
Uncertainty of cluster position along Y axis in station local coordinate system.
float xLocal() const
Cluster position along X axis in station local coordinate system.
float yLocal() const
Cluster position along Y axis in station local coordinate system.
float xLocalErr() const
Uncertainty of cluster position along X axis in station local coordinate system.
static constexpr int linReg
linear regression algorithm id=1
double chi2(TH1 *h0, TH1 *h1)
AFPSiHitsCluster_v1 AFPSiHitsCluster