Skip to content

Commit ba99301

Browse files
committed
[PWGJE,EMCAL-689] Add DeltaEta and DeltaPhi values to EMCALMatchedTracks table
- Add DeltaEta and DeltaPhi values to `EMCALMatchedTracks` table - Add PWGJE/Core/utilsTrackMatchingEMC.h where we do simple track matching. Previously we used the jetutils which matched tracks to clusters and clusters to track both. To save time we now use our own utils header and do only one. Also to make the code more easily understandble added struct `MatchResult` instead of using a complex tuple of vector<vector> abomination. - Fix PWGJE/Tasks/emcTmMonitor.cxx O2linter warnings and includes
1 parent 291c764 commit ba99301

File tree

6 files changed

+387
-276
lines changed

6 files changed

+387
-276
lines changed

PWGJE/Core/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,5 +25,6 @@ o2physics_target_root_dictionary(PWGJECore
2525
JetBkgSubUtils.h
2626
JetDerivedDataUtilities.h
2727
emcalCrossTalkEmulation.h
28+
utilsTrackMatchingEMC.h
2829
LINKDEF PWGJECoreLinkDef.h)
2930
endif()

PWGJE/Core/JetUtilities.h

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -76,11 +76,6 @@ std::tuple<std::vector<std::vector<int>>, std::vector<std::vector<int>>> MatchCl
7676
throw std::invalid_argument("track collection eta and phi sizes don't match. Check the inputs.");
7777
}
7878

79-
// for (std::size_t iTrack = 0; iTrack < nTracks; iTrack++) {
80-
// if (trackEta[iTrack] == 0)
81-
// LOG(warning) << "Track eta is 0!";
82-
// }
83-
8479
// Build the KD-trees using vectors
8580
// We build two trees:
8681
// treeBase, which contains the base collection.

PWGJE/Core/utilsTrackMatchingEMC.h

Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
1+
// Copyright 2019-2020 CERN and copyright holders of ALICE O2.
2+
// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders.
3+
// All rights not expressly granted are reserved.
4+
//
5+
// This software is distributed under the terms of the GNU General Public
6+
// License v3 (GPL Version 3), copied verbatim in the file "COPYING".
7+
//
8+
// In applying this license CERN does not waive the privileges and immunities
9+
// granted to it by virtue of its status as an Intergovernmental Organization
10+
// or submit itself to any jurisdiction.
11+
12+
/// \file utilsTrackMatchingEMC.h
13+
/// \brief EMCal track matching related utils
14+
/// \author Marvin Hemmer <marvin.hemmer@cern.ch>
15+
16+
#ifndef PWGJE_CORE_UTILSTRACKMATCHINGEMC_H_
17+
#define PWGJE_CORE_UTILSTRACKMATCHINGEMC_H_
18+
19+
#include <TKDTree.h>
20+
21+
#include <algorithm>
22+
#include <cmath>
23+
#include <cstddef>
24+
#include <limits>
25+
#include <span>
26+
#include <stdexcept>
27+
#include <vector>
28+
29+
namespace tmemcutilities
30+
{
31+
32+
struct MatchResult {
33+
std::vector<std::vector<int>> matchIndexTrack;
34+
std::vector<std::vector<float>> matchDeltaPhi;
35+
std::vector<std::vector<float>> matchDeltaEta;
36+
};
37+
38+
/**
39+
* Match clusters and tracks.
40+
*
41+
* Match cluster with tracks, where maxNumberMatches are considered in dR=maxMatchingDistance.
42+
* If no unique match was found for a jet, an index of -1 is stored.
43+
* The same map is created for clusters matched to tracks e.g. for electron analyses.
44+
*
45+
* @param clusterPhi cluster collection phi.
46+
* @param clusterEta cluster collection eta.
47+
* @param trackPhi track collection phi.
48+
* @param trackEta track collection eta.
49+
* @param maxMatchingDistance Maximum matching distance.
50+
* @param maxNumberMatches Maximum number of matches (e.g. 5 closest).
51+
*
52+
* @returns (cluster to track index map, track to cluster index map)
53+
*/
54+
MatchResult matchTracksToCluster(
55+
std::span<float> clusterPhi,
56+
std::span<float> clusterEta,
57+
std::span<float> trackPhi,
58+
std::span<float> trackEta,
59+
double maxMatchingDistance,
60+
int maxNumberMatches)
61+
{
62+
const std::size_t nClusters = clusterEta.size();
63+
const std::size_t nTracks = trackEta.size();
64+
MatchResult result;
65+
66+
result.matchIndexTrack.resize(nClusters);
67+
result.matchDeltaPhi.resize(nClusters);
68+
result.matchDeltaEta.resize(nClusters);
69+
70+
if (nClusters == 0 || nTracks == 0) {
71+
// There are no jets, so nothing to be done.
72+
return result;
73+
}
74+
// Input sizes must match
75+
if (clusterPhi.size() != clusterEta.size()) {
76+
throw std::invalid_argument("cluster collection eta and phi sizes don't match. Check the inputs.");
77+
}
78+
if (trackPhi.size() != trackEta.size()) {
79+
throw std::invalid_argument("track collection eta and phi sizes don't match. Check the inputs.");
80+
}
81+
82+
// Build the KD-trees using vectors
83+
// We build two trees:
84+
// treeBase, which contains the base collection.
85+
// treeTag, which contains the tag collection.
86+
// The trees are built to match in two dimensions (eta, phi)
87+
TKDTree<int, float> treeTrack(trackEta.size(), 2, 1);
88+
treeTrack.SetData(0, trackEta.data());
89+
treeTrack.SetData(1, trackPhi.data());
90+
treeTrack.Build();
91+
92+
// Find the track closest to each cluster.
93+
for (std::size_t iCluster = 0; iCluster < nClusters; iCluster++) {
94+
float point[2] = {clusterEta[iCluster], clusterPhi[iCluster]};
95+
int index[50]; // size 50 for safety
96+
float distance[50]; // size 50 for safery
97+
std::fill_n(index, 50, -1);
98+
std::fill_n(distance, 50, std::numeric_limits<float>::max());
99+
treeTrack.FindNearestNeighbors(point, maxNumberMatches, index, distance);
100+
101+
// allocate enough memory
102+
result.matchIndexTrack[iCluster].reserve(maxNumberMatches);
103+
result.matchDeltaPhi[iCluster].reserve(maxNumberMatches);
104+
result.matchDeltaEta[iCluster].reserve(maxNumberMatches);
105+
106+
// test whether indices are matching:
107+
for (int m = 0; m < maxNumberMatches; m++) {
108+
if (index[m] >= 0 && distance[m] < maxMatchingDistance) {
109+
result.matchIndexTrack[iCluster].push_back(index[m]);
110+
result.matchDeltaPhi[iCluster].push_back(trackPhi[index[m]] - clusterPhi[iCluster]);
111+
result.matchDeltaEta[iCluster].push_back(trackEta[index[m]] - clusterEta[iCluster]);
112+
}
113+
}
114+
}
115+
return result;
116+
}
117+
}; // namespace tmemcutilities
118+
119+
#endif // PWGJE_CORE_UTILSTRACKMATCHINGEMC_H_

PWGJE/DataModel/EMCALClusters.h

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -162,10 +162,13 @@ using EMCALClusterCell = EMCALClusterCells::iterator;
162162
using EMCALAmbiguousClusterCell = EMCALAmbiguousClusterCells::iterator;
163163
namespace emcalmatchedtrack
164164
{
165-
DECLARE_SOA_INDEX_COLUMN(Track, track); //! linked to Track table only for tracks that were matched
165+
DECLARE_SOA_INDEX_COLUMN(Track, track); //! linked to Track table only for tracks that were matched
166+
DECLARE_SOA_COLUMN(DeltaPhi, deltaPhi, float); //! difference between matched track and cluster azimuthal angle
167+
DECLARE_SOA_COLUMN(DeltaEta, deltaEta, float); //! difference between matched track and cluster pseudorapidity
166168
} // namespace emcalmatchedtrack
167-
DECLARE_SOA_TABLE(EMCALMatchedTracks, "AOD", "EMCMATCHTRACKS", //!
168-
o2::soa::Index<>, emcalclustercell::EMCALClusterId, emcalmatchedtrack::TrackId); //!
169+
DECLARE_SOA_TABLE(EMCALMatchedTracks, "AOD", "EMCMATCHTRACKS", //!
170+
o2::soa::Index<>, emcalclustercell::EMCALClusterId, emcalmatchedtrack::TrackId,
171+
emcalmatchedtrack::DeltaPhi, emcalmatchedtrack::DeltaEta); //!
169172
using EMCALMatchedTrack = EMCALMatchedTracks::iterator;
170173
} // namespace o2::aod
171174
#endif // PWGJE_DATAMODEL_EMCALCLUSTERS_H_

0 commit comments

Comments
 (0)