diff --git a/DataFormats/Reconstruction/include/ReconstructionDataFormats/MatchInfoTOF.h b/DataFormats/Reconstruction/include/ReconstructionDataFormats/MatchInfoTOF.h index ea0ba1e1f94d9..f1222d179304a 100644 --- a/DataFormats/Reconstruction/include/ReconstructionDataFormats/MatchInfoTOF.h +++ b/DataFormats/Reconstruction/include/ReconstructionDataFormats/MatchInfoTOF.h @@ -29,7 +29,7 @@ class MatchInfoTOF using evIdx = o2::dataformats::EvIndex; public: - MatchInfoTOF(evIdx evIdxTOFCl, float chi2, o2::track::TrackLTIntegral trkIntLT, evGIdx evIdxTrack, float dt = 0, float z = 0) : mEvIdxTOFCl(evIdxTOFCl), mChi2(chi2), mIntLT(trkIntLT), mEvIdxTrack(evIdxTrack), mDeltaT(dt), mZatTOF(z){}; + MatchInfoTOF(evIdx evIdxTOFCl, double time, float chi2, o2::track::TrackLTIntegral trkIntLT, evGIdx evIdxTrack, float dt = 0, float z = 0) : mEvIdxTOFCl(evIdxTOFCl), mSignal(time), mChi2(chi2), mIntLT(trkIntLT), mEvIdxTrack(evIdxTrack), mDeltaT(dt), mZatTOF(z){}; MatchInfoTOF() = default; void setEvIdxTOFCl(evIdx index) { mEvIdxTOFCl = index; } void setEvIdxTrack(evGIdx index) { mEvIdxTrack = index; } @@ -51,6 +51,8 @@ class MatchInfoTOF float getDeltaT() const { return mDeltaT; } void setZatTOF(float val) { mZatTOF = val; } float getZatTOF() const { return mZatTOF; } + void setSignal(double time) { mSignal = time; } + double getSignal() const { return mSignal; } private: float mChi2; // chi2 of the pair track-TOFcluster @@ -59,8 +61,9 @@ class MatchInfoTOF evGIdx mEvIdxTrack; ///< EvIdx for track (first: ev index; second: track global index) float mZatTOF = 0.0; ///< Z position at TOF float mDeltaT = 0.0; ///< tTOF - TPC (microsec) + double mSignal = 0.0; ///< TOF time in ps - ClassDefNV(MatchInfoTOF, 2); + ClassDefNV(MatchInfoTOF, 3); }; } // namespace dataformats } // namespace o2 diff --git a/DataFormats/Reconstruction/include/ReconstructionDataFormats/MatchInfoTOFReco.h b/DataFormats/Reconstruction/include/ReconstructionDataFormats/MatchInfoTOFReco.h index 35ab341e46ee0..29b5067470b2a 100644 --- a/DataFormats/Reconstruction/include/ReconstructionDataFormats/MatchInfoTOFReco.h +++ b/DataFormats/Reconstruction/include/ReconstructionDataFormats/MatchInfoTOFReco.h @@ -36,7 +36,7 @@ class MatchInfoTOFReco : public MatchInfoTOF ITSTPCTRD, SIZEALL }; - MatchInfoTOFReco(evIdx evIdxTOFCl, float chi2, o2::track::TrackLTIntegral trkIntLT, evGIdx evIdxTrack, TrackType trkType, float dt = 0, float z = 0) : MatchInfoTOF(evIdxTOFCl, chi2, trkIntLT, evIdxTrack, dt, z), mTrackType(trkType){}; + MatchInfoTOFReco(evIdx evIdxTOFCl, double time, float chi2, o2::track::TrackLTIntegral trkIntLT, evGIdx evIdxTrack, TrackType trkType, float dt = 0, float z = 0) : MatchInfoTOF(evIdxTOFCl, time, chi2, trkIntLT, evIdxTrack, dt, z), mTrackType(trkType){}; MatchInfoTOFReco() = default; @@ -45,7 +45,7 @@ class MatchInfoTOFReco : public MatchInfoTOF private: TrackType mTrackType; ///< track type (TPC, ITSTPC, TPCTRD, ITSTPCTRD) - ClassDefNV(MatchInfoTOFReco, 1); + ClassDefNV(MatchInfoTOFReco, 2); }; } // namespace dataformats } // namespace o2 diff --git a/Detectors/AOD/include/AODProducerWorkflow/AODProducerWorkflowSpec.h b/Detectors/AOD/include/AODProducerWorkflow/AODProducerWorkflowSpec.h index 6e38c9593727f..10c259db0d933 100644 --- a/Detectors/AOD/include/AODProducerWorkflow/AODProducerWorkflowSpec.h +++ b/Detectors/AOD/include/AODProducerWorkflow/AODProducerWorkflowSpec.h @@ -29,6 +29,7 @@ #include "DataFormatsITS/TrackITS.h" #include "DataFormatsMFT/TrackMFT.h" #include "DataFormatsTPC/TrackTPC.h" +#include "DataFormatsTRD/TrackTRD.h" #include "ReconstructionDataFormats/TrackTPCITS.h" #include @@ -39,6 +40,7 @@ using namespace o2::framework; using GID = o2::dataformats::GlobalTrackID; +using GIndex = o2::dataformats::VtxTrackIndex; using DataRequest = o2::globaltracking::DataRequest; namespace o2::aodproducer @@ -145,17 +147,16 @@ typedef boost::unordered_map Triple class AODProducerWorkflowDPL : public Task { public: - AODProducerWorkflowDPL(std::shared_ptr dataRequest, bool fillSVertices) : mDataRequest(dataRequest), mFillSVertices(fillSVertices) {} + AODProducerWorkflowDPL(GID::mask_t src, std::shared_ptr dataRequest, bool fillSVertices) : mInputSources(src), mDataRequest(dataRequest), mFillSVertices(fillSVertices) {} ~AODProducerWorkflowDPL() override = default; void init(InitContext& ic) final; void run(ProcessingContext& pc) final; void endOfStream(framework::EndOfStreamContext& ec) final; private: - int mFillTracksITS{1}; - int mFillTracksMFT{1}; - int mFillTracksTPC{0}; - int mFillTracksITSTPC{1}; + const float cSpeed = 0.029979246f; // speed of light in TOF units + + GID::mask_t mInputSources; int64_t mTFNumber{-1}; int mTruncate{1}; int mRecoOnly{0}; @@ -198,6 +199,7 @@ class AODProducerWorkflowDPL : public Task uint32_t mFDDAmplitude = 0xFFFFF000; // 11 bits uint32_t mT0Amplitude = 0xFFFFF000; // 11 bits + // helper struct for extra info in fillTrackTablesPerCollision() struct TrackExtraInfo { float tpcInnerParam = 0.f; uint32_t flags = 0; @@ -220,6 +222,15 @@ class AODProducerWorkflowDPL : public Task float trackPhiEMCAL = -999.f; }; + // helper struct for mc track labels + struct MCLabels { + uint32_t labelID = std::numeric_limits::max(); + uint32_t labelITS = std::numeric_limits::max(); + uint32_t labelTPC = std::numeric_limits::max(); + uint16_t labelMask = 0; + uint8_t mftLabelMask = 0; + }; + void collectBCs(gsl::span& ft0RecPoints, gsl::span& primVertices, const std::vector& mcRecords, @@ -237,12 +248,37 @@ class AODProducerWorkflowDPL : public Task template void addToMFTTracksTable(mftTracksCursorType& mftTracksCursor, const o2::mft::TrackMFT& track, int collisionID); + // helper for track tables + // fills tables collision by collision + // interaction time is for TOF information + template + void fillTrackTablesPerCollision(int collisionID, + double interactionTime, + const o2::dataformats::VtxTrackRef& trackRef, + gsl::span& GIndices, + o2::globaltracking::RecoContainer& data, + TracksCursorType& tracksCursor, + TracksCovCursorType& tracksCovCursor, + TracksExtraCursorType& tracksExtraCursor, + mftTracksCursorType& mftTracksCursor); + template void fillMCParticlesTable(o2::steer::MCKinematicsReader& mcReader, const MCParticlesCursorType& mcParticlesCursor, - gsl::span& mcTruthITS, std::vector& isStoredITS, - gsl::span& mcTruthMFT, std::vector& isStoredMFT, - gsl::span& mcTruthTPC, std::vector& isStoredTPC, - TripletsMap_t& toStore, std::vector> const& mccolidtoeventsource); + gsl::span& mcTruthITS, + gsl::span& mcTruthMFT, + gsl::span& mcTruthTPC, + TripletsMap_t& toStore, + std::vector> const& mccolidtoeventsource); + + // helper for tpc clusters + void countTPCClusters(const o2::tpc::TrackTPC& track, + const gsl::span& tpcClusRefs, + const gsl::span& tpcClusShMap, + const o2::tpc::ClusterNativeAccess& tpcClusAcc, + uint8_t& shared, uint8_t& found, uint8_t& crossed); + + // helper for trd pattern + uint8_t getTRDPattern(const o2::trd::TrackTRD& track); }; /// create a processor spec diff --git a/Detectors/AOD/src/AODProducerWorkflowSpec.cxx b/Detectors/AOD/src/AODProducerWorkflowSpec.cxx index 2151a2b4f4209..6687fe925abfb 100644 --- a/Detectors/AOD/src/AODProducerWorkflowSpec.cxx +++ b/Detectors/AOD/src/AODProducerWorkflowSpec.cxx @@ -12,12 +12,15 @@ /// @file AODProducerWorkflowSpec.cxx #include "AODProducerWorkflow/AODProducerWorkflowSpec.h" +#include "AnalysisDataModel/PID/PIDTOF.h" #include "DataFormatsFT0/RecPoints.h" #include "DataFormatsITS/TrackITS.h" #include "DataFormatsMFT/TrackMFT.h" #include "DataFormatsTPC/TrackTPC.h" #include "CCDB/BasicCCDBManager.h" +#include "CommonConstants/PhysicsConstants.h" #include "CommonDataFormat/InteractionRecord.h" +#include "DataFormatsTRD/TrackTRD.h" #include "DataFormatsGlobalTracking/RecoContainer.h" #include "Framework/AnalysisDataModel.h" #include "Framework/ConfigParamRegistry.h" @@ -47,7 +50,6 @@ using namespace o2::framework; using namespace o2::math_utils::detail; using PVertex = o2::dataformats::PrimaryVertex; -using V2TRef = o2::dataformats::VtxTrackRef; using GIndex = o2::dataformats::VtxTrackIndex; using DataRequest = o2::globaltracking::DataRequest; using GID = o2::dataformats::GlobalTrackID; @@ -194,12 +196,88 @@ void AODProducerWorkflowDPL::addToMFTTracksTable(mftTracksCursorType& mftTracksC track.getTrackChi2()); } +template +void AODProducerWorkflowDPL::fillTrackTablesPerCollision(int collisionID, + double interactionTime, + const o2::dataformats::VtxTrackRef& trackRef, + gsl::span& GIndices, + o2::globaltracking::RecoContainer& data, + TracksCursorType& tracksCursor, + TracksCovCursorType& tracksCovCursor, + TracksExtraCursorType& tracksExtraCursor, + mftTracksCursorType& mftTracksCursor) +{ + const auto& tpcClusRefs = data.getTPCTracksClusterRefs(); + const auto& tpcClusShMap = data.clusterShMapTPC; + const auto& tpcClusAcc = data.getTPCClusters(); + + for (int src = GIndex::NSources; src--;) { + int start = trackRef.getFirstEntryOfSource(src); + int end = start + trackRef.getEntriesOfSource(src); + LOG(DEBUG) << "Unassigned tracks: src = " << src << ", start = " << start << ", end = " << end; + for (int ti = start; ti < end; ti++) { + TrackExtraInfo extraInfoHolder; + auto& trackIndex = GIndices[ti]; + if (GIndex::includesSource(src, mInputSources)) { + if (src == GIndex::Source::MFT) { // MFT tracks are treated separately since they are stored in a different table + const auto& track = data.getMFTTrack(trackIndex.getIndex()); + addToMFTTracksTable(mftTracksCursor, track, collisionID); + } else { + auto contributorsGID = data.getSingleDetectorRefs(trackIndex); + const auto& trackPar = data.getTrackParam(trackIndex); + if (contributorsGID[GIndex::Source::ITS].isIndexSet()) { + const auto& itsOrig = data.getITSTrack(contributorsGID[GIndex::ITS]); + extraInfoHolder.itsClusterMap = itsOrig.getPattern(); + } + if (contributorsGID[GIndex::Source::TPC].isIndexSet()) { + const auto& tpcOrig = data.getTPCTrack(contributorsGID[GIndex::TPC]); + extraInfoHolder.tpcInnerParam = tpcOrig.getP(); + extraInfoHolder.tpcChi2NCl = tpcOrig.getNClusters() ? tpcOrig.getChi2() / tpcOrig.getNClusters() : 0; + extraInfoHolder.tpcSignal = tpcOrig.getdEdx().dEdxTotTPC; + uint8_t shared, found, crossed; // fixme: need to switch from these placeholders to something more reasonable + countTPCClusters(tpcOrig, tpcClusRefs, tpcClusShMap, tpcClusAcc, shared, found, crossed); + extraInfoHolder.tpcNClsFindable = tpcOrig.getNClusters(); + extraInfoHolder.tpcNClsFindableMinusFound = tpcOrig.getNClusters() - found; + extraInfoHolder.tpcNClsFindableMinusCrossedRows = tpcOrig.getNClusters() - crossed; + extraInfoHolder.tpcNClsShared = shared; + } + if (contributorsGID[GIndex::Source::ITSTPCTOF].isIndexSet()) { + const auto& tofMatch = data.getTOFMatch(contributorsGID[GIndex::Source::ITSTPCTOF]); + extraInfoHolder.tofChi2 = tofMatch.getChi2(); + const auto& tofInt = tofMatch.getLTIntegralOut(); + float intLen = tofInt.getL(); + extraInfoHolder.length = intLen; + extraInfoHolder.tofSignal = tofMatch.getSignal(); + float mass = o2::constants::physics::MassPionCharged; // default pid = pion + float expSig = tofInt.getTOF(o2::track::PID::Pion); + float expMom = 0.f; + if (expSig > 0 && interactionTime > 0) { + float tof = expSig - interactionTime; + float expBeta = (intLen / tof / cSpeed); + expMom = mass * expBeta / std::sqrt(1.f - expBeta * expBeta); + } + extraInfoHolder.tofExpMom = expMom; + } + if (src == GIndex::Source::TPCTRD || src == GIndex::Source::ITSTPCTRD) { + const auto& trdOrig = data.getTrack(src, contributorsGID[src].getIndex()); + extraInfoHolder.trdChi2 = trdOrig.getChi2(); + extraInfoHolder.trdPattern = getTRDPattern(trdOrig); + } + addToTracksTable(tracksCursor, tracksCovCursor, trackPar, collisionID, src); + addToTracksExtraTable(tracksExtraCursor, extraInfoHolder); + } + } + } + } +} + template void AODProducerWorkflowDPL::fillMCParticlesTable(o2::steer::MCKinematicsReader& mcReader, const MCParticlesCursorType& mcParticlesCursor, - gsl::span& mcTruthITS, std::vector& isStoredITS, - gsl::span& mcTruthMFT, std::vector& isStoredMFT, - gsl::span& mcTruthTPC, std::vector& isStoredTPC, - TripletsMap_t& toStore, std::vector> const& mccolid_to_eventandsource) + gsl::span& mcTruthITS, + gsl::span& mcTruthMFT, + gsl::span& mcTruthTPC, + TripletsMap_t& toStore, + std::vector> const& mccolid_to_eventandsource) { // mark reconstructed MC particles to store them into the table for (int i = 0; i < mcTruthITS.size(); i++) { @@ -335,14 +413,66 @@ void AODProducerWorkflowDPL::fillMCParticlesTable(o2::steer::MCKinematicsReader& } } +void AODProducerWorkflowDPL::countTPCClusters(const o2::tpc::TrackTPC& track, + const gsl::span& tpcClusRefs, + const gsl::span& tpcClusShMap, + const o2::tpc::ClusterNativeAccess& tpcClusAcc, + uint8_t& shared, uint8_t& found, uint8_t& crossed) +{ + constexpr int maxRows = 152; + constexpr int neighbour = 2; + std::array clMap{}, shMap{}; + uint8_t sectorIndex; + uint8_t rowIndex; + uint32_t clusterIndex; + shared = 0; + for (int i = 0; i < track.getNClusterReferences(); i++) { + o2::tpc::TrackTPC::getClusterReference(tpcClusRefs, i, sectorIndex, rowIndex, clusterIndex, track.getClusterRef()); + unsigned int absoluteIndex = tpcClusAcc.clusterOffset[sectorIndex][rowIndex] + clusterIndex; + clMap[rowIndex] = true; + if (tpcClusShMap[absoluteIndex] > 1) { + if (!shMap[rowIndex]) { + shared++; + } + shMap[rowIndex] = true; + } + } + + crossed = 0; + found = 0; + int last = -1; + for (int i = 0; i < maxRows; i++) { + if (clMap[i]) { + crossed++; + found++; + last = i; + } else if ((i - last) <= neighbour) { + crossed++; + } else { + int lim = std::min(i + 1 + neighbour, maxRows); + for (int j = i + 1; j < lim; j++) { + if (clMap[j]) { + crossed++; + } + } + } + } +} + +uint8_t AODProducerWorkflowDPL::getTRDPattern(const o2::trd::TrackTRD& track) +{ + uint8_t pattern = 0; + for (int il = o2::trd::TrackTRD::EGPUTRDTrack::kNLayers; il >= 0; il--) { + if (track.getTrackletIndex(il) != -1) { + pattern |= 0x1 << il; + } + } + return pattern; +} + void AODProducerWorkflowDPL::init(InitContext& ic) { mTimer.Stop(); - - mFillTracksITS = ic.options().get("fill-tracks-its"); - mFillTracksMFT = ic.options().get("fill-tracks-mft"); - mFillTracksTPC = ic.options().get("fill-tracks-tpc"); - mFillTracksITSTPC = ic.options().get("fill-tracks-its-tpc"); mTFNumber = ic.options().get("aod-timeframe-id"); mRecoOnly = ic.options().get("reco-mctracks-only"); mTruncate = ic.options().get("enable-truncation"); @@ -351,12 +481,8 @@ void AODProducerWorkflowDPL::init(InitContext& ic) LOG(INFO) << "TFNumber will be obtained from CCDB"; } - LOG(INFO) << "Track filling flags are set to: " - << "\n ITS = " << mFillTracksITS << "\n MFT = " << mFillTracksMFT << "\n TPC = " << mFillTracksTPC << "\n ITSTPC = " << mFillTracksITSTPC; - if (mTruncate != 1) { LOG(INFO) << "Truncation is not used!"; - mCollisionPosition = 0xFFFFFFFF; mCollisionPositionCov = 0xFFFFFFFF; mTrackX = 0xFFFFFFFF; @@ -398,9 +524,6 @@ void AODProducerWorkflowDPL::run(ProcessingContext& pc) { mTimer.Start(false); - // initialize track extra holder structure - TrackExtraInfo extraInfoHolder; - o2::globaltracking::RecoContainer recoData; recoData.collectData(pc, *mDataRequest); @@ -418,29 +541,14 @@ void AODProducerWorkflowDPL::run(ProcessingContext& pc) auto ft0ChData = recoData.getFT0ChannelsData(); auto ft0RecPoints = recoData.getFT0RecPoints(); - auto tracksITS = recoData.getITSTracks(); - auto tracksMFT = recoData.getMFTTracks(); - auto tracksTPC = recoData.getTPCTracks(); - auto tracksITSTPC = recoData.getTPCITSTracks(); - auto tracksTPCMCTruth = recoData.getTPCTracksMCLabels(); auto tracksITSMCTruth = recoData.getITSTracksMCLabels(); auto tracksMFTMCTruth = recoData.getMFTTracksMCLabels(); - // using vectors to mark referenced tracks - // todo: should not use these (?), to be removed, when all track types are processed - std::vector isStoredTPC(tracksTPC.size(), false); - std::vector isStoredITS(tracksITS.size(), false); - std::vector isStoredMFT(tracksMFT.size(), false); - LOG(DEBUG) << "FOUND " << primVertices.size() << " primary vertices"; - LOG(DEBUG) << "FOUND " << tracksTPC.size() << " TPC tracks"; LOG(DEBUG) << "FOUND " << tracksTPCMCTruth.size() << " TPC labels"; - LOG(DEBUG) << "FOUND " << tracksMFT.size() << " MFT tracks"; LOG(DEBUG) << "FOUND " << tracksMFTMCTruth.size() << " MFT labels"; - LOG(DEBUG) << "FOUND " << tracksITS.size() << " ITS tracks"; LOG(DEBUG) << "FOUND " << tracksITSMCTruth.size() << " ITS labels"; - LOG(DEBUG) << "FOUND " << tracksITSTPC.size() << " ITSTPC tracks"; LOG(DEBUG) << "FOUND " << ft0RecPoints.size() << " FT0 rec. points"; auto& bcBuilder = pc.outputs().make(Output{"AOD", "BC"}); @@ -643,104 +751,11 @@ void AODProducerWorkflowDPL::run(ProcessingContext& pc) // filling unassigned tracks first // so that all unassigned tracks are stored in the beginning of the table together - auto& trackRefU = primVer2TRefs.back(); // references to unassigned tracks are at the end - for (int src = GIndex::NSources; src--;) { - int start = trackRefU.getFirstEntryOfSource(src); - int end = start + trackRefU.getEntriesOfSource(src); - LOG(DEBUG) << "Unassigned tracks: src = " << src << ", start = " << start << ", end = " << end; - for (int ti = start; ti < end; ti++) { - extraInfoHolder.tpcInnerParam = 0.f; - extraInfoHolder.flags = 0; - extraInfoHolder.itsClusterMap = 0; - extraInfoHolder.tpcNClsFindable = 0; - extraInfoHolder.tpcNClsFindableMinusFound = 0; - extraInfoHolder.tpcNClsFindableMinusCrossedRows = 0; - extraInfoHolder.tpcNClsShared = 0; - extraInfoHolder.trdPattern = 0; - extraInfoHolder.itsChi2NCl = -999.f; - extraInfoHolder.tpcChi2NCl = -999.f; - extraInfoHolder.trdChi2 = -999.f; - extraInfoHolder.tofChi2 = -999.f; - extraInfoHolder.tpcSignal = -999.f; - extraInfoHolder.trdSignal = -999.f; - extraInfoHolder.tofSignal = -999.f; - extraInfoHolder.length = -999.f; - extraInfoHolder.tofExpMom = -999.f; - extraInfoHolder.trackEtaEMCAL = -999.f; - extraInfoHolder.trackPhiEMCAL = -999.f; - auto& trackIndex = primVerGIs[ti]; - if (src == GIndex::Source::ITS && mFillTracksITS) { - const auto& track = tracksITS[trackIndex.getIndex()]; - isStoredITS[trackIndex.getIndex()] = true; - // extra info - extraInfoHolder.itsClusterMap = track.getPattern(); - // track - addToTracksTable(tracksCursor, tracksCovCursor, track, -1, src); - addToTracksExtraTable(tracksExtraCursor, extraInfoHolder); - } - if (src == GIndex::Source::TPC && mFillTracksTPC) { - const auto& track = tracksTPC[trackIndex.getIndex()]; - isStoredTPC[trackIndex.getIndex()] = true; - // extra info - extraInfoHolder.tpcChi2NCl = track.getNClusters() ? track.getChi2() / track.getNClusters() : 0; - extraInfoHolder.tpcSignal = track.getdEdx().dEdxTotTPC; - extraInfoHolder.tpcNClsFindable = track.getNClusters(); - // track - addToTracksTable(tracksCursor, tracksCovCursor, track, -1, src); - addToTracksExtraTable(tracksExtraCursor, extraInfoHolder); - } - if (src == GIndex::Source::ITSTPC && mFillTracksITSTPC) { - const auto& track = tracksITSTPC[trackIndex.getIndex()]; - auto contributorsGID = recoData.getSingleDetectorRefs(trackIndex); - // extra info from sub-tracks - if (contributorsGID[GIndex::Source::ITS].isIndexSet()) { - isStoredITS[track.getRefITS()] = true; - const auto& itsOrig = recoData.getITSTrack(contributorsGID[GIndex::ITS]); - extraInfoHolder.itsClusterMap = itsOrig.getPattern(); - } - if (contributorsGID[GIndex::Source::TPC].isIndexSet()) { - isStoredTPC[track.getRefTPC()] = true; - const auto& tpcOrig = recoData.getTPCTrack(contributorsGID[GIndex::TPC]); - extraInfoHolder.tpcChi2NCl = tpcOrig.getNClusters() ? tpcOrig.getChi2() / tpcOrig.getNClusters() : 0; - extraInfoHolder.tpcSignal = tpcOrig.getdEdx().dEdxTotTPC; - extraInfoHolder.tpcNClsFindable = tpcOrig.getNClusters(); - } - addToTracksTable(tracksCursor, tracksCovCursor, track, -1, src); - addToTracksExtraTable(tracksExtraCursor, extraInfoHolder); - } - if (src == GIndex::Source::ITSTPCTOF && mFillTracksITSTPC) { - auto contributorsGID = recoData.getSingleDetectorRefs(trackIndex); - const auto& track = recoData.getITSTPCTOFTrack(contributorsGID[GIndex::Source::ITSTPCTOF]); - const auto& tofMatch = recoData.getTOFMatch(contributorsGID[GIndex::Source::ITSTPCTOF]); - extraInfoHolder.tofChi2 = tofMatch.getChi2(); - const auto& tofInt = tofMatch.getLTIntegralOut(); - extraInfoHolder.tofSignal = tofInt.getTOF(0); // fixme: what id should be used here? - extraInfoHolder.length = tofInt.getL(); - // extra info from sub-tracks - if (contributorsGID[GIndex::Source::ITS].isIndexSet()) { - isStoredITS[track.getRefITS()] = true; - const auto& itsOrig = recoData.getITSTrack(contributorsGID[GIndex::ITS]); - extraInfoHolder.itsClusterMap = itsOrig.getPattern(); - } - if (contributorsGID[GIndex::Source::TPC].isIndexSet()) { - isStoredTPC[track.getRefTPC()] = true; - const auto& tpcOrig = recoData.getTPCTrack(contributorsGID[GIndex::TPC]); - extraInfoHolder.tpcChi2NCl = tpcOrig.getNClusters() ? tpcOrig.getChi2() / tpcOrig.getNClusters() : 0; - extraInfoHolder.tpcSignal = tpcOrig.getdEdx().dEdxTotTPC; - extraInfoHolder.tpcNClsFindable = tpcOrig.getNClusters(); - } - addToTracksTable(tracksCursor, tracksCovCursor, track, -1, src); - addToTracksExtraTable(tracksExtraCursor, extraInfoHolder); - } - if (src == GIndex::Source::MFT && mFillTracksMFT) { - const auto& track = tracksMFT[trackIndex.getIndex()]; - isStoredMFT[trackIndex.getIndex()] = true; - addToMFTTracksTable(mftTracksCursor, track, -1); - } - } - } + auto& trackRef = primVer2TRefs.back(); // references to unassigned tracks are at the end + // fixme: interaction time is undefined for unassigned tracks (?) + fillTrackTablesPerCollision(-1, -1, trackRef, primVerGIs, recoData, tracksCursor, tracksCovCursor, tracksExtraCursor, mftTracksCursor); - // filling collisions table + // filling collisions and tracks into tables int collisionID = 0; for (auto& vertex : primVertices) { auto& cov = vertex.getCov(); @@ -777,102 +792,8 @@ void AODProducerWorkflowDPL::run(ProcessingContext& pc) truncateFloatFraction(timeStamp.getTimeStampError() * 1E3, mCollisionPositionCov), collisionTimeMask); auto& trackRef = primVer2TRefs[collisionID]; - for (int src = GIndex::NSources; src--;) { - int start = trackRef.getFirstEntryOfSource(src); - int end = start + trackRef.getEntriesOfSource(src); - LOG(DEBUG) << " ====> Collision " << collisionID << " ; src = " << src << " : ntracks = " << end - start; - LOG(DEBUG) << "start = " << start << ", end = " << end; - for (int ti = start; ti < end; ti++) { - extraInfoHolder.tpcInnerParam = 0.f; - extraInfoHolder.flags = 0; - extraInfoHolder.itsClusterMap = 0; - extraInfoHolder.tpcNClsFindable = 0; - extraInfoHolder.tpcNClsFindableMinusFound = 0; - extraInfoHolder.tpcNClsFindableMinusCrossedRows = 0; - extraInfoHolder.tpcNClsShared = 0; - extraInfoHolder.trdPattern = 0; - extraInfoHolder.itsChi2NCl = -999.f; - extraInfoHolder.tpcChi2NCl = -999.f; - extraInfoHolder.trdChi2 = -999.f; - extraInfoHolder.tofChi2 = -999.f; - extraInfoHolder.tpcSignal = -999.f; - extraInfoHolder.trdSignal = -999.f; - extraInfoHolder.tofSignal = -999.f; - extraInfoHolder.length = -999.f; - extraInfoHolder.tofExpMom = -999.f; - extraInfoHolder.trackEtaEMCAL = -999.f; - extraInfoHolder.trackPhiEMCAL = -999.f; - auto& trackIndex = primVerGIs[ti]; - if (src == GIndex::Source::ITS && mFillTracksITS) { - const auto& track = tracksITS[trackIndex.getIndex()]; - isStoredITS[trackIndex.getIndex()] = true; - // extra info - extraInfoHolder.itsClusterMap = track.getPattern(); - // track - addToTracksTable(tracksCursor, tracksCovCursor, track, collisionID, src); - addToTracksExtraTable(tracksExtraCursor, extraInfoHolder); - } - if (src == GIndex::Source::TPC && mFillTracksTPC) { - const auto& track = tracksTPC[trackIndex.getIndex()]; - isStoredTPC[trackIndex.getIndex()] = true; - // extra info - extraInfoHolder.tpcChi2NCl = track.getNClusters() ? track.getChi2() / track.getNClusters() : 0; - extraInfoHolder.tpcSignal = track.getdEdx().dEdxTotTPC; - extraInfoHolder.tpcNClsFindable = track.getNClusters(); - // track - addToTracksTable(tracksCursor, tracksCovCursor, track, collisionID, src); - addToTracksExtraTable(tracksExtraCursor, extraInfoHolder); - } - if (src == GIndex::Source::ITSTPC && mFillTracksITSTPC) { - const auto& track = tracksITSTPC[trackIndex.getIndex()]; - auto contributorsGID = recoData.getSingleDetectorRefs(trackIndex); - // extra info from sub-tracks - if (contributorsGID[GIndex::Source::ITS].isIndexSet()) { - isStoredITS[track.getRefITS()] = true; - const auto& itsOrig = recoData.getITSTrack(contributorsGID[GIndex::ITS]); - extraInfoHolder.itsClusterMap = itsOrig.getPattern(); - } - if (contributorsGID[GIndex::Source::TPC].isIndexSet()) { - isStoredTPC[track.getRefTPC()] = true; - const auto& tpcOrig = recoData.getTPCTrack(contributorsGID[GIndex::TPC]); - extraInfoHolder.tpcChi2NCl = tpcOrig.getNClusters() ? tpcOrig.getChi2() / tpcOrig.getNClusters() : 0; - extraInfoHolder.tpcSignal = tpcOrig.getdEdx().dEdxTotTPC; - extraInfoHolder.tpcNClsFindable = tpcOrig.getNClusters(); - } - addToTracksTable(tracksCursor, tracksCovCursor, track, collisionID, src); - addToTracksExtraTable(tracksExtraCursor, extraInfoHolder); - } - if (src == GIndex::Source::ITSTPCTOF && mFillTracksITSTPC) { - auto contributorsGID = recoData.getSingleDetectorRefs(trackIndex); - const auto& track = recoData.getITSTPCTOFTrack(contributorsGID[GIndex::Source::ITSTPCTOF]); - const auto& tofMatch = recoData.getTOFMatch(contributorsGID[GIndex::Source::ITSTPCTOF]); - extraInfoHolder.tofChi2 = tofMatch.getChi2(); - const auto& tofInt = tofMatch.getLTIntegralOut(); - extraInfoHolder.tofSignal = tofInt.getTOF(0); // fixme: what id should be used here? - extraInfoHolder.length = tofInt.getL(); - // extra info from sub-tracks - if (contributorsGID[GIndex::Source::ITS].isIndexSet()) { - isStoredITS[track.getRefITS()] = true; - const auto& itsOrig = recoData.getITSTrack(contributorsGID[GIndex::ITS]); - extraInfoHolder.itsClusterMap = itsOrig.getPattern(); - } - if (contributorsGID[GIndex::Source::TPC].isIndexSet()) { - isStoredTPC[track.getRefTPC()] = true; - const auto& tpcOrig = recoData.getTPCTrack(contributorsGID[GIndex::TPC]); - extraInfoHolder.tpcChi2NCl = tpcOrig.getNClusters() ? tpcOrig.getChi2() / tpcOrig.getNClusters() : 0; - extraInfoHolder.tpcSignal = tpcOrig.getdEdx().dEdxTotTPC; - extraInfoHolder.tpcNClsFindable = tpcOrig.getNClusters(); - } - addToTracksTable(tracksCursor, tracksCovCursor, track, collisionID, src); - addToTracksExtraTable(tracksExtraCursor, extraInfoHolder); - } - if (src == GIndex::Source::MFT && mFillTracksMFT) { - const auto& track = tracksMFT[trackIndex.getIndex()]; - isStoredMFT[trackIndex.getIndex()] = true; - addToMFTTracksTable(mftTracksCursor, track, collisionID); - } - } - } + // passing interaction time in [ps] + fillTrackTablesPerCollision(collisionID, tsTimeStamp * 1E3, trackRef, primVerGIs, recoData, tracksCursor, tracksCovCursor, tracksExtraCursor, mftTracksCursor); collisionID++; } @@ -892,14 +813,11 @@ void AODProducerWorkflowDPL::run(ProcessingContext& pc) // filling mc particles table TripletsMap_t toStore; fillMCParticlesTable(mcReader, mcParticlesCursor, - tracksITSMCTruth, isStoredITS, - tracksMFTMCTruth, isStoredMFT, - tracksTPCMCTruth, isStoredTPC, - toStore, mccolid_to_eventandsource); - - isStoredITS.clear(); - isStoredMFT.clear(); - isStoredTPC.clear(); + tracksITSMCTruth, + tracksMFTMCTruth, + tracksTPCMCTruth, + toStore, + mccolid_to_eventandsource); // ------------------------------------------------------ // filling track labels @@ -910,106 +828,96 @@ void AODProducerWorkflowDPL::run(ProcessingContext& pc) // bit 15 -- isFake() == true // labelID = std::numeric_limits::max() -- label is not set - uint32_t labelID; - uint32_t labelITS; - uint32_t labelTPC; - uint16_t labelMask; - uint8_t mftLabelMask; - // need to go through labels in the same order as for tracks + // todo: fill labels in the same way as tracks, using reco container for (auto& trackRef : primVer2TRefs) { for (int src = GIndex::NSources; src--;) { int start = trackRef.getFirstEntryOfSource(src); int end = start + trackRef.getEntriesOfSource(src); for (int ti = start; ti < end; ti++) { auto& trackIndex = primVerGIs[ti]; - labelID = std::numeric_limits::max(); - labelITS = labelID; - labelTPC = labelID; - labelMask = 0; - mftLabelMask = 0; + MCLabels labelHolder; // its labels - if (src == GIndex::Source::ITS && mFillTracksITS) { + if (src == GIndex::Source::ITS) { auto& mcTruthITS = tracksITSMCTruth[trackIndex.getIndex()]; if (mcTruthITS.isValid()) { - labelID = toStore.at(Triplet_t(mcTruthITS.getSourceID(), mcTruthITS.getEventID(), mcTruthITS.getTrackID())); + labelHolder.labelID = toStore.at(Triplet_t(mcTruthITS.getSourceID(), mcTruthITS.getEventID(), mcTruthITS.getTrackID())); } if (mcTruthITS.isFake()) { - labelMask |= (0x1 << 15); + labelHolder.labelMask |= (0x1 << 15); } if (mcTruthITS.isNoise()) { - labelMask |= (0x1 << 14); + labelHolder.labelMask |= (0x1 << 14); } mcTrackLabelCursor(0, - labelID, - labelMask); + labelHolder.labelID, + labelHolder.labelMask); } // tpc labels - if (src == GIndex::Source::TPC && mFillTracksTPC) { + if (src == GIndex::Source::TPC) { auto& mcTruthTPC = tracksTPCMCTruth[trackIndex.getIndex()]; if (mcTruthTPC.isValid()) { - labelID = toStore.at(Triplet_t(mcTruthTPC.getSourceID(), mcTruthTPC.getEventID(), mcTruthTPC.getTrackID())); + labelHolder.labelID = toStore.at(Triplet_t(mcTruthTPC.getSourceID(), mcTruthTPC.getEventID(), mcTruthTPC.getTrackID())); } if (mcTruthTPC.isFake()) { - labelMask |= (0x1 << 15); + labelHolder.labelMask |= (0x1 << 15); } if (mcTruthTPC.isNoise()) { - labelMask |= (0x1 << 14); + labelHolder.labelMask |= (0x1 << 14); } mcTrackLabelCursor(0, - labelID, - labelMask); + labelHolder.labelID, + labelHolder.labelMask); } - // its-tpc labels and its-tpc-tof labels + // its-tpc and its-tpc-tof labels // todo: // probably need to store both its and tpc labels // for now filling only TPC label - if ((src == GIndex::Source::ITSTPC || src == GIndex::Source::ITSTPCTOF) && mFillTracksITSTPC) { + if ((src == GIndex::Source::ITSTPC || src == GIndex::Source::ITSTPCTOF)) { auto contributorsGID = recoData.getSingleDetectorRefs(trackIndex); auto& mcTruthITS = tracksITSMCTruth[contributorsGID[GIndex::Source::ITS].getIndex()]; auto& mcTruthTPC = tracksTPCMCTruth[contributorsGID[GIndex::Source::TPC].getIndex()]; // its-contributor label if (contributorsGID[GIndex::Source::ITS].isIndexSet()) { if (mcTruthITS.isValid()) { - labelITS = toStore.at(Triplet_t(mcTruthITS.getSourceID(), mcTruthITS.getEventID(), mcTruthITS.getTrackID())); + labelHolder.labelITS = toStore.at(Triplet_t(mcTruthITS.getSourceID(), mcTruthITS.getEventID(), mcTruthITS.getTrackID())); } } if (contributorsGID[GIndex::Source::TPC].isIndexSet()) { if (mcTruthTPC.isValid()) { - labelTPC = toStore.at(Triplet_t(mcTruthTPC.getSourceID(), mcTruthTPC.getEventID(), mcTruthTPC.getTrackID())); + labelHolder.labelTPC = toStore.at(Triplet_t(mcTruthTPC.getSourceID(), mcTruthTPC.getEventID(), mcTruthTPC.getTrackID())); } } - labelID = labelTPC; + labelHolder.labelID = labelHolder.labelTPC; if (mcTruthITS.isFake() || mcTruthTPC.isFake()) { - labelMask |= (0x1 << 15); + labelHolder.labelMask |= (0x1 << 15); } if (mcTruthITS.isNoise() || mcTruthTPC.isNoise()) { - labelMask |= (0x1 << 14); + labelHolder.labelMask |= (0x1 << 14); } - if (labelITS != labelTPC) { + if (labelHolder.labelITS != labelHolder.labelTPC) { LOG(DEBUG) << "ITS-TPC MCTruth: labelIDs do not match at " << trackIndex.getIndex(); - labelMask |= (0x1 << 13); + labelHolder.labelMask |= (0x1 << 13); } mcTrackLabelCursor(0, - labelID, - labelMask); + labelHolder.labelID, + labelHolder.labelMask); } // mft labels - // todo: move to a separate table - if (src == GIndex::Source::MFT && mFillTracksMFT) { + if (src == GIndex::Source::MFT) { auto& mcTruthMFT = tracksMFTMCTruth[trackIndex.getIndex()]; if (mcTruthMFT.isValid()) { - labelID = toStore.at(Triplet_t(mcTruthMFT.getSourceID(), mcTruthMFT.getEventID(), mcTruthMFT.getTrackID())); + labelHolder.labelID = toStore.at(Triplet_t(mcTruthMFT.getSourceID(), mcTruthMFT.getEventID(), mcTruthMFT.getTrackID())); } if (mcTruthMFT.isFake()) { - mftLabelMask |= (0x1 << 7); + labelHolder.mftLabelMask |= (0x1 << 7); } if (mcTruthMFT.isNoise()) { - mftLabelMask |= (0x1 << 6); + labelHolder.mftLabelMask |= (0x1 << 6); } mcMFTTrackLabelCursor(0, - labelID, - mftLabelMask); + labelHolder.labelID, + labelHolder.mftLabelMask); } } } @@ -1039,6 +947,7 @@ DataProcessorSpec getAODProducerWorkflowSpec(GID::mask_t src, bool useMC, bool f dataRequest->requestSecondaryVertertices(useMC); } dataRequest->requestFT0RecPoints(false); + dataRequest->requestClusters(GIndex::getSourcesMask("TPC"), false); outputs.emplace_back(OutputLabel{"O2bc"}, "AOD", "BC", 0, Lifetime::Timeframe); outputs.emplace_back(OutputLabel{"O2collision"}, "AOD", "COLLISION", 0, Lifetime::Timeframe); @@ -1062,12 +971,8 @@ DataProcessorSpec getAODProducerWorkflowSpec(GID::mask_t src, bool useMC, bool f "aod-producer-workflow", dataRequest->inputs, outputs, - AlgorithmSpec{adaptFromTask(dataRequest, fillSVertices)}, + AlgorithmSpec{adaptFromTask(src, dataRequest, fillSVertices)}, Options{ - ConfigParamSpec{"fill-tracks-its", VariantType::Int, 1, {"Fill ITS tracks into tracks table"}}, - ConfigParamSpec{"fill-tracks-mft", VariantType::Int, 1, {"Fill MFT tracks into mfttracks table"}}, - ConfigParamSpec{"fill-tracks-tpc", VariantType::Int, 0, {"Fill TPC tracks into tracks table"}}, - ConfigParamSpec{"fill-tracks-its-tpc", VariantType::Int, 1, {"Fill ITS-TPC tracks into tracks table"}}, ConfigParamSpec{"aod-timeframe-id", VariantType::Int64, -1L, {"Set timeframe number"}}, ConfigParamSpec{"enable-truncation", VariantType::Int, 1, {"Truncation parameter: 1 -- on, != 1 -- off"}}, ConfigParamSpec{"reco-mctracks-only", VariantType::Int, 0, {"Store only reconstructed MC tracks and their mothers/daughters. 0 -- off, != 0 -- on"}}}}; diff --git a/Detectors/AOD/src/aod-producer-workflow.cxx b/Detectors/AOD/src/aod-producer-workflow.cxx index b5514f5f8c4db..a7639580b8645 100644 --- a/Detectors/AOD/src/aod-producer-workflow.cxx +++ b/Detectors/AOD/src/aod-producer-workflow.cxx @@ -27,6 +27,7 @@ void customize(std::vector& workflowOptions) {"disable-root-input", o2::framework::VariantType::Bool, false, {"disable root-files input reader"}}, {"disable-root-output", o2::framework::VariantType::Bool, false, {"disable root-files output writer"}}, {"disable-mc", o2::framework::VariantType::Bool, false, {"disable MC propagation"}}, + {"info-sources", VariantType::String, std::string{GID::ALL}, {"comma-separated list of sources to use"}}, {"fill-svertices", o2::framework::VariantType::Bool, false, {"fill V0 table"}}, {"configKeyValues", VariantType::String, "", {"Semicolon separated key=value strings ..."}}}; @@ -41,14 +42,13 @@ WorkflowSpec defineDataProcessing(ConfigContext const& configcontext) auto fillSVertices = configcontext.options().get("fill-svertices"); auto useMC = !configcontext.options().get("disable-mc"); - GID::mask_t src = GID::getSourcesMask("ITS,MFT,TPC,ITS-TPC,ITS-TPC-TOF,TPC-TOF,FT0"); // asking only for currently processed sources - GID::mask_t dummy, srcClus = GID::includesDet(DetID::TOF, src) ? GID::getSourceMask(GID::TOF) : dummy; + GID::mask_t allowedSrc = GID::getSourcesMask("ITS,MFT,TPC,ITS-TPC,ITS-TPC-TOF,TPC-TOF,FT0,TPC-TRD,ITS-TPC-TRD"); + GID::mask_t src = allowedSrc & GID::getSourcesMask(configcontext.options().get("info-sources")); WorkflowSpec specs; - specs.emplace_back(o2::aodproducer::getAODProducerWorkflowSpec(src, useMC, fillSVertices)); - o2::globaltracking::InputHelper::addInputSpecs(configcontext, specs, srcClus, src, src, useMC, srcClus); + o2::globaltracking::InputHelper::addInputSpecs(configcontext, specs, src, src, src, useMC, src); o2::globaltracking::InputHelper::addInputSpecsPVertex(configcontext, specs, useMC); if (fillSVertices) { o2::globaltracking::InputHelper::addInputSpecsSVertex(configcontext, specs); diff --git a/Detectors/GlobalTracking/src/MatchTOF.cxx b/Detectors/GlobalTracking/src/MatchTOF.cxx index c3fe595cec87e..6bca22b92a799 100644 --- a/Detectors/GlobalTracking/src/MatchTOF.cxx +++ b/Detectors/GlobalTracking/src/MatchTOF.cxx @@ -626,7 +626,7 @@ void MatchTOF::doMatching(int sec) // set event indexes (to be checked) evIdx eventIndexTOFCluster(trefTOF.getEntryInTree(), mTOFClusSectIndexCache[indices[0]][itof]); evGIdx eventIndexTracks(mCurrTracksTreeEntry, {uint32_t(mTracksSectIndexCache[type][indices[0]][itrk]), o2::dataformats::GlobalTrackID::ITSTPC}); - mMatchedTracksPairs.emplace_back(eventIndexTOFCluster, chi2, trkLTInt[iPropagation], eventIndexTracks, type); // TODO: check if this is correct! + mMatchedTracksPairs.emplace_back(eventIndexTOFCluster, mTOFClusWork[cacheTOF[itof]].getTime(), chi2, trkLTInt[iPropagation], eventIndexTracks, type); // TODO: check if this is correct! } } } @@ -939,7 +939,7 @@ void MatchTOF::doMatchingForTPC(int sec) // set event indexes (to be checked) evIdx eventIndexTOFCluster(trefTOF.getEntryInTree(), mTOFClusSectIndexCache[indices[0]][itof]); evGIdx eventIndexTracks(mCurrTracksTreeEntry, {uint32_t(mTracksSectIndexCache[trkType::UNCONS][indices[0]][itrk]), o2::dataformats::GlobalTrackID::TPC}); - mMatchedTracksPairs.emplace_back(eventIndexTOFCluster, chi2, trkLTInt[ibc][iPropagation], eventIndexTracks, trkType::UNCONS, resZ / vdrift * side, trefTOF.getZ()); // TODO: check if this is correct! + mMatchedTracksPairs.emplace_back(eventIndexTOFCluster, mTOFClusWork[cacheTOF[itof]].getTime(), chi2, trkLTInt[ibc][iPropagation], eventIndexTracks, trkType::UNCONS, resZ / vdrift * side, trefTOF.getZ()); // TODO: check if this is correct! } } }