@@ -152,8 +152,8 @@ struct Photonhbt {
152152 };
153153
154154 struct CrossObs {
155- std::array<float , 2 > mee{999 .f , 999 .f }; // crossed m(e+e-) per combo
156- std::array< float , 2 > dist {999 .f , 999 . f }; // crossed line-line distance (cm)
155+ std::array<float , 2 > mee{999 .f , 999 .f };
156+ float meeOverQ {999 .f };
157157 };
158158
159159 struct TruthGamma {
@@ -350,8 +350,7 @@ struct Photonhbt {
350350 std::string prefix = " crosspair_group" ;
351351 Configurable<bool > cfgDoCrossPairQA{" cfgDoCrossPairQA" , false , " fill crossed-hypothesis QA (mee_cross, dist_cross vs qinv) for pairs passing all other pair cuts; SE and ME" };
352352 Configurable<bool > cfgDoCrossPairCut{" cfgDoCrossPairCut" , false , " reject pairs with a photon-like crossed combination; applied to SE AND ME" };
353- Configurable<float > cfgCrossMaxMee{" cfgCrossMaxMee" , 0 .04f , " veto: crossed m_ee below this (GeV/c^2)" };
354- Configurable<float > cfgCrossMaxDist{" cfgCrossMaxDist" , 1 .0f , " veto: crossed line-line distance below this (cm)" };
353+ Configurable<float > cfgCrossMaxMeeRatio{" cfgCrossMaxMeeRatio" , 0 .2f , " veto: min(m_ee^cross)/q_inv below this; genuine pairs sit near 0.5, leg swaps near 0" };
355354 Configurable<float > cfgCrossMaxQinvQA{" cfgCrossMaxQinvQA" , 0 .3f , " fill crossed QA sparses only below this qinv" };
356355 } crosspair;
357356
@@ -752,9 +751,9 @@ struct Photonhbt {
752751 return ;
753752 }
754753 for (const auto & sm : {std::string (" Pair/same/CrossPair/" ), std::string (" Pair/mix/CrossPair/" )}) {
755- fRegistryCF .add ((sm + " hSparse_Mee_Dist_Qinv " ).c_str (),
756- " crossed-hypothesis QA;m_{ee}^{cross} (GeV/c^{2});crossed line distance (cm);q_{inv} (GeV/c)" ,
757- kTHnSparseF , {{100 , 0 .f , 0 . 1f }, {100 , 0 .f , 10 .f }, {60 , 0 .f , 0 .3f }}, true );
754+ fRegistryCF .add ((sm + " hSparse_MeeRatio_dR_Qinv " ).c_str (),
755+ " crossed-hypothesis QA;min( m_{ee}^{cross})/q_{inv};|R_{1}-R_{2}| (cm);q_{inv} (GeV/c)" ,
756+ kTHnSparseF , {{100 , 0 .f , 2 . f }, {80 , 0 .f , 80 .f }, {60 , 0 .f , 0 .3f }}, true );
758757 auto h = fRegistryCF .add <TH1 >((sm + " hVetoCounter" ).c_str (), " crossed-pair veto;;pairs" , kTH1D , {{2 , -0 .5f , 1 .5f }}, true );
759758 h->GetXaxis ()->SetBinLabel (1 , " evaluated" );
760759 h->GetXaxis ()->SetBinLabel (2 , " vetoed" );
@@ -1307,42 +1306,22 @@ struct Photonhbt {
13071306 return s.u > pairsep.cfgUCut .value ;
13081307 }
13091308
1310- [[nodiscard]] static float lineLineDistance (std::array<float , 3 > const & o1, std::array<float , 3 > const & d1,
1311- std::array<float , 3 > const & o2, std::array<float , 3 > const & d2)
1312- {
1313- const std::array<float , 3 > w = {o2[0 ] - o1[0 ], o2[1 ] - o1[1 ], o2[2 ] - o1[2 ]};
1314- const std::array<float , 3 > n = {d1[1 ] * d2[2 ] - d1[2 ] * d2[1 ],
1315- d1[2 ] * d2[0 ] - d1[0 ] * d2[2 ],
1316- d1[0 ] * d2[1 ] - d1[1 ] * d2[0 ]};
1317- const float nMag = std::sqrt (n[0 ] * n[0 ] + n[1 ] * n[1 ] + n[2 ] * n[2 ]);
1318- const float d1Mag2 = d1[0 ] * d1[0 ] + d1[1 ] * d1[1 ] + d1[2 ] * d1[2 ];
1319- if (nMag < 1e-6f * d1Mag2) { // o2-linter: disable=magic-number (near-parallel: point-to-line distance)
1320- const float wDotD = (w[0 ] * d1[0 ] + w[1 ] * d1[1 ] + w[2 ] * d1[2 ]) / d1Mag2;
1321- const std::array<float , 3 > perp = {w[0 ] - wDotD * d1[0 ], w[1 ] - wDotD * d1[1 ], w[2 ] - wDotD * d1[2 ]};
1322- return std::sqrt (perp[0 ] * perp[0 ] + perp[1 ] * perp[1 ] + perp[2 ] * perp[2 ]);
1323- }
1324- return std::fabs (w[0 ] * n[0 ] + w[1 ] * n[1 ] + w[2 ] * n[2 ]) / nMag;
1325- }
1326-
1327- [[nodiscard]] CrossObs computeCrossObs (PhotonWithLegs const & a, PhotonWithLegs const & b) const
1309+ [[nodiscard]] CrossObs computeCrossObs (PhotonWithLegs const & a, PhotonWithLegs const & b, float qinv) const
13281310 {
13291311 constexpr float kMe = 0 .000510999f ; // electron mass, GeV/c^2
13301312 CrossObs c;
13311313 auto legVec = [](PhotonWithLegs const & p, int i) {
13321314 return ROOT::Math::PtEtaPhiMVector (p.fLegPt [i], p.fLegEta [i], p.fLegPhi [i], kMe );
13331315 };
1334- auto legDir = [](PhotonWithLegs const & p, int i) -> std::array<float , 3 > {
1335- return {p.fLegPt [i] * std::cos (p.fLegPhi [i]), p.fLegPt [i] * std::sin (p.fLegPhi [i]),
1336- p.fLegPt [i] * std::sinh (p.fLegEta [i])};
1337- };
13381316 // Leg index 0 = e+, 1 = e- (makePhotonWithLegs filling order).
13391317 // Combo 0: a's e+ with b's e-. Combo 1: b's e+ with a's e-.
1340- for (int combo = 0 ; combo < 2 ; ++combo) { // o2-linter: disable=magic-number (combinations of fake photons )
1318+ for (int combo = 0 ; combo < 2 ; ++combo) { // o2-linter: disable=magic-number (the two leg-swap combinations )
13411319 PhotonWithLegs const & pPos = (combo == 0 ) ? a : b;
13421320 PhotonWithLegs const & pEle = (combo == 0 ) ? b : a;
13431321 c.mee [combo] = static_cast <float >((legVec (pPos, 0 ) + legVec (pEle, 1 )).M ());
1344- c.dist [combo] = lineLineDistance ({pPos.fVx , pPos.fVy , pPos.fVz }, legDir (pPos, 0 ),
1345- {pEle.fVx , pEle.fVy , pEle.fVz }, legDir (pEle, 1 ));
1322+ }
1323+ if (qinv > 0 .f ) {
1324+ c.meeOverQ = std::min (c.mee [0 ], c.mee [1 ]) / qinv;
13461325 }
13471326 return c;
13481327 }
@@ -1352,25 +1331,19 @@ struct Photonhbt {
13521331 if (!crosspair.cfgDoCrossPairCut .value ) {
13531332 return true ;
13541333 }
1355- for (int i = 0 ; i < 2 ; ++i) { // o2-linter: disable=magic-number (combinations of fake photons)
1356- if (c.mee [i] < crosspair.cfgCrossMaxMee .value && c.dist [i] < crosspair.cfgCrossMaxDist .value ) {
1357- return false ;
1358- }
1359- }
1360- return true ;
1334+ // A photon-like crossed combination means the pairing is ambiguous.
1335+ return c.meeOverQ > crosspair.cfgCrossMaxMeeRatio .value ;
13611336 }
13621337
13631338 template <int ev_id>
1364- inline void fillCrossPair (CrossObs const & c, float qinv, bool vetoed)
1339+ inline void fillCrossPair (CrossObs const & c, float qinv, float deltaR, bool vetoed)
13651340 {
13661341 constexpr auto dir = (ev_id == 0 ) ? " Pair/same/CrossPair/" : " Pair/mix/CrossPair/" ;
13671342 fRegistryCF .fill (HIST (dir) + HIST (" hVetoCounter" ), vetoed ? 1.0 : 0.0 );
13681343 if (qinv > crosspair.cfgCrossMaxQinvQA .value ) {
13691344 return ;
13701345 }
1371- for (int i = 0 ; i < 2 ; ++i) { // o2-linter: disable=magic-number (combinations of fake photons)
1372- fRegistryCF .fill (HIST (dir) + HIST (" hSparse_Mee_Dist_Qinv" ), c.mee [i], c.dist [i], qinv);
1373- }
1346+ fRegistryCF .fill (HIST (dir) + HIST (" hSparse_MeeRatio_dR_Qinv" ), c.meeOverQ , deltaR, qinv);
13741347 }
13751348
13761349 [[nodiscard]] float uTrue (TruthGamma const & g1, TruthGamma const & g2) const
@@ -2043,9 +2016,9 @@ struct Photonhbt {
20432016 continue ;
20442017 }
20452018 if (crosspair.cfgDoCrossPairQA .value || crosspair.cfgDoCrossPairCut .value ) {
2046- const auto cross = computeCrossObs (pwl1, pwl2);
2019+ const auto cross = computeCrossObs (pwl1, pwl2, obs. qinv );
20472020 const bool vetoed = !passCrossPairVeto (cross);
2048- fillCrossPair<0 >(cross, obs.qinv , vetoed);
2021+ fillCrossPair<0 >(cross, obs.qinv , obs. deltaR , vetoed);
20492022 if (vetoed) {
20502023 continue ;
20512024 }
@@ -2141,9 +2114,9 @@ struct Photonhbt {
21412114 continue ;
21422115 }
21432116 if (crosspair.cfgDoCrossPairQA .value || crosspair.cfgDoCrossPairCut .value ) {
2144- const auto cross = computeCrossObs (g1, g2);
2117+ const auto cross = computeCrossObs (g1, g2, obs. qinv );
21452118 const bool vetoed = !passCrossPairVeto (cross);
2146- fillCrossPair<1 >(cross, obs.qinv , vetoed);
2119+ fillCrossPair<1 >(cross, obs.qinv , obs. deltaR , vetoed);
21472120 if (vetoed) {
21482121 continue ;
21492122 }
@@ -2271,9 +2244,9 @@ struct Photonhbt {
22712244 continue ;
22722245 }
22732246 if (crosspair.cfgDoCrossPairQA .value || crosspair.cfgDoCrossPairCut .value ) {
2274- const auto cross = computeCrossObs (pwl1, pwl2);
2247+ const auto cross = computeCrossObs (pwl1, pwl2, obs. qinv );
22752248 const bool vetoed = !passCrossPairVeto (cross);
2276- fillCrossPair<0 >(cross, obs.qinv , vetoed);
2249+ fillCrossPair<0 >(cross, obs.qinv , obs. deltaR , vetoed);
22772250 if (vetoed) {
22782251 continue ;
22792252 }
@@ -2422,9 +2395,9 @@ struct Photonhbt {
24222395 continue ;
24232396 }
24242397 if (crosspair.cfgDoCrossPairQA .value || crosspair.cfgDoCrossPairCut .value ) {
2425- const auto cross = computeCrossObs (g1, g2);
2398+ const auto cross = computeCrossObs (g1, g2, obs. qinv );
24262399 const bool vetoed = !passCrossPairVeto (cross);
2427- fillCrossPair<1 >(cross, obs.qinv , vetoed);
2400+ fillCrossPair<1 >(cross, obs.qinv , obs. deltaR , vetoed);
24282401 if (vetoed) {
24292402 continue ;
24302403 }
@@ -2735,7 +2708,7 @@ struct Photonhbt {
27352708 fRegistryTruthMC .fill (HIST (" MC/TruthAO2D/hQinvVsKt_all4LegsThisColl" ), kt, qinv_true);
27362709 fRegistryTruthMC .fill (HIST (" MC/TruthAO2D/hDEtaDPhi_all4LegsThisColl" ), deta, dphi);
27372710 }
2738- if (g1Sel && g2Sel ) {
2711+ if (g1Built && g2Built ) {
27392712 fRegistryTruthMC .fill (HIST (" MC/TruthAO2D/hSparse_DEtaDPhi_qinv_bothPhotonsBuilt" ), deta, dphi, qinv_true);
27402713 fRegistryTruthMC .fill (HIST (" MC/TruthAO2D/hSparse_DEtaDPhi_kT_bothPhotonsBuilt" ), deta, dphi, kt);
27412714 fRegistryTruthMC .fill (HIST (" MC/TruthAO2D/hQinvVsKt_bothPhotonsBuilt" ), kt, qinv_true);
0 commit comments