Project
Loading...
Searching...
No Matches
TrackingStudy.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
12#include <vector>
13#include <TStopwatch.h>
46#include "GPUO2InterfaceRefit.h"
47#include "GPUO2Interface.h" // Needed for propper settings in GPUParam.h
48#include "GPUParam.h"
49#include "GPUParam.inc"
50#include "GPUTPCGeometry.h"
52#include "MathUtils/fit.h"
53#include <TF1.h>
54
55namespace o2::trackstudy
56{
57
58using namespace o2::framework;
61
67
69
70class TrackingStudySpec : public Task
71{
72 public:
73 TrackingStudySpec(std::shared_ptr<DataRequest> dr, std::shared_ptr<o2::base::GRPGeomRequest> gr, GTrackID::mask_t src, bool useMC, const o2::tpc::CorrectionMapsLoaderGloOpts& sclOpts)
74 : mDataRequest(dr), mGGCCDBRequest(gr), mTracksSrc(src), mUseMC(useMC)
75 {
76 mTPCCorrMapsLoader.setLumiScaleType(sclOpts.lumiType);
77 mTPCCorrMapsLoader.setLumiScaleMode(sclOpts.lumiMode);
78 mTPCCorrMapsLoader.setCheckCTPIDCConsistency(sclOpts.checkCTPIDCconsistency);
79 }
80 ~TrackingStudySpec() final = default;
81 void init(InitContext& ic) final;
82 void run(ProcessingContext& pc) final;
83 void endOfStream(EndOfStreamContext& ec) final;
84 void finaliseCCDB(ConcreteDataMatcher& matcher, void* obj) final;
85 void process(o2::globaltracking::RecoContainer& recoData);
86
87 private:
88 void updateTimeDependentParams(ProcessingContext& pc);
89 float getDCAYCut(float pt) const;
90 float getDCAZCut(float pt) const;
91 std::shared_ptr<DataRequest> mDataRequest;
92 std::shared_ptr<o2::base::GRPGeomRequest> mGGCCDBRequest;
93 o2::tpc::VDriftHelper mTPCVDriftHelper{};
94 o2::tpc::CorrectionMapsLoader mTPCCorrMapsLoader{};
95 bool mUseMC{false};
96 std::unique_ptr<o2::utils::TreeStreamRedirector> mDBGOut;
97 std::unique_ptr<o2::utils::TreeStreamRedirector> mDBGOutVtx;
98 std::unique_ptr<o2::gpu::GPUO2InterfaceRefit> mTPCRefitter;
99 std::vector<float> mMltHistTB, mTBinClOccAft, mTBinClOccBef, mTBinClOccWgh;
100 std::unique_ptr<TF1> mOccWghFun;
101 float mITSROFrameLengthMUS = 0.f;
102 float mTPCTBinMUS = 0.f; // TPC bin in microseconds
103 float mTPCTBinMUSInv = 0.f;
104 int mMaxNeighbours = 3;
105 float mMaxVTTimeDiff = 80.; // \mus
106 float mTPCDCAYCut = 2.;
107 float mTPCDCAZCut = 2.;
108 float mMinX = 46.;
109 float mMaxEta = 0.8;
110 float mMinPt = 0.1;
111 int mNOccBinsDrift = 10;
112 int mMinTPCClusters = 60;
113 int mNTPCOccBinLength = 0;
114 int mNHBPerTF = 0;
115 float mNTPCOccBinLengthInv;
116 bool mStoreWithITSOnly = false;
117 bool mDoPairsCorr = false;
118 std::string mDCAYFormula = "0.0105 + 0.0350 / pow(x, 1.1)";
119 std::string mDCAZFormula = "0.0105 + 0.0350 / pow(x, 1.1)";
120 GTrackID::mask_t mTracksSrc{};
122 o2::steer::MCKinematicsReader mcReader; // reader of MC information
123};
124
126{
128 mTPCCorrMapsLoader.init(ic);
129 int lane = ic.services().get<const o2::framework::DeviceSpec>().inputTimesliceId;
130 int maxLanes = ic.services().get<const o2::framework::DeviceSpec>().maxInputTimeslices;
131 std::string dbgnm = maxLanes == 1 ? "trackStudy.root" : fmt::format("trackStudy_{}.root", lane);
132 mDBGOut = std::make_unique<o2::utils::TreeStreamRedirector>(dbgnm.c_str(), "recreate");
133 dbgnm = maxLanes == 1 ? "trackStudyVtx.root" : fmt::format("trackStudyVtx_{}.root", lane);
134 mDBGOutVtx = std::make_unique<o2::utils::TreeStreamRedirector>(dbgnm.c_str(), "recreate");
135 mStoreWithITSOnly = ic.options().get<bool>("with-its-only");
136 mMaxVTTimeDiff = ic.options().get<float>("max-vtx-timediff");
137 mMaxNeighbours = ic.options().get<int>("max-vtx-neighbours");
138 mTPCDCAYCut = ic.options().get<float>("max-tpc-dcay");
139 mTPCDCAZCut = ic.options().get<float>("max-tpc-dcaz");
140 mMinX = ic.options().get<float>("min-x-prop");
141 mMaxEta = ic.options().get<float>("max-eta");
142 mMinPt = ic.options().get<float>("min-pt");
143 mMinTPCClusters = ic.options().get<int>("min-tpc-clusters");
144 mDCAYFormula = ic.options().get<std::string>("dcay-vs-pt");
145 mDCAZFormula = ic.options().get<std::string>("dcaz-vs-pt");
146 mDoPairsCorr = ic.options().get<bool>("pair-correlations");
147 mNOccBinsDrift = ic.options().get<int>("noccbins");
148 if (mNOccBinsDrift < 3) {
149 mNOccBinsDrift = 3;
150 }
151 auto str = ic.options().get<std::string>("occ-weight-fun");
152 if (!str.empty()) {
153 mOccWghFun = std::make_unique<TF1>("occFun", str.c_str(), -100., 100.);
154 }
155}
156
158{
160 recoData.collectData(pc, *mDataRequest.get()); // select tracks of needed type, with minimal cuts, the real selected will be done in the vertexer
161 updateTimeDependentParams(pc); // Make sure this is called after recoData.collectData, which may load some conditions
162 if (recoData.inputsTPCclusters) {
163 mTPCRefitter = std::make_unique<o2::gpu::GPUO2InterfaceRefit>(&recoData.inputsTPCclusters->clusterIndex, &mTPCCorrMapsLoader, o2::base::Propagator::Instance()->getNominalBz(),
164 recoData.getTPCTracksClusterRefs().data(), 0, recoData.clusterShMapTPC.data(), recoData.occupancyMapTPC.data(),
165 recoData.occupancyMapTPC.size(), nullptr, o2::base::Propagator::Instance());
166 mTPCRefitter->setTrackReferenceX(900); // disable propagation after refit by setting reference to value > 500
167 mNTPCOccBinLength = mTPCRefitter->getParam()->rec.tpc.occupancyMapTimeBins;
168 mTBinClOccBef.clear();
169 mTBinClOccAft.clear();
170 mTBinClOccWgh.clear();
171 }
172
173 // prepare TPC occupancy data
174 if (mNTPCOccBinLength > 1 && recoData.occupancyMapTPC.size()) {
175 mNTPCOccBinLengthInv = 1. / mNTPCOccBinLength;
176 int nTPCBins = mNHBPerTF * o2::constants::lhc::LHCMaxBunches / 8, ninteg = 0;
177 int nTPCOccBins = nTPCBins * mNTPCOccBinLengthInv, sumBins = std::max(1, int(o2::constants::lhc::LHCMaxBunches / 8 * mNTPCOccBinLengthInv));
178 mTBinClOccAft.resize(nTPCOccBins);
179 mTBinClOccBef.resize(nTPCOccBins);
180 float sm = 0., tb = 0.5 * mNTPCOccBinLength;
181 mMltHistTB.resize(nTPCOccBins);
182 for (int i = 0; i < nTPCOccBins; i++) {
183 mMltHistTB[i] = mTPCRefitter->getParam()->GetUnscaledMult(tb);
184 tb += mNTPCOccBinLength;
185 }
186 for (int i = nTPCOccBins; i--;) {
187 sm += mMltHistTB[i];
188 if (i + sumBins < nTPCOccBins) {
189 sm -= mMltHistTB[i + sumBins];
190 }
191 mTBinClOccAft[i] = sm;
192 }
193 sm = 0;
194 for (int i = 0; i < nTPCOccBins; i++) {
195 sm += mMltHistTB[i];
196 if (i - sumBins > 0) {
197 sm -= mMltHistTB[i - sumBins];
198 }
199 mTBinClOccBef[i] = sm;
200 }
201 } else {
202 mTBinClOccBef.resize(1);
203 mTBinClOccAft.resize(1);
204 }
205
206 process(recoData);
207}
208
209void TrackingStudySpec::updateTimeDependentParams(ProcessingContext& pc)
210{
212 mTPCVDriftHelper.extractCCDBInputs(pc);
213 mTPCCorrMapsLoader.extractCCDBInputs(pc);
214 static bool initOnceDone = false;
215 if (!initOnceDone) { // this params need to be queried only once
216 initOnceDone = true;
217 // Note: reading of the ITS AlpideParam needed for ITS timing is done by the RecoContainer
220 if (!grp->isDetContinuousReadOut(DetID::ITS)) {
221 mITSROFrameLengthMUS = alpParams.roFrameLengthTrig / 1.e3; // ITS ROFrame duration in \mus
222 } else {
223 mITSROFrameLengthMUS = alpParams.roFrameLengthInBC * o2::constants::lhc::LHCBunchSpacingNS * 1e-3; // ITS ROFrame duration in \mus
224 }
226 mNHBPerTF = o2::base::GRPGeomHelper::instance().getGRPECS()->getNHBFPerTF();
228 mTPCTBinMUS = elParam.ZbinWidth; // TPC bin in microseconds
229 mTPCTBinMUSInv = 1. / mTPCTBinMUS;
230 }
231 bool updateMaps = false;
232 if (mTPCCorrMapsLoader.isUpdated()) {
233 mTPCCorrMapsLoader.acknowledgeUpdate();
234 updateMaps = true;
235 }
236 if (mTPCVDriftHelper.isUpdated()) {
237 LOGP(info, "Updating TPC fast transform map with new VDrift factor of {} wrt reference {} and DriftTimeOffset correction {} wrt {} from source {}",
238 mTPCVDriftHelper.getVDriftObject().corrFact, mTPCVDriftHelper.getVDriftObject().refVDrift,
239 mTPCVDriftHelper.getVDriftObject().timeOffsetCorr, mTPCVDriftHelper.getVDriftObject().refTimeOffset,
240 mTPCVDriftHelper.getSourceName());
241 mTPCVDriftHelper.acknowledgeUpdate();
242 updateMaps = true;
243 }
244 if (updateMaps) {
245 mTPCCorrMapsLoader.updateVDrift(mTPCVDriftHelper.getVDriftObject().corrFact, mTPCVDriftHelper.getVDriftObject().refVDrift, mTPCVDriftHelper.getVDriftObject().getTimeOffset());
246 }
247}
248
250{
251 auto pvvec = recoData.getPrimaryVertices();
252 auto trackIndex = recoData.getPrimaryVertexMatchedTracks(); // Global ID's for associated tracks
253 auto vtxRefs = recoData.getPrimaryVertexMatchedTrackRefs(); // references from vertex to these track IDs
254 auto prop = o2::base::Propagator::Instance();
255 auto FITInfo = recoData.getFT0RecPoints();
256 static int TFCount = 0;
257 int nv = vtxRefs.size();
259 o2::dataformats::PrimaryVertexExt vtxDummy(mMeanVtx.getPos(), {}, {}, 0);
260 std::vector<o2::dataformats::PrimaryVertexExt> pveVec(nv);
261 std::vector<float> tpcOccAftV, tpcOccBefV;
262 pveVec.back() = vtxDummy;
264 float tBiasITS = alpParams.roFrameBiasInBC * o2::constants::lhc::LHCBunchSpacingMUS;
266 std::vector<o2::dataformats::TrackInfoExt> trcExtVec;
267 std::vector<o2::trackstudy::TrackPairInfo> trcPairsVec;
268 auto vdrift = mTPCVDriftHelper.getVDriftObject().getVDrift();
269 float maxDriftTB = 250.f / vdrift / (o2::constants::lhc::LHCBunchSpacingMUS * 8);
270 int groupOcc = std::ceil(maxDriftTB / mNOccBinsDrift / mNTPCOccBinLength);
271
272 bool tpcTrackOK = recoData.isTrackSourceLoaded(GTrackID::TPC);
273
274 auto fillTPCClInfo = [&recoData, this](const o2::tpc::TrackTPC& trc, o2::dataformats::TrackInfoExt& trExt, float timestampTB = -1e9) {
275 const auto clRefs = recoData.getTPCTracksClusterRefs();
276 const auto tpcClusAcc = recoData.getTPCClusters();
277 const auto shMap = recoData.clusterShMapTPC;
278
279 if (recoData.inputsTPCclusters) {
280 uint8_t clSect = 0, clRow = 0, lowestR = -1;
281 uint32_t clIdx = 0;
282 for (int ic = 0; ic < trc.getNClusterReferences(); ic++) { // outside -> inside ordering, but on the sector boundaries backward jumps are possible
283 trc.getClusterReference(clRefs, ic, clSect, clRow, clIdx);
284 if (clRow < lowestR) {
285 trExt.rowCountTPC++;
286 lowestR = clRow;
287 }
288 unsigned int absoluteIndex = tpcClusAcc.clusterOffset[clSect][clRow] + clIdx;
289 if (shMap[absoluteIndex] & o2::gpu::GPUTPCGMMergedTrackHit::flagShared) {
290 trExt.nClTPCShared++;
291 }
292 }
293 trExt.rowMinTPC = lowestR;
294 const auto& clus = tpcClusAcc.clusters[clSect][clRow][clIdx];
295 trExt.padFromEdge = uint8_t(clus.getPad());
296 int npads = o2::gpu::GPUTPCGeometry::NPads(lowestR);
297 if (trExt.padFromEdge > npads / 2) {
298 trExt.padFromEdge = npads - 1 - trExt.padFromEdge;
299 }
300 this->mTPCCorrMapsLoader.Transform(clSect, clRow, clus.getPad(), clus.getTime(), trExt.innerTPCPos0[0], trExt.innerTPCPos0[1], trExt.innerTPCPos0[2], trc.getTime0()); // nominal time of the track
301 if (timestampTB > -1e8) {
302 this->mTPCCorrMapsLoader.Transform(clSect, clRow, clus.getPad(), clus.getTime(), trExt.innerTPCPos[0], trExt.innerTPCPos[1], trExt.innerTPCPos[2], timestampTB); // time assigned from the global track track
303 } else {
304 trExt.innerTPCPos = trExt.innerTPCPos0;
305 }
306 trc.getClusterReference(clRefs, 0, clSect, clRow, clIdx);
307 trExt.rowMaxTPC = clRow;
308 }
309 };
310
311 auto getTPCPairSharing = [&recoData, this](const o2::tpc::TrackTPC& trc0, const o2::tpc::TrackTPC& trc1) {
312 const auto clRefs = recoData.getTPCTracksClusterRefs();
313 uint8_t nsh = 0, nshRows = 0, lastSharedRow = -1;
314 if (recoData.inputsTPCclusters) {
315 uint8_t clSect0 = 0, clRow0 = 0, clSect1 = 0, clRow1 = 0;
316 uint32_t clIdx0 = 0, clIdx1 = 0;
317 int ic1Start = 0;
318 for (int ic0 = 0; ic0 < trc0.getNClusterReferences(); ic0++) { // outside -> inside, but on the sector boundaries backward jumps are possible
319 trc0.getClusterReference(clRefs, ic0, clSect0, clRow0, clIdx0);
320 for (int ic1 = ic1Start; ic1 < trc1.getNClusterReferences(); ic1++) { // outside -> inside, but on the sector boundaries backward jumps are possible
321 trc1.getClusterReference(clRefs, ic1, clSect1, clRow1, clIdx1);
322 if (clRow1 > clRow0) {
323 ic1Start = ic1 + 1;
324 continue; // catch up ic0
325 }
326 if (clRow1 == clRow0) {
327 if (clSect0 == clSect1 && clIdx0 == clIdx1) {
328 nsh++;
329 if (lastSharedRow != clRow0) {
330 lastSharedRow = clRow0;
331 nshRows++;
332 }
333 ic1Start = ic1 + 1;
334 break; // check next ic0
335 }
336 }
337 }
338 }
339 }
340 return std::make_pair(nsh, nshRows);
341 };
342
343 auto assignRecTrack = [&recoData, this](const o2::dataformats::TrackInfoExt& src, o2::trackstudy::RecTrack& dst) {
344 dst.track = src.track;
345 dst.gid = src.gid;
346 dst.ts.setTimeStamp(src.ttime);
347 dst.ts.setTimeStampError(src.ttimeE);
348 dst.nClITS = src.nClITS;
349 dst.nClTPC = src.nClTPC;
350 dst.pattITS = src.pattITS;
351 if (src.q2ptITS == 0. && dst.nClITS > 0) {
352 dst.pattITS |= 0x1 << 7;
353 }
354 dst.lowestPadRow = src.rowMinTPC;
355 if (this->mUseMC) {
356 auto gidSet = recoData.getSingleDetectorRefs(src.gid);
357 if (recoData.getTrackMCLabel(src.gid).isFake()) {
358 dst.flags |= RecTrack::FakeGLO;
359 }
360 auto msk = src.gid.getSourceDetectorsMask();
361 if (msk[DetID::ITS]) {
362 if (gidSet[GTrackID::ITS].isSourceSet()) { // has ITS track rather than AB tracklet
363 auto lblITS = recoData.getTrackMCLabel(gidSet[GTrackID::ITS]);
364 if (lblITS.isFake()) {
365 dst.flags |= RecTrack::FakeITS;
366 }
367 } else { // AB ITS tracklet
368 if (recoData.getTrackMCLabel(gidSet[GTrackID::ITSAB]).isFake()) {
369 dst.flags |= RecTrack::FakeITS;
370 }
371 }
372 if (msk[DetID::TPC]) { // has both ITS and TPC contribution
373 if (recoData.getTrackMCLabel(gidSet[GTrackID::ITSTPC]).isFake()) {
374 dst.flags |= RecTrack::FakeITSTPC;
375 }
376 }
377 }
378 if (msk[DetID::TPC]) {
379 if (recoData.getTrackMCLabel(gidSet[GTrackID::TPC]).isFake()) {
380 dst.flags |= RecTrack::FakeTPC;
381 }
382 }
383 }
384 };
385 tpcOccAftV.resize(mNOccBinsDrift);
386 tpcOccBefV.resize(mNOccBinsDrift);
387
388 for (int iv = 0; iv < nv; iv++) {
389 LOGP(debug, "processing PV {} of {}", iv, nv);
390 const auto& vtref = vtxRefs[iv];
391 if (iv != nv - 1) {
392 auto& pve = pveVec[iv];
393 static_cast<o2::dataformats::PrimaryVertex&>(pve) = pvvec[iv];
394 // find best matching FT0 signal
395 float bestTimeDiff = 1000, bestTime = -999;
396 int bestFTID = -1;
397 if (mTracksSrc[GTrackID::FT0]) {
398 for (int ift0 = vtref.getFirstEntryOfSource(GTrackID::FT0); ift0 < vtref.getFirstEntryOfSource(GTrackID::FT0) + vtref.getEntriesOfSource(GTrackID::FT0); ift0++) {
399 const auto& ft0 = FITInfo[trackIndex[ift0]];
400 if (ft0Params.isSelected(ft0)) {
401 auto fitTime = ft0.getInteractionRecord().differenceInBCMUS(recoData.startIR);
402 if (std::abs(fitTime - pve.getTimeStamp().getTimeStamp()) < bestTimeDiff) {
403 bestTimeDiff = fitTime - pve.getTimeStamp().getTimeStamp();
404 bestFTID = trackIndex[ift0];
405 }
406 }
407 }
408 } else {
409 LOGP(warn, "FT0 is not requested, cannot set complete vertex info");
410 }
411 if (bestFTID >= 0) {
412 pve.FT0A = FITInfo[bestFTID].getTrigger().getAmplA();
413 pve.FT0C = FITInfo[bestFTID].getTrigger().getAmplC();
414 pve.FT0Time = double(FITInfo[bestFTID].getInteractionRecord().differenceInBCMUS(recoData.startIR)) + FITInfo[bestFTID].getCollisionTimeMean() * 1e-6; // time in \mus
415 }
416 pve.VtxID = iv;
417 }
418 trcExtVec.clear();
419 trcPairsVec.clear();
420 float q2ptITS, q2ptTPC, q2ptITSTPC, q2ptITSTPCTRD;
421 for (int is = 0; is < GTrackID::NSources; is++) {
422 DetID::mask_t dm = GTrackID::getSourceDetectorsMask(is);
423 bool skipTracks = !mTracksSrc[is] || !recoData.isTrackSourceLoaded(is) || !(dm[DetID::ITS] || dm[DetID::TPC]);
424 int idMin = vtref.getFirstEntryOfSource(is), idMax = idMin + vtref.getEntriesOfSource(is);
425 for (int i = idMin; i < idMax; i++) {
426 auto vid = trackIndex[i];
427 bool pvCont = vid.isPVContributor();
428 if (pvCont) {
429 pveVec[iv].nSrc[is]++;
430 }
431 if (skipTracks) {
432 continue;
433 }
434 GTrackID tpcTrID;
435 const o2::tpc::TrackTPC* tpcTr = nullptr;
436 int nclTPC = 0;
437 if (dm[DetID::TPC] && tpcTrackOK) {
438 tpcTrID = recoData.getTPCContributorGID(vid);
439 tpcTr = &recoData.getTPCTrack(tpcTrID);
440 nclTPC = tpcTr->getNClusters();
441 if (nclTPC < mMinTPCClusters) {
442 continue;
443 }
444 }
445 bool ambig = vid.isAmbiguous();
446 auto trc = recoData.getTrackParam(vid);
447 if (abs(trc.getEta()) > mMaxEta) {
448 continue;
449 }
450 if (iv < nv - 1 && is == GTrackID::TPC && tpcTr && !tpcTr->hasBothSidesClusters()) { // for unconstrained TPC tracks correct track Z
451 float corz = vdrift * (tpcTr->getTime0() * mTPCTBinMUS - pvvec[iv].getTimeStamp().getTimeStamp());
452 if (tpcTr->hasASideClustersOnly()) {
453 corz = -corz; // A-side
454 }
455 trc.setZ(trc.getZ() + corz);
456 }
457 float xmin = trc.getX();
459 if (!prop->propagateToDCA(iv == nv - 1 ? vtxDummy : pvvec[iv], trc, prop->getNominalBz(), 2., o2::base::PropagatorF::MatCorrType::USEMatCorrLUT, &dca)) {
460 continue;
461 }
462 bool hasITS = GTrackID::getSourceDetectorsMask(is)[GTrackID::ITS];
463 if (std::abs(dca.getY()) > (hasITS ? getDCAYCut(trc.getPt()) : mTPCDCAYCut) ||
464 std::abs(dca.getZ()) > (hasITS ? getDCAZCut(trc.getPt()) : mTPCDCAZCut)) {
465 continue;
466 }
467 if (trc.getPt() < mMinPt) {
468 continue;
469 }
470 if (iv != nv - 1) {
471 pveVec[iv].nSrcA[is]++;
472 if (ambig) {
473 pveVec[iv].nSrcAU[is]++;
474 }
475 }
476 if (!hasITS && mStoreWithITSOnly) {
477 continue;
478 }
479 {
480 auto& trcExt = trcExtVec.emplace_back();
481 recoData.getTrackTime(vid, trcExt.ttime, trcExt.ttimeE);
482 trcExt.track = trc;
483 trcExt.hashIU = trc.hash();
484 trcExt.dca = dca;
485 trcExt.gid = vid;
486 trcExt.xmin = xmin;
487 trcExt.dcaTPC.set(-999.f, -999.f);
488
489 if (tpcTr) {
490 float tsuse = trcExt.ttime / (8 * o2::constants::lhc::LHCBunchSpacingMUS);
491 if (tpcTr->hasASideClusters()) {
492 trcExt.setTPCA();
493 }
494 if (tpcTr->hasCSideClusters()) {
495 trcExt.setTPCC();
496 }
497 if (is == GTrackID::TPC) {
498 trcExt.dcaTPC = dca;
499 tsuse = -1e9;
500 } else {
501 o2::track::TrackParCov tmpTPC(*tpcTr);
502 if (iv < nv - 1 && is == GTrackID::TPC && tpcTr && !tpcTr->hasBothSidesClusters()) { // for unconstrained TPC tracks correct track Z
503 float corz = vdrift * (tpcTr->getTime0() * mTPCTBinMUS - pvvec[iv].getTimeStamp().getTimeStamp());
504 if (tpcTr->hasASideClustersOnly()) {
505 corz = -corz; // A-side
506 }
507 tmpTPC.setZ(tmpTPC.getZ() + corz);
508 }
509 if (!prop->propagateToDCA(iv == nv - 1 ? vtxDummy : pvvec[iv], tmpTPC, prop->getNominalBz(), 2., o2::base::PropagatorF::MatCorrType::USEMatCorrLUT, &trcExt.dcaTPC)) {
510 trcExt.dcaTPC.set(-999.f, -999.f);
511 }
512 }
513 fillTPCClInfo(*tpcTr, trcExt, tsuse);
514 trcExt.chi2TPC = tpcTr->getChi2();
515 }
516 auto gidRefs = recoData.getSingleDetectorRefs(vid);
517 if (gidRefs[GTrackID::ITS].isIndexSet()) {
518 const auto& itsTr = recoData.getITSTrack(gidRefs[GTrackID::ITS]);
519 trcExt.q2ptITS = itsTr.getQ2Pt();
520 trcExt.nClITS = itsTr.getNClusters();
521 for (int il = 0; il < 7; il++) {
522 if (itsTr.hasHitOnLayer(il)) {
523 trcExt.pattITS |= 0x1 << il;
524 }
525 }
526 } else if (gidRefs[GTrackID::ITSAB].isIndexSet()) {
527 const auto& itsTrf = recoData.getITSABRefs()[gidRefs[GTrackID::ITSAB]];
528 trcExt.nClITS = itsTrf.getNClusters();
529 for (int il = 0; il < 7; il++) {
530 if (itsTrf.hasHitOnLayer(il)) {
531 trcExt.pattITS |= 0x1 << il;
532 }
533 }
534 }
535 if (gidRefs[GTrackID::TPC].isIndexSet()) {
536 trcExt.q2ptTPC = recoData.getTrackParam(gidRefs[GTrackID::TPC]).getQ2Pt();
537 trcExt.nClTPC = nclTPC;
538 }
539 if (gidRefs[GTrackID::ITSTPC].isIndexSet()) {
540 const auto& trTPCITS = recoData.getTPCITSTrack(gidRefs[GTrackID::ITSTPC]);
541 trcExt.q2ptITSTPC = trTPCITS.getQ2Pt();
542 trcExt.chi2ITSTPC = trTPCITS.getChi2Match();
543 }
544 if (gidRefs[GTrackID::TRD].isIndexSet()) {
545 trcExt.q2ptITSTPCTRD = recoData.getTrackParam(gidRefs[GTrackID::TRD]).getQ2Pt();
546 }
547 if (gidRefs[GTrackID::TOF].isIndexSet()) {
548 trcExt.infoTOF = recoData.getTOFMatch(vid);
549 }
550 }
551 }
552 }
553 float tpcOccBef = 0., tpcOccAft = 0.;
554 if (iv != nv - 1) {
555 int tb = pveVec[iv].getTimeStamp().getTimeStamp() * mTPCTBinMUSInv * mNTPCOccBinLengthInv;
556 tpcOccBef = tb < 0 ? mTBinClOccBef[0] : (tb >= mTBinClOccBef.size() ? mTBinClOccBef.back() : mTBinClOccBef[tb]);
557 tpcOccAft = tb < 0 ? mTBinClOccAft[0] : (tb >= mTBinClOccAft.size() ? mTBinClOccAft.back() : mTBinClOccAft[tb]);
558 int tbc = pveVec[iv].getTimeStamp().getTimeStamp() * mTPCTBinMUSInv * mNTPCOccBinLengthInv - groupOcc / 2.;
559 for (int iob = 0; iob < mNOccBinsDrift; iob++) {
560 float sm = 0;
561 for (int ig = 0; ig < groupOcc; ig++) {
562 int ocb = tbc + ig + groupOcc * iob;
563 if (ocb < 0 || ocb >= (int)mMltHistTB.size()) {
564 sm = -1;
565 break;
566 }
567 sm += mMltHistTB[ocb];
568 }
569 tpcOccAftV[iob] = sm;
570 //
571 sm = 0;
572 for (int ig = 0; ig < groupOcc; ig++) {
573 int ocb = tbc + ig - groupOcc * iob;
574 if (ocb < 0 || ocb >= (int)mMltHistTB.size()) {
575 sm = -1;
576 break;
577 }
578 sm += mMltHistTB[ocb];
579 }
580 tpcOccBefV[iob] = sm;
581 }
582 }
583 (*mDBGOut) << "trpv"
584 << "orbit=" << recoData.startIR.orbit << "tfID=" << TFCount
585 << "tpcOccBef=" << tpcOccBef << "tpcOccAft=" << tpcOccAft
586 << "tpcOccBefV=" << tpcOccBefV << "tpcOccAftV=" << tpcOccAftV
587 << "pve=" << pveVec[iv] << "trc=" << trcExtVec << "\n";
588
589 if (mDoPairsCorr) {
590 for (int it0 = 0; it0 < (int)trcExtVec.size(); it0++) {
591 const auto& tr0 = trcExtVec[it0];
592 if (tr0.nClTPC < 1) {
593 continue;
594 }
595 for (int it1 = it0 + 1; it1 < (int)trcExtVec.size(); it1++) {
596 const auto& tr1 = trcExtVec[it1];
597 if (tr1.nClTPC < 1) {
598 continue;
599 }
600
601 if (std::abs(tr0.track.getTgl() - tr1.track.getTgl()) > 0.25) {
602 continue;
603 }
604 auto dphi = tr0.track.getPhi() - tr1.track.getPhi();
605 if (dphi < -o2::constants::math::PI) {
607 } else if (dphi > o2::constants::math::PI) {
609 }
610 if (std::abs(dphi) > 0.25) {
611 continue;
612 }
613 auto& pr = trcPairsVec.emplace_back();
614 assignRecTrack(tr0, pr.tr0);
615 assignRecTrack(tr1, pr.tr1);
616 auto shinfo = getTPCPairSharing(recoData.getTPCTrack(recoData.getTPCContributorGID(tr0.gid)), recoData.getTPCTrack(recoData.getTPCContributorGID(tr1.gid)));
617 pr.nshTPC = shinfo.first;
618 pr.nshTPCRow = shinfo.second;
619 }
620 }
621 (*mDBGOut) << "pairs" << "pr=" << trcPairsVec << "\n";
622 }
623 }
624
625 int nvtot = mMaxNeighbours < 0 ? -1 : (int)pveVec.size();
626
627 auto insSlot = [maxSlots = mMaxNeighbours](std::vector<float>& vc, float v, int slot, std::vector<int>& vid, int id) {
628 for (int i = maxSlots - 1; i > slot; i--) {
629 std::swap(vc[i], vc[i - 1]);
630 std::swap(vid[i], vid[i - 1]);
631 }
632 vc[slot] = v;
633 vid[slot] = id;
634 };
635
636 for (int cnt = 0; cnt < nvtot; cnt++) {
637 const auto& pve = pveVec[cnt];
638 float tv = pve.getTimeStamp().getTimeStamp();
639 std::vector<o2::dataformats::PrimaryVertexExt> pveT(mMaxNeighbours); // neighbours in time
640 std::vector<o2::dataformats::PrimaryVertexExt> pveZ(mMaxNeighbours); // neighbours in Z
641 std::vector<int> idT(mMaxNeighbours), idZ(mMaxNeighbours);
642 std::vector<float> dT(mMaxNeighbours), dZ(mMaxNeighbours);
643 for (int i = 0; i < mMaxNeighbours; i++) {
644 idT[i] = idZ[i] = -1;
645 dT[i] = mMaxVTTimeDiff;
646 dZ[i] = 1e9;
647 }
648 int cntM = cnt - 1, cntP = cnt + 1;
649 for (; cntM >= 0; cntM--) { // backward
650 const auto& vt = pveVec[cntM];
651 auto dtime = std::abs(tv - vt.getTimeStamp().getTimeStamp());
652 if (dtime > mMaxVTTimeDiff) {
653 continue;
654 }
655 for (int i = 0; i < mMaxNeighbours; i++) {
656 if (dT[i] > dtime) {
657 insSlot(dT, dtime, i, idT, cntM);
658 break;
659 }
660 }
661 auto dz = std::abs(pve.getZ() - vt.getZ());
662 for (int i = 0; i < mMaxNeighbours; i++) {
663 if (dZ[i] > dz) {
664 insSlot(dZ, dz, i, idZ, cntM);
665 break;
666 }
667 }
668 }
669 for (; cntP < nvtot; cntP++) { // forward
670 const auto& vt = pveVec[cntP];
671 auto dtime = std::abs(tv - vt.getTimeStamp().getTimeStamp());
672 if (dtime > mMaxVTTimeDiff) {
673 continue;
674 }
675 for (int i = 0; i < mMaxNeighbours; i++) {
676 if (dT[i] > dtime) {
677 insSlot(dT, dtime, i, idT, cntP);
678 break;
679 }
680 }
681 auto dz = std::abs(pve.getZ() - vt.getZ());
682 for (int i = 0; i < mMaxNeighbours; i++) {
683 if (dZ[i] > dz) {
684 insSlot(dZ, dz, i, idZ, cntP);
685 break;
686 }
687 }
688 }
689 for (int i = 0; i < mMaxNeighbours; i++) {
690 if (idT[i] != -1) {
691 pveT[i] = pveVec[idT[i]];
692 } else {
693 break;
694 }
695 }
696 for (int i = 0; i < mMaxNeighbours; i++) {
697 if (idZ[i] != -1) {
698 pveZ[i] = pveVec[idZ[i]];
699 } else {
700 break;
701 }
702 }
703 (*mDBGOutVtx) << "pvExt"
704 << "pve=" << pve
705 << "pveT=" << pveT
706 << "pveZ=" << pveZ
707 << "tfID=" << TFCount
708 << "\n";
709 }
710
711 TFCount++;
712}
713
715{
716 mDBGOut.reset();
717 mDBGOutVtx.reset();
718}
719
721{
723 return;
724 }
725 if (mTPCVDriftHelper.accountCCDBInputs(matcher, obj)) {
726 return;
727 }
728 if (mTPCCorrMapsLoader.accountCCDBInputs(matcher, obj)) {
729 return;
730 }
731 if (matcher == ConcreteDataMatcher("GLO", "MEANVERTEX", 0)) {
732 LOG(info) << "Imposing new MeanVertex: " << ((const o2::dataformats::MeanVertexObject*)obj)->asString();
733 mMeanVtx = *(const o2::dataformats::MeanVertexObject*)obj;
734 return;
735 }
736}
737
738float TrackingStudySpec::getDCAYCut(float pt) const
739{
740 static TF1 fun("dcayvspt", mDCAYFormula.c_str(), 0, 20);
741 return fun.Eval(pt);
742}
743
744float TrackingStudySpec::getDCAZCut(float pt) const
745{
746 static TF1 fun("dcazvspt", mDCAZFormula.c_str(), 0, 20);
747 return fun.Eval(pt);
748}
749
751{
752 std::vector<OutputSpec> outputs;
753 auto dataRequest = std::make_shared<DataRequest>();
754
755 dataRequest->requestTracks(srcTracks, useMC);
756 dataRequest->requestClusters(srcClusters, useMC);
757 dataRequest->requestPrimaryVertices(useMC);
758 dataRequest->inputs.emplace_back("meanvtx", "GLO", "MEANVERTEX", 0, Lifetime::Condition, ccdbParamSpec("GLO/Calib/MeanVertex", {}, 1));
759 auto ggRequest = std::make_shared<o2::base::GRPGeomRequest>(false, // orbitResetTime
760 true, // GRPECS=true
761 true, // GRPLHCIF
762 true, // GRPMagField
763 true, // askMatLUT
765 dataRequest->inputs,
766 true);
767
768 Options opts{
769 {"max-vtx-neighbours", VariantType::Int, 3, {"Max PV neighbours fill, no PV study if < 0"}},
770 {"max-vtx-timediff", VariantType::Float, 90.f, {"Max PV time difference to consider"}},
771 {"dcay-vs-pt", VariantType::String, "0.0105 + 0.0350 / pow(x, 1.1)", {"Formula for global tracks DCAy vs pT cut"}},
772 {"dcaz-vs-pt", VariantType::String, "0.0105 + 0.0350 / pow(x, 1.1)", {"Formula for global tracks DCAy vs pT cut"}},
773 {"min-tpc-clusters", VariantType::Int, 60, {"Cut on TPC clusters"}},
774 {"max-tpc-dcay", VariantType::Float, 5.f, {"Cut on TPC dcaY"}},
775 {"max-tpc-dcaz", VariantType::Float, 5.f, {"Cut on TPC dcaZ"}},
776 {"max-eta", VariantType::Float, 1.0f, {"Cut on track eta"}},
777 {"min-pt", VariantType::Float, 0.1f, {"Cut on track pT"}},
778 {"with-its-only", VariantType::Bool, false, {"Store tracks with ITS only"}},
779 {"pair-correlations", VariantType::Bool, false, {"Do pairs correlation"}},
780 {"occ-weight-fun", VariantType::String, "(x>=-40&&x<-5) ? (1./1225*pow(x+40,2)) : ((x>-5&&x<15) ? 1. : ((x>=15&&x<40) ? (-0.4/25*x+1.24 ) : ( (x>40&&x<100) ? -0.4/60*x+0.6+0.8/3 : 0)))", {"Occupancy weighting f-n vs time in musec"}},
781 {"noccbins", VariantType::Int, 10, {"Number of occupancy bins per full drift time"}},
782 {"min-x-prop", VariantType::Float, 100.f, {"track should be propagated to this X at least"}},
783 };
784 o2::tpc::VDriftHelper::requestCCDBInputs(dataRequest->inputs);
785 o2::tpc::CorrectionMapsLoader::requestCCDBInputs(dataRequest->inputs, opts, sclOpts);
786
787 return DataProcessorSpec{
788 "track-study",
789 dataRequest->inputs,
790 outputs,
791 AlgorithmSpec{adaptFromTask<TrackingStudySpec>(dataRequest, ggRequest, srcTracks, useMC, sclOpts)},
792 opts};
793}
794
795} // namespace o2::trackstudy
Helper class to access load maps from CCDB.
Wrapper container for different reconstructed object types.
Definition of the GeometryManager class.
Definition of the FIT RecPoints class.
int32_t i
Helper for geometry and GRP related CCDB requests.
Global index for barrel track: provides provenance (detectors combination), index in respective array...
Utility functions for MC particles.
Definition of the Names Generator class.
Definition of the parameter class for the detector electronics.
Wrapper container for different reconstructed object types.
Result of refitting TPC-ITS matched track.
Reference on ITS/MFT clusters set.
Helper class to extract VDrift from different sources.
std::ostringstream debug
Referenc on track indices contributing to the vertex, with possibility chose tracks from specific sou...
bool isFake() const
Definition MCCompLabel.h:78
void checkUpdates(o2::framework::ProcessingContext &pc)
static GRPGeomHelper & instance()
void setRequest(std::shared_ptr< GRPGeomRequest > req)
GPUd() value_type estimateLTFast(o2 static GPUd() float estimateLTIncrement(const o2 PropagatorImpl * Instance(bool uninitialized=false)
Definition Propagator.h:143
math_utils::Point3D< float > & getPos()
Static class with identifiers, bitmasks and names for ALICE detectors.
Definition DetID.h:58
static constexpr ID ITS
Definition DetID.h:63
static constexpr ID TPC
Definition DetID.h:64
ServiceRegistryRef services()
Definition InitContext.h:34
ConfigParamRegistry const & options()
Definition InitContext.h:33
decltype(auto) get(R binding, int part=0) const
InputRecord & inputs()
The inputs associated with this processing context.
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
void process(o2::globaltracking::RecoContainer &recoData)
void run(ProcessingContext &pc) final
TrackingStudySpec(std::shared_ptr< DataRequest > dr, std::shared_ptr< o2::base::GRPGeomRequest > gr, GTrackID::mask_t src, bool useMC, const o2::tpc::CorrectionMapsLoaderGloOpts &sclOpts)
void finaliseCCDB(ConcreteDataMatcher &matcher, void *obj) final
void endOfStream(EndOfStreamContext &ec) final
This is invoked whenever we have an EndOfStream event.
void init(InitContext &ic) final
GLenum src
Definition glcorearb.h:1767
const GLdouble * v
Definition glcorearb.h:832
GLenum GLenum dst
Definition glcorearb.h:1767
GLuint id
Definition glcorearb.h:650
constexpr double LHCBunchSpacingMUS
constexpr int LHCMaxBunches
constexpr double LHCBunchSpacingNS
constexpr float TwoPI
constexpr float PI
Defining PrimaryVertex explicitly as messageable.
Definition TFIDInfo.h:20
std::vector< ConfigParamSpec > ccdbParamSpec(std::string const &path, int runDependent, std::vector< CCDBMetadata > metadata={}, int qrate=0)
std::vector< ConfigParamSpec > Options
detail::Bracket< float > Bracketf_t
Definition Primitive2D.h:40
TrackParCovF TrackParCov
Definition Track.h:33
o2::math_utils::Bracketf_t TBracket
o2::framework::DataProcessorSpec getTrackingStudySpec(o2::dataformats::GlobalTrackID::mask_t srcTracks, o2::dataformats::GlobalTrackID::mask_t srcClus, bool useMC, const o2::tpc::CorrectionMapsLoaderGloOpts &sclOpts)
create a processor spec
o2::dataformats::VtxTrackRef V2TRef
o2::dataformats::VtxTrackIndex VTIndex
a couple of static helper functions to create timestamp values for CCDB queries or override obsolete ...
Defining DataPointCompositeObject explicitly as copiable.
uint32_t orbit
LHC orbit.
bool isSelected(const RecPoints &rp) const
GlobalIDSet getSingleDetectorRefs(GTrackID gidx) const
const o2::tpc::TrackTPC & getTPCTrack(GTrackID id) const
const o2::tpc::ClusterNativeAccess & getTPCClusters() const
o2::MCCompLabel getTrackMCLabel(GTrackID id) const
GTrackID getTPCContributorGID(GTrackID source) const
const o2::track::TrackParCov & getTrackParam(GTrackID gidx) 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)
const o2::its::TrackITS & getITSTrack(GTrackID gid) const
std::unique_ptr< o2::tpc::internal::getWorkflowTPCInput_ret > inputsTPCclusters
void getTrackTime(GTrackID gid, float &t, float &tErr) const
gsl::span< const unsigned int > occupancyMapTPC
externally set TPC clusters occupancy map
const o2::dataformats::MatchInfoTOF & getTOFMatch(GTrackID id) const
int lumiType
what estimator to used for corrections scaling: 0: no scaling, 1: CTP, 2: IDC
int lumiMode
what corrections method to use: 0: classical scaling, 1: Using of the derivative map,...
float refTimeOffset
additive time offset reference (\mus)
float refVDrift
reference vdrift for which factor was extracted
float getTimeOffset() const
float timeOffsetCorr
additive time offset correction (\mus)
float corrFact
drift velocity correction factor (multiplicative)
LOG(info)<< "Compressed in "<< sw.CpuTime()<< " s"
const std::string str