3333#include " DataFormatsPHOS/TriggerRecord.h"
3434#include " DataFormatsPHOS/EventHandler.h"
3535#include " DataFormatsTPC/TrackTPC.h"
36- #include " DataFormatsTRD/TriggerRecord.h"
3736#include " DataFormatsZDC/BCRecData.h"
3837#include " DataFormatsZDC/ZDCEnergy.h"
3938#include " DataFormatsZDC/ZDCTDCData.h"
4544#include " CommonDataFormat/InteractionRecord.h"
4645#include " DataFormatsTRD/TrackTRD.h"
4746#include " DataFormatsTRD/TrackTriggerRecord.h"
47+ #include " DataFormatsTRD/CalibratedTracklet.h"
48+ #include " DataFormatsTRD/TriggerRecord.h"
49+ #include " DataFormatsTRD/Tracklet64.h"
4850#include " DataFormatsGlobalTracking/RecoContainer.h"
4951#include " Framework/AnalysisDataModel.h"
5052#include " Framework/ConfigParamRegistry.h"
@@ -390,6 +392,121 @@ void AODProducerWorkflowDPL::addToTracksQATable(TracksQACursorType& tracksQACurs
390392 mTrackQCRetainOnlydEdx ? std::numeric_limits<int8_t >::min () : trackQAInfoHolder.dTofdZ );
391393}
392394
395+ template <typename TRDsExtraCursorType>
396+ void AODProducerWorkflowDPL::addToTRDsExtra (const o2::globaltracking::RecoContainer& recoData, TRDsExtraCursorType& trdExtraCursor, const GIndex& trkIdx, int trkTableIdx)
397+ {
398+ int q0s[6 ] = {-1 }, q1s[6 ] = {-1 }, q2s[6 ] = {-1 };
399+ float q0sCor[6 ] = {-1 }, q1sCor[6 ] = {-1 }, q2sCor[6 ] = {-1 };
400+ float ttgls[6 ] = {-999 }, tphis[6 ] = {-999 };
401+
402+ auto contributorsGID = recoData.getSingleDetectorRefs (trkIdx);
403+ if (!contributorsGID[GIndex::Source::TRD].isIndexSet ()) { // should be redunant
404+ return ;
405+ }
406+ const auto & trk = recoData.getTrack <o2::trd::TrackTRD>(contributorsGID[GIndex::Source::TRD]);
407+ o2::track::TrackPar trkC{contributorsGID[GIndex::Source::ITSTPC].isIndexSet () ? recoData.getTPCITSTrack (contributorsGID[GIndex::Source::ITSTPC]).getParamOut () : recoData.getTPCTrack (contributorsGID[GIndex::Source::TPC]).getParamOut ()};
408+ const auto & trklets = recoData.getTRDTracklets ();
409+ const auto & ctrklets = recoData.getTRDCalibratedTracklets ();
410+ for (int iLay{0 }; iLay < 6 ; ++iLay) {
411+ q0s[iLay] = q1s[iLay] = q2s[iLay] = -1 ;
412+ q0sCor[iLay] = q1sCor[iLay] = q2sCor[iLay] = -1 ;
413+ tphis[iLay] = ttgls[iLay] = -999 ;
414+ auto trkltId = trk.getTrackletIndex (iLay);
415+ if (trkltId < 0 ) {
416+ continue ;
417+ }
418+ const auto & tracklet = trklets[trkltId];
419+ if (mTRDNoiseMap ->isTrackletFromNoisyMCM (tracklet)) {
420+ continue ;
421+ }
422+ // we need to propagate into TRD local system
423+ int trkltDet = tracklet.getDetector ();
424+ int trkltSec = trkltDet / 30 ;
425+ if (trkltSec != o2::math_utils::angle2Sector (trkC.getAlpha ())) {
426+ if (!trkC.rotate (o2::math_utils::sector2Angle (trkltSec))) {
427+ break ;
428+ }
429+ }
430+ if (!o2::base::Propagator::Instance ()->PropagateToXBxByBz (trkC, ctrklets[trkltId].getX (), o2::base::Propagator::MAX_SIN_PHI, o2::base::Propagator::MAX_STEP, mMatCorr )) {
431+ break ;
432+ }
433+
434+ auto tphi = trkC.getSnp () / std::sqrt ((1 .f - trkC.getSnp ()) * (1 .f + trkC.getSnp ()));
435+ auto trackletLength = std::sqrt (1 .f + tphi * tphi + trkC.getTgl () * trkC.getTgl ());
436+ float cor = mTRDLocalGain ->getValue (tracklet.getHCID () / 2 , tracklet.getPadCol (), tracklet.getPadRow ()) * mTRDGainCalib ->getMPVdEdx (tracklet.getDetector ()) / o2::trd::constants::MPVDEDXDEFAULT * trackletLength;
437+ q0s[iLay] = tracklet.getQ0 ();
438+ q1s[iLay] = tracklet.getQ1 ();
439+ q2s[iLay] = tracklet.getQ2 ();
440+ q0sCor[iLay] = (float )tracklet.getQ0 () / cor;
441+ q1sCor[iLay] = (float )tracklet.getQ1 () / cor;
442+ q2sCor[iLay] = (float )tracklet.getQ2 () / cor;
443+ ttgls[iLay] = trkC.getTgl ();
444+ tphis[iLay] = tphi;
445+
446+ // z-row merging, we want to merge only with tracklets from the same trigger record
447+ if (trk.getIsCrossingNeighbor (iLay) && trk.getHasNeighbor ()) {
448+ // find the trigger the tracklet belongs to
449+ auto trigsTRD = recoData.getTRDTriggerRecords ();
450+ size_t trdSelID = -1 ;
451+
452+ const auto & trig = trigsTRD[mCurrentTRDTrigID ];
453+ bool foundTRDTrigger = false ;
454+ // first check current trigger
455+ if (trkltId >= trig.getFirstTracklet () && trkltId < trig.getFirstTracklet () + trig.getNumberOfTracklets ()) {
456+ trdSelID = mCurrentTRDTrigID ;
457+ foundTRDTrigger = true ;
458+ } else {
459+ // then check next trigger
460+ if (mCurrentTRDTrigID < trigsTRD.size () - 1 ) {
461+ const auto & trig = trigsTRD[mCurrentTRDTrigID + 1 ];
462+ if (trkltId >= trig.getFirstTracklet () && trkltId < trig.getFirstTracklet () + trig.getNumberOfTracklets ()) {
463+ trdSelID = mCurrentTRDTrigID + 1 ;
464+ foundTRDTrigger = true ;
465+ }
466+ }
467+ }
468+
469+ size_t low = 0 , up = trigsTRD.size () - 1 ;
470+
471+ // otherwise binary search
472+ while (low <= up && !foundTRDTrigger) {
473+ trdSelID = low + std::floor ((up - low) / 2 );
474+ const auto & trig = trigsTRD[trdSelID];
475+ if (trig.getFirstTracklet () > trkltId) {
476+ up = trdSelID - 1 ;
477+ } else {
478+ if (trig.getFirstTracklet () + trig.getNumberOfTracklets () <= trkltId) {
479+ low = trdSelID + 1 ;
480+ } else {
481+ foundTRDTrigger = true ;
482+ }
483+ }
484+ }
485+ // -------------------
486+ mCurrentTRDTrigID = trdSelID;
487+ const auto & trigSel = trigsTRD[trdSelID];
488+
489+ // loop on other tracklets from the same trigger record
490+ for (const auto & trklt : trklets.subspan (trigSel.getFirstTracklet (), trigSel.getNumberOfTracklets ())) {
491+ if (tracklet.getTrackletWord () == trklt.getTrackletWord () || tracklet.getDetector () != trklt.getDetector ()) {
492+ continue ;
493+ }
494+ if (std::abs (tracklet.getPadCol () - trklt.getPadCol ()) <= 1 && std::abs (tracklet.getPadRow () - trklt.getPadRow ()) == 1 ) {
495+ cor = mTRDLocalGain ->getValue (trklt.getHCID () / 2 , trklt.getPadCol (), trklt.getPadRow ()) * mTRDGainCalib ->getMPVdEdx (tracklet.getDetector ()) / o2::trd::constants::MPVDEDXDEFAULT * trackletLength;
496+ q0s[iLay] += trklt.getQ0 ();
497+ q1s[iLay] += trklt.getQ1 ();
498+ q2s[iLay] += trklt.getQ2 ();
499+ q0sCor[iLay] += (float )trklt.getQ0 () / cor;
500+ q1sCor[iLay] += (float )trklt.getQ1 () / cor;
501+ q2sCor[iLay] += (float )trklt.getQ2 () / cor;
502+ }
503+ }
504+ }
505+ }
506+
507+ trdExtraCursor (trkTableIdx, q0s, q1s, q2s, q0sCor, q1sCor, q2sCor, ttgls, tphis);
508+ }
509+
393510template <typename mftTracksCursorType, typename AmbigMFTTracksCursorType>
394511void AODProducerWorkflowDPL::addToMFTTracksTable (mftTracksCursorType& mftTracksCursor, AmbigMFTTracksCursorType& ambigMFTTracksCursor,
395512 GIndex trackID, const o2::globaltracking::RecoContainer& data, int collisionID,
@@ -430,8 +547,7 @@ void AODProducerWorkflowDPL::addToMFTTracksTable(mftTracksCursorType& mftTracksC
430547 ambigMFTTracksCursor (mTableTrMFTID , bcSlice);
431548 }
432549}
433-
434- template <typename TracksCursorType, typename TracksCovCursorType, typename TracksExtraCursorType, typename TracksQACursorType, typename AmbigTracksCursorType,
550+ template <typename TracksCursorType, typename TracksCovCursorType, typename TracksExtraCursorType, typename TracksQACursorType, typename TRDsExtraCursor, typename AmbigTracksCursorType,
435551 typename MFTTracksCursorType, typename MFTTracksCovCursorType, typename AmbigMFTTracksCursorType,
436552 typename FwdTracksCursorType, typename FwdTracksCovCursorType, typename AmbigFwdTracksCursorType, typename FwdTrkClsCursorType>
437553void AODProducerWorkflowDPL::fillTrackTablesPerCollision (int collisionID,
@@ -443,6 +559,7 @@ void AODProducerWorkflowDPL::fillTrackTablesPerCollision(int collisionID,
443559 TracksCovCursorType& tracksCovCursor,
444560 TracksExtraCursorType& tracksExtraCursor,
445561 TracksQACursorType& tracksQACursor,
562+ TRDsExtraCursor& trdsExtraCursor,
446563 AmbigTracksCursorType& ambigTracksCursor,
447564 MFTTracksCursorType& mftTracksCursor,
448565 MFTTracksCovCursorType& mftTracksCovCursor,
@@ -553,7 +670,9 @@ void AODProducerWorkflowDPL::fillTrackTablesPerCollision(int collisionID,
553670 addToTracksTable (tracksCursor, tracksCovCursor, trOrig, collisionID, aod::track::TrackIU);
554671 }
555672 addToTracksExtraTable (tracksExtraCursor, extraInfoHolder);
556-
673+ if (mEnableTRDextra && trackIndex.includesDet (GIndex::Source::TRD)) {
674+ addToTRDsExtra (data, trdsExtraCursor, trackIndex, mTableTrID );
675+ }
557676 // collecting table indices of barrel tracks for V0s table
558677 if (extraInfoHolder.bcSlice [0 ] >= 0 && collisionID < 0 ) {
559678 ambigTracksCursor (mTableTrID , extraInfoHolder.bcSlice );
@@ -1934,6 +2053,12 @@ void AODProducerWorkflowDPL::run(ProcessingContext& pc)
19342053 auto cpvClustersCursor = createTableCursor<o2::aod::CPVClusters>(pc);
19352054 auto originCursor = createTableCursor<o2::aod::Origins>(pc);
19362055
2056+ // / Extra tables
2057+ o2::framework::Produces<o2::aod::TRDsExtra> trdExtraCursor;
2058+ if (mEnableTRDextra ) {
2059+ trdExtraCursor = createTableCursor<o2::aod::TRDsExtra>(pc);
2060+ }
2061+
19372062 // Declare MC cursors type without adding the output for a table
19382063 o2::framework::Produces<o2::aod::McCollisionLabels> mcColLabelsCursor;
19392064 o2::framework::Produces<o2::aod::McCollisions> mcCollisionsCursor;
@@ -2294,14 +2419,16 @@ void AODProducerWorkflowDPL::run(ProcessingContext& pc)
22942419 }
22952420 }
22962421
2422+ mCurrentTRDTrigID = 0 ; // reinitialize index for TRD trigger record search
22972423 // filling unassigned tracks first
22982424 // so that all unassigned tracks are stored in the beginning of the table together
22992425 auto & trackRef = primVer2TRefs.back (); // references to unassigned tracks are at the end
23002426 // fixme: interaction time is undefined for unassigned tracks (?)
2301- fillTrackTablesPerCollision (-1 , std::uint64_t (-1 ), trackRef, primVerGIs, recoData, tracksCursor, tracksCovCursor, tracksExtraCursor, tracksQACursor,
2427+ fillTrackTablesPerCollision (-1 , std::uint64_t (-1 ), trackRef, primVerGIs, recoData, tracksCursor, tracksCovCursor, tracksExtraCursor, tracksQACursor, trdExtraCursor,
23022428 ambigTracksCursor, mftTracksCursor, mftTracksCovCursor, ambigMFTTracksCursor,
23032429 fwdTracksCursor, fwdTracksCovCursor, ambigFwdTracksCursor, fwdTrkClsCursor, bcsMap);
23042430
2431+ mCurrentTRDTrigID = 0 ; // reinitialize index for TRD trigger record search
23052432 // filling collisions and tracks into tables
23062433 collisionID = 0 ;
23072434 collisionsCursor.reserve (primVertices.size ());
@@ -2340,7 +2467,7 @@ void AODProducerWorkflowDPL::run(ProcessingContext& pc)
23402467
23412468 auto & trackRef = primVer2TRefs[collisionID];
23422469 // passing interaction time in [ps]
2343- fillTrackTablesPerCollision (collisionID, globalBC, trackRef, primVerGIs, recoData, tracksCursor, tracksCovCursor, tracksExtraCursor, tracksQACursor, ambigTracksCursor,
2470+ fillTrackTablesPerCollision (collisionID, globalBC, trackRef, primVerGIs, recoData, tracksCursor, tracksCovCursor, tracksExtraCursor, tracksQACursor, trdExtraCursor, ambigTracksCursor,
23442471 mftTracksCursor, mftTracksCovCursor, ambigMFTTracksCursor,
23452472 fwdTracksCursor, fwdTracksCovCursor, ambigFwdTracksCursor, fwdTrkClsCursor, bcsMap);
23462473 collisionID++;
@@ -3011,6 +3138,11 @@ void AODProducerWorkflowDPL::updateTimeDependentParams(ProcessingContext& pc)
30113138 mFieldON = std::abs (o2::base::Propagator::Instance ()->getNominalBz ()) > 0.01 ;
30123139
30133140 pc.inputs ().get <o2::ctp::CTPConfiguration*>(" ctpconfig" );
3141+ if (mEnableTRDextra ) {
3142+ mTRDLocalGain = pc.inputs ().get <o2::trd::LocalGainFactor*>(" trdlocalgainfactors" ).get ();
3143+ mTRDNoiseMap = pc.inputs ().get <o2::trd::NoiseStatusMCM*>(" trdnoisemap" ).get ();
3144+ mTRDGainCalib = pc.inputs ().get <o2::trd::CalGain*>(" trdgaincalib" ).get (); // time dependent gain
3145+ }
30143146 }
30153147 if (mPropTracks ) {
30163148 pc.inputs ().get <o2::dataformats::MeanVertexObject*>(" meanvtx" );
@@ -3222,7 +3354,7 @@ void AODProducerWorkflowDPL::endOfStream(EndOfStreamContext& /*ec*/)
32223354 mStreamer .reset ();
32233355}
32243356
3225- DataProcessorSpec getAODProducerWorkflowSpec (GID::mask_t src, bool enableSV, bool enableStrangenessTracking, bool useMC, bool CTPConfigPerRun, bool enableFITextra)
3357+ DataProcessorSpec getAODProducerWorkflowSpec (GID::mask_t src, bool enableSV, bool enableStrangenessTracking, bool useMC, bool CTPConfigPerRun, bool enableFITextra, bool enableTRDextra )
32263358{
32273359 auto dataRequest = std::make_shared<DataRequest>();
32283360 dataRequest->inputs .emplace_back (" ctpconfig" , " CTP" , " CTPCONFIG" , 0 , Lifetime::Condition, ccdbParamSpec (" CTP/Config/Config" , CTPConfigPerRun));
@@ -3313,6 +3445,13 @@ DataProcessorSpec getAODProducerWorkflowSpec(GID::mask_t src, bool enableSV, boo
33133445 OutputSpec{" TFF" , " TFFilename" },
33143446 OutputSpec{" AMD" , " AODMetadataKeys" },
33153447 OutputSpec{" AMD" , " AODMetadataVals" }};
3448+ // / Extra tables
3449+ if (enableTRDextra) {
3450+ outputs.push_back (OutputForTable<TRDsExtra>::spec ());
3451+ dataRequest->inputs .emplace_back (" trdlocalgainfactors" , " TRD" , " LOCALGAINFACTORS" , 0 , Lifetime::Condition, ccdbParamSpec (" TRD/Calib/LocalGainFactor" ));
3452+ dataRequest->inputs .emplace_back (" trdnoisemap" , " TRD" , " NOISEMAP" , 0 , Lifetime::Condition, ccdbParamSpec (" TRD/Calib/NoiseMapMCM" ));
3453+ dataRequest->inputs .emplace_back (" trdgaincalib" , " TRD" , " CALGAIN" , 0 , Lifetime::Condition, ccdbParamSpec (" TRD/Calib/CalGain" ));
3454+ }
33163455
33173456 if (useMC) {
33183457 outputs.insert (outputs.end (),
@@ -3336,7 +3475,7 @@ DataProcessorSpec getAODProducerWorkflowSpec(GID::mask_t src, bool enableSV, boo
33363475 " aod-producer-workflow" ,
33373476 dataRequest->inputs ,
33383477 outputs,
3339- AlgorithmSpec{adaptFromTask<AODProducerWorkflowDPL>(src, dataRequest, ggRequest, enableSV, useMC, enableFITextra)},
3478+ AlgorithmSpec{adaptFromTask<AODProducerWorkflowDPL>(src, dataRequest, ggRequest, enableSV, useMC, enableFITextra, enableTRDextra )},
33403479 Options{
33413480 ConfigParamSpec{" run-number" , VariantType::Int64, -1L , {" The run-number. If left default we try to get it from DPL header." }},
33423481 ConfigParamSpec{" aod-timeframe-id" , VariantType::Int64, -1L , {" Set timeframe number" }},
0 commit comments