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