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