ATLAS Offline Software
Loading...
Searching...
No Matches
AFPSiDLinRegTool Class Reference

Tool for reconstructing AFPTrack parameters from track candidates. More...

#include <AFPSiDLinRegTool.h>

Inheritance diagram for AFPSiDLinRegTool:
Collaboration diagram for AFPSiDLinRegTool:

Public Member Functions

 AFPSiDLinRegTool (const std::string &type, const std::string &name, const IInterface *parent)
virtual ~AFPSiDLinRegTool () override
virtual StatusCode initialize () override
 Read parameters from job options and print tool configuration.
StatusCode reconstructTracks (std::unique_ptr< xAOD::AFPTrackContainer > &outputContainer, const EventContext &ctx) const override
 Reconstructs tracks properties from track candidates.
const std::string & outputContainerName () const override

Private Member Functions

std::vector< const xAOD::AFPSiHitsCluster * > findClusterAroundElement (std::list< const xAOD::AFPSiHitsCluster * > &toJoin, const xAOD::AFPSiHitsCluster *init) const
 Looks for cluster around init cluster.
bool areNeighbours (const xAOD::AFPSiHitsCluster *a, const xAOD::AFPSiHitsCluster *b) const
 Checks if clusters are neighbours Compares distance between them to m_allowedDistanceBetweenClustersInTrack.
std::pair< double, double > linearRegression (const std::vector< std::pair< double, double > > &YX) const
 Simple linear regression Used to calculate track postions and slopes.

Private Attributes

Gaudi::Property< std::string > m_tracksContainerName {this, "tracksContainerName", "AFPTrackContainer", "Name of the container in which tracks are saved"}
 Name of the xAOD container to which tracks will be saved; actual saving is done in AFPSIDLocRecoTool.
Gaudi::Property< int > m_stationID {this, "stationID", 0, "ID number of station for which tracks should be reconstructed"}
 AFP station ID for which tracks will be reconstructed.
Gaudi::Property< double > m_allowedDistanceBetweenClustersInTrack {this, "allowedDistanceBetweenClustersInTrack", 0.5, "Maximum allowed distance between clusters to be considered coming from the same proton"}
 Maximum allowed distance between clusters to be considered coming from the same proton.
Gaudi::Property< std::string > m_trackSelection {this, "trackSelection", "Medium", "Track selection, allowed values are \"Loose\" (accept all track candidates), \"Medium\" (accept only tracks with clusters in at least #m_minimalNumberOfPlanesInTrack planes), or \"Tight\" (reject all with more than a single cluster per plane and less than #m_minimalNumberOfPlanesInTrack planes)"}
 Track selection type:
Gaudi::Property< unsigned int > m_minimalNumberOfPlanesInTrack {this, "minimalNumberOfPlanesInTrack", 2, "Minimal numer of planes required for track candidate"}
 Minimal numer of planes required for track candidate.
std::function< bool(const std::vector< const xAOD::AFPSiHitsCluster * > &)> m_selectionFunction
SG::ReadHandleKey< xAOD::AFPSiHitsClusterContainerm_hitsClusterContainerKey {this, "AFPSiHitsClusterContainerKey", "AFPSiHitsClusterContainer", "Name of the container with clusters of hits from which tracks are to be reconstructed"}
 Name of the xAOD container with clusters to be used in track reconstruction.

Detailed Description

Tool for reconstructing AFPTrack parameters from track candidates.

Definition at line 40 of file AFPSiDLinRegTool.h.

Constructor & Destructor Documentation

◆ AFPSiDLinRegTool()

AFPSiDLinRegTool::AFPSiDLinRegTool ( const std::string & type,
const std::string & name,
const IInterface * parent )

Definition at line 15 of file AFPSiDLinRegTool.cxx.

17 :
18 base_class( type, name, parent )
19{
20}

◆ ~AFPSiDLinRegTool()

virtual AFPSiDLinRegTool::~AFPSiDLinRegTool ( )
inlineoverridevirtual

Definition at line 47 of file AFPSiDLinRegTool.h.

47{}

Member Function Documentation

◆ areNeighbours()

bool AFPSiDLinRegTool::areNeighbours ( const xAOD::AFPSiHitsCluster * a,
const xAOD::AFPSiHitsCluster * b ) const
private

Checks if clusters are neighbours Compares distance between them to m_allowedDistanceBetweenClustersInTrack.

Definition at line 76 of file AFPSiDLinRegTool.cxx.

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}
static Double_t a
Gaudi::Property< double > m_allowedDistanceBetweenClustersInTrack
Maximum allowed distance between clusters to be considered coming from the same proton.

◆ findClusterAroundElement()

std::vector< const xAOD::AFPSiHitsCluster * > AFPSiDLinRegTool::findClusterAroundElement ( std::list< const xAOD::AFPSiHitsCluster * > & toJoin,
const xAOD::AFPSiHitsCluster * init ) const
private

Looks for cluster around init cluster.

  • Loops over clusters in the list toJoin
  • Checks if those clusters are neighbours of init cluster
  • Adds neighbouring cluster to cluster vector and removes them from the list
Returns
Vector of clusters - track candiate

Definition at line 93 of file AFPSiDLinRegTool.cxx.

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}
bool areNeighbours(const xAOD::AFPSiHitsCluster *a, const xAOD::AFPSiHitsCluster *b) const
Checks if clusters are neighbours Compares distance between them to m_allowedDistanceBetweenClustersI...

◆ initialize()

StatusCode AFPSiDLinRegTool::initialize ( )
overridevirtual

Read parameters from job options and print tool configuration.

Definition at line 23 of file AFPSiDLinRegTool.cxx.

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}
#define ATH_MSG_ERROR(x)
#define CHECK(...)
Evaluate an expression and check for errors.
Gaudi::Property< unsigned int > m_minimalNumberOfPlanesInTrack
Minimal numer of planes required for track candidate.
SG::ReadHandleKey< xAOD::AFPSiHitsClusterContainer > m_hitsClusterContainerKey
Name of the xAOD container with clusters to be used in track reconstruction.
std::function< bool(const std::vector< const xAOD::AFPSiHitsCluster * > &)> m_selectionFunction
Gaudi::Property< std::string > m_trackSelection
Track selection type:

◆ linearRegression()

std::pair< double, double > AFPSiDLinRegTool::linearRegression ( const std::vector< std::pair< double, double > > & YX) const
private

Simple linear regression Used to calculate track postions and slopes.

Definition at line 127 of file AFPSiDLinRegTool.cxx.

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}
#define y
#define x

◆ outputContainerName()

const std::string & AFPSiDLinRegTool::outputContainerName ( ) const
inlineoverride

Definition at line 60 of file AFPSiDLinRegTool.h.

Gaudi::Property< std::string > m_tracksContainerName
Name of the xAOD container to which tracks will be saved; actual saving is done in AFPSIDLocRecoTool.

◆ reconstructTracks()

StatusCode AFPSiDLinRegTool::reconstructTracks ( std::unique_ptr< xAOD::AFPTrackContainer > & outputContainer,
const EventContext & ctx ) const
override

Reconstructs tracks properties from track candidates.

  • Loops over all tracks candidates
  • Calcutates and sets track properties

Definition at line 155 of file AFPSiDLinRegTool.cxx.

156{
157 SG::ReadHandle<xAOD::AFPSiHitsClusterContainer> clusters( m_hitsClusterContainerKey, ctx );
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) {
195 ElementLink<xAOD::AFPSiHitsClusterContainer> clusterLink;
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
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}
#define ATH_MSG_DEBUG(x)
#define z
std::pair< double, double > linearRegression(const std::vector< std::pair< double, double > > &YX) const
Simple linear regression Used to calculate track postions and slopes.
Gaudi::Property< int > m_stationID
AFP station ID for which tracks will be reconstructed.
std::vector< const xAOD::AFPSiHitsCluster * > findClusterAroundElement(std::list< const xAOD::AFPSiHitsCluster * > &toJoin, const xAOD::AFPSiHitsCluster *init) const
Looks for cluster around init cluster.
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

Member Data Documentation

◆ m_allowedDistanceBetweenClustersInTrack

Gaudi::Property<double> AFPSiDLinRegTool::m_allowedDistanceBetweenClustersInTrack {this, "allowedDistanceBetweenClustersInTrack", 0.5, "Maximum allowed distance between clusters to be considered coming from the same proton"}
private

Maximum allowed distance between clusters to be considered coming from the same proton.

Definition at line 70 of file AFPSiDLinRegTool.h.

70{this, "allowedDistanceBetweenClustersInTrack", 0.5, "Maximum allowed distance between clusters to be considered coming from the same proton"};

◆ m_hitsClusterContainerKey

SG::ReadHandleKey<xAOD::AFPSiHitsClusterContainer> AFPSiDLinRegTool::m_hitsClusterContainerKey {this, "AFPSiHitsClusterContainerKey", "AFPSiHitsClusterContainer", "Name of the container with clusters of hits from which tracks are to be reconstructed"}
private

Name of the xAOD container with clusters to be used in track reconstruction.

Definition at line 85 of file AFPSiDLinRegTool.h.

85{this, "AFPSiHitsClusterContainerKey", "AFPSiHitsClusterContainer", "Name of the container with clusters of hits from which tracks are to be reconstructed"};

◆ m_minimalNumberOfPlanesInTrack

Gaudi::Property<unsigned int> AFPSiDLinRegTool::m_minimalNumberOfPlanesInTrack {this, "minimalNumberOfPlanesInTrack", 2, "Minimal numer of planes required for track candidate"}
private

Minimal numer of planes required for track candidate.

Definition at line 79 of file AFPSiDLinRegTool.h.

79{this, "minimalNumberOfPlanesInTrack", 2, "Minimal numer of planes required for track candidate"};

◆ m_selectionFunction

std::function<bool(const std::vector<const xAOD::AFPSiHitsCluster*>&)> AFPSiDLinRegTool::m_selectionFunction
private

Definition at line 82 of file AFPSiDLinRegTool.h.

◆ m_stationID

Gaudi::Property<int> AFPSiDLinRegTool::m_stationID {this, "stationID", 0, "ID number of station for which tracks should be reconstructed"}
private

AFP station ID for which tracks will be reconstructed.

Definition at line 67 of file AFPSiDLinRegTool.h.

67{this, "stationID", 0, "ID number of station for which tracks should be reconstructed"};

◆ m_tracksContainerName

Gaudi::Property<std::string> AFPSiDLinRegTool::m_tracksContainerName {this, "tracksContainerName", "AFPTrackContainer", "Name of the container in which tracks are saved"}
private

Name of the xAOD container to which tracks will be saved; actual saving is done in AFPSIDLocRecoTool.

Definition at line 64 of file AFPSiDLinRegTool.h.

64{this, "tracksContainerName", "AFPTrackContainer", "Name of the container in which tracks are saved"};

◆ m_trackSelection

Gaudi::Property<std::string> AFPSiDLinRegTool::m_trackSelection {this, "trackSelection", "Medium", "Track selection, allowed values are \"Loose\" (accept all track candidates), \"Medium\" (accept only tracks with clusters in at least #m_minimalNumberOfPlanesInTrack planes), or \"Tight\" (reject all with more than a single cluster per plane and less than #m_minimalNumberOfPlanesInTrack planes)"}
private

Track selection type:

Definition at line 76 of file AFPSiDLinRegTool.h.

76{this, "trackSelection", "Medium", "Track selection, allowed values are \"Loose\" (accept all track candidates), \"Medium\" (accept only tracks with clusters in at least #m_minimalNumberOfPlanesInTrack planes), or \"Tight\" (reject all with more than a single cluster per plane and less than #m_minimalNumberOfPlanesInTrack planes)"};

The documentation for this class was generated from the following files: