From ff118eb431354e738a827e1c59501f94a0226986 Mon Sep 17 00:00:00 2001 From: Felix Schlepper Date: Thu, 27 Feb 2025 17:32:46 +0100 Subject: [PATCH 01/10] TRD: add optional(default=off) extra table for PID studies Signed-off-by: Felix Schlepper --- .../AODProducerWorkflowSpec.h | 16 ++- Detectors/AOD/src/AODProducerWorkflowSpec.cxx | 130 ++++++++++++++++-- Detectors/AOD/src/aod-producer-workflow.cxx | 4 +- .../include/Framework/AnalysisDataModel.h | 29 +++- 4 files changed, 159 insertions(+), 20 deletions(-) diff --git a/Detectors/AOD/include/AODProducerWorkflow/AODProducerWorkflowSpec.h b/Detectors/AOD/include/AODProducerWorkflow/AODProducerWorkflowSpec.h index 959aed28cab6b..669cd204c1412 100644 --- a/Detectors/AOD/include/AODProducerWorkflow/AODProducerWorkflowSpec.h +++ b/Detectors/AOD/include/AODProducerWorkflow/AODProducerWorkflowSpec.h @@ -19,6 +19,8 @@ #include "DataFormatsGlobalTracking/RecoContainer.h" #include "DataFormatsPHOS/Cell.h" #include "DataFormatsTRD/TrackTRD.h" +#include "TRDBase/PadCalibrationsAliases.h" +#include "DataFormatsTRD/NoiseCalibration.h" #include "DetectorsBase/GRPGeomHelper.h" #include "DetectorsBase/Propagator.h" #include "Framework/DataProcessorSpec.h" @@ -215,7 +217,7 @@ enum struct AODProducerStreamerFlags : uint8_t { class AODProducerWorkflowDPL : public Task { public: - AODProducerWorkflowDPL(GID::mask_t src, std::shared_ptr dataRequest, std::shared_ptr gr, bool enableSV, bool useMC = true, bool enableFITextra = false) : mUseMC(useMC), mEnableSV(enableSV), mEnableFITextra(enableFITextra), mInputSources(src), mDataRequest(dataRequest), mGGCCDBRequest(gr) {} + AODProducerWorkflowDPL(GID::mask_t src, std::shared_ptr dataRequest, std::shared_ptr gr, bool enableSV, bool useMC = true, bool enableFITextra = false, bool enableTRDextra = false) : mUseMC(useMC), mEnableSV(enableSV), mEnableFITextra(enableFITextra), mEnableTRDextra(enableTRDextra), mInputSources(src), mDataRequest(dataRequest), mGGCCDBRequest(gr) {} ~AODProducerWorkflowDPL() override = default; void init(InitContext& ic) final; void run(ProcessingContext& pc) final; @@ -245,6 +247,9 @@ class AODProducerWorkflowDPL : public Task o2::dataformats::MeanVertexObject mVtx; float mMinPropR{o2::constants::geom::XTPCInnerRef + 0.1f}; + const o2::trd::LocalGainFactor* mTRDLocalGain; // TRD local gain factors from krypton calibration + const o2::trd::NoiseStatusMCM* mTRDNoiseMap; // TRD noise map + std::unordered_set mGIDUsedBySVtx; std::unordered_set mGIDUsedByStr; @@ -255,6 +260,7 @@ class AODProducerWorkflowDPL : public Task bool mUseMC = true; bool mEnableSV = true; // enable secondary vertices bool mEnableFITextra = false; + bool mEnableTRDextra = false; bool mFieldON = false; const float cSpeed = 0.029979246f; // speed of light in TOF units @@ -517,6 +523,9 @@ class AODProducerWorkflowDPL : public Task template void addToTracksQATable(TracksQACursorType& tracksQACursor, TrackQA& trackQAInfoHolder); + template + void addToTRDsExtra(const o2::globaltracking::RecoContainer& recoData, TRDsExtraCursorType& trdExtraCursor, const GIndex& trkIdx, int trkTableIdx); + template void addToMFTTracksTable(mftTracksCursorType& mftTracksCursor, AmbigMFTTracksCursorType& ambigMFTTracksCursor, GIndex trackID, const o2::globaltracking::RecoContainer& data, int collisionID, @@ -536,7 +545,7 @@ class AODProducerWorkflowDPL : public Task // helper for track tables // * fills tables collision by collision // * interaction time is for TOF information - template void fillTrackTablesPerCollision(int collisionID, @@ -548,6 +557,7 @@ class AODProducerWorkflowDPL : public Task TracksCovCursorType& tracksCovCursor, TracksExtraCursorType& tracksExtraCursor, TracksQACursorType& tracksQACursor, + TRDsExtraCursorType& trdsExtraCursor, AmbigTracksCursorType& ambigTracksCursor, MFTTracksCursorType& mftTracksCursor, MFTTracksCovCursorType& mftTracksCovCursor, @@ -672,7 +682,7 @@ class AODProducerWorkflowDPL : public Task }; /// create a processor spec -framework::DataProcessorSpec getAODProducerWorkflowSpec(GID::mask_t src, bool enableSV, bool enableST, bool useMC, bool CTPConfigPerRun, bool enableFITextra); +framework::DataProcessorSpec getAODProducerWorkflowSpec(GID::mask_t src, bool enableSV, bool enableST, bool useMC, bool CTPConfigPerRun, bool enableFITextra, bool enableTRDextra); // helper interface for calo cells to "befriend" emcal and phos cells class CellHelper diff --git a/Detectors/AOD/src/AODProducerWorkflowSpec.cxx b/Detectors/AOD/src/AODProducerWorkflowSpec.cxx index c12b614960554..9d348571b125b 100644 --- a/Detectors/AOD/src/AODProducerWorkflowSpec.cxx +++ b/Detectors/AOD/src/AODProducerWorkflowSpec.cxx @@ -33,7 +33,6 @@ #include "DataFormatsPHOS/TriggerRecord.h" #include "DataFormatsPHOS/EventHandler.h" #include "DataFormatsTPC/TrackTPC.h" -#include "DataFormatsTRD/TriggerRecord.h" #include "DataFormatsZDC/BCRecData.h" #include "DataFormatsZDC/ZDCEnergy.h" #include "DataFormatsZDC/ZDCTDCData.h" @@ -45,6 +44,9 @@ #include "CommonDataFormat/InteractionRecord.h" #include "DataFormatsTRD/TrackTRD.h" #include "DataFormatsTRD/TrackTriggerRecord.h" +#include "DataFormatsTRD/CalibratedTracklet.h" +#include "DataFormatsTRD/TriggerRecord.h" +#include "DataFormatsTRD/Tracklet64.h" #include "DataFormatsGlobalTracking/RecoContainer.h" #include "Framework/AnalysisDataModel.h" #include "Framework/ConfigParamRegistry.h" @@ -387,6 +389,79 @@ void AODProducerWorkflowDPL::addToTracksQATable(TracksQACursorType& tracksQACurs trackQAInfoHolder.dTofdZ); } +template +void AODProducerWorkflowDPL::addToTRDsExtra(const o2::globaltracking::RecoContainer& recoData, TRDsExtraCursorType& trdExtraCursor, const GIndex& trkIdx, int trkTableIdx) +{ + static int q0s[6] = {-1}, q1s[6] = {-1}, q2s[6] = {-1}; + static float q0sCor[6] = {-1}, q1sCor[6] = {-1}, q2sCor[6] = {-1}; + static float ttgls[6] = {-999}, tphis[6] = {-999}; + + auto contributorsGID = recoData.getSingleDetectorRefs(trkIdx); + if (!contributorsGID[GIndex::Source::TRD].isIndexSet()) { // should be redunant + return; + } + const auto& trk = recoData.getTrack(contributorsGID[GIndex::Source::TRD]); + auto trkC = trk; + const auto& trklets = recoData.getTRDTracklets(); + const auto& ctrklets = recoData.getTRDCalibratedTracklets(); + for (int iLay{0}; iLay < 6; ++iLay) { + q0s[iLay] = q1s[iLay] = q2s[iLay] = -1; + q0sCor[iLay] = q1sCor[iLay] = q2sCor[iLay] = -1; + tphis[iLay] = ttgls[iLay] = -999; + auto trkltId = trk.getTrackletIndex(iLay); + if (trkltId < 0) { + continue; + } + const auto& tracklet = trklets[trkltId]; + if (mTRDNoiseMap->isTrackletFromNoisyMCM(tracklet)) { + continue; + } + // we need to propagate into TRD local system + int trkltDet = tracklet.getDetector(); + int trkltSec = trkltDet / 30; + if (trkltSec != o2::math_utils::angle2Sector(trkC.getAlpha())) { + if (!trkC.rotate(o2::math_utils::sector2Angle(trkltSec))) { + break; + } + } + if (!o2::base::Propagator::Instance()->PropagateToXBxByBz(trkC, ctrklets[trkltId].getX(), o2::base::Propagator::MAX_SIN_PHI, o2::base::Propagator::MAX_STEP, mMatCorr)) { + break; + } + + auto tphi = trkC.getSnp() / std::sqrt((1.f - trkC.getSnp()) * (1.f + trkC.getSnp())); + auto trackletLength = std::sqrt(1.f + tphi * tphi + trkC.getTgl() * trkC.getTgl()); + float cor = mTRDLocalGain->getValue(tracklet.getHCID() / 2, tracklet.getPadCol(), tracklet.getPadRow()) * trackletLength; + q0s[iLay] = tracklet.getQ0(); + q1s[iLay] = tracklet.getQ1(); + q2s[iLay] = tracklet.getQ2(); + q0sCor[iLay] = (float)tracklet.getQ0() / cor; + q1sCor[iLay] = (float)tracklet.getQ1() / cor; + q2sCor[iLay] = (float)tracklet.getQ2() / cor; + ttgls[iLay] = trkC.getTgl(); + tphis[iLay] = tphi; + + // z-row merging + if (trk.getIsCrossingNeighbor(iLay) && trk.getHasNeighbor()) { + for (const auto& trklt : trklets) { + if (tracklet.getTrackletWord() == trklt.getTrackletWord()) { + continue; + } + if (std::abs(tracklet.getPadCol() - trklt.getPadCol()) <= 1 && std::abs(tracklet.getPadRow() - trklt.getPadRow()) == 1) { + cor = mTRDLocalGain->getValue(trklt.getHCID() / 2, trklt.getPadCol(), trklt.getPadRow()) * trackletLength; + q0s[iLay] += trklt.getQ0(); + q1s[iLay] += trklt.getQ1(); + q2s[iLay] += trklt.getQ2(); + q0sCor[iLay] += (float)trklt.getQ0() / cor; + q1sCor[iLay] += (float)trklt.getQ1() / cor; + q2sCor[iLay] += (float)trklt.getQ2() / cor; + } + } + } + } + + trdExtraCursor(trkTableIdx, q0s, q1s, q2s, q0sCor, q1sCor, q2sCor, ttgls, tphis); +} + template void AODProducerWorkflowDPL::addToMFTTracksTable(mftTracksCursorType& mftTracksCursor, AmbigMFTTracksCursorType& ambigMFTTracksCursor, GIndex trackID, const o2::globaltracking::RecoContainer& data, int collisionID, @@ -428,7 +503,7 @@ void AODProducerWorkflowDPL::addToMFTTracksTable(mftTracksCursorType& mftTracksC } } -template void AODProducerWorkflowDPL::fillTrackTablesPerCollision(int collisionID, @@ -440,6 +515,7 @@ void AODProducerWorkflowDPL::fillTrackTablesPerCollision(int collisionID, TracksCovCursorType& tracksCovCursor, TracksExtraCursorType& tracksExtraCursor, TracksQACursorType& tracksQACursor, + TRDsExtraCursor& trdsExtraCursor, AmbigTracksCursorType& ambigTracksCursor, MFTTracksCursorType& mftTracksCursor, MFTTracksCovCursorType& mftTracksCovCursor, @@ -538,6 +614,10 @@ void AODProducerWorkflowDPL::fillTrackTablesPerCollision(int collisionID, } addToTracksExtraTable(tracksExtraCursor, extraInfoHolder); + if (mEnableTRDextra && trackIndex.includesDet(GIndex::Source::TRD)) { + addToTRDsExtra(data, trdsExtraCursor, trackIndex, mTableTrID); + } + // collecting table indices of barrel tracks for V0s table if (extraInfoHolder.bcSlice[0] >= 0 && collisionID < 0) { ambigTracksCursor(mTableTrID, extraInfoHolder.bcSlice); @@ -1110,7 +1190,7 @@ void AODProducerWorkflowDPL::fillMCTrackLabelsTable(MCTrackLabelCursorType& mcTr if (!needToStore(mGIDToTableID)) { continue; } - if (mcTruth.isValid()) { // if not set, -1 will be stored + if (mcTruth.isValid()) { // if not set, -1 will be stored labelHolder.labelID = (mToStore[mcTruth.getSourceID()][mcTruth.getEventID()])[mcTruth.getTrackID()]; // defined by TPC if it contributes, otherwise: by ITS if (mcTruth.isFake()) { labelHolder.labelMask |= (0x1 << 15); @@ -1832,11 +1912,8 @@ void AODProducerWorkflowDPL::run(ProcessingContext& pc) auto trackedV0Cursor = createTableCursor(pc); auto tracked3BodyCurs = createTableCursor(pc); auto fddCursor = createTableCursor(pc); - auto fddExtraCursor = createTableCursor(pc); auto ft0Cursor = createTableCursor(pc); - auto ft0ExtraCursor = createTableCursor(pc); auto fv0aCursor = createTableCursor(pc); - auto fv0aExtraCursor = createTableCursor(pc); auto fwdTracksCursor = createTableCursor(pc); auto fwdTracksCovCursor = createTableCursor(pc); auto fwdTrkClsCursor = createTableCursor(pc); @@ -1857,6 +1934,19 @@ void AODProducerWorkflowDPL::run(ProcessingContext& pc) auto cpvClustersCursor = createTableCursor(pc); auto originCursor = createTableCursor(pc); + /// Extra tables + o2::framework::Produces ft0ExtraCursor; + o2::framework::Produces fddExtraCursor; + o2::framework::Produces fv0aExtraCursor; + if (mEnableFITextra) { + ft0ExtraCursor = createTableCursor(pc); + fddExtraCursor = createTableCursor(pc); + fv0aExtraCursor = createTableCursor(pc); + } + o2::framework::Produces trdExtraCursor; + if (mEnableTRDextra) { + trdExtraCursor = createTableCursor(pc); + } // Declare MC cursors type without adding the output for a table o2::framework::Produces mcColLabelsCursor; o2::framework::Produces mcCollisionsCursor; @@ -2199,7 +2289,7 @@ void AODProducerWorkflowDPL::run(ProcessingContext& pc) // so that all unassigned tracks are stored in the beginning of the table together auto& trackRef = primVer2TRefs.back(); // references to unassigned tracks are at the end // fixme: interaction time is undefined for unassigned tracks (?) - fillTrackTablesPerCollision(-1, std::uint64_t(-1), trackRef, primVerGIs, recoData, tracksCursor, tracksCovCursor, tracksExtraCursor, tracksQACursor, + fillTrackTablesPerCollision(-1, std::uint64_t(-1), trackRef, primVerGIs, recoData, tracksCursor, tracksCovCursor, tracksExtraCursor, tracksQACursor, trdExtraCursor, ambigTracksCursor, mftTracksCursor, mftTracksCovCursor, ambigMFTTracksCursor, fwdTracksCursor, fwdTracksCovCursor, ambigFwdTracksCursor, fwdTrkClsCursor, bcsMap); @@ -2241,7 +2331,7 @@ void AODProducerWorkflowDPL::run(ProcessingContext& pc) auto& trackRef = primVer2TRefs[collisionID]; // passing interaction time in [ps] - fillTrackTablesPerCollision(collisionID, globalBC, trackRef, primVerGIs, recoData, tracksCursor, tracksCovCursor, tracksExtraCursor, tracksQACursor, ambigTracksCursor, + fillTrackTablesPerCollision(collisionID, globalBC, trackRef, primVerGIs, recoData, tracksCursor, tracksCovCursor, tracksExtraCursor, tracksQACursor, trdExtraCursor, ambigTracksCursor, mftTracksCursor, mftTracksCovCursor, ambigMFTTracksCursor, fwdTracksCursor, fwdTracksCovCursor, ambigFwdTracksCursor, fwdTrkClsCursor, bcsMap); collisionID++; @@ -2892,6 +2982,11 @@ void AODProducerWorkflowDPL::updateTimeDependentParams(ProcessingContext& pc) mFieldON = std::abs(o2::base::Propagator::Instance()->getNominalBz()) > 0.01; pc.inputs().get("ctpconfig"); + + if (mEnableTRDextra) { + mTRDLocalGain = pc.inputs().get("trdlocalgainfactors").get(); + mTRDNoiseMap = pc.inputs().get("trdnoisemap").get(); + } } if (mPropTracks) { pc.inputs().get("meanvtx"); @@ -3103,7 +3198,7 @@ void AODProducerWorkflowDPL::endOfStream(EndOfStreamContext& /*ec*/) mStreamer.reset(); } -DataProcessorSpec getAODProducerWorkflowSpec(GID::mask_t src, bool enableSV, bool enableStrangenessTracking, bool useMC, bool CTPConfigPerRun, bool enableFITextra) +DataProcessorSpec getAODProducerWorkflowSpec(GID::mask_t src, bool enableSV, bool enableStrangenessTracking, bool useMC, bool CTPConfigPerRun, bool enableFITextra, bool enableTRDextra) { auto dataRequest = std::make_shared(); dataRequest->inputs.emplace_back("ctpconfig", "CTP", "CTPCONFIG", 0, Lifetime::Condition, ccdbParamSpec("CTP/Config/Config", CTPConfigPerRun)); @@ -3163,11 +3258,8 @@ DataProcessorSpec getAODProducerWorkflowSpec(GID::mask_t src, bool enableSV, boo OutputForTable::spec(), OutputForTable::spec(), OutputForTable::spec(), - OutputForTable::spec(), OutputForTable::spec(), - OutputForTable::spec(), OutputForTable::spec(), - OutputForTable::spec(), OutputForTable::spec(), OutputForTable::spec(), OutputForTable::spec(), @@ -3195,6 +3287,18 @@ DataProcessorSpec getAODProducerWorkflowSpec(GID::mask_t src, bool enableSV, boo OutputSpec{"AMD", "AODMetadataKeys"}, OutputSpec{"AMD", "AODMetadataVals"}}; + /// Extra tables + if (enableFITextra) { + outputs.insert(outputs.end(), + {OutputForTable::spec(), + OutputForTable::spec(), + OutputForTable::spec()}); + } + if (enableTRDextra) { + outputs.push_back(OutputForTable::spec()); + dataRequest->inputs.emplace_back("trdlocalgainfactors", "TRD", "LOCALGAINFACTORS", 0, Lifetime::Condition, ccdbParamSpec("TRD/Calib/LocalGainFactor")); + dataRequest->inputs.emplace_back("trdnoisemap", "TRD", "NOISEMAP", 0, Lifetime::Condition, ccdbParamSpec("TRD/Calib/NoiseMapMCM")); + } if (useMC) { outputs.insert(outputs.end(), {OutputForTable::spec(), @@ -3217,7 +3321,7 @@ DataProcessorSpec getAODProducerWorkflowSpec(GID::mask_t src, bool enableSV, boo "aod-producer-workflow", dataRequest->inputs, outputs, - AlgorithmSpec{adaptFromTask(src, dataRequest, ggRequest, enableSV, useMC, enableFITextra)}, + AlgorithmSpec{adaptFromTask(src, dataRequest, ggRequest, enableSV, useMC, enableFITextra, enableTRDextra)}, Options{ ConfigParamSpec{"run-number", VariantType::Int64, -1L, {"The run-number. If left default we try to get it from DPL header."}}, ConfigParamSpec{"aod-timeframe-id", VariantType::Int64, -1L, {"Set timeframe number"}}, diff --git a/Detectors/AOD/src/aod-producer-workflow.cxx b/Detectors/AOD/src/aod-producer-workflow.cxx index 81e178642e403..f6bfaae170bbd 100644 --- a/Detectors/AOD/src/aod-producer-workflow.cxx +++ b/Detectors/AOD/src/aod-producer-workflow.cxx @@ -38,6 +38,7 @@ void customize(std::vector& workflowOptions) {"disable-secondary-vertices", o2::framework::VariantType::Bool, false, {"disable filling secondary vertices"}}, {"disable-strangeness-tracker", o2::framework::VariantType::Bool, false, {"disable filling strangeness tracking"}}, {"enable-FIT-extra", o2::framework::VariantType::Bool, false, {"enable FIT extra output"}}, + {"enable-TRD-extra", o2::framework::VariantType::Bool, false, {"enable TRD extra output"}}, {"info-sources", VariantType::String, std::string{GID::ALL}, {"comma-separated list of sources to use"}}, {"configKeyValues", VariantType::String, "", {"Semicolon separated key=value strings ..."}}, {"combine-source-devices", o2::framework::VariantType::Bool, false, {"merge DPL source devices"}}, @@ -56,6 +57,7 @@ WorkflowSpec defineDataProcessing(ConfigContext const& configcontext) bool enableST = !configcontext.options().get("disable-strangeness-tracker"); bool ctpcfgperrun = !configcontext.options().get("ctpconfig-run-independent"); bool enableFITextra = configcontext.options().get("enable-FIT-extra"); + bool enableTRDextra = configcontext.options().get("enable-TRD-extra"); GID::mask_t allowedSrc = GID::getSourcesMask("ITS,MFT,MCH,MID,MCH-MID,TPC,TRD,ITS-TPC,TPC-TOF,TPC-TRD,ITS-TPC-TOF,ITS-TPC-TRD,TPC-TRD-TOF,ITS-TPC-TRD-TOF,MFT-MCH,FT0,FV0,FDD,ZDC,EMC,CTP,PHS,CPV,HMP"); GID::mask_t src = allowedSrc & GID::getSourcesMask(configcontext.options().get("info-sources")); @@ -66,7 +68,7 @@ WorkflowSpec defineDataProcessing(ConfigContext const& configcontext) } WorkflowSpec specs; - specs.emplace_back(o2::aodproducer::getAODProducerWorkflowSpec(src, enableSV, enableST, useMC, ctpcfgperrun, enableFITextra)); + specs.emplace_back(o2::aodproducer::getAODProducerWorkflowSpec(src, enableSV, enableST, useMC, ctpcfgperrun, enableFITextra, enableTRDextra)); auto srcCls = src & ~(GID::getSourceMask(GID::MCH) | GID::getSourceMask(GID::MID)); // Don't read global MID and MCH clusters (those attached to tracks are always read) auto srcMtc = src; diff --git a/Framework/Core/include/Framework/AnalysisDataModel.h b/Framework/Core/include/Framework/AnalysisDataModel.h index 8c9f323f3dcc6..b3bda4b8208dd 100644 --- a/Framework/Core/include/Framework/AnalysisDataModel.h +++ b/Framework/Core/include/Framework/AnalysisDataModel.h @@ -460,13 +460,13 @@ DECLARE_SOA_DYNAMIC_COLUMN(TPCFractionSharedCls, tpcFractionSharedCls, //! Fract return (float)tpcNClsShared / (float)tpcNClsFound; }); -DECLARE_SOA_DYNAMIC_COLUMN(TRDHasNeighbor, trdPattern, //! Flag to check if at least one tracklet of a TRD Track has a neighboring tracklet +DECLARE_SOA_DYNAMIC_COLUMN(TRDHasNeighbor, trdHasNeighbor, //! Flag to check if at least one tracklet of a TRD Track has a neighboring tracklet [](uint8_t trdPattern) -> bool { return trdPattern & o2::aod::track::HasNeighbor; }); -DECLARE_SOA_DYNAMIC_COLUMN(TRDHasCrossing, trdPattern, //! Flag to check if at least one tracklet of a TRD Track crossed a padrow +DECLARE_SOA_DYNAMIC_COLUMN(TRDHasCrossing, trdHasCrossing, //! Flag to check if at least one tracklet of a TRD Track crossed a padrow [](uint8_t trdPattern) -> bool { return trdPattern & o2::aod::track::HasCrossing; }); -DECLARE_SOA_DYNAMIC_COLUMN(TRDNLayers, trdPattern, //! Number of TRD tracklets in a Track +DECLARE_SOA_DYNAMIC_COLUMN(TRDNTracklets, trdNTracklets, //! Number of TRD tracklets in a Track [](uint8_t trdPattern) -> std::size_t { return std::bitset<6>(trdPattern).count(); }); } // namespace track @@ -579,6 +579,7 @@ DECLARE_SOA_TABLE_FULL(StoredTracksExtra_000, "TracksExtra", "AOD", "TRACKEXTRA" track::TPCCrossedRowsOverFindableCls, track::TPCFoundOverFindableCls, track::TPCFractionSharedCls, + track::TRDHasCrossing, track::TRDHasNeighbor, track::TRDNTracklets, track::TrackEtaEMCAL, track::TrackPhiEMCAL, track::TrackTime, track::TrackTimeRes); DECLARE_SOA_TABLE_FULL_VERSIONED(StoredTracksExtra_001, "TracksExtra", "AOD", "TRACKEXTRA", 1, // On disk version of TracksExtra, version 1 @@ -608,6 +609,7 @@ DECLARE_SOA_TABLE_FULL_VERSIONED(StoredTracksExtra_001, "TracksExtra", "AOD", "T track::TPCCrossedRowsOverFindableCls, track::TPCFoundOverFindableCls, track::TPCFractionSharedCls, + track::TRDHasCrossing, track::TRDHasNeighbor, track::TRDNTracklets, track::TrackEtaEMCAL, track::TrackPhiEMCAL, track::TrackTime, track::TrackTimeRes); DECLARE_SOA_TABLE_FULL_VERSIONED(StoredTracksExtra_002, "TracksExtra", "AOD", "TRACKEXTRA", 2, // On disk version of TracksExtra, version 2 @@ -637,6 +639,7 @@ DECLARE_SOA_TABLE_FULL_VERSIONED(StoredTracksExtra_002, "TracksExtra", "AOD", "T track::TPCCrossedRowsOverFindableCls, track::TPCFoundOverFindableCls, track::TPCFractionSharedCls, + track::TRDHasCrossing, track::TRDHasNeighbor, track::TRDNTracklets, track::TrackEtaEMCAL, track::TrackPhiEMCAL, track::TrackTime, track::TrackTimeRes); DECLARE_SOA_EXTENDED_TABLE(TracksExtra_000, StoredTracksExtra_000, "EXTRACKEXTRA", 0, //! Additional track information (clusters, PID, etc.) @@ -1588,6 +1591,26 @@ DECLARE_SOA_TABLE(FDDsExtra, "AOD", "FDDEXTRA", //! FDDsExtra table fdd::TimeFDDA, fdd::TimeFDDC); using FDDExtra = FDDsExtra::iterator; +namespace trd +{ +DECLARE_SOA_INDEX_COLUMN(Track, track); //! Track index +DECLARE_SOA_COLUMN(TRDQ0s, trdQ0s, int[6]); //! Q0 charge (un-corrected) +DECLARE_SOA_COLUMN(TRDQ1s, trdQ1s, int[6]); //! Q1 charge (un-corrected) +DECLARE_SOA_COLUMN(TRDQ2s, trdQ2s, int[6]); //! Q2 charge (un-corrected) +DECLARE_SOA_COLUMN(TRDQ0sCorrected, trdQ0sCorrected, float[6]); //! Q0 charge (corrected) +DECLARE_SOA_COLUMN(TRDQ1sCorrected, trdQ1sCorrected, float[6]); //! Q1 charge (corrected) +DECLARE_SOA_COLUMN(TRDQ2sCorrected, trdQ2sCorrected, float[6]); //! Q2 charge (corrected) +DECLARE_SOA_COLUMN(TRDTgls, trdTgls, float[6]); //! Local tracklet TgL +DECLARE_SOA_COLUMN(TRDPhis, trdPhis, float[6]); //! Local tracklet phi +} // namespace trd + +DECLARE_SOA_TABLE(TRDsExtra, "AOD", "TRDEXTRA", //! TRDExtra table + o2::soa::Index<>, trd::TrackId, + trd::TRDQ0s, trd::TRDQ1s, trd::TRDQ2s, + trd::TRDQ0sCorrected, trd::TRDQ1sCorrected, trd::TRDQ2sCorrected, + trd::TRDTgls, trd::TRDPhis); +using TRDExtra = TRDsExtra::iterator; + namespace v0 { DECLARE_SOA_INDEX_COLUMN_FULL(PosTrack, posTrack, int, Tracks, "_Pos"); //! Positive track From ac2bcf3e9ca567b2470208549ea26d76107b4b5f Mon Sep 17 00:00:00 2001 From: Felix Schlepper Date: Wed, 19 Mar 2025 09:10:47 +0100 Subject: [PATCH 02/10] TRD: Add QTot getter in tracklet Signed-off-by: Felix Schlepper --- DataFormats/Detectors/TRD/include/DataFormatsTRD/Tracklet64.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/DataFormats/Detectors/TRD/include/DataFormatsTRD/Tracklet64.h b/DataFormats/Detectors/TRD/include/DataFormatsTRD/Tracklet64.h index e63d8fbb5f277..c9a5edba805dd 100644 --- a/DataFormats/Detectors/TRD/include/DataFormatsTRD/Tracklet64.h +++ b/DataFormats/Detectors/TRD/include/DataFormatsTRD/Tracklet64.h @@ -190,6 +190,10 @@ class Tracklet64 return getDynamicCharge((mtrackletWord & Q2mask) >> Q2bs); } }; // no unit + GPUd() int getQTot() const + { + return getQ0() + getQ1() + getQ2(); + }; // no unit // ----- Setters for tracklet word manipulation ----- GPUd() void setTrackletWord(uint64_t trackletword) { mtrackletWord = trackletword; } From bcd0da54489ce22d23adc375f5a5f88ef88b6c6a Mon Sep 17 00:00:00 2001 From: Felix Schlepper Date: Sat, 15 Mar 2025 10:52:11 +0100 Subject: [PATCH 03/10] AOD: protoype TRD signal and eProb encoding Note to self: think about inverse-log encoding pid signal and give 8 more bits to dEdx. Signed-off-by: Felix Schlepper --- .../AODProducerWorkflowSpec.h | 2 +- Detectors/AOD/src/AODProducerWorkflowSpec.cxx | 78 +++++++++---------- .../include/Framework/AnalysisDataModel.h | 21 ++++- Framework/Core/include/Framework/DataTypes.h | 63 +++++++++++++++ 4 files changed, 120 insertions(+), 44 deletions(-) diff --git a/Detectors/AOD/include/AODProducerWorkflow/AODProducerWorkflowSpec.h b/Detectors/AOD/include/AODProducerWorkflow/AODProducerWorkflowSpec.h index 669cd204c1412..ff66772cd8c22 100644 --- a/Detectors/AOD/include/AODProducerWorkflow/AODProducerWorkflowSpec.h +++ b/Detectors/AOD/include/AODProducerWorkflow/AODProducerWorkflowSpec.h @@ -524,7 +524,7 @@ class AODProducerWorkflowDPL : public Task void addToTracksQATable(TracksQACursorType& tracksQACursor, TrackQA& trackQAInfoHolder); template - void addToTRDsExtra(const o2::globaltracking::RecoContainer& recoData, TRDsExtraCursorType& trdExtraCursor, const GIndex& trkIdx, int trkTableIdx); + void addToTRDsExtra(const o2::globaltracking::RecoContainer& recoData, TRDsExtraCursorType& trdExtraCursor, const GIndex& trkIdx, TrackExtraInfo& extraInfo, int trkTableIdx); template void addToMFTTracksTable(mftTracksCursorType& mftTracksCursor, AmbigMFTTracksCursorType& ambigMFTTracksCursor, diff --git a/Detectors/AOD/src/AODProducerWorkflowSpec.cxx b/Detectors/AOD/src/AODProducerWorkflowSpec.cxx index 9d348571b125b..1624a66f92fb2 100644 --- a/Detectors/AOD/src/AODProducerWorkflowSpec.cxx +++ b/Detectors/AOD/src/AODProducerWorkflowSpec.cxx @@ -349,7 +349,7 @@ void AODProducerWorkflowDPL::addToTracksExtraTable(TracksExtraCursorType& tracks truncateFloatFraction(extraInfoHolder.trdChi2, mTrackChi2), truncateFloatFraction(extraInfoHolder.tofChi2, mTrackChi2), truncateFloatFraction(extraInfoHolder.tpcSignal, mTrackSignal), - truncateFloatFraction(extraInfoHolder.trdSignal, mTrackSignal), + extraInfoHolder.trdSignal, // byte encoded value do not truncate truncateFloatFraction(extraInfoHolder.length, mTrackSignal), truncateFloatFraction(extraInfoHolder.tofExpMom, mTrack1Pt), truncateFloatFraction(extraInfoHolder.trackEtaEMCAL, mTrackPosEMCAL), @@ -390,24 +390,24 @@ void AODProducerWorkflowDPL::addToTracksQATable(TracksQACursorType& tracksQACurs } template -void AODProducerWorkflowDPL::addToTRDsExtra(const o2::globaltracking::RecoContainer& recoData, TRDsExtraCursorType& trdExtraCursor, const GIndex& trkIdx, int trkTableIdx) +void AODProducerWorkflowDPL::addToTRDsExtra(const o2::globaltracking::RecoContainer& recoData, TRDsExtraCursorType& trdExtraCursor, const GIndex& trkIdx, TrackExtraInfo& extraInfo, int trkTableIdx) { - static int q0s[6] = {-1}, q1s[6] = {-1}, q2s[6] = {-1}; - static float q0sCor[6] = {-1}, q1sCor[6] = {-1}, q2sCor[6] = {-1}; - static float ttgls[6] = {-999}, tphis[6] = {-999}; + const int NLAYERS = o2::trd::TrackTRD::EGPUTRDTrack::kNLayers; + int q0s[NLAYERS] = {-1}, q1s[NLAYERS] = {-1}, q2s[NLAYERS] = {-1}; + float q0sCor[NLAYERS] = {-1}, q1sCor[NLAYERS] = {-1}, q2sCor[NLAYERS] = {-1}; + float ttgls[NLAYERS] = {-999}, tphis[NLAYERS] = {-999}; auto contributorsGID = recoData.getSingleDetectorRefs(trkIdx); if (!contributorsGID[GIndex::Source::TRD].isIndexSet()) { // should be redunant return; } const auto& trk = recoData.getTrack(contributorsGID[GIndex::Source::TRD]); - auto trkC = trk; const auto& trklets = recoData.getTRDTracklets(); const auto& ctrklets = recoData.getTRDCalibratedTracklets(); - for (int iLay{0}; iLay < 6; ++iLay) { - q0s[iLay] = q1s[iLay] = q2s[iLay] = -1; - q0sCor[iLay] = q1sCor[iLay] = q2sCor[iLay] = -1; - tphis[iLay] = ttgls[iLay] = -999; + auto trkC = trk; // local copy to propagate + + float dEdx{0.}; + for (int iLay{0}; iLay < NLAYERS; ++iLay) { auto trkltId = trk.getTrackletIndex(iLay); if (trkltId < 0) { continue; @@ -421,45 +421,39 @@ void AODProducerWorkflowDPL::addToTRDsExtra(const o2::globaltracking::RecoContai int trkltSec = trkltDet / 30; if (trkltSec != o2::math_utils::angle2Sector(trkC.getAlpha())) { if (!trkC.rotate(o2::math_utils::sector2Angle(trkltSec))) { - break; + continue; } } if (!o2::base::Propagator::Instance()->PropagateToXBxByBz(trkC, ctrklets[trkltId].getX(), o2::base::Propagator::MAX_SIN_PHI, o2::base::Propagator::MAX_STEP, mMatCorr)) { - break; + continue; } auto tphi = trkC.getSnp() / std::sqrt((1.f - trkC.getSnp()) * (1.f + trkC.getSnp())); auto trackletLength = std::sqrt(1.f + tphi * tphi + trkC.getTgl() * trkC.getTgl()); float cor = mTRDLocalGain->getValue(tracklet.getHCID() / 2, tracklet.getPadCol(), tracklet.getPadRow()) * trackletLength; - q0s[iLay] = tracklet.getQ0(); - q1s[iLay] = tracklet.getQ1(); - q2s[iLay] = tracklet.getQ2(); - q0sCor[iLay] = (float)tracklet.getQ0() / cor; - q1sCor[iLay] = (float)tracklet.getQ1() / cor; - q2sCor[iLay] = (float)tracklet.getQ2() / cor; - ttgls[iLay] = trkC.getTgl(); - tphis[iLay] = tphi; - - // z-row merging - if (trk.getIsCrossingNeighbor(iLay) && trk.getHasNeighbor()) { - for (const auto& trklt : trklets) { - if (tracklet.getTrackletWord() == trklt.getTrackletWord()) { - continue; - } - if (std::abs(tracklet.getPadCol() - trklt.getPadCol()) <= 1 && std::abs(tracklet.getPadRow() - trklt.getPadRow()) == 1) { - cor = mTRDLocalGain->getValue(trklt.getHCID() / 2, trklt.getPadCol(), trklt.getPadRow()) * trackletLength; - q0s[iLay] += trklt.getQ0(); - q1s[iLay] += trklt.getQ1(); - q2s[iLay] += trklt.getQ2(); - q0sCor[iLay] += (float)trklt.getQ0() / cor; - q1sCor[iLay] += (float)trklt.getQ1() / cor; - q2sCor[iLay] += (float)trklt.getQ2() / cor; - } - } + if (mEnableTRDextra) { + q0s[iLay] = tracklet.getQ0(); + q1s[iLay] = tracklet.getQ1(); + q2s[iLay] = tracklet.getQ2(); + q0sCor[iLay] = (float)tracklet.getQ0() / cor; + q1sCor[iLay] = (float)tracklet.getQ1() / cor; + q2sCor[iLay] = (float)tracklet.getQ2() / cor; + ttgls[iLay] = trkC.getTgl(); + tphis[iLay] = tphi; } + + dEdx += (float)tracklet.getQTot() / cor; } + dEdx /= (float)trkC.getNtracklets(); + + aod::track::extensions::TRDSignalEncoding enc; + enc.setDEdx(dEdx); + enc.setEProb(trk.getSignal()); + extraInfo.trdSignal = enc.getSignal(); - trdExtraCursor(trkTableIdx, q0s, q1s, q2s, q0sCor, q1sCor, q2sCor, ttgls, tphis); + if (mEnableTRDextra) { + trdExtraCursor(trkTableIdx, q0s, q1s, q2s, q0sCor, q1sCor, q2sCor, ttgls, tphis); + } } template @@ -612,12 +606,13 @@ void AODProducerWorkflowDPL::fillTrackTablesPerCollision(int collisionID, if (!isProp) { addToTracksTable(tracksCursor, tracksCovCursor, trOrig, collisionID, aod::track::TrackIU); } - addToTracksExtraTable(tracksExtraCursor, extraInfoHolder); - if (mEnableTRDextra && trackIndex.includesDet(GIndex::Source::TRD)) { - addToTRDsExtra(data, trdsExtraCursor, trackIndex, mTableTrID); + if (trackIndex.includesDet(GIndex::Source::TRD)) { + addToTRDsExtra(data, trdsExtraCursor, trackIndex, extraInfoHolder, mTableTrID); } + addToTracksExtraTable(tracksExtraCursor, extraInfoHolder); + // collecting table indices of barrel tracks for V0s table if (extraInfoHolder.bcSlice[0] >= 0 && collisionID < 0) { ambigTracksCursor(mTableTrID, extraInfoHolder.bcSlice); @@ -2606,7 +2601,6 @@ AODProducerWorkflowDPL::TrackExtraInfo AODProducerWorkflowDPL::processBarrelTrac if (contributorsGID[GIndex::Source::TRD].isIndexSet()) { // ITS-TPC-TRD-TOF, TPC-TRD-TOF, TPC-TRD, ITS-TPC-TRD const auto& trdOrig = data.getTrack(contributorsGID[GIndex::Source::TRD]); // refitted TRD trac extraInfoHolder.trdChi2 = trdOrig.getChi2(); - extraInfoHolder.trdSignal = trdOrig.getSignal(); extraInfoHolder.trdPattern = getTRDPattern(trdOrig); if (extraInfoHolder.trackTimeRes < 0.) { // time is not set yet, this is possible only for TPC-TRD and ITS-TPC-TRD tracks, since those with TOF are set upstream // TRD is triggered: time uncertainty is within a BC diff --git a/Framework/Core/include/Framework/AnalysisDataModel.h b/Framework/Core/include/Framework/AnalysisDataModel.h index b3bda4b8208dd..6df672bab9e07 100644 --- a/Framework/Core/include/Framework/AnalysisDataModel.h +++ b/Framework/Core/include/Framework/AnalysisDataModel.h @@ -394,6 +394,23 @@ DECLARE_SOA_DYNAMIC_COLUMN(TPCDeltaTBwd, tpcDeltaTBwd, //! Delta Backward of tra } // namespace v001 +namespace v002::extensions +{ +using TRDEncoding = o2::aod::track::extensions::TRDSignalEncoding; +DECLARE_SOA_DYNAMIC_COLUMN(TRDDEdx, trdDEDx, //! TRD dEdx signal (a.u.), returns 0. if no valid signal is provided + [](float signal) -> float { + TRDEncoding enc; + enc.setSignal(signal); + return enc.getDEdx(); + }); +DECLARE_SOA_DYNAMIC_COLUMN(TRDEProb, trdEProb, //! TRD electron probability [0., 1.), returns 0. if no valid signal is provided + [](float signal) -> float { + TRDEncoding enc; + enc.setSignal(signal); + return enc.getDEdx(); + }); +} // namespace v002::extensions + DECLARE_SOA_DYNAMIC_COLUMN(HasITS, hasITS, //! Flag to check if track has a ITS match [](uint8_t detectorMap) -> bool { return detectorMap & o2::aod::track::ITS; }); DECLARE_SOA_DYNAMIC_COLUMN(HasTPC, hasTPC, //! Flag to check if track has a TPC match @@ -617,7 +634,9 @@ DECLARE_SOA_TABLE_FULL_VERSIONED(StoredTracksExtra_002, "TracksExtra", "AOD", "T track::TPCNClsFindable, track::TPCNClsFindableMinusFound, track::TPCNClsFindableMinusPID, track::TPCNClsFindableMinusCrossedRows, track::TPCNClsShared, track::v001::extensions::TPCDeltaTFwd, track::v001::extensions::TPCDeltaTBwd, track::TRDPattern, track::ITSChi2NCl, track::TPCChi2NCl, track::TRDChi2, track::TOFChi2, - track::TPCSignal, track::TRDSignal, track::Length, track::TOFExpMom, + track::TPCSignal, + track::TRDSignal, track::v002::extensions::TRDDEdx, track::v002::extensions::TRDEProb, + track::Length, track::TOFExpMom, track::PIDForTracking, track::IsPVContributor, track::HasITS, track::HasTPC, diff --git a/Framework/Core/include/Framework/DataTypes.h b/Framework/Core/include/Framework/DataTypes.h index 0a96ab49059fe..fe59773b7bbf7 100644 --- a/Framework/Core/include/Framework/DataTypes.h +++ b/Framework/Core/include/Framework/DataTypes.h @@ -76,6 +76,7 @@ enum TRDTrackPattern : uint8_t { HasNeighbor = 0x40, HasCrossing = 0x80, }; + namespace extensions { struct TPCTimeErrEncoding { @@ -121,6 +122,68 @@ struct TPCTimeErrEncoding { return static_cast(encoding.deltas.timeBackward) / timeScaler * TPCBinNS; } }; + +class TRDSignalEncoding +{ + union { + float signal{0}; + struct { + uint16_t dEdx{0}; // range [0., 512.) + uint16_t eProb{0}; // range [0., 1.) + } __attribute((packed)) data; + } encoding{0}; + static_assert(sizeof(float) == 2 * sizeof(uint16_t)); + + public: + static constexpr float dEdxMax{512.f}; + static constexpr float dEdxScaler{(1 << 16) / dEdxMax}; + static constexpr float eProbMax{1.f}; + static constexpr float eProbScaler{(1 << 16) / eProbMax}; + + void setSignal(float signal) + { + if (signal == -1. || signal == -999.f) { + // these two signal produce valid looking values + // but for backward comp. and not to confuse we mask these two specifically + encoding.signal = 0.; + } else { + encoding.signal = signal; + } + } + + void setDEdx(float v) + { + if (v >= 0. && v < dEdxMax) { + encoding.data.dEdx = static_cast(v * dEdxScaler); + } else { + encoding.data.dEdx = 0.f; + } + } + void setEProb(float v) + { + if (v >= 0. && v < eProbMax) { + encoding.data.eProb = static_cast(v * eProbScaler); + } else { + encoding.data.eProb = 0.f; + } + } + + float getSignal() const noexcept + { + return encoding.signal; + } + + float getDEdx() const noexcept + { + return static_cast(encoding.data.dEdx) / dEdxScaler; + } + + float getEProb() const noexcept + { + return static_cast(encoding.data.eProb) / eProbScaler; + } +}; + } // namespace extensions // Reference radius for extrapolated tracks From ca571804f6095da689d80b5bc3e411eb5a940b45 Mon Sep 17 00:00:00 2001 From: Felix Schlepper Date: Wed, 19 Mar 2025 09:29:28 +0100 Subject: [PATCH 04/10] AOD: Add TRD debug streamer Signed-off-by: Felix Schlepper --- .../AODProducerWorkflowSpec.h | 3 +- Detectors/AOD/src/AODProducerWorkflowSpec.cxx | 56 +++++++++++++++++++ 2 files changed, 58 insertions(+), 1 deletion(-) diff --git a/Detectors/AOD/include/AODProducerWorkflow/AODProducerWorkflowSpec.h b/Detectors/AOD/include/AODProducerWorkflow/AODProducerWorkflowSpec.h index ff66772cd8c22..98fb9e725d2fe 100644 --- a/Detectors/AOD/include/AODProducerWorkflow/AODProducerWorkflowSpec.h +++ b/Detectors/AOD/include/AODProducerWorkflow/AODProducerWorkflowSpec.h @@ -210,8 +210,9 @@ class BunchCrossings }; // end internal class // Steering bits for additional output during AOD production -enum struct AODProducerStreamerFlags : uint8_t { +enum class AODProducerStreamerFlags : uint8_t { TrackQA, + TRDExtra, }; class AODProducerWorkflowDPL : public Task diff --git a/Detectors/AOD/src/AODProducerWorkflowSpec.cxx b/Detectors/AOD/src/AODProducerWorkflowSpec.cxx index 1624a66f92fb2..21c5dba2dc69c 100644 --- a/Detectors/AOD/src/AODProducerWorkflowSpec.cxx +++ b/Detectors/AOD/src/AODProducerWorkflowSpec.cxx @@ -396,6 +396,7 @@ void AODProducerWorkflowDPL::addToTRDsExtra(const o2::globaltracking::RecoContai int q0s[NLAYERS] = {-1}, q1s[NLAYERS] = {-1}, q2s[NLAYERS] = {-1}; float q0sCor[NLAYERS] = {-1}, q1sCor[NLAYERS] = {-1}, q2sCor[NLAYERS] = {-1}; float ttgls[NLAYERS] = {-999}, tphis[NLAYERS] = {-999}; + o2::trd::Tracklet64 trkletsa[NLAYERS]; auto contributorsGID = recoData.getSingleDetectorRefs(trkIdx); if (!contributorsGID[GIndex::Source::TRD].isIndexSet()) { // should be redunant @@ -416,6 +417,7 @@ void AODProducerWorkflowDPL::addToTRDsExtra(const o2::globaltracking::RecoContai if (mTRDNoiseMap->isTrackletFromNoisyMCM(tracklet)) { continue; } + trkletsa[iLay] = tracklet; // we need to propagate into TRD local system int trkltDet = tracklet.getDetector(); int trkltSec = trkltDet / 30; @@ -454,6 +456,60 @@ void AODProducerWorkflowDPL::addToTRDsExtra(const o2::globaltracking::RecoContai if (mEnableTRDextra) { trdExtraCursor(trkTableIdx, q0s, q1s, q2s, q0sCor, q1sCor, q2sCor, ttgls, tphis); } + + if (mStreamerFlags[AODProducerStreamerFlags::TRDExtra]) { + const auto& tpctrk = recoData.getTrack(contributorsGID[GIndex::Source::TPC]); + (*mStreamer) << "trdExtra" + << "dEdx=" << dEdx + << "eProb=" << trk.getSignal() + << "q00=" << q0s[0] + << "q01=" << q0s[1] + << "q02=" << q0s[2] + << "q03=" << q0s[3] + << "q04=" << q0s[4] + << "q05=" << q0s[5] + << "q10=" << q1s[0] + << "q11=" << q1s[1] + << "q12=" << q1s[2] + << "q13=" << q1s[3] + << "q14=" << q1s[4] + << "q15=" << q1s[5] + << "q20=" << q2s[0] + << "q21=" << q2s[1] + << "q22=" << q2s[2] + << "q23=" << q2s[3] + << "q24=" << q2s[4] + << "q25=" << q2s[5] + << "q00Cor=" << q0sCor[0] + << "q01Cor=" << q0sCor[1] + << "q02Cor=" << q0sCor[2] + << "q03Cor=" << q0sCor[3] + << "q04Cor=" << q0sCor[4] + << "q05Cor=" << q0sCor[5] + << "q10Cor=" << q1sCor[0] + << "q11Cor=" << q1sCor[1] + << "q12Cor=" << q1sCor[2] + << "q13Cor=" << q1sCor[3] + << "q14Cor=" << q1sCor[4] + << "q15Cor=" << q1sCor[5] + << "q20Cor=" << q2sCor[0] + << "q21Cor=" << q2sCor[1] + << "q22Cor=" << q2sCor[2] + << "q23Cor=" << q2sCor[3] + << "q24Cor=" << q2sCor[4] + << "q25Cor=" << q2sCor[5] + << "pattern=" << getTRDPattern(trk) + << "tracklet0=" << trkletsa[0] + << "tracklet1=" << trkletsa[1] + << "tracklet2=" << trkletsa[2] + << "tracklet3=" << trkletsa[3] + << "tracklet4=" << trkletsa[4] + << "tracklet5=" << trkletsa[5] + << "tpctrk=" << tpctrk + << "trdtrk=" << trk + << "globaltrk=" << recoData.getTrack(trkIdx) + << "\n"; + } } template From 5942c9bf9465605ac97b02eae1d78a00697391cf Mon Sep 17 00:00:00 2001 From: Felix Schlepper Date: Sat, 22 Mar 2025 02:26:50 +0100 Subject: [PATCH 05/10] Common: allow to write c-style arrays in TreeStream Signed-off-by: Felix Schlepper --- Common/Utils/include/CommonUtils/TreeStream.h | 162 +++++++++--------- Common/Utils/src/TreeStream.cxx | 38 +++- Common/Utils/test/testTreeStream.cxx | 42 ++++- 3 files changed, 148 insertions(+), 94 deletions(-) diff --git a/Common/Utils/include/CommonUtils/TreeStream.h b/Common/Utils/include/CommonUtils/TreeStream.h index 2aa02f6509d2c..d1d4527ffc99d 100644 --- a/Common/Utils/include/CommonUtils/TreeStream.h +++ b/Common/Utils/include/CommonUtils/TreeStream.h @@ -19,6 +19,8 @@ #include #include #include +#include +#include #include "GPUCommonDef.h" class TBranch; @@ -39,10 +41,79 @@ namespace utils /// /// See testTreeStream.cxx for functional example /// +namespace details +{ +template +struct IsTrivialRootType { + static constexpr bool value = + std::is_same_v || // Float_t + std::is_same_v || // Double_t + std::is_same_v || std::is_same_v || // ULong64_t or ULong_t + std::is_same_v || std::is_same_v || // Long64_t or Long_t + std::is_same_v || // UInt_t + std::is_same_v || // Int_t + std::is_same_v || // UShort_t + std::is_same_v || // Short_t + std::is_same_v || // UChar_t + std::is_same_v || std::is_same_v || std::is_same_v; // Char_t, int8_t, or Bool_t +}; + +template +struct IsTrivialRootType { + static constexpr bool value = IsTrivialRootType::value; +}; + +template +struct IsTrivialRootType { + static constexpr bool value = IsTrivialRootType::value; +}; + +template +concept TrivialRootType = IsTrivialRootType::value; + +template +concept ComplexRootType = !IsTrivialRootType::value; + +template +static constexpr char getRootTypeCode() +{ + if constexpr (std::is_array_v) { + return getRootTypeCode>(); + } else if constexpr (std::is_same_v) { + return 'F'; + } else if constexpr (std::is_same_v) { + return 'D'; + } else if constexpr (std::is_same_v || + std::is_same_v) { + return 'l'; + } else if constexpr (std::is_same_v || + std::is_same_v) { + return 'L'; + } else if constexpr (std::is_same_v) { + return 'i'; + } else if constexpr (std::is_same_v) { + return 'I'; + } else if constexpr (std::is_same_v) { + return 's'; + } else if constexpr (std::is_same_v) { + return 'S'; + } else if constexpr (std::is_same_v) { + return 'b'; + } else if constexpr (std::is_same_v || + std::is_same_v || + std::is_same_v) { + return 'B'; + } else { + static_assert(false, "unsupported type!"); + } +} +} // namespace details + class TreeStream { public: struct TreeDataElement { + int arsize = 1; ///< size of array char type = 0; ///< type of data element const TClass* cls = nullptr; ///< data type pointer const void* ptr = nullptr; ///< pointer to element @@ -64,87 +135,10 @@ class TreeStream void setID(int id) { mID = id; } int getID() const { return mID; } - TreeStream& operator<<(const Bool_t& b) - { - CheckIn('B', &b); - return *this; - } - - TreeStream& operator<<(const Char_t& c) - { - CheckIn('B', &c); - return *this; - } - - TreeStream& operator<<(const int8_t& i) - { - CheckIn('B', &i); - return *this; - } - - TreeStream& operator<<(const UChar_t& c) - { - CheckIn('b', &c); - return *this; - } - - TreeStream& operator<<(const Short_t& h) - { - CheckIn('S', &h); - return *this; - } - - TreeStream& operator<<(const UShort_t& h) - { - CheckIn('s', &h); - return *this; - } - - TreeStream& operator<<(const Int_t& i) - { - CheckIn('I', &i); - return *this; - } - - TreeStream& operator<<(const UInt_t& i) - { - CheckIn('i', &i); - return *this; - } - - TreeStream& operator<<(const Long_t& l) - { - CheckIn('L', &l); - return *this; - } - - TreeStream& operator<<(const ULong_t& l) - { - CheckIn('l', &l); - return *this; - } - - TreeStream& operator<<(const Long64_t& l) - { - CheckIn('L', &l); - return *this; - } - - TreeStream& operator<<(const ULong64_t& l) - { - CheckIn('l', &l); - return *this; - } - - TreeStream& operator<<(const Float_t& f) - { - CheckIn('F', &f); - return *this; - } - - TreeStream& operator<<(const Double_t& d) + template + TreeStream& operator<<(const T& t) { - CheckIn('D', &d); + CheckIn(details::getRootTypeCode(), &t); return *this; } @@ -157,7 +151,7 @@ class TreeStream return *this; } - template ::value, bool>::type* = nullptr> + template ::value, bool>::type* = nullptr> TreeStream& operator<<(const T& obj) { CheckIn(&obj); @@ -175,6 +169,7 @@ class TreeStream int mCurrentIndex = 0; ///< index of current element int mID = -1; ///< identifier of layout int mNextNameCounter = 0; ///< next name counter + int mNextArraySize = 0; ///< next array size int mStatus = 0; ///< status of the layout TString mNextName; ///< name for next entry @@ -191,8 +186,7 @@ Int_t TreeStream::CheckIn(const T* obj) } if (mCurrentIndex >= static_cast(mElements.size())) { - mElements.emplace_back(); - auto& element = mElements.back(); + auto& element = mElements.emplace_back(); element.cls = pClass; TString name = mNextName; if (name.Length()) { @@ -204,6 +198,8 @@ Int_t TreeStream::CheckIn(const T* obj) } element.name = name.Data(); element.ptr = obj; + element.arsize = mNextArraySize; + mNextArraySize = 1; // reset } else { auto& element = mElements[mCurrentIndex]; if (!element.cls) { diff --git a/Common/Utils/src/TreeStream.cxx b/Common/Utils/src/TreeStream.cxx index da25f25ad2eb1..cd0641a11d043 100644 --- a/Common/Utils/src/TreeStream.cxx +++ b/Common/Utils/src/TreeStream.cxx @@ -29,8 +29,7 @@ int TreeStream::CheckIn(Char_t type, const void* pointer) // Insert object if (mCurrentIndex >= static_cast(mElements.size())) { - mElements.emplace_back(); - auto& element = mElements.back(); + auto& element = mElements.emplace_back(); element.type = type; TString name = mNextName; if (name.Length()) { @@ -42,6 +41,8 @@ int TreeStream::CheckIn(Char_t type, const void* pointer) } element.name = name.Data(); element.ptr = pointer; + element.arsize = mNextArraySize; + mNextArraySize = 1; // reset } else { auto& element = mElements[mCurrentIndex]; if (element.type != type) { @@ -89,7 +90,13 @@ void TreeStream::BuildTree() } if (element.type > 0) { - TString nameC = TString::Format("%s/%c", name.Data(), element.type); + TString nameC; + if (element.arsize > 1) { + nameC = TString::Format("%s[%d]/%c", name.Data(), element.arsize, + element.type); + } else { + nameC = TString::Format("%s/%c", name.Data(), element.type); + } br = mTree.Branch(name.Data(), const_cast(element.ptr), nameC.Data()); if (entriesFilled) { br->SetAddress(nullptr); @@ -148,28 +155,43 @@ TreeStream& TreeStream::Endl() TreeStream& TreeStream::operator<<(const Char_t* name) { // Stream the branch name - // if (name[0] == '\n') { return Endl(); } - // + // if tree was already defined ignore if (mTree.GetEntries() > 0) { return *this; } + + int arsize = 1; + // check branch name if tree was not - // Int_t last = 0; for (last = 0;; last++) { if (name[last] == 0) { break; } } - if (last > 0 && name[last - 1] == '=') { mNextName = name; - mNextName[last - 1] = 0; + mNextName[last - 1] = 0; // remove '=' from string mNextNameCounter = 0; + + TString inName{name}; + auto brkStaPos = inName.Index('['); + + if (brkStaPos != kNPOS) { + auto brkEndPos = inName.Index(']'); + if (brkEndPos != kNPOS && brkEndPos > brkStaPos + 1) { + TString size = inName(brkStaPos + 1, brkEndPos - brkStaPos - 1); + arsize = size.Atoi(); + mNextName = inName(0, brkStaPos); // use parsed name + } + } } + + mNextArraySize = arsize; + return *this; } diff --git a/Common/Utils/test/testTreeStream.cxx b/Common/Utils/test/testTreeStream.cxx index 7ff6f165a1d37..2491fea7f6efd 100644 --- a/Common/Utils/test/testTreeStream.cxx +++ b/Common/Utils/test/testTreeStream.cxx @@ -53,12 +53,28 @@ BOOST_AUTO_TEST_CASE(TreeStream_test) tstStream << "TrackTreeR" << "id=" << i << "x=" << x << "track=" << trc << "\n"; } + + // test for c-arrays + int iArray[6] = {1, 2, 3, 4, 5, 6}; + float fArray[6] = {1.1f, 2.2f, 3.3f, 4.4f, 5.5f, 6.6f}; + for (int i{0}; i < nit; ++i) { + for (int j{0}; j < 6; ++j) { + iArray[j] += i; + fArray[j] += (float)i; + } + tstStream << "ArrayTree" + << "id=" << i + << "iArray[6]=" << iArray + << "fArray[6]=" << fArray + << "\n"; + } + // on destruction of tstTreem the trees will be stored, but we can also force it by tstStream.Close(); } // - LOG(info) << "Testing reading back tree maid by the TreeStream "; - // read back tracks + LOG(info) << "Testing reading back tree made by the TreeStream "; + // read back tracks and arrays { TFile inpf(outFName.data()); BOOST_CHECK(!inpf.IsZombie()); @@ -80,6 +96,27 @@ BOOST_AUTO_TEST_CASE(TreeStream_test) trc->printParam(); BOOST_CHECK(std::abs(x - trc->getX()) < 1e-4); } + + // check arrays + tree = (TTree*)inpf.GetObjectChecked("ArrayTree", "TTree"); + BOOST_CHECK(tree); + nent = tree->GetEntries(); + BOOST_CHECK(nent == nit); + int iArray[6]; + float fArray[6]; + BOOST_CHECK(!tree->SetBranchAddress("id", &id)); + BOOST_CHECK(!tree->SetBranchAddress("iArray", iArray)); + BOOST_CHECK(!tree->SetBranchAddress("fArray", fArray)); + for (int i = 0; i < nit; i++) { + BOOST_CHECK(tree->GetEntry(i) > 0); + BOOST_CHECK(id == i); + for (int j = 0; j < 6; j++) { + BOOST_CHECK(iArray[j] == (1 + j + i * (i + 1) / 2)); + } + for (int j = 0; j < 6; j++) { + BOOST_CHECK_CLOSE(fArray[j], (1.f + j + i * (i + 1) / 2.f + 0.1 * (j + 1)), 1e-5); + } + } } LOG(info) << "Testing loading tree via RootChain"; @@ -104,7 +141,6 @@ BOOST_AUTO_TEST_CASE(TreeStream_test) nit = 1000; BOOST_CHECK(UnitTestSparse(0.5, nit)); BOOST_CHECK(UnitTestSparse(0.1, nit)); - // } //_________________________________________________ From 2edb4f3cd5e4d9e012df566235f01c34abd98ef9 Mon Sep 17 00:00:00 2001 From: Felix Schlepper Date: Sat, 22 Mar 2025 02:54:24 +0100 Subject: [PATCH 06/10] AOD: Add trd tracklet streamer Signed-off-by: Felix Schlepper --- .../AODProducerWorkflowSpec.h | 2 + Detectors/AOD/src/AODProducerWorkflowSpec.cxx | 84 +++++++------------ 2 files changed, 33 insertions(+), 53 deletions(-) diff --git a/Detectors/AOD/include/AODProducerWorkflow/AODProducerWorkflowSpec.h b/Detectors/AOD/include/AODProducerWorkflow/AODProducerWorkflowSpec.h index 98fb9e725d2fe..d469ae398e316 100644 --- a/Detectors/AOD/include/AODProducerWorkflow/AODProducerWorkflowSpec.h +++ b/Detectors/AOD/include/AODProducerWorkflow/AODProducerWorkflowSpec.h @@ -20,6 +20,7 @@ #include "DataFormatsPHOS/Cell.h" #include "DataFormatsTRD/TrackTRD.h" #include "TRDBase/PadCalibrationsAliases.h" +#include "TRDBase/TrackletTransformer.h" #include "DataFormatsTRD/NoiseCalibration.h" #include "DetectorsBase/GRPGeomHelper.h" #include "DetectorsBase/Propagator.h" @@ -250,6 +251,7 @@ class AODProducerWorkflowDPL : public Task const o2::trd::LocalGainFactor* mTRDLocalGain; // TRD local gain factors from krypton calibration const o2::trd::NoiseStatusMCM* mTRDNoiseMap; // TRD noise map + std::unique_ptr mTRDTransformer; std::unordered_set mGIDUsedBySVtx; std::unordered_set mGIDUsedByStr; diff --git a/Detectors/AOD/src/AODProducerWorkflowSpec.cxx b/Detectors/AOD/src/AODProducerWorkflowSpec.cxx index 21c5dba2dc69c..df9c7a68afb8f 100644 --- a/Detectors/AOD/src/AODProducerWorkflowSpec.cxx +++ b/Detectors/AOD/src/AODProducerWorkflowSpec.cxx @@ -396,7 +396,9 @@ void AODProducerWorkflowDPL::addToTRDsExtra(const o2::globaltracking::RecoContai int q0s[NLAYERS] = {-1}, q1s[NLAYERS] = {-1}, q2s[NLAYERS] = {-1}; float q0sCor[NLAYERS] = {-1}, q1sCor[NLAYERS] = {-1}, q2sCor[NLAYERS] = {-1}; float ttgls[NLAYERS] = {-999}, tphis[NLAYERS] = {-999}; - o2::trd::Tracklet64 trkletsa[NLAYERS]; + std::vector trkletsa(NLAYERS); + std::vector ctrkletsa(NLAYERS); + std::vector cloctrkletsa(NLAYERS); auto contributorsGID = recoData.getSingleDetectorRefs(trkIdx); if (!contributorsGID[GIndex::Source::TRD].isIndexSet()) { // should be redunant @@ -418,6 +420,8 @@ void AODProducerWorkflowDPL::addToTRDsExtra(const o2::globaltracking::RecoContai continue; } trkletsa[iLay] = tracklet; + ctrkletsa[iLay] = ctrklets[trkltId]; + cloctrkletsa[iLay] = mTRDTransformer->transformTracklet(tracklet, false); // we need to propagate into TRD local system int trkltDet = tracklet.getDetector(); int trkltSec = trkltDet / 30; @@ -433,16 +437,14 @@ void AODProducerWorkflowDPL::addToTRDsExtra(const o2::globaltracking::RecoContai auto tphi = trkC.getSnp() / std::sqrt((1.f - trkC.getSnp()) * (1.f + trkC.getSnp())); auto trackletLength = std::sqrt(1.f + tphi * tphi + trkC.getTgl() * trkC.getTgl()); float cor = mTRDLocalGain->getValue(tracklet.getHCID() / 2, tracklet.getPadCol(), tracklet.getPadRow()) * trackletLength; - if (mEnableTRDextra) { - q0s[iLay] = tracklet.getQ0(); - q1s[iLay] = tracklet.getQ1(); - q2s[iLay] = tracklet.getQ2(); - q0sCor[iLay] = (float)tracklet.getQ0() / cor; - q1sCor[iLay] = (float)tracklet.getQ1() / cor; - q2sCor[iLay] = (float)tracklet.getQ2() / cor; - ttgls[iLay] = trkC.getTgl(); - tphis[iLay] = tphi; - } + q0s[iLay] = tracklet.getQ0(); + q1s[iLay] = tracklet.getQ1(); + q2s[iLay] = tracklet.getQ2(); + q0sCor[iLay] = (float)tracklet.getQ0() / cor; + q1sCor[iLay] = (float)tracklet.getQ1() / cor; + q2sCor[iLay] = (float)tracklet.getQ2() / cor; + ttgls[iLay] = trkC.getTgl(); + tphis[iLay] = tphi; dEdx += (float)tracklet.getQTot() / cor; } @@ -462,49 +464,16 @@ void AODProducerWorkflowDPL::addToTRDsExtra(const o2::globaltracking::RecoContai (*mStreamer) << "trdExtra" << "dEdx=" << dEdx << "eProb=" << trk.getSignal() - << "q00=" << q0s[0] - << "q01=" << q0s[1] - << "q02=" << q0s[2] - << "q03=" << q0s[3] - << "q04=" << q0s[4] - << "q05=" << q0s[5] - << "q10=" << q1s[0] - << "q11=" << q1s[1] - << "q12=" << q1s[2] - << "q13=" << q1s[3] - << "q14=" << q1s[4] - << "q15=" << q1s[5] - << "q20=" << q2s[0] - << "q21=" << q2s[1] - << "q22=" << q2s[2] - << "q23=" << q2s[3] - << "q24=" << q2s[4] - << "q25=" << q2s[5] - << "q00Cor=" << q0sCor[0] - << "q01Cor=" << q0sCor[1] - << "q02Cor=" << q0sCor[2] - << "q03Cor=" << q0sCor[3] - << "q04Cor=" << q0sCor[4] - << "q05Cor=" << q0sCor[5] - << "q10Cor=" << q1sCor[0] - << "q11Cor=" << q1sCor[1] - << "q12Cor=" << q1sCor[2] - << "q13Cor=" << q1sCor[3] - << "q14Cor=" << q1sCor[4] - << "q15Cor=" << q1sCor[5] - << "q20Cor=" << q2sCor[0] - << "q21Cor=" << q2sCor[1] - << "q22Cor=" << q2sCor[2] - << "q23Cor=" << q2sCor[3] - << "q24Cor=" << q2sCor[4] - << "q25Cor=" << q2sCor[5] + << "q0s[6]=" << q0s + << "q1s[6]=" << q1s + << "q2s[6]=" << q2s + << "q0sCor[6]=" << q0sCor + << "q1sCor[6]=" << q1sCor + << "q2sCor[6]=" << q2sCor << "pattern=" << getTRDPattern(trk) - << "tracklet0=" << trkletsa[0] - << "tracklet1=" << trkletsa[1] - << "tracklet2=" << trkletsa[2] - << "tracklet3=" << trkletsa[3] - << "tracklet4=" << trkletsa[4] - << "tracklet5=" << trkletsa[5] + << "tracklets=" << trkletsa + << "ctracklets=" << ctrkletsa + << "cloctracklets=" << cloctrkletsa << "tpctrk=" << tpctrk << "trdtrk=" << trk << "globaltrk=" << recoData.getTrack(trkIdx) @@ -3036,6 +3005,9 @@ void AODProducerWorkflowDPL::updateTimeDependentParams(ProcessingContext& pc) if (mEnableTRDextra) { mTRDLocalGain = pc.inputs().get("trdlocalgainfactors").get(); mTRDNoiseMap = pc.inputs().get("trdnoisemap").get(); + mTRDTransformer = std::make_unique(); + mTRDTransformer->init(); + pc.inputs().get("calvdexb"); } } if (mPropTracks) { @@ -3070,6 +3042,11 @@ void AODProducerWorkflowDPL::finaliseCCDB(ConcreteDataMatcher& matcher, void* ob mVtx = *(const o2::dataformats::MeanVertexObject*)obj; return; } + if (matcher == ConcreteDataMatcher("TRD", "CALVDRIFTEXB", 0)) { + LOG(info) << "TRD CalVdriftExB object has been updated"; + mTRDTransformer->setCalVdriftExB((const o2::trd::CalVdriftExB*)obj); + return; + } if (matcher == ConcreteDataMatcher("CTP", "CTPCONFIG", 0)) { // construct mask with EMCAL trigger classes for rejection of incomplete triggers auto ctpconfig = *(const o2::ctp::CTPConfiguration*)obj; @@ -3348,6 +3325,7 @@ DataProcessorSpec getAODProducerWorkflowSpec(GID::mask_t src, bool enableSV, boo outputs.push_back(OutputForTable::spec()); dataRequest->inputs.emplace_back("trdlocalgainfactors", "TRD", "LOCALGAINFACTORS", 0, Lifetime::Condition, ccdbParamSpec("TRD/Calib/LocalGainFactor")); dataRequest->inputs.emplace_back("trdnoisemap", "TRD", "NOISEMAP", 0, Lifetime::Condition, ccdbParamSpec("TRD/Calib/NoiseMapMCM")); + dataRequest->inputs.emplace_back("calvdexb", "TRD", "CALVDRIFTEXB", 0, Lifetime::Condition, ccdbParamSpec("TRD/Calib/CalVdriftExB")); } if (useMC) { outputs.insert(outputs.end(), From 833637e75919936c0afd07351983f1ba3005d43c Mon Sep 17 00:00:00 2001 From: Felix Schlepper Date: Sat, 22 Mar 2025 16:18:35 +0100 Subject: [PATCH 07/10] AOD: trd streamer add tof Signed-off-by: Felix Schlepper --- Detectors/AOD/src/AODProducerWorkflowSpec.cxx | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/Detectors/AOD/src/AODProducerWorkflowSpec.cxx b/Detectors/AOD/src/AODProducerWorkflowSpec.cxx index df9c7a68afb8f..65bd6766da75e 100644 --- a/Detectors/AOD/src/AODProducerWorkflowSpec.cxx +++ b/Detectors/AOD/src/AODProducerWorkflowSpec.cxx @@ -461,6 +461,13 @@ void AODProducerWorkflowDPL::addToTRDsExtra(const o2::globaltracking::RecoContai if (mStreamerFlags[AODProducerStreamerFlags::TRDExtra]) { const auto& tpctrk = recoData.getTrack(contributorsGID[GIndex::Source::TPC]); + o2::dataformats::MatchInfoTOF tofMtc; + o2::track::TrackParCov toftrk; + toftrk.invalidate(); + if (contributorsGID[GIndex::Source::TOF].isIndexSet()) { + tofMtc = recoData.getTOFMatch(trkIdx); + toftrk = recoData.getTrackParamOut(trkIdx); + } (*mStreamer) << "trdExtra" << "dEdx=" << dEdx << "eProb=" << trk.getSignal() @@ -476,6 +483,8 @@ void AODProducerWorkflowDPL::addToTRDsExtra(const o2::globaltracking::RecoContai << "cloctracklets=" << cloctrkletsa << "tpctrk=" << tpctrk << "trdtrk=" << trk + << "toftrk=" << toftrk + << "tofMtc=" << tofMtc << "globaltrk=" << recoData.getTrack(trkIdx) << "\n"; } From 868a38a425de79a9ee97402714d799e24937aefa Mon Sep 17 00:00:00 2001 From: Felix Schlepper Date: Sat, 22 Mar 2025 16:46:37 +0100 Subject: [PATCH 08/10] AOD: trd streamer build own pattern Signed-off-by: Felix Schlepper --- Detectors/AOD/src/AODProducerWorkflowSpec.cxx | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/Detectors/AOD/src/AODProducerWorkflowSpec.cxx b/Detectors/AOD/src/AODProducerWorkflowSpec.cxx index 65bd6766da75e..053a6dc1388ed 100644 --- a/Detectors/AOD/src/AODProducerWorkflowSpec.cxx +++ b/Detectors/AOD/src/AODProducerWorkflowSpec.cxx @@ -410,6 +410,7 @@ void AODProducerWorkflowDPL::addToTRDsExtra(const o2::globaltracking::RecoContai auto trkC = trk; // local copy to propagate float dEdx{0.}; + uint8_t pattern = 0; for (int iLay{0}; iLay < NLAYERS; ++iLay) { auto trkltId = trk.getTrackletIndex(iLay); if (trkltId < 0) { @@ -447,6 +448,13 @@ void AODProducerWorkflowDPL::addToTRDsExtra(const o2::globaltracking::RecoContai tphis[iLay] = tphi; dEdx += (float)tracklet.getQTot() / cor; + pattern |= 0x1 << iLay; + } + if (trk.getHasNeighbor()) { + pattern |= 0x1 << 6; + } + if (trk.getHasPadrowCrossing()) { + pattern |= 0x1 << 7; } dEdx /= (float)trkC.getNtracklets(); @@ -477,7 +485,7 @@ void AODProducerWorkflowDPL::addToTRDsExtra(const o2::globaltracking::RecoContai << "q0sCor[6]=" << q0sCor << "q1sCor[6]=" << q1sCor << "q2sCor[6]=" << q2sCor - << "pattern=" << getTRDPattern(trk) + << "pattern=" << pattern << "tracklets=" << trkletsa << "ctracklets=" << ctrkletsa << "cloctracklets=" << cloctrkletsa From 30b8678783ba811933ce64d78e247913a611175b Mon Sep 17 00:00:00 2001 From: Felix Schlepper Date: Sat, 22 Mar 2025 20:01:02 +0100 Subject: [PATCH 09/10] AOD: trd streamer add pv,tfID and runnumber Signed-off-by: Felix Schlepper --- .../AODProducerWorkflowSpec.h | 3 +- Detectors/AOD/src/AODProducerWorkflowSpec.cxx | 42 ++++++++++++------- 2 files changed, 28 insertions(+), 17 deletions(-) diff --git a/Detectors/AOD/include/AODProducerWorkflow/AODProducerWorkflowSpec.h b/Detectors/AOD/include/AODProducerWorkflow/AODProducerWorkflowSpec.h index d469ae398e316..c6f89e4dac394 100644 --- a/Detectors/AOD/include/AODProducerWorkflow/AODProducerWorkflowSpec.h +++ b/Detectors/AOD/include/AODProducerWorkflow/AODProducerWorkflowSpec.h @@ -269,6 +269,7 @@ class AODProducerWorkflowDPL : public Task GID::mask_t mInputSources; int64_t mTFNumber{-1}; + uint64_t mCurTFNumber{0}; int mRunNumber{-1}; int mTruncate{1}; int mRecoOnly{0}; @@ -527,7 +528,7 @@ class AODProducerWorkflowDPL : public Task void addToTracksQATable(TracksQACursorType& tracksQACursor, TrackQA& trackQAInfoHolder); template - void addToTRDsExtra(const o2::globaltracking::RecoContainer& recoData, TRDsExtraCursorType& trdExtraCursor, const GIndex& trkIdx, TrackExtraInfo& extraInfo, int trkTableIdx); + void addToTRDsExtra(const o2::globaltracking::RecoContainer& recoData, TRDsExtraCursorType& trdExtraCursor, int colIdx, const GIndex& trkIdx, TrackExtraInfo& extraInfo, int trkTableIdx); template void addToMFTTracksTable(mftTracksCursorType& mftTracksCursor, AmbigMFTTracksCursorType& ambigMFTTracksCursor, diff --git a/Detectors/AOD/src/AODProducerWorkflowSpec.cxx b/Detectors/AOD/src/AODProducerWorkflowSpec.cxx index 053a6dc1388ed..82d66bfd67823 100644 --- a/Detectors/AOD/src/AODProducerWorkflowSpec.cxx +++ b/Detectors/AOD/src/AODProducerWorkflowSpec.cxx @@ -390,12 +390,13 @@ void AODProducerWorkflowDPL::addToTracksQATable(TracksQACursorType& tracksQACurs } template -void AODProducerWorkflowDPL::addToTRDsExtra(const o2::globaltracking::RecoContainer& recoData, TRDsExtraCursorType& trdExtraCursor, const GIndex& trkIdx, TrackExtraInfo& extraInfo, int trkTableIdx) +void AODProducerWorkflowDPL::addToTRDsExtra(const o2::globaltracking::RecoContainer& recoData, TRDsExtraCursorType& trdExtraCursor, int colIdx, const GIndex& trkIdx, TrackExtraInfo& extraInfo, int trkTableIdx) { const int NLAYERS = o2::trd::TrackTRD::EGPUTRDTrack::kNLayers; int q0s[NLAYERS] = {-1}, q1s[NLAYERS] = {-1}, q2s[NLAYERS] = {-1}; float q0sCor[NLAYERS] = {-1}, q1sCor[NLAYERS] = {-1}, q2sCor[NLAYERS] = {-1}; float ttgls[NLAYERS] = {-999}, tphis[NLAYERS] = {-999}; + float gain[NLAYERS] = {-999}, length[NLAYERS] = {-999}; std::vector trkletsa(NLAYERS); std::vector ctrkletsa(NLAYERS); std::vector cloctrkletsa(NLAYERS); @@ -411,15 +412,13 @@ void AODProducerWorkflowDPL::addToTRDsExtra(const o2::globaltracking::RecoContai float dEdx{0.}; uint8_t pattern = 0; + uint8_t noisy = 0; for (int iLay{0}; iLay < NLAYERS; ++iLay) { auto trkltId = trk.getTrackletIndex(iLay); if (trkltId < 0) { continue; } const auto& tracklet = trklets[trkltId]; - if (mTRDNoiseMap->isTrackletFromNoisyMCM(tracklet)) { - continue; - } trkletsa[iLay] = tracklet; ctrkletsa[iLay] = ctrklets[trkltId]; cloctrkletsa[iLay] = mTRDTransformer->transformTracklet(tracklet, false); @@ -436,18 +435,23 @@ void AODProducerWorkflowDPL::addToTRDsExtra(const o2::globaltracking::RecoContai } auto tphi = trkC.getSnp() / std::sqrt((1.f - trkC.getSnp()) * (1.f + trkC.getSnp())); - auto trackletLength = std::sqrt(1.f + tphi * tphi + trkC.getTgl() * trkC.getTgl()); - float cor = mTRDLocalGain->getValue(tracklet.getHCID() / 2, tracklet.getPadCol(), tracklet.getPadRow()) * trackletLength; + length[iLay] = std::sqrt(1.f + tphi * tphi + trkC.getTgl() * trkC.getTgl()); + gain[iLay] = mTRDLocalGain->getValue(tracklet.getHCID() / 2, tracklet.getPadCol(), tracklet.getPadRow()); + float cor = 1.f / (gain[iLay] * length[iLay]); q0s[iLay] = tracklet.getQ0(); q1s[iLay] = tracklet.getQ1(); q2s[iLay] = tracklet.getQ2(); - q0sCor[iLay] = (float)tracklet.getQ0() / cor; - q1sCor[iLay] = (float)tracklet.getQ1() / cor; - q2sCor[iLay] = (float)tracklet.getQ2() / cor; + q0sCor[iLay] = (float)tracklet.getQ0() * cor; + q1sCor[iLay] = (float)tracklet.getQ1() * cor; + q2sCor[iLay] = (float)tracklet.getQ2() * cor; ttgls[iLay] = trkC.getTgl(); tphis[iLay] = tphi; - dEdx += (float)tracklet.getQTot() / cor; + if (!mTRDNoiseMap->isTrackletFromNoisyMCM(tracklet)) { + dEdx += (float)tracklet.getQTot() * cor; + } else { + noisy |= 0x1 << iLay; + } pattern |= 0x1 << iLay; } if (trk.getHasNeighbor()) { @@ -468,6 +472,7 @@ void AODProducerWorkflowDPL::addToTRDsExtra(const o2::globaltracking::RecoContai } if (mStreamerFlags[AODProducerStreamerFlags::TRDExtra]) { + const auto& pv = recoData.getPrimaryVertex(colIdx); const auto& tpctrk = recoData.getTrack(contributorsGID[GIndex::Source::TPC]); o2::dataformats::MatchInfoTOF tofMtc; o2::track::TrackParCov toftrk; @@ -485,7 +490,10 @@ void AODProducerWorkflowDPL::addToTRDsExtra(const o2::globaltracking::RecoContai << "q0sCor[6]=" << q0sCor << "q1sCor[6]=" << q1sCor << "q2sCor[6]=" << q2sCor + << "gain[6]=" << gain + << "length[6]=" << length << "pattern=" << pattern + << "noisy=" << noisy << "tracklets=" << trkletsa << "ctracklets=" << ctrkletsa << "cloctracklets=" << cloctrkletsa @@ -494,6 +502,9 @@ void AODProducerWorkflowDPL::addToTRDsExtra(const o2::globaltracking::RecoContai << "toftrk=" << toftrk << "tofMtc=" << tofMtc << "globaltrk=" << recoData.getTrack(trkIdx) + << "pv=" << pv + << "tfID=" << mCurTFNumber + << "runNumber=" << mRunNumber << "\n"; } } @@ -650,7 +661,7 @@ void AODProducerWorkflowDPL::fillTrackTablesPerCollision(int collisionID, } if (trackIndex.includesDet(GIndex::Source::TRD)) { - addToTRDsExtra(data, trdsExtraCursor, trackIndex, extraInfoHolder, mTableTrID); + addToTRDsExtra(data, trdsExtraCursor, collisionID, trackIndex, extraInfoHolder, mTableTrID); } addToTracksExtraTable(tracksExtraCursor, extraInfoHolder); @@ -2021,13 +2032,12 @@ void AODProducerWorkflowDPL::run(ProcessingContext& pc) // initialize the bunch crossing container for further use below mBCLookup.init(bcsMap); - uint64_t tfNumber; const int runNumber = (mRunNumber == -1) ? int(tinfo.runNumber) : mRunNumber; if (mTFNumber == -1L) { // TODO has to use absolute time of TF - tfNumber = uint64_t(tinfo.firstTForbit) + (uint64_t(tinfo.runNumber) << 32); // getTFNumber(mStartIR, runNumber); + mCurTFNumber = uint64_t(tinfo.firstTForbit) + (uint64_t(tinfo.runNumber) << 32); // getTFNumber(mStartIR, runNumber); } else { - tfNumber = mTFNumber; + mCurTFNumber = mTFNumber; } std::vector aAmplitudes, aTimes; @@ -2502,7 +2512,7 @@ void AODProducerWorkflowDPL::run(ProcessingContext& pc) mGIDUsedBySVtx.clear(); mGIDUsedByStr.clear(); - originCursor(tfNumber); + originCursor(mCurTFNumber); // sending metadata to writer TString dataType = mUseMC ? "MC" : "RAW"; @@ -2513,7 +2523,7 @@ void AODProducerWorkflowDPL::run(ProcessingContext& pc) pc.outputs().snapshot(Output{"AMD", "AODMetadataKeys", 0}, mMetaDataKeys); pc.outputs().snapshot(Output{"AMD", "AODMetadataVals", 0}, mMetaDataVals); - pc.outputs().snapshot(Output{"TFN", "TFNumber", 0}, tfNumber); + pc.outputs().snapshot(Output{"TFN", "TFNumber", 0}, mCurTFNumber); pc.outputs().snapshot(Output{"TFF", "TFFilename", 0}, ""); mTimer.Stop(); From f0c5fa27c4fd44883df20dd8c936ba8b43b2242a Mon Sep 17 00:00:00 2001 From: Felix Schlepper Date: Mon, 24 Mar 2025 15:38:36 +0100 Subject: [PATCH 10/10] add more vars Signed-off-by: Felix Schlepper --- Detectors/AOD/src/AODProducerWorkflowSpec.cxx | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Detectors/AOD/src/AODProducerWorkflowSpec.cxx b/Detectors/AOD/src/AODProducerWorkflowSpec.cxx index 82d66bfd67823..ad1e69f5cab34 100644 --- a/Detectors/AOD/src/AODProducerWorkflowSpec.cxx +++ b/Detectors/AOD/src/AODProducerWorkflowSpec.cxx @@ -492,6 +492,8 @@ void AODProducerWorkflowDPL::addToTRDsExtra(const o2::globaltracking::RecoContai << "q2sCor[6]=" << q2sCor << "gain[6]=" << gain << "length[6]=" << length + << "loctgls[6]=" << ttgls + << "locphis[6]=" << tphis << "pattern=" << pattern << "noisy=" << noisy << "tracklets=" << trkletsa