@@ -94,6 +94,12 @@ enum MatCorrType {
9494 LUT = 2
9595};
9696
97+ enum TrackPropMode {
98+ kProper = 0 ,
99+ kFast = 1 ,
100+ kBoth = 2
101+ };
102+
97103struct PhotonConversionBuilder {
98104 Produces<aod::V0PhotonsKF> v0photonskf;
99105 Produces<aod::V0Legs> v0legs;
@@ -114,6 +120,7 @@ struct PhotonConversionBuilder {
114120 // Operation and minimisation criteria
115121 Configurable<double > d_bz_input{" d_bz" , -999 , " bz field, -999 is automatic" };
116122 Configurable<int > useMatCorrType{" useMatCorrType" , 0 , " 0: none, 1: TGeo, 2: LUT" };
123+ Configurable<int > modeTrackPropagation{" modeTrackPropagation" , 0 , " 0: use real track propagation, including material, 1: use fast approximation using only geometry, 2: Use real track propagation and make comparison to fast propagation (only for debugging and testing)" };
117124
118125 // single track cuts
119126 Configurable<int > min_ncluster_tpc{" min_ncluster_tpc" , 0 , " min ncluster tpc" };
@@ -325,6 +332,14 @@ struct PhotonConversionBuilder {
325332 registry.add (" V0/hBDTScoreAfterCutVsPt" , " BDT score after cut vs pT; pT (GeV/c); BDT score" , {HistType::kTH2F , {{1000 , 0 .0f , 20 .0f }, {1000 , 0 .0f , 1 .0f }}});
326333 }
327334 }
335+
336+ // Compare proper propagation and fast geometrical propagation
337+ if (modeTrackPropagation == TrackPropMode::kBoth ) {
338+ registry.add (" V0Leg/hDCAxyPropagationCompare" , " Comparison of DCA_{xy} propagation;DCA_{xy} (cm) proper propagation; DCA_{xy} (cm) geom. propagation" , {HistType::kTH2F , {{200 , -10 ., 10 .}, {200 , -10 ., 10 .}}});
339+ registry.add (" V0Leg/hDCAzPropagationCompare" , " Comparison of DCA_{z} propagation;DCA_{z} (cm) proper propagation; DCA_{z} (cm) geom. propagation" , {HistType::kTH2F , {{200 , -10 ., 10 .}, {200 , -10 ., 10 .}}});
340+ registry.add (" V0/hPhivPropagationCompare" , " Comparison of #phi_{v};#phi_{v} proper propagation; #phi_{v} geom. propagation" , {HistType::kTH2F , {{100 , 0 ., 1.6 }, {100 , 0 ., 1.6 }}});
341+ registry.add (" V0/hPsiPairPropagationCompare" , " Comparison of #Psi_{pair};#Psi_{pair} proper propagation; #Psi_{pair} geom. propagation" , {HistType::kTH2F , {{100 , 0 ., 1.6 }, {100 , 0 ., 1.6 }}});
342+ }
328343 }
329344
330345 void initCCDB (aod::BCsWithTimestamps::iterator const & bc)
@@ -555,8 +570,23 @@ struct PhotonConversionBuilder {
555570 return ;
556571 }
557572 auto pTrackC = pTrack;
573+ o2::math_utils::Point3D<float > vtxPrim{
574+ collision.posX (),
575+ collision.posY (),
576+ collision.posZ ()};
577+ if (modeTrackPropagation != TrackPropMode::kProper ) {
578+ dcaInfo = CalculateDCAFast (pTrackC, vtxPrim, d_bz);
579+ }
558580 pTrackC.setPID (o2::track::PID ::Electron);
559- o2::base::Propagator::Instance ()->propagateToDCABxByBz ({collision.posX (), collision.posY (), collision.posZ ()}, pTrackC, 2 .f , matCorr, &dcaInfo);
581+
582+ std::array<float , 2 > dcaInfoFast = dcaInfo;
583+ if (modeTrackPropagation != TrackPropMode::kFast ) {
584+ o2::base::Propagator::Instance ()->propagateToDCABxByBz ({collision.posX (), collision.posY (), collision.posZ ()}, pTrackC, 2 .f , matCorr, &dcaInfo);
585+ if (modeTrackPropagation == TrackPropMode::kBoth ) {
586+ registry.fill (HIST (" V0Leg/hDCAxyPropagationCompare" ), dcaInfo[0 ], dcaInfoFast[0 ]);
587+ registry.fill (HIST (" V0Leg/hDCAzPropagationCompare" ), dcaInfo[1 ], dcaInfoFast[1 ]);
588+ }
589+ }
560590 auto posdcaXY = dcaInfo[0 ];
561591 auto posdcaZ = dcaInfo[1 ];
562592
@@ -566,8 +596,19 @@ struct PhotonConversionBuilder {
566596 return ;
567597 }
568598 auto nTrackC = nTrack;
599+ if (modeTrackPropagation != TrackPropMode::kProper ) {
600+ dcaInfo = CalculateDCAFast (nTrackC, vtxPrim, d_bz);
601+ }
569602 nTrackC.setPID (o2::track::PID ::Electron);
570- o2::base::Propagator::Instance ()->propagateToDCABxByBz ({collision.posX (), collision.posY (), collision.posZ ()}, nTrackC, 2 .f , matCorr, &dcaInfo);
603+
604+ dcaInfoFast = dcaInfo;
605+ if (modeTrackPropagation != TrackPropMode::kFast ) {
606+ o2::base::Propagator::Instance ()->propagateToDCABxByBz ({collision.posX (), collision.posY (), collision.posZ ()}, nTrackC, 2 .f , matCorr, &dcaInfo);
607+ if (modeTrackPropagation == TrackPropMode::kBoth ) {
608+ registry.fill (HIST (" V0Leg/hDCAxyPropagationCompare" ), dcaInfo[0 ], dcaInfoFast[0 ]);
609+ registry.fill (HIST (" V0Leg/hDCAzPropagationCompare" ), dcaInfo[1 ], dcaInfoFast[1 ]);
610+ }
611+ }
571612 auto eledcaXY = dcaInfo[0 ];
572613 auto eledcaZ = dcaInfo[1 ];
573614
@@ -587,30 +628,69 @@ struct PhotonConversionBuilder {
587628
588629 float phiv = 999 .f ;
589630 float psipair = 999 .f ;
631+ float phivFast = 999 .f ;
632+ float psipairFast = 999 .f ;
590633 float baseR = std::hypot (xyz[0 ], xyz[1 ]);
591- std::array<float , 3 > offsetsR = {propV0LegsRadius, 30 .f , 10 .f };
592- bool pPropagatedSuccess = false ;
593- bool nPropagatedSuccess = false ;
594- auto pTrackProp = pTrack;
595- auto nTrackProp = nTrack;
596- for (const float & offsetR : offsetsR) {
597- pTrackProp = pTrack;
598- pTrackProp.setPID (o2::track::PID ::Electron);
599- nTrackProp = nTrack;
600- nTrackProp.setPID (o2::track::PID ::Electron);
601- o2::base::Propagator::Instance ()->propagateToDCABxByBz ({collision.posX (), collision.posY (), collision.posZ ()}, pTrackProp, 2 .f , matCorr, &dcaInfo);
602- o2::base::Propagator::Instance ()->propagateToDCABxByBz ({collision.posX (), collision.posY (), collision.posZ ()}, nTrackProp, 2 .f , matCorr, &dcaInfo);
603- pPropagatedSuccess = o2::base::Propagator::Instance ()->propagateToR (pTrackProp, baseR + offsetR);
604- nPropagatedSuccess = o2::base::Propagator::Instance ()->propagateToR (nTrackProp, baseR + offsetR);
605- if (pPropagatedSuccess && nPropagatedSuccess) {
606- KFPTrack kfp_track_posProp = createKFPTrackFromTrackParCov (pTrackProp, pos.sign (), pos.tpcNClsFound (), pos.tpcChi2NCl ());
607- KFPTrack kfp_track_eleProp = createKFPTrackFromTrackParCov (nTrackProp, ele.sign (), ele.tpcNClsFound (), ele.tpcChi2NCl ());
608- phiv = o2::aod::pwgem::dilepton::utils::pairutil::getPhivPair (kfp_track_posProp.GetPx (), kfp_track_posProp.GetPy (), kfp_track_posProp.GetPz (), kfp_track_eleProp.GetPx (), kfp_track_eleProp.GetPy (), kfp_track_eleProp.GetPz (), pos.sign (), ele.sign (), d_bz);
609- psipair = o2::aod::pwgem::dilepton::utils::pairutil::getPsiPair (kfp_track_posProp.GetPx (), kfp_track_posProp.GetPy (), kfp_track_posProp.GetPz (), kfp_track_eleProp.GetPx (), kfp_track_eleProp.GetPy (), kfp_track_eleProp.GetPz ());
610- break ;
634+ // This method uses the track Helix instead of the full propagation.
635+ // Hence, it is only an approximation but much faster
636+ if (modeTrackPropagation != TrackPropMode::kProper ) {
637+
638+ o2::track::TrackAuxPar helixPosEle (nTrack, d_bz);
639+ o2::track::TrackAuxPar helixPosPos (pTrack, d_bz);
640+
641+ float diffX = helixPosEle.xC - helixPosPos.xC ;
642+ float diffY = helixPosEle.yC - helixPosPos.yC ;
643+ auto phiHelix = RecoDecay::constrainAngle<float , float >(std::atan2 (diffY, diffX) - o2::constants::math::PI / 2 .);
644+
645+ // Electron
646+ float arcLenghtEle = helixPosEle.rC * 0.9 > propV0LegsRadius ? std::asin (propV0LegsRadius / helixPosEle.rC ) * helixPosEle.rC : o2::constants::math::PI / 2.2 * helixPosEle.rC ; // This assumes that the photon momentum vector is a tangent of the circle
647+ auto propTrackEle = getPropMomentumFromTrackHelix (arcLenghtEle, ele, helixPosEle, d_bz / 10 ., phiHelix - ele.phi ());
648+ // Positron
649+ float arcLenghtPos = helixPosPos.rC * 0.9 > propV0LegsRadius ? std::asin (propV0LegsRadius / helixPosPos.rC ) * helixPosPos.rC : o2::constants::math::PI / 2.2 * helixPosPos.rC ; // This assumes that the photon momentum vector is a tangent of the circle
650+ auto propTrackPos = getPropMomentumFromTrackHelix (arcLenghtPos, pos, helixPosPos, d_bz / 10 ., phiHelix - pos.phi ());
651+
652+ phiv = o2::aod::pwgem::dilepton::utils::pairutil::getPhivPair (propTrackPos[0 ], propTrackPos[1 ], propTrackPos[2 ], propTrackEle[0 ], propTrackEle[1 ], propTrackEle[2 ], pos.sign (), ele.sign (), d_bz);
653+ psipair = o2::aod::pwgem::dilepton::utils::pairutil::getPsiPair (propTrackPos[0 ], propTrackPos[1 ], propTrackPos[2 ], propTrackEle[0 ], propTrackEle[1 ], propTrackEle[2 ]);
654+
655+ // Store values for later comparison
656+ phivFast = phiv;
657+ psipairFast = psipair;
658+ }
659+ // This uses the full propagation including material effects
660+ if (modeTrackPropagation != TrackPropMode::kFast ) {
661+ std::array<float , 3 > offsetsR = {propV0LegsRadius, 30 .f , 10 .f };
662+ bool pPropagatedSuccess = false ;
663+ bool nPropagatedSuccess = false ;
664+ auto pTrackProp = pTrack;
665+ auto nTrackProp = nTrack;
666+ for (const auto & offsetR : offsetsR) {
667+ pTrackProp = pTrack;
668+ pTrackProp.setPID (o2::track::PID ::Electron);
669+ nTrackProp = nTrack;
670+ nTrackProp.setPID (o2::track::PID ::Electron);
671+
672+ o2::base::Propagator::Instance ()->propagateToDCABxByBz ({collision.posX (), collision.posY (), collision.posZ ()}, pTrackProp, 2 .f , matCorr, &dcaInfo);
673+ o2::base::Propagator::Instance ()->propagateToDCABxByBz ({collision.posX (), collision.posY (), collision.posZ ()}, nTrackProp, 2 .f , matCorr, &dcaInfo);
674+
675+ pPropagatedSuccess = o2::base::Propagator::Instance ()->propagateToR (pTrackProp, baseR + offsetR);
676+ nPropagatedSuccess = o2::base::Propagator::Instance ()->propagateToR (nTrackProp, baseR + offsetR);
677+
678+ if (pPropagatedSuccess && nPropagatedSuccess) {
679+ KFPTrack kfp_track_posProp = createKFPTrackFromTrackParCov (pTrackProp, pos.sign (), pos.tpcNClsFound (), pos.tpcChi2NCl ());
680+ KFPTrack kfp_track_eleProp = createKFPTrackFromTrackParCov (nTrackProp, ele.sign (), ele.tpcNClsFound (), ele.tpcChi2NCl ());
681+ phiv = o2::aod::pwgem::dilepton::utils::pairutil::getPhivPair (kfp_track_posProp.GetPx (), kfp_track_posProp.GetPy (), kfp_track_posProp.GetPz (), kfp_track_eleProp.GetPx (), kfp_track_eleProp.GetPy (), kfp_track_eleProp.GetPz (), pos.sign (), ele.sign (), d_bz);
682+ psipair = o2::aod::pwgem::dilepton::utils::pairutil::getPsiPair (kfp_track_posProp.GetPx (), kfp_track_posProp.GetPy (), kfp_track_posProp.GetPz (), kfp_track_eleProp.GetPx (), kfp_track_eleProp.GetPy (), kfp_track_eleProp.GetPz ());
683+ break ;
684+ } else {
685+ LOG (debug) << " Propagation to offset" << offsetR << " cm failed for " << (pPropagatedSuccess ? " negative" : " positive" ) << " track. Trying smaller offset." ;
686+ }
687+ }
688+ if (modeTrackPropagation == TrackPropMode::kBoth ) {
689+ registry.fill (HIST (" V0/hPhivPropagationCompare" ), phiv, phivFast);
690+ registry.fill (HIST (" V0/hPsiPairPropagationCompare" ), psipair, psipairFast);
611691 }
612- LOG (debug) << " Propagation to offset" << offsetR << " cm failed for " << (pPropagatedSuccess ? " negative" : " positive" ) << " track. Trying smaller offset." ;
613692 }
693+
614694 if (phiv == 999 .f || psipair == 999 .f ) {
615695 LOG (debug) << " Propagation failed for all radii (" << propV0LegsRadius << " , 30, 10 cm). Using default values for phiv and psipair (999.f)." ;
616696 }
@@ -985,14 +1065,14 @@ struct PhotonConversionBuilder {
9851065 fillV0Table<isMC, TBCs, TCollisions, TTracks>(v0, true );
9861066 } // end of fullv0Id loop
9871067
988- for (const auto & collision : collisions) {
989- if constexpr (isMC) {
990- if (!collision.has_mcCollision ()) {
991- continue ;
992- }
993- }
994- // events_ngpcm(nv0_map[collision.globalIndex()]);
995- } // end of collision loop
1068+ // for (const auto& collision : collisions) {
1069+ // if constexpr (isMC) {
1070+ // if (!collision.has_mcCollision()) {
1071+ // continue;
1072+ // }
1073+ // }
1074+ // // events_ngpcm(nv0_map[collision.globalIndex()]);
1075+ // } // end of collision loop
9961076
9971077 pca_map.clear ();
9981078 cospa_map.clear ();
0 commit comments