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 mTFNumber = ic.
options().
get<int64_t>(
"aod-timeframe-id");
1822 mRecoOnly = ic.
options().
get<
int>(
"reco-mctracks-only");
1823 mTruncate = ic.
options().
get<
int>(
"enable-truncation");
1824 mRunNumber = ic.
options().
get<
int>(
"run-number");
1825 mCTPReadout = ic.
options().
get<
int>(
"ctpreadout-create");
1826 mNThreads = std::max(1, ic.
options().
get<
int>(
"nthreads"));
1827 mEMCselectLeading = ic.
options().
get<
bool>(
"emc-select-leading");
1828 mThinTracks = ic.
options().
get<
bool>(
"thin-tracks");
1829 mPropTracks = ic.
options().
get<
bool>(
"propagate-tracks");
1830 mMaxPropXiu = ic.
options().
get<
float>(
"propagate-tracks-max-xiu");
1831 mPropMuons = ic.
options().
get<
bool>(
"propagate-muons");
1832 if (
auto s = ic.
options().
get<std::string>(
"with-streamers"); !
s.empty()) {
1833 mStreamerFlags.
set(
s);
1834 if (mStreamerFlags) {
1835 LOGP(info,
"Writing streamer data with mask:");
1836 LOG(info) << mStreamerFlags;
1838 LOGP(warn,
"Specified non-default empty streamer mask!");
1841 mTrackQCKeepGlobalTracks = ic.
options().
get<
bool>(
"trackqc-keepglobaltracks");
1842 mTrackQCRetainOnlydEdx = ic.
options().
get<
bool>(
"trackqc-retainonlydedx");
1843 mTrackQCFraction = ic.
options().
get<
float>(
"trackqc-fraction");
1844 mTrackQCNTrCut = ic.
options().
get<int64_t>(
"trackqc-NTrCut");
1845 mTrackQCDCAxy = ic.
options().
get<
float>(
"trackqc-tpc-dca");
1846 mTrackQCPt = ic.
options().
get<
float>(
"trackqc-tpc-pt");
1847 mTrackQCNCls = ic.
options().
get<
int>(
"trackqc-tpc-cls");
1848 if (
auto seed = ic.
options().
get<
int>(
"seed"); seed == 0) {
1849 LOGP(info,
"Using random device for seeding");
1850 std::random_device
rd;
1851 std::array<int, std::mt19937::state_size> seed_data{};
1852 std::generate(std::begin(seed_data), std::end(seed_data), std::ref(
rd));
1853 std::seed_seq seq(std::begin(seed_data), std::end(seed_data));
1854 mGenerator = std::mt19937(seq);
1856 LOGP(info,
"Using seed {} for sampling", seed);
1857 mGenerator.seed(seed);
1860 LOGP(info,
"Multi-threaded parts will run with {} OpenMP threads", mNThreads);
1863 LOG(info) <<
"OpenMP is disabled";
1865 if (mTFNumber == -1L) {
1866 LOG(info) <<
"TFNumber will be obtained from CCDB";
1868 if (mRunNumber == -1L) {
1869 LOG(info) <<
"The Run number will be obtained from DPL headers";
1872 mUseSigFiltMC = ic.
options().
get<
bool>(
"mc-signal-filt");
1875 if (mTruncate != 1) {
1876 LOG(info) <<
"Truncation is not used!";
1877 mCollisionPosition = 0xFFFFFFFF;
1878 mCollisionPositionCov = 0xFFFFFFFF;
1879 mTrackX = 0xFFFFFFFF;
1880 mTrackAlpha = 0xFFFFFFFF;
1881 mTrackSnp = 0xFFFFFFFF;
1882 mTrackTgl = 0xFFFFFFFF;
1883 mTrack1Pt = 0xFFFFFFFF;
1884 mTrackChi2 = 0xFFFFFFFF;
1885 mTrackCovDiag = 0xFFFFFFFF;
1886 mTrackCovOffDiag = 0xFFFFFFFF;
1887 mTrackSignal = 0xFFFFFFFF;
1888 mTrackTime = 0xFFFFFFFF;
1889 mTPCTime0 = 0xFFFFFFFF;
1890 mTrackTimeError = 0xFFFFFFFF;
1891 mTrackPosEMCAL = 0xFFFFFFFF;
1892 mTracklets = 0xFFFFFFFF;
1893 mMcParticleW = 0xFFFFFFFF;
1894 mMcParticlePos = 0xFFFFFFFF;
1895 mMcParticleMom = 0xFFFFFFFF;
1896 mCaloAmp = 0xFFFFFFFF;
1897 mCaloTime = 0xFFFFFFFF;
1898 mCPVPos = 0xFFFFFFFF;
1899 mCPVAmpl = 0xFFFFFFFF;
1900 mMuonTr1P = 0xFFFFFFFF;
1901 mMuonTrThetaX = 0xFFFFFFFF;
1902 mMuonTrThetaY = 0xFFFFFFFF;
1903 mMuonTrZmu = 0xFFFFFFFF;
1904 mMuonTrBend = 0xFFFFFFFF;
1905 mMuonTrNonBend = 0xFFFFFFFF;
1906 mMuonTrCov = 0xFFFFFFFF;
1907 mMuonCl = 0xFFFFFFFF;
1908 mMuonClErr = 0xFFFFFFFF;
1909 mV0Time = 0xFFFFFFFF;
1910 mV0ChannelTime = 0xFFFFFFFF;
1911 mFDDTime = 0xFFFFFFFF;
1912 mFDDChannelTime = 0xFFFFFFFF;
1913 mT0Time = 0xFFFFFFFF;
1914 mT0ChannelTime = 0xFFFFFFFF;
1915 mV0Amplitude = 0xFFFFFFFF;
1916 mFDDAmplitude = 0xFFFFFFFF;
1917 mT0Amplitude = 0xFFFFFFFF;
1921 mZDCEnergyMap[ic] = -std::numeric_limits<float>::infinity();
1924 mZDCTDCMap[ic] = -std::numeric_limits<float>::infinity();
1927 std::string hepmcUpdate = ic.
options().
get<std::string>(
"hepmc-update");
1928 HepMCUpdate when = (hepmcUpdate ==
"never" ? HepMCUpdate::never : hepmcUpdate ==
"always" ? HepMCUpdate::always
1929 : hepmcUpdate ==
"all" ? HepMCUpdate::allKeys
1930 : HepMCUpdate::anyKey);
1931 mXSectionUpdate = when;
1932 mPdfInfoUpdate = when;
1933 mHeavyIonUpdate = when;
1937 if (mStreamerFlags) {
1938 mStreamer = std::make_unique<o2::utils::TreeStreamRedirector>(
"AO2DStreamer.root",
"RECREATE");
1944void add_additional_meta_info(std::vector<TString>& keys, std::vector<TString>&
values)
1947 auto aod_external_meta_info_file = getenv(
"AOD_ADDITIONAL_METADATA_FILE");
1948 if (aod_external_meta_info_file !=
nullptr) {
1949 LOG(info) <<
"Trying to inject additional AOD meta-data from " << aod_external_meta_info_file;
1950 if (std::filesystem::exists(aod_external_meta_info_file)) {
1951 std::ifstream input_file(aod_external_meta_info_file);
1953 nlohmann::json json_data;
1955 input_file >> json_data;
1956 }
catch (nlohmann::json::parse_error& e) {
1957 std::cerr <<
"JSON Parse Error: " << e.what() <<
"\n";
1958 std::cerr <<
"Exception ID: " << e.id <<
"\n";
1959 std::cerr <<
"Byte position: " << e.byte <<
"\n";
1963 for (
const auto& [
key,
value] : json_data.items()) {
1964 LOG(info) <<
"Adding AOD MetaData" <<
key <<
" : " <<
value;
1965 keys.push_back(
key.c_str());
1976 mTimer.Start(
false);
1979 updateTimeDependentParams(pc);
2004 std::vector<o2::ctp::CTPDigit> ctpDigitsCreated;
2005 if (mCTPReadout == 1) {
2006 LOG(info) <<
"CTP : creating ctpreadout in AOD producer";
2007 createCTPReadout(recoData, ctpDigitsCreated, pc);
2008 LOG(info) <<
"CTP : ctpreadout created from AOD";
2009 ctpDigits = gsl::span<o2::ctp::CTPDigit>(ctpDigitsCreated);
2011 LOG(
debug) <<
"FOUND " << primVertices.size() <<
" primary vertices";
2012 LOG(
debug) <<
"FOUND " << ft0RecPoints.size() <<
" FT0 rec. points";
2013 LOG(
debug) <<
"FOUND " << fv0RecPoints.size() <<
" FV0 rec. points";
2014 LOG(
debug) <<
"FOUND " << fddRecPoints.size() <<
" FDD rec. points";
2015 LOG(
debug) <<
"FOUND " << cpvClusters.size() <<
" CPV clusters";
2016 LOG(
debug) <<
"FOUND " << cpvTrigRecs.size() <<
" CPV trigger records";
2018 LOG(info) <<
"FOUND " << primVertices.size() <<
" primary vertices";
2022 auto bcCursor = createTableCursor<o2::aod::BCs>(pc);
2023 auto bcFlagsCursor = createTableCursor<o2::aod::BCFlags>(pc);
2024 auto cascadesCursor = createTableCursor<o2::aod::Cascades>(pc);
2025 auto collisionsCursor = createTableCursor<o2::aod::Collisions>(pc);
2026 auto decay3BodyCursor = createTableCursor<o2::aod::Decay3Bodys>(pc);
2027 auto trackedCascadeCursor = createTableCursor<o2::aod::TrackedCascades>(pc);
2028 auto trackedV0Cursor = createTableCursor<o2::aod::TrackedV0s>(pc);
2029 auto tracked3BodyCurs = createTableCursor<o2::aod::Tracked3Bodys>(pc);
2030 auto fddCursor = createTableCursor<o2::aod::FDDs>(pc);
2031 auto fddExtraCursor = createTableCursor<o2::aod::FDDsExtra>(pc);
2032 auto ft0Cursor = createTableCursor<o2::aod::FT0s>(pc);
2033 auto ft0ExtraCursor = createTableCursor<o2::aod::FT0sExtra>(pc);
2034 auto fv0aCursor = createTableCursor<o2::aod::FV0As>(pc);
2035 auto fv0aExtraCursor = createTableCursor<o2::aod::FV0AsExtra>(pc);
2036 auto fwdTracksCursor = createTableCursor<o2::aod::StoredFwdTracks>(pc);
2037 auto fwdTracksCovCursor = createTableCursor<o2::aod::StoredFwdTracksCov>(pc);
2038 auto fwdTrkClsCursor = createTableCursor<o2::aod::FwdTrkCls>(pc);
2039 auto mftTracksCursor = createTableCursor<o2::aod::StoredMFTTracks>(pc);
2040 auto mftTracksCovCursor = createTableCursor<o2::aod::StoredMFTTracksCov>(pc);
2041 auto tracksCursor = createTableCursor<o2::aod::StoredTracksIU>(pc);
2042 auto tracksCovCursor = createTableCursor<o2::aod::StoredTracksCovIU>(pc);
2043 auto tracksExtraCursor = createTableCursor<o2::aod::StoredTracksExtra>(pc);
2044 auto tracksQACursor = createTableCursor<o2::aod::TracksQAVersion>(pc);
2045 auto ambigTracksCursor = createTableCursor<o2::aod::AmbiguousTracks>(pc);
2046 auto ambigMFTTracksCursor = createTableCursor<o2::aod::AmbiguousMFTTracks>(pc);
2047 auto ambigFwdTracksCursor = createTableCursor<o2::aod::AmbiguousFwdTracks>(pc);
2048 auto v0sCursor = createTableCursor<o2::aod::V0s>(pc);
2049 auto zdcCursor = createTableCursor<o2::aod::Zdcs>(pc);
2050 auto hmpCursor = createTableCursor<o2::aod::HMPIDs>(pc);
2051 auto caloCellsCursor = createTableCursor<o2::aod::Calos>(pc);
2052 auto caloCellsTRGTableCursor = createTableCursor<o2::aod::CaloTriggers>(pc);
2053 auto cpvClustersCursor = createTableCursor<o2::aod::CPVClusters>(pc);
2054 auto originCursor = createTableCursor<o2::aod::Origins>(pc);
2058 if (mEnableTRDextra) {
2059 trdExtraCursor = createTableCursor<o2::aod::TRDsExtra>(pc);
2074 mcColLabelsCursor = createTableCursor<o2::aod::McCollisionLabels>(pc);
2075 mcCollisionsCursor = createTableCursor<o2::aod::McCollisions>(pc);
2076 hepmcXSectionsCursor = createTableCursor<o2::aod::HepMCXSections>(pc);
2077 hepmcPdfInfosCursor = createTableCursor<o2::aod::HepMCPdfInfos>(pc);
2078 hepmcHeavyIonsCursor = createTableCursor<o2::aod::HepMCHeavyIons>(pc);
2079 mcMFTTrackLabelCursor = createTableCursor<o2::aod::McMFTTrackLabels>(pc);
2080 mcFwdTrackLabelCursor = createTableCursor<o2::aod::McFwdTrackLabels>(pc);
2081 mcParticlesCursor = createTableCursor<o2::aod::StoredMcParticles_001>(pc);
2082 mcTrackLabelCursor = createTableCursor<o2::aod::McTrackLabels>(pc);
2083 mcCaloLabelsCursor = createTableCursor<o2::aod::McCaloLabels_001>(pc);
2086 std::unique_ptr<o2::steer::MCKinematicsReader> mcReader;
2088 mcReader = std::make_unique<o2::steer::MCKinematicsReader>(
"collisioncontext.root");
2090 mMCKineReader = mcReader.get();
2091 std::map<uint64_t, int> bcsMap;
2092 collectBCs(recoData, mUseMC ? mcReader->getDigitizationContext()->getEventRecords() : std::vector<o2::InteractionTimeRecord>{}, bcsMap);
2093 if (!primVer2TRefs.empty()) {
2094 addRefGlobalBCsForTOF(primVer2TRefs.back(), primVerGIs, recoData, bcsMap);
2097 mBCLookup.
init(bcsMap);
2100 const int runNumber = (mRunNumber == -1) ?
int(tinfo.runNumber) : mRunNumber;
2101 if (mTFNumber == -1L) {
2103 tfNumber = uint64_t(tinfo.firstTForbit) + (uint64_t(tinfo.runNumber) << 32);
2105 tfNumber = mTFNumber;
2108 std::vector<float> aAmplitudes, aTimes;
2109 std::vector<uint8_t> aChannels;
2110 fv0aCursor.reserve(fv0RecPoints.size());
2111 for (
auto& fv0RecPoint : fv0RecPoints) {
2112 aAmplitudes.clear();
2115 const auto channelData = fv0RecPoint.getBunchChannelData(fv0ChData);
2116 for (
auto& channel : channelData) {
2117 if (channel.charge > 0) {
2118 aAmplitudes.push_back(truncateFloatFraction(channel.charge, mV0Amplitude));
2119 aTimes.push_back(truncateFloatFraction(channel.time * 1.E-3, mV0ChannelTime));
2120 aChannels.push_back(channel.channel);
2123 uint64_t
bc = fv0RecPoint.getInteractionRecord().toLong();
2124 auto item = bcsMap.find(
bc);
2126 if (item != bcsMap.end()) {
2127 bcID = item->second;
2129 LOG(fatal) <<
"Error: could not find a corresponding BC ID for a FV0 rec. point; BC = " <<
bc;
2134 truncateFloatFraction(fv0RecPoint.getCollisionGlobalMeanTime() * 1E-3, mV0Time),
2135 fv0RecPoint.getTrigger().getTriggersignals());
2137 if (mEnableFITextra) {
2138 fv0aExtraCursor(bcID,
2143 std::vector<float> zdcEnergy, zdcAmplitudes, zdcTime;
2144 std::vector<uint8_t> zdcChannelsE, zdcChannelsT;
2145 zdcCursor.reserve(zdcBCRecData.size());
2146 for (
auto zdcRecData : zdcBCRecData) {
2147 uint64_t
bc = zdcRecData.ir.toLong();
2148 auto item = bcsMap.find(
bc);
2150 if (item != bcsMap.end()) {
2151 bcID = item->second;
2153 LOG(fatal) <<
"Error: could not find a corresponding BC ID for a ZDC rec. point; BC = " <<
bc;
2155 int fe, ne, ft, nt, fi, ni;
2156 zdcRecData.getRef(fe, ne, ft, nt, fi, ni);
2158 zdcChannelsE.clear();
2159 zdcAmplitudes.clear();
2161 zdcChannelsT.clear();
2162 for (
int ie = 0; ie < ne; ie++) {
2163 auto& zdcEnergyData = zdcEnergies[fe + ie];
2164 zdcEnergy.emplace_back(zdcEnergyData.energy());
2165 zdcChannelsE.emplace_back(zdcEnergyData.ch());
2167 for (
int it = 0; it < nt; it++) {
2168 auto& tdc = zdcTDCData[ft + it];
2169 zdcAmplitudes.emplace_back(tdc.amplitude());
2170 zdcTime.emplace_back(tdc.value());
2184 std::vector<std::vector<int>> mcColToEvSrc;
2190 int nMCCollisions = mcReader->getDigitizationContext()->getNCollisions();
2191 const auto& mcRecords = mcReader->getDigitizationContext()->getEventRecords();
2192 const auto& mcParts = mcReader->getDigitizationContext()->getEventParts();
2195 if (mUseSigFiltMC) {
2196 std::vector<int> sourceIDs{};
2197 for (
int iCol = 0; iCol < nMCCollisions; iCol++) {
2198 for (
auto const& colPart : mcParts[iCol]) {
2199 int sourceID = colPart.sourceID;
2200 if (std::find(sourceIDs.begin(), sourceIDs.end(), sourceID) == sourceIDs.end()) {
2201 sourceIDs.push_back(sourceID);
2203 if (sourceIDs.size() > 1) {
2207 if (sourceIDs.size() > 1) {
2211 if (sourceIDs.size() <= 1) {
2212 LOGP(fatal,
"Signal filtering cannot be enabled without embedding. Please fix the configuration either enabling the embedding, or turning off the signal filtering.");
2217 int totalNParts = 0;
2218 for (
int iCol = 0; iCol < nMCCollisions; iCol++) {
2219 totalNParts += mcParts[iCol].size();
2221 mcCollisionsCursor.
reserve(totalNParts);
2223 for (
int iCol = 0; iCol < nMCCollisions; iCol++) {
2224 const auto time = mcRecords[iCol].getTimeOffsetWrtBC();
2225 auto globalBC = mcRecords[iCol].toLong();
2226 auto item = bcsMap.find(globalBC);
2228 if (item != bcsMap.end()) {
2229 bcID = item->second;
2231 LOG(fatal) <<
"Error: could not find a corresponding BC ID "
2232 <<
"for MC collision; BC = " << globalBC
2233 <<
", mc collision = " << iCol;
2235 auto& colParts = mcParts[iCol];
2236 auto nParts = colParts.size();
2237 for (
auto colPart : colParts) {
2238 auto eventID = colPart.entryID;
2239 auto sourceID = colPart.sourceID;
2242 if (nParts == 1 || sourceID == 0) {
2245 auto& header = mcReader->getMCEventHeader(sourceID, eventID);
2246 updateMCHeader(mcCollisionsCursor.
cursor,
2247 hepmcXSectionsCursor.
cursor,
2248 hepmcPdfInfosCursor.
cursor,
2249 hepmcHeavyIonsCursor.
cursor,
2257 mcColToEvSrc.emplace_back(std::vector<int>{iCol, sourceID, eventID});
2262 std::sort(mcColToEvSrc.begin(), mcColToEvSrc.end(),
2263 [](
const std::vector<int>&
left,
const std::vector<int>&
right) { return (left[0] < right[0]); });
2266 int16_t aFDDAmplitudesA[8] = {0u}, aFDDAmplitudesC[8] = {0u};
2267 float aFDDTimesA[8] = {0.f}, aFDDTimesC[8] = {0.f};
2269 fddCursor.reserve(fddRecPoints.size());
2270 for (
const auto& fddRecPoint : fddRecPoints) {
2271 for (
int i = 0;
i < 8;
i++) {
2272 aFDDAmplitudesA[
i] = 0;
2273 aFDDAmplitudesC[
i] = 0;
2274 aFDDTimesA[
i] = 0.f;
2275 aFDDTimesC[
i] = 0.f;
2277 uint64_t globalBC = fddRecPoint.getInteractionRecord().toLong();
2278 uint64_t
bc = globalBC;
2279 auto item = bcsMap.find(
bc);
2281 if (item != bcsMap.end()) {
2282 bcID = item->second;
2284 LOG(fatal) <<
"Error: could not find a corresponding BC ID for a FDD rec. point; BC = " <<
bc;
2286 const auto channelData = fddRecPoint.getBunchChannelData(fddChData);
2287 for (
const auto& channel : channelData) {
2288 if (channel.mPMNumber < 8) {
2289 aFDDAmplitudesC[channel.mPMNumber] = channel.mChargeADC;
2290 aFDDTimesC[channel.mPMNumber] = truncateFloatFraction(channel.mTime * 1E-3, mFDDChannelTime);
2292 aFDDAmplitudesA[channel.mPMNumber - 8] = channel.mChargeADC;
2293 aFDDTimesA[channel.mPMNumber - 8] = truncateFloatFraction(channel.mTime * 1E-3, mFDDChannelTime);
2300 truncateFloatFraction(fddRecPoint.getCollisionTimeA() * 1E-3, mFDDTime),
2301 truncateFloatFraction(fddRecPoint.getCollisionTimeC() * 1E-3, mFDDTime),
2302 fddRecPoint.getTrigger().getTriggersignals());
2303 if (mEnableFITextra) {
2304 fddExtraCursor(bcID,
2311 std::vector<float> aAmplitudesA, aAmplitudesC, aTimesA, aTimesC;
2312 std::vector<uint8_t> aChannelsA, aChannelsC;
2313 ft0Cursor.reserve(ft0RecPoints.size());
2314 for (
auto& ft0RecPoint : ft0RecPoints) {
2315 aAmplitudesA.clear();
2316 aAmplitudesC.clear();
2321 const auto channelData = ft0RecPoint.getBunchChannelData(ft0ChData);
2322 for (
auto& channel : channelData) {
2324 if (channel.QTCAmpl > 0) {
2326 if (channel.ChId < nFT0ChannelsAside) {
2327 aChannelsA.push_back(channel.ChId);
2328 aAmplitudesA.push_back(truncateFloatFraction(channel.QTCAmpl, mT0Amplitude));
2329 aTimesA.push_back(truncateFloatFraction(channel.CFDTime * 1E-3, mT0ChannelTime));
2331 aChannelsC.push_back(channel.ChId - nFT0ChannelsAside);
2332 aAmplitudesC.push_back(truncateFloatFraction(channel.QTCAmpl, mT0Amplitude));
2333 aTimesC.push_back(truncateFloatFraction(channel.CFDTime * 1E-3, mT0ChannelTime));
2337 uint64_t globalBC = ft0RecPoint.getInteractionRecord().toLong();
2338 uint64_t
bc = globalBC;
2339 auto item = bcsMap.find(
bc);
2341 if (item != bcsMap.end()) {
2342 bcID = item->second;
2344 LOG(fatal) <<
"Error: could not find a corresponding BC ID for a FT0 rec. point; BC = " <<
bc;
2351 truncateFloatFraction(ft0RecPoint.getCollisionTimeA() * 1E-3, mT0Time),
2352 truncateFloatFraction(ft0RecPoint.getCollisionTimeC() * 1E-3, mT0Time),
2353 ft0RecPoint.getTrigger().getTriggersignals());
2354 if (mEnableFITextra) {
2355 ft0ExtraCursor(bcID,
2363 mcColLabelsCursor.
reserve(primVerLabels.size());
2364 for (
auto&
label : primVerLabels) {
2365 auto it = std::find_if(mcColToEvSrc.begin(), mcColToEvSrc.end(),
2366 [&
label](
const auto& mcColInfo) { return mcColInfo[1] == label.getSourceID() && mcColInfo[2] == label.getEventID(); });
2367 int32_t mcCollisionID = -1;
2368 if (it != mcColToEvSrc.end()) {
2369 mcCollisionID = it->at(0);
2371 uint16_t mcMask = 0;
2372 mcColLabelsCursor(mcCollisionID, mcMask);
2376 cacheTriggers(recoData);
2377 countTPCClusters(recoData);
2379 int collisionID = 0;
2383 auto& trackReffwd = primVer2TRefs.back();
2384 fillIndexTablesPerCollision(trackReffwd, primVerGIs, recoData);
2386 for (
auto&
vertex : primVertices) {
2387 auto& trackReffwd = primVer2TRefs[collisionID];
2388 fillIndexTablesPerCollision(trackReffwd, primVerGIs, recoData);
2393 prepareStrangenessTracking(recoData);
2395 mGIDToTableFwdID.clear();
2396 mGIDToTableMFTID.clear();
2398 if (mPropTracks || mThinTracks) {
2402 mGIDUsedBySVtx.reserve(v0s.size() * 2 + cascades.size() + decays3Body.size() * 3);
2403 for (
const auto&
v0 : v0s) {
2404 mGIDUsedBySVtx.insert(
v0.getProngID(0));
2405 mGIDUsedBySVtx.insert(
v0.getProngID(1));
2407 for (
const auto& cascade : cascades) {
2408 mGIDUsedBySVtx.insert(cascade.getBachelorID());
2410 for (
const auto& id3Body : decays3Body) {
2411 mGIDUsedBySVtx.insert(id3Body.getProngID(0));
2412 mGIDUsedBySVtx.insert(id3Body.getProngID(1));
2413 mGIDUsedBySVtx.insert(id3Body.getProngID(2));
2422 mCurrentTRDTrigID = 0;
2425 auto& trackRef = primVer2TRefs.back();
2427 fillTrackTablesPerCollision(-1, std::uint64_t(-1), trackRef, primVerGIs, recoData, tracksCursor, tracksCovCursor, tracksExtraCursor, tracksQACursor, trdExtraCursor,
2428 ambigTracksCursor, mftTracksCursor, mftTracksCovCursor, ambigMFTTracksCursor,
2429 fwdTracksCursor, fwdTracksCovCursor, ambigFwdTracksCursor, fwdTrkClsCursor, bcsMap);
2431 mCurrentTRDTrigID = 0;
2434 collisionsCursor.reserve(primVertices.size());
2435 for (
auto&
vertex : primVertices) {
2436 auto& cov =
vertex.getCov();
2437 auto& timeStamp =
vertex.getTimeStamp();
2438 const double interactionTime = timeStamp.getTimeStamp() * 1E3;
2439 uint64_t globalBC = relativeTime_to_GlobalBC(interactionTime);
2440 uint64_t localBC = relativeTime_to_LocalBC(interactionTime);
2441 LOG(
debug) <<
"global BC " << globalBC <<
" local BC " << localBC <<
" relative interaction time " << interactionTime;
2444 auto item = bcsMap.find(globalBC);
2446 if (item != bcsMap.end()) {
2447 bcID = item->second;
2449 LOG(fatal) <<
"Error: could not find a corresponding BC ID for a collision; BC = " << globalBC <<
", collisionID = " << collisionID;
2451 collisionsCursor(bcID,
2452 truncateFloatFraction(
vertex.getX(), mCollisionPosition),
2453 truncateFloatFraction(
vertex.getY(), mCollisionPosition),
2454 truncateFloatFraction(
vertex.getZ(), mCollisionPosition),
2455 truncateFloatFraction(cov[0], mCollisionPositionCov),
2456 truncateFloatFraction(cov[1], mCollisionPositionCov),
2457 truncateFloatFraction(cov[2], mCollisionPositionCov),
2458 truncateFloatFraction(cov[3], mCollisionPositionCov),
2459 truncateFloatFraction(cov[4], mCollisionPositionCov),
2460 truncateFloatFraction(cov[5], mCollisionPositionCov),
2462 truncateFloatFraction(
vertex.getChi2(), mCollisionPositionCov),
2463 vertex.getNContributors(),
2464 truncateFloatFraction(relInteractionTime, mCollisionPosition),
2465 truncateFloatFraction(timeStamp.getTimeStampError() * 1E3, mCollisionPositionCov));
2466 mVtxToTableCollID[collisionID] = mTableCollID++;
2468 auto& trackRef = primVer2TRefs[collisionID];
2470 fillTrackTablesPerCollision(collisionID, globalBC, trackRef, primVerGIs, recoData, tracksCursor, tracksCovCursor, tracksExtraCursor, tracksQACursor, trdExtraCursor, ambigTracksCursor,
2471 mftTracksCursor, mftTracksCovCursor, ambigMFTTracksCursor,
2472 fwdTracksCursor, fwdTracksCovCursor, ambigFwdTracksCursor, fwdTrkClsCursor, bcsMap);
2476 fillSecondaryVertices(recoData, v0sCursor, cascadesCursor, decay3BodyCursor);
2477 fillHMPID(recoData, hmpCursor);
2478 fillStrangenessTrackingTables(recoData, trackedV0Cursor, trackedCascadeCursor, tracked3BodyCurs);
2482 std::unordered_map<uint64_t, std::pair<uint64_t, uint64_t>> bcToClassMask;
2484 LOG(
debug) <<
"CTP input available";
2485 for (
auto& ctpDigit : ctpDigits) {
2486 uint64_t
bc = ctpDigit.intRecord.toLong();
2487 uint64_t classMask = ctpDigit.CTPClassMask.to_ulong();
2488 uint64_t inputMask = ctpDigit.CTPInputMask.to_ulong();
2489 if (emcalIncomplete.find(
bc) != emcalIncomplete.end()) {
2491 auto classMaskOrig = classMask;
2492 classMask = classMask & ~mEMCALTrgClassMask;
2493 LOG(
debug) <<
"Found EMCAL incomplete event, mask before " << std::bitset<64>(classMaskOrig) <<
", after " << std::bitset<64>(classMask);
2495 bcToClassMask[
bc] = {classMask, inputMask};
2501 bcCursor.reserve(bcsMap.size());
2502 for (
auto& item : bcsMap) {
2503 uint64_t
bc = item.first;
2504 std::pair<uint64_t, uint64_t> masks{0, 0};
2506 auto bcClassPair = bcToClassMask.find(
bc);
2507 if (bcClassPair != bcToClassMask.end()) {
2508 masks = bcClassPair->second;
2517 bcToClassMask.clear();
2520 auto bcFlags = fillBCFlags(recoData, bcsMap);
2521 bcFlagsCursor.reserve(bcFlags.size());
2522 for (
auto f : bcFlags) {
2529 cpvClustersCursor.reserve(cpvTrigRecs.size());
2530 for (
auto& cpvEvent : cpvTrigRecs) {
2531 uint64_t
bc = cpvEvent.getBCData().toLong();
2532 auto item = bcsMap.find(
bc);
2534 if (item != bcsMap.end()) {
2535 bcID = item->second;
2537 LOG(fatal) <<
"Error: could not find a corresponding BC ID for a CPV Trigger Record; BC = " <<
bc;
2539 for (
int iClu = cpvEvent.getFirstEntry(); iClu < cpvEvent.getFirstEntry() + cpvEvent.getNumberOfObjects(); iClu++) {
2540 auto&
clu = cpvClusters[iClu];
2541 clu.getLocalPosition(posX, posZ);
2542 cpvClustersCursor(bcID,
2543 truncateFloatFraction(posX, mCPVPos),
2544 truncateFloatFraction(posZ, mCPVPos),
2545 truncateFloatFraction(
clu.getEnergy(), mCPVAmpl),
2546 clu.getPackedClusterStatus());
2555 fillMCParticlesTable(*mcReader,
2556 mcParticlesCursor.
cursor,
2562 LOG(info) <<
"FILL MC took " << timer.RealTime() <<
" s";
2563 mcColToEvSrc.clear();
2569 fillMCTrackLabelsTable(mcTrackLabelCursor, mcMFTTrackLabelCursor, mcFwdTrackLabelCursor, primVer2TRefs.back(), primVerGIs, recoData);
2570 for (
auto iref = 0U; iref < primVer2TRefs.size() - 1; iref++) {
2571 auto& trackRef = primVer2TRefs[iref];
2572 fillMCTrackLabelsTable(mcTrackLabelCursor, mcMFTTrackLabelCursor, mcFwdTrackLabelCursor, trackRef, primVerGIs, recoData, iref);
2578 fillCaloTable(caloCellsCursor, caloCellsTRGTableCursor, mcCaloLabelsCursor, bcsMap, recoData);
2583 mGIDToTableID.clear();
2585 mGIDToTableFwdID.clear();
2587 mGIDToTableMFTID.clear();
2589 mVtxToTableCollID.clear();
2591 mV0ToTableID.clear();
2594 mIndexTableFwd.clear();
2596 mIndexTableMFT.clear();
2601 mGIDUsedBySVtx.clear();
2602 mGIDUsedByStr.clear();
2604 originCursor(tfNumber);
2607 TString dataType = mUseMC ?
"MC" :
"RAW";
2609 TString ROOTVersion = ROOT_RELEASE;
2610 mMetaDataKeys = {
"DataType",
"Run",
"O2Version",
"ROOTVersion",
"RecoPassName",
"AnchorProduction",
"AnchorPassName",
"LPMProductionTag",
"CreatedBy"};
2611 mMetaDataVals = {dataType,
"3", O2Version, ROOTVersion, mRecoPass, mAnchorProd, mAnchorPass, mLPMProdTag, mUser};
2612 add_additional_meta_info(mMetaDataKeys, mMetaDataVals);
2630 for (
const auto& rof : rofs) {
2631 int first = rof.getFirstEntry(), last =
first + rof.getNEntries();
2632 for (
int i =
first;
i < last;
i++) {
2633 mITSROFs.push_back(
count);
2643 for (
const auto& rof : rofs) {
2644 int first = rof.getFirstEntry(),
last =
first + rof.getNEntries();
2646 mMFTROFs.push_back(
count);
2653 mITSTPCTRDTriggers.clear();
2656 for (
const auto& trig : itstpctrigs) {
2657 int first = trig.getFirstTrack(),
last =
first + trig.getNumberOfTracks();
2659 mITSTPCTRDTriggers.push_back(
count);
2666 mTPCTRDTriggers.clear();
2669 for (
const auto& trig : tpctrigs) {
2670 int first = trig.getFirstTrack(),
last =
first + trig.getNumberOfTracks();
2672 mTPCTRDTriggers.push_back(
count);
2682 for (
const auto& rof : rofs) {
2685 mMCHROFs.push_back(
count);
2692AODProducerWorkflowDPL::TrackExtraInfo AODProducerWorkflowDPL::processBarrelTrack(
int collisionID, std::uint64_t collisionBC,
GIndex trackIndex,
2695 TrackExtraInfo extraInfoHolder;
2696 if (collisionID < 0) {
2699 bool needBCSlice = collisionID < 0;
2700 uint64_t bcOfTimeRef = collisionBC - mStartIR.
toLong();
2702 auto setTrackTime = [&](
double t,
double terr,
bool gaussian) {
2708 extraInfoHolder.trackTimeRes = terr;
2710 double error = this->mTimeMarginTrackTime + (gaussian ? extraInfoHolder.trackTimeRes * this->mNSigmaTimeTrack : extraInfoHolder.trackTimeRes);
2711 bcOfTimeRef = fillBCSlice(extraInfoHolder.bcSlice, t - error, t + error, bcsMap);
2714 extraInfoHolder.diffBCRef =
int(bcOfTimeRef);
2716 truncateFloatFraction(extraInfoHolder.trackTime, mTrackTime), truncateFloatFraction(extraInfoHolder.trackTimeRes, mTrackTimeError),
2719 auto contributorsGID =
data.getSingleDetectorRefs(trackIndex);
2720 const auto& trackPar =
data.getTrackParam(trackIndex);
2721 extraInfoHolder.flags |= trackPar.getPID() << 28;
2722 auto src = trackIndex.getSource();
2724 const auto& tofMatch =
data.getTOFMatch(trackIndex);
2725 extraInfoHolder.tofChi2 = tofMatch.getChi2();
2726 const auto& tofInt = tofMatch.getLTIntegralOut();
2727 float intLen = tofInt.getL();
2728 extraInfoHolder.length = intLen;
2735 extraInfoHolder.tofExpMom = mass * expBeta / std::sqrt(1.f - expBeta * expBeta);
2738 const double massZ = o2::track::PID::getMass2Z(trackPar.getPID());
2739 const double energy = sqrt((massZ * massZ) + (extraInfoHolder.tofExpMom * extraInfoHolder.tofExpMom));
2740 const double exp = extraInfoHolder.length * energy / (cSpeed * extraInfoHolder.tofExpMom);
2741 auto tofSignal = (tofMatch.getSignal() -
exp) * 1e-3;
2742 setTrackTime(tofSignal, 0.2,
true);
2746 extraInfoHolder.trdChi2 = trdOrig.getChi2();
2747 extraInfoHolder.trdSignal = trdOrig.getSignal();
2748 extraInfoHolder.trdPattern = getTRDPattern(trdOrig);
2749 if (extraInfoHolder.trackTimeRes < 0.) {
2751 const auto& trdTrig = (
src ==
GIndex::Source::TPCTRD) ?
data.getTPCTRDTriggers()[mTPCTRDTriggers[trackIndex.getIndex()]] :
data.getITSTPCTRDTriggers()[mITSTPCTRDTriggers[trackIndex.getIndex()]];
2753 setTrackTime(ttrig, 1.,
true);
2757 const auto& itsTrack =
data.getITSTrack(contributorsGID[
GIndex::ITS]);
2758 int nClusters = itsTrack.getNClusters();
2759 float chi2 = itsTrack.getChi2();
2761 extraInfoHolder.itsClusterSizes = itsTrack.getClusterSizes();
2763 const auto& rof =
data.getITSTracksROFRecords()[mITSROFs[trackIndex.getIndex()]];
2765 setTrackTime(t, mITSROFrameHalfLengthNS,
false);
2768 extraInfoHolder.itsClusterSizes =
data.getITSABRefs()[contributorsGID[
GIndex::Source::ITSAB].getIndex()].getClusterSizes();
2772 const auto& tpcClData = mTPCCounters[contributorsGID[
GIndex::TPC]];
2773 const auto& dEdx = tpcOrig.getdEdx().dEdxTotTPC > 0 ? tpcOrig.getdEdx() : tpcOrig.getdEdxAlt();
2774 if (tpcOrig.getdEdx().dEdxTotTPC == 0) {
2777 if (tpcOrig.hasASideClusters()) {
2780 if (tpcOrig.hasCSideClusters()) {
2783 extraInfoHolder.tpcInnerParam = tpcOrig.getP() / tpcOrig.getAbsCharge();
2784 extraInfoHolder.tpcChi2NCl = tpcOrig.getNClusters() ? tpcOrig.getChi2() / tpcOrig.getNClusters() : 0;
2785 extraInfoHolder.tpcSignal = dEdx.dEdxTotTPC;
2786 extraInfoHolder.tpcNClsFindable = tpcOrig.getNClusters();
2787 extraInfoHolder.tpcNClsFindableMinusFound = tpcOrig.getNClusters() - tpcClData.found;
2788 extraInfoHolder.tpcNClsFindableMinusCrossedRows = tpcOrig.getNClusters() - tpcClData.crossed;
2789 extraInfoHolder.tpcNClsShared = tpcClData.shared;
2790 uint32_t clsUsedForPID = dEdx.NHitsIROC + dEdx.NHitsOROC1 + dEdx.NHitsOROC2 + dEdx.NHitsOROC3;
2791 extraInfoHolder.tpcNClsFindableMinusPID = tpcOrig.getNClusters() - clsUsedForPID;
2794 double t = (tpcOrig.getTime0() + 0.5 * (tpcOrig.getDeltaTFwd() - tpcOrig.getDeltaTBwd())) * mTPCBinNS;
2795 double terr = 0.5 * (tpcOrig.getDeltaTFwd() + tpcOrig.getDeltaTBwd()) * mTPCBinNS;
2796 double err = mTimeMarginTrackTime + terr;
2797 bcOfTimeRef = fillBCSlice(extraInfoHolder.bcSlice, t - err, t + err, bcsMap);
2800 p.setDeltaTFwd(tpcOrig.getDeltaTFwd());
2801 p.setDeltaTBwd(tpcOrig.getDeltaTBwd());
2802 extraInfoHolder.trackTimeRes =
p.getTimeErr();
2804 extraInfoHolder.diffBCRef =
int(bcOfTimeRef);
2805 extraInfoHolder.isTPConly =
true;
2808 const auto& trITSTPC =
data.getTPCITSTrack(trackIndex);
2809 auto ts = trITSTPC.getTimeMUS();
2810 setTrackTime(ts.getTimeStamp() * 1.e3, ts.getTimeStampError() * 1.e3,
true);
2814 extrapolateToCalorimeters(extraInfoHolder,
data.getTrackParamOut(trackIndex));
2819 return extraInfoHolder;
2822AODProducerWorkflowDPL::TrackQA AODProducerWorkflowDPL::processBarrelTrackQA(
int collisionID, std::uint64_t collisionBC,
GIndex trackIndex,
2826 auto contributorsGID =
data.getTPCContributorGID(trackIndex);
2827 const auto& trackPar =
data.getTrackParam(trackIndex);
2828 if (contributorsGID.isIndexSet()) {
2830 const auto& tpcOrig =
data.getTPCTrack(contributorsGID);
2835 std::array<float, 2> dcaInfo{-999., -999.};
2836 if (prop->propagateToDCABxByBz({v.getX(), v.getY(), v.getZ()}, tpcTMP, 2.f, mMatType, &dcaInfo)) {
2837 trackQAHolder.tpcdcaR = 100. * dcaInfo[0] / sqrt(1. + trackPar.getQ2Pt() * trackPar.getQ2Pt());
2838 trackQAHolder.tpcdcaZ = 100. * dcaInfo[1] / sqrt(1. + trackPar.getQ2Pt() * trackPar.getQ2Pt());
2842 auto safeInt8Clamp = [](
auto value) -> int8_t {
2843 using ValType =
decltype(
value);
2844 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()))));
2846 auto safeUInt8Clamp = [](
auto value) -> uint8_t {
2847 using ValType =
decltype(
value);
2848 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()))));
2852 uint8_t clusterCounters[8] = {0};
2854 uint8_t sectorIndex, rowIndex;
2855 uint32_t clusterIndex;
2856 const auto& tpcClusRefs =
data.getTPCTracksClusterRefs();
2857 for (
int i = 0;
i < tpcOrig.getNClusterReferences();
i++) {
2858 o2::tpc::TrackTPC::getClusterReference(tpcClusRefs,
i, sectorIndex, rowIndex, clusterIndex, tpcOrig.getClusterRef());
2859 char indexTracklet = (rowIndex % 152) / 19;
2860 clusterCounters[indexTracklet]++;
2864 for (
int i = 0;
i < 8;
i++) {
2865 if (clusterCounters[
i] > 5) {
2866 byteMask |= (1 <<
i);
2869 trackQAHolder.tpcTime0 = tpcOrig.getTime0();
2870 trackQAHolder.tpcClusterByteMask = byteMask;
2871 const auto& dEdxInfoAlt = tpcOrig.getdEdxAlt();
2872 const float dEdxNorm = (dEdxInfoAlt.dEdxTotTPC > 0) ? 100. / dEdxInfoAlt.dEdxTotTPC : 0;
2873 trackQAHolder.tpcdEdxNorm = dEdxInfoAlt.dEdxTotTPC;
2874 trackQAHolder.tpcdEdxMax0R = safeUInt8Clamp(dEdxInfoAlt.dEdxMaxIROC * dEdxNorm);
2875 trackQAHolder.tpcdEdxMax1R = safeUInt8Clamp(dEdxInfoAlt.dEdxMaxOROC1 * dEdxNorm);
2876 trackQAHolder.tpcdEdxMax2R = safeUInt8Clamp(dEdxInfoAlt.dEdxMaxOROC2 * dEdxNorm);
2877 trackQAHolder.tpcdEdxMax3R = safeUInt8Clamp(dEdxInfoAlt.dEdxMaxOROC3 * dEdxNorm);
2879 trackQAHolder.tpcdEdxTot0R = safeUInt8Clamp(dEdxInfoAlt.dEdxTotIROC * dEdxNorm);
2880 trackQAHolder.tpcdEdxTot1R = safeUInt8Clamp(dEdxInfoAlt.dEdxTotOROC1 * dEdxNorm);
2881 trackQAHolder.tpcdEdxTot2R = safeUInt8Clamp(dEdxInfoAlt.dEdxTotOROC2 * dEdxNorm);
2882 trackQAHolder.tpcdEdxTot3R = safeUInt8Clamp(dEdxInfoAlt.dEdxTotOROC3 * dEdxNorm);
2885 auto contributorsGIDA =
data.getSingleDetectorRefs(trackIndex);
2887 const auto& tofMatch =
data.getTOFMatch(trackIndex);
2888 const float qpt = trackPar.getQ2Pt();
2890 trackQAHolder.dTofdX = safeInt8Clamp(tofMatch.getDXatTOF() / scaleTOF);
2891 trackQAHolder.dTofdZ = safeInt8Clamp(tofMatch.getDZatTOF() / scaleTOF);
2897 if (
auto itsContGID =
data.getITSContributorGID(trackIndex); itsContGID.isIndexSet() && itsContGID.getSource() !=
GIndex::ITSAB) {
2898 const auto& itsOrig =
data.getITSTrack(itsContGID);
2907 const float beta0 = std::sqrt(std::min(50.f / tpcOrig.getdEdx().dEdxMaxTPC, 1.f));
2908 const float qpt = gloCopy.getQ2Pt();
2909 const float x = qpt / beta0;
2911 auto scaleCont = [&
x](
int i) ->
float {
2914 auto scaleGlo = [&
x](
int i) ->
float {
2919 trackQAHolder.dRefContY = safeInt8Clamp((itsCopy.getY() - tpcCopy.getY()) * scaleCont(0));
2920 trackQAHolder.dRefContZ = safeInt8Clamp((itsCopy.getZ() - tpcCopy.getZ()) * scaleCont(1));
2921 trackQAHolder.dRefContSnp = safeInt8Clamp((itsCopy.getSnp() - tpcCopy.getSnp()) * scaleCont(2));
2922 trackQAHolder.dRefContTgl = safeInt8Clamp((itsCopy.getTgl() - tpcCopy.getTgl()) * scaleCont(3));
2923 trackQAHolder.dRefContQ2Pt = safeInt8Clamp((itsCopy.getQ2Pt() - tpcCopy.getQ2Pt()) * scaleCont(4));
2925 trackQAHolder.dRefGloY = safeInt8Clamp(((itsCopy.getY() + tpcCopy.getY()) * 0.5f - gloCopy.getY()) * scaleGlo(0));
2926 trackQAHolder.dRefGloZ = safeInt8Clamp(((itsCopy.getZ() + tpcCopy.getZ()) * 0.5f - gloCopy.getZ()) * scaleGlo(1));
2927 trackQAHolder.dRefGloSnp = safeInt8Clamp(((itsCopy.getSnp() + tpcCopy.getSnp()) * 0.5f - gloCopy.getSnp()) * scaleGlo(2));
2928 trackQAHolder.dRefGloTgl = safeInt8Clamp(((itsCopy.getTgl() + tpcCopy.getTgl()) * 0.5f - gloCopy.getTgl()) * scaleGlo(3));
2929 trackQAHolder.dRefGloQ2Pt = safeInt8Clamp(((itsCopy.getQ2Pt() + tpcCopy.getQ2Pt()) * 0.5f - gloCopy.getQ2Pt()) * scaleGlo(4));
2933 (*mStreamer) <<
"trackQA"
2934 <<
"trackITSOrig=" << itsOrig
2935 <<
"trackTPCOrig=" << tpcOrig
2936 <<
"trackITSTPCOrig=" << trackPar
2937 <<
"trackITSProp=" << itsCopy
2938 <<
"trackTPCProp=" << tpcCopy
2939 <<
"trackITSTPCProp=" << gloCopy
2942 <<
"scaleCont0=" << scaleCont(0)
2943 <<
"scaleCont1=" << scaleCont(1)
2944 <<
"scaleCont2=" << scaleCont(2)
2945 <<
"scaleCont3=" << scaleCont(3)
2946 <<
"scaleCont4=" << scaleCont(4)
2947 <<
"scaleGlo0=" << scaleGlo(0)
2948 <<
"scaleGlo1=" << scaleGlo(1)
2949 <<
"scaleGlo2=" << scaleGlo(2)
2950 <<
"scaleGlo3=" << scaleGlo(3)
2951 <<
"scaleGlo4=" << scaleGlo(4)
2952 <<
"trackQAHolder.tpcTime0=" << trackQAHolder.tpcTime0
2953 <<
"trackQAHolder.tpcdEdxNorm=" << trackQAHolder.tpcdEdxNorm
2954 <<
"trackQAHolder.tpcdcaR=" << trackQAHolder.tpcdcaR
2955 <<
"trackQAHolder.tpcdcaZ=" << trackQAHolder.tpcdcaZ
2956 <<
"trackQAHolder.tpcdcaClusterByteMask=" << trackQAHolder.tpcClusterByteMask
2957 <<
"trackQAHolder.tpcdEdxMax0R=" << trackQAHolder.tpcdEdxMax0R
2958 <<
"trackQAHolder.tpcdEdxMax1R=" << trackQAHolder.tpcdEdxMax1R
2959 <<
"trackQAHolder.tpcdEdxMax2R=" << trackQAHolder.tpcdEdxMax2R
2960 <<
"trackQAHolder.tpcdEdxMax3R=" << trackQAHolder.tpcdEdxMax3R
2961 <<
"trackQAHolder.tpcdEdxTot0R=" << trackQAHolder.tpcdEdxTot0R
2962 <<
"trackQAHolder.tpcdEdxTot1R=" << trackQAHolder.tpcdEdxTot1R
2963 <<
"trackQAHolder.tpcdEdxTot2R=" << trackQAHolder.tpcdEdxTot2R
2964 <<
"trackQAHolder.tpcdEdxTot3R=" << trackQAHolder.tpcdEdxTot3R
2965 <<
"trackQAHolder.dRefContY=" << trackQAHolder.dRefContY
2966 <<
"trackQAHolder.dRefContZ=" << trackQAHolder.dRefContZ
2967 <<
"trackQAHolder.dRefContSnp=" << trackQAHolder.dRefContSnp
2968 <<
"trackQAHolder.dRefContTgl=" << trackQAHolder.dRefContTgl
2969 <<
"trackQAHolder.dRefContQ2Pt=" << trackQAHolder.dRefContQ2Pt
2970 <<
"trackQAHolder.dRefGloY=" << trackQAHolder.dRefGloY
2971 <<
"trackQAHolder.dRefGloZ=" << trackQAHolder.dRefGloZ
2972 <<
"trackQAHolder.dRefGloSnp=" << trackQAHolder.dRefGloSnp
2973 <<
"trackQAHolder.dRefGloTgl=" << trackQAHolder.dRefGloTgl
2974 <<
"trackQAHolder.dRefGloQ2Pt=" << trackQAHolder.dRefGloQ2Pt
2975 <<
"trackQAHolder.dTofdX=" << trackQAHolder.dTofdX
2976 <<
"trackQAHolder.dTofdZ=" << trackQAHolder.dTofdZ
2977 <<
"scaleTOF=" << scaleTOF
2984 return trackQAHolder;
2992 dcaInfo.set(999.f, 999.f, 999.f, 999.f, 999.f);
2997void AODProducerWorkflowDPL::extrapolateToCalorimeters(TrackExtraInfo& extraInfoHolder,
const o2::track::TrackPar& track)
2999 constexpr float XEMCAL = 440.f, XPHOS = 460.f, XEMCAL2 = XEMCAL * XEMCAL;
3000 constexpr float ETAEMCAL = 0.75;
3001 constexpr float ZEMCALFastCheck = 460.;
3002 constexpr float ETADCALINNER = 0.22;
3003 constexpr float ETAPHOS = 0.13653194;
3004 constexpr float ETAPHOSMARGIN = 0.17946979;
3005 constexpr float ETADCALPHOSSWITCH = (ETADCALINNER + ETAPHOS) / 2;
3006 constexpr short SNONE = 0, SEMCAL = 0x1, SPHOS = 0x2;
3007 constexpr short SECTORTYPE[18] = {
3008 SNONE, SNONE, SNONE, SNONE,
3009 SEMCAL, SEMCAL, SEMCAL, SEMCAL, SEMCAL, SEMCAL,
3012 SPHOS | SEMCAL, SPHOS | SEMCAL, SPHOS | SEMCAL,
3023 (std::abs(outTr.getZAt(xtrg, 0)) > ZEMCALFastCheck) ||
3024 !prop->PropagateToXBxByBz(outTr, xtrg, 0.95, 10, o2::base::Propagator::MatCorrType::USEMatCorrLUT)) {
3025 LOGP(
debug,
"preliminary step: does not reach R={} {}", XEMCAL, outTr.asString());
3029 if ((outTr.getX() * outTr.getX() + outTr.getY() * outTr.getY() < XEMCAL2) &&
3030 (!outTr.rotateParam(outTr.getPhi()) ||
3032 !prop->PropagateToXBxByBz(outTr, xtrg, 0.95, 10, o2::base::Propagator::MatCorrType::USEMatCorrLUT))) {
3033 LOGP(
debug,
"does not reach R={} {}", XEMCAL, outTr.asString());
3039 auto propExactSector = [&outTr, §or, prop](
float xprop) ->
bool {
3042 auto outTrTmp = outTr;
3044 if ((std::abs(outTr.getZ()) > ZEMCALFastCheck) || !outTrTmp.rotateParam(
alpha) ||
3045 !prop->PropagateToXBxByBz(outTrTmp, xprop, 0.95, 10, o2::base::Propagator::MatCorrType::USEMatCorrLUT)) {
3046 LOGP(
debug,
"failed on rotation to {} (sector {}) or propagation to X={} {}",
alpha, sector, xprop, outTrTmp.asString());
3051 if (sectorTmp == sector) {
3059 LOGP(
debug,
"failed to rotate to sector, {}", outTr.asString());
3066 if (!propExactSector(XEMCAL) || SECTORTYPE[sector] == SNONE) {
3071 float r = std::sqrt(outTr.getX() * outTr.getX() + outTr.getY() * outTr.getY()), tg = std::atan2(
r, outTr.getZ());
3072 float eta = -std::log(std::tan(0.5f * tg)), etaAbs = std::abs(eta);
3073 if (etaAbs > ETAEMCAL) {
3074 LOGP(
debug,
"eta = {} is off at EMCAL radius", eta, outTr.asString());
3078 if ((SECTORTYPE[sector] & SPHOS) && etaAbs < ETADCALPHOSSWITCH) {
3079 if (!propExactSector(XPHOS)) {
3082 r = std::sqrt(outTr.getX() * outTr.getX() + outTr.getY() * outTr.getY());
3083 tg = std::atan2(
r, outTr.getZ());
3084 eta = -std::log(std::tan(0.5f * tg));
3085 }
else if (!(SECTORTYPE[sector] & SEMCAL)) {
3088 extraInfoHolder.trackPhiEMCAL = outTr.getPhiPos();
3089 extraInfoHolder.trackEtaEMCAL = eta;
3090 LOGP(
debug,
"eta = {} phi = {} sector {} for {}", extraInfoHolder.trackEtaEMCAL, extraInfoHolder.trackPhiEMCAL, sector, outTr.asString());
3094std::set<uint64_t> AODProducerWorkflowDPL::filterEMCALIncomplete(
const gsl::span<const o2::emcal::TriggerRecord> triggers)
3096 std::set<uint64_t> emcalIncompletes;
3097 for (
const auto& trg : triggers) {
3098 if (trg.getTriggerBits() & o2::emcal::triggerbits::Inc) {
3100 emcalIncompletes.insert(trg.getBCData().toLong());
3103 return emcalIncompletes;
3109 static bool initOnceDone =
false;
3110 if (!initOnceDone) {
3111 initOnceDone =
true;
3118 for (
auto i = 0U;
i < bs.size();
i++) {
3133 mTPCBinNS = elParam.ZbinWidth * 1.e3;
3136 mNSigmaTimeTrack = pvParams.nSigmaTimeTrack;
3137 mTimeMarginTrackTime = pvParams.timeMarginTrackTime * 1.e3;
3141 if (mEnableTRDextra) {
3163 LOG(info) <<
"ITS Alpide param updated";
3165 par.printKeyValues();
3169 LOG(info) <<
"MFT Alpide param updated";
3171 par.printKeyValues();
3182 mEMCALTrgClassMask = 0;
3183 for (
const auto& trgclass : ctpconfig.getCTPClasses()) {
3185 mEMCALTrgClassMask |= trgclass.classMask;
3188 LOG(info) <<
"Loaded EMCAL trigger class mask: " << std::bitset<64>(mEMCALTrgClassMask);
3192void AODProducerWorkflowDPL::addRefGlobalBCsForTOF(
const o2::dataformats::VtxTrackRef& trackRef,
const gsl::span<const GIndex>& GIndices,
3203 int nbitsFrac = 24 - (32 - o2::math_utils::popcount(mTrackTime));
3204 int nbitsLoss = std::max(0,
int(std::log2(TOFTimePrecPS)));
3205 assert(nbitsFrac > 1);
3206 std::uint64_t maxRangePS = std::uint64_t(0x1) << (nbitsFrac + nbitsLoss);
3208 LOG(info) <<
"Max gap of " << maxGapBC <<
" BCs to closest globalBC reference is needed for TOF tracks to provide precision of "
3209 << TOFTimePrecPS <<
" ps";
3212 if (!trackRef.getEntries()) {
3216 std::uint64_t maxBC = mStartIR.
toLong();
3217 const auto& tofClus =
data.getTOFClusters();
3224 for (
int ti =
start; ti <
end; ti++) {
3225 auto& trackIndex = GIndices[ti];
3226 const auto& tofMatch =
data.getTOFMatch(trackIndex);
3227 const auto& tofInt = tofMatch.getLTIntegralOut();
3228 float intLen = tofInt.getL();
3229 float tofExpMom = 0.;
3239 double massZ = o2::track::PID::getMass2Z(
data.getTrackParam(trackIndex).getPID());
3240 double energy = sqrt((massZ * massZ) + (tofExpMom * tofExpMom));
3241 double exp = intLen * energy / (cSpeed * tofExpMom);
3242 auto tofSignal = (tofMatch.getSignal() -
exp) * 1e-3;
3243 auto bc = relativeTime_to_GlobalBC(tofSignal);
3245 auto it = bcsMap.lower_bound(
bc);
3246 if (it == bcsMap.end() || it->first >
bc + maxGapBC) {
3247 bcsMap.emplace_hint(it,
bc, 1);
3256 if ((--bcsMap.end())->first <= maxBC) {
3257 bcsMap.emplace_hint(bcsMap.end(), maxBC + 1, 1);
3261 for (
auto& item : bcsMap) {
3267std::uint64_t AODProducerWorkflowDPL::fillBCSlice(
int (&slice)[2],
double tmin,
double tmax,
const std::map<uint64_t, int>& bcsMap)
const
3279 uint64_t bcMin = relativeTime_to_GlobalBC(tmin), bcMax = relativeTime_to_GlobalBC(tmax);
3302 auto upperindex =
p.first;
3303 while (upperindex < bcvector.size() && bcvector[upperindex] <= bcMax) {
3306 if (upperindex !=
p.first) {
3310 slice[1] = upperindex;
3312 auto bcOfTimeRef =
p.second - this->mStartIR.
toLong();
3313 LOG(
debug) <<
"BC slice t:" << tmin <<
" " << slice[0]
3314 <<
" t: " << tmax <<
" " << slice[1]
3315 <<
" bcref: " << bcOfTimeRef;
3321 std::vector<uint8_t>
flags(bcsMap.size());
3324 auto bcIt = bcsMap.begin();
3325 auto itsrofs =
data.getITSTracksROFRecords();
3328 for (
auto& rof : itsrofs) {
3329 if (!rof.getFlag(o2::itsmft::ROFRecord::VtxUPCMode)) {
3332 uint64_t globalBC0 = rof.getBCData().toLong() + bROF, globalBC1 = globalBC0 + lROF - 1;
3334 while (bcIt != bcsMap.end()) {
3335 if (bcIt->first < globalBC0) {
3339 if (bcIt->first > globalBC1) {
3351 LOGF(info,
"aod producer dpl total timing: Cpu: %.3e Real: %.3e s in %d slots",
3352 mTimer.CpuTime(), mTimer.RealTime(), mTimer.Counter() - 1);
3359 auto dataRequest = std::make_shared<DataRequest>();
3360 dataRequest->inputs.emplace_back(
"ctpconfig",
"CTP",
"CTPCONFIG", 0, Lifetime::Condition,
ccdbParamSpec(
"CTP/Config/Config", CTPConfigPerRun));
3362 dataRequest->requestTracks(
src, useMC);
3363 dataRequest->requestPrimaryVertices(useMC);
3365 dataRequest->requestCTPDigits(useMC);
3368 dataRequest->requestSecondaryVertices(useMC);
3370 if (enableStrangenessTracking) {
3371 dataRequest->requestStrangeTracks(useMC);
3372 LOGF(info,
"requestStrangeTracks Finish");
3381 dataRequest->requestTOFClusters(useMC);
3384 dataRequest->requestPHOSCells(useMC);
3387 dataRequest->requestTRDTracklets(
false);
3390 dataRequest->requestEMCALCells(useMC);
3393 dataRequest->requestCPVClusters(useMC);
3396 auto ggRequest = std::make_shared<o2::base::GRPGeomRequest>(
true,
3402 dataRequest->inputs,
3405 dataRequest->inputs.emplace_back(
"meanvtx",
"GLO",
"MEANVERTEX", 0, Lifetime::Condition,
ccdbParamSpec(
"GLO/Calib/MeanVertex", {}, 1));
3410 std::vector<OutputSpec> outputs{
3449 if (enableTRDextra) {
3451 dataRequest->inputs.emplace_back(
"trdlocalgainfactors",
"TRD",
"LOCALGAINFACTORS", 0, Lifetime::Condition,
ccdbParamSpec(
"TRD/Calib/LocalGainFactor"));
3452 dataRequest->inputs.emplace_back(
"trdnoisemap",
"TRD",
"NOISEMAP", 0, Lifetime::Condition,
ccdbParamSpec(
"TRD/Calib/NoiseMapMCM"));
3453 dataRequest->inputs.emplace_back(
"trdgaincalib",
"TRD",
"CALGAIN", 0, Lifetime::Condition,
ccdbParamSpec(
"TRD/Calib/CalGain"));
3457 outputs.insert(outputs.end(),
3458 {OutputForTable<McCollisions>::spec(),
3459 OutputForTable<HepMCXSections>::spec(),
3460 OutputForTable<HepMCPdfInfos>::spec(),
3461 OutputForTable<HepMCHeavyIons>::spec(),
3462 OutputForTable<McMFTTrackLabels>::spec(),
3463 OutputForTable<McFwdTrackLabels>::spec(),
3464 OutputForTable<StoredMcParticles_001>::spec(),
3465 OutputForTable<McTrackLabels>::spec(),
3466 OutputForTable<McCaloLabels_001>::spec(),
3471 {OutputLabel{
"McCollisionLabels"},
"AOD",
"MCCOLLISIONLABEL", 0, Lifetime::Timeframe}});
3475 "aod-producer-workflow",
3478 AlgorithmSpec{adaptFromTask<AODProducerWorkflowDPL>(
src, dataRequest, ggRequest, enableSV, useMC, enableFITextra, enableTRDextra)},
3480 ConfigParamSpec{
"run-number", VariantType::Int64, -1L, {
"The run-number. If left default we try to get it from DPL header."}},
3481 ConfigParamSpec{
"aod-timeframe-id", VariantType::Int64, -1L, {
"Set timeframe number"}},
3482 ConfigParamSpec{
"fill-calo-cells", VariantType::Int, 1, {
"Fill calo cells into cell table"}},
3483 ConfigParamSpec{
"enable-truncation", VariantType::Int, 1, {
"Truncation parameter: 1 -- on, != 1 -- off"}},
3484 ConfigParamSpec{
"lpmp-prod-tag", VariantType::String,
"", {
"LPMProductionTag"}},
3485 ConfigParamSpec{
"anchor-pass", VariantType::String,
"", {
"AnchorPassName"}},
3486 ConfigParamSpec{
"anchor-prod", VariantType::String,
"", {
"AnchorProduction"}},
3487 ConfigParamSpec{
"reco-pass", VariantType::String,
"", {
"RecoPassName"}},
3488 ConfigParamSpec{
"created-by", VariantType::String,
"", {
"Who created this AO2D"}},
3489 ConfigParamSpec{
"nthreads", VariantType::Int, std::max(1,
int(std::thread::hardware_concurrency() / 2)), {
"Number of threads"}},
3490 ConfigParamSpec{
"reco-mctracks-only", VariantType::Int, 0, {
"Store only reconstructed MC tracks and their mothers/daughters. 0 -- off, != 0 -- on"}},
3491 ConfigParamSpec{
"ctpreadout-create", VariantType::Int, 0, {
"Create CTP digits from detector readout and CTP inputs. !=1 -- off, 1 -- on"}},
3492 ConfigParamSpec{
"emc-select-leading", VariantType::Bool,
false, {
"Flag to select if only the leading contributing particle for an EMCal cell should be stored"}},
3493 ConfigParamSpec{
"propagate-tracks", VariantType::Bool,
false, {
"Propagate tracks (not used for secondary vertices) to IP"}},
3494 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)"}},
3495 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)"}},
3496 ConfigParamSpec{
"propagate-muons", VariantType::Bool,
false, {
"Propagate muons to IP"}},
3497 ConfigParamSpec{
"thin-tracks", VariantType::Bool,
false, {
"Produce thinned track tables"}},
3498 ConfigParamSpec{
"trackqc-keepglobaltracks", VariantType::Bool,
false, {
"Always keep TrackQA for global tracks"}},
3499 ConfigParamSpec{
"trackqc-retainonlydedx", VariantType::Bool,
false, {
"Keep only dEdx information, zero out everything else"}},
3500 ConfigParamSpec{
"trackqc-fraction", VariantType::Float, float(0.1), {
"Fraction of tracks to QC"}},
3501 ConfigParamSpec{
"trackqc-NTrCut", VariantType::Int64, 4L, {
"Minimal length of the track - in amount of tracklets"}},
3502 ConfigParamSpec{
"trackqc-tpc-dca", VariantType::Float, 3.f, {
"Keep TPC standalone track with this DCAxy to the PV"}},
3503 ConfigParamSpec{
"trackqc-tpc-cls", VariantType::Int, 80, {
"Keep TPC standalone track with this #clusters"}},
3504 ConfigParamSpec{
"trackqc-tpc-pt", VariantType::Float, 0.2f, {
"Keep TPC standalone track with this pt"}},
3505 ConfigParamSpec{
"with-streamers", VariantType::String,
"", {
"Bit-mask to steer writing of intermediate streamer files"}},
3506 ConfigParamSpec{
"seed", VariantType::Int, 0, {
"Set seed for random generator used for sampling (0 (default) means using a random_device)"}},
3507 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