Project
Loading...
Searching...
No Matches
TPCRefitter.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 <random>
13#include <vector>
14#include <TStopwatch.h>
25#include "Framework/Task.h"
26#include "MathUtils/Tsallis.h"
33#include "GPUO2InterfaceRefit.h"
38
39namespace o2::trackstudy
40{
41
42using namespace o2::framework;
45
51
53
54class TPCRefitterSpec final : public Task
55{
56 public:
57 enum StudyType {
58 TPC = 0x1,
59 ITSTPC = 0x2,
60 Cosmics = 0x4,
61 };
63 Streamer = 0x1,
64 TFVectors = 0x2,
65 };
66 TPCRefitterSpec(std::shared_ptr<DataRequest> dr, std::shared_ptr<o2::base::GRPGeomRequest> gr, const o2::tpc::CorrectionMapsLoaderGloOpts& sclOpts, GTrackID::mask_t src, bool useMC)
67 : mDataRequest(dr), mGGCCDBRequest(gr), mTracksSrc(src), mUseMC(useMC)
68 {
69 mTPCCorrMapsLoader.setLumiScaleType(sclOpts.lumiType);
70 mTPCCorrMapsLoader.setLumiScaleMode(sclOpts.lumiMode);
71 }
72 ~TPCRefitterSpec() final = default;
73 void init(InitContext& ic) final;
74 void run(ProcessingContext& pc) final;
75 void endOfStream(EndOfStreamContext& ec) final;
76 void finaliseCCDB(ConcreteDataMatcher& matcher, void* obj) final;
77 void process(o2::globaltracking::RecoContainer& recoData);
78 bool getDCAs(const o2::track::TrackPar& track, float& dcar, float& dcaz);
79
80 private:
81 void updateTimeDependentParams(ProcessingContext& pc);
82 std::shared_ptr<DataRequest> mDataRequest;
83 std::shared_ptr<o2::base::GRPGeomRequest> mGGCCDBRequest;
84 o2::tpc::VDriftHelper mTPCVDriftHelper{};
85 o2::tpc::CorrectionMapsLoader mTPCCorrMapsLoader{};
86 bool mUseMC{false};
87 bool mUseGPUModel{false};
88 float mXRef = 83.;
89 float mDCAMinPt = 1.;
90 int mTFStart = 0;
91 int mTFEnd = 999999999;
92 int mTFCount = -1;
93 int mDCAMinNCl = 80;
94 int mStudyType = 0;
95 int mWriterType = 0;
96 float mSqrt{13600};
97 float mSamplingFactor{0.1};
98 bool mUseR = false;
99 bool mEnableDCA = false;
100 int mWriteTrackClusters = 0;
101 bool mDoSampling{false};
102 bool mDoRefit{true};
103 std::vector<size_t> mClusterOccupancy;
104 std::vector<size_t> mITSTPCTrackOccupanyTPCTime;
105 std::vector<size_t> mITSTPCTrackOccupanyCombinedTime;
106 std::unique_ptr<o2::utils::TreeStreamRedirector> mDBGOutTPC;
107 std::unique_ptr<o2::utils::TreeStreamRedirector> mDBGOutITSTPC;
108 std::unique_ptr<o2::utils::TreeStreamRedirector> mDBGOutTPCTF;
109 std::unique_ptr<o2::utils::TreeStreamRedirector> mDBGOutITSTPCTF;
110 std::unique_ptr<o2::utils::TreeStreamRedirector> mDBGOutCosmics;
111 std::unique_ptr<o2::utils::TreeStreamRedirector> mDBGOutCl;
112 float mITSROFrameLengthMUS = 0.;
113 GTrackID::mask_t mTracksSrc{};
115 std::mt19937 mGenerator;
116 float mVdriftTB;
117 float mTPCTBBias;
118 uint32_t mTimeBinsPerTF{};
119 uint32_t mOccupancyBinsPerTF{};
120 uint32_t mTimeBinsPerDrift{500};
121 //
122 // Input data
123 //
124 gsl::span<const o2::tpc::TPCClRefElem> mTPCTrackClusIdx;
125 gsl::span<const o2::tpc::TrackTPC> mTPCTracksArray;
126 gsl::span<const o2::dataformats::TrackTPCITS> mITSTPCTracksArray;
127 gsl::span<const o2::its::TrackITS> mITSTracksArray;
128 gsl::span<const o2::dataformats::TrackCosmics> mCosmics;
129 gsl::span<const unsigned char> mTPCRefitterShMap;
130 gsl::span<const unsigned int> mTPCRefitterOccMap;
131 const o2::tpc::ClusterNativeAccess* mTPCClusterIdxStruct = nullptr;
132 gsl::span<const o2::MCCompLabel> mTPCTrkLabels;
133 std::unique_ptr<o2::gpu::GPUO2InterfaceRefit> mTPCRefitter;
134 std::vector<o2::InteractionTimeRecord> mIntRecs;
135
136 void fillOccupancyVectors(o2::globaltracking::RecoContainer& recoData);
137 bool processTPCTrack(o2::tpc::TrackTPC tr, o2::MCCompLabel lbl, o2::utils::TreeStreamRedirector* streamer, const o2::its::TrackITS* its = nullptr, const o2::dataformats::TrackTPCITS* itstpc = nullptr, bool outward = false, float time0custom = -1);
138 void processCosmics(o2::globaltracking::RecoContainer& recoData);
139};
140
142{
144 mXRef = ic.options().get<float>("target-x");
145 mUseR = ic.options().get<bool>("use-r-as-x");
146 mEnableDCA = ic.options().get<bool>("enable-dcas");
147 mUseGPUModel = ic.options().get<bool>("use-gpu-fitter");
148 mTFStart = ic.options().get<int>("tf-start");
149 mTFEnd = ic.options().get<int>("tf-end");
150 mDCAMinPt = ic.options().get<float>("dcaMinPt");
151 mDCAMinNCl = ic.options().get<float>("dcaMinNCl");
152 mSqrt = ic.options().get<float>("sqrts");
153 mSamplingFactor = ic.options().get<float>("sampling-factor");
154 mDoSampling = ic.options().get<bool>("do-sampling");
155 mDoRefit = ic.options().get<bool>("do-refit");
156 mStudyType = ic.options().get<int>("study-type");
157 mWriterType = ic.options().get<int>("writer-type");
158 mWriteTrackClusters = ic.options().get<int>("write-track-clusters");
159 const auto occBinsPerDrift = ic.options().get<uint32_t>("occupancy-bins-per-drift");
160 mTimeBinsPerTF = (o2::raw::HBFUtils::Instance().nHBFPerTF * o2::constants::lhc::LHCMaxBunches) / 8 + 2 * mTimeBinsPerDrift; // add one drift before and after the TF
161 mOccupancyBinsPerTF = static_cast<uint32_t>(std::ceil(float(mTimeBinsPerTF * occBinsPerDrift) / mTimeBinsPerDrift));
162 mClusterOccupancy.resize(mOccupancyBinsPerTF);
163 mITSTPCTrackOccupanyTPCTime.resize(mOccupancyBinsPerTF);
164 mITSTPCTrackOccupanyCombinedTime.resize(mOccupancyBinsPerTF);
165 LOGP(info, "Using {} bins for the occupancy per TF", mOccupancyBinsPerTF);
166
167 if ((mWriterType & WriterType::Streamer) == WriterType::Streamer) {
168 if ((mStudyType & StudyType::TPC) == StudyType::TPC) {
169 mDBGOutTPC = std::make_unique<o2::utils::TreeStreamRedirector>("tpctracks-study-streamer.root", "recreate");
170 }
171 if ((mStudyType & StudyType::ITSTPC) == StudyType::ITSTPC) {
172 mDBGOutITSTPC = std::make_unique<o2::utils::TreeStreamRedirector>("itstpctracks-study-streamer.root", "recreate");
173 }
174 if ((mStudyType & StudyType::Cosmics) == StudyType::Cosmics) {
175 mDBGOutCosmics = std::make_unique<o2::utils::TreeStreamRedirector>("cosmics-study-streamer.root", "recreate");
176 }
177 }
178 if (ic.options().get<bool>("dump-clusters")) {
179 mDBGOutCl = std::make_unique<o2::utils::TreeStreamRedirector>("tpc-trackStudy-cl.root", "recreate");
180 }
181
182 if (mXRef < 0.) {
183 mXRef = 0.;
184 }
185 mGenerator = std::mt19937(std::random_device{}());
186 mTPCCorrMapsLoader.init(ic);
187}
188
190{
191 ++mTFCount;
192 if (mTFCount < mTFStart || mTFCount > mTFEnd) {
193 LOGP(info, "Skipping TF {}", mTFCount);
194 return;
195 }
196
198 recoData.collectData(pc, *mDataRequest.get()); // select tracks of needed type, with minimal cuts, the real selected will be done in the vertexer
199 updateTimeDependentParams(pc); // Make sure this is called after recoData.collectData, which may load some conditions
200 fillOccupancyVectors(recoData);
201 process(recoData);
202
203 if (mTFCount >= mTFEnd) {
204 LOGP(info, "Stopping processing after TF {}", mTFCount);
206 return;
207 }
208}
209
210void TPCRefitterSpec::updateTimeDependentParams(ProcessingContext& pc)
211{
213 mTPCVDriftHelper.extractCCDBInputs(pc);
214 mTPCCorrMapsLoader.extractCCDBInputs(pc);
215 static bool initOnceDone = false;
216 if (!initOnceDone) { // this params need to be queried only once
217 initOnceDone = true;
218 // none at the moment
219 }
220 // we may have other params which need to be queried regularly
221 bool updateMaps = false;
222 if (mTPCCorrMapsLoader.isUpdated()) {
223 mTPCCorrMapsLoader.acknowledgeUpdate();
224 updateMaps = true;
225 }
226 if (mTPCVDriftHelper.isUpdated()) {
227 LOGP(info, "Updating TPC fast transform map with new VDrift factor of {} wrt reference {} and DriftTimeOffset correction {} wrt {} from source {}",
228 mTPCVDriftHelper.getVDriftObject().corrFact, mTPCVDriftHelper.getVDriftObject().refVDrift,
229 mTPCVDriftHelper.getVDriftObject().timeOffsetCorr, mTPCVDriftHelper.getVDriftObject().refTimeOffset,
230 mTPCVDriftHelper.getSourceName());
231 mTPCVDriftHelper.acknowledgeUpdate();
232 updateMaps = true;
233 }
234 if (updateMaps) {
235 mTPCCorrMapsLoader.updateVDrift(mTPCVDriftHelper.getVDriftObject().corrFact, mTPCVDriftHelper.getVDriftObject().refVDrift, mTPCVDriftHelper.getVDriftObject().getTimeOffset());
236 }
237}
238
239void TPCRefitterSpec::fillOccupancyVectors(o2::globaltracking::RecoContainer& recoData)
240{
241 // reset counters
242 std::fill(mClusterOccupancy.begin(), mClusterOccupancy.end(), 0u);
243 std::fill(mITSTPCTrackOccupanyTPCTime.begin(), mITSTPCTrackOccupanyTPCTime.end(), 0u);
244 std::fill(mITSTPCTrackOccupanyCombinedTime.begin(), mITSTPCTrackOccupanyCombinedTime.end(), 0u);
245
246 // fill cluster occupancy
247 const auto& clusterIndex = recoData.inputsTPCclusters->clusterIndex;
248 using namespace o2::tpc::constants;
249 for (int sector = 0; sector < MAXSECTOR; ++sector) {
250 for (int padrow = 0; padrow < MAXGLOBALPADROW; ++padrow) {
251 for (size_t icl = 0; icl < clusterIndex.nClusters[sector][padrow]; ++icl) {
252 const auto& cl = clusterIndex.clusters[sector][padrow][icl];
253 // shift by one TPC drift to allow seeing pile-up
254 const auto tpcTime = cl.getTime() + mTimeBinsPerDrift;
255 const uint32_t clOccPos = static_cast<uint32_t>(tpcTime * mOccupancyBinsPerTF / mTimeBinsPerTF);
256 if (clOccPos >= mOccupancyBinsPerTF) {
257 LOGP(error, "cluster with time {} outside TPC acceptanc", cl.getTime());
258 } else {
259 ++mClusterOccupancy[clOccPos];
260 }
261 }
262 }
263 }
264
265 // fill track occupancy for its-tpc matched tracks
266 auto tpcTracks = recoData.getTPCTracks();
267 auto itstpcTracks = recoData.getTPCITSTracks();
268 const auto& paramEle = o2::tpc::ParameterElectronics::Instance();
269
270 for (const auto& tpcitsTrack : itstpcTracks) {
271 const auto idxTPC = tpcitsTrack.getRefTPC().getIndex();
272 if (idxTPC >= tpcTracks.size()) {
273 LOGP(fatal, "TPC index {} out of array size {}", idxTPC, tpcTracks.size());
274 }
275 const auto& tpcTrack = tpcTracks[idxTPC];
276 // shift by one TPC drift to allow seeing pile-up
277 const auto tpcTime = tpcTrack.getTime0() + mTimeBinsPerDrift;
278 if (tpcTime >= 0) {
279 const uint32_t clOccPosTPC = static_cast<uint32_t>(tpcTime * mOccupancyBinsPerTF / mTimeBinsPerTF);
280 if (clOccPosTPC < mITSTPCTrackOccupanyTPCTime.size()) {
281 ++mITSTPCTrackOccupanyTPCTime[clOccPosTPC];
282 } else {
283 LOGP(warn, "TF {}: TPC occupancy index {} out of range {}", mTFCount, clOccPosTPC, mITSTPCTrackOccupanyTPCTime.size());
284 }
285 }
286 // convert mus to time bins
287 // shift by one TPC drift to allow seeing pile-up
288 const auto tpcitsTime = tpcitsTrack.getTimeMUS().getTimeStamp() / paramEle.ZbinWidth + mTimeBinsPerDrift;
289 if (tpcitsTime > 0) {
290 const uint32_t clOccPosITSTPC = static_cast<uint32_t>(tpcitsTime * mOccupancyBinsPerTF / mTimeBinsPerTF);
291 if (clOccPosITSTPC < mITSTPCTrackOccupanyCombinedTime.size()) {
292 ++mITSTPCTrackOccupanyCombinedTime[clOccPosITSTPC];
293 }
294 }
295 }
296
297 auto fillDebug = [this](o2::utils::TreeStreamRedirector* streamer) {
298 if (streamer) {
299 *streamer << "occupancy"
300 << "tfCounter=" << mTFCount
301 << "clusterOcc=" << mClusterOccupancy
302 << "tpcTrackTimeOcc=" << mITSTPCTrackOccupanyTPCTime
303 << "itstpcTrackTimeOcc=" << mITSTPCTrackOccupanyCombinedTime
304 << "\n";
305 }
306 };
307
308 fillDebug(mDBGOutTPC.get());
309 fillDebug(mDBGOutITSTPC.get());
310}
311
313{
314 auto prop = o2::base::Propagator::Instance();
315
316 mITSTracksArray = recoData.getITSTracks();
317 mTPCTracksArray = recoData.getTPCTracks();
318 mITSTPCTracksArray = recoData.getTPCITSTracks();
319 mCosmics = recoData.getCosmicTracks();
320
321 mTPCTrackClusIdx = recoData.getTPCTracksClusterRefs();
322 mTPCClusterIdxStruct = &recoData.inputsTPCclusters->clusterIndex;
323 mTPCRefitterShMap = recoData.clusterShMapTPC;
324 mTPCRefitterOccMap = recoData.occupancyMapTPC;
325
326 LOGP(info, "Processing TF {} with {} its, {} tpc, {} its-tpc tracks and {} comsmics", mTFCount, mITSTracksArray.size(), mTPCTracksArray.size(), mITSTPCTracksArray.size(), mCosmics.size());
327 if (mUseMC) { // extract MC tracks
328 const o2::steer::DigitizationContext* digCont = nullptr;
329 if (!mcReader.initFromDigitContext("collisioncontext.root")) {
330 throw std::invalid_argument("initialization of MCKinematicsReader failed");
331 }
332 digCont = mcReader.getDigitizationContext();
333 mIntRecs = digCont->getEventRecords();
334 mTPCTrkLabels = recoData.getTPCTracksMCLabels();
335 }
336
337 mTPCRefitter = std::make_unique<o2::gpu::GPUO2InterfaceRefit>(mTPCClusterIdxStruct, &mTPCCorrMapsLoader, prop->getNominalBz(), mTPCTrackClusIdx.data(), 0, mTPCRefitterShMap.data(), mTPCRefitterOccMap.data(), mTPCRefitterOccMap.size(), nullptr, prop);
338 mTPCRefitter->setTrackReferenceX(900); // disable propagation after refit by setting reference to value > 500
339
340 mVdriftTB = mTPCVDriftHelper.getVDriftObject().getVDrift() * o2::tpc::ParameterElectronics::Instance().ZbinWidth; // VDrift expressed in cm/TimeBin
341 mTPCTBBias = mTPCVDriftHelper.getVDriftObject().getTimeOffset() / (8 * o2::constants::lhc::LHCBunchSpacingMUS);
342
343 auto dumpClusters = [this] {
344 static int tf = 0;
345 const auto* corrMap = this->mTPCCorrMapsLoader.getCorrMap();
346 for (int sector = 0; sector < 36; sector++) {
347 float alp = ((sector % 18) * 20 + 10) * TMath::DegToRad();
348 float sn = TMath::Sin(alp), cs = TMath::Cos(alp);
349 for (int row = 0; row < 152; row++) {
350 for (int ic = 0; ic < this->mTPCClusterIdxStruct->nClusters[sector][row]; ic++) {
351 const auto cl = this->mTPCClusterIdxStruct->clusters[sector][row][ic];
352 float x, y, z, xG, yG;
353 corrMap->TransformIdeal(sector, row, cl.getPad(), cl.getTime(), x, y, z, 0);
354 o2::math_utils::detail::rotateZ(x, y, xG, yG, sn, cs);
355 LOGP(debug, "tf:{} s:{} r:{} p:{} t:{} qm:{} qt:{} f:{} x:{} y:{} z:{}", tf, sector, row, cl.getPad(), cl.getTime(), cl.getQmax(), cl.getQtot(), cl.getFlags(), x, y, z);
356 (*mDBGOutCl) << "tpccl"
357 << "tf=" << tf << "sect=" << sector << "row=" << row << "pad=" << cl.getPad() << "time=" << cl.getTime() << "qmax=" << cl.getQmax() << "qtot=" << cl.getQtot()
358 << "sigT=" << cl.getSigmaTime() << "sigP=" << cl.getSigmaPad()
359 << "flags=" << cl.getFlags()
360 << "x=" << x << "y=" << y << "z=" << z << "xg=" << xG << "yg=" << yG
361 << "\n";
362 }
363 }
364 }
365 tf++;
366 };
367
368 if (mDBGOutCl) {
369 dumpClusters();
370 }
371
372 if ((mStudyType & StudyType::TPC) == StudyType::TPC) {
373 for (size_t itr = 0; itr < mTPCTracksArray.size(); itr++) {
374 processTPCTrack(mTPCTracksArray[itr], mUseMC ? mTPCTrkLabels[itr] : o2::MCCompLabel{}, mDBGOutTPC.get());
375 }
376 }
377
378 if ((mStudyType & StudyType::ITSTPC) == StudyType::ITSTPC) {
379 for (const auto& tpcitsTrack : mITSTPCTracksArray) {
380 const auto idxTPC = tpcitsTrack.getRefTPC().getIndex();
381 const auto idxITS = tpcitsTrack.getRefITS().getIndex();
382 if (idxITS >= mITSTracksArray.size()) {
383 LOGP(fatal, "ITS index {} out of array size {}", idxITS, mITSTracksArray.size());
384 }
385 if (idxTPC >= mTPCTracksArray.size()) {
386 LOGP(fatal, "TPC index {} out of array size {}", idxTPC, mTPCTracksArray.size());
387 }
388 processTPCTrack(mTPCTracksArray[idxTPC], mUseMC ? mTPCTrkLabels[idxTPC] : o2::MCCompLabel{}, mDBGOutITSTPC.get(), &mITSTracksArray[idxITS], &tpcitsTrack);
389 }
390 }
391
392 if (mCosmics.size() > 0) {
393 LOGP(info, "Procssing {} cosmics", mCosmics.size());
394 processCosmics(recoData);
395 }
396}
397
399{
400 mDBGOutTPC.reset();
401 mDBGOutITSTPC.reset();
402 mDBGOutTPCTF.reset();
403 mDBGOutITSTPCTF.reset();
404 mDBGOutCosmics.reset();
405 mDBGOutCl.reset();
406}
407
409{
411 return;
412 }
413 if (mTPCVDriftHelper.accountCCDBInputs(matcher, obj)) {
414 return;
415 }
416 if (mTPCCorrMapsLoader.accountCCDBInputs(matcher, obj)) {
417 return;
418 }
419}
420
421bool TPCRefitterSpec::getDCAs(const o2::track::TrackPar& track, float& dcar, float& dcaz)
422{
423 auto propagator = o2::base::Propagator::Instance();
425 const o2::math_utils::Point3D<float> refPoint{0, 0, 0};
426 o2::track::TrackPar propTrack(track);
427 const auto ok = propagator->propagateToDCABxByBz(refPoint, propTrack, 2., o2::base::Propagator::MatCorrType::USEMatCorrLUT, &dca);
428 dcar = dca[0];
429 dcaz = dca[1];
430 if (!ok) {
431 dcar = 9998.;
432 dcaz = 9998.;
433 }
434 return ok;
435}
436
437bool TPCRefitterSpec::processTPCTrack(o2::tpc::TrackTPC tr, o2::MCCompLabel lbl, o2::utils::TreeStreamRedirector* streamer, const o2::its::TrackITS* its, const o2::dataformats::TrackTPCITS* itstpc, bool outward, float time0custom)
438{
439 auto prop = o2::base::Propagator::Instance();
440 static long counter = -1;
441
442 struct ClusterData {
443 std::vector<int> occCl;
444 std::vector<short> clSector, clRow;
445 std::vector<float> clX, clY, clZ, clXI, clYI, clZI; // *I are the uncorrected cluster positions
446 std::vector<tpc::ClusterNative> clNative;
447 } clData;
448 float dcar, dcaz, dcarRef, dcazRef;
449
450 // auto tr = mTPCTracksArray[itr]; // create track copy
451 if (tr.hasBothSidesClusters()) {
452 return false;
453 }
454
455 bool sampleTsallis = false;
456 bool sampleMB = false;
457 float tsallisWeight = 0;
458 if (mDoSampling) {
459 std::uniform_real_distribution<> distr(0., 1.);
460 if (o2::math_utils::Tsallis::downsampleTsallisCharged(tr.getPt(), mSamplingFactor, mSqrt, tsallisWeight, distr(mGenerator))) {
461 sampleTsallis = true;
462 }
463 if (distr(mGenerator) < mSamplingFactor) {
464 sampleMB = true;
465 }
466
467 if (!sampleMB && !sampleTsallis) {
468 return false;
469 }
470 }
471 //=========================================================================
472 // create refitted copy
473 auto trackRefit = [&tr, this](o2::track::TrackParCov& trc, float t, float chi2refit, bool outward = false) -> bool {
474 int retVal = mUseGPUModel ? this->mTPCRefitter->RefitTrackAsGPU(trc, tr.getClusterRef(), t, &chi2refit, outward, true)
475 : this->mTPCRefitter->RefitTrackAsTrackParCov(trc, tr.getClusterRef(), t, &chi2refit, outward, true);
476 if (retVal < 0) {
477 LOGP(warn, "Refit failed ({}) with time={}: track#{}[{}]", retVal, t, counter, trc.asString());
478 return false;
479 }
480 return true;
481 };
482
483 auto trackProp = [&tr, prop, this](o2::track::TrackParCov& trc) -> bool {
484 if (!trc.rotate(tr.getAlpha())) {
485 LOGP(warn, "Rotation to original track alpha {} failed, track#{}[{}]", tr.getAlpha(), counter, trc.asString());
486 return false;
487 }
488 float xtgt = this->mXRef;
489 if (mUseR && !trc.getXatLabR(this->mXRef, xtgt, prop->getNominalBz(), o2::track::DirInward)) {
490 xtgt = 0;
491 return false;
492 }
493 if (!prop->PropagateToXBxByBz(trc, xtgt)) {
494 LOGP(warn, "Propagation to X={} failed, track#{}[{}]", xtgt, counter, trc.asString());
495 return false;
496 }
497 return true;
498 };
499
500 // auto prepClus = [this, &tr, &clSector, &clRow, &clX, &clY, &clZ, &clXI, &clYI, &clZI, &clNative](float t) { // extract cluster info
501 auto prepClus = [this, &tr, &clData](float t) { // extract cluster info
502 int count = tr.getNClusters();
503 const auto* corrMap = this->mTPCCorrMapsLoader.getCorrMap();
504 const o2::tpc::ClusterNative* cl = nullptr;
505 for (int ic = count; ic--;) {
506 uint8_t sector, row;
507 uint32_t clusterIndex;
508 o2::tpc::TrackTPC::getClusterReference(mTPCTrackClusIdx, ic, sector, row, clusterIndex, tr.getClusterRef());
509 unsigned int absoluteIndex = mTPCClusterIdxStruct->clusterOffset[sector][row] + clusterIndex;
510 cl = &mTPCClusterIdxStruct->clusters[sector][row][clusterIndex];
511 uint8_t clflags = cl->getFlags();
512 if (mTPCRefitterShMap[absoluteIndex] & o2::gpu::GPUTPCGMMergedTrackHit::flagShared) {
513 clflags |= 0x10;
514 }
515 clData.clSector.emplace_back(sector);
516 clData.clRow.emplace_back(row);
517 auto& clCopy = clData.clNative.emplace_back(*cl);
518 clCopy.setFlags(clflags);
519
520 float x, y, z;
521 // ideal transformation without distortions
522 corrMap->TransformIdeal(sector, row, cl->getPad(), cl->getTime(), x, y, z, t); // nominal time of the track
523 clData.clXI.emplace_back(x);
524 clData.clYI.emplace_back(y);
525 clData.clZI.emplace_back(z);
526
527 // transformation without distortions
528 mTPCCorrMapsLoader.Transform(sector, row, cl->getPad(), cl->getTime(), x, y, z, t); // nominal time of the track
529 clData.clX.emplace_back(x);
530 clData.clY.emplace_back(y);
531 clData.clZ.emplace_back(z);
532
533 // occupancy estimator
534 const auto tpcTime = cl->getTime() + mTimeBinsPerDrift;
535 const uint32_t clOccPosTPC = static_cast<uint32_t>(tpcTime * mOccupancyBinsPerTF / mTimeBinsPerTF);
536 clData.occCl.emplace_back((clOccPosTPC < mClusterOccupancy.size()) ? mClusterOccupancy[clOccPosTPC] : -1);
537 }
538 };
539
540 //=========================================================================
541
542 auto trf = tr.getOuterParam(); // we refit inward original track
543 float chi2refit = 0;
544 float time0 = tr.getTime0();
545 if (time0custom > 0) {
546 time0 = time0custom;
547 }
548 if (mDoRefit) {
549 if (!trackRefit(trf, time0, chi2refit) || !trackProp(trf)) {
550 return false;
551 }
552 }
553
554 // propagate original track
555 if (!trackProp(tr)) {
556 return false;
557 }
558
559 if (mWriteTrackClusters) {
560 prepClus(time0); // original clusters
561 }
562
563 if (mEnableDCA) {
564 dcar = dcaz = dcarRef = dcazRef = 9999.f;
565 if ((trf.getPt() > mDCAMinPt) && (tr.getNClusters() > mDCAMinNCl)) {
566 getDCAs(trf, dcarRef, dcazRef);
567 getDCAs(tr, dcar, dcaz);
568 }
569 }
570
571 counter++;
572 // store results
573 if (streamer) {
574 (*streamer) << "tpc"
575 << "counter=" << counter
576 << "tfCounter=" << mTFCount
577 << "tpc=" << tr;
578
579 if (mDoRefit) {
580 (*streamer) << "tpc"
581 << "tpcRF=" << trf
582 << "time0=" << time0
583 << "chi2refit=" << chi2refit;
584 }
585
586 if (mDoSampling) {
587 (*streamer) << "tpc"
588 << "tsallisWeight=" << tsallisWeight
589 << "sampleTsallis=" << sampleTsallis
590 << "sampleMB=" << sampleMB;
591 }
592
593 if (mWriteTrackClusters) {
594 (*streamer) << "tpc"
595 << "clSector=" << clData.clSector
596 << "clRow=" << clData.clRow;
597
598 if ((mWriteTrackClusters & 0x1) == 0x1) {
599 (*streamer) << "tpc"
600 << "cl=" << clData.clNative;
601 }
602
603 if ((mWriteTrackClusters & 0x2) == 0x2) {
604 (*streamer) << "tpc"
605 << "clX=" << clData.clX
606 << "clY=" << clData.clY
607 << "clZ=" << clData.clZ;
608 }
609
610 if ((mWriteTrackClusters & 0x4) == 0x4) {
611 (*streamer) << "tpc"
612 << "clXI=" << clData.clXI // ideal (uncorrected) cluster positions
613 << "clYI=" << clData.clYI // ideal (uncorrected) cluster positions
614 << "clZI=" << clData.clZI; // ideal (uncorrected) cluster positions
615 }
616
617 if ((mWriteTrackClusters & 0x8) == 0x8) {
618 (*streamer) << "tpc"
619 << "clOcc=" << clData.occCl;
620 }
621 }
622
623 if (its) {
624 (*streamer) << "tpc"
625 << "its=" << *its;
626 }
627 if (itstpc) {
628 (*streamer) << "tpc"
629 << "itstpc=" << *itstpc;
630 }
631
632 if (mEnableDCA) {
633 (*streamer) << "tpc"
634 << "dcar=" << dcar
635 << "dcaz=" << dcaz
636 << "dcarRef=" << dcarRef
637 << "dcazRef=" << dcazRef;
638 }
639
640 if (mUseMC) {
641 (*streamer) << "tpc"
642 << "mcLabel=" << lbl;
643 }
644
645 (*streamer) << "tpc"
646 << "\n";
647 }
648
649 float dz = 0;
650
651 if (mUseMC) { // impose MC time in TPC timebin and refit inward after resetted covariance
652 // extract MC truth
653 const o2::MCTrack* mcTrack = nullptr;
654 if (!lbl.isValid() || !(mcTrack = mcReader.getTrack(lbl))) {
655 return false;
656 }
657 long bc = mIntRecs[lbl.getEventID()].toLong(); // bunch crossing of the interaction
658 float bcTB = bc / 8. + mTPCTBBias; // the same in TPC timebins, accounting for the TPC time bias
659 // create MC truth track in O2 format
660 std::array<float, 3> xyz{(float)mcTrack->GetStartVertexCoordinatesX(), (float)mcTrack->GetStartVertexCoordinatesY(), (float)mcTrack->GetStartVertexCoordinatesZ()},
662 TParticlePDG* pPDG = TDatabasePDG::Instance()->GetParticle(mcTrack->GetPdgCode());
663 if (!pPDG) {
664 return false;
665 }
666 o2::track::TrackPar mctrO2(xyz, pxyz, TMath::Nint(pPDG->Charge() / 3), false);
667 //
668 // propagate it to the alpha/X of the reconstructed track
669 if (!mctrO2.rotate(tr.getAlpha()) || !prop->PropagateToXBxByBz(mctrO2, tr.getX())) {
670 return false;
671 }
672 // now create a properly refitted track with correct time and distortions correction
673 {
674 auto trfm = tr.getOuterParam(); // we refit inward
675 // impose MC time in TPC timebin and refit inward after resetted covariance
676 float chi2refit = 0;
677 if (!trackRefit(trfm, bcTB, chi2refit) || !trfm.rotate(tr.getAlpha()) || !prop->PropagateToXBxByBz(trfm, tr.getX())) {
678 LOGP(warn, "Failed to propagate MC-time refitted track#{} [{}] to X/alpha of original track [{}]", counter, trfm.asString(), tr.asString());
679 return false;
680 }
681 // estimate Z shift in case of no-distortions
682 dz = (tr.getTime0() - bcTB) * mVdriftTB;
683 if (tr.hasCSideClustersOnly()) {
684 dz = -dz;
685 }
686 //
687 prepClus(bcTB); // clusters for MC time
688 if (streamer) {
689 (*streamer) << "tpcMC"
690 << "counter=" << counter
691 << "movTrackRef=" << trfm
692 << "mcTrack=" << mctrO2
693 << "imposedTB=" << bcTB
694 << "chi2refit=" << chi2refit
695 << "dz=" << dz
696 << "clX=" << clData.clX
697 << "clY=" << clData.clY
698 << "clZ=" << clData.clZ
699 << "\n";
700 }
701 }
702 return false;
703 }
704
705 return true;
706}
707
708void TPCRefitterSpec::processCosmics(o2::globaltracking::RecoContainer& recoData)
709{
710 auto tof = recoData.getTOFClusters();
711 const auto& par = o2::tpc::ParameterElectronics::Instance();
712 const auto invBinWidth = 1.f / par.ZbinWidth;
713
714 for (const auto& cosmic : mCosmics) {
715 //
716 const auto& gidtop = cosmic.getRefTop();
717 const auto& gidbot = cosmic.getRefBottom();
718
719 // LOGP(info, "Sources: {} - {}", o2::dataformats::GlobalTrackID::getSourceName(gidtop.getSource()), o2::dataformats::GlobalTrackID::getSourceName(gidbot.getSource()));
720
721 std::array<GTrackID, GTrackID::NSources> contributorsGID[2] = {recoData.getSingleDetectorRefs(cosmic.getRefTop()), recoData.getSingleDetectorRefs(cosmic.getRefBottom())};
722 const auto trackTime = cosmic.getTimeMUS().getTimeStamp() * invBinWidth;
723
724 // check if track has TPC & TOF for top and bottom part
725 // loop over both parts
726 for (const auto& comsmicInfo : contributorsGID) {
727 auto& tpcGlobal = comsmicInfo[GTrackID::TPC];
728 auto& tofGlobal = comsmicInfo[GTrackID::TOF];
729 if (tpcGlobal.isIndexSet() && tofGlobal.isIndexSet()) {
730 const auto itrTPC = tpcGlobal.getIndex();
731 const auto itrTOF = tofGlobal.getIndex();
732 const auto& tofCl = tof[itrTOF];
733 const auto tofTime = tofCl.getTime() * 1e-6 * invBinWidth; // ps -> us -> time bins
734 const auto tofTimeRaw = tofCl.getTimeRaw() * 1e-6 * invBinWidth; // ps -> us -> time bins
735 const auto& trackTPC = mTPCTracksArray[itrTPC];
736 // LOGP(info, "Cosmic time: {}, TOF time: {}, TOF time raw: {}, TPC time: {}", trackTime, tofTime, tofTimeRaw, trackTPC.getTime0());
737 processTPCTrack(trackTPC, mUseMC ? mTPCTrkLabels[itrTPC] : o2::MCCompLabel{}, mDBGOutCosmics.get(), nullptr, nullptr, false, tofTime);
738 }
739 }
740 }
741}
742
743DataProcessorSpec getTPCRefitterSpec(GTrackID::mask_t srcTracks, GTrackID::mask_t srcClusters, bool useMC, const o2::tpc::CorrectionMapsLoaderGloOpts& sclOpts, bool requestCosmics)
744{
745 std::vector<OutputSpec> outputs;
746 Options opts{
747 {"target-x", VariantType::Float, 83.f, {"Try to propagate to this radius"}},
748 {"dump-clusters", VariantType::Bool, false, {"dump all clusters"}},
749 {"write-track-clusters", VariantType::Int, 3, {"Bitmask write clusters associated to the track, full native cluster (0x1), corrected (0x2) and uncorrected (0x4) positions, (0x8) occupancy info"}},
750 {"tf-start", VariantType::Int, 0, {"1st TF to process"}},
751 {"tf-end", VariantType::Int, 999999999, {"last TF to process"}},
752 {"use-gpu-fitter", VariantType::Bool, false, {"use GPU track model for refit instead of TrackParCov"}},
753 {"do-refit", VariantType::Bool, false, {"do refitting of TPC track"}},
754 {"use-r-as-x", VariantType::Bool, false, {"Use radius instead of target sector X"}},
755 {"enable-dcas", VariantType::Bool, false, {"Propagate to DCA and add it to the tree"}},
756 {"dcaMinPt", VariantType::Float, 1.f, {"Min pT of tracks propagated to DCA"}},
757 {"dcaMinNCl", VariantType::Int, 80, {"Min number of clusters for tracks propagated to DCA"}},
758 {"sqrts", VariantType::Float, 13600.f, {"Centre of mass energy used for downsampling"}},
759 {"do-sampling", VariantType::Bool, false, {"Perform sampling, min. bias and on Tsallis function, using 'sampling-factor'"}},
760 {"sampling-factor", VariantType::Float, 0.1f, {"Sampling factor in case sample-unbinned-tsallis is used"}},
761 {"study-type", VariantType::Int, 1, {"Bitmask of study type: 0x1 = TPC only, 0x2 = TPC + ITS, 0x4 = Cosmics"}},
762 {"writer-type", VariantType::Int, 1, {"Bitmask of writer type: 0x1 = per track streamer, 0x2 = per TF vectors"}},
763 {"occupancy-bins-per-drift", VariantType::UInt32, 31u, {"number of bin for occupancy histogram per drift time (500tb)"}},
764 };
765 auto dataRequest = std::make_shared<DataRequest>();
766
767 dataRequest->requestTracks(srcTracks, useMC);
768 dataRequest->requestClusters(srcClusters, useMC);
769 if (requestCosmics) {
770 dataRequest->requestCoscmicTracks(useMC);
771 }
772 auto ggRequest = std::make_shared<o2::base::GRPGeomRequest>(false, // orbitResetTime
773 true, // GRPECS=true
774 false, // GRPLHCIF
775 true, // GRPMagField
776 true, // askMatLUT
778 dataRequest->inputs,
779 true);
780 o2::tpc::VDriftHelper::requestCCDBInputs(dataRequest->inputs);
781 o2::tpc::CorrectionMapsLoader::requestCCDBInputs(dataRequest->inputs, opts, sclOpts);
782
783 return DataProcessorSpec{
784 "tpc-refitter",
785 dataRequest->inputs,
786 outputs,
787 AlgorithmSpec{adaptFromTask<TPCRefitterSpec>(dataRequest, ggRequest, sclOpts, srcTracks, useMC)},
788 opts};
789}
790
791} // namespace o2::trackstudy
Helper class to access load maps from CCDB.
Wrapper container for different reconstructed object types.
uint64_t bc
Definition RawEventData.h:5
int32_t retVal
Helper for geometry and GRP related CCDB requests.
Global index for barrel track: provides provenance (detectors combination), index in respective array...
Header to collect LHC related constants.
Definition of the parameter class for the detector electronics.
uint32_t padrow
Definition RawData.h:5
Wrapper container for different reconstructed object types.
Result of top-bottom cosmic tracks leg matching.
Helper class to extract VDrift from different sources.
std::ostringstream debug
int getEventID() const
bool isValid() const
Definition MCCompLabel.h:75
Double_t GetStartVertexMomentumZ() const
Definition MCTrack.h:81
Double_t GetStartVertexMomentumX() const
Definition MCTrack.h:79
Double_t GetStartVertexCoordinatesY() const
Definition MCTrack.h:83
Double_t GetStartVertexCoordinatesZ() const
Definition MCTrack.h:84
Double_t GetStartVertexMomentumY() const
Definition MCTrack.h:80
Double_t GetStartVertexCoordinatesX() const
Definition MCTrack.h:82
Int_t GetPdgCode() const
Accessors.
Definition MCTrack.h:72
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
Static class with identifiers, bitmasks and names for ALICE detectors.
Definition DetID.h:58
ConfigParamRegistry const & options()
Definition InitContext.h:33
ServiceRegistryRef services()
The services registry associated with this processing context.
std::vector< o2::InteractionTimeRecord > & getEventRecords(bool withQED=false)
bool initFromDigitContext(std::string_view filename)
DigitizationContext const * getDigitizationContext() const
MCTrack const * getTrack(o2::MCCompLabel const &) const
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
TPCRefitterSpec(std::shared_ptr< DataRequest > dr, std::shared_ptr< o2::base::GRPGeomRequest > gr, const o2::tpc::CorrectionMapsLoaderGloOpts &sclOpts, GTrackID::mask_t src, bool useMC)
void process(o2::globaltracking::RecoContainer &recoData)
void run(ProcessingContext &pc) final
void init(InitContext &ic) final
void endOfStream(EndOfStreamContext &ec) final
This is invoked whenever we have an EndOfStream event.
@ ITSTPC
TPC + ITS matched tracks.
bool getDCAs(const o2::track::TrackPar &track, float &dcar, float &dcaz)
@ Streamer
Write per track streamer information.
@ TFVectors
Writer vectors per TF.
void finaliseCCDB(ConcreteDataMatcher &matcher, void *obj) final
GLint GLenum GLint x
Definition glcorearb.h:403
GLenum src
Definition glcorearb.h:1767
GLint GLsizei count
Definition glcorearb.h:399
GLint y
Definition glcorearb.h:270
GLdouble GLdouble GLdouble z
Definition glcorearb.h:843
GLuint counter
Definition glcorearb.h:3987
uint8_t itsSharedClusterMap uint8_t
constexpr double LHCBunchSpacingMUS
constexpr int LHCMaxBunches
Defining PrimaryVertex explicitly as messageable.
Definition TFIDInfo.h:20
std::vector< ConfigParamSpec > Options
std::array< T, N > array
auto get(const std::byte *buffer, size_t=0)
Definition DataHeader.h:454
std::tuple< T, T > rotateZ(T xL, T yL, T snAlp, T csAlp)
detail::Bracket< float > Bracketf_t
Definition Primitive2D.h:40
return * this
constexpr int MAXSECTOR
Definition Constants.h:28
constexpr int MAXGLOBALPADROW
Definition Constants.h:34
TrackParCovF TrackParCov
Definition Track.h:33
o2::math_utils::Bracketf_t TBracket
o2::dataformats::VtxTrackRef V2TRef
o2::dataformats::VtxTrackIndex VTIndex
o2::framework::DataProcessorSpec getTPCRefitterSpec(o2::dataformats::GlobalTrackID::mask_t srcTracks, o2::dataformats::GlobalTrackID::mask_t srcClus, bool useMC, const o2::tpc::CorrectionMapsLoaderGloOpts &sclOpts, bool requestCosmics=false)
create a processor spec
@ sampleTsallis
perform sampling on tsallis pdf
a couple of static helper functions to create timestamp values for CCDB queries or override obsolete ...
Defining DataPointCompositeObject explicitly as copiable.
std::unique_ptr< GPUReconstructionTimeframe > tf
GlobalIDSet getSingleDetectorRefs(GTrackID gidx) const
gsl::span< const unsigned char > clusterShMapTPC
externally set TPC clusters sharing map
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
static bool downsampleTsallisCharged(float pt, float factorPt, float sqrts, float &weight, float rnd, float mass=0.13957)
Definition Tsallis.cxx:31
int nHBFPerTF
number of orbits per BC
Definition HBFUtils.h:138
unsigned int nClusters[constants::MAXSECTOR][constants::MAXGLOBALPADROW]
const ClusterNative * clusters[constants::MAXSECTOR][constants::MAXGLOBALPADROW]
unsigned int clusterOffset[constants::MAXSECTOR][constants::MAXGLOBALPADROW]
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)
std::uniform_int_distribution< unsigned long long > distr
std::vector< int > row