Project
Loading...
Searching...
No Matches
CalculatedEdx.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
16
18#include "TPCBase/PadPos.h"
19#include "TPCBase/ROC.h"
20#include "TPCBase/Mapper.h"
28#include "GPUO2InterfaceUtils.h"
30
31using namespace o2::tpc;
32
34{
35 mTPCCorrMapsHelper.setOwner(true);
36 mTPCCorrMapsHelper.setCorrMap(TPCFastTransformHelperO2::instance()->create(0));
37}
38
39void CalculatedEdx::setMembers(std::vector<o2::tpc::TPCClRefElem>* tpcTrackClIdxVecInput, const o2::tpc::ClusterNativeAccess& clIndex, std::vector<o2::tpc::TrackTPC>* vTPCTracksArrayInp)
40{
41 mTracks = vTPCTracksArrayInp;
42 mTPCTrackClIdxVecInput = tpcTrackClIdxVecInput;
43 mClusterIndex = &clIndex;
44}
45
46void CalculatedEdx::setRefit(const unsigned int nHbfPerTf)
47{
48 mTPCRefitterShMap.reserve(mClusterIndex->nClustersTotal);
49 auto sizeOcc = o2::gpu::GPUO2InterfaceRefit::fillOccupancyMapGetSize(nHbfPerTf, nullptr);
50 mTPCRefitterOccMap.resize(sizeOcc);
51 std::fill(mTPCRefitterOccMap.begin(), mTPCRefitterOccMap.end(), 0);
52 o2::gpu::GPUO2InterfaceRefit::fillSharedClustersAndOccupancyMap(mClusterIndex, *mTracks, mTPCTrackClIdxVecInput->data(), mTPCRefitterShMap.data(), mTPCRefitterOccMap.data(), nHbfPerTf);
53 mRefit = std::make_unique<o2::gpu::GPUO2InterfaceRefit>(mClusterIndex, &mTPCCorrMapsHelper, mFieldNominalGPUBz, mTPCTrackClIdxVecInput->data(), nHbfPerTf, mTPCRefitterShMap.data(), mTPCRefitterOccMap.data(), mTPCRefitterOccMap.size());
54}
55
56void CalculatedEdx::fillMissingClusters(int missingClusters[4], float minChargeTot, float minChargeMax, int method, std::array<std::vector<float>, 5>& chargeTotROC, std::array<std::vector<float>, 5>& chargeMaxROC)
57{
58 if (method != 0 && method != 1) {
59 LOGP(info, "Unrecognized subthreshold cluster treatment. Not adding virtual charges to the track!");
60 return;
61 }
62
63 for (int roc = 0; roc < 4; roc++) {
64 for (int i = 0; i < missingClusters[roc]; i++) {
65 float chargeTot = (method == 1) ? minChargeTot / 2.f : minChargeTot;
66 float chargeMax = (method == 1) ? minChargeMax / 2.f : minChargeMax;
67
68 chargeTotROC[roc].emplace_back(chargeTot);
69 chargeTotROC[4].emplace_back(chargeTot);
70
71 chargeMaxROC[roc].emplace_back(chargeMax);
72 chargeMaxROC[4].emplace_back(chargeMax);
73 }
74 }
75}
76
77void CalculatedEdx::calculatedEdx(o2::tpc::TrackTPC& track, dEdxInfo& output, float low, float high, CorrectionFlags correctionMask, ClusterFlags clusterMask, int subthresholdMethod, const char* debugRootFile)
78{
79 // get number of clusters
80 const int nClusters = track.getNClusterReferences();
81
82 int nClsROC[4] = {0, 0, 0, 0};
83 int nClsSubThreshROC[4] = {0, 0, 0, 0};
84
85 const int nType = 5;
86 std::array<std::vector<float>, nType> chargeTotROC;
87 std::array<std::vector<float>, nType> chargeMaxROC;
88 for (int i = 0; i < nType; ++i) {
89 chargeTotROC[i].reserve(Mapper::PADROWS);
90 chargeMaxROC[i].reserve(Mapper::PADROWS);
91 }
92
93 // debug vectors
94 std::vector<int> excludeClVector;
95 std::vector<int> regionVector;
96 std::vector<unsigned char> rowIndexVector;
97 std::vector<unsigned char> padVector;
98 std::vector<unsigned char> sectorVector;
99 std::vector<int> stackVector;
100 std::vector<float> localXVector;
101 std::vector<float> localYVector;
102 std::vector<float> offsPadVector;
103
104 std::vector<float> topologyCorrVector;
105 std::vector<float> topologyCorrTotVector;
106 std::vector<float> topologyCorrMaxVector;
107 std::vector<float> gainVector;
108 std::vector<float> gainResidualVector;
109 std::vector<float> residualCorrTotVector;
110 std::vector<float> residualCorrMaxVector;
111 std::vector<float> scCorrVector;
112
113 std::vector<o2::tpc::TrackTPC> trackVector;
114 std::vector<o2::tpc::ClusterNative> clVector;
115 std::vector<unsigned int> occupancyVector;
116 std::vector<bool> isClusterShared;
117
118 if (mDebug) {
119 excludeClVector.reserve(nClusters);
120 regionVector.reserve(nClusters);
121 rowIndexVector.reserve(nClusters);
122 padVector.reserve(nClusters);
123 stackVector.reserve(nClusters);
124 sectorVector.reserve(nClusters);
125 localXVector.reserve(nClusters);
126 localYVector.reserve(nClusters);
127 offsPadVector.reserve(nClusters);
128 topologyCorrVector.reserve(nClusters);
129 topologyCorrTotVector.reserve(nClusters);
130 topologyCorrMaxVector.reserve(nClusters);
131 gainVector.reserve(nClusters);
132 gainResidualVector.reserve(nClusters);
133 residualCorrTotVector.reserve(nClusters);
134 residualCorrMaxVector.reserve(nClusters);
135 trackVector.reserve(nClusters);
136 clVector.reserve(nClusters);
137 scCorrVector.reserve(nClusters);
138 occupancyVector.reserve(nClusters);
139 isClusterShared.reserve(nClusters);
140 }
141
142 // for missing clusters
143 unsigned char rowIndexOld = 0;
144 unsigned char sectorIndexOld = 0;
145 float minChargeTot = 100000.f;
146 float minChargeMax = 100000.f;
147
148 // loop over the clusters
149 for (int iCl = 0; iCl < nClusters; iCl++) {
150
151 const o2::tpc::ClusterNative& cl = track.getCluster(*mTPCTrackClIdxVecInput, iCl, *mClusterIndex);
152
153 unsigned char sectorIndex = 0;
154 unsigned char rowIndex = 0;
155 unsigned int clusterIndexNumb = 0;
156
157 // set sectorIndex, rowIndex, clusterIndexNumb
158 track.getClusterReference(*mTPCTrackClIdxVecInput, iCl, sectorIndex, rowIndex, clusterIndexNumb);
159
160 // check if the cluster is shared
161 const unsigned int absoluteIndex = mClusterIndex->clusterOffset[sectorIndex][rowIndex] + clusterIndexNumb;
162 const bool isShared = mRefit ? (mTPCRefitterShMap[absoluteIndex] & o2::gpu::GPUTPCGMMergedTrackHit::flagShared) : 0;
163
164 // get region, pad, stack and stack ID
165 const int region = Mapper::REGION[rowIndex];
166 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
167 const CRU cru(Sector(sectorIndex), region);
168 const auto stack = cru.gemStack();
169 StackID stackID{sectorIndex, stack};
170 // the stack number for debugging
171 const int stackNumber = static_cast<int>(stack);
172
173 // get local coordinates, offset and flags
174 const float localX = o2::tpc::Mapper::instance().getPadCentre(PadPos(rowIndex, pad)).X();
175 const float localY = Mapper::instance().getPadCentre(PadPos(rowIndex, pad)).Y();
176 const float offsPad = (cl.getPad() - pad) * o2::tpc::Mapper::instance().getPadRegionInfo(Mapper::REGION[rowIndex]).getPadWidth();
177 const auto flagsCl = cl.getFlags();
178
179 int excludeCl = 0; // works as a bit mask
181 excludeCl += 0b001; // 1 for single cluster
182 }
184 excludeCl += 0b010; // 2 for split cluster
185 }
187 excludeCl += 0b100; // 4 for edge cluster
188 }
189 if (((clusterMask & ClusterFlags::ExcludeSharedCl) == ClusterFlags::ExcludeSharedCl) && isShared) {
190 excludeCl += 0b10000; // for shared cluster
191 }
192
193 // get the x position of the track
194 const float xPosition = Mapper::instance().getPadCentre(PadPos(rowIndex, 0)).X();
195
196 bool check = true;
197 if (!mPropagateTrack) {
198 if (mRefit == nullptr) {
199 LOGP(error, "mRefit is a nullptr, call the function setRefit() before looping over the tracks.");
200 }
201 mRefit->setTrackReferenceX(xPosition);
202 check = (mRefit->RefitTrackAsGPU(track, false, true) < 0) ? false : true;
203 } else {
204 // propagate this track to the plane X=xk (cm) in the field "b" (kG)
205 track.rotate(o2::math_utils::detail::sector2Angle<float>(sectorIndex));
206 check = o2::base::Propagator::Instance()->PropagateToXBxByBz(track, xPosition, 0.999f, 2., o2::base::Propagator::MatCorrType::USEMatCorrLUT);
207 }
208
209 if (!check || std::isnan(track.getParam(1))) {
210 excludeCl += 0b1000; // 8 for failure of track propagation or refit
211 }
212
213 if (excludeCl != 0) {
214 // for debugging
215 if (mDebug) {
216 excludeClVector.emplace_back(excludeCl);
217 regionVector.emplace_back(region);
218 rowIndexVector.emplace_back(rowIndex);
219 padVector.emplace_back(pad);
220 sectorVector.emplace_back(sectorIndex);
221 stackVector.emplace_back(stackNumber);
222 localXVector.emplace_back(localX);
223 localYVector.emplace_back(localY);
224 offsPadVector.emplace_back(offsPad);
225 trackVector.emplace_back(track);
226 clVector.emplace_back(cl);
227 occupancyVector.emplace_back(getOccupancy(cl));
228 isClusterShared.emplace_back(isShared);
229
230 topologyCorrVector.emplace_back(-999.f);
231 topologyCorrTotVector.emplace_back(-999.f);
232 topologyCorrMaxVector.emplace_back(-999.f);
233 gainVector.emplace_back(-999.f);
234 gainResidualVector.emplace_back(-999.f);
235 residualCorrTotVector.emplace_back(-999.f);
236 residualCorrMaxVector.emplace_back(-999.f);
237 scCorrVector.emplace_back(-999.f);
238 }
239 // to avoid counting the skipped cluster as a subthreshold cluster
240 rowIndexOld = rowIndex;
241 sectorIndexOld = sectorIndex;
242 continue;
243 }
244
245 // get charge values
246 float chargeTot = cl.qTot;
247 float chargeMax = cl.qMax;
248
249 // get threshold
250 const float threshold = mCalibCont.getZeroSupressionThreshold(sectorIndex, rowIndex, pad);
251
252 // find missing clusters
253 int missingClusters = rowIndexOld - rowIndex - 1;
254 if ((missingClusters > 0) && (missingClusters <= mMaxMissingCl)) {
256 if (sectorIndexOld == sectorIndex) {
257 if (stack == GEMstack::IROCgem) {
258 nClsSubThreshROC[0] += missingClusters;
259 nClsROC[0] += missingClusters;
260 } else if (stack == GEMstack::OROC1gem) {
261 nClsSubThreshROC[1] += missingClusters;
262 nClsROC[1] += missingClusters;
263 } else if (stack == GEMstack::OROC2gem) {
264 nClsSubThreshROC[2] += missingClusters;
265 nClsROC[2] += missingClusters;
266 } else if (stack == GEMstack::OROC3gem) {
267 nClsSubThreshROC[3] += missingClusters;
268 nClsROC[3] += missingClusters;
269 }
270 }
271 } else {
272 if (stack == GEMstack::IROCgem) {
273 nClsSubThreshROC[0] += missingClusters;
274 nClsROC[0] += missingClusters;
275 } else if (stack == GEMstack::OROC1gem) {
276 nClsSubThreshROC[1] += missingClusters;
277 nClsROC[1] += missingClusters;
278 } else if (stack == GEMstack::OROC2gem) {
279 nClsSubThreshROC[2] += missingClusters;
280 nClsROC[2] += missingClusters;
281 } else if (stack == GEMstack::OROC3gem) {
282 nClsSubThreshROC[3] += missingClusters;
283 nClsROC[3] += missingClusters;
284 }
285 }
286 };
287 rowIndexOld = rowIndex;
288 sectorIndexOld = sectorIndex;
289
290 // get effective length
291 float effectiveLength = 1.0f;
292 float effectiveLengthTot = 1.0f;
293 float effectiveLengthMax = 1.0f;
295 effectiveLength = getTrackTopologyCorrection(track, region);
296 chargeTot /= effectiveLength;
297 chargeMax /= effectiveLength;
298 };
300 effectiveLengthTot = getTrackTopologyCorrectionPol(track, cl, region, chargeTot, ChargeType::Tot, threshold);
301 effectiveLengthMax = getTrackTopologyCorrectionPol(track, cl, region, chargeMax, ChargeType::Max, threshold);
302 chargeTot /= effectiveLengthTot;
303 chargeMax /= effectiveLengthMax;
304 };
305
306 // get gain
307 float gain = 1.0f;
308 float gainResidual = 1.0f;
309 if ((correctionMask & CorrectionFlags::GainFull) == CorrectionFlags::GainFull) {
310 gain = mCalibCont.getGain(sectorIndex, rowIndex, pad);
311 };
313 gainResidual = mCalibCont.getResidualGain(sectorIndex, rowIndex, pad);
314 };
315 chargeTot /= gain * gainResidual;
316 chargeMax /= gain * gainResidual;
317
318 // get dEdx correction on tgl and sector plane
319 float corrTot = 1.0f;
320 float corrMax = 1.0f;
322 corrTot = mCalibCont.getResidualCorrection(stackID, ChargeType::Tot, track.getTgl(), track.getSnp());
323 corrMax = mCalibCont.getResidualCorrection(stackID, ChargeType::Max, track.getTgl(), track.getSnp());
324 if (corrTot > 0) {
325 chargeTot /= corrTot;
326 };
327 if (corrMax > 0) {
328 chargeMax /= corrMax;
329 };
330 };
331
332 // set the min charge
333 if (chargeTot < minChargeTot) {
334 minChargeTot = chargeTot;
335 };
336
337 if (chargeMax < minChargeMax) {
338 minChargeMax = chargeMax;
339 };
340
341 // space-charge dEdx corrections
342 const float time = cl.getTime() - track.getTime0(); // ToDo: get correct time from ITS-TPC track if possible
343 float scCorr = 1.0f;
344 if ((correctionMask & CorrectionFlags::dEdxSC) == CorrectionFlags::dEdxSC) {
345 scCorr = mSCdEdxCorrection.getCorrection(time, sectorIndex, rowIndex, pad);
346 if (scCorr > 0) {
347 chargeTot /= scCorr;
348 };
349 if (corrMax > 0) {
350 chargeMax /= scCorr;
351 };
352 }
353
354 if (stack == GEMstack::IROCgem) {
355 chargeTotROC[0].emplace_back(chargeTot);
356 chargeMaxROC[0].emplace_back(chargeMax);
357 nClsROC[0]++;
358 } else if (stack == GEMstack::OROC1gem) {
359 chargeTotROC[1].emplace_back(chargeTot);
360 chargeMaxROC[1].emplace_back(chargeMax);
361 nClsROC[1]++;
362 } else if (stack == GEMstack::OROC2gem) {
363 chargeTotROC[2].emplace_back(chargeTot);
364 chargeMaxROC[2].emplace_back(chargeMax);
365 nClsROC[2]++;
366 } else if (stack == GEMstack::OROC3gem) {
367 chargeTotROC[3].emplace_back(chargeTot);
368 chargeMaxROC[3].emplace_back(chargeMax);
369 nClsROC[3]++;
370 };
371
372 chargeTotROC[4].emplace_back(chargeTot);
373 chargeMaxROC[4].emplace_back(chargeMax);
374
375 // for debugging
376 if (mDebug) {
377 excludeClVector.emplace_back(0); // cl is successfully processed
378 regionVector.emplace_back(region);
379 rowIndexVector.emplace_back(rowIndex);
380 padVector.emplace_back(pad);
381 sectorVector.emplace_back(sectorIndex);
382 stackVector.emplace_back(stackNumber);
383 localXVector.emplace_back(localX);
384 localYVector.emplace_back(localY);
385 offsPadVector.emplace_back(offsPad);
386 trackVector.emplace_back(track);
387 clVector.emplace_back(cl);
388 occupancyVector.emplace_back(getOccupancy(cl));
389 isClusterShared.emplace_back(isShared);
390
391 topologyCorrVector.emplace_back(effectiveLength);
392 topologyCorrTotVector.emplace_back(effectiveLengthTot);
393 topologyCorrMaxVector.emplace_back(effectiveLengthMax);
394 gainVector.emplace_back(gain);
395 gainResidualVector.emplace_back(gainResidual);
396 residualCorrTotVector.emplace_back(corrTot);
397 residualCorrMaxVector.emplace_back(corrMax);
398 scCorrVector.emplace_back(scCorr);
399 };
400 }
401
402 // number of clusters
403 output.NHitsSubThresholdIROC = nClsROC[0];
404 output.NHitsSubThresholdOROC1 = nClsROC[1];
405 output.NHitsSubThresholdOROC2 = nClsROC[2];
406 output.NHitsSubThresholdOROC3 = nClsROC[3];
407
408 // check if the lost clusters are subthreshold clusters based on the charge thresholds
409 if (minChargeTot <= mMinChargeTotThreshold && minChargeMax <= mMinChargeMaxThreshold) {
410 output.NHitsIROC = nClsROC[0] - nClsSubThreshROC[0];
411 output.NHitsOROC1 = nClsROC[1] - nClsSubThreshROC[1];
412 output.NHitsOROC2 = nClsROC[2] - nClsSubThreshROC[2];
413 output.NHitsOROC3 = nClsROC[3] - nClsSubThreshROC[3];
414
415 // fill subthreshold clusters if not excluded
417 fillMissingClusters(nClsSubThreshROC, minChargeTot, minChargeMax, subthresholdMethod, chargeTotROC, chargeMaxROC);
418 }
419 } else {
420 output.NHitsIROC = nClsROC[0];
421 output.NHitsOROC1 = nClsROC[1];
422 output.NHitsOROC2 = nClsROC[2];
423 output.NHitsOROC3 = nClsROC[3];
424 }
425
426 // copy corrected cluster charges
427 auto chargeTotVector = mDebug ? chargeTotROC[4] : std::vector<float>();
428 auto chargeMaxVector = mDebug ? chargeMaxROC[4] : std::vector<float>();
429
430 // calculate dEdx
431 output.dEdxTotIROC = getTruncMean(chargeTotROC[0], low, high);
432 output.dEdxTotOROC1 = getTruncMean(chargeTotROC[1], low, high);
433 output.dEdxTotOROC2 = getTruncMean(chargeTotROC[2], low, high);
434 output.dEdxTotOROC3 = getTruncMean(chargeTotROC[3], low, high);
435 output.dEdxTotTPC = getTruncMean(chargeTotROC[4], low, high);
436
437 output.dEdxMaxIROC = getTruncMean(chargeMaxROC[0], low, high);
438 output.dEdxMaxOROC1 = getTruncMean(chargeMaxROC[1], low, high);
439 output.dEdxMaxOROC2 = getTruncMean(chargeMaxROC[2], low, high);
440 output.dEdxMaxOROC3 = getTruncMean(chargeMaxROC[3], low, high);
441 output.dEdxMaxTPC = getTruncMean(chargeMaxROC[4], low, high);
442
443 // for debugging
444 if (mDebug) {
445 if (mStreamer == nullptr) {
446 setStreamer(debugRootFile);
447 }
448
449 (*mStreamer) << "dEdxDebug"
450 << "Ncl=" << nClusters
451 << "excludeClVector=" << excludeClVector
452 << "regionVector=" << regionVector
453 << "rowIndexVector=" << rowIndexVector
454 << "padVector=" << padVector
455 << "sectorVector=" << sectorVector
456 << "stackVector=" << stackVector
457 << "topologyCorrVector=" << topologyCorrVector
458 << "topologyCorrTotVector=" << topologyCorrTotVector
459 << "topologyCorrMaxVector=" << topologyCorrMaxVector
460 << "gainVector=" << gainVector
461 << "gainResidualVector=" << gainResidualVector
462 << "residualCorrTotVector=" << residualCorrTotVector
463 << "residualCorrMaxVector=" << residualCorrMaxVector
464 << "scCorrVector=" << scCorrVector
465 << "localXVector=" << localXVector
466 << "localYVector=" << localYVector
467 << "offsPadVector=" << offsPadVector
468 << "trackVector=" << trackVector
469 << "clVector=" << clVector
470 << "minChargeTot=" << minChargeTot
471 << "minChargeMax=" << minChargeMax
472 << "output=" << output
473 << "occupancy=" << occupancyVector
474 << "chargeTotVector=" << chargeTotVector
475 << "chargeMaxVector=" << chargeMaxVector
476 << "isClusterShared=" << isClusterShared
477 << "\n";
478 }
479}
480
481float CalculatedEdx::getTruncMean(std::vector<float>& charge, float low, float high) const
482{
483 // sort the charge vector
484 std::sort(charge.begin(), charge.end());
485
486 // calculate truncated mean
487 int nCl = 0;
488 float sum = 0;
489 size_t firstCl = charge.size() * low;
490 size_t lastCl = charge.size() * high;
491
492 for (size_t iCl = firstCl; iCl < lastCl; ++iCl) {
493 sum += charge[iCl];
494 ++nCl;
495 }
496
497 if (nCl > 0) {
498 sum /= nCl;
499 }
500 return sum;
501}
502
503float CalculatedEdx::getTrackTopologyCorrection(const o2::tpc::TrackTPC& track, const unsigned int region) const
504{
505 const float padLength = Mapper::instance().getPadRegionInfo(region).getPadHeight();
506 const float snp = track.getSnp();
507 const float tgl = track.getTgl();
508 const float snp2 = snp * snp;
509 const float tgl2 = tgl * tgl;
510 // calculate the trace length of the track over the pad
511 const float effectiveLength = padLength * std::sqrt((1 + tgl2) / (1 - snp2));
512 return effectiveLength;
513}
514
515float CalculatedEdx::getTrackTopologyCorrectionPol(const o2::tpc::TrackTPC& track, const o2::tpc::ClusterNative& cl, const unsigned int region, const float charge, ChargeType chargeType, const float threshold) const
516{
517 const float snp = std::abs(track.getSnp());
518 const float tgl = track.getTgl();
519 const float snp2 = snp * snp;
520 const float tgl2 = tgl * tgl;
521 const float sec2 = 1.f / (1.f - snp2);
522 const float tanTheta = std::sqrt(tgl2 * sec2);
523
524 const float z = std::abs(track.getParam(1));
525 const float padTmp = cl.getPad();
526 const float absRelPad = std::abs(padTmp - int(padTmp + 0.5f));
527 const float relTime = cl.getTime() - int(cl.getTime() + 0.5f);
528
529 const float effectiveLength = mCalibCont.getTopologyCorrection(region, chargeType, tanTheta, snp, z, absRelPad, relTime, threshold, charge);
530 return effectiveLength;
531}
532
533void CalculatedEdx::loadCalibsFromCCDB(long runNumberOrTimeStamp, const bool isMC)
534{
535 // setup CCDB manager
537 cm.setURL("http://alice-ccdb.cern.ch/");
538
539 auto tRun = runNumberOrTimeStamp;
540 if (runNumberOrTimeStamp < 10000000) {
541 auto runDuration = cm.getRunDuration(runNumberOrTimeStamp);
542 tRun = runDuration.first + (runDuration.second - runDuration.first) / 2; // time stamp for the middle of the run duration
543 }
544 LOGP(info, "Timestamp: {}", tRun);
545 cm.setTimestamp(tRun);
546
547 // set the track topology correction
549 o2::tpc::CalibdEdxTrackTopologyPol calibTrackTopology;
550 calibTrackTopology.setFromContainer(*calibTrackTopologyContainer);
551 mCalibCont.setPolTopologyCorrection(calibTrackTopology);
552
553 // set the gain map
555 const o2::tpc::CalDet<float> gainMapResidual = (*cm.getForTimeStamp<std::unordered_map<std::string, o2::tpc::CalDet<float>>>(o2::tpc::CDBTypeMap.at(o2::tpc::CDBType::CalPadGainResidual), tRun))["GainMap"];
556
557 const float minGain = 0;
558 const float maxGain = 2;
559 mCalibCont.setGainMap(*gainMap, minGain, maxGain);
560 mCalibCont.setGainMapResidual(gainMapResidual);
561
562 // set the residual dEdx correction
564
565 const auto* residualCorr = static_cast<o2::tpc::CalibdEdxCorrection*>(residualObj);
566 mCalibCont.setResidualCorrection(*residualCorr);
567
568 // set the zero supression threshold map
569 std::unordered_map<string, o2::tpc::CalDet<float>>* zeroSupressionThresholdMap = cm.getForTimeStamp<std::unordered_map<string, o2::tpc::CalDet<float>>>(o2::tpc::CDBTypeMap.at(o2::tpc::CDBType::ConfigFEEPad), tRun);
570 mCalibCont.setZeroSupresssionThreshold(zeroSupressionThresholdMap->at("ThresholdMap"));
571
572 // set the magnetic field
573 auto magField = cm.get<o2::parameters::GRPMagField>("GLO/Config/GRPMagField");
575 float bz = GPUO2InterfaceUtils::getNominalGPUBz(*magField);
576 LOGP(info, "Magnetic field: {}", bz);
578
579 // set the propagator
580 auto propagator = o2::base::Propagator::Instance();
582 propagator->setMatLUT(matLut);
583
584 // load sc correction maps
587
590
591 mSCdEdxCorrection.setCorrectionMaps(avgMap, derMap);
592}
593
594void CalculatedEdx::loadCalibsFromLocalCCDBFolder(const char* localCCDBFolder)
595{
596 setTrackTopologyCorrectionFromFile(localCCDBFolder, "/TPC/Calib/TopologyGainPiecewise/snapshot.root", "ccdb_object");
597 setGainMapFromFile(localCCDBFolder, "/TPC/Calib/PadGainFull/snapshot.root", "ccdb_object");
598 setGainMapResidualFromFile(localCCDBFolder, "/TPC/Calib/PadGainResidual/snapshot.root", "ccdb_object");
599 setResidualCorrectionFromFile(localCCDBFolder, "/TPC/Calib/TimeGain/snapshot.root", "ccdb_object");
600 setZeroSuppressionThresholdFromFile(localCCDBFolder, "/TPC/Config/FEEPad/snapshot.root", "ccdb_object");
601 setMagneticFieldFromFile(localCCDBFolder, "/GLO/Config/GRPMagField/snapshot.root", "ccdb_object");
602 setPropagatorFromFile(localCCDBFolder, "/GLO/Param/MatLUT/snapshot.root", "ccdb_object");
603}
604
605void CalculatedEdx::setTrackTopologyCorrectionFromFile(const char* folder, const char* file, const char* object)
606{
607 o2::tpc::CalibdEdxTrackTopologyPol calibTrackTopology;
608 calibTrackTopology.loadFromFile(fmt::format("{}{}", folder, file).data(), object);
609 mCalibCont.setPolTopologyCorrection(calibTrackTopology);
610}
611
612void CalculatedEdx::setGainMapFromFile(const char* folder, const char* file, const char* object)
613{
614 std::unique_ptr<TFile> gainMapFile(TFile::Open(fmt::format("{}{}", folder, file).data()));
615 if (!gainMapFile->IsZombie()) {
616 LOGP(info, "Using file: {}", gainMapFile->GetName());
617 o2::tpc::CalDet<float>* gainMap = (o2::tpc::CalDet<float>*)gainMapFile->Get(object);
618 mCalibCont.setGainMap(*gainMap, 0., 2.);
619 }
620}
621
622void CalculatedEdx::setGainMapResidualFromFile(const char* folder, const char* file, const char* object)
623{
624 std::unique_ptr<TFile> gainMapResidualFile(TFile::Open(fmt::format("{}{}", folder, file).data()));
625 if (!gainMapResidualFile->IsZombie()) {
626 LOGP(info, "Using file: {}", gainMapResidualFile->GetName());
627 std::unordered_map<string, o2::tpc::CalDet<float>>* gainMapResidual = (std::unordered_map<string, o2::tpc::CalDet<float>>*)gainMapResidualFile->Get(object);
628 mCalibCont.setGainMapResidual(gainMapResidual->at("GainMap"));
629 }
630}
631
632void CalculatedEdx::setResidualCorrectionFromFile(const char* folder, const char* file, const char* object)
633{
634 std::unique_ptr<TFile> calibdEdxResidualFile(TFile::Open(fmt::format("{}{}", folder, file).data()));
635 if (!calibdEdxResidualFile->IsZombie()) {
636 LOGP(info, "Using file: {}", calibdEdxResidualFile->GetName());
637 o2::tpc::CalibdEdxCorrection* calibdEdxResidual = (o2::tpc::CalibdEdxCorrection*)calibdEdxResidualFile->Get(object);
638 mCalibCont.setResidualCorrection(*calibdEdxResidual);
639 }
640}
641
642void CalculatedEdx::setZeroSuppressionThresholdFromFile(const char* folder, const char* file, const char* object)
643{
644 std::unique_ptr<TFile> zeroSuppressionFile(TFile::Open(fmt::format("{}{}", folder, file).data()));
645 if (!zeroSuppressionFile->IsZombie()) {
646 LOGP(info, "Using file: {}", zeroSuppressionFile->GetName());
647 std::unordered_map<string, o2::tpc::CalDet<float>>* zeroSupressionThresholdMap = (std::unordered_map<string, o2::tpc::CalDet<float>>*)zeroSuppressionFile->Get(object);
648 mCalibCont.setZeroSupresssionThreshold(zeroSupressionThresholdMap->at("ThresholdMap"));
649 }
650}
651
652void CalculatedEdx::setMagneticFieldFromFile(const char* folder, const char* file, const char* object)
653{
654 std::unique_ptr<TFile> magFile(TFile::Open(fmt::format("{}{}", folder, file).data()));
655 if (!magFile->IsZombie()) {
656 LOGP(info, "Using file: {}", magFile->GetName());
657 o2::parameters::GRPMagField* magField = (o2::parameters::GRPMagField*)magFile->Get(object);
659 float bz = GPUO2InterfaceUtils::getNominalGPUBz(*magField);
660 LOGP(info, "Magnetic field: {}", bz);
662 }
663}
664
665void CalculatedEdx::setPropagatorFromFile(const char* folder, const char* file, const char* object)
666{
667 auto propagator = o2::base::Propagator::Instance();
668 std::unique_ptr<TFile> matLutFile(TFile::Open(fmt::format("{}{}", folder, file).data()));
669 if (!matLutFile->IsZombie()) {
670 LOGP(info, "Using file: {}", matLutFile->GetName());
672 propagator->setMatLUT(matLut);
673 }
674}
675
677{
678 const int nTimeBinsPerOccupBin = 16;
679 const int iBinOcc = cl.getTime() / nTimeBinsPerOccupBin + 2;
680 const unsigned int occupancy = mTPCRefitterOccMap.empty() ? -1 : mTPCRefitterOccMap[iBinOcc];
681 return occupancy;
682}
Simple interface to the CDB manager.
Class of a TPC cluster in TPC-native coordinates (row, time)
int16_t charge
Definition RawEventData.h:5
int16_t time
Definition RawEventData.h:4
int32_t i
Header of the General Run Parameters object for B field values.
void output(const std::map< std::string, ChannelStat > &channels)
Definition rawdump.cxx:197
uint32_t roc
Definition RawData.h:3
uint32_t stack
Definition RawData.h:1
class to create TPC fast transformation
int nClusters
static MatLayerCylSet * rectifyPtrFromFile(MatLayerCylSet *ptr)
static int initFieldFromGRP(const o2::parameters::GRPMagField *grp, bool verbose=false)
GPUd() value_type estimateLTFast(o2 static GPUd() float estimateLTIncrement(const o2 PropagatorImpl * Instance(bool uninitialized=false)
Definition Propagator.h:143
static BasicCCDBManager & instance()
void setCorrMap(std::unique_ptr< o2::gpu::TPCFastTransform > &&m)
static size_t fillOccupancyMapGetSize(uint32_t nHbfPerTf, const GPUParam *param=nullptr)
static void fillSharedClustersAndOccupancyMap(const o2::tpc::ClusterNativeAccess *cl, const gsl::span< const o2::tpc::TrackTPC > trks, const o2::tpc::TPCClRefElem *trackRef, uint8_t *shmap, uint32_t *ocmap=nullptr, uint32_t nHbfPerTf=0, const GPUParam *param=nullptr)
static float getNominalGPUBz(T &src)
GEMstack gemStack() const
Definition CRU.h:82
unsigned int getOccupancy(const o2::tpc::ClusterNative &cl) const
void setFieldNominalGPUBz(const float field)
void loadCalibsFromCCDB(long runNumberOrTimeStamp, const bool isMC=false)
void fillMissingClusters(int missingClusters[4], float minChargeTot, float minChargeMax, int method, std::array< std::vector< float >, 5 > &chargeTotROC, std::array< std::vector< float >, 5 > &chargeMaxROC)
fill missing clusters with minimum charge (method=0) or minimum charge/2 (method=1) or Landau (method...
void setTrackTopologyCorrectionFromFile(const char *folder, const char *file, const char *object)
void loadCalibsFromLocalCCDBFolder(const char *localCCDBFolder)
void setZeroSuppressionThresholdFromFile(const char *folder, const char *file, const char *object)
void setPropagatorFromFile(const char *folder, const char *file, const char *object)
void setRefit(const unsigned int nHbfPerTf=32)
set the refitter
float getTrackTopologyCorrectionPol(const o2::tpc::TrackTPC &track, const o2::tpc::ClusterNative &cl, const unsigned int region, const float charge, ChargeType chargeType, const float threshold) const
void setMembers(std::vector< o2::tpc::TPCClRefElem > *tpcTrackClIdxVecInput, const o2::tpc::ClusterNativeAccess &clIndex, std::vector< o2::tpc::TrackTPC > *vTPCTracksArrayInp)
float getTruncMean(std::vector< float > &charge, float low, float high) const
void setResidualCorrectionFromFile(const char *folder, const char *file, const char *object)
float getTrackTopologyCorrection(const o2::tpc::TrackTPC &track, const unsigned int region) const
void calculatedEdx(TrackTPC &track, dEdxInfo &output, float low=0.015f, float high=0.6f, CorrectionFlags correctionMask=CorrectionFlags::TopologyPol|CorrectionFlags::dEdxResidual, ClusterFlags clusterMask=ClusterFlags::None, int subthresholdMethod=0, const char *debugRootFile="dEdxDebug.root")
void setMagneticFieldFromFile(const char *folder, const char *file, const char *object)
void setGainMapResidualFromFile(const char *folder, const char *file, const char *object)
void setStreamer(const char *debugRootFile)
set the debug streamer
void setGainMapFromFile(const char *folder, const char *file, const char *object)
void setGainMap(const CalDet< float > &gainMap, const float minGain, const float maxGain)
setting the gain map map from a CalDet
void setPolTopologyCorrection(const CalibdEdxTrackTopologyPol &calibTrackTopology)
void setZeroSupresssionThreshold(const CalDet< float > &thresholdMap)
void setResidualCorrection(const CalibdEdxCorrection &residualCorr)
void setGainMapResidual(const CalDet< float > &gainMapResidual, const float minResidualGain=0.7f, const float maxResidualGain=1.3f)
setting the gain map map from a CalDet
calibration class for the track topology correction of the dE/dx using multvariate polynomials
void loadFromFile(const char *fileName, const char *name)
void setFromContainer(const CalibdEdxTrackTopologyPolContainer &container)
float getCorrection(const float time, unsigned char sector, unsigned char padrow, int pad) const
void setCorrectionMaps(o2::gpu::TPCFastTransform *avg, o2::gpu::TPCFastTransform *der, const float lumi)
static const std::vector< unsigned int > PADSPERROW[NREGIONS]
number of pads per row in region
Definition Mapper.h:567
static unsigned int getLocalRowFromGlobalRow(const unsigned int row)
Definition Mapper.h:72
static Mapper & instance(const std::string mappingDir="")
Definition Mapper.h:44
const PadRegionInfo & getPadRegionInfo(const unsigned char region) const
Definition Mapper.h:385
static constexpr unsigned int PADROWS
total number of pad rows
Definition Mapper.h:528
GlobalPosition2D getPadCentre(const PadSecPos &padSec) const
Definition Mapper.h:163
static constexpr unsigned REGION[PADROWS]
region for global pad row
Definition Mapper.h:537
float getPadWidth() const
float getPadHeight() const
static TPCFastTransformHelperO2 * instance()
Singleton.
GLboolean * data
Definition glcorearb.h:298
GLdouble GLdouble GLdouble z
Definition glcorearb.h:843
void check(const std::vector< std::string > &arguments, const std::vector< ConfigParamSpec > &workflowOptions, const std::vector< DeviceSpec > &deviceSpecs, CheckMatrix &matrix)
Global TPC definitions and constants.
Definition SimTraits.h:167
@ IROCgem
Definition Defs.h:53
@ OROC1gem
Definition Defs.h:54
@ OROC3gem
Definition Defs.h:56
@ OROC2gem
Definition Defs.h:55
@ ExcludeSingleCl
flag to exclude single clusters in dEdx calculation
@ ExcludeSubthresholdCl
flag to exclude subthreshold clusters in dEdx calculation
@ ExcludeEdgeCl
flag to exclude sector edge clusters in dEdx calculation
@ ExcludeSectorBoundaries
flag to exclude sector boundary clusters in subthreshold cluster treatment
@ ExcludeSplitCl
flag to exclude split clusters in dEdx calculation
@ ExcludeSharedCl
flag to exclude clusters shared between tracks
ChargeType
Definition Defs.h:70
@ Tot
Definition Defs.h:72
@ Max
Definition Defs.h:71
const std::unordered_map< CDBType, const std::string > CDBTypeMap
Storage name in CCDB for each calibration and parameter type.
Definition CDBTypes.h:94
CorrectionFlags
dEdx calculation class
@ TopologyPol
flag for topology correction from polynomials
@ TopologySimple
flag for simple analytical topology correction
@ dEdxResidual
flag for residual dEdx correction
@ dEdxSC
flag for space-charge dEdx correction
@ GainFull
flag for full gain map from calibration container
@ GainResidual
flag for residuals gain map from calibration container
@ CalCorrMapMC
Cluster correction map (high IR rate distortions) for MC.
@ CalPadGainFull
Full pad gain calibration.
@ ConfigFEEPad
FEE pad-by-pad configuration map.
@ CalPadGainResidual
ResidualpPad gain calibration (e.g. from tracks)
@ CalTimeGain
Gain variation over time.
@ CalCorrMap
Cluster correction map (high IR rate distortions)
DataT sum(const Vector< DataT, N > &a)
Definition Vector.h:107
simple struct to enable writing the MultivariatePolynomialCT to file
unsigned int clusterOffset[constants::MAXSECTOR][constants::MAXGLOBALPADROW]
GEM stack identification.
Definition Defs.h:77