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<MCColInfo>& mcColToEvSrc)
1091 for (
auto& p : mcColToEvSrc) {
1092 NSources = std::max(p.sourceID, NSources);
1093 NEvents = std::max(p.eventID, 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.eventID;
1170 int source = colInfo.sourceID;
1171 int mcColId = colInfo.colIndex;
1173 LOG(
debug) <<
"Event=" <<
event <<
" source=" <<
source <<
" collision=" << mcColId;
1192template <
typename MCTrackLabelCursorType,
typename MCMFTTrackLabelCursorType,
typename MCFwdTrackLabelCursorType>
1193void AODProducerWorkflowDPL::fillMCTrackLabelsTable(MCTrackLabelCursorType& mcTrackLabelCursor,
1194 MCMFTTrackLabelCursorType& mcMFTTrackLabelCursor,
1195 MCFwdTrackLabelCursorType& mcFwdTrackLabelCursor,
1197 const gsl::span<const GIndex>& primVerGIs,
1210 mcMFTTrackLabelCursor.reserve(
end -
start + mcMFTTrackLabelCursor.lastIndex());
1211 mcFwdTrackLabelCursor.reserve(
end -
start + mcFwdTrackLabelCursor.lastIndex());
1212 mcTrackLabelCursor.reserve(
end -
start + mcTrackLabelCursor.lastIndex());
1213 for (
int ti =
start; ti <
end; ti++) {
1214 const auto trackIndex = primVerGIs[ti];
1217 auto needToStore = [trackIndex](std::unordered_map<GIndex, int>& mp) {
1218 auto entry = mp.find(trackIndex);
1219 if (
entry == mp.end() ||
entry->second == -1) {
1226 if (GIndex::includesSource(
src, mInputSources)) {
1227 auto mcTruth =
data.getTrackMCLabel(trackIndex);
1228 MCLabels labelHolder{};
1233 if (mcTruth.isValid()) {
1234 labelHolder.labelID = (mToStore[mcTruth.getSourceID()][mcTruth.getEventID()])[mcTruth.getTrackID()];
1236 if (mcTruth.isFake()) {
1237 labelHolder.fwdLabelMask |= (0x1 << 7);
1239 if (mcTruth.isNoise()) {
1240 labelHolder.fwdLabelMask |= (0x1 << 6);
1243 mcMFTTrackLabelCursor(labelHolder.labelID,
1244 labelHolder.fwdLabelMask);
1246 mcFwdTrackLabelCursor(labelHolder.labelID,
1247 labelHolder.fwdLabelMask);
1250 if (!needToStore(mGIDToTableID)) {
1253 if (mcTruth.isValid()) {
1254 labelHolder.labelID = (mToStore[mcTruth.getSourceID()][mcTruth.getEventID()])[mcTruth.getTrackID()];
1255 if (mcTruth.isFake()) {
1256 labelHolder.labelMask |= (0x1 << 15);
1259 auto contributorsGID =
data.getSingleDetectorRefs(trackIndex);
1262 labelHolder.labelMask |= (0x1 << 13);
1267 auto itsGID =
data.getITSContributorGID(trackIndex);
1268 auto itsSource = itsGID.getSource();
1270 auto& itsTrack =
data.getITSTrack(itsGID);
1271 for (
unsigned int iL = 0; iL < 7; ++iL) {
1272 if (itsTrack.isFakeOnLayer(iL)) {
1273 labelHolder.labelMask |= (0x1 << iL);
1277 labelHolder.labelMask |= (
data.getTrackMCLabel(itsGID).isFake() << 12);
1281 }
else if (mcTruth.isNoise()) {
1282 labelHolder.labelMask |= (0x1 << 14);
1284 mcTrackLabelCursor(labelHolder.labelID, labelHolder.labelMask);
1291 auto sTrackLabels =
data.getStrangeTracksMCLabels();
1293 if (!(vertexId < 0 || vertexId >= mVertexStrLUT.size() - 1)) {
1294 mcTrackLabelCursor.reserve(mVertexStrLUT[vertexId + 1] + mcTrackLabelCursor.lastIndex());
1295 for (
int iS{mVertexStrLUT[vertexId]}; iS < mVertexStrLUT[vertexId + 1]; ++iS) {
1296 auto& collStrTrk = mCollisionStrTrk[iS];
1297 auto&
label = sTrackLabels[collStrTrk.second];
1298 MCLabels labelHolder;
1299 labelHolder.labelID =
label.isValid() ? (mToStore[
label.getSourceID()][
label.getEventID()])[
label.getTrackID()] : -1;
1300 labelHolder.labelMask = (
label.isFake() << 15) | (
label.isNoise() << 14);
1301 mcTrackLabelCursor(labelHolder.labelID, labelHolder.labelMask);
1306template <
typename V0CursorType,
typename CascadeCursorType,
typename Decay3BodyCursorType>
1307void AODProducerWorkflowDPL::fillSecondaryVertices(
const o2::globaltracking::RecoContainer& recoData, V0CursorType& v0Cursor, CascadeCursorType& cascadeCursor, Decay3BodyCursorType& decay3BodyCursor)
1314 v0Cursor.reserve(v0s.size());
1316 for (
size_t iv0 = 0; iv0 < v0s.size(); iv0++) {
1317 const auto&
v0 = v0s[iv0];
1318 auto trPosID =
v0.getProngID(0);
1319 auto trNegID =
v0.getProngID(1);
1320 uint8_t v0flags =
v0.getBits();
1321 int posTableIdx = -1, negTableIdx = -1, collID = -1;
1322 auto item = mGIDToTableID.find(trPosID);
1323 if (item != mGIDToTableID.end()) {
1324 posTableIdx = item->second;
1326 LOG(warn) <<
"Could not find a positive track index for prong ID " << trPosID;
1328 item = mGIDToTableID.find(trNegID);
1329 if (item != mGIDToTableID.end()) {
1330 negTableIdx = item->second;
1332 LOG(warn) <<
"Could not find a negative track index for prong ID " << trNegID;
1334 auto itemV = mVtxToTableCollID.find(
v0.getVertexID());
1335 if (itemV == mVtxToTableCollID.end()) {
1336 LOG(warn) <<
"Could not find V0 collisionID for the vertex ID " <<
v0.getVertexID();
1338 collID = itemV->second;
1340 if (posTableIdx != -1 and negTableIdx != -1 and collID != -1) {
1341 v0Cursor(collID, posTableIdx, negTableIdx, v0flags);
1342 mV0ToTableID[
int(iv0)] = mTableV0ID++;
1347 cascadeCursor.reserve(cascades.size());
1348 for (
auto& cascade : cascades) {
1349 auto itemV0 = mV0ToTableID.find(cascade.getV0ID());
1350 if (itemV0 == mV0ToTableID.end()) {
1353 int v0tableID = itemV0->second, bachTableIdx = -1, collID = -1;
1354 auto bachelorID = cascade.getBachelorID();
1355 auto item = mGIDToTableID.find(bachelorID);
1356 if (item != mGIDToTableID.end()) {
1357 bachTableIdx = item->second;
1359 LOG(warn) <<
"Could not find a bachelor track index";
1362 auto itemV = mVtxToTableCollID.find(cascade.getVertexID());
1363 if (itemV != mVtxToTableCollID.end()) {
1364 collID = itemV->second;
1366 LOG(warn) <<
"Could not find cascade collisionID for the vertex ID " << cascade.getVertexID();
1369 cascadeCursor(collID, v0tableID, bachTableIdx);
1373 decay3BodyCursor.reserve(decays3Body.size());
1374 for (
size_t i3Body = 0; i3Body < decays3Body.size(); i3Body++) {
1375 const auto& decay3Body = decays3Body[i3Body];
1377 decay3Body.getProngID(0),
1378 decay3Body.getProngID(1),
1379 decay3Body.getProngID(2)};
1380 int tableIdx[3]{-1, -1, -1}, collID = -1;
1381 bool missing{
false};
1382 for (
int i{0};
i < 3; ++
i) {
1383 auto item = mGIDToTableID.find(trIDs[
i]);
1384 if (item != mGIDToTableID.end()) {
1385 tableIdx[
i] = item->second;
1387 LOG(warn) << fmt::format(
"Could not find a track index for prong ID {}", (
int)trIDs[
i]);
1391 auto itemV = mVtxToTableCollID.find(decay3Body.getVertexID());
1392 if (itemV == mVtxToTableCollID.end()) {
1393 LOG(warn) <<
"Could not find 3 body collisionID for the vertex ID " << decay3Body.getVertexID();
1396 collID = itemV->second;
1401 decay3BodyCursor(collID, tableIdx[0], tableIdx[1], tableIdx[2]);
1405template <
typename FwdTrkClsCursorType>
1412 int mchTrackID = -1;
1414 mchTrackID = trackID.getIndex();
1416 auto mchmidMatch = mchmidMatches[trackID.getIndex()];
1417 mchTrackID = mchmidMatch.getMCHRef().getIndex();
1420 if (mchTrackID > -1 && mchTrackID < mchTracks.size()) {
1421 const auto& mchTrack = mchTracks[mchTrackID];
1422 fwdTrkClsCursor.reserve(mchTrack.getNClusters() + fwdTrkClsCursor.lastIndex());
1423 int first = mchTrack.getFirstClusterIdx();
1424 int last = mchTrack.getLastClusterIdx();
1425 for (
int i =
first;
i <= last;
i++) {
1426 const auto& cluster = mchClusters[
i];
1427 fwdTrkClsCursor(fwdTrackId,
1428 truncateFloatFraction(cluster.x, mMuonCl),
1429 truncateFloatFraction(cluster.y, mMuonCl),
1430 truncateFloatFraction(cluster.z, mMuonCl),
1431 (((cluster.ey < 5.) & 0x1) << 12) | (((cluster.ex < 5.) & 0x1) << 11) | cluster.getDEId());
1436template <
typename HMPCursorType>
1441 hmpCursor.reserve(hmpMatches.size());
1444 for (
size_t iHmp = 0; iHmp < hmpMatches.size(); iHmp++) {
1446 const auto&
match = hmpMatches[iHmp];
1448 float xTrk, yTrk, theta,
phi;
1452 match.getHMPIDtrk(xTrk, yTrk, theta,
phi);
1455 auto photChargeVec =
match.getPhotCharge();
1457 float photChargeVec2[10];
1459 for (Int_t
i = 0;
i < 10;
i++) {
1460 photChargeVec2[
i] = photChargeVec[
i];
1462 auto tref = mGIDToTableID.find(
match.getTrackRef());
1463 if (tref != mGIDToTableID.end()) {
1464 hmpCursor(tref->second,
match.getHMPsignal(), xTrk, yTrk, xMip, yMip, nph,
charge,
match.getIdxHMPClus(),
match.getHmpMom(), photChargeVec2);
1466 LOG(error) <<
"Could not find AOD track table entry for HMP-matched track " <<
match.getTrackRef().asString();
1478 mCollisionStrTrk.clear();
1480 mVertexStrLUT.clear();
1482 for (
auto& sTrk : recoData.getStrangeTracks()) {
1486 vtxId = v0s[sTrk.mDecayRef].getVertexID();
1488 vtxId = cascades[sTrk.mDecayRef].getVertexID();
1490 vtxId = decays3Body[sTrk.mDecayRef].getVertexID();
1492 mCollisionStrTrk.emplace_back(vtxId, sTrkID++);
1493 mVertexStrLUT[vtxId]++;
1495 std::exclusive_scan(mVertexStrLUT.begin(), mVertexStrLUT.end(), mVertexStrLUT.begin(), 0);
1498 std::sort(mCollisionStrTrk.begin(), mCollisionStrTrk.end(), [](
const auto&
a,
const auto&
b) { return a.first < b.first; });
1499 mStrTrkIndices.clear();
1500 mStrTrkIndices.resize(mCollisionStrTrk.size(), -1);
1503template <
typename V0C,
typename CC,
typename D3BC>
1506 int itsTableIdx = -1;
1512 for (
const auto& sTrk : recoData.getStrangeTracks()) {
1522 v0Curs.reserve(nV0);
1523 cascCurs.reserve(nCasc);
1524 d3BodyCurs.reserve(nD3Body);
1526 for (
const auto& sTrk : recoData.getStrangeTracks()) {
1528 auto item = mGIDToTableID.find(ITSIndex);
1529 if (item != mGIDToTableID.end()) {
1530 itsTableIdx = item->second;
1532 LOG(warn) <<
"Could not find a ITS strange track index " << ITSIndex;
1536 v0Curs(mStrTrkIndices[sTrkID++],
1546 sTrk.getAverageClusterSize());
1548 cascCurs(mStrTrkIndices[sTrkID++],
1558 sTrk.getAverageClusterSize());
1560 d3BodyCurs(mStrTrkIndices[sTrkID++],
1570 sTrk.getAverageClusterSize());
1577 const auto& tpcTracks =
data.getTPCTracks();
1578 const auto& tpcClusRefs =
data.getTPCTracksClusterRefs();
1579 const auto& tpcClusShMap =
data.clusterShMapTPC;
1580 const auto& tpcClusAcc =
data.getTPCClusters();
1581 constexpr int maxRows = 152;
1582 constexpr int neighbour = 2;
1583 int ntr = tpcTracks.size();
1584 mTPCCounters.clear();
1585 mTPCCounters.resize(ntr);
1587 int ngroup = std::min(50, std::max(1, ntr / mNThreads));
1588#pragma omp parallel for schedule(dynamic, ngroup) num_threads(mNThreads)
1590 for (
int itr = 0; itr < ntr; itr++) {
1591 std::array<bool, maxRows> clMap{}, shMap{};
1592 uint8_t sectorIndex, rowIndex;
1593 uint32_t clusterIndex;
1594 auto&
counters = mTPCCounters[itr];
1595 const auto& track = tpcTracks[itr];
1596 for (
int i = 0;
i < track.getNClusterReferences();
i++) {
1597 o2::tpc::TrackTPC::getClusterReference(tpcClusRefs,
i, sectorIndex, rowIndex, clusterIndex, track.getClusterRef());
1598 unsigned int absoluteIndex = tpcClusAcc.clusterOffset[sectorIndex][rowIndex] + clusterIndex;
1599 clMap[rowIndex] =
true;
1601 if (!shMap[rowIndex]) {
1604 shMap[rowIndex] =
true;
1608 for (
int i = 0;
i < maxRows;
i++) {
1613 }
else if ((
i - last) <= neighbour) {
1616 int lim = std::min(
i + 1 + neighbour, maxRows);
1617 for (
int j =
i + 1;
j < lim;
j++) {
1632 if (track.getTrackletIndex(il) != -1) {
1636 if (track.getHasNeighbor()) {
1639 if (track.getHasPadrowCrossing()) {
1645template <
typename TCaloHandler,
typename TCaloCursor,
typename TCaloTRGCursor,
typename TMCCaloLabelCursor>
1646void AODProducerWorkflowDPL::addToCaloTable(TCaloHandler& caloHandler, TCaloCursor& caloCellCursor, TCaloTRGCursor& caloTRGCursor,
1647 TMCCaloLabelCursor& mcCaloCellLabelCursor,
int eventID,
int bcID, int8_t caloType)
1649 auto inputEvent = caloHandler.buildEvent(eventID);
1650 auto cellsInEvent = inputEvent.mCells;
1651 auto cellMClabels = inputEvent.mMCCellLabels;
1652 caloCellCursor.reserve(cellsInEvent.size() + caloCellCursor.lastIndex());
1653 caloTRGCursor.reserve(cellsInEvent.size() + caloTRGCursor.lastIndex());
1655 mcCaloCellLabelCursor.reserve(cellsInEvent.size() + mcCaloCellLabelCursor.lastIndex());
1657 for (
auto iCell = 0U; iCell < cellsInEvent.size(); iCell++) {
1658 caloCellCursor(bcID,
1662 cellsInEvent[iCell].
getType(),
1676 std::vector<int32_t> particleIds;
1677 std::vector<float> amplitudeFraction;
1678 if (!mEMCselectLeading) {
1679 particleIds.reserve(cellMClabels.size());
1680 amplitudeFraction.reserve(cellMClabels.size());
1682 float tmpMaxAmplitude = 0;
1683 int32_t tmpindex = 0;
1684 for (
auto& mclabel : cellMClabels[iCell]) {
1686 if (mclabel.isValid()) {
1687 if (mEMCselectLeading) {
1688 if (mclabel.getAmplitudeFraction() > tmpMaxAmplitude) {
1690 if (mToStore.at(mclabel.getSourceID()).at(mclabel.getEventID()).find(mclabel.getTrackID()) !=
1691 mToStore.at(mclabel.getSourceID()).at(mclabel.getEventID()).end()) {
1692 tmpMaxAmplitude = mclabel.getAmplitudeFraction();
1693 tmpindex = (mToStore.at(mclabel.getSourceID()).at(mclabel.getEventID())).at(mclabel.getTrackID());
1697 auto trackStore = mToStore.at(mclabel.getSourceID()).at(mclabel.getEventID());
1698 auto iter = trackStore.find(mclabel.getTrackID());
1699 if (iter != trackStore.end()) {
1700 amplitudeFraction.emplace_back(mclabel.getAmplitudeFraction());
1701 particleIds.emplace_back(iter->second);
1703 particleIds.emplace_back(-1);
1704 amplitudeFraction.emplace_back(0.f);
1705 LOG(warn) <<
"CaloTable: Could not find track for mclabel (" << mclabel.getSourceID() <<
"," << mclabel.getEventID() <<
"," << mclabel.getTrackID() <<
") in the AOD MC store";
1706 if (mMCKineReader) {
1707 auto mctrack = mMCKineReader->
getTrack(mclabel);
1710 LOG(warn) <<
" ... this track is of PDG " << mctrack->GetPdgCode() <<
" produced by " << mctrack->getProdProcessAsString() <<
" at (" <<
vec.X() <<
"," <<
vec.Y() <<
"," <<
vec.Z() <<
")";
1716 if (mEMCselectLeading) {
1717 amplitudeFraction.emplace_back(tmpMaxAmplitude);
1718 particleIds.emplace_back(tmpindex);
1720 if (particleIds.size() == 0) {
1721 particleIds.emplace_back(-1);
1722 amplitudeFraction.emplace_back(0.f);
1724 mcCaloCellLabelCursor(particleIds,
1731template <
typename TCaloCursor,
typename TCaloTRGCursor,
typename TMCCaloLabelCursor>
1732void AODProducerWorkflowDPL::fillCaloTable(TCaloCursor& caloCellCursor, TCaloTRGCursor& caloTRGCursor,
1733 TMCCaloLabelCursor& mcCaloCellLabelCursor,
const std::map<uint64_t, int>& bcsMap,
1737 auto caloEMCCells =
data.getEMCALCells();
1738 auto caloEMCCellsTRGR =
data.getEMCALTriggers();
1739 auto mcCaloEMCCellLabels =
data.getEMCALCellsMCLabels();
1741 auto caloPHOSCells =
data.getPHOSCells();
1742 auto caloPHOSCellsTRGR =
data.getPHOSTriggers();
1743 auto mcCaloPHOSCellLabels =
data.getPHOSCellsMCLabels();
1747 caloPHOSCellsTRGR = {};
1748 mcCaloPHOSCellLabels = {};
1753 caloEMCCellsTRGR = {};
1754 mcCaloEMCCellLabels = {};
1761 emcEventHandler.
reset();
1762 emcEventHandler.
setCellData(caloEMCCells, caloEMCCellsTRGR);
1765 phsEventHandler.
reset();
1766 phsEventHandler.
setCellData(caloPHOSCells, caloPHOSCellsTRGR);
1772 std::vector<std::tuple<uint64_t, int8_t, int>> caloEvents;
1774 caloEvents.reserve(emcNEvents + phsNEvents);
1776 for (
int iev = 0; iev < emcNEvents; ++iev) {
1778 caloEvents.emplace_back(std::make_tuple(
bc, 1, iev));
1781 for (
int iev = 0; iev < phsNEvents; ++iev) {
1783 caloEvents.emplace_back(std::make_tuple(
bc, 0, iev));
1786 std::sort(caloEvents.begin(), caloEvents.end(),
1787 [](
const auto&
left,
const auto&
right) { return std::get<0>(left) < std::get<0>(right); });
1790 for (
int i = 0;
i < emcNEvents + phsNEvents; ++
i) {
1791 uint64_t globalBC = std::get<0>(caloEvents[
i]);
1792 int8_t caloType = std::get<1>(caloEvents[
i]);
1793 int eventID = std::get<2>(caloEvents[
i]);
1794 auto item = bcsMap.find(globalBC);
1796 if (item != bcsMap.end()) {
1797 bcID = item->second;
1799 LOG(warn) <<
"Error: could not find a corresponding BC ID for a calo point; globalBC = " << globalBC <<
", caloType = " << (
int)caloType;
1801 if (caloType == 0) {
1802 addToCaloTable(phsEventHandler, caloCellCursor, caloTRGCursor, mcCaloCellLabelCursor, eventID, bcID, caloType);
1804 if (caloType == 1) {
1805 addToCaloTable(emcEventHandler, caloCellCursor, caloTRGCursor, mcCaloCellLabelCursor, eventID, bcID, caloType);
1816 mLPMProdTag = ic.
options().
get<std::string>(
"lpmp-prod-tag");
1817 mAnchorPass = ic.
options().
get<std::string>(
"anchor-pass");
1818 mAnchorProd = ic.
options().
get<std::string>(
"anchor-prod");
1819 mUser = ic.
options().
get<std::string>(
"created-by");
1820 mRecoPass = ic.
options().
get<std::string>(
"reco-pass");
1821 mAODParent = ic.
options().
get<std::string>(
"aod-parent");
1822 mTFNumber = ic.
options().
get<int64_t>(
"aod-timeframe-id");
1823 mRecoOnly = ic.
options().
get<
int>(
"reco-mctracks-only");
1824 mTruncate = ic.
options().
get<
int>(
"enable-truncation");
1825 mRunNumber = ic.
options().
get<
int>(
"run-number");
1826 mCTPReadout = ic.
options().
get<
int>(
"ctpreadout-create");
1827 mNThreads = std::max(1, ic.
options().
get<
int>(
"nthreads"));
1828 mEMCselectLeading = ic.
options().
get<
bool>(
"emc-select-leading");
1829 mThinTracks = ic.
options().
get<
bool>(
"thin-tracks");
1830 mPropTracks = ic.
options().
get<
bool>(
"propagate-tracks");
1831 mMaxPropXiu = ic.
options().
get<
float>(
"propagate-tracks-max-xiu");
1832 mPropMuons = ic.
options().
get<
bool>(
"propagate-muons");
1833 if (
auto s = ic.
options().
get<std::string>(
"with-streamers"); !
s.empty()) {
1834 mStreamerFlags.
set(
s);
1835 if (mStreamerFlags) {
1836 LOGP(info,
"Writing streamer data with mask:");
1837 LOG(info) << mStreamerFlags;
1839 LOGP(warn,
"Specified non-default empty streamer mask!");
1842 mTrackQCKeepGlobalTracks = ic.
options().
get<
bool>(
"trackqc-keepglobaltracks");
1843 mTrackQCRetainOnlydEdx = ic.
options().
get<
bool>(
"trackqc-retainonlydedx");
1844 mTrackQCFraction = ic.
options().
get<
float>(
"trackqc-fraction");
1845 mTrackQCNTrCut = ic.
options().
get<int64_t>(
"trackqc-NTrCut");
1846 mTrackQCDCAxy = ic.
options().
get<
float>(
"trackqc-tpc-dca");
1847 mTrackQCPt = ic.
options().
get<
float>(
"trackqc-tpc-pt");
1848 mTrackQCNCls = ic.
options().
get<
int>(
"trackqc-tpc-cls");
1849 if (
auto seed = ic.
options().
get<
int>(
"seed"); seed == 0) {
1850 LOGP(info,
"Using random device for seeding");
1851 std::random_device
rd;
1852 std::array<int, std::mt19937::state_size> seed_data{};
1853 std::generate(std::begin(seed_data), std::end(seed_data), std::ref(
rd));
1854 std::seed_seq seq(std::begin(seed_data), std::end(seed_data));
1855 mGenerator = std::mt19937(seq);
1857 LOGP(info,
"Using seed {} for sampling", seed);
1858 mGenerator.seed(seed);
1861 LOGP(info,
"Multi-threaded parts will run with {} OpenMP threads", mNThreads);
1864 LOG(info) <<
"OpenMP is disabled";
1866 if (mTFNumber == -1L) {
1867 LOG(info) <<
"TFNumber will be obtained from CCDB";
1869 if (mRunNumber == -1L) {
1870 LOG(info) <<
"The Run number will be obtained from DPL headers";
1873 mUseSigFiltMC = ic.
options().
get<
bool>(
"mc-signal-filt");
1876 if (mTruncate != 1) {
1877 LOG(info) <<
"Truncation is not used!";
1878 mCollisionPosition = 0xFFFFFFFF;
1879 mCollisionPositionCov = 0xFFFFFFFF;
1880 mTrackX = 0xFFFFFFFF;
1881 mTrackAlpha = 0xFFFFFFFF;
1882 mTrackSnp = 0xFFFFFFFF;
1883 mTrackTgl = 0xFFFFFFFF;
1884 mTrack1Pt = 0xFFFFFFFF;
1885 mTrackChi2 = 0xFFFFFFFF;
1886 mTrackCovDiag = 0xFFFFFFFF;
1887 mTrackCovOffDiag = 0xFFFFFFFF;
1888 mTrackSignal = 0xFFFFFFFF;
1889 mTrackTime = 0xFFFFFFFF;
1890 mTPCTime0 = 0xFFFFFFFF;
1891 mTrackTimeError = 0xFFFFFFFF;
1892 mTrackPosEMCAL = 0xFFFFFFFF;
1893 mTracklets = 0xFFFFFFFF;
1894 mMcParticleW = 0xFFFFFFFF;
1895 mMcParticlePos = 0xFFFFFFFF;
1896 mMcParticleMom = 0xFFFFFFFF;
1897 mCaloAmp = 0xFFFFFFFF;
1898 mCaloTime = 0xFFFFFFFF;
1899 mCPVPos = 0xFFFFFFFF;
1900 mCPVAmpl = 0xFFFFFFFF;
1901 mMuonTr1P = 0xFFFFFFFF;
1902 mMuonTrThetaX = 0xFFFFFFFF;
1903 mMuonTrThetaY = 0xFFFFFFFF;
1904 mMuonTrZmu = 0xFFFFFFFF;
1905 mMuonTrBend = 0xFFFFFFFF;
1906 mMuonTrNonBend = 0xFFFFFFFF;
1907 mMuonTrCov = 0xFFFFFFFF;
1908 mMuonCl = 0xFFFFFFFF;
1909 mMuonClErr = 0xFFFFFFFF;
1910 mV0Time = 0xFFFFFFFF;
1911 mV0ChannelTime = 0xFFFFFFFF;
1912 mFDDTime = 0xFFFFFFFF;
1913 mFDDChannelTime = 0xFFFFFFFF;
1914 mT0Time = 0xFFFFFFFF;
1915 mT0ChannelTime = 0xFFFFFFFF;
1916 mV0Amplitude = 0xFFFFFFFF;
1917 mFDDAmplitude = 0xFFFFFFFF;
1918 mT0Amplitude = 0xFFFFFFFF;
1922 mZDCEnergyMap[ic] = -std::numeric_limits<float>::infinity();
1925 mZDCTDCMap[ic] = -std::numeric_limits<float>::infinity();
1928 std::string hepmcUpdate = ic.
options().
get<std::string>(
"hepmc-update");
1929 HepMCUpdate when = (hepmcUpdate ==
"never" ? HepMCUpdate::never : hepmcUpdate ==
"always" ? HepMCUpdate::always
1930 : hepmcUpdate ==
"all" ? HepMCUpdate::allKeys
1931 : HepMCUpdate::anyKey);
1932 mXSectionUpdate = when;
1933 mPdfInfoUpdate = when;
1934 mHeavyIonUpdate = when;
1938 if (mStreamerFlags) {
1939 mStreamer = std::make_unique<o2::utils::TreeStreamRedirector>(
"AO2DStreamer.root",
"RECREATE");
1945void add_additional_meta_info(std::vector<TString>& keys, std::vector<TString>&
values)
1948 auto aod_external_meta_info_file = getenv(
"AOD_ADDITIONAL_METADATA_FILE");
1949 if (aod_external_meta_info_file !=
nullptr) {
1950 LOG(info) <<
"Trying to inject additional AOD meta-data from " << aod_external_meta_info_file;
1951 if (std::filesystem::exists(aod_external_meta_info_file)) {
1952 std::ifstream input_file(aod_external_meta_info_file);
1954 nlohmann::json json_data;
1956 input_file >> json_data;
1957 }
catch (nlohmann::json::parse_error& e) {
1958 std::cerr <<
"JSON Parse Error: " << e.what() <<
"\n";
1959 std::cerr <<
"Exception ID: " << e.id <<
"\n";
1960 std::cerr <<
"Byte position: " << e.byte <<
"\n";
1964 for (
const auto& [
key,
value] : json_data.items()) {
1965 LOG(info) <<
"Adding AOD MetaData" <<
key <<
" : " <<
value;
1966 keys.push_back(
key.c_str());
1977 mTimer.Start(
false);
1980 updateTimeDependentParams(pc);
2005 std::vector<o2::ctp::CTPDigit> ctpDigitsCreated;
2006 if (mCTPReadout == 1) {
2007 LOG(info) <<
"CTP : creating ctpreadout in AOD producer";
2008 createCTPReadout(recoData, ctpDigitsCreated, pc);
2009 LOG(info) <<
"CTP : ctpreadout created from AOD";
2010 ctpDigits = gsl::span<o2::ctp::CTPDigit>(ctpDigitsCreated);
2012 LOG(
debug) <<
"FOUND " << primVertices.size() <<
" primary vertices";
2013 LOG(
debug) <<
"FOUND " << ft0RecPoints.size() <<
" FT0 rec. points";
2014 LOG(
debug) <<
"FOUND " << fv0RecPoints.size() <<
" FV0 rec. points";
2015 LOG(
debug) <<
"FOUND " << fddRecPoints.size() <<
" FDD rec. points";
2016 LOG(
debug) <<
"FOUND " << cpvClusters.size() <<
" CPV clusters";
2017 LOG(
debug) <<
"FOUND " << cpvTrigRecs.size() <<
" CPV trigger records";
2019 LOG(info) <<
"FOUND " << primVertices.size() <<
" primary vertices";
2023 auto bcCursor = createTableCursor<o2::aod::BCs>(pc);
2024 auto bcFlagsCursor = createTableCursor<o2::aod::BCFlags>(pc);
2025 auto cascadesCursor = createTableCursor<o2::aod::Cascades>(pc);
2026 auto collisionsCursor = createTableCursor<o2::aod::Collisions>(pc);
2027 auto decay3BodyCursor = createTableCursor<o2::aod::Decay3Bodys>(pc);
2028 auto trackedCascadeCursor = createTableCursor<o2::aod::TrackedCascades>(pc);
2029 auto trackedV0Cursor = createTableCursor<o2::aod::TrackedV0s>(pc);
2030 auto tracked3BodyCurs = createTableCursor<o2::aod::Tracked3Bodys>(pc);
2031 auto fddCursor = createTableCursor<o2::aod::FDDs>(pc);
2032 auto fddExtraCursor = createTableCursor<o2::aod::FDDsExtra>(pc);
2033 auto ft0Cursor = createTableCursor<o2::aod::FT0s>(pc);
2034 auto ft0ExtraCursor = createTableCursor<o2::aod::FT0sExtra>(pc);
2035 auto fv0aCursor = createTableCursor<o2::aod::FV0As>(pc);
2036 auto fv0aExtraCursor = createTableCursor<o2::aod::FV0AsExtra>(pc);
2037 auto fwdTracksCursor = createTableCursor<o2::aod::StoredFwdTracks>(pc);
2038 auto fwdTracksCovCursor = createTableCursor<o2::aod::StoredFwdTracksCov>(pc);
2039 auto fwdTrkClsCursor = createTableCursor<o2::aod::FwdTrkCls>(pc);
2040 auto mftTracksCursor = createTableCursor<o2::aod::StoredMFTTracks>(pc);
2041 auto mftTracksCovCursor = createTableCursor<o2::aod::StoredMFTTracksCov>(pc);
2042 auto tracksCursor = createTableCursor<o2::aod::StoredTracksIU>(pc);
2043 auto tracksCovCursor = createTableCursor<o2::aod::StoredTracksCovIU>(pc);
2044 auto tracksExtraCursor = createTableCursor<o2::aod::StoredTracksExtra>(pc);
2045 auto tracksQACursor = createTableCursor<o2::aod::TracksQAVersion>(pc);
2046 auto ambigTracksCursor = createTableCursor<o2::aod::AmbiguousTracks>(pc);
2047 auto ambigMFTTracksCursor = createTableCursor<o2::aod::AmbiguousMFTTracks>(pc);
2048 auto ambigFwdTracksCursor = createTableCursor<o2::aod::AmbiguousFwdTracks>(pc);
2049 auto v0sCursor = createTableCursor<o2::aod::V0s>(pc);
2050 auto zdcCursor = createTableCursor<o2::aod::Zdcs>(pc);
2051 auto hmpCursor = createTableCursor<o2::aod::HMPIDs>(pc);
2052 auto caloCellsCursor = createTableCursor<o2::aod::Calos>(pc);
2053 auto caloCellsTRGTableCursor = createTableCursor<o2::aod::CaloTriggers>(pc);
2054 auto cpvClustersCursor = createTableCursor<o2::aod::CPVClusters>(pc);
2055 auto originCursor = createTableCursor<o2::aod::Origins>(pc);
2059 if (mEnableTRDextra) {
2060 trdExtraCursor = createTableCursor<o2::aod::TRDsExtra>(pc);
2075 mcColLabelsCursor = createTableCursor<o2::aod::McCollisionLabels>(pc);
2076 mcCollisionsCursor = createTableCursor<o2::aod::McCollisions>(pc);
2077 hepmcXSectionsCursor = createTableCursor<o2::aod::HepMCXSections>(pc);
2078 hepmcPdfInfosCursor = createTableCursor<o2::aod::HepMCPdfInfos>(pc);
2079 hepmcHeavyIonsCursor = createTableCursor<o2::aod::HepMCHeavyIons>(pc);
2080 mcMFTTrackLabelCursor = createTableCursor<o2::aod::McMFTTrackLabels>(pc);
2081 mcFwdTrackLabelCursor = createTableCursor<o2::aod::McFwdTrackLabels>(pc);
2082 mcParticlesCursor = createTableCursor<o2::aod::StoredMcParticles_001>(pc);
2083 mcTrackLabelCursor = createTableCursor<o2::aod::McTrackLabels>(pc);
2084 mcCaloLabelsCursor = createTableCursor<o2::aod::McCaloLabels_001>(pc);
2087 std::unique_ptr<o2::steer::MCKinematicsReader> mcReader;
2089 mcReader = std::make_unique<o2::steer::MCKinematicsReader>(
"collisioncontext.root");
2091 mMCKineReader = mcReader.get();
2092 std::map<uint64_t, int> bcsMap;
2093 collectBCs(recoData, mUseMC ? mcReader->getDigitizationContext()->getEventRecords() : std::vector<o2::InteractionTimeRecord>{}, bcsMap);
2094 if (!primVer2TRefs.empty()) {
2095 addRefGlobalBCsForTOF(primVer2TRefs.back(), primVerGIs, recoData, bcsMap);
2098 mBCLookup.
init(bcsMap);
2101 const int runNumber = (mRunNumber == -1) ?
int(tinfo.runNumber) : mRunNumber;
2102 if (mTFNumber == -1L) {
2104 tfNumber = uint64_t(tinfo.firstTForbit) + (uint64_t(tinfo.runNumber) << 32);
2106 tfNumber = mTFNumber;
2109 std::vector<float> aAmplitudes, aTimes;
2110 std::vector<uint8_t> aChannels;
2111 fv0aCursor.reserve(fv0RecPoints.size());
2112 for (
auto& fv0RecPoint : fv0RecPoints) {
2113 aAmplitudes.clear();
2116 const auto channelData = fv0RecPoint.getBunchChannelData(fv0ChData);
2117 for (
auto& channel : channelData) {
2118 if (channel.charge > 0) {
2119 aAmplitudes.push_back(truncateFloatFraction(channel.charge, mV0Amplitude));
2120 aTimes.push_back(truncateFloatFraction(channel.time * 1.E-3, mV0ChannelTime));
2121 aChannels.push_back(channel.channel);
2124 uint64_t
bc = fv0RecPoint.getInteractionRecord().toLong();
2125 auto item = bcsMap.find(
bc);
2127 if (item != bcsMap.end()) {
2128 bcID = item->second;
2130 LOG(fatal) <<
"Error: could not find a corresponding BC ID for a FV0 rec. point; BC = " <<
bc;
2135 truncateFloatFraction(fv0RecPoint.getCollisionGlobalMeanTime() * 1E-3, mV0Time),
2136 fv0RecPoint.getTrigger().getTriggersignals());
2138 if (mEnableFITextra) {
2139 fv0aExtraCursor(bcID,
2144 std::vector<float> zdcEnergy, zdcAmplitudes, zdcTime;
2145 std::vector<uint8_t> zdcChannelsE, zdcChannelsT;
2146 zdcCursor.reserve(zdcBCRecData.size());
2147 for (
auto zdcRecData : zdcBCRecData) {
2148 uint64_t
bc = zdcRecData.ir.toLong();
2149 auto item = bcsMap.find(
bc);
2151 if (item != bcsMap.end()) {
2152 bcID = item->second;
2154 LOG(fatal) <<
"Error: could not find a corresponding BC ID for a ZDC rec. point; BC = " <<
bc;
2156 int fe, ne, ft, nt, fi, ni;
2157 zdcRecData.getRef(fe, ne, ft, nt, fi, ni);
2159 zdcChannelsE.clear();
2160 zdcAmplitudes.clear();
2162 zdcChannelsT.clear();
2163 for (
int ie = 0; ie < ne; ie++) {
2164 auto& zdcEnergyData = zdcEnergies[fe + ie];
2165 zdcEnergy.emplace_back(zdcEnergyData.energy());
2166 zdcChannelsE.emplace_back(zdcEnergyData.ch());
2168 for (
int it = 0; it < nt; it++) {
2169 auto& tdc = zdcTDCData[ft + it];
2170 zdcAmplitudes.emplace_back(tdc.amplitude());
2171 zdcTime.emplace_back(tdc.value());
2183 std::vector<MCColInfo> mcColToEvSrc;
2189 int nMCCollisions = mcReader->getDigitizationContext()->getNCollisions();
2190 const auto& mcRecords = mcReader->getDigitizationContext()->getEventRecords();
2191 const auto& mcParts = mcReader->getDigitizationContext()->getEventParts();
2194 if (mUseSigFiltMC) {
2195 std::vector<int> sourceIDs{};
2196 for (
int iCol = 0; iCol < nMCCollisions; iCol++) {
2197 for (
auto const& colPart : mcParts[iCol]) {
2198 int sourceID = colPart.sourceID;
2199 if (std::find(sourceIDs.begin(), sourceIDs.end(), sourceID) == sourceIDs.end()) {
2200 sourceIDs.push_back(sourceID);
2202 if (sourceIDs.size() > 1) {
2206 if (sourceIDs.size() > 1) {
2210 if (sourceIDs.size() <= 1) {
2211 LOGP(fatal,
"Signal filtering cannot be enabled without embedding. Please fix the configuration either enabling the embedding, or turning off the signal filtering.");
2216 int totalNParts = 0;
2217 for (
int iCol = 0; iCol < nMCCollisions; iCol++) {
2218 totalNParts += mcParts[iCol].size();
2220 mcCollisionsCursor.
reserve(totalNParts);
2222 for (
int iCol = 0; iCol < nMCCollisions; iCol++) {
2223 const auto time = mcRecords[iCol].getTimeOffsetWrtBC();
2224 auto globalBC = mcRecords[iCol].toLong();
2225 auto item = bcsMap.find(globalBC);
2227 if (item != bcsMap.end()) {
2228 bcID = item->second;
2230 LOG(fatal) <<
"Error: could not find a corresponding BC ID "
2231 <<
"for MC collision; BC = " << globalBC
2232 <<
", mc collision = " << iCol;
2234 auto& colParts = mcParts[iCol];
2235 auto nParts = colParts.size();
2236 for (
auto colPart : colParts) {
2237 auto eventID = colPart.entryID;
2238 auto sourceID = colPart.sourceID;
2241 if (nParts == 1 || sourceID == 0) {
2244 auto& header = mcReader->getMCEventHeader(sourceID, eventID);
2245 updateMCHeader(mcCollisionsCursor.
cursor,
2246 hepmcXSectionsCursor.
cursor,
2247 hepmcPdfInfosCursor.
cursor,
2248 hepmcHeavyIonsCursor.
cursor,
2256 mcColToEvSrc.emplace_back(
MCColInfo{iCol, sourceID, eventID, globalBC});
2261 std::sort(mcColToEvSrc.begin(), mcColToEvSrc.end(),
2265 int16_t aFDDAmplitudesA[8] = {0u}, aFDDAmplitudesC[8] = {0u};
2266 float aFDDTimesA[8] = {0.f}, aFDDTimesC[8] = {0.f};
2268 fddCursor.reserve(fddRecPoints.size());
2269 for (
const auto& fddRecPoint : fddRecPoints) {
2270 for (
int i = 0;
i < 8;
i++) {
2271 aFDDAmplitudesA[
i] = 0;
2272 aFDDAmplitudesC[
i] = 0;
2273 aFDDTimesA[
i] = 0.f;
2274 aFDDTimesC[
i] = 0.f;
2276 uint64_t globalBC = fddRecPoint.getInteractionRecord().toLong();
2277 uint64_t
bc = globalBC;
2278 auto item = bcsMap.find(
bc);
2280 if (item != bcsMap.end()) {
2281 bcID = item->second;
2283 LOG(fatal) <<
"Error: could not find a corresponding BC ID for a FDD rec. point; BC = " <<
bc;
2285 const auto channelData = fddRecPoint.getBunchChannelData(fddChData);
2286 for (
const auto& channel : channelData) {
2287 if (channel.mPMNumber < 8) {
2288 aFDDAmplitudesC[channel.mPMNumber] = channel.mChargeADC;
2289 aFDDTimesC[channel.mPMNumber] = truncateFloatFraction(channel.mTime * 1E-3, mFDDChannelTime);
2291 aFDDAmplitudesA[channel.mPMNumber - 8] = channel.mChargeADC;
2292 aFDDTimesA[channel.mPMNumber - 8] = truncateFloatFraction(channel.mTime * 1E-3, mFDDChannelTime);
2299 truncateFloatFraction(fddRecPoint.getCollisionTimeA() * 1E-3, mFDDTime),
2300 truncateFloatFraction(fddRecPoint.getCollisionTimeC() * 1E-3, mFDDTime),
2301 fddRecPoint.getTrigger().getTriggersignals());
2302 if (mEnableFITextra) {
2303 fddExtraCursor(bcID,
2310 std::vector<float> aAmplitudesA, aAmplitudesC, aTimesA, aTimesC;
2311 std::vector<uint8_t> aChannelsA, aChannelsC;
2312 ft0Cursor.reserve(ft0RecPoints.size());
2313 for (
auto& ft0RecPoint : ft0RecPoints) {
2314 aAmplitudesA.clear();
2315 aAmplitudesC.clear();
2320 const auto channelData = ft0RecPoint.getBunchChannelData(ft0ChData);
2321 for (
auto& channel : channelData) {
2323 if (channel.QTCAmpl > 0) {
2325 if (channel.ChId < nFT0ChannelsAside) {
2326 aChannelsA.push_back(channel.ChId);
2327 aAmplitudesA.push_back(truncateFloatFraction(channel.QTCAmpl, mT0Amplitude));
2328 aTimesA.push_back(truncateFloatFraction(channel.CFDTime * 1E-3, mT0ChannelTime));
2330 aChannelsC.push_back(channel.ChId - nFT0ChannelsAside);
2331 aAmplitudesC.push_back(truncateFloatFraction(channel.QTCAmpl, mT0Amplitude));
2332 aTimesC.push_back(truncateFloatFraction(channel.CFDTime * 1E-3, mT0ChannelTime));
2336 uint64_t globalBC = ft0RecPoint.getInteractionRecord().toLong();
2337 uint64_t
bc = globalBC;
2338 auto item = bcsMap.find(
bc);
2340 if (item != bcsMap.end()) {
2341 bcID = item->second;
2343 LOG(fatal) <<
"Error: could not find a corresponding BC ID for a FT0 rec. point; BC = " <<
bc;
2350 truncateFloatFraction(ft0RecPoint.getCollisionTimeA() * 1E-3, mT0Time),
2351 truncateFloatFraction(ft0RecPoint.getCollisionTimeC() * 1E-3, mT0Time),
2352 ft0RecPoint.getTrigger().getTriggersignals());
2353 if (mEnableFITextra) {
2354 ft0ExtraCursor(bcID,
2362 mcColLabelsCursor.
reserve(primVerLabels.size());
2363 for (
size_t ivert = 0; ivert < primVerLabels.size(); ++ivert) {
2364 const auto&
label = primVerLabels[ivert];
2370 std::vector<std::pair<int32_t, int64_t>> candidates;
2371 for (
const auto& colInfo : mcColToEvSrc) {
2372 if (colInfo.sourceID ==
label.getSourceID() &&
2373 colInfo.eventID ==
label.getEventID()) {
2374 candidates.emplace_back(colInfo.colIndex, colInfo.bc);
2378 int32_t mcCollisionID = -1;
2379 if (candidates.size() == 1) {
2380 mcCollisionID = candidates[0].first;
2381 }
else if (candidates.size() > 1) {
2387 const auto& timeStamp = primVertices[ivert].getTimeStamp();
2388 const double interactionTime = timeStamp.getTimeStamp() * 1E3;
2389 const auto recoBC = relativeTime_to_GlobalBC(interactionTime);
2390 int64_t bestDiff = std::numeric_limits<int64_t>::max();
2391 for (
const auto& [colIndex,
bc] : candidates) {
2392 const auto bcDiff = std::abs(
static_cast<int64_t
>(
bc) -
static_cast<int64_t
>(recoBC));
2393 if (bcDiff < bestDiff) {
2395 mcCollisionID = colIndex;
2400 uint16_t mcMask = 0;
2401 mcColLabelsCursor(mcCollisionID, mcMask);
2405 cacheTriggers(recoData);
2406 countTPCClusters(recoData);
2408 int collisionID = 0;
2412 auto& trackReffwd = primVer2TRefs.back();
2413 fillIndexTablesPerCollision(trackReffwd, primVerGIs, recoData);
2415 for (
auto&
vertex : primVertices) {
2416 auto& trackReffwd = primVer2TRefs[collisionID];
2417 fillIndexTablesPerCollision(trackReffwd, primVerGIs, recoData);
2422 prepareStrangenessTracking(recoData);
2424 mGIDToTableFwdID.clear();
2425 mGIDToTableMFTID.clear();
2427 if (mPropTracks || mThinTracks) {
2431 mGIDUsedBySVtx.reserve(v0s.size() * 2 + cascades.size() + decays3Body.size() * 3);
2432 for (
const auto&
v0 : v0s) {
2433 mGIDUsedBySVtx.insert(
v0.getProngID(0));
2434 mGIDUsedBySVtx.insert(
v0.getProngID(1));
2436 for (
const auto& cascade : cascades) {
2437 mGIDUsedBySVtx.insert(cascade.getBachelorID());
2439 for (
const auto& id3Body : decays3Body) {
2440 mGIDUsedBySVtx.insert(id3Body.getProngID(0));
2441 mGIDUsedBySVtx.insert(id3Body.getProngID(1));
2442 mGIDUsedBySVtx.insert(id3Body.getProngID(2));
2451 mCurrentTRDTrigID = 0;
2454 auto& trackRef = primVer2TRefs.back();
2456 fillTrackTablesPerCollision(-1, std::uint64_t(-1), trackRef, primVerGIs, recoData, tracksCursor, tracksCovCursor, tracksExtraCursor, tracksQACursor, trdExtraCursor,
2457 ambigTracksCursor, mftTracksCursor, mftTracksCovCursor, ambigMFTTracksCursor,
2458 fwdTracksCursor, fwdTracksCovCursor, ambigFwdTracksCursor, fwdTrkClsCursor, bcsMap);
2460 mCurrentTRDTrigID = 0;
2463 collisionsCursor.reserve(primVertices.size());
2464 for (
auto&
vertex : primVertices) {
2465 auto& cov =
vertex.getCov();
2466 auto& timeStamp =
vertex.getTimeStamp();
2467 const double interactionTime = timeStamp.getTimeStamp() * 1E3;
2468 uint64_t globalBC = relativeTime_to_GlobalBC(interactionTime);
2469 uint64_t localBC = relativeTime_to_LocalBC(interactionTime);
2470 LOG(
debug) <<
"global BC " << globalBC <<
" local BC " << localBC <<
" relative interaction time " << interactionTime;
2473 auto item = bcsMap.find(globalBC);
2475 if (item != bcsMap.end()) {
2476 bcID = item->second;
2478 LOG(fatal) <<
"Error: could not find a corresponding BC ID for a collision; BC = " << globalBC <<
", collisionID = " << collisionID;
2480 collisionsCursor(bcID,
2481 truncateFloatFraction(
vertex.getX(), mCollisionPosition),
2482 truncateFloatFraction(
vertex.getY(), mCollisionPosition),
2483 truncateFloatFraction(
vertex.getZ(), mCollisionPosition),
2484 truncateFloatFraction(cov[0], mCollisionPositionCov),
2485 truncateFloatFraction(cov[1], mCollisionPositionCov),
2486 truncateFloatFraction(cov[2], mCollisionPositionCov),
2487 truncateFloatFraction(cov[3], mCollisionPositionCov),
2488 truncateFloatFraction(cov[4], mCollisionPositionCov),
2489 truncateFloatFraction(cov[5], mCollisionPositionCov),
2491 truncateFloatFraction(
vertex.getChi2(), mCollisionPositionCov),
2492 vertex.getNContributors(),
2493 truncateFloatFraction(relInteractionTime, mCollisionPosition),
2494 truncateFloatFraction(timeStamp.getTimeStampError() * 1E3, mCollisionPositionCov));
2495 mVtxToTableCollID[collisionID] = mTableCollID++;
2497 auto& trackRef = primVer2TRefs[collisionID];
2499 fillTrackTablesPerCollision(collisionID, globalBC, trackRef, primVerGIs, recoData, tracksCursor, tracksCovCursor, tracksExtraCursor, tracksQACursor, trdExtraCursor, ambigTracksCursor,
2500 mftTracksCursor, mftTracksCovCursor, ambigMFTTracksCursor,
2501 fwdTracksCursor, fwdTracksCovCursor, ambigFwdTracksCursor, fwdTrkClsCursor, bcsMap);
2505 fillSecondaryVertices(recoData, v0sCursor, cascadesCursor, decay3BodyCursor);
2506 fillHMPID(recoData, hmpCursor);
2507 fillStrangenessTrackingTables(recoData, trackedV0Cursor, trackedCascadeCursor, tracked3BodyCurs);
2511 std::unordered_map<uint64_t, std::pair<uint64_t, uint64_t>> bcToClassMask;
2513 LOG(
debug) <<
"CTP input available";
2514 for (
auto& ctpDigit : ctpDigits) {
2515 uint64_t
bc = ctpDigit.intRecord.toLong();
2516 uint64_t classMask = ctpDigit.CTPClassMask.to_ulong();
2517 uint64_t inputMask = ctpDigit.CTPInputMask.to_ulong();
2518 if (emcalIncomplete.find(
bc) != emcalIncomplete.end()) {
2520 auto classMaskOrig = classMask;
2521 classMask = classMask & ~mEMCALTrgClassMask;
2522 LOG(
debug) <<
"Found EMCAL incomplete event, mask before " << std::bitset<64>(classMaskOrig) <<
", after " << std::bitset<64>(classMask);
2524 bcToClassMask[
bc] = {classMask, inputMask};
2530 bcCursor.reserve(bcsMap.size());
2531 for (
auto& item : bcsMap) {
2532 uint64_t
bc = item.first;
2533 std::pair<uint64_t, uint64_t> masks{0, 0};
2535 auto bcClassPair = bcToClassMask.find(
bc);
2536 if (bcClassPair != bcToClassMask.end()) {
2537 masks = bcClassPair->second;
2546 bcToClassMask.clear();
2549 auto bcFlags = fillBCFlags(recoData, bcsMap);
2550 bcFlagsCursor.reserve(bcFlags.size());
2551 for (
auto f : bcFlags) {
2558 cpvClustersCursor.reserve(cpvTrigRecs.size());
2559 for (
auto& cpvEvent : cpvTrigRecs) {
2560 uint64_t
bc = cpvEvent.getBCData().toLong();
2561 auto item = bcsMap.find(
bc);
2563 if (item != bcsMap.end()) {
2564 bcID = item->second;
2566 LOG(fatal) <<
"Error: could not find a corresponding BC ID for a CPV Trigger Record; BC = " <<
bc;
2568 for (
int iClu = cpvEvent.getFirstEntry(); iClu < cpvEvent.getFirstEntry() + cpvEvent.getNumberOfObjects(); iClu++) {
2569 auto&
clu = cpvClusters[iClu];
2570 clu.getLocalPosition(posX, posZ);
2571 cpvClustersCursor(bcID,
2572 truncateFloatFraction(posX, mCPVPos),
2573 truncateFloatFraction(posZ, mCPVPos),
2574 truncateFloatFraction(
clu.getEnergy(), mCPVAmpl),
2575 clu.getPackedClusterStatus());
2584 fillMCParticlesTable(*mcReader,
2585 mcParticlesCursor.
cursor,
2591 LOG(info) <<
"FILL MC took " << timer.RealTime() <<
" s";
2592 mcColToEvSrc.clear();
2598 fillMCTrackLabelsTable(mcTrackLabelCursor, mcMFTTrackLabelCursor, mcFwdTrackLabelCursor, primVer2TRefs.back(), primVerGIs, recoData);
2599 for (
auto iref = 0U; iref < primVer2TRefs.size() - 1; iref++) {
2600 auto& trackRef = primVer2TRefs[iref];
2601 fillMCTrackLabelsTable(mcTrackLabelCursor, mcMFTTrackLabelCursor, mcFwdTrackLabelCursor, trackRef, primVerGIs, recoData, iref);
2607 fillCaloTable(caloCellsCursor, caloCellsTRGTableCursor, mcCaloLabelsCursor, bcsMap, recoData);
2612 mGIDToTableID.clear();
2614 mGIDToTableFwdID.clear();
2616 mGIDToTableMFTID.clear();
2618 mVtxToTableCollID.clear();
2620 mV0ToTableID.clear();
2623 mIndexTableFwd.clear();
2625 mIndexTableMFT.clear();
2630 mGIDUsedBySVtx.clear();
2631 mGIDUsedByStr.clear();
2633 originCursor(tfNumber);
2636 TString dataType = mUseMC ?
"MC" :
"RAW";
2638 TString ROOTVersion = ROOT_RELEASE;
2639 mMetaDataKeys = {
"DataType",
"Run",
"O2Version",
"ROOTVersion",
"RecoPassName",
"AnchorProduction",
"AnchorPassName",
"LPMProductionTag",
"CreatedBy"};
2640 mMetaDataVals = {dataType,
"3", O2Version, ROOTVersion, mRecoPass, mAnchorProd, mAnchorPass, mLPMProdTag, mUser};
2641 add_additional_meta_info(mMetaDataKeys, mMetaDataVals);
2659 for (
const auto& rof : rofs) {
2660 int first = rof.getFirstEntry(), last =
first + rof.getNEntries();
2661 for (
int i =
first;
i < last;
i++) {
2662 mITSROFs.push_back(
count);
2672 for (
const auto& rof : rofs) {
2673 int first = rof.getFirstEntry(),
last =
first + rof.getNEntries();
2675 mMFTROFs.push_back(
count);
2682 mITSTPCTRDTriggers.clear();
2685 for (
const auto& trig : itstpctrigs) {
2686 int first = trig.getFirstTrack(),
last =
first + trig.getNumberOfTracks();
2688 mITSTPCTRDTriggers.push_back(
count);
2695 mTPCTRDTriggers.clear();
2698 for (
const auto& trig : tpctrigs) {
2699 int first = trig.getFirstTrack(),
last =
first + trig.getNumberOfTracks();
2701 mTPCTRDTriggers.push_back(
count);
2711 for (
const auto& rof : rofs) {
2714 mMCHROFs.push_back(
count);
2721AODProducerWorkflowDPL::TrackExtraInfo AODProducerWorkflowDPL::processBarrelTrack(
int collisionID, std::uint64_t collisionBC,
GIndex trackIndex,
2724 TrackExtraInfo extraInfoHolder;
2725 if (collisionID < 0) {
2728 bool needBCSlice = collisionID < 0;
2729 uint64_t bcOfTimeRef = collisionBC - mStartIR.
toLong();
2731 auto setTrackTime = [&](
double t,
double terr,
bool gaussian) {
2737 extraInfoHolder.trackTimeRes = terr;
2739 double error = this->mTimeMarginTrackTime + (gaussian ? extraInfoHolder.trackTimeRes * this->mNSigmaTimeTrack : extraInfoHolder.trackTimeRes);
2740 bcOfTimeRef = fillBCSlice(extraInfoHolder.bcSlice, t - error, t + error, bcsMap);
2743 extraInfoHolder.diffBCRef =
int(bcOfTimeRef);
2745 truncateFloatFraction(extraInfoHolder.trackTime, mTrackTime), truncateFloatFraction(extraInfoHolder.trackTimeRes, mTrackTimeError),
2748 auto contributorsGID =
data.getSingleDetectorRefs(trackIndex);
2749 const auto& trackPar =
data.getTrackParam(trackIndex);
2750 extraInfoHolder.flags |= trackPar.getPID() << 28;
2751 auto src = trackIndex.getSource();
2753 const auto& tofMatch =
data.getTOFMatch(trackIndex);
2754 extraInfoHolder.tofChi2 = tofMatch.getChi2();
2755 const auto& tofInt = tofMatch.getLTIntegralOut();
2756 float intLen = tofInt.getL();
2757 extraInfoHolder.length = intLen;
2764 extraInfoHolder.tofExpMom = mass * expBeta / std::sqrt(1.f - expBeta * expBeta);
2767 const double massZ = o2::track::PID::getMass2Z(trackPar.getPID());
2768 const double energy = sqrt((massZ * massZ) + (extraInfoHolder.tofExpMom * extraInfoHolder.tofExpMom));
2769 const double exp = extraInfoHolder.length * energy / (cSpeed * extraInfoHolder.tofExpMom);
2770 auto tofSignal = (tofMatch.getSignal() -
exp) * 1e-3;
2771 setTrackTime(tofSignal, 0.2,
true);
2775 extraInfoHolder.trdChi2 = trdOrig.getChi2();
2776 extraInfoHolder.trdSignal = trdOrig.getSignal();
2777 extraInfoHolder.trdPattern = getTRDPattern(trdOrig);
2778 if (extraInfoHolder.trackTimeRes < 0.) {
2780 const auto& trdTrig = (
src ==
GIndex::Source::TPCTRD) ?
data.getTPCTRDTriggers()[mTPCTRDTriggers[trackIndex.getIndex()]] :
data.getITSTPCTRDTriggers()[mITSTPCTRDTriggers[trackIndex.getIndex()]];
2782 setTrackTime(ttrig, 1.,
true);
2786 const auto& itsTrack =
data.getITSTrack(contributorsGID[
GIndex::ITS]);
2787 int nClusters = itsTrack.getNClusters();
2788 float chi2 = itsTrack.getChi2();
2790 extraInfoHolder.itsClusterSizes = itsTrack.getClusterSizes();
2792 const auto& rof =
data.getITSTracksROFRecords()[mITSROFs[trackIndex.getIndex()]];
2794 setTrackTime(t, mITSROFrameHalfLengthNS,
false);
2797 extraInfoHolder.itsClusterSizes =
data.getITSABRefs()[contributorsGID[
GIndex::Source::ITSAB].getIndex()].getClusterSizes();
2801 const auto& tpcClData = mTPCCounters[contributorsGID[
GIndex::TPC]];
2802 const auto& dEdx = tpcOrig.getdEdx().dEdxTotTPC > 0 ? tpcOrig.getdEdx() : tpcOrig.getdEdxAlt();
2803 if (tpcOrig.getdEdx().dEdxTotTPC == 0) {
2806 if (tpcOrig.hasASideClusters()) {
2809 if (tpcOrig.hasCSideClusters()) {
2812 extraInfoHolder.tpcInnerParam = tpcOrig.getP() / tpcOrig.getAbsCharge();
2813 extraInfoHolder.tpcChi2NCl = tpcOrig.getNClusters() ? tpcOrig.getChi2() / tpcOrig.getNClusters() : 0;
2814 extraInfoHolder.tpcSignal = dEdx.dEdxTotTPC;
2815 extraInfoHolder.tpcNClsFindable = tpcOrig.getNClusters();
2816 extraInfoHolder.tpcNClsFindableMinusFound = tpcOrig.getNClusters() - tpcClData.found;
2817 extraInfoHolder.tpcNClsFindableMinusCrossedRows = tpcOrig.getNClusters() - tpcClData.crossed;
2818 extraInfoHolder.tpcNClsShared = tpcClData.shared;
2819 uint32_t clsUsedForPID = dEdx.NHitsIROC + dEdx.NHitsOROC1 + dEdx.NHitsOROC2 + dEdx.NHitsOROC3;
2820 extraInfoHolder.tpcNClsFindableMinusPID = tpcOrig.getNClusters() - clsUsedForPID;
2823 double t = (tpcOrig.getTime0() + 0.5 * (tpcOrig.getDeltaTFwd() - tpcOrig.getDeltaTBwd())) * mTPCBinNS;
2824 double terr = 0.5 * (tpcOrig.getDeltaTFwd() + tpcOrig.getDeltaTBwd()) * mTPCBinNS;
2825 double err = mTimeMarginTrackTime + terr;
2826 bcOfTimeRef = fillBCSlice(extraInfoHolder.bcSlice, t - err, t + err, bcsMap);
2829 p.setDeltaTFwd(tpcOrig.getDeltaTFwd());
2830 p.setDeltaTBwd(tpcOrig.getDeltaTBwd());
2831 extraInfoHolder.trackTimeRes =
p.getTimeErr();
2833 extraInfoHolder.diffBCRef =
int(bcOfTimeRef);
2834 extraInfoHolder.isTPConly =
true;
2837 const auto& trITSTPC =
data.getTPCITSTrack(trackIndex);
2838 auto ts = trITSTPC.getTimeMUS();
2839 setTrackTime(ts.getTimeStamp() * 1.e3, ts.getTimeStampError() * 1.e3,
true);
2843 extrapolateToCalorimeters(extraInfoHolder,
data.getTrackParamOut(trackIndex));
2848 return extraInfoHolder;
2851AODProducerWorkflowDPL::TrackQA AODProducerWorkflowDPL::processBarrelTrackQA(
int collisionID, std::uint64_t collisionBC,
GIndex trackIndex,
2855 auto contributorsGID =
data.getTPCContributorGID(trackIndex);
2856 const auto& trackPar =
data.getTrackParam(trackIndex);
2857 if (contributorsGID.isIndexSet()) {
2859 const auto& tpcOrig =
data.getTPCTrack(contributorsGID);
2864 std::array<float, 2> dcaInfo{-999., -999.};
2865 if (prop->propagateToDCABxByBz({v.getX(), v.getY(), v.getZ()}, tpcTMP, 2.f, mMatType, &dcaInfo)) {
2866 trackQAHolder.tpcdcaR = 100. * dcaInfo[0] / sqrt(1. + trackPar.getQ2Pt() * trackPar.getQ2Pt());
2867 trackQAHolder.tpcdcaZ = 100. * dcaInfo[1] / sqrt(1. + trackPar.getQ2Pt() * trackPar.getQ2Pt());
2871 auto safeInt8Clamp = [](
auto value) -> int8_t {
2872 using ValType =
decltype(
value);
2873 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()))));
2875 auto safeUInt8Clamp = [](
auto value) -> uint8_t {
2876 using ValType =
decltype(
value);
2877 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()))));
2881 uint8_t clusterCounters[8] = {0};
2883 uint8_t sectorIndex, rowIndex;
2884 uint32_t clusterIndex;
2885 const auto& tpcClusRefs =
data.getTPCTracksClusterRefs();
2886 for (
int i = 0;
i < tpcOrig.getNClusterReferences();
i++) {
2887 o2::tpc::TrackTPC::getClusterReference(tpcClusRefs,
i, sectorIndex, rowIndex, clusterIndex, tpcOrig.getClusterRef());
2888 char indexTracklet = (rowIndex % 152) / 19;
2889 clusterCounters[indexTracklet]++;
2893 for (
int i = 0;
i < 8;
i++) {
2894 if (clusterCounters[
i] > 5) {
2895 byteMask |= (1 <<
i);
2898 trackQAHolder.tpcTime0 = tpcOrig.getTime0();
2899 trackQAHolder.tpcClusterByteMask = byteMask;
2900 const auto& dEdxInfoAlt = tpcOrig.getdEdxAlt();
2901 const float dEdxNorm = (dEdxInfoAlt.dEdxTotTPC > 0) ? 100. / dEdxInfoAlt.dEdxTotTPC : 0;
2902 trackQAHolder.tpcdEdxNorm = dEdxInfoAlt.dEdxTotTPC;
2903 trackQAHolder.tpcdEdxMax0R = safeUInt8Clamp(dEdxInfoAlt.dEdxMaxIROC * dEdxNorm);
2904 trackQAHolder.tpcdEdxMax1R = safeUInt8Clamp(dEdxInfoAlt.dEdxMaxOROC1 * dEdxNorm);
2905 trackQAHolder.tpcdEdxMax2R = safeUInt8Clamp(dEdxInfoAlt.dEdxMaxOROC2 * dEdxNorm);
2906 trackQAHolder.tpcdEdxMax3R = safeUInt8Clamp(dEdxInfoAlt.dEdxMaxOROC3 * dEdxNorm);
2908 trackQAHolder.tpcdEdxTot0R = safeUInt8Clamp(dEdxInfoAlt.dEdxTotIROC * dEdxNorm);
2909 trackQAHolder.tpcdEdxTot1R = safeUInt8Clamp(dEdxInfoAlt.dEdxTotOROC1 * dEdxNorm);
2910 trackQAHolder.tpcdEdxTot2R = safeUInt8Clamp(dEdxInfoAlt.dEdxTotOROC2 * dEdxNorm);
2911 trackQAHolder.tpcdEdxTot3R = safeUInt8Clamp(dEdxInfoAlt.dEdxTotOROC3 * dEdxNorm);
2914 auto contributorsGIDA =
data.getSingleDetectorRefs(trackIndex);
2916 const auto& tofMatch =
data.getTOFMatch(trackIndex);
2917 const float qpt = trackPar.getQ2Pt();
2919 trackQAHolder.dTofdX = safeInt8Clamp(tofMatch.getDXatTOF() / scaleTOF);
2920 trackQAHolder.dTofdZ = safeInt8Clamp(tofMatch.getDZatTOF() / scaleTOF);
2926 if (
auto itsContGID =
data.getITSContributorGID(trackIndex); itsContGID.isIndexSet() && itsContGID.getSource() !=
GIndex::ITSAB) {
2927 const auto& itsOrig =
data.getITSTrack(itsContGID);
2936 const float beta0 = std::sqrt(std::min(50.f / tpcOrig.getdEdx().dEdxMaxTPC, 1.f));
2937 const float qpt = gloCopy.getQ2Pt();
2938 const float x = qpt / beta0;
2940 auto scaleCont = [&
x](
int i) ->
float {
2943 auto scaleGlo = [&
x](
int i) ->
float {
2948 trackQAHolder.dRefContY = safeInt8Clamp((itsCopy.getY() - tpcCopy.getY()) * scaleCont(0));
2949 trackQAHolder.dRefContZ = safeInt8Clamp((itsCopy.getZ() - tpcCopy.getZ()) * scaleCont(1));
2950 trackQAHolder.dRefContSnp = safeInt8Clamp((itsCopy.getSnp() - tpcCopy.getSnp()) * scaleCont(2));
2951 trackQAHolder.dRefContTgl = safeInt8Clamp((itsCopy.getTgl() - tpcCopy.getTgl()) * scaleCont(3));
2952 trackQAHolder.dRefContQ2Pt = safeInt8Clamp((itsCopy.getQ2Pt() - tpcCopy.getQ2Pt()) * scaleCont(4));
2954 trackQAHolder.dRefGloY = safeInt8Clamp(((itsCopy.getY() + tpcCopy.getY()) * 0.5f - gloCopy.getY()) * scaleGlo(0));
2955 trackQAHolder.dRefGloZ = safeInt8Clamp(((itsCopy.getZ() + tpcCopy.getZ()) * 0.5f - gloCopy.getZ()) * scaleGlo(1));
2956 trackQAHolder.dRefGloSnp = safeInt8Clamp(((itsCopy.getSnp() + tpcCopy.getSnp()) * 0.5f - gloCopy.getSnp()) * scaleGlo(2));
2957 trackQAHolder.dRefGloTgl = safeInt8Clamp(((itsCopy.getTgl() + tpcCopy.getTgl()) * 0.5f - gloCopy.getTgl()) * scaleGlo(3));
2958 trackQAHolder.dRefGloQ2Pt = safeInt8Clamp(((itsCopy.getQ2Pt() + tpcCopy.getQ2Pt()) * 0.5f - gloCopy.getQ2Pt()) * scaleGlo(4));
2962 (*mStreamer) <<
"trackQA"
2963 <<
"trackITSOrig=" << itsOrig
2964 <<
"trackTPCOrig=" << tpcOrig
2965 <<
"trackITSTPCOrig=" << trackPar
2966 <<
"trackITSProp=" << itsCopy
2967 <<
"trackTPCProp=" << tpcCopy
2968 <<
"trackITSTPCProp=" << gloCopy
2971 <<
"scaleCont0=" << scaleCont(0)
2972 <<
"scaleCont1=" << scaleCont(1)
2973 <<
"scaleCont2=" << scaleCont(2)
2974 <<
"scaleCont3=" << scaleCont(3)
2975 <<
"scaleCont4=" << scaleCont(4)
2976 <<
"scaleGlo0=" << scaleGlo(0)
2977 <<
"scaleGlo1=" << scaleGlo(1)
2978 <<
"scaleGlo2=" << scaleGlo(2)
2979 <<
"scaleGlo3=" << scaleGlo(3)
2980 <<
"scaleGlo4=" << scaleGlo(4)
2981 <<
"trackQAHolder.tpcTime0=" << trackQAHolder.tpcTime0
2982 <<
"trackQAHolder.tpcdEdxNorm=" << trackQAHolder.tpcdEdxNorm
2983 <<
"trackQAHolder.tpcdcaR=" << trackQAHolder.tpcdcaR
2984 <<
"trackQAHolder.tpcdcaZ=" << trackQAHolder.tpcdcaZ
2985 <<
"trackQAHolder.tpcdcaClusterByteMask=" << trackQAHolder.tpcClusterByteMask
2986 <<
"trackQAHolder.tpcdEdxMax0R=" << trackQAHolder.tpcdEdxMax0R
2987 <<
"trackQAHolder.tpcdEdxMax1R=" << trackQAHolder.tpcdEdxMax1R
2988 <<
"trackQAHolder.tpcdEdxMax2R=" << trackQAHolder.tpcdEdxMax2R
2989 <<
"trackQAHolder.tpcdEdxMax3R=" << trackQAHolder.tpcdEdxMax3R
2990 <<
"trackQAHolder.tpcdEdxTot0R=" << trackQAHolder.tpcdEdxTot0R
2991 <<
"trackQAHolder.tpcdEdxTot1R=" << trackQAHolder.tpcdEdxTot1R
2992 <<
"trackQAHolder.tpcdEdxTot2R=" << trackQAHolder.tpcdEdxTot2R
2993 <<
"trackQAHolder.tpcdEdxTot3R=" << trackQAHolder.tpcdEdxTot3R
2994 <<
"trackQAHolder.dRefContY=" << trackQAHolder.dRefContY
2995 <<
"trackQAHolder.dRefContZ=" << trackQAHolder.dRefContZ
2996 <<
"trackQAHolder.dRefContSnp=" << trackQAHolder.dRefContSnp
2997 <<
"trackQAHolder.dRefContTgl=" << trackQAHolder.dRefContTgl
2998 <<
"trackQAHolder.dRefContQ2Pt=" << trackQAHolder.dRefContQ2Pt
2999 <<
"trackQAHolder.dRefGloY=" << trackQAHolder.dRefGloY
3000 <<
"trackQAHolder.dRefGloZ=" << trackQAHolder.dRefGloZ
3001 <<
"trackQAHolder.dRefGloSnp=" << trackQAHolder.dRefGloSnp
3002 <<
"trackQAHolder.dRefGloTgl=" << trackQAHolder.dRefGloTgl
3003 <<
"trackQAHolder.dRefGloQ2Pt=" << trackQAHolder.dRefGloQ2Pt
3004 <<
"trackQAHolder.dTofdX=" << trackQAHolder.dTofdX
3005 <<
"trackQAHolder.dTofdZ=" << trackQAHolder.dTofdZ
3006 <<
"scaleTOF=" << scaleTOF
3013 return trackQAHolder;
3021 dcaInfo.set(999.f, 999.f, 999.f, 999.f, 999.f);
3026void AODProducerWorkflowDPL::extrapolateToCalorimeters(TrackExtraInfo& extraInfoHolder,
const o2::track::TrackPar& track)
3028 constexpr float XEMCAL = 440.f, XPHOS = 460.f, XEMCAL2 = XEMCAL * XEMCAL;
3029 constexpr float ETAEMCAL = 0.75;
3030 constexpr float ZEMCALFastCheck = 460.;
3031 constexpr float ETADCALINNER = 0.22;
3032 constexpr float ETAPHOS = 0.13653194;
3033 constexpr float ETAPHOSMARGIN = 0.17946979;
3034 constexpr float ETADCALPHOSSWITCH = (ETADCALINNER + ETAPHOS) / 2;
3035 constexpr short SNONE = 0, SEMCAL = 0x1, SPHOS = 0x2;
3036 constexpr short SECTORTYPE[18] = {
3037 SNONE, SNONE, SNONE, SNONE,
3038 SEMCAL, SEMCAL, SEMCAL, SEMCAL, SEMCAL, SEMCAL,
3041 SPHOS | SEMCAL, SPHOS | SEMCAL, SPHOS | SEMCAL,
3052 (std::abs(outTr.getZAt(xtrg, 0)) > ZEMCALFastCheck) ||
3053 !prop->PropagateToXBxByBz(outTr, xtrg, 0.95, 10, o2::base::Propagator::MatCorrType::USEMatCorrLUT)) {
3054 LOGP(
debug,
"preliminary step: does not reach R={} {}", XEMCAL, outTr.asString());
3058 if ((outTr.getX() * outTr.getX() + outTr.getY() * outTr.getY() < XEMCAL2) &&
3059 (!outTr.rotateParam(outTr.getPhi()) ||
3061 !prop->PropagateToXBxByBz(outTr, xtrg, 0.95, 10, o2::base::Propagator::MatCorrType::USEMatCorrLUT))) {
3062 LOGP(
debug,
"does not reach R={} {}", XEMCAL, outTr.asString());
3068 auto propExactSector = [&outTr, §or, prop](
float xprop) ->
bool {
3071 auto outTrTmp = outTr;
3073 if ((std::abs(outTr.getZ()) > ZEMCALFastCheck) || !outTrTmp.rotateParam(
alpha) ||
3074 !prop->PropagateToXBxByBz(outTrTmp, xprop, 0.95, 10, o2::base::Propagator::MatCorrType::USEMatCorrLUT)) {
3075 LOGP(
debug,
"failed on rotation to {} (sector {}) or propagation to X={} {}",
alpha, sector, xprop, outTrTmp.asString());
3080 if (sectorTmp == sector) {
3088 LOGP(
debug,
"failed to rotate to sector, {}", outTr.asString());
3095 if (!propExactSector(XEMCAL) || SECTORTYPE[sector] == SNONE) {
3100 float r = std::sqrt(outTr.getX() * outTr.getX() + outTr.getY() * outTr.getY()), tg = std::atan2(
r, outTr.getZ());
3101 float eta = -std::log(std::tan(0.5f * tg)), etaAbs = std::abs(eta);
3102 if (etaAbs > ETAEMCAL) {
3103 LOGP(
debug,
"eta = {} is off at EMCAL radius", eta, outTr.asString());
3107 if ((SECTORTYPE[sector] & SPHOS) && etaAbs < ETADCALPHOSSWITCH) {
3108 if (!propExactSector(XPHOS)) {
3111 r = std::sqrt(outTr.getX() * outTr.getX() + outTr.getY() * outTr.getY());
3112 tg = std::atan2(
r, outTr.getZ());
3113 eta = -std::log(std::tan(0.5f * tg));
3114 }
else if (!(SECTORTYPE[sector] & SEMCAL)) {
3117 extraInfoHolder.trackPhiEMCAL = outTr.getPhiPos();
3118 extraInfoHolder.trackEtaEMCAL = eta;
3119 LOGP(
debug,
"eta = {} phi = {} sector {} for {}", extraInfoHolder.trackEtaEMCAL, extraInfoHolder.trackPhiEMCAL, sector, outTr.asString());
3123std::set<uint64_t> AODProducerWorkflowDPL::filterEMCALIncomplete(
const gsl::span<const o2::emcal::TriggerRecord> triggers)
3125 std::set<uint64_t> emcalIncompletes;
3126 for (
const auto& trg : triggers) {
3127 if (trg.getTriggerBits() & o2::emcal::triggerbits::Inc) {
3129 emcalIncompletes.insert(trg.getBCData().toLong());
3132 return emcalIncompletes;
3138 static bool initOnceDone =
false;
3139 if (!initOnceDone) {
3140 initOnceDone =
true;
3147 for (
auto i = 0U;
i < bs.size();
i++) {
3162 mTPCBinNS = elParam.ZbinWidth * 1.e3;
3165 mNSigmaTimeTrack = pvParams.nSigmaTimeTrack;
3166 mTimeMarginTrackTime = pvParams.timeMarginTrackTime * 1.e3;
3170 if (mEnableTRDextra) {
3192 LOG(info) <<
"ITS Alpide param updated";
3194 par.printKeyValues();
3198 LOG(info) <<
"MFT Alpide param updated";
3200 par.printKeyValues();
3211 mEMCALTrgClassMask = 0;
3212 for (
const auto& trgclass : ctpconfig.getCTPClasses()) {
3214 mEMCALTrgClassMask |= trgclass.classMask;
3217 LOG(info) <<
"Loaded EMCAL trigger class mask: " << std::bitset<64>(mEMCALTrgClassMask);
3221void AODProducerWorkflowDPL::addRefGlobalBCsForTOF(
const o2::dataformats::VtxTrackRef& trackRef,
const gsl::span<const GIndex>& GIndices,
3232 int nbitsFrac = 24 - (32 - o2::math_utils::popcount(mTrackTime));
3233 int nbitsLoss = std::max(0,
int(std::log2(TOFTimePrecPS)));
3234 assert(nbitsFrac > 1);
3235 std::uint64_t maxRangePS = std::uint64_t(0x1) << (nbitsFrac + nbitsLoss);
3237 LOG(info) <<
"Max gap of " << maxGapBC <<
" BCs to closest globalBC reference is needed for TOF tracks to provide precision of "
3238 << TOFTimePrecPS <<
" ps";
3241 if (!trackRef.getEntries()) {
3245 std::uint64_t maxBC = mStartIR.
toLong();
3246 const auto& tofClus =
data.getTOFClusters();
3253 for (
int ti =
start; ti <
end; ti++) {
3254 auto& trackIndex = GIndices[ti];
3255 const auto& tofMatch =
data.getTOFMatch(trackIndex);
3256 const auto& tofInt = tofMatch.getLTIntegralOut();
3257 float intLen = tofInt.getL();
3258 float tofExpMom = 0.;
3268 double massZ = o2::track::PID::getMass2Z(
data.getTrackParam(trackIndex).getPID());
3269 double energy = sqrt((massZ * massZ) + (tofExpMom * tofExpMom));
3270 double exp = intLen * energy / (cSpeed * tofExpMom);
3271 auto tofSignal = (tofMatch.getSignal() -
exp) * 1e-3;
3272 auto bc = relativeTime_to_GlobalBC(tofSignal);
3274 auto it = bcsMap.lower_bound(
bc);
3275 if (it == bcsMap.end() || it->first >
bc + maxGapBC) {
3276 bcsMap.emplace_hint(it,
bc, 1);
3285 if ((--bcsMap.end())->first <= maxBC) {
3286 bcsMap.emplace_hint(bcsMap.end(), maxBC + 1, 1);
3290 for (
auto& item : bcsMap) {
3296std::uint64_t AODProducerWorkflowDPL::fillBCSlice(
int (&slice)[2],
double tmin,
double tmax,
const std::map<uint64_t, int>& bcsMap)
const
3308 uint64_t bcMin = relativeTime_to_GlobalBC(tmin), bcMax = relativeTime_to_GlobalBC(tmax);
3331 auto upperindex =
p.first;
3332 while (upperindex < bcvector.size() && bcvector[upperindex] <= bcMax) {
3335 if (upperindex !=
p.first) {
3339 slice[1] = upperindex;
3341 auto bcOfTimeRef =
p.second - this->mStartIR.
toLong();
3342 LOG(
debug) <<
"BC slice t:" << tmin <<
" " << slice[0]
3343 <<
" t: " << tmax <<
" " << slice[1]
3344 <<
" bcref: " << bcOfTimeRef;
3350 std::vector<uint8_t>
flags(bcsMap.size());
3353 auto bcIt = bcsMap.begin();
3354 auto itsrofs =
data.getITSTracksROFRecords();
3357 for (
auto& rof : itsrofs) {
3358 if (!rof.getFlag(o2::itsmft::ROFRecord::VtxUPCMode)) {
3361 uint64_t globalBC0 = rof.getBCData().toLong() + bROF, globalBC1 = globalBC0 + lROF - 1;
3363 while (bcIt != bcsMap.end()) {
3364 if (bcIt->first < globalBC0) {
3368 if (bcIt->first > globalBC1) {
3380 LOGF(info,
"aod producer dpl total timing: Cpu: %.3e Real: %.3e s in %d slots",
3381 mTimer.CpuTime(), mTimer.RealTime(), mTimer.Counter() - 1);
3388 auto dataRequest = std::make_shared<DataRequest>();
3389 dataRequest->inputs.emplace_back(
"ctpconfig",
"CTP",
"CTPCONFIG", 0, Lifetime::Condition,
ccdbParamSpec(
"CTP/Config/Config", CTPConfigPerRun));
3391 dataRequest->requestTracks(
src, useMC);
3392 dataRequest->requestPrimaryVertices(useMC);
3394 dataRequest->requestCTPDigits(useMC);
3397 dataRequest->requestSecondaryVertices(useMC);
3399 if (enableStrangenessTracking) {
3400 dataRequest->requestStrangeTracks(useMC);
3401 LOGF(info,
"requestStrangeTracks Finish");
3410 dataRequest->requestTOFClusters(useMC);
3413 dataRequest->requestPHOSCells(useMC);
3416 dataRequest->requestTRDTracklets(
false);
3419 dataRequest->requestEMCALCells(useMC);
3422 dataRequest->requestCPVClusters(useMC);
3425 auto ggRequest = std::make_shared<o2::base::GRPGeomRequest>(
true,
3431 dataRequest->inputs,
3434 dataRequest->inputs.emplace_back(
"meanvtx",
"GLO",
"MEANVERTEX", 0, Lifetime::Condition,
ccdbParamSpec(
"GLO/Calib/MeanVertex", {}, 1));
3439 std::vector<OutputSpec> outputs{
3478 if (enableTRDextra) {
3480 dataRequest->inputs.emplace_back(
"trdlocalgainfactors",
"TRD",
"LOCALGAINFACTORS", 0, Lifetime::Condition,
ccdbParamSpec(
"TRD/Calib/LocalGainFactor"));
3481 dataRequest->inputs.emplace_back(
"trdnoisemap",
"TRD",
"NOISEMAP", 0, Lifetime::Condition,
ccdbParamSpec(
"TRD/Calib/NoiseMapMCM"));
3482 dataRequest->inputs.emplace_back(
"trdgaincalib",
"TRD",
"CALGAIN", 0, Lifetime::Condition,
ccdbParamSpec(
"TRD/Calib/CalGain"));
3486 outputs.insert(outputs.end(),
3487 {OutputForTable<McCollisions>::spec(),
3488 OutputForTable<HepMCXSections>::spec(),
3489 OutputForTable<HepMCPdfInfos>::spec(),
3490 OutputForTable<HepMCHeavyIons>::spec(),
3491 OutputForTable<McMFTTrackLabels>::spec(),
3492 OutputForTable<McFwdTrackLabels>::spec(),
3493 OutputForTable<StoredMcParticles_001>::spec(),
3494 OutputForTable<McTrackLabels>::spec(),
3495 OutputForTable<McCaloLabels_001>::spec(),
3500 {OutputLabel{
"McCollisionLabels"},
"AOD",
"MCCOLLISIONLABEL", 0, Lifetime::Timeframe}});
3504 "aod-producer-workflow",
3507 AlgorithmSpec{adaptFromTask<AODProducerWorkflowDPL>(
src, dataRequest, ggRequest, enableSV, useMC, enableFITextra, enableTRDextra)},
3509 ConfigParamSpec{
"run-number", VariantType::Int64, -1L, {
"The run-number. If left default we try to get it from DPL header."}},
3510 ConfigParamSpec{
"aod-timeframe-id", VariantType::Int64, -1L, {
"Set timeframe number"}},
3511 ConfigParamSpec{
"fill-calo-cells", VariantType::Int, 1, {
"Fill calo cells into cell table"}},
3512 ConfigParamSpec{
"enable-truncation", VariantType::Int, 1, {
"Truncation parameter: 1 -- on, != 1 -- off"}},
3513 ConfigParamSpec{
"lpmp-prod-tag", VariantType::String,
"", {
"LPMProductionTag"}},
3514 ConfigParamSpec{
"anchor-pass", VariantType::String,
"", {
"AnchorPassName"}},
3515 ConfigParamSpec{
"anchor-prod", VariantType::String,
"", {
"AnchorProduction"}},
3516 ConfigParamSpec{
"reco-pass", VariantType::String,
"", {
"RecoPassName"}},
3517 ConfigParamSpec{
"aod-parent", VariantType::String,
"", {
"Parent AOD file name (if any)"}},
3518 ConfigParamSpec{
"created-by", VariantType::String,
"", {
"Who created this AO2D"}},
3519 ConfigParamSpec{
"nthreads", VariantType::Int, std::max(1,
int(std::thread::hardware_concurrency() / 2)), {
"Number of threads"}},
3520 ConfigParamSpec{
"reco-mctracks-only", VariantType::Int, 0, {
"Store only reconstructed MC tracks and their mothers/daughters. 0 -- off, != 0 -- on"}},
3521 ConfigParamSpec{
"ctpreadout-create", VariantType::Int, 0, {
"Create CTP digits from detector readout and CTP inputs. !=1 -- off, 1 -- on"}},
3522 ConfigParamSpec{
"emc-select-leading", VariantType::Bool,
false, {
"Flag to select if only the leading contributing particle for an EMCal cell should be stored"}},
3523 ConfigParamSpec{
"propagate-tracks", VariantType::Bool,
false, {
"Propagate tracks (not used for secondary vertices) to IP"}},
3524 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)"}},
3525 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)"}},
3526 ConfigParamSpec{
"propagate-muons", VariantType::Bool,
false, {
"Propagate muons to IP"}},
3527 ConfigParamSpec{
"thin-tracks", VariantType::Bool,
false, {
"Produce thinned track tables"}},
3528 ConfigParamSpec{
"trackqc-keepglobaltracks", VariantType::Bool,
false, {
"Always keep TrackQA for global tracks"}},
3529 ConfigParamSpec{
"trackqc-retainonlydedx", VariantType::Bool,
false, {
"Keep only dEdx information, zero out everything else"}},
3530 ConfigParamSpec{
"trackqc-fraction", VariantType::Float, float(0.1), {
"Fraction of tracks to QC"}},
3531 ConfigParamSpec{
"trackqc-NTrCut", VariantType::Int64, 4L, {
"Minimal length of the track - in amount of tracklets"}},
3532 ConfigParamSpec{
"trackqc-tpc-dca", VariantType::Float, 3.f, {
"Keep TPC standalone track with this DCAxy to the PV"}},
3533 ConfigParamSpec{
"trackqc-tpc-cls", VariantType::Int, 80, {
"Keep TPC standalone track with this #clusters"}},
3534 ConfigParamSpec{
"trackqc-tpc-pt", VariantType::Float, 0.2f, {
"Keep TPC standalone track with this pt"}},
3535 ConfigParamSpec{
"with-streamers", VariantType::String,
"", {
"Bit-mask to steer writing of intermediate streamer files"}},
3536 ConfigParamSpec{
"seed", VariantType::Int, 0, {
"Set seed for random generator used for sampling (0 (default) means using a random_device)"}},
3537 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 ITS Vertex 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)
helper struct to keep mapping of colIndex to MC labels and bunch crossing
static constexpr auto 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