Project
Loading...
Searching...
No Matches
TRDGlobalTrackingSpec.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
13
15#include "TRDBase/Geometry.h"
35#include "ITStracking/IOUtils.h"
43
44// GPU header
45#include "GPUReconstruction.h"
46#include "GPUChainTracking.h"
47#include "GPUChainTrackingGetters.inc"
49#include "GPUO2InterfaceUtils.h"
50#include "GPUSettings.h"
51#include "GPUDataTypesIO.h"
52#include "GPUTRDDef.h"
53#include "GPUTRDTrack.h"
54#include "GPUTRDTrackletWord.h"
55#include "GPUTRDInterfaces.h"
56#include "GPUTRDGeometry.h"
57#include "GPUConstantMem.h"
59
60#ifdef ENABLE_UPGRADES
62#endif
63
64#include <regex>
65#include <algorithm>
66#include <numeric>
67
68using namespace o2::framework;
69using namespace o2::gpu;
70using namespace o2::globaltracking;
71using namespace o2::trd::constants;
72
74
75namespace o2
76{
77namespace trd
78{
79
81
83{
85 mTPCCorrMapsLoader.init(ic);
86 mTimer.Stop();
87 mTimer.Reset();
88}
89
90void TRDGlobalTracking::updateTimeDependentParams(ProcessingContext& pc)
91{
93 mTPCVDriftHelper.extractCCDBInputs(pc);
94 mTPCCorrMapsLoader.extractCCDBInputs(pc);
95 // pc.inputs().get<TopologyDictionary*>("cldict"); // called by the RecoContainer to trigger finaliseCCDB
96 static bool initOnceDone = false;
97 if (!initOnceDone) { // this params need to be queried only once
98 initOnceDone = true;
99 // init-once stuff
100
101 auto geo = Geometry::instance();
103 geo->createPadPlaneArray();
104 geo->createClusterMatrixArray();
105 mFlatGeo = std::make_unique<GeometryFlat>(*geo);
106
107 GPURecoStepConfiguration cfgRecoStep;
108 cfgRecoStep.steps = gpudatatypes::RecoStep::NoRecoStep;
109 cfgRecoStep.inputs.clear();
110 cfgRecoStep.outputs.clear();
111 mRec = GPUReconstruction::CreateInstance("CPU", true);
112
114 config.ReadConfigurableParam(config);
116 config.configProcessing.o2PropagatorUseGPUField = false;
117 mRecoParam.init(o2::base::Propagator::Instance()->getNominalBz(), &config.configReconstruction);
118
119 mRec->SetSettings(&config.configGRP, &config.configReconstruction, &config.configProcessing, &cfgRecoStep);
120
121 mChainTracking = mRec->AddChain<GPUChainTracking>();
123
124 mTracker = new GPUTRDTracker();
125 mTracker->SetNCandidates(mRec->GetProcessingSettings().trdNCandidates); // must be set before initialization
126 if (mStrict && mRec->GetProcessingSettings().trdNCandidates == 1) {
127 LOG(error) << "Strict matching mode requested, but tracks with another close hypothesis will not be rejected. Please set trdNCandidates to at least 3.";
128 }
129 mTracker->SetProcessPerTimeFrame(true);
130 mTracker->SetGenerateSpacePoints(false); // set to true to force space point calculation by the TRD tracker itself
131
132 mRec->RegisterGPUProcessor(mTracker, false);
133 mChainTracking->SetTRDGeometry(std::move(mFlatGeo));
134 mChainTracking->SetTRDRecoParam(&mRecoParam);
135 if (mRec->Init()) {
136 LOG(fatal) << "GPUReconstruction could not be initialized";
137 }
138
139 mTracker->PrintSettings();
140 LOG(info) << "Strict matching mode is " << ((mStrict) ? "ON" : "OFF");
141 LOGF(info, "The search road in time for ITS-TPC tracks is set to %.1f sigma and %.2f us are added to it on top",
142 mRec->GetParam().rec.trd.nSigmaTerrITSTPC, mRec->GetParam().rec.trd.addTimeRoadITSTPC);
143
145 if (mWithPID) {
146 mBase = getTRDPIDPolicy(mPolicy);
147 mBase->init(pc);
148 mBase->setLocalGainFactors(pc.inputs().get<o2::trd::LocalGainFactor*>("localgainfactors").get());
149 }
150 }
151 bool updateCalib = false;
152 if (mTPCCorrMapsLoader.isUpdated()) {
153 mTPCCorrMapsLoader.acknowledgeUpdate();
154 updateCalib = true;
155 }
156 const auto& trackTune = TrackTuneParams::Instance();
157 float scale = mTPCCorrMapsLoader.getInstLumiCTP();
158 if (scale < 0.f) {
159 scale = 0.f;
160 }
161 mCovDiagInner = trackTune.getCovInnerTotal(scale);
162 mCovDiagOuter = trackTune.getCovOuterTotal(scale);
163
164 if (mTPCVDriftHelper.isUpdated()) {
166 mTPCTBinMUS = elParam.ZbinWidth;
167 mTPCTBinMUSInv = 1. / mTPCTBinMUS;
168 auto& vd = mTPCVDriftHelper.getVDriftObject();
169 mTPCVdrift = vd.getVDrift();
170 mTPCTDriftOffset = vd.getTimeOffset();
171 LOGP(info, "Updating TPC VDrift factor of {} wrt reference {} and DriftTimeOffset correction {} wrt {} from source {}",
172 vd.corrFact, vd.refVDrift, vd.timeOffsetCorr, vd.refTimeOffset, mTPCVDriftHelper.getSourceName());
173 mTracker->SetTPCVdrift(mTPCVdrift);
174 mTracker->SetTPCTDriftOffset(mTPCTDriftOffset);
175 mTPCVDriftHelper.acknowledgeUpdate();
176 updateCalib = true;
177 }
178 if (updateCalib) {
179 auto& vd = mTPCVDriftHelper.getVDriftObject();
180 mTPCCorrMapsLoader.updateVDrift(vd.corrFact, vd.refVDrift, vd.getTimeOffset());
181 }
182}
183
185{
187 return;
188 }
189 if (mTPCVDriftHelper.accountCCDBInputs(matcher, obj)) {
190 return;
191 }
192 if (mTPCCorrMapsLoader.accountCCDBInputs(matcher, obj)) {
193 return;
194 }
195 if (matcher == ConcreteDataMatcher("ITS", "CLUSDICT", 0)) {
196 LOG(info) << "cluster dictionary updated";
197 mITSDict = (const o2::itsmft::TopologyDictionary*)obj;
198 return;
199 }
200#ifdef ENABLE_UPGRADES
201 if (matcher == ConcreteDataMatcher("IT3", "CLUSDICT", 0)) {
202 LOG(info) << "it3 cluster dictionary updated";
203 mIT3Dict = (const o2::its3::TopologyDictionary*)obj;
204 return;
205 }
206#endif
207}
208
209void TRDGlobalTracking::fillMCTruthInfo(const TrackTRD& trk, o2::MCCompLabel lblSeed, std::vector<o2::MCCompLabel>& lblContainerTrd, std::vector<o2::MCCompLabel>& lblContainerMatch, const o2::dataformats::MCTruthContainer<o2::MCCompLabel>* trkltLabels) const
210{
211 // Check MC labels of the TRD tracklets attached to the track seed.
212 // Set TRD track label to the most frequent tracklet label.
213 // Fake flag is set if either not all TRD tracklets have most frequent label
214 // or if the seeding label is different from the most frequent TRD label.
215 // In case multiple tracklet labels occur most often we choose the one which matches the label of the seed, or,
216 // if that is not the case one of the most frequent labels is chosen arbitrarily
217 LOG(debug) << "Checking seed with label: " << lblSeed;
218 std::unordered_map<o2::MCCompLabel, unsigned int> labelCounter;
219 int maxOccurences = 0;
220 for (int iLy = 0; iLy < constants::NLAYER; ++iLy) {
221 auto trkltIndex = trk.getTrackletIndex(iLy);
222 if (trkltIndex == -1) {
223 // no tracklet in this layer
224 continue;
225 }
226 const auto& lblsTrklt = trkltLabels->getLabels(trkltIndex);
227 for (const auto lblTrklt : lblsTrklt) {
228 int nOcc = ++labelCounter[lblTrklt];
229 if (nOcc > maxOccurences) {
230 maxOccurences = nOcc;
231 }
232 }
233 }
234 o2::MCCompLabel mostFrequentLabel;
235 for (const auto& [lbl, count] : labelCounter) {
236 LOG(debug) << "Label " << lbl << " occured " << count << " times.";
237 if (count == maxOccurences) {
238 if (lblSeed == lbl) {
239 // most frequent label matches seed label
240 mostFrequentLabel = lbl;
241 mostFrequentLabel.setFakeFlag(maxOccurences != trk.getNtracklets());
242 lblContainerTrd.push_back(mostFrequentLabel);
243 lblContainerMatch.push_back(lblSeed); // is not fake by definition, since the seed label matches the TRD track label
244 return;
245 } else {
246 // maybe multiple labels occur with the same frequency and the next one might match the seed?
247 mostFrequentLabel = lbl;
248 }
249 }
250 }
251 mostFrequentLabel.setFakeFlag(maxOccurences != trk.getNtracklets());
252 lblContainerTrd.push_back(mostFrequentLabel);
253 lblSeed.setFakeFlag(lblSeed != mostFrequentLabel);
254 lblContainerMatch.push_back(lblSeed);
255}
256
257void TRDGlobalTracking::fillTrackTriggerRecord(const std::vector<TrackTRD>& tracks, std::vector<TrackTriggerRecord>& trigRec, const gsl::span<const o2::trd::TriggerRecord>& trackletTrigRec) const
258{
259 // after the tracking is done we assemble here a TrackTriggerRecord similar to the TriggerRecord
260 // which for each TRD trigger stores the index of the first found track and the total number of tracks
261
262 int nTracksCurr = 0;
263 int iTrackFirst = 0;
264 int prevCollisionID = -1;
265
266 for (size_t iTrk = 0; iTrk < tracks.size(); ++iTrk) {
267 const auto& trk = tracks[iTrk];
268 auto collisionID = trk.getCollisionId();
269 if (iTrk == 0) {
270 prevCollisionID = collisionID;
271 }
272 if (collisionID != prevCollisionID) {
273 // we have a track from a new trigger within the same TF
274 trigRec.emplace_back(trackletTrigRec[prevCollisionID].getBCData(), iTrackFirst, nTracksCurr);
275 iTrackFirst += nTracksCurr;
276 prevCollisionID = collisionID;
277 nTracksCurr = 0;
278 }
279 ++nTracksCurr;
280 }
281 if (nTracksCurr > 0) {
282 // this is the last trigger record for this TF, we can take the collision ID from the last track
283 trigRec.emplace_back(trackletTrigRec[tracks.back().getCollisionId()].getBCData(), iTrackFirst, nTracksCurr);
284 }
285}
286
288{
289 mTimer.Start(false);
291 inputTracks.collectData(pc, *mDataRequest);
292 updateTimeDependentParams(pc);
293 mChainTracking->ClearIOPointers();
294
295 mTPCClusterIdxStruct = &inputTracks.inputsTPCclusters->clusterIndex;
296 mTPCRefitter = std::make_unique<o2::gpu::GPUO2InterfaceRefit>(mTPCClusterIdxStruct, &mTPCCorrMapsLoader, o2::base::Propagator::Instance()->getNominalBz(), inputTracks.getTPCTracksClusterRefs().data(), 0, inputTracks.clusterShMapTPC.data(), inputTracks.occupancyMapTPC.data(), inputTracks.occupancyMapTPC.size(), nullptr, o2::base::Propagator::Instance());
297 mTPCRefitter->setTrackReferenceX(900); // disable propagation after refit by setting reference to value > 500
298 auto tmpInputContainer = getRecoInputContainer(pc, &mChainTracking->mIOPtrs, &inputTracks, mUseMC);
299 auto tmpContainer = GPUWorkflowHelper::fillIOPtr(mChainTracking->mIOPtrs, inputTracks, mUseMC, nullptr, GTrackID::getSourcesMask("TRD"), mTrkMask, GTrackID::mask_t{GTrackID::MASK_NONE});
300 mTrackletsRaw = inputTracks.getTRDTracklets();
301 mTrackletsCalib = inputTracks.getTRDCalibratedTracklets();
302 mTPCTracksArray = inputTracks.getTPCTracks();
303 if (GTrackID::includesDet(GTrackID::DetID::ITS, mTrkMask)) {
304 // load ITS tracks and clusters needed for the refit
305 mITSTracksArray = inputTracks.getITSTracks();
306 mITSTrackClusIdx = inputTracks.getITSTracksClusterRefs();
307 mITSABRefsArray = inputTracks.getITSABRefs();
308 mITSABTrackClusIdx = inputTracks.getITSABClusterRefs();
309 const auto clusITS = inputTracks.getITSClusters();
310 const auto patterns = inputTracks.getITSClustersPatterns();
311 auto pattIt = patterns.begin();
312 mITSClustersArray.clear();
313 mITSClustersArray.reserve(clusITS.size());
314#ifdef ENABLE_UPGRADES
315 if (o2::GlobalParams::Instance().withITS3) {
316 o2::its3::ioutils::convertCompactClusters(clusITS, pattIt, mITSClustersArray, mIT3Dict);
317 } else {
318 o2::its::ioutils::convertCompactClusters(clusITS, pattIt, mITSClustersArray, mITSDict);
319 }
320#else
321 o2::its::ioutils::convertCompactClusters(clusITS, pattIt, mITSClustersArray, mITSDict);
322#endif
323 }
324
325 LOGF(info, "There are %i tracklets in total from %i trigger records", mChainTracking->mIOPtrs.nTRDTracklets, mChainTracking->mIOPtrs.nTRDTriggerRecords);
326 LOGF(info, "As input seeds are available: %i ITS-TPC matched tracks and %i TPC tracks", mChainTracking->mIOPtrs.nTracksTPCITSO2, mChainTracking->mIOPtrs.nOutputTracksTPCO2);
327
328 std::vector<o2::MCCompLabel> matchLabelsITSTPC;
329 std::vector<o2::MCCompLabel> trdLabelsITSTPC;
330 std::vector<o2::MCCompLabel> matchLabelsTPC;
331 std::vector<o2::MCCompLabel> trdLabelsTPC;
332 gsl::span<const o2::MCCompLabel> tpcTrackLabels;
333 gsl::span<const o2::MCCompLabel> itstpcTrackLabels;
334 if (mUseMC) {
335 if (GTrackID::includesSource(GTrackID::Source::ITSTPC, mTrkMask)) {
336 itstpcTrackLabels = inputTracks.getTPCITSTracksMCLabels();
337 }
338 if (GTrackID::includesSource(GTrackID::Source::TPC, mTrkMask)) {
339 tpcTrackLabels = inputTracks.getTPCTracksMCLabels();
340 }
341 }
342 mTracker->Reset();
343 mRec->PrepareEvent();
344 mRec->SetupGPUProcessor(mTracker, true);
345
346 // check trigger record filter setting
347 bool foundFilteredTrigger = false;
348 for (unsigned int iTrig = 0; iTrig < mChainTracking->mIOPtrs.nTRDTriggerRecords; ++iTrig) {
349 if (mChainTracking->mIOPtrs.trdTrigRecMask[iTrig] == 0) {
350 foundFilteredTrigger = true;
351 }
352 LOGF(debug, "TRD trigger %u added with time %f", iTrig, mChainTracking->mIOPtrs.trdTriggerTimes[iTrig]);
353 }
354 if (!foundFilteredTrigger && mTrigRecFilter) {
355 static bool warningSent = false;
356 if (!warningSent) {
357 LOG(warning) << "Trigger filtering requested, but no TRD trigger is actually masked. Can be that none needed to be masked or that the setting was not active for the tracklet transformer";
358 warningSent = true;
359 }
360 } else if (foundFilteredTrigger && !mTrigRecFilter) {
361 LOG(error) << "Trigger filtering is not requested, but masked TRD triggers are found. Rerun tracklet transformer without trigger filtering";
362 }
363
364 // load input tracks
365 const auto& trackTune = TrackTuneParams::Instance();
366 LOG(debug) << "Start loading input seeds into TRD tracker";
367 int nTracksLoadedITSTPC = 0;
368 int nTracksLoadedTPC = 0;
369 // load ITS-TPC matched tracks
370 for (unsigned int iTrk = 0; iTrk < mChainTracking->mIOPtrs.nTracksTPCITSO2; ++iTrk) {
371 const auto& trkITSTPC = mChainTracking->mIOPtrs.tracksTPCITSO2[iTrk];
372 GPUTRDTracker::HelperTrackAttributes trkAttribs;
373 trkAttribs.mTime = trkITSTPC.getTimeMUS().getTimeStamp();
374 trkAttribs.mTimeAddMax = trkITSTPC.getTimeMUS().getTimeStampError() * mRec->GetParam().rec.trd.nSigmaTerrITSTPC + mRec->GetParam().rec.trd.addTimeRoadITSTPC;
375 trkAttribs.mTimeSubMax = trkITSTPC.getTimeMUS().getTimeStampError() * mRec->GetParam().rec.trd.nSigmaTerrITSTPC + mRec->GetParam().rec.trd.addTimeRoadITSTPC;
376 GPUTRDTrack trkLoad(trkITSTPC);
377 // no TrackTuneParams for outerParam of ITS-TPC tracks: if needed, they are corrected already in the ITS-TPC matching refit
378 auto trackGID = GTrackID(iTrk, GTrackID::ITSTPC);
379 if (mTracker->LoadTrack(trkLoad, trackGID.getRaw(), true, &trkAttribs)) {
380 continue;
381 }
382 ++nTracksLoadedITSTPC;
383 LOGF(debug, "Loaded ITS-TPC track %i with time %f. Window from %f to %f", nTracksLoadedITSTPC, trkAttribs.mTime, trkAttribs.mTime - trkAttribs.mTimeSubMax, trkAttribs.mTime + trkAttribs.mTimeAddMax);
384 }
385 // load TPC-only tracks
386 for (unsigned int iTrk = 0; iTrk < mChainTracking->mIOPtrs.nOutputTracksTPCO2; ++iTrk) {
387 if (mChainTracking->mIOPtrs.tpcLinkITS && mChainTracking->mIOPtrs.tpcLinkITS[iTrk] != -1) {
388 // this TPC tracks has already been matched to ITS and the ITS-TPC track has already been loaded in the tracker
389 continue;
390 }
391 const auto& trkTpc = mChainTracking->mIOPtrs.outputTracksTPCO2[iTrk];
392 GPUTRDTracker::HelperTrackAttributes trkAttribs;
393 trkAttribs.mTime = trkTpc.getTime0() * mTPCTBinMUS - mTPCTDriftOffset; // account for the eventual time bias for TPC tracks time
394 trkAttribs.mTimeAddMax = trkTpc.getDeltaTFwd() * mTPCTBinMUS;
395 trkAttribs.mTimeSubMax = trkTpc.getDeltaTBwd() * mTPCTBinMUS;
396 if (trkTpc.hasASideClustersOnly()) {
397 trkAttribs.mSide = -1;
398 } else if (trkTpc.hasCSideClustersOnly()) {
399 trkAttribs.mSide = 1;
400 }
401 GPUTRDTrack trkLoad(trkTpc);
402 if (!trackTune.sourceLevelTPC) { // correct TPC tracks only if they were not corrected on the source level
403 if (trackTune.useTPCOuterCorr) {
404 trkLoad.updateParams(trackTune.tpcParOuter);
405 }
406 if (trackTune.tpcCovOuterType != TrackTuneParams::AddCovType::Disable) {
407 trkLoad.updateCov(mCovDiagOuter, trackTune.tpcCovOuterType == TrackTuneParams::AddCovType::WithCorrelations);
408 }
409 }
410 auto trackGID = GTrackID(iTrk, GTrackID::TPC);
411 if (mTracker->LoadTrack(trkLoad, trackGID.getRaw(), true, &trkAttribs)) {
412 continue;
413 }
414 ++nTracksLoadedTPC;
415 LOGF(debug, "Loaded TPC track %i with time %f. Window from %f to %f", nTracksLoadedTPC, trkAttribs.mTime, trkAttribs.mTime - trkAttribs.mTimeSubMax, trkAttribs.mTime + trkAttribs.mTimeAddMax);
416 }
417 LOGF(info, "%i tracks are loaded into the TRD tracker. Out of those %i ITS-TPC tracks and %i TPC tracks", nTracksLoadedITSTPC + nTracksLoadedTPC, nTracksLoadedITSTPC, nTracksLoadedTPC);
418
419 // start the tracking
420 // mTracker->DumpTracks();
421 mChainTracking->DoTRDGPUTracking<GPUTRDTrackerKernels::o2Version>(mTracker);
422 // mTracker->DumpTracks();
423
424 // finished tracking, now collect the output
425 std::vector<TrackTRD> tracksOutITSTPC;
426 std::vector<TrackTRD> tracksOutTPC;
427 std::vector<TrackTriggerRecord> trackTrigRecITSTPC;
428 std::vector<TrackTriggerRecord> trackTrigRecTPC;
429 GPUTRDTrack* tracksOutRaw = mTracker->Tracks();
430 std::vector<unsigned int> trackIdxArray(mTracker->NTracks()); // track indices sorted by trigger record index
431 std::iota(trackIdxArray.begin(), trackIdxArray.end(), 0);
432 std::sort(trackIdxArray.begin(), trackIdxArray.end(), [tracksOutRaw](int lhs, int rhs) { return tracksOutRaw[lhs].getCollisionId() < tracksOutRaw[rhs].getCollisionId(); });
433
434 std::vector<std::pair<uint8_t, uint8_t>> pileUpDist;
435 bool ft0Seen = false;
436 if (mTrkMask[GTrackID::FT0]) { // pile-up tagging was requested
437 long maxDiffFwd = mTracker->Param().rec.trd.pileupFwdNBC;
438 long maxDiffBwd = mTracker->Param().rec.trd.pileupBwdNBC;
439 auto ft0recPoints = inputTracks.getFT0RecPoints();
440 auto trdTriggers = tmpInputContainer->mTriggerRecords;
441 ft0Seen = ft0recPoints.size() > 0;
442 pileUpDist.resize(trdTriggers.size(), {0, 0});
443 size_t curFT0 = 0;
444 for (size_t itrd = 0; itrd < trdTriggers.size(); itrd++) {
445 const auto& trig = trdTriggers[itrd];
446 uint8_t fwd = 0, bwd = 0;
447 for (size_t ft0id = curFT0; ft0id < ft0recPoints.size(); ft0id++) {
448 const auto& f0rec = ft0recPoints[ft0id];
449 if (o2::ft0::InteractionTag::Instance().isSelected(f0rec)) {
450 auto bcdiff = trig.getBCData().toLong() - f0rec.getInteractionRecord().toLong();
451 if (bcdiff > maxDiffBwd) {
452 curFT0 = ft0id + 1;
453 continue;
454 }
455 if (bcdiff > 0) { // pre-trigger pileup, maxDiffBwd is guaranteed to be < max uint8_t
456 if (bwd == 0) {
457 bwd = uint8_t(bcdiff);
458 }
459 } else {
460 if (bcdiff < -maxDiffFwd) {
461 break;
462 }
463 fwd = uint8_t(-bcdiff); // post-trigger pileup, maxDiffFwd is guaranteed to be < max uint8_t
464 }
465 }
466 }
467 pileUpDist[itrd] = {bwd, fwd};
468 }
469 }
470
471 int nTrackletsAttached = 0; // only used for debug information
472 int nTracksFailedTPCTRDRefit = 0;
473 int nTracksFailedITSTPCTRDRefit = 0;
474 for (int iTrk = 0; iTrk < mTracker->NTracks(); ++iTrk) {
475 const auto& trdTrack = mTracker->Tracks()[trackIdxArray[iTrk]];
476 if (trdTrack.getCollisionId() < 0) {
477 // skip tracks without TRD tracklets (the collision ID for the TRD tracks is initialized to -1 and only changed if a tracklet is attached to the track)
478 continue;
479 }
480 if (mStrict && (trdTrack.getIsAmbiguous() || trdTrack.getReducedChi2() > mTracker->Param().rec.trd.chi2StrictCut)) {
481 // skip tracks which have another hypothesis close to the best one or which do are above strict chi2 threshold
482 continue;
483 }
484 if (trdTrack.getNtracklets() < mTracker->Param().rec.trd.nTrackletsMin) {
485 continue;
486 }
487 if (trdTrack.getChi2() / trdTrack.getNtracklets() > mTracker->Param().rec.trd.maxChi2Red) {
488 continue;
489 }
490 nTrackletsAttached += trdTrack.getNtracklets();
491 auto trackGID = trdTrack.getRefGlobalTrackId();
492 if (trackGID.includesDet(GTrackID::Source::ITS)) {
493 // this track is from an ITS-TPC seed
494 tracksOutITSTPC.push_back(trdTrack);
495 if (ft0Seen) {
496 tracksOutITSTPC.back().setPileUpDistance(pileUpDist[trdTrack.getCollisionId()].first, pileUpDist[trdTrack.getCollisionId()].second);
497 } else {
498 tracksOutITSTPC.back().setPileUpDistance(mTracker->Param().rec.trd.pileupBwdNBC, mTracker->Param().rec.trd.pileupFwdNBC);
499 }
500 if (!refitITSTPCTRDTrack(tracksOutITSTPC.back(), mChainTracking->mIOPtrs.trdTriggerTimes[trdTrack.getCollisionId()], &inputTracks) || std::isnan(tracksOutITSTPC.back().getSnp())) {
501 tracksOutITSTPC.pop_back();
502 ++nTracksFailedITSTPCTRDRefit;
503 continue;
504 }
505 if (mUseMC) {
506 fillMCTruthInfo(trdTrack, itstpcTrackLabels[trackGID], trdLabelsITSTPC, matchLabelsITSTPC, inputTracks.getTRDTrackletsMCLabels());
507 }
508 if (mWithPID) {
509 tracksOutITSTPC.back().setSignal(mBase->process(trdTrack, inputTracks, false));
510 }
511 } else {
512 // this track is from a TPC-only seed
513 tracksOutTPC.push_back(trdTrack);
514 if (ft0Seen) {
515 tracksOutTPC.back().setPileUpDistance(pileUpDist[trdTrack.getCollisionId()].first, pileUpDist[trdTrack.getCollisionId()].second);
516 } else {
517 tracksOutTPC.back().setPileUpDistance(mTracker->Param().rec.trd.pileupBwdNBC, mTracker->Param().rec.trd.pileupFwdNBC);
518 }
519 if (!refitTPCTRDTrack(tracksOutTPC.back(), mChainTracking->mIOPtrs.trdTriggerTimes[trdTrack.getCollisionId()], &inputTracks) || std::isnan(tracksOutTPC.back().getSnp())) {
520 tracksOutTPC.pop_back();
521 ++nTracksFailedTPCTRDRefit;
522 continue;
523 }
524 if (mUseMC) {
525 fillMCTruthInfo(trdTrack, tpcTrackLabels[trackGID], trdLabelsTPC, matchLabelsTPC, inputTracks.getTRDTrackletsMCLabels());
526 }
527 if (mWithPID) {
528 tracksOutTPC.back().setSignal(mBase->process(trdTrack, inputTracks, true));
529 }
530 }
531 }
532
533 fillTrackTriggerRecord(tracksOutITSTPC, trackTrigRecITSTPC, tmpInputContainer->mTriggerRecords);
534 fillTrackTriggerRecord(tracksOutTPC, trackTrigRecTPC, tmpInputContainer->mTriggerRecords);
535
536 LOGF(info, "The TRD tracker found %lu tracks from TPC seeds and %lu tracks from ITS-TPC seeds and attached in total %i tracklets out of %i",
537 tracksOutTPC.size(), tracksOutITSTPC.size(), nTrackletsAttached, mChainTracking->mIOPtrs.nTRDTracklets);
538 LOGF(info, "Number of tracks failed in the refit: TPC-TRD (%i), ITS-TPC-TRD (%i)", nTracksFailedTPCTRDRefit, nTracksFailedITSTPCTRDRefit);
539
540 uint32_t ss = o2::globaltracking::getSubSpec(mStrict ? o2::globaltracking::MatchingType::Strict : o2::globaltracking::MatchingType::Standard);
541 if (GTrackID::includesSource(GTrackID::Source::ITSTPC, mTrkMask)) {
542 pc.outputs().snapshot(Output{o2::header::gDataOriginTRD, "MATCH_ITSTPC", 0}, tracksOutITSTPC);
543 pc.outputs().snapshot(Output{o2::header::gDataOriginTRD, "TRGREC_ITSTPC", 0}, trackTrigRecITSTPC);
544 if (mUseMC) {
545 pc.outputs().snapshot(Output{o2::header::gDataOriginTRD, "MCLB_ITSTPC", 0}, matchLabelsITSTPC);
546 pc.outputs().snapshot(Output{o2::header::gDataOriginTRD, "MCLB_ITSTPC_TRD", 0}, trdLabelsITSTPC);
547 }
548 }
549 if (GTrackID::includesSource(GTrackID::Source::TPC, mTrkMask)) {
550 pc.outputs().snapshot(Output{o2::header::gDataOriginTRD, "MATCH_TPC", ss}, tracksOutTPC);
551 pc.outputs().snapshot(Output{o2::header::gDataOriginTRD, "TRGREC_TPC", ss}, trackTrigRecTPC);
552 if (mUseMC) {
553 pc.outputs().snapshot(Output{o2::header::gDataOriginTRD, "MCLB_TPC", ss}, matchLabelsTPC);
554 pc.outputs().snapshot(Output{o2::header::gDataOriginTRD, "MCLB_TPC_TRD", ss}, trdLabelsTPC);
555 }
556 }
557
558 static bool first = true;
559 if (first) {
560 first = false;
561 if (pc.services().get<const o2::framework::DeviceSpec>().inputTimesliceId == 0) {
563 }
564 }
565
566 mTimer.Stop();
567}
568
570{
571 auto propagator = o2::base::Propagator::Instance();
572
573 // refit ITS-TPC-TRD track outwards to outermost TRD space point (start with ITS outer track parameters)
574 auto& outerParam = trk.getOuterParam();
575 auto detRefs = recoCont->getSingleDetectorRefs(trk.getRefGlobalTrackId());
576 int nCl = -1, clEntry = -1, nClRefit = 0, clRefs[14];
577 float chi2Out = 0, timeZErr = 0.;
578 bool pileUpOn = trk.hasPileUpInfo(); // distance to farthest collision within the pileup integration time is set
580 auto matCorr = o2::base::Propagator::MatCorrType(mRec->GetParam().rec.trd.matCorrType);
581 if (detRefs[GTrackID::ITS].isIndexSet()) { // this is ITS track
582 const auto& trkITS = mITSTracksArray[detRefs[GTrackID::ITS]];
583 outerParam = trkITS.getParamOut();
584 outerParam.setPID(recoCont->getTPCITSTrack(trk.getRefGlobalTrackId()).getPID(), true);
585 nCl = trkITS.getNumberOfClusters();
586 clEntry = trkITS.getFirstClusterEntry();
587 chi2Out = trkITS.getChi2();
588 for (int icl = 0; icl < nCl; icl++) { // clusters are stored from outer to inner layers
589 clRefs[icl] = mITSTrackClusIdx[clEntry + icl]; // from outer to inner layer
590 }
591 } else { // this is ITS-AB track, will need to refit including the ITS part
592 const auto& trkITSABref = mITSABRefsArray[detRefs[GTrackID::ITSAB]];
593 nCl = trkITSABref.getNClusters();
594 clEntry = trkITSABref.getFirstEntry();
595 outerParam = recoCont->getTPCITSTrack(trk.getRefGlobalTrackId()); // start from the inner kinematics of ITS-TPC, no need to set PID, will be transferred from ITSTPC track
596 outerParam.resetCovariance(100); // reset covariance to something big
597 // refit
598 for (int icl = 0; icl < nCl; icl++) { // clusters are stored from inner to outer layers
599 const auto& clus = mITSClustersArray[clRefs[nCl - icl - 1] = mITSABTrackClusIdx[clEntry + icl]]; // register in clRefs from outer to inner layer
600 if (!outerParam.rotate(geom->getSensorRefAlpha(clus.getSensorID())) ||
601 !propagator->propagateToX(outerParam, clus.getX(), propagator->getNominalBz(), o2::base::Propagator::MAX_SIN_PHI, o2::base::Propagator::MAX_STEP, matCorr)) {
602 break;
603 }
604 chi2Out += outerParam.getPredictedChi2(clus);
605 if (!outerParam.update(clus)) {
606 break;
607 }
608 nClRefit++;
609 }
610 if (nClRefit != nCl) {
611 LOG(debug) << "ITS-AB refit outward failed";
612 return false;
613 }
614 }
615 // propagate to TPC inner boundary
616 float xtogo = 0;
617 if (!outerParam.getXatLabR(o2::constants::geom::XTPCInnerRef, xtogo, propagator->getNominalBz(), o2::track::DirOutward) ||
618 !propagator->PropagateToXBxByBz(outerParam, xtogo, o2::base::Propagator::MAX_SIN_PHI, o2::base::Propagator::MAX_STEP, matCorr)) {
619 LOG(debug) << "Propagation to inner TPC boundary X=" << xtogo << " failed, Xtr=" << outerParam.getX() << " snp=" << outerParam.getSnp();
620 return false;
621 }
622 int retVal = mTPCRefitter->RefitTrackAsTrackParCov(outerParam, mTPCTracksArray[detRefs[GTrackID::TPC]].getClusterRef(), timeTRD * mTPCTBinMUSInv, &chi2Out, true, false); // outward refit
623 if (retVal < 0) {
624 LOG(debug) << "TPC refit outwards failed";
625 return false;
626 }
627
628 if (!refitTRDTrack(trk, chi2Out, false, false)) {
629 LOG(debug) << "TRD refit outwards failed";
630 return false;
631 }
632 // refit ITS-TPC-TRD track inwards to innermost ITS cluster
633 // here we also calculate the LT integral for matching to TOF
634 float chi2In = 0.f;
635 if (!refitTRDTrack(trk, chi2In, true, false)) {
636 LOG(debug) << "TRD refit inwards failed";
637 return false;
638 }
639 auto posStart = trk.getXYZGlo();
640 retVal = mTPCRefitter->RefitTrackAsTrackParCov(trk, mTPCTracksArray[detRefs[GTrackID::TPC]].getClusterRef(), timeTRD * mTPCTBinMUSInv, &chi2In, false, false); // inward refit
641 if (retVal < 0) {
642 LOG(debug) << "TPC refit inwards failed";
643 return false;
644 }
645 // if for some reason the track was overshoot over the inner field cage, bring it back w/o material correction and LTintegral update
646 if (trk.getX() < o2::constants::geom::XTPCInnerRef &&
647 !propagator->PropagateToXBxByBz(trk, o2::constants::geom::XTPCInnerRef, o2::base::Propagator::MAX_SIN_PHI, o2::base::Propagator::MAX_STEP, o2::base::Propagator::MatCorrType::USEMatCorrNONE)) {
648 LOG(debug) << "BACK-Propagationto inner boundary failed";
649 return false;
650 }
651 auto posEnd = trk.getXYZGlo();
652 auto lInt = propagator->estimateLTIncrement(trk, posStart, posEnd);
653 trk.getLTIntegralOut().addStep(lInt, trk.getQ2P2());
654 // trk.getLTIntegralOut().addX2X0(lInt * mTPCmeanX0Inv); // do we need to account for the material budget here? probably
655
656 const auto& trackTune = TrackTuneParams::Instance();
657 if (trackTune.tpcCovInnerType != TrackTuneParams::AddCovType::Disable || trackTune.useTPCInnerCorr) { // if needed, correct TPC track in the middle of TPC->ITS refit
658 if (!propagator->PropagateToXBxByBz(trk, o2::constants::geom::XTPCInnerRef, o2::base::Propagator::MAX_SIN_PHI, o2::base::Propagator::MAX_STEP, matCorr, &trk.getLTIntegralOut())) {
659 LOG(debug) << "Propagation to TPC inner reference X for ITS refit inwards failed";
660 return false;
661 }
662 if (!trackTune.useTPCInnerCorr) {
663 trk.updateParams(trackTune.tpcParInner);
664 }
665 if (trackTune.tpcCovInnerType != TrackTuneParams::AddCovType::Disable) {
666 trk.updateCov(mCovDiagInner, trackTune.tpcCovInnerType == TrackTuneParams::AddCovType::WithCorrelations);
667 }
668 }
669
670 nClRefit = 0;
671 for (int icl = 0; icl < nCl; icl++) {
672 const auto& clus = mITSClustersArray[clRefs[icl]];
673 if (!trk.rotate(geom->getSensorRefAlpha(clus.getSensorID())) ||
674 // note: here we also calculate the L,T integral (in the inward direction, but this is irrelevant)
675 // note: we should eventually use TPC pid in the refit (TODO)
676 // note: since we are at small R, we can use field BZ component at origin rather than 3D field
677 !propagator->propagateToX(trk, clus.getX(), propagator->getNominalBz(), o2::base::Propagator::MAX_SIN_PHI, o2::base::Propagator::MAX_STEP, matCorr, &trk.getLTIntegralOut())) {
678 break;
679 }
680 chi2In += trk.getPredictedChi2(clus);
681 if (!trk.update(clus)) {
682 break;
683 }
684 nClRefit++;
685 }
686 if (nClRefit != nCl) {
687 LOG(debug) << "ITS refit inwards failed";
688 return false;
689 }
690 // We need to update the LTOF integral by the distance to the "primary vertex"
691 // We want to leave the track at the the position of its last update, so we do a fast propagation on the TrackPar copy of trfit,
692 // and since for the LTOF calculation the material effects are irrelevant, we skip material corrections
693 const o2::dataformats::VertexBase vtxDummy; // at the moment using dummy vertex: TODO use MeanVertex constraint instead
694 o2::track::TrackPar trkPar(trk);
695 if (!propagator->propagateToDCA(vtxDummy.getXYZ(), trkPar, propagator->getNominalBz(), o2::base::Propagator::MAX_STEP, matCorr, nullptr, &trk.getLTIntegralOut())) {
696 LOG(error) << "LTOF integral might be incorrect";
697 }
698 return true;
699}
700
702{
703 auto propagator = o2::base::Propagator::Instance();
704 auto matCorr = o2::base::Propagator::MatCorrType(mRec->GetParam().rec.trd.matCorrType);
705 // refit TPC-TRD track outwards toward outermost TRD space point
706 auto& outerParam = trk.getOuterParam();
707 auto detRefs = recoCont->getSingleDetectorRefs(trk.getRefGlobalTrackId());
708 outerParam = trk;
709 float chi2Out = 0, timeZErr = 0.;
710 bool pileUpOn = trk.hasPileUpInfo(); // distance to farthest collision within the pileup integration time is set
711 int retVal = mTPCRefitter->RefitTrackAsTrackParCov(outerParam, mTPCTracksArray[detRefs[GTrackID::TPC]].getClusterRef(), timeTRD * mTPCTBinMUSInv, &chi2Out, true, false); // outward refit
712 if (retVal < 0) {
713 LOG(debug) << "TPC refit outwards failed";
714 return false;
715 }
716 if (pileUpOn) { // account pileup time uncertainty in Z errors
717 timeZErr = mTPCVdrift * trk.getPileUpTimeErrorMUS();
718 outerParam.updateCov(timeZErr, o2::track::CovLabels::kSigZ2);
719 }
720 if (!refitTRDTrack(trk, chi2Out, false, true)) {
721 LOG(debug) << "TRD refit outwards failed";
722 return false;
723 }
724
725 // refit TPC-TRD track inwards toward inner TPC radius
726 float chi2In = 0.f;
727 if (!refitTRDTrack(trk, chi2In, true, true)) {
728 LOG(debug) << "TRD refit inwards failed";
729 return false;
730 }
731 auto posStart = trk.getXYZGlo();
732 retVal = mTPCRefitter->RefitTrackAsTrackParCov(trk, mTPCTracksArray[detRefs[GTrackID::TPC]].getClusterRef(), timeTRD * mTPCTBinMUSInv, &chi2In, false, false); // inward refit
733 if (retVal < 0) {
734 LOG(debug) << "TPC refit inwards failed";
735 return false;
736 }
737 if (pileUpOn) { // account pileup time uncertainty in Z errors
738 trk.updateCov(timeZErr, o2::track::CovLabels::kSigZ2);
739 }
740 // if for some reason the track was overshoot over the inner field cage, bring it back w/o material correction and LTintegral update
741 if (trk.getX() < o2::constants::geom::XTPCInnerRef &&
742 !propagator->PropagateToXBxByBz(trk, o2::constants::geom::XTPCInnerRef, o2::base::Propagator::MAX_SIN_PHI, o2::base::Propagator::MAX_STEP, o2::base::Propagator::MatCorrType::USEMatCorrNONE)) {
743 LOG(debug) << "BACK-Propagationto inner boundary failed";
744 return false;
745 }
746 auto posEnd = trk.getXYZGlo();
747 auto lInt = propagator->estimateLTIncrement(trk, posStart, posEnd);
748 trk.getLTIntegralOut().addStep(lInt, trk.getQ2P2());
749 // trk.getLTIntegralOut().addX2X0(lInt * mTPCmeanX0Inv); // do we need to account for the material budget here? probably?
750
751 if (!propagator->PropagateToXBxByBz(trk, o2::constants::geom::XTPCInnerRef, o2::base::Propagator::MAX_SIN_PHI, o2::base::Propagator::MAX_STEP, matCorr, &trk.getLTIntegralOut())) {
752 LOG(debug) << "Final propagation to inner TPC radius failed (not removing the track because of this)";
753 }
754
755 const auto& trackTune = TrackTuneParams::Instance(); // if needed, correct the track after inward TPC refit
756 if (!trackTune.useTPCInnerCorr) {
757 trk.updateParams(trackTune.tpcParInner);
758 }
759 if (trackTune.tpcCovInnerType != TrackTuneParams::AddCovType::Disable) {
760 trk.updateCov(mCovDiagInner, trackTune.tpcCovInnerType == TrackTuneParams::AddCovType::WithCorrelations);
761 }
762
763 propagator->estimateLTFast(trk.getLTIntegralOut(), trk); // guess about initial value for the track integral from the origin
764 return true;
765}
766
767bool TRDGlobalTracking::refitTRDTrack(TrackTRD& trk, float& chi2, bool inwards, bool tpcSA)
768{
769 auto propagator = o2::base::Propagator::Instance();
770
771 int lyStart = inwards ? NLAYER - 1 : 0;
772 int direction = inwards ? -1 : 1;
773 int lyEnd = inwards ? -1 : NLAYER;
774 o2::track::TrackParCov* trkParam = nullptr;
775 o2::track::TrackLTIntegral* tofL = nullptr;
776 auto matCorr = o2::base::Propagator::MatCorrType(mRec->GetParam().rec.trd.matCorrType);
777
778 if (inwards) {
779 trkParam = &trk;
780 tofL = &trk.getLTIntegralOut();
781 } else {
782 trkParam = &trk.getOuterParam();
783 trkParam->setUserField(trk.getUserField()); // pileup timing info
784
785 const auto& trackTune = TrackTuneParams::Instance();
786 if ((trackTune.useTPCOuterCorr || trackTune.tpcCovOuterType != TrackTuneParams::AddCovType::Disable) &&
787 (!tpcSA || !trackTune.sourceLevelTPC)) { // for TPC standalone make sure correction was not applied ad the source level
788 if (!propagator->PropagateToXBxByBz(*trkParam, o2::constants::geom::XTPCOuterRef, o2::base::Propagator::MAX_SIN_PHI, o2::base::Propagator::MAX_STEP, matCorr)) {
789 LOG(debug) << "Propagation to TPC outer reference X for TRD outward refit failed";
790 return false;
791 }
792 if (trackTune.useTPCOuterCorr) {
793 trkParam->updateParams(trackTune.tpcParOuter);
794 }
795 if (trackTune.tpcCovOuterType != TrackTuneParams::AddCovType::Disable) {
796 trkParam->updateCov(mCovDiagOuter, trackTune.tpcCovOuterType == TrackTuneParams::AddCovType::WithCorrelations);
797 }
798 }
799 }
800
801 if (inwards) {
802 // reset covariance to something big for inwards refit
803 trkParam->resetCovariance(100);
804 }
805 for (int iLy = lyStart; iLy != lyEnd; iLy += direction) {
806 int trkltId = trk.getTrackletIndex(iLy);
807 if (trkltId < 0) {
808 continue;
809 }
810 int trkltDet = mTrackletsRaw[trkltId].getDetector();
811 int trkltSec = trkltDet / (NLAYER * NSTACK);
812 if (trkltSec != o2::math_utils::angle2Sector(trkParam->getAlpha())) {
813 if (!trkParam->rotate(o2::math_utils::sector2Angle(trkltSec))) {
814 LOGF(debug, "Track at alpha=%.2f could not be rotated in tracklet coordinate system with alpha=%.2f", trkParam->getAlpha(), o2::math_utils::sector2Angle(trkltSec));
815 return false;
816 }
817 }
818 if (!propagator->PropagateToXBxByBz(*trkParam, mTrackletsCalib[trkltId].getX(), o2::base::Propagator::MAX_SIN_PHI, o2::base::Propagator::MAX_STEP, matCorr, tofL)) {
819 LOGF(debug, "Track propagation failed in layer %i (pt=%f, xTrk=%f, xToGo=%f)", iLy, trkParam->getPt(), trkParam->getX(), mTrackletsCalib[trkltId].getX());
820 return false;
821 }
822 const PadPlane* pad = Geometry::instance()->getPadPlane(trkltDet);
823 float tilt = tan(TMath::DegToRad() * pad->getTiltingAngle()); // tilt is signed! and returned in degrees
824 float tiltCorrUp = tilt * (mTrackletsCalib[trkltId].getZ() - trkParam->getZ());
825 float zPosCorrUp = mTrackletsCalib[trkltId].getZ() + mRecoParam.getZCorrCoeffNRC() * trkParam->getTgl();
826 float padLength = pad->getRowSize(mTrackletsRaw[trkltId].getPadRow());
827 if (!((trkParam->getSigmaZ2() < (padLength * padLength / 12.f)) && (std::fabs(mTrackletsCalib[trkltId].getZ() - trkParam->getZ()) < padLength))) {
828 tiltCorrUp = 0.f;
829 }
830
831 std::array<float, 2> trkltPosUp{mTrackletsCalib[trkltId].getY() - tiltCorrUp, zPosCorrUp};
832 std::array<float, 3> trkltCovUp;
833 mRecoParam.recalcTrkltCov(tilt, trkParam->getSnp(), pad->getRowSize(mTrackletsRaw[trkltId].getPadRow()), trkltCovUp);
834
835 chi2 += trkParam->getPredictedChi2(trkltPosUp, trkltCovUp);
836 if (!trkParam->update(trkltPosUp, trkltCovUp)) {
837 LOGF(debug, "Failed to update track with space point in layer %i", iLy);
838 return false;
839 }
840 }
841 if (!inwards) { // to make sure that the inward fit will start from the trkParam
842 ((o2::track::TrackParCov&)trk) = *trkParam;
843 } else { // propagate to the TPC outer reference
844 if (!propagator->PropagateToXBxByBz(*trkParam, o2::constants::geom::XTPCOuterRef, o2::base::Propagator::MAX_SIN_PHI, o2::base::Propagator::MAX_STEP, matCorr, tofL)) {
845 LOG(debug) << "Propagation to TPC outer reference X after TRD inward refit failed";
846 return false;
847 }
848 // make sure we are in the correct sector
849 int sector = o2::math_utils::angle2Sector(trkParam->getPhiPos());
850 if (sector != o2::math_utils::angle2Sector(trkParam->getAlpha()) &&
851 !trkParam->rotate(o2::math_utils::sector2Angle(sector)) &&
852 !propagator->PropagateToXBxByBz(*trkParam, o2::constants::geom::XTPCOuterRef, o2::base::Propagator::MAX_SIN_PHI, o2::base::Propagator::MAX_STEP, matCorr, tofL)) {
853 LOG(debug) << "Propagation/rotation to TPC outer reference X after TRD inward refit failed " << trkParam->asString();
854 return false;
855 }
856 }
857 return true;
858}
859
861{
862 LOGF(info, "TRD global tracking total timing: Cpu: %.3e Real: %.3e s in %d slots",
863 mTimer.CpuTime(), mTimer.RealTime(), mTimer.Counter() - 1);
864}
865
866DataProcessorSpec getTRDGlobalTrackingSpec(bool useMC, GTrackID::mask_t src, bool trigRecFilterActive, bool strict, bool withPID, PIDPolicy policy, const o2::tpc::CorrectionMapsLoaderGloOpts& sclOpts)
867{
868 std::vector<OutputSpec> outputs;
869 uint32_t ss = o2::globaltracking::getSubSpec(strict ? o2::globaltracking::MatchingType::Strict : o2::globaltracking::MatchingType::Standard);
870 std::shared_ptr<DataRequest> dataRequest = std::make_shared<DataRequest>();
871 if (strict) {
872 dataRequest->setMatchingInputStrict();
873 }
874 auto trkSrc = src;
875 trkSrc |= GTrackID::getSourcesMask("TPC");
876 dataRequest->requestClusters(GTrackID::getSourcesMask("TRD"), useMC);
877 dataRequest->requestTPCClusters(false); // only needed for refit, don't care about labels
878 if (GTrackID::includesSource(GTrackID::Source::ITSTPC, src)) {
879 // ITS clusters are only needed if we match to ITS-TPC tracks
880#ifdef ENABLE_UPGRADES
881 if (o2::GlobalParams::Instance().withITS3) {
882 dataRequest->requestIT3Clusters(false); // only needed for refit, don't care about labels
883 } else {
884 dataRequest->requestITSClusters(false); // only needed for refit, don't care about labels
885 }
886#else
887 dataRequest->requestITSClusters(false); // only needed for refit, don't care about labels
888#endif
889 trkSrc |= GTrackID::getSourcesMask("ITS");
890 }
891 dataRequest->requestTracks(trkSrc, useMC);
892 auto& inputs = dataRequest->inputs;
893 auto ggRequest = std::make_shared<o2::base::GRPGeomRequest>(false, // orbitResetTime
894 false, // GRPECS=true
895 false, // GRPLHCIF
896 true, // GRPMagField
897 true, // askMatLUT
899 inputs,
900 true);
902 Options opts;
904
905 // Request PID policy data
906 if (withPID) {
907 // request policy
908 switch (policy) {
909 case PIDPolicy::LQ1D:
910 inputs.emplace_back("lq1dlut", "TRD", "LQ1D", 0, Lifetime::Condition, ccdbParamSpec("TRD/PID/LQ1D"));
911 break;
912 case PIDPolicy::LQ2D:
913 inputs.emplace_back("lq2dlut", "TRD", "LQ2D", 0, Lifetime::Condition, ccdbParamSpec("TRD/PID/LQ2D"));
914 break;
915 case PIDPolicy::LQ3D:
916 inputs.emplace_back("lq3dlut", "TRD", "LQ3D", 0, Lifetime::Condition, ccdbParamSpec("TRD/PID/LQ3D"));
917 break;
918#ifdef TRDPID_WITH_ONNX
919 case PIDPolicy::XGB:
920 inputs.emplace_back("xgb", "TRD", "XGB", 0, Lifetime::Condition, ccdbParamSpec("TRD_test/PID_new/xgb"));
921 break;
922 case PIDPolicy::PY:
923 inputs.emplace_back("py", "TRD", "py", 0, Lifetime::Condition, ccdbParamSpec("TRD_test/PID_new/py"));
924 break;
925#endif
926 case PIDPolicy::Dummy:
927 break;
928 default:
929 throw std::runtime_error("Unable to load requested PID policy data!");
930 }
931 // request calibration data
932 inputs.emplace_back("localgainfactors", "TRD", "LOCALGAINFACTORS", 0, Lifetime::Condition, ccdbParamSpec("TRD/Calib/LocalGainFactor"));
933 }
934
935 if (GTrackID::includesSource(GTrackID::Source::ITSTPC, src)) {
936 outputs.emplace_back(o2::header::gDataOriginTRD, "MATCH_ITSTPC", 0, Lifetime::Timeframe);
937 outputs.emplace_back(o2::header::gDataOriginTRD, "TRGREC_ITSTPC", 0, Lifetime::Timeframe);
938 if (useMC) {
939 outputs.emplace_back(o2::header::gDataOriginTRD, "MCLB_ITSTPC", 0, Lifetime::Timeframe);
940 outputs.emplace_back(o2::header::gDataOriginTRD, "MCLB_ITSTPC_TRD", 0, Lifetime::Timeframe);
941 }
942 if (withPID) {
943 outputs.emplace_back(o2::header::gDataOriginTRD, "TRDPID_ITSTPC", 0, Lifetime::Timeframe);
944 }
945 }
946 if (GTrackID::includesSource(GTrackID::Source::TPC, src)) {
947 outputs.emplace_back(o2::header::gDataOriginTRD, "MATCH_TPC", ss, Lifetime::Timeframe);
948 outputs.emplace_back(o2::header::gDataOriginTRD, "TRGREC_TPC", ss, Lifetime::Timeframe);
949 if (useMC) {
950 outputs.emplace_back(o2::header::gDataOriginTRD, "MCLB_TPC", ss, Lifetime::Timeframe);
951 outputs.emplace_back(o2::header::gDataOriginTRD, "MCLB_TPC_TRD", ss, Lifetime::Timeframe);
952 }
953 if (trigRecFilterActive) {
954 LOG(info) << "Matching to TPC-only tracks requested, but IRs without ITS contribution are filtered out (used strict matching mode to constrain TPC tracks before matching to ITS)";
955 }
956 }
957
958 std::string processorName = o2::utils::Str::concat_string("trd-globaltracking", GTrackID::getSourcesNames(src));
959 std::regex reg("[,\\[\\]]+");
960 processorName = regex_replace(processorName, reg, "_");
961
962 return DataProcessorSpec{
963 processorName,
964 inputs,
965 outputs,
966 AlgorithmSpec{adaptFromTask<TRDGlobalTracking>(useMC, withPID, policy, dataRequest, ggRequest, sclOpts, src, trigRecFilterActive, strict)},
967 opts};
968}
969
970} // namespace trd
971} // namespace o2
Definition of the ITS/MFT clusterer settings.
o2d::GlobalTrackID GTrackID
Definition of the ITSMFT cluster.
Global TRD definitions and constants.
Definition of the Names Generator class.
Definition of the GeometryManager class.
std::ostringstream debug
Definition of the FIT RecPoints class.
int32_t retVal
TRD Tracklet word for GPU tracker - 32bit tracklet info + half chamber ID + index.
Some ALICE geometry constants of common interest.
Definition of the GeometryTGeo class.
Definition of the parameter class for the detector electronics.
Declarations of the helper class for clusters / roadwidth matching.
Struct for input data required by TRD tracking workflow.
class to create TPC fast transformation
Result of refitting TPC-ITS matched track.
Configurable params for tracks ad hoc tuning.
Helper class to obtain TPC clusters / digits / labels from DPL.
void clear()
Definition bitfield.h:54
void setFakeFlag(bool v=true)
void checkUpdates(o2::framework::ProcessingContext &pc)
static GRPGeomHelper & instance()
void setRequest(std::shared_ptr< GRPGeomRequest > req)
static std::string getConfigOutputFileName(const std::string &procName, const std::string &confName="", bool json=true)
Definition NameConf.cxx:115
static constexpr float MAX_SIN_PHI
Definition Propagator.h:72
static constexpr float MAX_STEP
Definition Propagator.h:73
GPUd() value_type estimateLTFast(o2 static GPUd() float estimateLTIncrement(const o2 PropagatorImpl * Instance(bool uninitialized=false)
Definition Propagator.h:178
static void write(std::string const &filename, std::string const &keyOnly="")
static mask_t getSourcesMask(const std::string_view srcList)
static std::string getSourcesNames(mask_t srcm)
A container to hold and manage MC truth information/labels.
gsl::span< TruthElement > getLabels(uint32_t dataindex)
void snapshot(const Output &spec, T const &object)
decltype(auto) get(R binding, int part=0) const
DataAllocator & outputs()
The data allocator is used to allocate memory for the output data.
InputRecord & inputs()
The inputs associated with this processing context.
ServiceRegistryRef services()
The services registry associated with this processing context.
void SetTRDGeometry(std::unique_ptr< o2::trd::GeometryFlat > &&geo)
void SetO2Propagator(const o2::base::Propagator *prop)
void SetTRDRecoParam(std::unique_ptr< GPUTRDRecoParam > &&par)
int32_t DoTRDGPUTracking(T *externalInstance=nullptr)
GPUTrackingInOutPointers & mIOPtrs
static float getNominalGPUBz(T &src)
void SetupGPUProcessor(T *proc, bool allocate)
void RegisterGPUProcessor(T *proc, bool deviceSlave)
void SetSettings(float solenoidBzNominalGPU, const GPURecoStepConfiguration *workflow=nullptr)
static GPUReconstruction * CreateInstance(const GPUSettingsDeviceBackend &cfg)
const GPUParam & GetParam() const
const GPUSettingsProcessing & GetProcessingSettings() const
void init(float bz, const GPUSettingsRec *rec=nullptr)
Load parameterization for given magnetic field.
void SetNCandidates(int32_t n)
static std::shared_ptr< const tmpDataContainer > fillIOPtr(GPUTrackingInOutPointers &ioPtr, const o2::globaltracking::RecoContainer &recoCont, bool useMC, const GPUCalibObjectsConst *calib=nullptr, GID::mask_t maskCl=GID::MASK_ALL, GID::mask_t maskTrk=GID::MASK_ALL, GID::mask_t maskMatch=GID::MASK_ALL)
static GeometryTGeo * Instance()
void fillMatrixCache(int mask) override
void extractCCDBInputs(o2::framework::ProcessingContext &pc)
void updateVDrift(float vdriftCorr, float vdrifRef, float driftTimeOffset=0)
bool accountCCDBInputs(const o2::framework::ConcreteDataMatcher &matcher, void *obj)
static void requestCCDBInputs(std::vector< o2::framework::InputSpec > &inputs, std::vector< o2::framework::ConfigParamSpec > &options, const CorrectionMapsLoaderGloOpts &gloOpts)
void init(o2::framework::InitContext &ic)
static void requestCCDBInputs(std::vector< o2::framework::InputSpec > &inputs, bool laser=true, bool itstpcTgl=true)
void extractCCDBInputs(o2::framework::ProcessingContext &pc, bool laser=true, bool itstpcTgl=true)
const VDriftCorrFact & getVDriftObject() const
bool accountCCDBInputs(const o2::framework::ConcreteDataMatcher &matcher, void *obj)
static std::string_view getSourceName(Source s)
bool isUpdated() const
static Geometry * instance()
Definition Geometry.h:33
void fillMCTruthInfo(const TrackTRD &trk, o2::MCCompLabel lblSeed, std::vector< o2::MCCompLabel > &lblContainerTrd, std::vector< o2::MCCompLabel > &lblContainerMatch, const o2::dataformats::MCTruthContainer< o2::MCCompLabel > *trkltLabels) const
void finaliseCCDB(o2::framework::ConcreteDataMatcher &matcher, void *obj) final
void endOfStream(o2::framework::EndOfStreamContext &ec) final
This is invoked whenever we have an EndOfStream event.
void run(o2::framework::ProcessingContext &pc) final
bool refitTRDTrack(TrackTRD &trk, float &chi2, bool inwards, bool tpcSA)
void init(o2::framework::InitContext &ic) final
bool refitITSTPCTRDTrack(TrackTRD &trk, float timeTRD, o2::globaltracking::RecoContainer *recoCont)
void fillTrackTriggerRecord(const std::vector< TrackTRD > &tracks, std::vector< TrackTriggerRecord > &trigRec, const gsl::span< const o2::trd::TriggerRecord > &trackletTrigRec) const
bool refitTPCTRDTrack(TrackTRD &trk, float timeTRD, o2::globaltracking::RecoContainer *recoCont)
GLenum src
Definition glcorearb.h:1767
GLint GLsizei count
Definition glcorearb.h:399
constexpr o2::header::DataOrigin gDataOriginTRD
Definition DataHeader.h:577
constexpr float XTPCOuterRef
reference radius to propagate outer TPC track
constexpr float XTPCInnerRef
reference radius at which TPC provides the tracks
Defining PrimaryVertex explicitly as messageable.
std::vector< ConfigParamSpec > ccdbParamSpec(std::string const &path, int runDependent, std::vector< CCDBMetadata > metadata={}, int qrate=0)
std::vector< ConfigParamSpec > Options
GPUTRDTracker_t< GPUTRDTrack, GPUTRDPropagator > GPUTRDTracker
Definition GPUTRDDef.h:58
void convertCompactClusters(gsl::span< const itsmft::CompClusterExt > clusters, gsl::span< const unsigned char >::iterator &pattIt, std::vector< o2::BaseCluster< float > > &output, const its3::TopologyDictionary *dict)
convert compact clusters to 3D spacepoints
Definition IOUtils.cxx:30
void convertCompactClusters(gsl::span< const itsmft::CompClusterExt > clusters, gsl::span< const unsigned char >::iterator &pattIt, std::vector< o2::BaseCluster< float > > &output, const itsmft::TopologyDictionary *dict)
convert compact clusters to 3D spacepoints
Definition IOUtils.cxx:35
int angle2Sector(float phi)
Definition Utils.h:183
float sector2Angle(int sect)
Definition Utils.h:193
TrackParCovF TrackParCov
Definition Track.h:33
constexpr int NLAYER
the number of layers
Definition Constants.h:27
constexpr int NSTACK
the number of stacks per sector
Definition Constants.h:26
std::unique_ptr< PIDBase > getTRDPIDPolicy(PIDPolicy policy)
Factory function to create a PID policy.
Definition PIDBase.cxx:63
PIDPolicy
Option for available PID policies.
Definition PID.h:29
@ LQ3D
3-Dimensional Likelihood model
@ LQ2D
2-Dimensional Likelihood model
@ Dummy
Dummy object outputting -1.f.
@ LQ1D
1-Dimensional Likelihood model
auto getRecoInputContainer(o2::framework::ProcessingContext &pc, o2::gpu::GPUTrackingInOutPointers *ptrs, const o2::globaltracking::RecoContainer *inputTracks, bool mc=false)
framework::DataProcessorSpec getTRDGlobalTrackingSpec(bool useMC, o2::dataformats::GlobalTrackID::mask_t src, bool trigRecFilterActive, bool strict, bool withPID, PIDPolicy policy, const o2::tpc::CorrectionMapsLoaderGloOpts &sclOpts)
create a processor spec
a couple of static helper functions to create timestamp values for CCDB queries or override obsolete ...
std::string name
The name of the associated DataProcessorSpec.
Definition DeviceSpec.h:50
GlobalIDSet getSingleDetectorRefs(GTrackID gidx) const
gsl::span< const o2::trd::CalibratedTracklet > getTRDCalibratedTracklets() const
const o2::dataformats::MCTruthContainer< o2::MCCompLabel > * getTRDTrackletsMCLabels() const
gsl::span< const unsigned char > clusterShMapTPC
externally set TPC clusters sharing map
const o2::dataformats::TrackTPCITS & getTPCITSTrack(GTrackID gid) const
void collectData(o2::framework::ProcessingContext &pc, const DataRequest &request)
std::unique_ptr< o2::tpc::internal::getWorkflowTPCInput_ret > inputsTPCclusters
gsl::span< const unsigned int > occupancyMapTPC
externally set TPC clusters occupancy map
gsl::span< const o2::trd::Tracklet64 > getTRDTracklets() const
gpudatatypes::RecoStepField steps
gpudatatypes::InOutTypeField inputs
gpudatatypes::InOutTypeField outputs
const o2::dataformats::TrackTPCITS * tracksTPCITSO2
const o2::tpc::TrackTPC * outputTracksTPCO2
static constexpr int T2L
Definition Cartesian.h:55
static constexpr int T2GRot
Definition Cartesian.h:57
static std::string concat_string(Ts const &... ts)
LOG(info)<< "Compressed in "<< sw.CpuTime()<< " s"