89#include "Math/SMatrix.h"
95#include <unordered_map>
100#include "TLorentzVector.h"
108#include <nlohmann/json.hpp>
129 uint64_t classMaskEMCAL = 0, classMaskTRD = 0, classMaskPHOSCPV = 0;
130 for (
const auto& trgclass : ctpcfg->getCTPClasses()) {
131 if (trgclass.cluster->getClusterDetNames().find(
"EMC") != std::string::npos) {
132 classMaskEMCAL = trgclass.classMask;
134 if (trgclass.cluster->getClusterDetNames().find(
"PHS") != std::string::npos) {
135 classMaskPHOSCPV = trgclass.classMask;
137 if (trgclass.cluster->getClusterDetNames().find(
"TRD") != std::string::npos) {
138 classMaskTRD = trgclass.classMask;
141 LOG(info) <<
"createCTPReadout: Class Mask EMCAL -> " << classMaskEMCAL;
142 LOG(info) <<
"createCTPReadout: Class Mask PHOS/CPV -> " << classMaskPHOSCPV;
143 LOG(info) <<
"createCTPReadout: Class Mask TRD -> " << classMaskTRD;
151 std::vector<o2::emcal::TriggerRecord> triggerRecordEMCALPhys;
152 for (
const auto& trg : triggerrecordEMCAL) {
156 triggerRecordEMCALPhys.push_back(trg);
162 std::set<uint64_t> bcsMapT0triggers;
164 for (
auto& ft0RecPoint : ft0RecPoints) {
165 auto t0triggers = ft0RecPoint.getTrigger();
166 if (t0triggers.getVertex()) {
167 uint64_t globalBC = ft0RecPoint.getInteractionRecord().toLong();
168 bcsMapT0triggers.insert(globalBC);
172 auto genericCTPDigitizer = [&bcsMapT0triggers, &ctpDigits](
auto triggerrecords, uint64_t classmask) ->
int {
176 uint32_t orbitPrev = 0;
178 for (
auto& trigger : triggerrecords) {
179 auto orbitPrevT = orbitPrev;
180 auto bcPrevT = bcPrev;
181 bcPrev = trigger.getBCData().bc;
182 orbitPrev = trigger.getBCData().orbit;
188 uint64_t globalBC = trigger.getBCData().toLong();
189 auto t0entry = bcsMapT0triggers.find(globalBC);
190 if (t0entry != bcsMapT0triggers.end()) {
191 auto ctpdig = std::find_if(ctpDigits.begin(), ctpDigits.end(), [globalBC](
const o2::ctp::CTPDigit& dig) { return static_cast<uint64_t>(dig.intRecord.toLong()) == globalBC; });
192 if (ctpdig != ctpDigits.end()) {
194 ctpdig->CTPClassMask |= std::bitset<64>(classmask);
195 LOG(
debug) <<
"createCTPReadout: Merging " << classmask <<
" CTP digits with existing digit, CTP mask " << ctpdig->CTPClassMask;
198 LOG(
debug) <<
"createCTPReadout: New CTP digit needed for class " << classmask << std::endl;
199 auto& ctpdigNew = ctpDigits.emplace_back();
200 ctpdigNew.intRecord.setFromLong(globalBC);
201 ctpdigNew.CTPClassMask = classmask;
204 LOG(warning) <<
"createCTPReadout: Found " << classmask <<
" and no MTVX:" << globalBC;
211 auto warningsTRD = genericCTPDigitizer(triggerrecordTRD, classMaskTRD);
212 auto warningsEMCAL = genericCTPDigitizer(triggerRecordEMCALPhys, classMaskEMCAL);
213 auto warningsPHOSCPV = genericCTPDigitizer(triggerrecordPHOSCPV, classMaskPHOSCPV);
215 LOG(info) <<
"createCTPReadout:# of TRD bogus triggers:" << warningsTRD;
216 LOG(info) <<
"createCTPReadout:# of EMCAL bogus triggers:" << warningsEMCAL;
217 LOG(info) <<
"createCTPReadout:# of PHOS/CPV bogus triggers:" << warningsPHOSCPV;
221 const std::vector<o2::InteractionTimeRecord>& mcRecords,
222 std::map<uint64_t, int>& bcsMap)
224 const auto& primVertices =
data.getPrimaryVertices();
225 const auto& fddRecPoints =
data.getFDDRecPoints();
226 const auto& ft0RecPoints =
data.getFT0RecPoints();
227 const auto& fv0RecPoints =
data.getFV0RecPoints();
228 const auto& caloEMCCellsTRGR =
data.getEMCALTriggers();
229 const auto& caloPHOSCellsTRGR =
data.getPHOSTriggers();
230 const auto& cpvTRGR =
data.getCPVTriggers();
231 const auto& ctpDigits =
data.getCTPDigits();
232 const auto& zdcBCRecData =
data.getZDCBCRecData();
234 bcsMap[mStartIR.
toLong()] = 1;
237 for (
auto&
rec : mcRecords) {
238 uint64_t globalBC =
rec.toLong();
239 bcsMap[globalBC] = 1;
242 for (
auto& fddRecPoint : fddRecPoints) {
243 uint64_t globalBC = fddRecPoint.getInteractionRecord().toLong();
244 bcsMap[globalBC] = 1;
247 for (
auto& ft0RecPoint : ft0RecPoints) {
248 uint64_t globalBC = ft0RecPoint.getInteractionRecord().toLong();
249 bcsMap[globalBC] = 1;
252 for (
auto& fv0RecPoint : fv0RecPoints) {
253 uint64_t globalBC = fv0RecPoint.getInteractionRecord().toLong();
254 bcsMap[globalBC] = 1;
257 for (
auto& zdcRecData : zdcBCRecData) {
258 uint64_t globalBC = zdcRecData.ir.toLong();
259 bcsMap[globalBC] = 1;
262 for (
auto&
vertex : primVertices) {
263 auto& timeStamp =
vertex.getTimeStamp();
264 double tsTimeStamp = timeStamp.getTimeStamp() * 1E3;
265 uint64_t globalBC = relativeTime_to_GlobalBC(tsTimeStamp);
266 bcsMap[globalBC] = 1;
269 for (
auto& emcaltrg : caloEMCCellsTRGR) {
270 uint64_t globalBC = emcaltrg.getBCData().toLong();
271 bcsMap[globalBC] = 1;
274 for (
auto& phostrg : caloPHOSCellsTRGR) {
275 uint64_t globalBC = phostrg.getBCData().toLong();
276 bcsMap[globalBC] = 1;
279 for (
auto& cpvtrg : cpvTRGR) {
280 uint64_t globalBC = cpvtrg.getBCData().toLong();
281 bcsMap[globalBC] = 1;
284 for (
auto& ctpDigit : ctpDigits) {
285 uint64_t globalBC = ctpDigit.intRecord.toLong();
286 bcsMap[globalBC] = 1;
290 for (
auto& item : bcsMap) {
296template <
typename TracksCursorType,
typename TracksCovCursorType>
297void AODProducerWorkflowDPL::addToTracksTable(TracksCursorType& tracksCursor, TracksCovCursorType& tracksCovCursor,
300 tracksCursor(collisionID,
302 truncateFloatFraction(track.getX(), mTrackX),
303 truncateFloatFraction(track.getAlpha(), mTrackAlpha),
306 truncateFloatFraction(track.getSnp(), mTrackSnp),
307 truncateFloatFraction(track.getTgl(), mTrackTgl),
308 truncateFloatFraction(track.getQ2Pt(), mTrack1Pt));
310 float sY = TMath::Sqrt(track.getSigmaY2()), sZ = TMath::Sqrt(track.getSigmaZ2()), sSnp = TMath::Sqrt(track.getSigmaSnp2()),
311 sTgl = TMath::Sqrt(track.getSigmaTgl2()), sQ2Pt = TMath::Sqrt(track.getSigma1Pt2());
312 tracksCovCursor(truncateFloatFraction(sY, mTrackCovDiag),
313 truncateFloatFraction(sZ, mTrackCovDiag),
314 truncateFloatFraction(sSnp, mTrackCovDiag),
315 truncateFloatFraction(sTgl, mTrackCovDiag),
316 truncateFloatFraction(sQ2Pt, mTrackCovDiag),
317 (Char_t)(128. * track.getSigmaZY() / (sZ * sY)),
318 (Char_t)(128. * track.getSigmaSnpY() / (sSnp * sY)),
319 (Char_t)(128. * track.getSigmaSnpZ() / (sSnp * sZ)),
320 (Char_t)(128. * track.getSigmaTglY() / (sTgl * sY)),
321 (Char_t)(128. * track.getSigmaTglZ() / (sTgl * sZ)),
322 (Char_t)(128. * track.getSigmaTglSnp() / (sTgl * sSnp)),
323 (Char_t)(128. * track.getSigma1PtY() / (sQ2Pt * sY)),
324 (Char_t)(128. * track.getSigma1PtZ() / (sQ2Pt * sZ)),
325 (Char_t)(128. * track.getSigma1PtSnp() / (sQ2Pt * sSnp)),
326 (Char_t)(128. * track.getSigma1PtTgl() / (sQ2Pt * sTgl)));
329template <
typename TracksExtraCursorType>
330void AODProducerWorkflowDPL::addToTracksExtraTable(TracksExtraCursorType& tracksExtraCursor, TrackExtraInfo& extraInfoHolder)
334 auto trackTimeRes = extraInfoHolder.trackTimeRes;
335 if (!extraInfoHolder.isTPConly) {
336 trackTimeRes = truncateFloatFraction(trackTimeRes, mTrackTimeError);
340 tracksExtraCursor(truncateFloatFraction(extraInfoHolder.tpcInnerParam, mTrack1Pt),
341 extraInfoHolder.flags,
342 extraInfoHolder.itsClusterSizes,
343 extraInfoHolder.tpcNClsFindable,
344 extraInfoHolder.tpcNClsFindableMinusFound,
345 extraInfoHolder.tpcNClsFindableMinusPID,
346 extraInfoHolder.tpcNClsFindableMinusCrossedRows,
347 extraInfoHolder.tpcNClsShared,
348 extraInfoHolder.trdPattern,
349 truncateFloatFraction(extraInfoHolder.itsChi2NCl, mTrackChi2),
350 truncateFloatFraction(extraInfoHolder.tpcChi2NCl, mTrackChi2),
351 truncateFloatFraction(extraInfoHolder.trdChi2, mTrackChi2),
352 truncateFloatFraction(extraInfoHolder.tofChi2, mTrackChi2),
353 truncateFloatFraction(extraInfoHolder.tpcSignal, mTrackSignal),
354 truncateFloatFraction(extraInfoHolder.trdSignal, mTrackSignal),
355 truncateFloatFraction(extraInfoHolder.length, mTrackSignal),
356 truncateFloatFraction(extraInfoHolder.tofExpMom, mTrack1Pt),
357 truncateFloatFraction(extraInfoHolder.trackEtaEMCAL, mTrackPosEMCAL),
358 truncateFloatFraction(extraInfoHolder.trackPhiEMCAL, mTrackPosEMCAL),
359 truncateFloatFraction(extraInfoHolder.trackTime, mTrackTime),
363template <
typename TracksQACursorType>
364void AODProducerWorkflowDPL::addToTracksQATable(TracksQACursorType& tracksQACursor,
TrackQA& trackQAInfoHolder)
367 trackQAInfoHolder.trackID,
368 mTrackQCRetainOnlydEdx ? 0.0f : truncateFloatFraction(trackQAInfoHolder.tpcTime0, mTPCTime0),
369 truncateFloatFraction(trackQAInfoHolder.tpcdEdxNorm, mTrackSignal),
370 mTrackQCRetainOnlydEdx ? std::numeric_limits<int16_t>::min() : trackQAInfoHolder.tpcdcaR,
371 mTrackQCRetainOnlydEdx ? std::numeric_limits<int16_t>::min() : trackQAInfoHolder.tpcdcaZ,
372 trackQAInfoHolder.tpcClusterByteMask,
373 trackQAInfoHolder.tpcdEdxMax0R,
374 trackQAInfoHolder.tpcdEdxMax1R,
375 trackQAInfoHolder.tpcdEdxMax2R,
376 trackQAInfoHolder.tpcdEdxMax3R,
377 trackQAInfoHolder.tpcdEdxTot0R,
378 trackQAInfoHolder.tpcdEdxTot1R,
379 trackQAInfoHolder.tpcdEdxTot2R,
380 trackQAInfoHolder.tpcdEdxTot3R,
381 mTrackQCRetainOnlydEdx ? std::numeric_limits<int8_t>::min() : trackQAInfoHolder.dRefContY,
382 mTrackQCRetainOnlydEdx ? std::numeric_limits<int8_t>::min() : trackQAInfoHolder.dRefContZ,
383 mTrackQCRetainOnlydEdx ? std::numeric_limits<int8_t>::min() : trackQAInfoHolder.dRefContSnp,
384 mTrackQCRetainOnlydEdx ? std::numeric_limits<int8_t>::min() : trackQAInfoHolder.dRefContTgl,
385 mTrackQCRetainOnlydEdx ? std::numeric_limits<int8_t>::min() : trackQAInfoHolder.dRefContQ2Pt,
386 mTrackQCRetainOnlydEdx ? std::numeric_limits<int8_t>::min() : trackQAInfoHolder.dRefGloY,
387 mTrackQCRetainOnlydEdx ? std::numeric_limits<int8_t>::min() : trackQAInfoHolder.dRefGloZ,
388 mTrackQCRetainOnlydEdx ? std::numeric_limits<int8_t>::min() : trackQAInfoHolder.dRefGloSnp,
389 mTrackQCRetainOnlydEdx ? std::numeric_limits<int8_t>::min() : trackQAInfoHolder.dRefGloTgl,
390 mTrackQCRetainOnlydEdx ? std::numeric_limits<int8_t>::min() : trackQAInfoHolder.dRefGloQ2Pt,
391 mTrackQCRetainOnlydEdx ? std::numeric_limits<int8_t>::min() : trackQAInfoHolder.dTofdX,
392 mTrackQCRetainOnlydEdx ? std::numeric_limits<int8_t>::min() : trackQAInfoHolder.dTofdZ);
395template <
typename TRDsExtraCursorType>
398 int q0s[6] = {-1}, q1s[6] = {-1}, q2s[6] = {-1};
399 float q0sCor[6] = {-1}, q1sCor[6] = {-1}, q2sCor[6] = {-1};
400 float ttgls[6] = {-999}, tphis[6] = {-999};
410 for (
int iLay{0}; iLay < 6; ++iLay) {
411 q0s[iLay] = q1s[iLay] = q2s[iLay] = -1;
412 q0sCor[iLay] = q1sCor[iLay] = q2sCor[iLay] = -1;
413 tphis[iLay] = ttgls[iLay] = -999;
414 auto trkltId = trk.getTrackletIndex(iLay);
418 const auto& tracklet = trklets[trkltId];
423 int trkltDet = tracklet.getDetector();
424 int trkltSec = trkltDet / 30;
434 auto tphi = trkC.getSnp() / std::sqrt((1.f - trkC.getSnp()) * (1.f + trkC.getSnp()));
435 auto trackletLength = std::sqrt(1.f + tphi * tphi + trkC.getTgl() * trkC.getTgl());
437 q0s[iLay] = tracklet.getQ0();
438 q1s[iLay] = tracklet.getQ1();
439 q2s[iLay] = tracklet.getQ2();
440 q0sCor[iLay] = (float)tracklet.getQ0() / cor;
441 q1sCor[iLay] = (float)tracklet.getQ1() / cor;
442 q2sCor[iLay] = (float)tracklet.getQ2() / cor;
443 ttgls[iLay] = trkC.getTgl();
447 if (trk.getIsCrossingNeighbor(iLay) && trk.getHasNeighbor()) {
450 size_t trdSelID = -1;
452 const auto& trig = trigsTRD[mCurrentTRDTrigID];
453 bool foundTRDTrigger =
false;
455 if (trkltId >= trig.getFirstTracklet() && trkltId < trig.getFirstTracklet() + trig.getNumberOfTracklets()) {
456 trdSelID = mCurrentTRDTrigID;
457 foundTRDTrigger =
true;
460 if (mCurrentTRDTrigID < trigsTRD.size() - 1) {
461 const auto& trig = trigsTRD[mCurrentTRDTrigID + 1];
462 if (trkltId >= trig.getFirstTracklet() && trkltId < trig.getFirstTracklet() + trig.getNumberOfTracklets()) {
463 trdSelID = mCurrentTRDTrigID + 1;
464 foundTRDTrigger =
true;
469 size_t low = 0, up = trigsTRD.size() - 1;
472 while (low <= up && !foundTRDTrigger) {
473 trdSelID = low + std::floor((up - low) / 2);
474 const auto& trig = trigsTRD[trdSelID];
475 if (trig.getFirstTracklet() > trkltId) {
478 if (trig.getFirstTracklet() + trig.getNumberOfTracklets() <= trkltId) {
481 foundTRDTrigger =
true;
486 mCurrentTRDTrigID = trdSelID;
487 const auto& trigSel = trigsTRD[trdSelID];
490 for (
const auto& trklt : trklets.subspan(trigSel.getFirstTracklet(), trigSel.getNumberOfTracklets())) {
491 if (tracklet.getTrackletWord() == trklt.getTrackletWord() || tracklet.getDetector() != trklt.getDetector()) {
494 if (std::abs(tracklet.getPadCol() - trklt.getPadCol()) <= 1 && std::abs(tracklet.getPadRow() - trklt.getPadRow()) == 1) {
496 q0s[iLay] += trklt.getQ0();
497 q1s[iLay] += trklt.getQ1();
498 q2s[iLay] += trklt.getQ2();
499 q0sCor[iLay] += (float)trklt.getQ0() / cor;
500 q1sCor[iLay] += (float)trklt.getQ1() / cor;
501 q2sCor[iLay] += (float)trklt.getQ2() / cor;
507 trdExtraCursor(trkTableIdx, q0s, q1s, q2s, q0sCor, q1sCor, q2sCor, ttgls, tphis);
510template <
typename mftTracksCursorType,
typename AmbigMFTTracksCursorType>
511void AODProducerWorkflowDPL::addToMFTTracksTable(mftTracksCursorType& mftTracksCursor, AmbigMFTTracksCursorType& ambigMFTTracksCursor,
513 std::uint64_t collisionBC,
const std::map<uint64_t, int>& bcsMap)
516 int bcSlice[2] = {-1, -1};
517 const auto& track =
data.getMFTTrack(trackID);
518 const auto& rof =
data.getMFTTracksROFRecords()[mMFTROFs[trackID.getIndex()]];
520 float trackTimeRes = mMFTROFrameHalfLengthNS;
521 bool needBCSlice = collisionID < 0;
522 std::uint64_t bcOfTimeRef;
524 double error = mTimeMarginTrackTime + trackTimeRes;
525 bcOfTimeRef = fillBCSlice(bcSlice, trackTime - error, trackTime + error, bcsMap);
527 bcOfTimeRef = collisionBC - mStartIR.
toLong();
532 uint64_t mftClusterSizesAndTrackFlags = track.getClusterSizes();
533 mftClusterSizesAndTrackFlags |= (track.isCA()) ? (1ULL << (60)) : 0;
535 mftTracksCursor(collisionID,
538 truncateFloatFraction(track.getZ(), mTrackX),
539 truncateFloatFraction(track.getPhi(), mTrackAlpha),
540 truncateFloatFraction(track.getTanl(), mTrackTgl),
541 truncateFloatFraction(track.getInvQPt(), mTrack1Pt),
542 mftClusterSizesAndTrackFlags,
543 truncateFloatFraction(track.getTrackChi2(), mTrackChi2),
544 truncateFloatFraction(trackTime, mTrackTime),
545 truncateFloatFraction(trackTimeRes, mTrackTimeError));
547 ambigMFTTracksCursor(mTableTrMFTID, bcSlice);
550template <
typename TracksCursorType,
typename TracksCovCursorType,
typename TracksExtraCursorType,
typename TracksQACursorType,
typename TRDsExtraCursor,
typename AmbigTracksCursorType,
551 typename MFTTracksCursorType,
typename MFTTracksCovCursorType,
typename AmbigMFTTracksCursorType,
552 typename FwdTracksCursorType,
typename FwdTracksCovCursorType,
typename AmbigFwdTracksCursorType,
typename FwdTrkClsCursorType>
553void AODProducerWorkflowDPL::fillTrackTablesPerCollision(
int collisionID,
554 std::uint64_t collisionBC,
556 const gsl::span<const GIndex>& GIndices,
558 TracksCursorType& tracksCursor,
559 TracksCovCursorType& tracksCovCursor,
560 TracksExtraCursorType& tracksExtraCursor,
561 TracksQACursorType& tracksQACursor,
562 TRDsExtraCursor& trdsExtraCursor,
563 AmbigTracksCursorType& ambigTracksCursor,
564 MFTTracksCursorType& mftTracksCursor,
565 MFTTracksCovCursorType& mftTracksCovCursor,
566 AmbigMFTTracksCursorType& ambigMFTTracksCursor,
567 FwdTracksCursorType& fwdTracksCursor,
568 FwdTracksCovCursorType& fwdTracksCovCursor,
569 AmbigFwdTracksCursorType& ambigFwdTracksCursor,
570 FwdTrkClsCursorType& fwdTrkClsCursor,
571 const std::map<uint64_t, int>& bcsMap)
574 if (!GIndex::isTrackSource(
src)) {
581 mftTracksCursor.reserve(nToReserve + mftTracksCursor.lastIndex());
583 fwdTracksCursor.reserve(nToReserve + fwdTracksCursor.lastIndex());
584 fwdTracksCovCursor.reserve(nToReserve + fwdTracksCovCursor.lastIndex());
586 mftTracksCovCursor.reserve(nToReserve + mftTracksCovCursor.lastIndex());
589 tracksCursor.reserve(nToReserve + tracksCursor.lastIndex());
590 tracksCovCursor.reserve(nToReserve + tracksCovCursor.lastIndex());
591 tracksExtraCursor.reserve(nToReserve + tracksExtraCursor.lastIndex());
593 for (
int ti =
start; ti <
end; ti++) {
594 const auto& trackIndex = GIndices[ti];
595 if (GIndex::includesSource(
src, mInputSources)) {
597 if (trackIndex.isAmbiguous() && mGIDToTableMFTID.find(trackIndex) != mGIDToTableMFTID.end()) {
600 addToMFTTracksTable(mftTracksCursor, ambigMFTTracksCursor, trackIndex,
data, collisionID, collisionBC, bcsMap);
601 mGIDToTableMFTID.emplace(trackIndex, mTableTrMFTID);
604 if (trackIndex.isAmbiguous() && mGIDToTableFwdID.find(trackIndex) != mGIDToTableFwdID.end()) {
607 addToFwdTracksTable(fwdTracksCursor, fwdTracksCovCursor, ambigFwdTracksCursor, mftTracksCovCursor, trackIndex,
data, collisionID, collisionBC, bcsMap);
608 mGIDToTableFwdID.emplace(trackIndex, mTableTrFwdID);
609 addClustersToFwdTrkClsTable(
data, fwdTrkClsCursor, trackIndex, mTableTrFwdID);
613 if (trackIndex.isAmbiguous() && mGIDToTableID.find(trackIndex) != mGIDToTableID.end()) {
618 static std::uniform_real_distribution<>
distr(0., 1.);
620 auto extraInfoHolder = processBarrelTrack(collisionID, collisionBC, trackIndex,
data, bcsMap);
623 auto trackQAInfoHolder = processBarrelTrackQA(collisionID, collisionBC, trackIndex,
data, bcsMap);
624 if (std::bitset<8>(trackQAInfoHolder.tpcClusterByteMask).count() >= mTrackQCNTrCut) {
625 trackQAInfoHolder.trackID = mTableTrID;
629 addToTracksQATable(tracksQACursor, trackQAInfoHolder);
636 if (mThinTracks && extraInfoHolder.isTPConly && !writeQAData) {
637 auto trk =
data.getTPCTrack(trackIndex);
638 if (trk.getNClusters() >= mTrackQCNCls && trk.getPt() >= mTrackQCPt) {
648 if (mThinTracks &&
src ==
GIndex::Source::TPC && mGIDUsedBySVtx.find(trackIndex) == mGIDUsedBySVtx.end() && mGIDUsedByStr.find(trackIndex) == mGIDUsedByStr.end() && !writeQAData) {
649 mGIDToTableID.emplace(trackIndex, -1);
653 if (!extraInfoHolder.isTPConly && extraInfoHolder.trackTimeRes < 0.f) {
654 LOG(warning) <<
"Barrel track " << trackIndex <<
" has no time set, rejection is not expected : time=" << extraInfoHolder.trackTime
655 <<
" timeErr=" << extraInfoHolder.trackTimeRes <<
" BCSlice: " << extraInfoHolder.bcSlice[0] <<
":" << extraInfoHolder.bcSlice[1];
658 const auto& trOrig =
data.getTrackParam(trackIndex);
660 if (mPropTracks && trOrig.getX() < mMaxPropXiu &&
661 mGIDUsedBySVtx.find(trackIndex) == mGIDUsedBySVtx.end() &&
662 mGIDUsedByStr.find(trackIndex) == mGIDUsedByStr.end()) {
663 auto trackPar(trOrig);
664 isProp = propagateTrackToPV(trackPar,
data, collisionID);
666 addToTracksTable(tracksCursor, tracksCovCursor, trackPar, collisionID,
aod::track::Track);
672 addToTracksExtraTable(tracksExtraCursor, extraInfoHolder);
674 addToTRDsExtra(
data, trdsExtraCursor, trackIndex, mTableTrID);
677 if (extraInfoHolder.bcSlice[0] >= 0 && collisionID < 0) {
678 ambigTracksCursor(mTableTrID, extraInfoHolder.bcSlice);
680 mGIDToTableID.emplace(trackIndex, mTableTrID);
686 if (collisionID < 0) {
690 auto sTracks =
data.getStrangeTracks();
691 tracksCursor.reserve(mVertexStrLUT[collisionID + 1] + tracksCursor.lastIndex());
692 tracksCovCursor.reserve(mVertexStrLUT[collisionID + 1] + tracksCovCursor.lastIndex());
693 tracksExtraCursor.reserve(mVertexStrLUT[collisionID + 1] + tracksExtraCursor.lastIndex());
694 for (
int iS{mVertexStrLUT[collisionID]}; iS < mVertexStrLUT[collisionID + 1]; ++iS) {
695 auto& collStrTrk = mCollisionStrTrk[iS];
696 auto& sTrk = sTracks[collStrTrk.second];
697 TrackExtraInfo extraInfo;
698 extraInfo.itsChi2NCl = sTrk.mTopoChi2;
699 extraInfo.itsClusterSizes = sTrk.getClusterSizes();
701 addToTracksExtraTable(tracksExtraCursor, extraInfo);
702 mStrTrkIndices[collStrTrk.second] = mTableTrID;
709 const auto& mchmidMatches =
data.getMCHMIDMatches();
714 for (
int ti =
start; ti <
end; ti++) {
715 auto& trackIndex = GIndices[ti];
716 if (GIndex::includesSource(
src, mInputSources)) {
718 if (trackIndex.isAmbiguous() && mGIDToTableMFTID.find(trackIndex) != mGIDToTableMFTID.end()) {
721 mGIDToTableMFTID.emplace(trackIndex, mIndexMFTID);
722 mIndexTableMFT[trackIndex.getIndex()] = mIndexMFTID;
725 if (trackIndex.isAmbiguous() && mGIDToTableFwdID.find(trackIndex) != mGIDToTableFwdID.end()) {
728 mGIDToTableFwdID.emplace(trackIndex, mIndexFwdID);
730 mIndexTableFwd[trackIndex.getIndex()] = mIndexFwdID;
732 const auto& mchmidMatch = mchmidMatches[trackIndex.getIndex()];
733 const auto mchTrackID = mchmidMatch.getMCHRef().getIndex();
734 mIndexTableFwd[mchTrackID] = mIndexFwdID;
743template <
typename FwdTracksCursorType,
typename FwdTracksCovCursorType,
typename AmbigFwdTracksCursorType,
typename mftTracksCovCursorType>
744void AODProducerWorkflowDPL::addToFwdTracksTable(FwdTracksCursorType& fwdTracksCursor, FwdTracksCovCursorType& fwdTracksCovCursor,
745 AmbigFwdTracksCursorType& ambigFwdTracksCursor, mftTracksCovCursorType& mftTracksCovCursor,
GIndex trackID,
747 const std::map<uint64_t, int>& bcsMap)
749 const auto& mchTracks =
data.getMCHTracks();
750 const auto& midTracks =
data.getMIDTracks();
751 const auto& mchmidMatches =
data.getMCHMIDMatches();
752 const auto& mchClusters =
data.getMCHTrackClusters();
754 FwdTrackInfo fwdInfo;
755 FwdTrackCovInfo fwdCovInfo;
756 int bcSlice[2] = {-1, -1};
759 auto getMCHBitMap = [&](
int mchTrackID) {
760 if (mchTrackID != -1) {
761 const auto& mchTrack = mchTracks[mchTrackID];
762 int first = mchTrack.getFirstClusterIdx();
763 int last = mchTrack.getLastClusterIdx();
764 for (
int i =
first;
i <= last;
i++) {
765 const auto& cluster = mchClusters[
i];
766 int chamberId = cluster.getChamberId();
767 fwdInfo.mchBitMap |= 1 << chamberId;
772 auto getMIDBitMapBoards = [&](
int midTrackID) {
773 if (midTrackID != -1) {
774 const auto& midTrack = midTracks[midTrackID];
775 fwdInfo.midBitMap = midTrack.getHitMap();
776 fwdInfo.midBoards = midTrack.getEfficiencyWord();
780 auto extrapMCHTrack = [&](
int mchTrackID) {
781 const auto& track = mchTracks[mchTrackID];
789 float vx = 0, vy = 0, vz = 0;
790 if (collisionID >= 0) {
791 const auto&
v =
data.getPrimaryVertex(collisionID);
797 o2::mch::TrackParam trackParamAtVertex(track.getZ(), track.getParameters(), track.getCovariances());
820 double dca = std::sqrt(dcaX * dcaX + dcaY * dcaY);
825 double dpdca = track.getP() * dca;
826 double dchi2 = track.getChi2OverNDF();
828 auto fwdmuon = mMatching.
MCHtoFwd(trackParamAtVertex);
830 fwdInfo.x = fwdmuon.
getX();
831 fwdInfo.y = fwdmuon.getY();
832 fwdInfo.z = fwdmuon.getZ();
833 fwdInfo.phi = fwdmuon.getPhi();
834 fwdInfo.tanl = fwdmuon.getTgl();
835 fwdInfo.invqpt = fwdmuon.getInvQPt();
836 fwdInfo.rabs = std::sqrt(xAbs * xAbs + yAbs * yAbs);
837 fwdInfo.chi2 = dchi2;
838 fwdInfo.pdca = dpdca;
839 fwdInfo.nClusters = track.getNClusters();
841 fwdCovInfo.sigX = TMath::Sqrt(fwdmuon.getCovariances()(0, 0));
842 fwdCovInfo.sigY = TMath::Sqrt(fwdmuon.getCovariances()(1, 1));
843 fwdCovInfo.sigPhi = TMath::Sqrt(fwdmuon.getCovariances()(2, 2));
844 fwdCovInfo.sigTgl = TMath::Sqrt(fwdmuon.getCovariances()(3, 3));
845 fwdCovInfo.sig1Pt = TMath::Sqrt(fwdmuon.getCovariances()(4, 4));
846 fwdCovInfo.rhoXY = (Char_t)(128. * fwdmuon.getCovariances()(0, 1) / (fwdCovInfo.sigX * fwdCovInfo.sigY));
847 fwdCovInfo.rhoPhiX = (Char_t)(128. * fwdmuon.getCovariances()(0, 2) / (fwdCovInfo.sigPhi * fwdCovInfo.sigX));
848 fwdCovInfo.rhoPhiY = (Char_t)(128. * fwdmuon.getCovariances()(1, 2) / (fwdCovInfo.sigPhi * fwdCovInfo.sigY));
849 fwdCovInfo.rhoTglX = (Char_t)(128. * fwdmuon.getCovariances()(0, 3) / (fwdCovInfo.sigTgl * fwdCovInfo.sigX));
850 fwdCovInfo.rhoTglY = (Char_t)(128. * fwdmuon.getCovariances()(1, 3) / (fwdCovInfo.sigTgl * fwdCovInfo.sigY));
851 fwdCovInfo.rhoTglPhi = (Char_t)(128. * fwdmuon.getCovariances()(2, 3) / (fwdCovInfo.sigTgl * fwdCovInfo.sigPhi));
852 fwdCovInfo.rho1PtX = (Char_t)(128. * fwdmuon.getCovariances()(0, 4) / (fwdCovInfo.sig1Pt * fwdCovInfo.sigX));
853 fwdCovInfo.rho1PtY = (Char_t)(128. * fwdmuon.getCovariances()(1, 4) / (fwdCovInfo.sig1Pt * fwdCovInfo.sigY));
854 fwdCovInfo.rho1PtPhi = (Char_t)(128. * fwdmuon.getCovariances()(2, 4) / (fwdCovInfo.sig1Pt * fwdCovInfo.sigPhi));
855 fwdCovInfo.rho1PtTgl = (Char_t)(128. * fwdmuon.getCovariances()(3, 4) / (fwdCovInfo.sig1Pt * fwdCovInfo.sigTgl));
861 int mchTrackID = trackID.getIndex();
862 getMCHBitMap(mchTrackID);
863 if (!extrapMCHTrack(mchTrackID)) {
864 LOGF(warn,
"Unable to extrapolate MCH track with ID %d! Dummy parameters will be used", mchTrackID);
867 const auto& rof =
data.getMCHTracksROFRecords()[mMCHROFs[mchTrackID]];
868 auto time = rof.getTimeMUS(mStartIR).first;
869 fwdInfo.trackTime =
time.getTimeStamp() * 1.e3;
870 fwdInfo.trackTimeRes =
time.getTimeStampError() * 1.e3;
873 auto mchmidMatch = mchmidMatches[trackID.getIndex()];
874 auto mchTrackID = mchmidMatch.getMCHRef().getIndex();
875 if (!extrapMCHTrack(mchTrackID)) {
876 LOGF(warn,
"Unable to extrapolate MCH track with ID %d! Dummy parameters will be used", mchTrackID);
878 auto midTrackID = mchmidMatch.getMIDRef().getIndex();
879 fwdInfo.chi2matchmchmid = mchmidMatch.getMatchChi2OverNDF();
880 getMCHBitMap(mchTrackID);
881 getMIDBitMapBoards(midTrackID);
882 auto time = mchmidMatch.getTimeMUS(mStartIR).first;
883 fwdInfo.trackTime =
time.getTimeStamp() * 1.e3;
884 fwdInfo.trackTimeRes =
time.getTimeStampError() * 1.e3;
886 const auto& track =
data.getGlobalFwdTrack(trackID);
887 const auto& mftTracks =
data.getMFTTracks();
888 const auto& mfttrack = mftTracks[track.getMFTTrackID()];
889 if (!extrapMCHTrack(track.getMCHTrackID())) {
890 LOGF(warn,
"Unable to extrapolate MCH track with ID %d! Dummy parameters will be used", track.getMCHTrackID());
892 fwdInfo.x = track.getX();
893 fwdInfo.y = track.getY();
894 fwdInfo.z = track.getZ();
895 fwdInfo.phi = track.getPhi();
896 fwdInfo.tanl = track.getTanl();
897 fwdInfo.invqpt = track.getInvQPt();
898 fwdInfo.chi2 = track.getTrackChi2();
900 fwdInfo.chi2matchmchmid = track.getMIDMatchingChi2();
901 fwdInfo.chi2matchmchmft = track.getMFTMCHMatchingChi2();
902 fwdInfo.matchscoremchmft = track.getMFTMCHMatchingScore();
903 fwdInfo.matchmfttrackid = mIndexTableMFT[track.getMFTTrackID()];
904 fwdInfo.matchmchtrackid = mIndexTableFwd[track.getMCHTrackID()];
905 fwdInfo.trackTime = track.getTimeMUS().getTimeStamp() * 1.e3;
906 fwdInfo.trackTimeRes = track.getTimeMUS().getTimeStampError() * 1.e3;
908 getMCHBitMap(track.getMCHTrackID());
909 getMIDBitMapBoards(track.getMIDTrackID());
911 fwdCovInfo.sigX = TMath::Sqrt(track.getCovariances()(0, 0));
912 fwdCovInfo.sigY = TMath::Sqrt(track.getCovariances()(1, 1));
913 fwdCovInfo.sigPhi = TMath::Sqrt(track.getCovariances()(2, 2));
914 fwdCovInfo.sigTgl = TMath::Sqrt(track.getCovariances()(3, 3));
915 fwdCovInfo.sig1Pt = TMath::Sqrt(track.getCovariances()(4, 4));
916 fwdCovInfo.rhoXY = (Char_t)(128. * track.getCovariances()(0, 1) / (fwdCovInfo.sigX * fwdCovInfo.sigY));
917 fwdCovInfo.rhoPhiX = (Char_t)(128. * track.getCovariances()(0, 2) / (fwdCovInfo.sigPhi * fwdCovInfo.sigX));
918 fwdCovInfo.rhoPhiY = (Char_t)(128. * track.getCovariances()(1, 2) / (fwdCovInfo.sigPhi * fwdCovInfo.sigY));
919 fwdCovInfo.rhoTglX = (Char_t)(128. * track.getCovariances()(0, 3) / (fwdCovInfo.sigTgl * fwdCovInfo.sigX));
920 fwdCovInfo.rhoTglY = (Char_t)(128. * track.getCovariances()(1, 3) / (fwdCovInfo.sigTgl * fwdCovInfo.sigY));
921 fwdCovInfo.rhoTglPhi = (Char_t)(128. * track.getCovariances()(2, 3) / (fwdCovInfo.sigTgl * fwdCovInfo.sigPhi));
922 fwdCovInfo.rho1PtX = (Char_t)(128. * track.getCovariances()(0, 4) / (fwdCovInfo.sig1Pt * fwdCovInfo.sigX));
923 fwdCovInfo.rho1PtY = (Char_t)(128. * track.getCovariances()(1, 4) / (fwdCovInfo.sig1Pt * fwdCovInfo.sigY));
924 fwdCovInfo.rho1PtPhi = (Char_t)(128. * track.getCovariances()(2, 4) / (fwdCovInfo.sig1Pt * fwdCovInfo.sigPhi));
925 fwdCovInfo.rho1PtTgl = (Char_t)(128. * track.getCovariances()(3, 4) / (fwdCovInfo.sig1Pt * fwdCovInfo.sigTgl));
929 float sX = TMath::Sqrt(mfttrack.getSigma2X()), sY = TMath::Sqrt(mfttrack.getSigma2Y()), sPhi = TMath::Sqrt(mfttrack.getSigma2Phi()),
930 sTgl = TMath::Sqrt(mfttrack.getSigma2Tanl()), sQ2Pt = TMath::Sqrt(mfttrack.getSigma2InvQPt());
932 mftTracksCovCursor(fwdInfo.matchmfttrackid,
933 truncateFloatFraction(sX, mTrackCovDiag),
934 truncateFloatFraction(sY, mTrackCovDiag),
935 truncateFloatFraction(sPhi, mTrackCovDiag),
936 truncateFloatFraction(sTgl, mTrackCovDiag),
937 truncateFloatFraction(sQ2Pt, mTrackCovDiag),
938 (Char_t)(128. * mfttrack.getCovariances()(0, 1) / (sX * sY)),
939 (Char_t)(128. * mfttrack.getCovariances()(0, 2) / (sPhi * sX)),
940 (Char_t)(128. * mfttrack.getCovariances()(1, 2) / (sPhi * sY)),
941 (Char_t)(128. * mfttrack.getCovariances()(0, 3) / (sTgl * sX)),
942 (Char_t)(128. * mfttrack.getCovariances()(1, 3) / (sTgl * sY)),
943 (Char_t)(128. * mfttrack.getCovariances()(2, 3) / (sTgl * sPhi)),
944 (Char_t)(128. * mfttrack.getCovariances()(0, 4) / (sQ2Pt * sX)),
945 (Char_t)(128. * mfttrack.getCovariances()(1, 4) / (sQ2Pt * sY)),
946 (Char_t)(128. * mfttrack.getCovariances()(2, 4) / (sQ2Pt * sPhi)),
947 (Char_t)(128. * mfttrack.getCovariances()(3, 4) / (sQ2Pt * sTgl)));
950 std::uint64_t bcOfTimeRef;
951 bool needBCSlice = collisionID < 0;
953 float err = mTimeMarginTrackTime + fwdInfo.trackTimeRes;
954 bcOfTimeRef = fillBCSlice(bcSlice, fwdInfo.trackTime - err, fwdInfo.trackTime + err, bcsMap);
956 bcOfTimeRef = collisionBC - mStartIR.
toLong();
960 fwdTracksCursor(collisionID,
964 truncateFloatFraction(fwdInfo.z, mTrackX),
965 truncateFloatFraction(fwdInfo.phi, mTrackAlpha),
966 truncateFloatFraction(fwdInfo.tanl, mTrackTgl),
967 truncateFloatFraction(fwdInfo.invqpt, mTrack1Pt),
969 truncateFloatFraction(fwdInfo.pdca, mTrackX),
970 truncateFloatFraction(fwdInfo.rabs, mTrackX),
971 truncateFloatFraction(fwdInfo.chi2, mTrackChi2),
972 truncateFloatFraction(fwdInfo.chi2matchmchmid, mTrackChi2),
973 truncateFloatFraction(fwdInfo.chi2matchmchmft, mTrackChi2),
974 truncateFloatFraction(fwdInfo.matchscoremchmft, mTrackChi2),
975 fwdInfo.matchmfttrackid,
976 fwdInfo.matchmchtrackid,
980 truncateFloatFraction(fwdInfo.trackTime, mTrackTime),
981 truncateFloatFraction(fwdInfo.trackTimeRes, mTrackTimeError));
983 fwdTracksCovCursor(truncateFloatFraction(fwdCovInfo.sigX, mTrackCovDiag),
984 truncateFloatFraction(fwdCovInfo.sigY, mTrackCovDiag),
985 truncateFloatFraction(fwdCovInfo.sigPhi, mTrackCovDiag),
986 truncateFloatFraction(fwdCovInfo.sigTgl, mTrackCovDiag),
987 truncateFloatFraction(fwdCovInfo.sig1Pt, mTrackCovDiag),
993 fwdCovInfo.rhoTglPhi,
996 fwdCovInfo.rho1PtPhi,
997 fwdCovInfo.rho1PtTgl);
1000 ambigFwdTracksCursor(mTableTrFwdID, bcSlice);
1005void AODProducerWorkflowDPL::updateMCHeader(MCCollisionCursor& collisionCursor,
1006 XSectionCursor& xSectionCursor,
1007 PdfInfoCursor& pdfInfoCursor,
1008 HeavyIonCursor& heavyIonCursor,
1009 const MCEventHeader& header,
1021 auto genID = updateMCCollisions(collisionCursor,
1027 mCollisionPosition);
1028 mXSectionUpdate = (updateHepMCXSection(xSectionCursor,
1033 ? HepMCUpdate::always
1034 : HepMCUpdate::never);
1035 mPdfInfoUpdate = (updateHepMCPdfInfo(pdfInfoCursor,
1040 ? HepMCUpdate::always
1041 : HepMCUpdate::never);
1042 mHeavyIonUpdate = (updateHepMCHeavyIon(heavyIonCursor,
1047 ? HepMCUpdate::always
1048 : HepMCUpdate::never);
1053 store.resize(Nsources);
1054 for (
int s = 0;
s < Nsources; ++
s) {
1055 store[
s].resize(NEvents);
1061 for (
auto s = 0U;
s < store.size(); ++
s) {
1062 for (
auto e = 0U; e < store[
s].size(); ++e) {
1063 store[
s][e].clear();
1072 LOG(warn) <<
"trackID is smaller than 0. Neglecting";
1075 if (useSigFilt &&
source == 0) {
1083 MCParticlesCursor& mcParticlesCursor,
1084 const gsl::span<const o2::dataformats::VtxTrackRef>& primVer2TRefs,
1085 const gsl::span<const GIndex>& GIndices,
1087 const std::vector<std::vector<int>>& mcColToEvSrc)
1091 for (
auto& p : mcColToEvSrc) {
1092 NSources = std::max(p[1], NSources);
1093 NEvents = std::max(p[2], NEvents);
1097 LOG(info) <<
" number of events " << NEvents;
1098 LOG(info) <<
" number of sources " << NSources;
1101 std::vector<int> particleIDsToKeep;
1103 auto markMCTrackForSrc = [&](std::array<GID, GID::NSources>& contributorsGID, uint8_t
src) {
1104 auto mcLabel =
data.getTrackMCLabel(contributorsGID[
src]);
1105 if (!mcLabel.isValid()) {
1108 keepMCParticle(mToStore, mcLabel.getSourceID(), mcLabel.getEventID(), mcLabel.getTrackID(), 1, mUseSigFiltMC);
1112 for (
auto& trackRef : primVer2TRefs) {
1116 for (
int ti =
start; ti <
end; ti++) {
1117 auto& trackIndex = GIndices[ti];
1118 if (GIndex::includesSource(
src, mInputSources)) {
1119 auto mcTruth =
data.getTrackMCLabel(trackIndex);
1120 if (!mcTruth.isValid()) {
1123 keepMCParticle(mToStore, mcTruth.getSourceID(), mcTruth.getEventID(), mcTruth.getTrackID(), 1, mUseSigFiltMC);
1125 auto contributorsGID =
data.getSingleDetectorRefs(trackIndex);
1134 for (
auto& mcLabel : labelsTOF) {
1135 if (!mcLabel.isValid()) {
1138 keepMCParticle(mToStore, mcLabel.getSourceID(), mcLabel.getEventID(), mcLabel.getTrackID(), 1, mUseSigFiltMC);
1147 auto& mcCaloEMCCellLabels =
data.getEMCALCellsMCLabels()->getTruthArray();
1148 for (
auto& mcTruth : mcCaloEMCCellLabels) {
1149 if (!mcTruth.isValid()) {
1152 keepMCParticle(mToStore, mcTruth.getSourceID(), mcTruth.getEventID(), mcTruth.getTrackID(), 1, mUseSigFiltMC);
1156 auto& mcCaloPHOSCellLabels =
data.getPHOSCellsMCLabels()->getTruthArray();
1157 for (
auto& mcTruth : mcCaloPHOSCellLabels) {
1158 if (!mcTruth.isValid()) {
1161 keepMCParticle(mToStore, mcTruth.getSourceID(), mcTruth.getEventID(), mcTruth.getTrackID(), 1, mUseSigFiltMC);
1164 using namespace aodmchelpers;
1168 for (
auto& colInfo : mcColToEvSrc) {
1169 int event = colInfo[2];
1171 int mcColId = colInfo[0];
1173 LOG(
debug) <<
"Event=" <<
event <<
" source=" <<
source <<
" collision=" << mcColId;
1192template <
typename MCTrackLabelCursorType,
typename MCMFTTrackLabelCursorType,
typename MCFwdTrackLabelCursorType>
1193void AODProducerWorkflowDPL::fillMCTrackLabelsTable(MCTrackLabelCursorType& mcTrackLabelCursor,
1194 MCMFTTrackLabelCursorType& mcMFTTrackLabelCursor,
1195 MCFwdTrackLabelCursorType& mcFwdTrackLabelCursor,
1197 const gsl::span<const GIndex>& primVerGIs,
1210 mcMFTTrackLabelCursor.reserve(
end -
start + mcMFTTrackLabelCursor.lastIndex());
1211 mcFwdTrackLabelCursor.reserve(
end -
start + mcFwdTrackLabelCursor.lastIndex());
1212 mcTrackLabelCursor.reserve(
end -
start + mcTrackLabelCursor.lastIndex());
1213 for (
int ti =
start; ti <
end; ti++) {
1214 const auto trackIndex = primVerGIs[ti];
1217 auto needToStore = [trackIndex](std::unordered_map<GIndex, int>& mp) {
1218 auto entry = mp.find(trackIndex);
1219 if (
entry == mp.end() ||
entry->second == -1) {
1226 if (GIndex::includesSource(
src, mInputSources)) {
1227 auto mcTruth =
data.getTrackMCLabel(trackIndex);
1228 MCLabels labelHolder{};
1233 if (mcTruth.isValid()) {
1234 labelHolder.labelID = (mToStore[mcTruth.getSourceID()][mcTruth.getEventID()])[mcTruth.getTrackID()];
1236 if (mcTruth.isFake()) {
1237 labelHolder.fwdLabelMask |= (0x1 << 7);
1239 if (mcTruth.isNoise()) {
1240 labelHolder.fwdLabelMask |= (0x1 << 6);
1243 mcMFTTrackLabelCursor(labelHolder.labelID,
1244 labelHolder.fwdLabelMask);
1246 mcFwdTrackLabelCursor(labelHolder.labelID,
1247 labelHolder.fwdLabelMask);
1250 if (!needToStore(mGIDToTableID)) {
1253 if (mcTruth.isValid()) {
1254 labelHolder.labelID = (mToStore[mcTruth.getSourceID()][mcTruth.getEventID()])[mcTruth.getTrackID()];
1255 if (mcTruth.isFake()) {
1256 labelHolder.labelMask |= (0x1 << 15);
1259 auto contributorsGID =
data.getSingleDetectorRefs(trackIndex);
1262 labelHolder.labelMask |= (0x1 << 13);
1267 auto itsGID =
data.getITSContributorGID(trackIndex);
1268 auto itsSource = itsGID.getSource();
1270 auto& itsTrack =
data.getITSTrack(itsGID);
1271 for (
unsigned int iL = 0; iL < 7; ++iL) {
1272 if (itsTrack.isFakeOnLayer(iL)) {
1273 labelHolder.labelMask |= (0x1 << iL);
1277 labelHolder.labelMask |= (
data.getTrackMCLabel(itsGID).isFake() << 12);
1281 }
else if (mcTruth.isNoise()) {
1282 labelHolder.labelMask |= (0x1 << 14);
1284 mcTrackLabelCursor(labelHolder.labelID, labelHolder.labelMask);
1291 auto sTrackLabels =
data.getStrangeTracksMCLabels();
1293 if (!(vertexId < 0 || vertexId >= mVertexStrLUT.size() - 1)) {
1294 mcTrackLabelCursor.reserve(mVertexStrLUT[vertexId + 1] + mcTrackLabelCursor.lastIndex());
1295 for (
int iS{mVertexStrLUT[vertexId]}; iS < mVertexStrLUT[vertexId + 1]; ++iS) {
1296 auto& collStrTrk = mCollisionStrTrk[iS];
1297 auto&
label = sTrackLabels[collStrTrk.second];
1298 MCLabels labelHolder;
1299 labelHolder.labelID =
label.isValid() ? (mToStore[
label.getSourceID()][
label.getEventID()])[
label.getTrackID()] : -1;
1300 labelHolder.labelMask = (
label.isFake() << 15) | (
label.isNoise() << 14);
1301 mcTrackLabelCursor(labelHolder.labelID, labelHolder.labelMask);
1306template <
typename V0CursorType,
typename CascadeCursorType,
typename Decay3BodyCursorType>
1307void AODProducerWorkflowDPL::fillSecondaryVertices(
const o2::globaltracking::RecoContainer& recoData, V0CursorType& v0Cursor, CascadeCursorType& cascadeCursor, Decay3BodyCursorType& decay3BodyCursor)
1314 v0Cursor.reserve(v0s.size());
1316 for (
size_t iv0 = 0; iv0 < v0s.size(); iv0++) {
1317 const auto&
v0 = v0s[iv0];
1318 auto trPosID =
v0.getProngID(0);
1319 auto trNegID =
v0.getProngID(1);
1320 uint8_t v0flags =
v0.getBits();
1321 int posTableIdx = -1, negTableIdx = -1, collID = -1;
1322 auto item = mGIDToTableID.find(trPosID);
1323 if (item != mGIDToTableID.end()) {
1324 posTableIdx = item->second;
1326 LOG(warn) <<
"Could not find a positive track index for prong ID " << trPosID;
1328 item = mGIDToTableID.find(trNegID);
1329 if (item != mGIDToTableID.end()) {
1330 negTableIdx = item->second;
1332 LOG(warn) <<
"Could not find a negative track index for prong ID " << trNegID;
1334 auto itemV = mVtxToTableCollID.find(
v0.getVertexID());
1335 if (itemV == mVtxToTableCollID.end()) {
1336 LOG(warn) <<
"Could not find V0 collisionID for the vertex ID " <<
v0.getVertexID();
1338 collID = itemV->second;
1340 if (posTableIdx != -1 and negTableIdx != -1 and collID != -1) {
1341 v0Cursor(collID, posTableIdx, negTableIdx, v0flags);
1342 mV0ToTableID[
int(iv0)] = mTableV0ID++;
1347 cascadeCursor.reserve(cascades.size());
1348 for (
auto& cascade : cascades) {
1349 auto itemV0 = mV0ToTableID.find(cascade.getV0ID());
1350 if (itemV0 == mV0ToTableID.end()) {
1353 int v0tableID = itemV0->second, bachTableIdx = -1, collID = -1;
1354 auto bachelorID = cascade.getBachelorID();
1355 auto item = mGIDToTableID.find(bachelorID);
1356 if (item != mGIDToTableID.end()) {
1357 bachTableIdx = item->second;
1359 LOG(warn) <<
"Could not find a bachelor track index";
1362 auto itemV = mVtxToTableCollID.find(cascade.getVertexID());
1363 if (itemV != mVtxToTableCollID.end()) {
1364 collID = itemV->second;
1366 LOG(warn) <<
"Could not find cascade collisionID for the vertex ID " << cascade.getVertexID();
1369 cascadeCursor(collID, v0tableID, bachTableIdx);
1373 decay3BodyCursor.reserve(decays3Body.size());
1374 for (
size_t i3Body = 0; i3Body < decays3Body.size(); i3Body++) {
1375 const auto& decay3Body = decays3Body[i3Body];
1377 decay3Body.getProngID(0),
1378 decay3Body.getProngID(1),
1379 decay3Body.getProngID(2)};
1380 int tableIdx[3]{-1, -1, -1}, collID = -1;
1381 bool missing{
false};
1382 for (
int i{0};
i < 3; ++
i) {
1383 auto item = mGIDToTableID.find(trIDs[
i]);
1384 if (item != mGIDToTableID.end()) {
1385 tableIdx[
i] = item->second;
1387 LOG(warn) << fmt::format(
"Could not find a track index for prong ID {}", (
int)trIDs[
i]);
1391 auto itemV = mVtxToTableCollID.find(decay3Body.getVertexID());
1392 if (itemV == mVtxToTableCollID.end()) {
1393 LOG(warn) <<
"Could not find 3 body collisionID for the vertex ID " << decay3Body.getVertexID();
1396 collID = itemV->second;
1401 decay3BodyCursor(collID, tableIdx[0], tableIdx[1], tableIdx[2]);
1405template <
typename FwdTrkClsCursorType>
1412 int mchTrackID = -1;
1414 mchTrackID = trackID.getIndex();
1416 auto mchmidMatch = mchmidMatches[trackID.getIndex()];
1417 mchTrackID = mchmidMatch.getMCHRef().getIndex();
1420 if (mchTrackID > -1 && mchTrackID < mchTracks.size()) {
1421 const auto& mchTrack = mchTracks[mchTrackID];
1422 fwdTrkClsCursor.reserve(mchTrack.getNClusters() + fwdTrkClsCursor.lastIndex());
1423 int first = mchTrack.getFirstClusterIdx();
1424 int last = mchTrack.getLastClusterIdx();
1425 for (
int i =
first;
i <= last;
i++) {
1426 const auto& cluster = mchClusters[
i];
1427 fwdTrkClsCursor(fwdTrackId,
1428 truncateFloatFraction(cluster.x, mMuonCl),
1429 truncateFloatFraction(cluster.y, mMuonCl),
1430 truncateFloatFraction(cluster.z, mMuonCl),
1431 (((cluster.ey < 5.) & 0x1) << 12) | (((cluster.ex < 5.) & 0x1) << 11) | cluster.getDEId());
1436template <
typename HMPCursorType>
1441 hmpCursor.reserve(hmpMatches.size());
1444 for (
size_t iHmp = 0; iHmp < hmpMatches.size(); iHmp++) {
1446 const auto&
match = hmpMatches[iHmp];
1448 float xTrk, yTrk, theta,
phi;
1452 match.getHMPIDtrk(xTrk, yTrk, theta,
phi);
1455 auto photChargeVec =
match.getPhotCharge();
1457 float photChargeVec2[10];
1459 for (Int_t
i = 0;
i < 10;
i++) {
1460 photChargeVec2[
i] = photChargeVec[
i];
1462 auto tref = mGIDToTableID.find(
match.getTrackRef());
1463 if (tref != mGIDToTableID.end()) {
1464 hmpCursor(tref->second,
match.getHMPsignal(), xTrk, yTrk, xMip, yMip, nph,
charge,
match.getIdxHMPClus(),
match.getHmpMom(), photChargeVec2);
1466 LOG(error) <<
"Could not find AOD track table entry for HMP-matched track " <<
match.getTrackRef().asString();
1478 mCollisionStrTrk.clear();
1480 mVertexStrLUT.clear();
1482 for (
auto& sTrk : recoData.getStrangeTracks()) {
1486 vtxId = v0s[sTrk.mDecayRef].getVertexID();
1488 vtxId = cascades[sTrk.mDecayRef].getVertexID();
1490 vtxId = decays3Body[sTrk.mDecayRef].getVertexID();
1492 mCollisionStrTrk.emplace_back(vtxId, sTrkID++);
1493 mVertexStrLUT[vtxId]++;
1495 std::exclusive_scan(mVertexStrLUT.begin(), mVertexStrLUT.end(), mVertexStrLUT.begin(), 0);
1498 std::sort(mCollisionStrTrk.begin(), mCollisionStrTrk.end(), [](
const auto&
a,
const auto&
b) { return a.first < b.first; });
1499 mStrTrkIndices.clear();
1500 mStrTrkIndices.resize(mCollisionStrTrk.size(), -1);
1503template <
typename V0C,
typename CC,
typename D3BC>
1506 int itsTableIdx = -1;
1512 for (
const auto& sTrk : recoData.getStrangeTracks()) {
1522 v0Curs.reserve(nV0);
1523 cascCurs.reserve(nCasc);
1524 d3BodyCurs.reserve(nD3Body);
1526 for (
const auto& sTrk : recoData.getStrangeTracks()) {
1528 auto item = mGIDToTableID.find(ITSIndex);
1529 if (item != mGIDToTableID.end()) {
1530 itsTableIdx = item->second;
1532 LOG(warn) <<
"Could not find a ITS strange track index " << ITSIndex;
1536 v0Curs(mStrTrkIndices[sTrkID++],
1546 sTrk.getAverageClusterSize());
1548 cascCurs(mStrTrkIndices[sTrkID++],
1558 sTrk.getAverageClusterSize());
1560 d3BodyCurs(mStrTrkIndices[sTrkID++],
1570 sTrk.getAverageClusterSize());
1577 const auto& tpcTracks =
data.getTPCTracks();
1578 const auto& tpcClusRefs =
data.getTPCTracksClusterRefs();
1579 const auto& tpcClusShMap =
data.clusterShMapTPC;
1580 const auto& tpcClusAcc =
data.getTPCClusters();
1581 constexpr int maxRows = 152;
1582 constexpr int neighbour = 2;
1583 int ntr = tpcTracks.size();
1584 mTPCCounters.clear();
1585 mTPCCounters.resize(ntr);
1587 int ngroup = std::min(50, std::max(1, ntr / mNThreads));
1588#pragma omp parallel for schedule(dynamic, ngroup) num_threads(mNThreads)
1590 for (
int itr = 0; itr < ntr; itr++) {
1591 std::array<bool, maxRows> clMap{}, shMap{};
1592 uint8_t sectorIndex, rowIndex;
1593 uint32_t clusterIndex;
1594 auto&
counters = mTPCCounters[itr];
1595 const auto& track = tpcTracks[itr];
1596 for (
int i = 0;
i < track.getNClusterReferences();
i++) {
1597 o2::tpc::TrackTPC::getClusterReference(tpcClusRefs,
i, sectorIndex, rowIndex, clusterIndex, track.getClusterRef());
1598 unsigned int absoluteIndex = tpcClusAcc.clusterOffset[sectorIndex][rowIndex] + clusterIndex;
1599 clMap[rowIndex] =
true;
1601 if (!shMap[rowIndex]) {
1604 shMap[rowIndex] =
true;
1608 for (
int i = 0;
i < maxRows;
i++) {
1613 }
else if ((
i - last) <= neighbour) {
1616 int lim = std::min(
i + 1 + neighbour, maxRows);
1617 for (
int j =
i + 1;
j < lim;
j++) {
1632 if (track.getTrackletIndex(il) != -1) {
1636 if (track.getHasNeighbor()) {
1639 if (track.getHasPadrowCrossing()) {
1645template <
typename TCaloHandler,
typename TCaloCursor,
typename TCaloTRGCursor,
typename TMCCaloLabelCursor>
1646void AODProducerWorkflowDPL::addToCaloTable(TCaloHandler& caloHandler, TCaloCursor& caloCellCursor, TCaloTRGCursor& caloTRGCursor,
1647 TMCCaloLabelCursor& mcCaloCellLabelCursor,
int eventID,
int bcID, int8_t caloType)
1649 auto inputEvent = caloHandler.buildEvent(eventID);
1650 auto cellsInEvent = inputEvent.mCells;
1651 auto cellMClabels = inputEvent.mMCCellLabels;
1652 caloCellCursor.reserve(cellsInEvent.size() + caloCellCursor.lastIndex());
1653 caloTRGCursor.reserve(cellsInEvent.size() + caloTRGCursor.lastIndex());
1655 mcCaloCellLabelCursor.reserve(cellsInEvent.size() + mcCaloCellLabelCursor.lastIndex());
1657 for (
auto iCell = 0U; iCell < cellsInEvent.size(); iCell++) {
1658 caloCellCursor(bcID,
1662 cellsInEvent[iCell].
getType(),
1676 std::vector<int32_t> particleIds;
1677 std::vector<float> amplitudeFraction;
1678 if (!mEMCselectLeading) {
1679 particleIds.reserve(cellMClabels.size());
1680 amplitudeFraction.reserve(cellMClabels.size());
1682 float tmpMaxAmplitude = 0;
1683 int32_t tmpindex = 0;
1684 for (
auto& mclabel : cellMClabels[iCell]) {
1686 if (mclabel.isValid()) {
1687 if (mEMCselectLeading) {
1688 if (mclabel.getAmplitudeFraction() > tmpMaxAmplitude) {
1690 if (mToStore.at(mclabel.getSourceID()).at(mclabel.getEventID()).find(mclabel.getTrackID()) !=
1691 mToStore.at(mclabel.getSourceID()).at(mclabel.getEventID()).end()) {
1692 tmpMaxAmplitude = mclabel.getAmplitudeFraction();
1693 tmpindex = (mToStore.at(mclabel.getSourceID()).at(mclabel.getEventID())).at(mclabel.getTrackID());
1697 auto trackStore = mToStore.at(mclabel.getSourceID()).at(mclabel.getEventID());
1698 auto iter = trackStore.find(mclabel.getTrackID());
1699 if (iter != trackStore.end()) {
1700 amplitudeFraction.emplace_back(mclabel.getAmplitudeFraction());
1701 particleIds.emplace_back(iter->second);
1703 particleIds.emplace_back(-1);
1704 amplitudeFraction.emplace_back(0.f);
1705 LOG(warn) <<
"CaloTable: Could not find track for mclabel (" << mclabel.getSourceID() <<
"," << mclabel.getEventID() <<
"," << mclabel.getTrackID() <<
") in the AOD MC store";
1706 if (mMCKineReader) {
1707 auto mctrack = mMCKineReader->
getTrack(mclabel);
1710 LOG(warn) <<
" ... this track is of PDG " << mctrack->GetPdgCode() <<
" produced by " << mctrack->getProdProcessAsString() <<
" at (" <<
vec.X() <<
"," <<
vec.Y() <<
"," <<
vec.Z() <<
")";
1716 if (mEMCselectLeading) {
1717 amplitudeFraction.emplace_back(tmpMaxAmplitude);
1718 particleIds.emplace_back(tmpindex);
1720 if (particleIds.size() == 0) {
1721 particleIds.emplace_back(-1);
1722 amplitudeFraction.emplace_back(0.f);
1724 mcCaloCellLabelCursor(particleIds,
1731template <
typename TCaloCursor,
typename TCaloTRGCursor,
typename TMCCaloLabelCursor>
1732void AODProducerWorkflowDPL::fillCaloTable(TCaloCursor& caloCellCursor, TCaloTRGCursor& caloTRGCursor,
1733 TMCCaloLabelCursor& mcCaloCellLabelCursor,
const std::map<uint64_t, int>& bcsMap,
1737 auto caloEMCCells =
data.getEMCALCells();
1738 auto caloEMCCellsTRGR =
data.getEMCALTriggers();
1739 auto mcCaloEMCCellLabels =
data.getEMCALCellsMCLabels();
1741 auto caloPHOSCells =
data.getPHOSCells();
1742 auto caloPHOSCellsTRGR =
data.getPHOSTriggers();
1743 auto mcCaloPHOSCellLabels =
data.getPHOSCellsMCLabels();
1747 caloPHOSCellsTRGR = {};
1748 mcCaloPHOSCellLabels = {};
1753 caloEMCCellsTRGR = {};
1754 mcCaloEMCCellLabels = {};
1761 emcEventHandler.
reset();
1762 emcEventHandler.
setCellData(caloEMCCells, caloEMCCellsTRGR);
1765 phsEventHandler.
reset();
1766 phsEventHandler.
setCellData(caloPHOSCells, caloPHOSCellsTRGR);
1772 std::vector<std::tuple<uint64_t, int8_t, int>> caloEvents;
1774 caloEvents.reserve(emcNEvents + phsNEvents);
1776 for (
int iev = 0; iev < emcNEvents; ++iev) {
1778 caloEvents.emplace_back(std::make_tuple(
bc, 1, iev));
1781 for (
int iev = 0; iev < phsNEvents; ++iev) {
1783 caloEvents.emplace_back(std::make_tuple(
bc, 0, iev));
1786 std::sort(caloEvents.begin(), caloEvents.end(),
1787 [](
const auto&
left,
const auto&
right) { return std::get<0>(left) < std::get<0>(right); });
1790 for (
int i = 0;
i < emcNEvents + phsNEvents; ++
i) {
1791 uint64_t globalBC = std::get<0>(caloEvents[
i]);
1792 int8_t caloType = std::get<1>(caloEvents[
i]);
1793 int eventID = std::get<2>(caloEvents[
i]);
1794 auto item = bcsMap.find(globalBC);
1796 if (item != bcsMap.end()) {
1797 bcID = item->second;
1799 LOG(warn) <<
"Error: could not find a corresponding BC ID for a calo point; globalBC = " << globalBC <<
", caloType = " << (
int)caloType;
1801 if (caloType == 0) {
1802 addToCaloTable(phsEventHandler, caloCellCursor, caloTRGCursor, mcCaloCellLabelCursor, eventID, bcID, caloType);
1804 if (caloType == 1) {
1805 addToCaloTable(emcEventHandler, caloCellCursor, caloTRGCursor, mcCaloCellLabelCursor, eventID, bcID, caloType);
1816 mLPMProdTag = ic.
options().
get<std::string>(
"lpmp-prod-tag");
1817 mAnchorPass = ic.
options().
get<std::string>(
"anchor-pass");
1818 mAnchorProd = ic.
options().
get<std::string>(
"anchor-prod");
1819 mUser = ic.
options().
get<std::string>(
"created-by");
1820 mRecoPass = ic.
options().
get<std::string>(
"reco-pass");
1821 mAODParent = ic.
options().
get<std::string>(
"aod-parent");
1822 mTFNumber = ic.
options().
get<int64_t>(
"aod-timeframe-id");
1823 mRecoOnly = ic.
options().
get<
int>(
"reco-mctracks-only");
1824 mTruncate = ic.
options().
get<
int>(
"enable-truncation");
1825 mRunNumber = ic.
options().
get<
int>(
"run-number");
1826 mCTPReadout = ic.
options().
get<
int>(
"ctpreadout-create");
1827 mNThreads = std::max(1, ic.
options().
get<
int>(
"nthreads"));
1828 mEMCselectLeading = ic.
options().
get<
bool>(
"emc-select-leading");
1829 mThinTracks = ic.
options().
get<
bool>(
"thin-tracks");
1830 mPropTracks = ic.
options().
get<
bool>(
"propagate-tracks");
1831 mMaxPropXiu = ic.
options().
get<
float>(
"propagate-tracks-max-xiu");
1832 mPropMuons = ic.
options().
get<
bool>(
"propagate-muons");
1833 if (
auto s = ic.
options().
get<std::string>(
"with-streamers"); !
s.empty()) {
1834 mStreamerFlags.
set(
s);
1835 if (mStreamerFlags) {
1836 LOGP(info,
"Writing streamer data with mask:");
1837 LOG(info) << mStreamerFlags;
1839 LOGP(warn,
"Specified non-default empty streamer mask!");
1842 mTrackQCKeepGlobalTracks = ic.
options().
get<
bool>(
"trackqc-keepglobaltracks");
1843 mTrackQCRetainOnlydEdx = ic.
options().
get<
bool>(
"trackqc-retainonlydedx");
1844 mTrackQCFraction = ic.
options().
get<
float>(
"trackqc-fraction");
1845 mTrackQCNTrCut = ic.
options().
get<int64_t>(
"trackqc-NTrCut");
1846 mTrackQCDCAxy = ic.
options().
get<
float>(
"trackqc-tpc-dca");
1847 mTrackQCPt = ic.
options().
get<
float>(
"trackqc-tpc-pt");
1848 mTrackQCNCls = ic.
options().
get<
int>(
"trackqc-tpc-cls");
1849 if (
auto seed = ic.
options().
get<
int>(
"seed"); seed == 0) {
1850 LOGP(info,
"Using random device for seeding");
1851 std::random_device
rd;
1852 std::array<int, std::mt19937::state_size> seed_data{};
1853 std::generate(std::begin(seed_data), std::end(seed_data), std::ref(
rd));
1854 std::seed_seq seq(std::begin(seed_data), std::end(seed_data));
1855 mGenerator = std::mt19937(seq);
1857 LOGP(info,
"Using seed {} for sampling", seed);
1858 mGenerator.seed(seed);
1861 LOGP(info,
"Multi-threaded parts will run with {} OpenMP threads", mNThreads);
1864 LOG(info) <<
"OpenMP is disabled";
1866 if (mTFNumber == -1L) {
1867 LOG(info) <<
"TFNumber will be obtained from CCDB";
1869 if (mRunNumber == -1L) {
1870 LOG(info) <<
"The Run number will be obtained from DPL headers";
1873 mUseSigFiltMC = ic.
options().
get<
bool>(
"mc-signal-filt");
1876 if (mTruncate != 1) {
1877 LOG(info) <<
"Truncation is not used!";
1878 mCollisionPosition = 0xFFFFFFFF;
1879 mCollisionPositionCov = 0xFFFFFFFF;
1880 mTrackX = 0xFFFFFFFF;
1881 mTrackAlpha = 0xFFFFFFFF;
1882 mTrackSnp = 0xFFFFFFFF;
1883 mTrackTgl = 0xFFFFFFFF;
1884 mTrack1Pt = 0xFFFFFFFF;
1885 mTrackChi2 = 0xFFFFFFFF;
1886 mTrackCovDiag = 0xFFFFFFFF;
1887 mTrackCovOffDiag = 0xFFFFFFFF;
1888 mTrackSignal = 0xFFFFFFFF;
1889 mTrackTime = 0xFFFFFFFF;
1890 mTPCTime0 = 0xFFFFFFFF;
1891 mTrackTimeError = 0xFFFFFFFF;
1892 mTrackPosEMCAL = 0xFFFFFFFF;
1893 mTracklets = 0xFFFFFFFF;
1894 mMcParticleW = 0xFFFFFFFF;
1895 mMcParticlePos = 0xFFFFFFFF;
1896 mMcParticleMom = 0xFFFFFFFF;
1897 mCaloAmp = 0xFFFFFFFF;
1898 mCaloTime = 0xFFFFFFFF;
1899 mCPVPos = 0xFFFFFFFF;
1900 mCPVAmpl = 0xFFFFFFFF;
1901 mMuonTr1P = 0xFFFFFFFF;
1902 mMuonTrThetaX = 0xFFFFFFFF;
1903 mMuonTrThetaY = 0xFFFFFFFF;
1904 mMuonTrZmu = 0xFFFFFFFF;
1905 mMuonTrBend = 0xFFFFFFFF;
1906 mMuonTrNonBend = 0xFFFFFFFF;
1907 mMuonTrCov = 0xFFFFFFFF;
1908 mMuonCl = 0xFFFFFFFF;
1909 mMuonClErr = 0xFFFFFFFF;
1910 mV0Time = 0xFFFFFFFF;
1911 mV0ChannelTime = 0xFFFFFFFF;
1912 mFDDTime = 0xFFFFFFFF;
1913 mFDDChannelTime = 0xFFFFFFFF;
1914 mT0Time = 0xFFFFFFFF;
1915 mT0ChannelTime = 0xFFFFFFFF;
1916 mV0Amplitude = 0xFFFFFFFF;
1917 mFDDAmplitude = 0xFFFFFFFF;
1918 mT0Amplitude = 0xFFFFFFFF;
1922 mZDCEnergyMap[ic] = -std::numeric_limits<float>::infinity();
1925 mZDCTDCMap[ic] = -std::numeric_limits<float>::infinity();
1928 std::string hepmcUpdate = ic.
options().
get<std::string>(
"hepmc-update");
1929 HepMCUpdate when = (hepmcUpdate ==
"never" ? HepMCUpdate::never : hepmcUpdate ==
"always" ? HepMCUpdate::always
1930 : hepmcUpdate ==
"all" ? HepMCUpdate::allKeys
1931 : HepMCUpdate::anyKey);
1932 mXSectionUpdate = when;
1933 mPdfInfoUpdate = when;
1934 mHeavyIonUpdate = when;
1938 if (mStreamerFlags) {
1939 mStreamer = std::make_unique<o2::utils::TreeStreamRedirector>(
"AO2DStreamer.root",
"RECREATE");
1945void add_additional_meta_info(std::vector<TString>& keys, std::vector<TString>&
values)
1948 auto aod_external_meta_info_file = getenv(
"AOD_ADDITIONAL_METADATA_FILE");
1949 if (aod_external_meta_info_file !=
nullptr) {
1950 LOG(info) <<
"Trying to inject additional AOD meta-data from " << aod_external_meta_info_file;
1951 if (std::filesystem::exists(aod_external_meta_info_file)) {
1952 std::ifstream input_file(aod_external_meta_info_file);
1954 nlohmann::json json_data;
1956 input_file >> json_data;
1957 }
catch (nlohmann::json::parse_error& e) {
1958 std::cerr <<
"JSON Parse Error: " << e.what() <<
"\n";
1959 std::cerr <<
"Exception ID: " << e.id <<
"\n";
1960 std::cerr <<
"Byte position: " << e.byte <<
"\n";
1964 for (
const auto& [
key,
value] : json_data.items()) {
1965 LOG(info) <<
"Adding AOD MetaData" <<
key <<
" : " <<
value;
1966 keys.push_back(
key.c_str());
1977 mTimer.Start(
false);
1980 updateTimeDependentParams(pc);
2005 std::vector<o2::ctp::CTPDigit> ctpDigitsCreated;
2006 if (mCTPReadout == 1) {
2007 LOG(info) <<
"CTP : creating ctpreadout in AOD producer";
2008 createCTPReadout(recoData, ctpDigitsCreated, pc);
2009 LOG(info) <<
"CTP : ctpreadout created from AOD";
2010 ctpDigits = gsl::span<o2::ctp::CTPDigit>(ctpDigitsCreated);
2012 LOG(
debug) <<
"FOUND " << primVertices.size() <<
" primary vertices";
2013 LOG(
debug) <<
"FOUND " << ft0RecPoints.size() <<
" FT0 rec. points";
2014 LOG(
debug) <<
"FOUND " << fv0RecPoints.size() <<
" FV0 rec. points";
2015 LOG(
debug) <<
"FOUND " << fddRecPoints.size() <<
" FDD rec. points";
2016 LOG(
debug) <<
"FOUND " << cpvClusters.size() <<
" CPV clusters";
2017 LOG(
debug) <<
"FOUND " << cpvTrigRecs.size() <<
" CPV trigger records";
2019 LOG(info) <<
"FOUND " << primVertices.size() <<
" primary vertices";
2023 auto bcCursor = createTableCursor<o2::aod::BCs>(pc);
2024 auto bcFlagsCursor = createTableCursor<o2::aod::BCFlags>(pc);
2025 auto cascadesCursor = createTableCursor<o2::aod::Cascades>(pc);
2026 auto collisionsCursor = createTableCursor<o2::aod::Collisions>(pc);
2027 auto decay3BodyCursor = createTableCursor<o2::aod::Decay3Bodys>(pc);
2028 auto trackedCascadeCursor = createTableCursor<o2::aod::TrackedCascades>(pc);
2029 auto trackedV0Cursor = createTableCursor<o2::aod::TrackedV0s>(pc);
2030 auto tracked3BodyCurs = createTableCursor<o2::aod::Tracked3Bodys>(pc);
2031 auto fddCursor = createTableCursor<o2::aod::FDDs>(pc);
2032 auto fddExtraCursor = createTableCursor<o2::aod::FDDsExtra>(pc);
2033 auto ft0Cursor = createTableCursor<o2::aod::FT0s>(pc);
2034 auto ft0ExtraCursor = createTableCursor<o2::aod::FT0sExtra>(pc);
2035 auto fv0aCursor = createTableCursor<o2::aod::FV0As>(pc);
2036 auto fv0aExtraCursor = createTableCursor<o2::aod::FV0AsExtra>(pc);
2037 auto fwdTracksCursor = createTableCursor<o2::aod::StoredFwdTracks>(pc);
2038 auto fwdTracksCovCursor = createTableCursor<o2::aod::StoredFwdTracksCov>(pc);
2039 auto fwdTrkClsCursor = createTableCursor<o2::aod::FwdTrkCls>(pc);
2040 auto mftTracksCursor = createTableCursor<o2::aod::StoredMFTTracks>(pc);
2041 auto mftTracksCovCursor = createTableCursor<o2::aod::StoredMFTTracksCov>(pc);
2042 auto tracksCursor = createTableCursor<o2::aod::StoredTracksIU>(pc);
2043 auto tracksCovCursor = createTableCursor<o2::aod::StoredTracksCovIU>(pc);
2044 auto tracksExtraCursor = createTableCursor<o2::aod::StoredTracksExtra>(pc);
2045 auto tracksQACursor = createTableCursor<o2::aod::TracksQAVersion>(pc);
2046 auto ambigTracksCursor = createTableCursor<o2::aod::AmbiguousTracks>(pc);
2047 auto ambigMFTTracksCursor = createTableCursor<o2::aod::AmbiguousMFTTracks>(pc);
2048 auto ambigFwdTracksCursor = createTableCursor<o2::aod::AmbiguousFwdTracks>(pc);
2049 auto v0sCursor = createTableCursor<o2::aod::V0s>(pc);
2050 auto zdcCursor = createTableCursor<o2::aod::Zdcs>(pc);
2051 auto hmpCursor = createTableCursor<o2::aod::HMPIDs>(pc);
2052 auto caloCellsCursor = createTableCursor<o2::aod::Calos>(pc);
2053 auto caloCellsTRGTableCursor = createTableCursor<o2::aod::CaloTriggers>(pc);
2054 auto cpvClustersCursor = createTableCursor<o2::aod::CPVClusters>(pc);
2055 auto originCursor = createTableCursor<o2::aod::Origins>(pc);
2059 if (mEnableTRDextra) {
2060 trdExtraCursor = createTableCursor<o2::aod::TRDsExtra>(pc);
2075 mcColLabelsCursor = createTableCursor<o2::aod::McCollisionLabels>(pc);
2076 mcCollisionsCursor = createTableCursor<o2::aod::McCollisions>(pc);
2077 hepmcXSectionsCursor = createTableCursor<o2::aod::HepMCXSections>(pc);
2078 hepmcPdfInfosCursor = createTableCursor<o2::aod::HepMCPdfInfos>(pc);
2079 hepmcHeavyIonsCursor = createTableCursor<o2::aod::HepMCHeavyIons>(pc);
2080 mcMFTTrackLabelCursor = createTableCursor<o2::aod::McMFTTrackLabels>(pc);
2081 mcFwdTrackLabelCursor = createTableCursor<o2::aod::McFwdTrackLabels>(pc);
2082 mcParticlesCursor = createTableCursor<o2::aod::StoredMcParticles_001>(pc);
2083 mcTrackLabelCursor = createTableCursor<o2::aod::McTrackLabels>(pc);
2084 mcCaloLabelsCursor = createTableCursor<o2::aod::McCaloLabels_001>(pc);
2087 std::unique_ptr<o2::steer::MCKinematicsReader> mcReader;
2089 mcReader = std::make_unique<o2::steer::MCKinematicsReader>(
"collisioncontext.root");
2091 mMCKineReader = mcReader.get();
2092 std::map<uint64_t, int> bcsMap;
2093 collectBCs(recoData, mUseMC ? mcReader->getDigitizationContext()->getEventRecords() : std::vector<o2::InteractionTimeRecord>{}, bcsMap);
2094 if (!primVer2TRefs.empty()) {
2095 addRefGlobalBCsForTOF(primVer2TRefs.back(), primVerGIs, recoData, bcsMap);
2098 mBCLookup.
init(bcsMap);
2101 const int runNumber = (mRunNumber == -1) ?
int(tinfo.runNumber) : mRunNumber;
2102 if (mTFNumber == -1L) {
2104 tfNumber = uint64_t(tinfo.firstTForbit) + (uint64_t(tinfo.runNumber) << 32);
2106 tfNumber = mTFNumber;
2109 std::vector<float> aAmplitudes, aTimes;
2110 std::vector<uint8_t> aChannels;
2111 fv0aCursor.reserve(fv0RecPoints.size());
2112 for (
auto& fv0RecPoint : fv0RecPoints) {
2113 aAmplitudes.clear();
2116 const auto channelData = fv0RecPoint.getBunchChannelData(fv0ChData);
2117 for (
auto& channel : channelData) {
2118 if (channel.charge > 0) {
2119 aAmplitudes.push_back(truncateFloatFraction(channel.charge, mV0Amplitude));
2120 aTimes.push_back(truncateFloatFraction(channel.time * 1.E-3, mV0ChannelTime));
2121 aChannels.push_back(channel.channel);
2124 uint64_t
bc = fv0RecPoint.getInteractionRecord().toLong();
2125 auto item = bcsMap.find(
bc);
2127 if (item != bcsMap.end()) {
2128 bcID = item->second;
2130 LOG(fatal) <<
"Error: could not find a corresponding BC ID for a FV0 rec. point; BC = " <<
bc;
2135 truncateFloatFraction(fv0RecPoint.getCollisionGlobalMeanTime() * 1E-3, mV0Time),
2136 fv0RecPoint.getTrigger().getTriggersignals());
2138 if (mEnableFITextra) {
2139 fv0aExtraCursor(bcID,
2144 std::vector<float> zdcEnergy, zdcAmplitudes, zdcTime;
2145 std::vector<uint8_t> zdcChannelsE, zdcChannelsT;
2146 zdcCursor.reserve(zdcBCRecData.size());
2147 for (
auto zdcRecData : zdcBCRecData) {
2148 uint64_t
bc = zdcRecData.ir.toLong();
2149 auto item = bcsMap.find(
bc);
2151 if (item != bcsMap.end()) {
2152 bcID = item->second;
2154 LOG(fatal) <<
"Error: could not find a corresponding BC ID for a ZDC rec. point; BC = " <<
bc;
2156 int fe, ne, ft, nt, fi, ni;
2157 zdcRecData.getRef(fe, ne, ft, nt, fi, ni);
2159 zdcChannelsE.clear();
2160 zdcAmplitudes.clear();
2162 zdcChannelsT.clear();
2163 for (
int ie = 0; ie < ne; ie++) {
2164 auto& zdcEnergyData = zdcEnergies[fe + ie];
2165 zdcEnergy.emplace_back(zdcEnergyData.energy());
2166 zdcChannelsE.emplace_back(zdcEnergyData.ch());
2168 for (
int it = 0; it < nt; it++) {
2169 auto& tdc = zdcTDCData[ft + it];
2170 zdcAmplitudes.emplace_back(tdc.amplitude());
2171 zdcTime.emplace_back(tdc.value());
2185 std::vector<std::vector<int>> mcColToEvSrc;
2191 int nMCCollisions = mcReader->getDigitizationContext()->getNCollisions();
2192 const auto& mcRecords = mcReader->getDigitizationContext()->getEventRecords();
2193 const auto& mcParts = mcReader->getDigitizationContext()->getEventParts();
2196 if (mUseSigFiltMC) {
2197 std::vector<int> sourceIDs{};
2198 for (
int iCol = 0; iCol < nMCCollisions; iCol++) {
2199 for (
auto const& colPart : mcParts[iCol]) {
2200 int sourceID = colPart.sourceID;
2201 if (std::find(sourceIDs.begin(), sourceIDs.end(), sourceID) == sourceIDs.end()) {
2202 sourceIDs.push_back(sourceID);
2204 if (sourceIDs.size() > 1) {
2208 if (sourceIDs.size() > 1) {
2212 if (sourceIDs.size() <= 1) {
2213 LOGP(fatal,
"Signal filtering cannot be enabled without embedding. Please fix the configuration either enabling the embedding, or turning off the signal filtering.");
2218 int totalNParts = 0;
2219 for (
int iCol = 0; iCol < nMCCollisions; iCol++) {
2220 totalNParts += mcParts[iCol].size();
2222 mcCollisionsCursor.
reserve(totalNParts);
2224 for (
int iCol = 0; iCol < nMCCollisions; iCol++) {
2225 const auto time = mcRecords[iCol].getTimeOffsetWrtBC();
2226 auto globalBC = mcRecords[iCol].toLong();
2227 auto item = bcsMap.find(globalBC);
2229 if (item != bcsMap.end()) {
2230 bcID = item->second;
2232 LOG(fatal) <<
"Error: could not find a corresponding BC ID "
2233 <<
"for MC collision; BC = " << globalBC
2234 <<
", mc collision = " << iCol;
2236 auto& colParts = mcParts[iCol];
2237 auto nParts = colParts.size();
2238 for (
auto colPart : colParts) {
2239 auto eventID = colPart.entryID;
2240 auto sourceID = colPart.sourceID;
2243 if (nParts == 1 || sourceID == 0) {
2246 auto& header = mcReader->getMCEventHeader(sourceID, eventID);
2247 updateMCHeader(mcCollisionsCursor.
cursor,
2248 hepmcXSectionsCursor.
cursor,
2249 hepmcPdfInfosCursor.
cursor,
2250 hepmcHeavyIonsCursor.
cursor,
2258 mcColToEvSrc.emplace_back(std::vector<int>{iCol, sourceID, eventID});
2263 std::sort(mcColToEvSrc.begin(), mcColToEvSrc.end(),
2264 [](
const std::vector<int>&
left,
const std::vector<int>&
right) { return (left[0] < right[0]); });
2267 int16_t aFDDAmplitudesA[8] = {0u}, aFDDAmplitudesC[8] = {0u};
2268 float aFDDTimesA[8] = {0.f}, aFDDTimesC[8] = {0.f};
2270 fddCursor.reserve(fddRecPoints.size());
2271 for (
const auto& fddRecPoint : fddRecPoints) {
2272 for (
int i = 0;
i < 8;
i++) {
2273 aFDDAmplitudesA[
i] = 0;
2274 aFDDAmplitudesC[
i] = 0;
2275 aFDDTimesA[
i] = 0.f;
2276 aFDDTimesC[
i] = 0.f;
2278 uint64_t globalBC = fddRecPoint.getInteractionRecord().toLong();
2279 uint64_t
bc = globalBC;
2280 auto item = bcsMap.find(
bc);
2282 if (item != bcsMap.end()) {
2283 bcID = item->second;
2285 LOG(fatal) <<
"Error: could not find a corresponding BC ID for a FDD rec. point; BC = " <<
bc;
2287 const auto channelData = fddRecPoint.getBunchChannelData(fddChData);
2288 for (
const auto& channel : channelData) {
2289 if (channel.mPMNumber < 8) {
2290 aFDDAmplitudesC[channel.mPMNumber] = channel.mChargeADC;
2291 aFDDTimesC[channel.mPMNumber] = truncateFloatFraction(channel.mTime * 1E-3, mFDDChannelTime);
2293 aFDDAmplitudesA[channel.mPMNumber - 8] = channel.mChargeADC;
2294 aFDDTimesA[channel.mPMNumber - 8] = truncateFloatFraction(channel.mTime * 1E-3, mFDDChannelTime);
2301 truncateFloatFraction(fddRecPoint.getCollisionTimeA() * 1E-3, mFDDTime),
2302 truncateFloatFraction(fddRecPoint.getCollisionTimeC() * 1E-3, mFDDTime),
2303 fddRecPoint.getTrigger().getTriggersignals());
2304 if (mEnableFITextra) {
2305 fddExtraCursor(bcID,
2312 std::vector<float> aAmplitudesA, aAmplitudesC, aTimesA, aTimesC;
2313 std::vector<uint8_t> aChannelsA, aChannelsC;
2314 ft0Cursor.reserve(ft0RecPoints.size());
2315 for (
auto& ft0RecPoint : ft0RecPoints) {
2316 aAmplitudesA.clear();
2317 aAmplitudesC.clear();
2322 const auto channelData = ft0RecPoint.getBunchChannelData(ft0ChData);
2323 for (
auto& channel : channelData) {
2325 if (channel.QTCAmpl > 0) {
2327 if (channel.ChId < nFT0ChannelsAside) {
2328 aChannelsA.push_back(channel.ChId);
2329 aAmplitudesA.push_back(truncateFloatFraction(channel.QTCAmpl, mT0Amplitude));
2330 aTimesA.push_back(truncateFloatFraction(channel.CFDTime * 1E-3, mT0ChannelTime));
2332 aChannelsC.push_back(channel.ChId - nFT0ChannelsAside);
2333 aAmplitudesC.push_back(truncateFloatFraction(channel.QTCAmpl, mT0Amplitude));
2334 aTimesC.push_back(truncateFloatFraction(channel.CFDTime * 1E-3, mT0ChannelTime));
2338 uint64_t globalBC = ft0RecPoint.getInteractionRecord().toLong();
2339 uint64_t
bc = globalBC;
2340 auto item = bcsMap.find(
bc);
2342 if (item != bcsMap.end()) {
2343 bcID = item->second;
2345 LOG(fatal) <<
"Error: could not find a corresponding BC ID for a FT0 rec. point; BC = " <<
bc;
2352 truncateFloatFraction(ft0RecPoint.getCollisionTimeA() * 1E-3, mT0Time),
2353 truncateFloatFraction(ft0RecPoint.getCollisionTimeC() * 1E-3, mT0Time),
2354 ft0RecPoint.getTrigger().getTriggersignals());
2355 if (mEnableFITextra) {
2356 ft0ExtraCursor(bcID,
2364 mcColLabelsCursor.
reserve(primVerLabels.size());
2365 for (
auto&
label : primVerLabels) {
2366 auto it = std::find_if(mcColToEvSrc.begin(), mcColToEvSrc.end(),
2367 [&
label](
const auto& mcColInfo) { return mcColInfo[1] == label.getSourceID() && mcColInfo[2] == label.getEventID(); });
2368 int32_t mcCollisionID = -1;
2369 if (it != mcColToEvSrc.end()) {
2370 mcCollisionID = it->at(0);
2372 uint16_t mcMask = 0;
2373 mcColLabelsCursor(mcCollisionID, mcMask);
2377 cacheTriggers(recoData);
2378 countTPCClusters(recoData);
2380 int collisionID = 0;
2384 auto& trackReffwd = primVer2TRefs.back();
2385 fillIndexTablesPerCollision(trackReffwd, primVerGIs, recoData);
2387 for (
auto&
vertex : primVertices) {
2388 auto& trackReffwd = primVer2TRefs[collisionID];
2389 fillIndexTablesPerCollision(trackReffwd, primVerGIs, recoData);
2394 prepareStrangenessTracking(recoData);
2396 mGIDToTableFwdID.clear();
2397 mGIDToTableMFTID.clear();
2399 if (mPropTracks || mThinTracks) {
2403 mGIDUsedBySVtx.reserve(v0s.size() * 2 + cascades.size() + decays3Body.size() * 3);
2404 for (
const auto&
v0 : v0s) {
2405 mGIDUsedBySVtx.insert(
v0.getProngID(0));
2406 mGIDUsedBySVtx.insert(
v0.getProngID(1));
2408 for (
const auto& cascade : cascades) {
2409 mGIDUsedBySVtx.insert(cascade.getBachelorID());
2411 for (
const auto& id3Body : decays3Body) {
2412 mGIDUsedBySVtx.insert(id3Body.getProngID(0));
2413 mGIDUsedBySVtx.insert(id3Body.getProngID(1));
2414 mGIDUsedBySVtx.insert(id3Body.getProngID(2));
2423 mCurrentTRDTrigID = 0;
2426 auto& trackRef = primVer2TRefs.back();
2428 fillTrackTablesPerCollision(-1, std::uint64_t(-1), trackRef, primVerGIs, recoData, tracksCursor, tracksCovCursor, tracksExtraCursor, tracksQACursor, trdExtraCursor,
2429 ambigTracksCursor, mftTracksCursor, mftTracksCovCursor, ambigMFTTracksCursor,
2430 fwdTracksCursor, fwdTracksCovCursor, ambigFwdTracksCursor, fwdTrkClsCursor, bcsMap);
2432 mCurrentTRDTrigID = 0;
2435 collisionsCursor.reserve(primVertices.size());
2436 for (
auto&
vertex : primVertices) {
2437 auto& cov =
vertex.getCov();
2438 auto& timeStamp =
vertex.getTimeStamp();
2439 const double interactionTime = timeStamp.getTimeStamp() * 1E3;
2440 uint64_t globalBC = relativeTime_to_GlobalBC(interactionTime);
2441 uint64_t localBC = relativeTime_to_LocalBC(interactionTime);
2442 LOG(
debug) <<
"global BC " << globalBC <<
" local BC " << localBC <<
" relative interaction time " << interactionTime;
2445 auto item = bcsMap.find(globalBC);
2447 if (item != bcsMap.end()) {
2448 bcID = item->second;
2450 LOG(fatal) <<
"Error: could not find a corresponding BC ID for a collision; BC = " << globalBC <<
", collisionID = " << collisionID;
2452 collisionsCursor(bcID,
2453 truncateFloatFraction(
vertex.getX(), mCollisionPosition),
2454 truncateFloatFraction(
vertex.getY(), mCollisionPosition),
2455 truncateFloatFraction(
vertex.getZ(), mCollisionPosition),
2456 truncateFloatFraction(cov[0], mCollisionPositionCov),
2457 truncateFloatFraction(cov[1], mCollisionPositionCov),
2458 truncateFloatFraction(cov[2], mCollisionPositionCov),
2459 truncateFloatFraction(cov[3], mCollisionPositionCov),
2460 truncateFloatFraction(cov[4], mCollisionPositionCov),
2461 truncateFloatFraction(cov[5], mCollisionPositionCov),
2463 truncateFloatFraction(
vertex.getChi2(), mCollisionPositionCov),
2464 vertex.getNContributors(),
2465 truncateFloatFraction(relInteractionTime, mCollisionPosition),
2466 truncateFloatFraction(timeStamp.getTimeStampError() * 1E3, mCollisionPositionCov));
2467 mVtxToTableCollID[collisionID] = mTableCollID++;
2469 auto& trackRef = primVer2TRefs[collisionID];
2471 fillTrackTablesPerCollision(collisionID, globalBC, trackRef, primVerGIs, recoData, tracksCursor, tracksCovCursor, tracksExtraCursor, tracksQACursor, trdExtraCursor, ambigTracksCursor,
2472 mftTracksCursor, mftTracksCovCursor, ambigMFTTracksCursor,
2473 fwdTracksCursor, fwdTracksCovCursor, ambigFwdTracksCursor, fwdTrkClsCursor, bcsMap);
2477 fillSecondaryVertices(recoData, v0sCursor, cascadesCursor, decay3BodyCursor);
2478 fillHMPID(recoData, hmpCursor);
2479 fillStrangenessTrackingTables(recoData, trackedV0Cursor, trackedCascadeCursor, tracked3BodyCurs);
2483 std::unordered_map<uint64_t, std::pair<uint64_t, uint64_t>> bcToClassMask;
2485 LOG(
debug) <<
"CTP input available";
2486 for (
auto& ctpDigit : ctpDigits) {
2487 uint64_t
bc = ctpDigit.intRecord.toLong();
2488 uint64_t classMask = ctpDigit.CTPClassMask.to_ulong();
2489 uint64_t inputMask = ctpDigit.CTPInputMask.to_ulong();
2490 if (emcalIncomplete.find(
bc) != emcalIncomplete.end()) {
2492 auto classMaskOrig = classMask;
2493 classMask = classMask & ~mEMCALTrgClassMask;
2494 LOG(
debug) <<
"Found EMCAL incomplete event, mask before " << std::bitset<64>(classMaskOrig) <<
", after " << std::bitset<64>(classMask);
2496 bcToClassMask[
bc] = {classMask, inputMask};
2502 bcCursor.reserve(bcsMap.size());
2503 for (
auto& item : bcsMap) {
2504 uint64_t
bc = item.first;
2505 std::pair<uint64_t, uint64_t> masks{0, 0};
2507 auto bcClassPair = bcToClassMask.find(
bc);
2508 if (bcClassPair != bcToClassMask.end()) {
2509 masks = bcClassPair->second;
2518 bcToClassMask.clear();
2521 auto bcFlags = fillBCFlags(recoData, bcsMap);
2522 bcFlagsCursor.reserve(bcFlags.size());
2523 for (
auto f : bcFlags) {
2530 cpvClustersCursor.reserve(cpvTrigRecs.size());
2531 for (
auto& cpvEvent : cpvTrigRecs) {
2532 uint64_t
bc = cpvEvent.getBCData().toLong();
2533 auto item = bcsMap.find(
bc);
2535 if (item != bcsMap.end()) {
2536 bcID = item->second;
2538 LOG(fatal) <<
"Error: could not find a corresponding BC ID for a CPV Trigger Record; BC = " <<
bc;
2540 for (
int iClu = cpvEvent.getFirstEntry(); iClu < cpvEvent.getFirstEntry() + cpvEvent.getNumberOfObjects(); iClu++) {
2541 auto&
clu = cpvClusters[iClu];
2542 clu.getLocalPosition(posX, posZ);
2543 cpvClustersCursor(bcID,
2544 truncateFloatFraction(posX, mCPVPos),
2545 truncateFloatFraction(posZ, mCPVPos),
2546 truncateFloatFraction(
clu.getEnergy(), mCPVAmpl),
2547 clu.getPackedClusterStatus());
2556 fillMCParticlesTable(*mcReader,
2557 mcParticlesCursor.
cursor,
2563 LOG(info) <<
"FILL MC took " << timer.RealTime() <<
" s";
2564 mcColToEvSrc.clear();
2570 fillMCTrackLabelsTable(mcTrackLabelCursor, mcMFTTrackLabelCursor, mcFwdTrackLabelCursor, primVer2TRefs.back(), primVerGIs, recoData);
2571 for (
auto iref = 0U; iref < primVer2TRefs.size() - 1; iref++) {
2572 auto& trackRef = primVer2TRefs[iref];
2573 fillMCTrackLabelsTable(mcTrackLabelCursor, mcMFTTrackLabelCursor, mcFwdTrackLabelCursor, trackRef, primVerGIs, recoData, iref);
2579 fillCaloTable(caloCellsCursor, caloCellsTRGTableCursor, mcCaloLabelsCursor, bcsMap, recoData);
2584 mGIDToTableID.clear();
2586 mGIDToTableFwdID.clear();
2588 mGIDToTableMFTID.clear();
2590 mVtxToTableCollID.clear();
2592 mV0ToTableID.clear();
2595 mIndexTableFwd.clear();
2597 mIndexTableMFT.clear();
2602 mGIDUsedBySVtx.clear();
2603 mGIDUsedByStr.clear();
2605 originCursor(tfNumber);
2608 TString dataType = mUseMC ?
"MC" :
"RAW";
2610 TString ROOTVersion = ROOT_RELEASE;
2611 mMetaDataKeys = {
"DataType",
"Run",
"O2Version",
"ROOTVersion",
"RecoPassName",
"AnchorProduction",
"AnchorPassName",
"LPMProductionTag",
"CreatedBy"};
2612 mMetaDataVals = {dataType,
"3", O2Version, ROOTVersion, mRecoPass, mAnchorProd, mAnchorPass, mLPMProdTag, mUser};
2613 add_additional_meta_info(mMetaDataKeys, mMetaDataVals);
2631 for (
const auto& rof : rofs) {
2632 int first = rof.getFirstEntry(), last =
first + rof.getNEntries();
2633 for (
int i =
first;
i < last;
i++) {
2634 mITSROFs.push_back(
count);
2644 for (
const auto& rof : rofs) {
2645 int first = rof.getFirstEntry(),
last =
first + rof.getNEntries();
2647 mMFTROFs.push_back(
count);
2654 mITSTPCTRDTriggers.clear();
2657 for (
const auto& trig : itstpctrigs) {
2658 int first = trig.getFirstTrack(),
last =
first + trig.getNumberOfTracks();
2660 mITSTPCTRDTriggers.push_back(
count);
2667 mTPCTRDTriggers.clear();
2670 for (
const auto& trig : tpctrigs) {
2671 int first = trig.getFirstTrack(),
last =
first + trig.getNumberOfTracks();
2673 mTPCTRDTriggers.push_back(
count);
2683 for (
const auto& rof : rofs) {
2686 mMCHROFs.push_back(
count);
2693AODProducerWorkflowDPL::TrackExtraInfo AODProducerWorkflowDPL::processBarrelTrack(
int collisionID, std::uint64_t collisionBC,
GIndex trackIndex,
2696 TrackExtraInfo extraInfoHolder;
2697 if (collisionID < 0) {
2700 bool needBCSlice = collisionID < 0;
2701 uint64_t bcOfTimeRef = collisionBC - mStartIR.
toLong();
2703 auto setTrackTime = [&](
double t,
double terr,
bool gaussian) {
2709 extraInfoHolder.trackTimeRes = terr;
2711 double error = this->mTimeMarginTrackTime + (gaussian ? extraInfoHolder.trackTimeRes * this->mNSigmaTimeTrack : extraInfoHolder.trackTimeRes);
2712 bcOfTimeRef = fillBCSlice(extraInfoHolder.bcSlice, t - error, t + error, bcsMap);
2715 extraInfoHolder.diffBCRef =
int(bcOfTimeRef);
2717 truncateFloatFraction(extraInfoHolder.trackTime, mTrackTime), truncateFloatFraction(extraInfoHolder.trackTimeRes, mTrackTimeError),
2720 auto contributorsGID =
data.getSingleDetectorRefs(trackIndex);
2721 const auto& trackPar =
data.getTrackParam(trackIndex);
2722 extraInfoHolder.flags |= trackPar.getPID() << 28;
2723 auto src = trackIndex.getSource();
2725 const auto& tofMatch =
data.getTOFMatch(trackIndex);
2726 extraInfoHolder.tofChi2 = tofMatch.getChi2();
2727 const auto& tofInt = tofMatch.getLTIntegralOut();
2728 float intLen = tofInt.getL();
2729 extraInfoHolder.length = intLen;
2736 extraInfoHolder.tofExpMom = mass * expBeta / std::sqrt(1.f - expBeta * expBeta);
2739 const double massZ = o2::track::PID::getMass2Z(trackPar.getPID());
2740 const double energy = sqrt((massZ * massZ) + (extraInfoHolder.tofExpMom * extraInfoHolder.tofExpMom));
2741 const double exp = extraInfoHolder.length * energy / (cSpeed * extraInfoHolder.tofExpMom);
2742 auto tofSignal = (tofMatch.getSignal() -
exp) * 1e-3;
2743 setTrackTime(tofSignal, 0.2,
true);
2747 extraInfoHolder.trdChi2 = trdOrig.getChi2();
2748 extraInfoHolder.trdSignal = trdOrig.getSignal();
2749 extraInfoHolder.trdPattern = getTRDPattern(trdOrig);
2750 if (extraInfoHolder.trackTimeRes < 0.) {
2752 const auto& trdTrig = (
src ==
GIndex::Source::TPCTRD) ?
data.getTPCTRDTriggers()[mTPCTRDTriggers[trackIndex.getIndex()]] :
data.getITSTPCTRDTriggers()[mITSTPCTRDTriggers[trackIndex.getIndex()]];
2754 setTrackTime(ttrig, 1.,
true);
2758 const auto& itsTrack =
data.getITSTrack(contributorsGID[
GIndex::ITS]);
2759 int nClusters = itsTrack.getNClusters();
2760 float chi2 = itsTrack.getChi2();
2762 extraInfoHolder.itsClusterSizes = itsTrack.getClusterSizes();
2764 const auto& rof =
data.getITSTracksROFRecords()[mITSROFs[trackIndex.getIndex()]];
2766 setTrackTime(t, mITSROFrameHalfLengthNS,
false);
2769 extraInfoHolder.itsClusterSizes =
data.getITSABRefs()[contributorsGID[
GIndex::Source::ITSAB].getIndex()].getClusterSizes();
2773 const auto& tpcClData = mTPCCounters[contributorsGID[
GIndex::TPC]];
2774 const auto& dEdx = tpcOrig.getdEdx().dEdxTotTPC > 0 ? tpcOrig.getdEdx() : tpcOrig.getdEdxAlt();
2775 if (tpcOrig.getdEdx().dEdxTotTPC == 0) {
2778 if (tpcOrig.hasASideClusters()) {
2781 if (tpcOrig.hasCSideClusters()) {
2784 extraInfoHolder.tpcInnerParam = tpcOrig.getP() / tpcOrig.getAbsCharge();
2785 extraInfoHolder.tpcChi2NCl = tpcOrig.getNClusters() ? tpcOrig.getChi2() / tpcOrig.getNClusters() : 0;
2786 extraInfoHolder.tpcSignal = dEdx.dEdxTotTPC;
2787 extraInfoHolder.tpcNClsFindable = tpcOrig.getNClusters();
2788 extraInfoHolder.tpcNClsFindableMinusFound = tpcOrig.getNClusters() - tpcClData.found;
2789 extraInfoHolder.tpcNClsFindableMinusCrossedRows = tpcOrig.getNClusters() - tpcClData.crossed;
2790 extraInfoHolder.tpcNClsShared = tpcClData.shared;
2791 uint32_t clsUsedForPID = dEdx.NHitsIROC + dEdx.NHitsOROC1 + dEdx.NHitsOROC2 + dEdx.NHitsOROC3;
2792 extraInfoHolder.tpcNClsFindableMinusPID = tpcOrig.getNClusters() - clsUsedForPID;
2795 double t = (tpcOrig.getTime0() + 0.5 * (tpcOrig.getDeltaTFwd() - tpcOrig.getDeltaTBwd())) * mTPCBinNS;
2796 double terr = 0.5 * (tpcOrig.getDeltaTFwd() + tpcOrig.getDeltaTBwd()) * mTPCBinNS;
2797 double err = mTimeMarginTrackTime + terr;
2798 bcOfTimeRef = fillBCSlice(extraInfoHolder.bcSlice, t - err, t + err, bcsMap);
2801 p.setDeltaTFwd(tpcOrig.getDeltaTFwd());
2802 p.setDeltaTBwd(tpcOrig.getDeltaTBwd());
2803 extraInfoHolder.trackTimeRes =
p.getTimeErr();
2805 extraInfoHolder.diffBCRef =
int(bcOfTimeRef);
2806 extraInfoHolder.isTPConly =
true;
2809 const auto& trITSTPC =
data.getTPCITSTrack(trackIndex);
2810 auto ts = trITSTPC.getTimeMUS();
2811 setTrackTime(ts.getTimeStamp() * 1.e3, ts.getTimeStampError() * 1.e3,
true);
2815 extrapolateToCalorimeters(extraInfoHolder,
data.getTrackParamOut(trackIndex));
2820 return extraInfoHolder;
2823AODProducerWorkflowDPL::TrackQA AODProducerWorkflowDPL::processBarrelTrackQA(
int collisionID, std::uint64_t collisionBC,
GIndex trackIndex,
2827 auto contributorsGID =
data.getTPCContributorGID(trackIndex);
2828 const auto& trackPar =
data.getTrackParam(trackIndex);
2829 if (contributorsGID.isIndexSet()) {
2831 const auto& tpcOrig =
data.getTPCTrack(contributorsGID);
2836 std::array<float, 2> dcaInfo{-999., -999.};
2837 if (prop->propagateToDCABxByBz({v.getX(), v.getY(), v.getZ()}, tpcTMP, 2.f, mMatType, &dcaInfo)) {
2838 trackQAHolder.tpcdcaR = 100. * dcaInfo[0] / sqrt(1. + trackPar.getQ2Pt() * trackPar.getQ2Pt());
2839 trackQAHolder.tpcdcaZ = 100. * dcaInfo[1] / sqrt(1. + trackPar.getQ2Pt() * trackPar.getQ2Pt());
2843 auto safeInt8Clamp = [](
auto value) -> int8_t {
2844 using ValType =
decltype(
value);
2845 return static_cast<int8_t
>(TMath::Nint(std::clamp(
value,
static_cast<ValType
>(std::numeric_limits<int8_t>::min()),
static_cast<ValType
>(std::numeric_limits<int8_t>::max()))));
2847 auto safeUInt8Clamp = [](
auto value) -> uint8_t {
2848 using ValType =
decltype(
value);
2849 return static_cast<uint8_t>(TMath::Nint(std::clamp(
value,
static_cast<ValType
>(std::numeric_limits<uint8_t>::min()),
static_cast<ValType
>(std::numeric_limits<uint8_t>::max()))));
2853 uint8_t clusterCounters[8] = {0};
2855 uint8_t sectorIndex, rowIndex;
2856 uint32_t clusterIndex;
2857 const auto& tpcClusRefs =
data.getTPCTracksClusterRefs();
2858 for (
int i = 0;
i < tpcOrig.getNClusterReferences();
i++) {
2859 o2::tpc::TrackTPC::getClusterReference(tpcClusRefs,
i, sectorIndex, rowIndex, clusterIndex, tpcOrig.getClusterRef());
2860 char indexTracklet = (rowIndex % 152) / 19;
2861 clusterCounters[indexTracklet]++;
2865 for (
int i = 0;
i < 8;
i++) {
2866 if (clusterCounters[
i] > 5) {
2867 byteMask |= (1 <<
i);
2870 trackQAHolder.tpcTime0 = tpcOrig.getTime0();
2871 trackQAHolder.tpcClusterByteMask = byteMask;
2872 const auto& dEdxInfoAlt = tpcOrig.getdEdxAlt();
2873 const float dEdxNorm = (dEdxInfoAlt.dEdxTotTPC > 0) ? 100. / dEdxInfoAlt.dEdxTotTPC : 0;
2874 trackQAHolder.tpcdEdxNorm = dEdxInfoAlt.dEdxTotTPC;
2875 trackQAHolder.tpcdEdxMax0R = safeUInt8Clamp(dEdxInfoAlt.dEdxMaxIROC * dEdxNorm);
2876 trackQAHolder.tpcdEdxMax1R = safeUInt8Clamp(dEdxInfoAlt.dEdxMaxOROC1 * dEdxNorm);
2877 trackQAHolder.tpcdEdxMax2R = safeUInt8Clamp(dEdxInfoAlt.dEdxMaxOROC2 * dEdxNorm);
2878 trackQAHolder.tpcdEdxMax3R = safeUInt8Clamp(dEdxInfoAlt.dEdxMaxOROC3 * dEdxNorm);
2880 trackQAHolder.tpcdEdxTot0R = safeUInt8Clamp(dEdxInfoAlt.dEdxTotIROC * dEdxNorm);
2881 trackQAHolder.tpcdEdxTot1R = safeUInt8Clamp(dEdxInfoAlt.dEdxTotOROC1 * dEdxNorm);
2882 trackQAHolder.tpcdEdxTot2R = safeUInt8Clamp(dEdxInfoAlt.dEdxTotOROC2 * dEdxNorm);
2883 trackQAHolder.tpcdEdxTot3R = safeUInt8Clamp(dEdxInfoAlt.dEdxTotOROC3 * dEdxNorm);
2886 auto contributorsGIDA =
data.getSingleDetectorRefs(trackIndex);
2888 const auto& tofMatch =
data.getTOFMatch(trackIndex);
2889 const float qpt = trackPar.getQ2Pt();
2891 trackQAHolder.dTofdX = safeInt8Clamp(tofMatch.getDXatTOF() / scaleTOF);
2892 trackQAHolder.dTofdZ = safeInt8Clamp(tofMatch.getDZatTOF() / scaleTOF);
2898 if (
auto itsContGID =
data.getITSContributorGID(trackIndex); itsContGID.isIndexSet() && itsContGID.getSource() !=
GIndex::ITSAB) {
2899 const auto& itsOrig =
data.getITSTrack(itsContGID);
2908 const float beta0 = std::sqrt(std::min(50.f / tpcOrig.getdEdx().dEdxMaxTPC, 1.f));
2909 const float qpt = gloCopy.getQ2Pt();
2910 const float x = qpt / beta0;
2912 auto scaleCont = [&
x](
int i) ->
float {
2915 auto scaleGlo = [&
x](
int i) ->
float {
2920 trackQAHolder.dRefContY = safeInt8Clamp((itsCopy.getY() - tpcCopy.getY()) * scaleCont(0));
2921 trackQAHolder.dRefContZ = safeInt8Clamp((itsCopy.getZ() - tpcCopy.getZ()) * scaleCont(1));
2922 trackQAHolder.dRefContSnp = safeInt8Clamp((itsCopy.getSnp() - tpcCopy.getSnp()) * scaleCont(2));
2923 trackQAHolder.dRefContTgl = safeInt8Clamp((itsCopy.getTgl() - tpcCopy.getTgl()) * scaleCont(3));
2924 trackQAHolder.dRefContQ2Pt = safeInt8Clamp((itsCopy.getQ2Pt() - tpcCopy.getQ2Pt()) * scaleCont(4));
2926 trackQAHolder.dRefGloY = safeInt8Clamp(((itsCopy.getY() + tpcCopy.getY()) * 0.5f - gloCopy.getY()) * scaleGlo(0));
2927 trackQAHolder.dRefGloZ = safeInt8Clamp(((itsCopy.getZ() + tpcCopy.getZ()) * 0.5f - gloCopy.getZ()) * scaleGlo(1));
2928 trackQAHolder.dRefGloSnp = safeInt8Clamp(((itsCopy.getSnp() + tpcCopy.getSnp()) * 0.5f - gloCopy.getSnp()) * scaleGlo(2));
2929 trackQAHolder.dRefGloTgl = safeInt8Clamp(((itsCopy.getTgl() + tpcCopy.getTgl()) * 0.5f - gloCopy.getTgl()) * scaleGlo(3));
2930 trackQAHolder.dRefGloQ2Pt = safeInt8Clamp(((itsCopy.getQ2Pt() + tpcCopy.getQ2Pt()) * 0.5f - gloCopy.getQ2Pt()) * scaleGlo(4));
2934 (*mStreamer) <<
"trackQA"
2935 <<
"trackITSOrig=" << itsOrig
2936 <<
"trackTPCOrig=" << tpcOrig
2937 <<
"trackITSTPCOrig=" << trackPar
2938 <<
"trackITSProp=" << itsCopy
2939 <<
"trackTPCProp=" << tpcCopy
2940 <<
"trackITSTPCProp=" << gloCopy
2943 <<
"scaleCont0=" << scaleCont(0)
2944 <<
"scaleCont1=" << scaleCont(1)
2945 <<
"scaleCont2=" << scaleCont(2)
2946 <<
"scaleCont3=" << scaleCont(3)
2947 <<
"scaleCont4=" << scaleCont(4)
2948 <<
"scaleGlo0=" << scaleGlo(0)
2949 <<
"scaleGlo1=" << scaleGlo(1)
2950 <<
"scaleGlo2=" << scaleGlo(2)
2951 <<
"scaleGlo3=" << scaleGlo(3)
2952 <<
"scaleGlo4=" << scaleGlo(4)
2953 <<
"trackQAHolder.tpcTime0=" << trackQAHolder.tpcTime0
2954 <<
"trackQAHolder.tpcdEdxNorm=" << trackQAHolder.tpcdEdxNorm
2955 <<
"trackQAHolder.tpcdcaR=" << trackQAHolder.tpcdcaR
2956 <<
"trackQAHolder.tpcdcaZ=" << trackQAHolder.tpcdcaZ
2957 <<
"trackQAHolder.tpcdcaClusterByteMask=" << trackQAHolder.tpcClusterByteMask
2958 <<
"trackQAHolder.tpcdEdxMax0R=" << trackQAHolder.tpcdEdxMax0R
2959 <<
"trackQAHolder.tpcdEdxMax1R=" << trackQAHolder.tpcdEdxMax1R
2960 <<
"trackQAHolder.tpcdEdxMax2R=" << trackQAHolder.tpcdEdxMax2R
2961 <<
"trackQAHolder.tpcdEdxMax3R=" << trackQAHolder.tpcdEdxMax3R
2962 <<
"trackQAHolder.tpcdEdxTot0R=" << trackQAHolder.tpcdEdxTot0R
2963 <<
"trackQAHolder.tpcdEdxTot1R=" << trackQAHolder.tpcdEdxTot1R
2964 <<
"trackQAHolder.tpcdEdxTot2R=" << trackQAHolder.tpcdEdxTot2R
2965 <<
"trackQAHolder.tpcdEdxTot3R=" << trackQAHolder.tpcdEdxTot3R
2966 <<
"trackQAHolder.dRefContY=" << trackQAHolder.dRefContY
2967 <<
"trackQAHolder.dRefContZ=" << trackQAHolder.dRefContZ
2968 <<
"trackQAHolder.dRefContSnp=" << trackQAHolder.dRefContSnp
2969 <<
"trackQAHolder.dRefContTgl=" << trackQAHolder.dRefContTgl
2970 <<
"trackQAHolder.dRefContQ2Pt=" << trackQAHolder.dRefContQ2Pt
2971 <<
"trackQAHolder.dRefGloY=" << trackQAHolder.dRefGloY
2972 <<
"trackQAHolder.dRefGloZ=" << trackQAHolder.dRefGloZ
2973 <<
"trackQAHolder.dRefGloSnp=" << trackQAHolder.dRefGloSnp
2974 <<
"trackQAHolder.dRefGloTgl=" << trackQAHolder.dRefGloTgl
2975 <<
"trackQAHolder.dRefGloQ2Pt=" << trackQAHolder.dRefGloQ2Pt
2976 <<
"trackQAHolder.dTofdX=" << trackQAHolder.dTofdX
2977 <<
"trackQAHolder.dTofdZ=" << trackQAHolder.dTofdZ
2978 <<
"scaleTOF=" << scaleTOF
2985 return trackQAHolder;
2993 dcaInfo.set(999.f, 999.f, 999.f, 999.f, 999.f);
2998void AODProducerWorkflowDPL::extrapolateToCalorimeters(TrackExtraInfo& extraInfoHolder,
const o2::track::TrackPar& track)
3000 constexpr float XEMCAL = 440.f, XPHOS = 460.f, XEMCAL2 = XEMCAL * XEMCAL;
3001 constexpr float ETAEMCAL = 0.75;
3002 constexpr float ZEMCALFastCheck = 460.;
3003 constexpr float ETADCALINNER = 0.22;
3004 constexpr float ETAPHOS = 0.13653194;
3005 constexpr float ETAPHOSMARGIN = 0.17946979;
3006 constexpr float ETADCALPHOSSWITCH = (ETADCALINNER + ETAPHOS) / 2;
3007 constexpr short SNONE = 0, SEMCAL = 0x1, SPHOS = 0x2;
3008 constexpr short SECTORTYPE[18] = {
3009 SNONE, SNONE, SNONE, SNONE,
3010 SEMCAL, SEMCAL, SEMCAL, SEMCAL, SEMCAL, SEMCAL,
3013 SPHOS | SEMCAL, SPHOS | SEMCAL, SPHOS | SEMCAL,
3024 (std::abs(outTr.getZAt(xtrg, 0)) > ZEMCALFastCheck) ||
3025 !prop->PropagateToXBxByBz(outTr, xtrg, 0.95, 10, o2::base::Propagator::MatCorrType::USEMatCorrLUT)) {
3026 LOGP(
debug,
"preliminary step: does not reach R={} {}", XEMCAL, outTr.asString());
3030 if ((outTr.getX() * outTr.getX() + outTr.getY() * outTr.getY() < XEMCAL2) &&
3031 (!outTr.rotateParam(outTr.getPhi()) ||
3033 !prop->PropagateToXBxByBz(outTr, xtrg, 0.95, 10, o2::base::Propagator::MatCorrType::USEMatCorrLUT))) {
3034 LOGP(
debug,
"does not reach R={} {}", XEMCAL, outTr.asString());
3040 auto propExactSector = [&outTr, §or, prop](
float xprop) ->
bool {
3043 auto outTrTmp = outTr;
3045 if ((std::abs(outTr.getZ()) > ZEMCALFastCheck) || !outTrTmp.rotateParam(
alpha) ||
3046 !prop->PropagateToXBxByBz(outTrTmp, xprop, 0.95, 10, o2::base::Propagator::MatCorrType::USEMatCorrLUT)) {
3047 LOGP(
debug,
"failed on rotation to {} (sector {}) or propagation to X={} {}",
alpha, sector, xprop, outTrTmp.asString());
3052 if (sectorTmp == sector) {
3060 LOGP(
debug,
"failed to rotate to sector, {}", outTr.asString());
3067 if (!propExactSector(XEMCAL) || SECTORTYPE[sector] == SNONE) {
3072 float r = std::sqrt(outTr.getX() * outTr.getX() + outTr.getY() * outTr.getY()), tg = std::atan2(
r, outTr.getZ());
3073 float eta = -std::log(std::tan(0.5f * tg)), etaAbs = std::abs(eta);
3074 if (etaAbs > ETAEMCAL) {
3075 LOGP(
debug,
"eta = {} is off at EMCAL radius", eta, outTr.asString());
3079 if ((SECTORTYPE[sector] & SPHOS) && etaAbs < ETADCALPHOSSWITCH) {
3080 if (!propExactSector(XPHOS)) {
3083 r = std::sqrt(outTr.getX() * outTr.getX() + outTr.getY() * outTr.getY());
3084 tg = std::atan2(
r, outTr.getZ());
3085 eta = -std::log(std::tan(0.5f * tg));
3086 }
else if (!(SECTORTYPE[sector] & SEMCAL)) {
3089 extraInfoHolder.trackPhiEMCAL = outTr.getPhiPos();
3090 extraInfoHolder.trackEtaEMCAL = eta;
3091 LOGP(
debug,
"eta = {} phi = {} sector {} for {}", extraInfoHolder.trackEtaEMCAL, extraInfoHolder.trackPhiEMCAL, sector, outTr.asString());
3095std::set<uint64_t> AODProducerWorkflowDPL::filterEMCALIncomplete(
const gsl::span<const o2::emcal::TriggerRecord> triggers)
3097 std::set<uint64_t> emcalIncompletes;
3098 for (
const auto& trg : triggers) {
3099 if (trg.getTriggerBits() & o2::emcal::triggerbits::Inc) {
3101 emcalIncompletes.insert(trg.getBCData().toLong());
3104 return emcalIncompletes;
3110 static bool initOnceDone =
false;
3111 if (!initOnceDone) {
3112 initOnceDone =
true;
3119 for (
auto i = 0U;
i < bs.size();
i++) {
3134 mTPCBinNS = elParam.ZbinWidth * 1.e3;
3137 mNSigmaTimeTrack = pvParams.nSigmaTimeTrack;
3138 mTimeMarginTrackTime = pvParams.timeMarginTrackTime * 1.e3;
3142 if (mEnableTRDextra) {
3164 LOG(info) <<
"ITS Alpide param updated";
3166 par.printKeyValues();
3170 LOG(info) <<
"MFT Alpide param updated";
3172 par.printKeyValues();
3183 mEMCALTrgClassMask = 0;
3184 for (
const auto& trgclass : ctpconfig.getCTPClasses()) {
3186 mEMCALTrgClassMask |= trgclass.classMask;
3189 LOG(info) <<
"Loaded EMCAL trigger class mask: " << std::bitset<64>(mEMCALTrgClassMask);
3193void AODProducerWorkflowDPL::addRefGlobalBCsForTOF(
const o2::dataformats::VtxTrackRef& trackRef,
const gsl::span<const GIndex>& GIndices,
3204 int nbitsFrac = 24 - (32 - o2::math_utils::popcount(mTrackTime));
3205 int nbitsLoss = std::max(0,
int(std::log2(TOFTimePrecPS)));
3206 assert(nbitsFrac > 1);
3207 std::uint64_t maxRangePS = std::uint64_t(0x1) << (nbitsFrac + nbitsLoss);
3209 LOG(info) <<
"Max gap of " << maxGapBC <<
" BCs to closest globalBC reference is needed for TOF tracks to provide precision of "
3210 << TOFTimePrecPS <<
" ps";
3213 if (!trackRef.getEntries()) {
3217 std::uint64_t maxBC = mStartIR.
toLong();
3218 const auto& tofClus =
data.getTOFClusters();
3225 for (
int ti =
start; ti <
end; ti++) {
3226 auto& trackIndex = GIndices[ti];
3227 const auto& tofMatch =
data.getTOFMatch(trackIndex);
3228 const auto& tofInt = tofMatch.getLTIntegralOut();
3229 float intLen = tofInt.getL();
3230 float tofExpMom = 0.;
3240 double massZ = o2::track::PID::getMass2Z(
data.getTrackParam(trackIndex).getPID());
3241 double energy = sqrt((massZ * massZ) + (tofExpMom * tofExpMom));
3242 double exp = intLen * energy / (cSpeed * tofExpMom);
3243 auto tofSignal = (tofMatch.getSignal() -
exp) * 1e-3;
3244 auto bc = relativeTime_to_GlobalBC(tofSignal);
3246 auto it = bcsMap.lower_bound(
bc);
3247 if (it == bcsMap.end() || it->first >
bc + maxGapBC) {
3248 bcsMap.emplace_hint(it,
bc, 1);
3257 if ((--bcsMap.end())->first <= maxBC) {
3258 bcsMap.emplace_hint(bcsMap.end(), maxBC + 1, 1);
3262 for (
auto& item : bcsMap) {
3268std::uint64_t AODProducerWorkflowDPL::fillBCSlice(
int (&slice)[2],
double tmin,
double tmax,
const std::map<uint64_t, int>& bcsMap)
const
3280 uint64_t bcMin = relativeTime_to_GlobalBC(tmin), bcMax = relativeTime_to_GlobalBC(tmax);
3303 auto upperindex =
p.first;
3304 while (upperindex < bcvector.size() && bcvector[upperindex] <= bcMax) {
3307 if (upperindex !=
p.first) {
3311 slice[1] = upperindex;
3313 auto bcOfTimeRef =
p.second - this->mStartIR.
toLong();
3314 LOG(
debug) <<
"BC slice t:" << tmin <<
" " << slice[0]
3315 <<
" t: " << tmax <<
" " << slice[1]
3316 <<
" bcref: " << bcOfTimeRef;
3322 std::vector<uint8_t>
flags(bcsMap.size());
3325 auto bcIt = bcsMap.begin();
3326 auto itsrofs =
data.getITSTracksROFRecords();
3329 for (
auto& rof : itsrofs) {
3330 if (!rof.getFlag(o2::itsmft::ROFRecord::VtxUPCMode)) {
3333 uint64_t globalBC0 = rof.getBCData().toLong() + bROF, globalBC1 = globalBC0 + lROF - 1;
3335 while (bcIt != bcsMap.end()) {
3336 if (bcIt->first < globalBC0) {
3340 if (bcIt->first > globalBC1) {
3352 LOGF(info,
"aod producer dpl total timing: Cpu: %.3e Real: %.3e s in %d slots",
3353 mTimer.CpuTime(), mTimer.RealTime(), mTimer.Counter() - 1);
3360 auto dataRequest = std::make_shared<DataRequest>();
3361 dataRequest->inputs.emplace_back(
"ctpconfig",
"CTP",
"CTPCONFIG", 0, Lifetime::Condition,
ccdbParamSpec(
"CTP/Config/Config", CTPConfigPerRun));
3363 dataRequest->requestTracks(
src, useMC);
3364 dataRequest->requestPrimaryVertices(useMC);
3366 dataRequest->requestCTPDigits(useMC);
3369 dataRequest->requestSecondaryVertices(useMC);
3371 if (enableStrangenessTracking) {
3372 dataRequest->requestStrangeTracks(useMC);
3373 LOGF(info,
"requestStrangeTracks Finish");
3382 dataRequest->requestTOFClusters(useMC);
3385 dataRequest->requestPHOSCells(useMC);
3388 dataRequest->requestTRDTracklets(
false);
3391 dataRequest->requestEMCALCells(useMC);
3394 dataRequest->requestCPVClusters(useMC);
3397 auto ggRequest = std::make_shared<o2::base::GRPGeomRequest>(
true,
3403 dataRequest->inputs,
3406 dataRequest->inputs.emplace_back(
"meanvtx",
"GLO",
"MEANVERTEX", 0, Lifetime::Condition,
ccdbParamSpec(
"GLO/Calib/MeanVertex", {}, 1));
3411 std::vector<OutputSpec> outputs{
3450 if (enableTRDextra) {
3452 dataRequest->inputs.emplace_back(
"trdlocalgainfactors",
"TRD",
"LOCALGAINFACTORS", 0, Lifetime::Condition,
ccdbParamSpec(
"TRD/Calib/LocalGainFactor"));
3453 dataRequest->inputs.emplace_back(
"trdnoisemap",
"TRD",
"NOISEMAP", 0, Lifetime::Condition,
ccdbParamSpec(
"TRD/Calib/NoiseMapMCM"));
3454 dataRequest->inputs.emplace_back(
"trdgaincalib",
"TRD",
"CALGAIN", 0, Lifetime::Condition,
ccdbParamSpec(
"TRD/Calib/CalGain"));
3458 outputs.insert(outputs.end(),
3459 {OutputForTable<McCollisions>::spec(),
3460 OutputForTable<HepMCXSections>::spec(),
3461 OutputForTable<HepMCPdfInfos>::spec(),
3462 OutputForTable<HepMCHeavyIons>::spec(),
3463 OutputForTable<McMFTTrackLabels>::spec(),
3464 OutputForTable<McFwdTrackLabels>::spec(),
3465 OutputForTable<StoredMcParticles_001>::spec(),
3466 OutputForTable<McTrackLabels>::spec(),
3467 OutputForTable<McCaloLabels_001>::spec(),
3472 {OutputLabel{
"McCollisionLabels"},
"AOD",
"MCCOLLISIONLABEL", 0, Lifetime::Timeframe}});
3476 "aod-producer-workflow",
3479 AlgorithmSpec{adaptFromTask<AODProducerWorkflowDPL>(
src, dataRequest, ggRequest, enableSV, useMC, enableFITextra, enableTRDextra)},
3481 ConfigParamSpec{
"run-number", VariantType::Int64, -1L, {
"The run-number. If left default we try to get it from DPL header."}},
3482 ConfigParamSpec{
"aod-timeframe-id", VariantType::Int64, -1L, {
"Set timeframe number"}},
3483 ConfigParamSpec{
"fill-calo-cells", VariantType::Int, 1, {
"Fill calo cells into cell table"}},
3484 ConfigParamSpec{
"enable-truncation", VariantType::Int, 1, {
"Truncation parameter: 1 -- on, != 1 -- off"}},
3485 ConfigParamSpec{
"lpmp-prod-tag", VariantType::String,
"", {
"LPMProductionTag"}},
3486 ConfigParamSpec{
"anchor-pass", VariantType::String,
"", {
"AnchorPassName"}},
3487 ConfigParamSpec{
"anchor-prod", VariantType::String,
"", {
"AnchorProduction"}},
3488 ConfigParamSpec{
"reco-pass", VariantType::String,
"", {
"RecoPassName"}},
3489 ConfigParamSpec{
"aod-parent", VariantType::String,
"", {
"Parent AOD file name (if any)"}},
3490 ConfigParamSpec{
"created-by", VariantType::String,
"", {
"Who created this AO2D"}},
3491 ConfigParamSpec{
"nthreads", VariantType::Int, std::max(1,
int(std::thread::hardware_concurrency() / 2)), {
"Number of threads"}},
3492 ConfigParamSpec{
"reco-mctracks-only", VariantType::Int, 0, {
"Store only reconstructed MC tracks and their mothers/daughters. 0 -- off, != 0 -- on"}},
3493 ConfigParamSpec{
"ctpreadout-create", VariantType::Int, 0, {
"Create CTP digits from detector readout and CTP inputs. !=1 -- off, 1 -- on"}},
3494 ConfigParamSpec{
"emc-select-leading", VariantType::Bool,
false, {
"Flag to select if only the leading contributing particle for an EMCal cell should be stored"}},
3495 ConfigParamSpec{
"propagate-tracks", VariantType::Bool,
false, {
"Propagate tracks (not used for secondary vertices) to IP"}},
3496 ConfigParamSpec{
"propagate-tracks-max-xiu", VariantType::Float, 5.0f, {
"Propagate tracks to IP if X_IU smaller than this value (and if propagate tracks enabled)"}},
3497 ConfigParamSpec{
"hepmc-update", VariantType::String,
"always", {
"When to update HepMC Aux tables: always - force update, never - never update, all - if all keys are present, any - when any key is present (not valid yet)"}},
3498 ConfigParamSpec{
"propagate-muons", VariantType::Bool,
false, {
"Propagate muons to IP"}},
3499 ConfigParamSpec{
"thin-tracks", VariantType::Bool,
false, {
"Produce thinned track tables"}},
3500 ConfigParamSpec{
"trackqc-keepglobaltracks", VariantType::Bool,
false, {
"Always keep TrackQA for global tracks"}},
3501 ConfigParamSpec{
"trackqc-retainonlydedx", VariantType::Bool,
false, {
"Keep only dEdx information, zero out everything else"}},
3502 ConfigParamSpec{
"trackqc-fraction", VariantType::Float, float(0.1), {
"Fraction of tracks to QC"}},
3503 ConfigParamSpec{
"trackqc-NTrCut", VariantType::Int64, 4L, {
"Minimal length of the track - in amount of tracklets"}},
3504 ConfigParamSpec{
"trackqc-tpc-dca", VariantType::Float, 3.f, {
"Keep TPC standalone track with this DCAxy to the PV"}},
3505 ConfigParamSpec{
"trackqc-tpc-cls", VariantType::Int, 80, {
"Keep TPC standalone track with this #clusters"}},
3506 ConfigParamSpec{
"trackqc-tpc-pt", VariantType::Float, 0.2f, {
"Keep TPC standalone track with this pt"}},
3507 ConfigParamSpec{
"with-streamers", VariantType::String,
"", {
"Bit-mask to steer writing of intermediate streamer files"}},
3508 ConfigParamSpec{
"seed", VariantType::Int, 0, {
"Set seed for random generator used for sampling (0 (default) means using a random_device)"}},
3509 ConfigParamSpec{
"mc-signal-filt", VariantType::Bool,
false, {
"Enable usage of signal filtering (only for MC with embedding)"}}}};
Class to refer to the reconstructed information.
Definition of the 32 Central Trigger System (CTS) Trigger Types defined in https://twiki....
General auxilliary methods.
uint64_t exp(uint64_t base, uint8_t exp) noexcept
definition of CTPDigit, CTPInputDigit
Header of the AggregatedRunInfo struct.
Global Forward Muon tracks.
Global index for barrel track: provides provenance (detectors combination), index in respective array...
Definition of the MCTrack class.
Definition of a container to keep Monte Carlo truth external to simulation objects.
Utility functions for MC particles.
Class to perform MFT MCH (and MID) matching.
Class to store the output of the matching to HMPID.
Class to perform TOF matching to global tracks.
Definition of the parameter class for the detector electronics.
Header to collect physics constants.
Definition of the FDD RecPoint class.
Definition of the ITS track.
Definition of the MUON track.
Definition of the MCH track.
Definition of the MCH track parameters for internal use.
Result of refitting TPC-ITS matched track.
Extention of GlobalTrackID by flags relevant for verter-track association.
Referenc on track indices contributing to the vertex, with possibility chose tracks from specific sou...
Container class to store energy released in the ZDC.
Container class to store a TDC hit in a ZDC channel.
const auto & getBCPattern() const
void GetStartVertex(TVector3 &vertex) const
void endOfStream(framework::EndOfStreamContext &ec) final
This is invoked whenever we have an EndOfStream event.
void finaliseCCDB(ConcreteDataMatcher &matcher, void *obj) final
void run(ProcessingContext &pc) final
void init(InitContext &ic) final
std::pair< size_t, uint64_t > lower_bound(uint64_t timestamp) const
void init(std::map< uint64_t, int > const &bcs)
initialize this container (to be ready for lookup/search queries)
void clear()
clear/reset this container
std::vector< uint64_t > const & getBCTimeVector() const
return the sorted vector of increaing BC times
static float getAmplitude(const o2::emcal::Cell &cell)
static int16_t getLnAmplitude(const o2::emcal::Cell &)
static int8_t getTriggerBits(const o2::emcal::Cell &)
static int16_t getCellNumber(const o2::emcal::Cell &cell)
static int16_t getFastOrAbsID(const o2::emcal::Cell &)
static bool isTRU(const o2::emcal::Cell &cell)
static float getTimeStamp(const o2::emcal::Cell &cell)
void checkUpdates(o2::framework::ProcessingContext &pc)
static GRPGeomHelper & instance()
void setRequest(std::shared_ptr< GRPGeomRequest > req)
static constexpr float MAX_SIN_PHI
static constexpr float MAX_STEP
GPUd() value_type estimateLTFast(o2 static GPUd() float estimateLTIncrement(const o2 PropagatorImpl * Instance(bool uninitialized=false)
static const DPLAlpideParam< N > & Instance()
void printStream(std::ostream &stream) const
Static class with identifiers, bitmasks and names for ALICE detectors.
Handler for EMCAL event data.
void reset()
Reset containers with empty ranges.
void setCellData(CellRange cells, TriggerRange triggers)
Setting the data at cell level.
void setCellMCTruthContainer(const o2::dataformats::MCTruthContainer< o2::emcal::MCLabel > *mclabels)
Setting the pointer for the MCTruthContainer for cells.
InteractionRecord getInteractionRecordForEvent(int eventID) const
Get the interaction record for the given event.
int getNumberOfEvents() const
Get the number of events handled by the event handler.
T get(const char *key) const
void snapshot(const Output &spec, T const &object)
ConfigParamRegistry const & options()
DataAllocator & outputs()
The data allocator is used to allocate memory for the output data.
InputRecord & inputs()
The inputs associated with this processing context.
ServiceRegistryRef services()
The services registry associated with this processing context.
static constexpr int NCellsA
o2::dataformats::GlobalFwdTrack MCHtoFwd(const o2::mch::TrackParam &mchTrack)
Converts mchTrack parameters to Forward coordinate system.
track parameters for internal use
Double_t getNonBendingCoor() const
return non bending coordinate (cm)
Double_t getBendingCoor() const
return bending coordinate (cm)
void setCellMCTruthContainer(const o2::dataformats::MCTruthContainer< o2::phos::MCLabel > *mclabels)
Setting the pointer for the MCTruthContainer for cells.
void setCellData(CellRange cells, TriggerRange triggers)
Setting the data at cell level.
void reset()
Reset containers with empty ranges.
InteractionRecord getInteractionRecordForEvent(int eventID) const
int getNumberOfEvents() const
MCTrack const * getTrack(o2::MCCompLabel const &) const
void releaseTracksForSourceAndEvent(int source, int event)
API to ask releasing tracks (freeing memory) for source + event.
std::vector< MCTrack > const & getTracks(int source, int event) const
variant returning all tracks for source and event at once
static void addInteractionBC(int bc, bool fromCollisonCotext=false)
float getMPVdEdx(int iDet, bool defaultAvg=true) const
Simple noise status bit for each MCM of the TRD.
bool isTrackletFromNoisyMCM(const Tracklet64 &trklt) const
T getValue(int roc, int col, int row) const
void set(const std::string &s, int base=DefaultBase)
bool match(const std::vector< std::string > &queries, const char *pattern)
GLfloat GLfloat GLfloat alpha
GLint GLint GLsizei GLuint * counters
GLuint GLuint GLfloat weight
GLboolean GLboolean GLboolean b
GLsizei GLsizei GLchar * source
GLsizei const GLfloat * value
GLint GLint GLsizei GLint GLenum GLenum type
GLenum GLsizei GLsizei GLint * values
GLuint GLsizei const GLchar * label
GLboolean GLboolean GLboolean GLboolean a
constexpr std::array< float, 2 > trackQAScaledTOF
constexpr std::array< float, 5 > trackQAScaleContP1
uint8_t itsSharedClusterMap uint8_t
constexpr std::array< float, 5 > trackQAScaleContP0
constexpr std::array< float, 5 > trackQAScaleGloP0
constexpr std::array< float, 5 > trackQAScaleGloP1
constexpr float trackQAScaleBins
constexpr float trackQARefRadius
bool updateHepMCHeavyIon(const HeavyIonCursor &cursor, int collisionID, short generatorID, o2::dataformats::MCEventHeader const &header, HepMCUpdate when=HepMCUpdate::anyKey)
short updateMCCollisions(const CollisionCursor &cursor, int bcId, float time, o2::dataformats::MCEventHeader const &header, short generatorId=0, int sourceId=0, unsigned int mask=0xFFFFFFF0)
bool updateHepMCPdfInfo(const PdfInfoCursor &cursor, int collisionID, short generatorID, o2::dataformats::MCEventHeader const &header, HepMCUpdate when=HepMCUpdate::anyKey)
uint32_t updateParticles(const ParticleCursor &cursor, int collisionID, std::vector< MCTrack > const &tracks, TrackToIndex &preselect, uint32_t offset=0, bool filter=false, bool background=false, uint32_t weightMask=0xFFFFFFF0, uint32_t momentumMask=0xFFFFFFF0, uint32_t positionMask=0xFFFFFFF0, bool signalFilter=false)
bool updateHepMCXSection(const XSectionCursor &cursor, int collisionID, short generatorID, o2::dataformats::MCEventHeader const &header, HepMCUpdate when=HepMCUpdate::anyKey)
framework::DataProcessorSpec getAODProducerWorkflowSpec(GID::mask_t src, bool enableSV, bool enableST, bool useMC, bool CTPConfigPerRun, bool enableFITextra, bool enableTRDextra)
create a processor spec
void keepMCParticle(std::vector< std::vector< std::unordered_map< int, int > > > &store, int source, int event, int track, int value=1, bool useSigFilt=false)
void dimensionMCKeepStore(std::vector< std::vector< std::unordered_map< int, int > > > &store, int Nsources, int NEvents)
void clearMCKeepStore(std::vector< std::vector< std::unordered_map< int, int > > > &store)
constexpr int LHCMaxBunches
constexpr double LHCBunchSpacingNS
constexpr double MassPionCharged
Defining PrimaryVertex explicitly as messageable.
std::vector< ConfigParamSpec > ccdbParamSpec(std::string const &path, int runDependent, std::vector< CCDBMetadata > metadata={}, int qrate=0)
int angle2Sector(float phi)
float sector2Angle(int sect)
constexpr float MPVDEDXDEFAULT
default Most Probable Value of TRD dEdx
const int TDCSignal[NTDCChannels]
constexpr int NTDCChannels
std::string fullVersion()
get full version information (official O2 release and git commit)
static OutputSpec const spec()
decltype(FFL(std::declval< cursor_t >())) cursor
void reserve(int64_t size)
auto getZDCTDCData() const
auto getStrangeTracks() const
auto getFDDRecPoints() const
auto getMCHMIDMatches() const
const U & getTrack(int src, int id) const
o2::InteractionRecord startIR
GlobalIDSet getSingleDetectorRefs(GTrackID gidx) const
auto getDecays3BodyIdx() const
const o2::tpc::TrackTPC & getTPCTrack(GTrackID id) const
gsl::span< const o2::trd::CalibratedTracklet > getTRDCalibratedTracklets() const
auto getTPCTRDTriggers() const
auto getPrimaryVertices() const
auto getPrimaryVertexMatchedTracks() const
auto getMCHTrackClusters() const
auto getMCHTracksROFRecords() const
auto getCTPDigits() const
auto getCascadesIdx() const
auto getPrimaryVertexMatchedTrackRefs() const
gsl::span< const o2::trd::TriggerRecord > getTRDTriggerRecords() const
auto getCPVClusters() const
auto getFV0ChannelsData() const
auto getMFTTracksROFRecords() const
auto getCPVTriggers() const
const o2::dataformats::TrackTPCITS & getTPCITSTrack(GTrackID gid) const
void collectData(o2::framework::ProcessingContext &pc, const DataRequest &request)
auto getPrimaryVertexMCLabels() const
auto getZDCEnergy() const
auto getFT0RecPoints() const
auto getITSTracksROFRecords() const
auto getMCHTracks() const
auto getFV0RecPoints() const
auto getHMPMatches() const
auto getITSTPCTRDTriggers() const
auto getFT0ChannelsData() const
auto getFDDChannelsData() const
auto getZDCBCRecData() const
auto getEMCALTriggers() const
auto getMFTTracks() const
gsl::span< const o2::trd::Tracklet64 > getTRDTracklets() const
auto getPHOSTriggers() const
static bool downsampleTsallisCharged(float pt, float factorPt, float sqrts, float &weight, float rnd, float mass=0.13957)
std::vector< o2::ctf::BufferType > vec
LOG(info)<< "Compressed in "<< sw.CpuTime()<< " s"
std::uniform_int_distribution< unsigned long long > distr
std::array< uint16_t, 5 > pattern