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