Project
Loading...
Searching...
No Matches
VertexTrackMatcher.cxx
Go to the documentation of this file.
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
15
19#include <unordered_map>
20#include <numeric>
21
22using namespace o2::vertexing;
23
25{
26 const auto& PVParams = o2::vertexing::PVertexerParams::Instance();
27 mITSGloSources.clear();
28 if (PVParams.fillITSGloContributors) { // collect sources of global tracks with ITS contributor
29 for (int i = 0; i < GIndex::NSources; i++) {
30 if (GIndex::includesDet(o2::detectors::DetID::ITS, GIndex::getSourceDetectorsMask(i)) && i != GIndex::ITSAB) {
31 mITSGloSources.push_back(i);
32 }
33 }
34 }
35}
36
38 std::vector<VTIndex>& trackIndex,
39 std::vector<VRef>& vtxRefs)
40{
41 auto vertices = recoData.getPrimaryVertices();
42 auto v2tfitIDs = recoData.getPrimaryVertexContributors();
43 auto v2tfitRefs = recoData.getPrimaryVertexContributorsRefs();
44 const auto& PVParams = o2::vertexing::PVertexerParams::Instance();
45
46 int nv = vertices.size(), nv1 = nv + 1;
47 TmpMap tmpMap(nv1);
48 auto& orphans = tmpMap.back(); // in the last element we store unassigned track indices
49
50 // register vertex contributors
51 std::unordered_map<GIndex, bool> vcont;
52 std::vector<VtxTBracket> vtxOrdBrack; // vertex indices and brackets sorted in tmin
53 float maxVtxSpan = 0;
54 for (int iv = 0; iv < nv; iv++) {
55 int idMin = v2tfitRefs[iv].getFirstEntry(), idMax = idMin + v2tfitRefs[iv].getEntries();
56 auto& vtxIds = tmpMap[iv]; // global IDs of contibuting tracks
57 vtxIds.reserve(v2tfitRefs[iv].getEntries());
58 for (int id = idMin; id < idMax; id++) {
59 auto gid = v2tfitIDs[id];
60 vtxIds.emplace_back(gid).setPVContributor();
61 vcont[gid] = true;
62 }
63 const auto& vtx = vertices[iv];
64 const auto& vto = vtxOrdBrack.emplace_back(VtxTBracket{
65 {float((vtx.getIRMin().differenceInBC(recoData.startIR) - 0.5f) * o2::constants::lhc::LHCBunchSpacingMUS - PVParams.timeMarginVertexTime),
66 float((vtx.getIRMax().differenceInBC(recoData.startIR) + 0.5f) * o2::constants::lhc::LHCBunchSpacingMUS + PVParams.timeMarginVertexTime)},
67 iv});
68 if (vto.tBracket.delta() > maxVtxSpan) {
69 maxVtxSpan = vto.tBracket.delta();
70 }
71 }
72 // sort vertices in tmin
73 std::sort(vtxOrdBrack.begin(), vtxOrdBrack.end(), [](const VtxTBracket& a, const VtxTBracket& b) { return a.tBracket.getMin() < b.tBracket.getMin(); });
74
75 extractTracks(recoData, vcont); // extract all track t-brackets, excluding those tracks which contribute to vertex (already attached)
76
77 int ivStart = 0, nAssigned = 0, nAmbiguous = 0;
78 std::vector<int> vtxList; // list of vertices which match to checked track
79 for (const auto& tro : mTBrackets) {
80 vtxList.clear();
81 for (int iv = ivStart; iv < nv; iv++) {
82 const auto& vto = vtxOrdBrack[iv];
83 auto res = tro.tBracket.isOutside(vto.tBracket);
84 if (res == TBracket::Below) { // vertex preceeds the track
85 if (tro.tBracket.getMin() > vto.tBracket.getMin() + maxVtxSpan) { // all following vertices will be preceeding all following tracks times
86 ivStart = iv + 1;
87 }
88 continue; // following vertex with longer span might still match this track
89 }
90 if (res == TBracket::Above) { // track preceeds the vertex, so will preceed also all following vertices
91 break;
92 }
93 // track matches to vertex, register
94 vtxList.push_back(vto.origID); // flag matching vertex
95 }
96 if (vtxList.size()) {
97 nAssigned++;
98 bool ambig = vtxList.size() > 1;
99 for (auto v : vtxList) {
100 auto& ref = tmpMap[v].emplace_back(tro.origID);
101 if (ambig) {
102 ref.setAmbiguous();
103 }
104 }
105 if (ambig) { // did track match to multiple vertices?
106 nAmbiguous++;
107 }
108 } else {
109 orphans.emplace_back(tro.origID); // register unassigned track
110 }
111 }
112
113 // build final vector of global indices
114 trackIndex.clear();
115 vtxRefs.clear();
116 static size_t logCounter = 0;
117 bool logVertices = mPrescaleLogs > 0 ? (logCounter % mPrescaleLogs) == 0 : true;
118 for (int iv = 0; iv < nv1; iv++) {
119 auto& trvec = tmpMap[iv];
120 // sort entries in each vertex track indices list according to the source
121 std::sort(trvec.begin(), trvec.end(), [](VTIndex a, VTIndex b) { return a.getSource() < b.getSource(); });
122
123 auto entry0 = trackIndex.size(); // start of entries for this vertex
124 auto& vr = vtxRefs.emplace_back();
125 vr.setVtxID(iv < nv ? iv : -1); // flag table for unassigned tracks by VtxID = -1
126 int oldSrc = -1;
127 for (const auto gid0 : trvec) {
128 int src = gid0.getSource();
129 while (oldSrc < src) {
130 oldSrc++;
131 vr.setFirstEntryOfSource(oldSrc, trackIndex.size()); // register start of new source
132 }
133 trackIndex.push_back(gid0);
134 }
135 while (++oldSrc < GIndex::NSources) {
136 vr.setFirstEntryOfSource(oldSrc, trackIndex.size());
137 }
138 vr.setEnd(trackIndex.size());
139
140 if (PVParams.fillITSGloContributors) {
141 auto& ITSGloContributors = vr.getITSGloContributors();
142 ITSGloContributors.setFirstEntry(trackIndex.size());
143 for (auto srcITS : mITSGloSources) {
144 const int fst = vr.getFirstEntryOfSource(srcITS), lst = fst + vr.getEntriesOfSource(srcITS);
145 for (int ii = fst; ii < lst; ii++) {
146 auto vid = trackIndex[ii];
147 if (vid.isPVContributor()) {
148 const auto& trGlo = recoData.getTrackParam(vid);
149 trackIndex.emplace_back(ii == GIndex::ITS ? vid.getIndex() : recoData.getITSContributorGID(vid).getIndex(), trGlo.getPID().getID()); // this is guaranteed ITS track, store PID instead of Source
150 }
151 }
152 }
153 ITSGloContributors.setEntries(trackIndex.size() - ITSGloContributors.getFirstEntry());
154 }
155
156 if (logVertices) {
157 LOG(info) << vr;
158 }
159 }
160 logCounter++;
161 LOG(info) << "Assigned " << nAssigned << " (" << nAmbiguous << " ambiguously) out of " << mTBrackets.size() << " non-contributor tracks + " << vcont.size() << " contributors";
162}
163
164//________________________________________________________
165void VertexTrackMatcher::extractTracks(const o2::globaltracking::RecoContainer& data, const std::unordered_map<GIndex, bool>& vcont)
166{
167 // Scan all inputs and create tracks
168 mTBrackets.clear();
169 float itsBias = 0.5 * mITSROFrameLengthMUS + o2::itsmft::DPLAlpideParam<o2::detectors::DetID::ITS>::Instance().roFrameBiasInBC * o2::constants::lhc::LHCBunchSpacingNS * 1e-3; // ITS time is supplied in \mus as beginning of ROF
170 float mftBias = 0.5 * mMFTROFrameLengthMUS + o2::itsmft::DPLAlpideParam<o2::detectors::DetID::MFT>::Instance().roFrameBiasInBC * o2::constants::lhc::LHCBunchSpacingNS * 1e-3; // MFT time is supplied in \mus as beginning of ROF
171 auto creator = [this, itsBias, mftBias, &vcont](auto& _tr, GIndex _origID, float t0, float terr) {
172 if constexpr (!(isMFTTrack<decltype(_tr)>() || isMCHTrack<decltype(_tr)>() || isGlobalFwdTrack<decltype(_tr)>())) { // Skip test for forward tracks; do not contribute to vertex
173 if (vcont.find(_origID) != vcont.end()) { // track is contributor to vertex, already accounted
174 return true;
175 }
176 }
177 const auto& PVParams = o2::vertexing::PVertexerParams::Instance();
178 if constexpr (isTPCTrack<decltype(_tr)>()) {
179 // unconstrained TPC track, with t0 = TrackTPC.getTime0+0.5*(DeltaFwd-DeltaBwd) and terr = 0.5*(DeltaFwd+DeltaBwd) in TimeBins
180 t0 *= this->mTPCBin2MUS;
181 t0 -= this->mTPCTDriftOffset;
182 terr *= this->mTPCBin2MUS;
183 } else if constexpr (isITSTrack<decltype(_tr)>()) {
184 t0 += itsBias;
185 terr *= this->mITSROFrameLengthMUS; // error is supplied as a half-ROF duration, convert to \mus
186 } else if constexpr (isMFTTrack<decltype(_tr)>()) { // Same for MFT
187 t0 += mftBias;
188 terr *= this->mMFTROFrameLengthMUS;
189 } else if constexpr (!(isMCHTrack<decltype(_tr)>() || isGlobalFwdTrack<decltype(_tr)>())) {
190 // for all other tracks the time is in \mus with gaussian error
191 terr *= PVParams.nSigmaTimeTrack; // gaussian errors must be scaled by requested n-sigma
192 }
193
194 terr += PVParams.timeMarginTrackTime;
195 mTBrackets.emplace_back(TrackTBracket{{t0 - terr, t0 + terr}, _origID});
196
197 if constexpr (isGlobalFwdTrack<decltype(_tr)>() || isMFTTrack<decltype(_tr)>()) {
198 return false;
199 }
200 return true;
201 };
202
203 data.createTracksVariadic(creator);
204
205 // add non-tracks
206 unsigned int cntEMC = 0, cntPHS = 0, cntCPV = 0, cntFT0 = 0, cntFV0 = 0, cntFDD = 0;
207 for (const auto& trig : data.getEMCALTriggers()) {
208 auto t = trig.getBCData().differenceInBCMUS(data.startIR);
209 mTBrackets.emplace_back(TrackTBracket{{t, t}, GIndex{cntEMC++, GIndex::EMC}});
210 }
211 for (const auto& trig : data.getPHOSTriggers()) {
212 auto t = trig.getBCData().differenceInBCMUS(data.startIR);
213 mTBrackets.emplace_back(TrackTBracket{{t, t}, GIndex{cntPHS++, GIndex::PHS}});
214 }
215 for (const auto& trig : data.getPHOSTriggers()) {
216 auto t = trig.getBCData().differenceInBCMUS(data.startIR);
217 mTBrackets.emplace_back(TrackTBracket{{t, t}, GIndex{cntCPV++, GIndex::CPV}});
218 }
219 for (const auto& rec : data.getFT0RecPoints()) {
220 auto t = rec.getInteractionRecord().differenceInBCMUS(data.startIR);
221 mTBrackets.emplace_back(TrackTBracket{{t, t}, GIndex{cntFT0++, GIndex::FT0}});
222 }
223 for (const auto& rec : data.getFV0RecPoints()) {
224 auto t = rec.getInteractionRecord().differenceInBCMUS(data.startIR);
225 mTBrackets.emplace_back(TrackTBracket{{t, t}, GIndex{cntFV0++, GIndex::FV0}});
226 }
227 for (const auto& rec : data.getFDDRecPoints()) {
228 auto t = rec.getInteractionRecord().differenceInBCMUS(data.startIR);
229 mTBrackets.emplace_back(TrackTBracket{{t, t}, GIndex{cntFDD++, GIndex::FDD}});
230 }
231
232 // sort in increasing min.time
233 std::sort(mTBrackets.begin(), mTBrackets.end(), [](const TrackTBracket& a, const TrackTBracket& b) { return a.tBracket.getMin() < b.tBracket.getMin(); });
234
235 LOG(info) << "collected " << mTBrackets.size() << " non-contributor and " << vcont.size() << " contributor seeds";
236}
int32_t i
uint32_t res
Definition RawData.h:0
Wrapper container for different reconstructed object types.
Class for vertex track association.
static constexpr ID ITS
Definition DetID.h:63
void process(const o2::globaltracking::RecoContainer &recoData, std::vector< VTIndex > &trackIndex, std::vector< VRef > &vtxRefs)
std::vector< std::vector< VTIndex > > TmpMap
GLenum src
Definition glcorearb.h:1767
const GLdouble * v
Definition glcorearb.h:832
GLboolean GLboolean GLboolean b
Definition glcorearb.h:1233
GLboolean * data
Definition glcorearb.h:298
GLuint GLfloat GLfloat GLfloat GLfloat GLfloat GLfloat GLfloat t0
Definition glcorearb.h:5034
GLboolean GLboolean GLboolean GLboolean a
Definition glcorearb.h:1233
GLuint id
Definition glcorearb.h:650
constexpr double LHCBunchSpacingMUS
constexpr double LHCBunchSpacingNS
GPUReconstruction * rec
GTrackID getITSContributorGID(GTrackID source) const
const o2::track::TrackParCov & getTrackParam(GTrackID gidx) const
LOG(info)<< "Compressed in "<< sw.CpuTime()<< " s"