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 if (denominator == 0){
148 ATH_MSG_WARNING("AFPSiDLinRegTool::linearRegression: denominator is zero");
149 return {0.,0.};
150 }
151 const double slope = numerator / denominator;
152 const double position = meany - slope * meanx;
153
154 return {position, slope};
155}
#define ATH_MSG_WARNING(x)
#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 158 of file AFPSiDLinRegTool.cxx.

159{
160 SG::ReadHandle<xAOD::AFPSiHitsClusterContainer> clusters( m_hitsClusterContainerKey, ctx );
161 if(!clusters.isValid())
162 {
163 // this is allowed, there might be no AFP data in the input
164 return StatusCode::SUCCESS;
165 }
166
167 // Select clusters in given station
168 std::list<const xAOD::AFPSiHitsCluster*> clustersInStation;
169 std::copy_if(clusters->begin(), clusters->end(), std::back_inserter(clustersInStation),
170 [this](auto cluster) { return cluster->stationID() == m_stationID; });
171
172 ATH_MSG_DEBUG("clusters in " << m_stationID << " size: " << clustersInStation.size());
173
174
175 // Loop until all clusters are used
176 while (!clustersInStation.empty())
177 {
178 // Take first element from the list...
179 const auto *const initialCluster = clustersInStation.front();
180 clustersInStation.pop_front();
181
182 // ...and find other clusters around it
183 const auto clusterOfClusters = findClusterAroundElement(clustersInStation, initialCluster);
184
185 // If track candidate does not pass chosen selection, skip it
186 if (!m_selectionFunction(clusterOfClusters)) {
187 ATH_MSG_DEBUG("track candidate of size " << clusterOfClusters.size() << " did not pass selection.");
188 continue;
189 }
190
191 auto *track = outputContainer->push_back(std::make_unique<xAOD::AFPTrack>());
192
193 // Set stationID
194 track->setStationID(m_stationID);
195
196 // Add links to clusters
197 for (const auto *const cluster : clusterOfClusters) {
198 ElementLink<xAOD::AFPSiHitsClusterContainer> clusterLink;
199 clusterLink.toContainedElement(*clusters, cluster);
200 track->addCluster(clusterLink);
201 }
202
203 const int nClusters = track->clusters().size();
204
205 if(nClusters>0)
206 {
207 track->setNClusters(nClusters);
208 }
209 else
210 {
211 ATH_MSG_DEBUG("track candidate has 0 clusters, erasing ");
212 outputContainer->pop_back();
213 continue;
214 }
215
216 // Fit the clusters with a line in X and Y direction along Z
217 double x = 0.;
218 double y = 0.;
219 double xSlope = 0.;
220 double ySlope = 0.;
221 double chi2 = 0.;
222
223 if (nClusters == 1) {
224 x = (*(track->clusters().at(0)))->xLocal();
225 y = (*(track->clusters().at(0)))->yLocal();
226 }
227 else
228 {
229 std::vector<std::pair<double, double>> XZ;
230 std::vector<std::pair<double, double>> YZ;
231
232 for (int i = 0; i < nClusters; i++) {
233 const xAOD::AFPSiHitsCluster* cluster = *(track->clusters().at(i));
234
235 XZ.emplace_back(cluster->xLocal(), cluster->zLocal());
236 YZ.emplace_back(cluster->yLocal(), cluster->zLocal());
237 }
238
239 auto linregx = linearRegression(XZ);
240 auto linregy = linearRegression(YZ);
241
242 std::tie(x, xSlope) = linregx;
243 std::tie(y, ySlope) = linregy;
244
245 for (int i = 0; i < nClusters; i++) {
246 const xAOD::AFPSiHitsCluster* cluster = *(track->clusters().at(i));
247
248 const double z = cluster->zLocal();
249 const double ex = cluster->xLocalErr();
250 const double ey = cluster->yLocalErr();
251
252 const double dx = cluster->xLocal() - (x + xSlope * z);
253 const double dy = cluster->yLocal() - (y + ySlope * z);
254
255 chi2 += dx * dx / (ex * ex);
256 chi2 += dy * dy / (ey * ey);
257 }
258 }
259
260 // Set track properties
261 track->setChi2(chi2);
262 track->setXLocal(x);
263 track->setXSlope(xSlope);
264 track->setYLocal(y);
265 track->setYSlope(ySlope);
266 track->setZLocal(0.); // because positions of x/y are calculated at z=0
267
269
270 std::vector<int> clustersPlane{0, 0, 0, 0};
271 for (const auto& cl : track->clusters()) {
272 ++clustersPlane[(*cl)->pixelLayerID()];
273 }
274 auto HasNoClusters = [](int n) { return n == 0; };
275 track->setNHoles(std::count_if(clustersPlane.begin(), clustersPlane.end(), HasNoClusters));
276
277
278 ATH_MSG_DEBUG("new track with " << track->clusters().size() << " clusters, x: " << track->xLocal()
279 << ", y: " << track->yLocal() << ", sx: " << track->xSlope()
280 << ", sy: " << track->ySlope() << ", chi2: " << track->chi2());
281 for (auto&& cluster : track->clusters())
282 {
283 ATH_MSG_DEBUG('\t' << (*cluster)->xLocal() << " " << (*cluster)->yLocal() << " " << (*cluster)->zLocal());
284 }
285 }
286
287 return StatusCode::SUCCESS;
288}
#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: