2626#include " CalibdEdxTrackTopologyPol.h"
2727#include " DataFormatsParameters/GRPMagField.h"
2828#include " GPUO2InterfaceUtils.h"
29+ #include " GPUTPCGMMergedTrackHit.h"
2930
3031using namespace o2 ::tpc;
3132
@@ -111,9 +112,12 @@ void CalculatedEdx::calculatedEdx(o2::tpc::TrackTPC& track, dEdxInfo& output, fl
111112 std::vector<float > gainResidualVector;
112113 std::vector<float > residualCorrTotVector;
113114 std::vector<float > residualCorrMaxVector;
115+ std::vector<float > scCorrVector;
114116
115117 std::vector<o2::tpc::TrackTPC> trackVector;
116118 std::vector<o2::tpc::ClusterNative> clVector;
119+ std::vector<unsigned int > occupancyVector;
120+ std::vector<bool > isClusterShared;
117121
118122 if (mDebug ) {
119123 excludeClVector.reserve (nClusters);
@@ -134,6 +138,9 @@ void CalculatedEdx::calculatedEdx(o2::tpc::TrackTPC& track, dEdxInfo& output, fl
134138 residualCorrMaxVector.reserve (nClusters);
135139 trackVector.reserve (nClusters);
136140 clVector.reserve (nClusters);
141+ scCorrVector.reserve (nClusters);
142+ occupancyVector.reserve (nClusters);
143+ isClusterShared.reserve (nClusters);
137144 }
138145
139146 // for missing clusters
@@ -154,6 +161,10 @@ void CalculatedEdx::calculatedEdx(o2::tpc::TrackTPC& track, dEdxInfo& output, fl
154161 // set sectorIndex, rowIndex, clusterIndexNumb
155162 track.getClusterReference (*mTPCTrackClIdxVecInput , iCl, sectorIndex, rowIndex, clusterIndexNumb);
156163
164+ // check if the cluster is shared
165+ const unsigned int absoluteIndex = mClusterIndex ->clusterOffset [sectorIndex][rowIndex] + clusterIndexNumb;
166+ const bool isShared = mRefit ? (mTPCRefitterShMap [absoluteIndex] & GPUCA_NAMESPACE::gpu::GPUTPCGMMergedTrackHit::flagShared) : 0 ;
167+
157168 // get region, pad, stack and stack ID
158169 const int region = Mapper::REGION[rowIndex];
159170 const unsigned char pad = std::clamp (static_cast <unsigned int >(cl.getPad () + 0 .5f ), static_cast <unsigned int >(0 ), Mapper::PADSPERROW[region][Mapper::getLocalRowFromGlobalRow (rowIndex)] - 1 ); // the left side of the pad is defined at e.g. 3.5 and the right side at 4.5
@@ -179,6 +190,9 @@ void CalculatedEdx::calculatedEdx(o2::tpc::TrackTPC& track, dEdxInfo& output, fl
179190 if (((clusterMask & ClusterFlags::ExcludeEdgeCl) == ClusterFlags::ExcludeEdgeCl) && ((flagsCl & ClusterNative::flagEdge) == ClusterNative::flagEdge)) {
180191 excludeCl += 0b100 ; // 4 for edge cluster
181192 }
193+ if (((clusterMask & ClusterFlags::ExcludeSharedCl) == ClusterFlags::ExcludeSharedCl) && isShared) {
194+ excludeCl += 0b10000 ; // for shared cluster
195+ }
182196
183197 // get the x position of the track
184198 const float xPosition = Mapper::instance ().getPadCentre (PadPos (rowIndex, 0 )).X ();
@@ -214,6 +228,8 @@ void CalculatedEdx::calculatedEdx(o2::tpc::TrackTPC& track, dEdxInfo& output, fl
214228 offsPadVector.emplace_back (offsPad);
215229 trackVector.emplace_back (track);
216230 clVector.emplace_back (cl);
231+ occupancyVector.emplace_back (getOccupancy (cl));
232+ isClusterShared.emplace_back (isShared);
217233
218234 topologyCorrVector.emplace_back (-999 .f );
219235 topologyCorrTotVector.emplace_back (-999 .f );
@@ -222,6 +238,7 @@ void CalculatedEdx::calculatedEdx(o2::tpc::TrackTPC& track, dEdxInfo& output, fl
222238 gainResidualVector.emplace_back (-999 .f );
223239 residualCorrTotVector.emplace_back (-999 .f );
224240 residualCorrMaxVector.emplace_back (-999 .f );
241+ scCorrVector.emplace_back (-999 .f );
225242 }
226243 // to avoid counting the skipped cluster as a subthreshold cluster
227244 rowIndexOld = rowIndex;
@@ -325,6 +342,19 @@ void CalculatedEdx::calculatedEdx(o2::tpc::TrackTPC& track, dEdxInfo& output, fl
325342 minChargeMax = chargeMax;
326343 };
327344
345+ // space-charge dEdx corrections
346+ const float time = cl.getTime () - track.getTime0 (); // ToDo: get correct time from ITS-TPC track if possible
347+ float scCorr = 1 .0f ;
348+ if ((correctionMask & CorrectionFlags::dEdxSC) == CorrectionFlags::dEdxSC) {
349+ scCorr = mSCdEdxCorrection .getCorrection (time, sectorIndex, rowIndex, pad);
350+ if (scCorr > 0 ) {
351+ chargeTot /= scCorr;
352+ };
353+ if (corrMax > 0 ) {
354+ chargeMax /= scCorr;
355+ };
356+ }
357+
328358 if (stack == GEMstack::IROCgem) {
329359 mChargeTotROC [0 ].emplace_back (chargeTot);
330360 mChargeMaxROC [0 ].emplace_back (chargeMax);
@@ -359,6 +389,8 @@ void CalculatedEdx::calculatedEdx(o2::tpc::TrackTPC& track, dEdxInfo& output, fl
359389 offsPadVector.emplace_back (offsPad);
360390 trackVector.emplace_back (track);
361391 clVector.emplace_back (cl);
392+ occupancyVector.emplace_back (getOccupancy (cl));
393+ isClusterShared.emplace_back (isShared);
362394
363395 topologyCorrVector.emplace_back (effectiveLength);
364396 topologyCorrTotVector.emplace_back (effectiveLengthTot);
@@ -367,6 +399,7 @@ void CalculatedEdx::calculatedEdx(o2::tpc::TrackTPC& track, dEdxInfo& output, fl
367399 gainResidualVector.emplace_back (gainResidual);
368400 residualCorrTotVector.emplace_back (corrTot);
369401 residualCorrMaxVector.emplace_back (corrMax);
402+ scCorrVector.emplace_back (scCorr);
370403 };
371404 }
372405
@@ -394,6 +427,10 @@ void CalculatedEdx::calculatedEdx(o2::tpc::TrackTPC& track, dEdxInfo& output, fl
394427 output.NHitsOROC3 = nClsROC[3 ];
395428 }
396429
430+ // copy corrected cluster charges
431+ auto chargeTotVector = mChargeTotROC [4 ];
432+ auto chargeMaxVector = mChargeMaxROC [4 ];
433+
397434 // calculate dEdx
398435 output.dEdxTotIROC = getTruncMean (mChargeTotROC [0 ], low, high);
399436 output.dEdxTotOROC1 = getTruncMean (mChargeTotROC [1 ], low, high);
@@ -428,6 +465,7 @@ void CalculatedEdx::calculatedEdx(o2::tpc::TrackTPC& track, dEdxInfo& output, fl
428465 << " gainResidualVector=" << gainResidualVector
429466 << " residualCorrTotVector=" << residualCorrTotVector
430467 << " residualCorrMaxVector=" << residualCorrMaxVector
468+ << " scCorrVector=" << scCorrVector
431469 << " localXVector=" << localXVector
432470 << " localYVector=" << localYVector
433471 << " offsPadVector=" << offsPadVector
@@ -436,6 +474,10 @@ void CalculatedEdx::calculatedEdx(o2::tpc::TrackTPC& track, dEdxInfo& output, fl
436474 << " minChargeTot=" << minChargeTot
437475 << " minChargeMax=" << minChargeMax
438476 << " output=" << output
477+ << " occupancy=" << occupancyVector
478+ << " chargeTotVector=" << chargeTotVector
479+ << " chargeMaxVector=" << chargeMaxVector
480+ << " isClusterShared=" << isClusterShared
439481 << " \n " ;
440482 }
441483}
@@ -492,7 +534,7 @@ float CalculatedEdx::getTrackTopologyCorrectionPol(const o2::tpc::TrackTPC& trac
492534 return effectiveLength;
493535}
494536
495- void CalculatedEdx::loadCalibsFromCCDB (long runNumberOrTimeStamp)
537+ void CalculatedEdx::loadCalibsFromCCDB (long runNumberOrTimeStamp, const bool isMC )
496538{
497539 // setup CCDB manager
498540 auto & cm = o2::ccdb::BasicCCDBManager::instance ();
@@ -542,6 +584,15 @@ void CalculatedEdx::loadCalibsFromCCDB(long runNumberOrTimeStamp)
542584 auto propagator = o2::base::Propagator::Instance ();
543585 const o2::base::MatLayerCylSet* matLut = o2::base::MatLayerCylSet::rectifyPtrFromFile (cm.get <o2::base::MatLayerCylSet>(" GLO/Param/MatLUT" ));
544586 propagator->setMatLUT (matLut);
587+
588+ // load sc correction maps
589+ auto avgMap = isMC ? cm.getForTimeStamp <o2::gpu::TPCFastTransform>(o2::tpc::CDBTypeMap.at (o2::tpc::CDBType::CalCorrMapMC), tRun) : cm.getForTimeStamp <o2::gpu::TPCFastTransform>(o2::tpc::CDBTypeMap.at (o2::tpc::CDBType::CalCorrMap), tRun);
590+ avgMap->rectifyAfterReadingFromFile ();
591+
592+ auto derMap = isMC ? cm.getForTimeStamp <o2::gpu::TPCFastTransform>(o2::tpc::CDBTypeMap.at (o2::tpc::CDBType::CalCorrDerivMapMC), tRun) : cm.getForTimeStamp <o2::gpu::TPCFastTransform>(o2::tpc::CDBTypeMap.at (o2::tpc::CDBType::CalCorrDerivMap), tRun);
593+ derMap->rectifyAfterReadingFromFile ();
594+
595+ mSCdEdxCorrection .setCorrectionMaps (avgMap, derMap);
545596}
546597
547598void CalculatedEdx::loadCalibsFromLocalCCDBFolder (const char * localCCDBFolder)
@@ -624,4 +675,12 @@ void CalculatedEdx::setPropagatorFromFile(const char* folder, const char* file,
624675 o2::base::MatLayerCylSet* matLut = o2::base::MatLayerCylSet::rectifyPtrFromFile ((o2::base::MatLayerCylSet*)matLutFile->Get (object));
625676 propagator->setMatLUT (matLut);
626677 }
627- }
678+ }
679+
680+ unsigned int CalculatedEdx::getOccupancy (const o2::tpc::ClusterNative& cl) const
681+ {
682+ const int nTimeBinsPerOccupBin = 16 ;
683+ const int iBinOcc = cl.getTime () / nTimeBinsPerOccupBin + 2 ;
684+ const unsigned int occupancy = mTPCRefitterOccMap .empty () ? -1 : mTPCRefitterOccMap [iBinOcc];
685+ return occupancy;
686+ }
0 commit comments