@@ -150,8 +150,8 @@ struct Photonhbt {
150150 };
151151
152152 struct CrossObs {
153- std::array<float , 2 > mee{999 .f , 999 .f }; // crossed m(e+e-) per combo
154- std::array< float , 2 > dist {999 .f , 999 . f }; // crossed line-line distance (cm)
153+ std::array<float , 2 > mee{999 .f , 999 .f };
154+ float meeOverQ {999 .f };
155155 };
156156
157157 struct TruthGamma {
@@ -345,8 +345,7 @@ struct Photonhbt {
345345 std::string prefix = " crosspair_group" ;
346346 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" };
347347 Configurable<bool > cfgDoCrossPairCut{" cfgDoCrossPairCut" , false , " reject pairs with a photon-like crossed combination; applied to SE AND ME" };
348- Configurable<float > cfgCrossMaxMee{" cfgCrossMaxMee" , 0 .04f , " veto: crossed m_ee below this (GeV/c^2)" };
349- Configurable<float > cfgCrossMaxDist{" cfgCrossMaxDist" , 1 .0f , " veto: crossed line-line distance below this (cm)" };
348+ 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" };
350349 Configurable<float > cfgCrossMaxQinvQA{" cfgCrossMaxQinvQA" , 0 .3f , " fill crossed QA sparses only below this qinv" };
351350 } crosspair;
352351
@@ -736,9 +735,9 @@ struct Photonhbt {
736735 return ;
737736 }
738737 for (const auto & sm : {std::string (" Pair/same/CrossPair/" ), std::string (" Pair/mix/CrossPair/" )}) {
739- fRegistryCF .add ((sm + " hSparse_Mee_Dist_Qinv " ).c_str (),
740- " crossed-hypothesis QA;m_{ee}^{cross} (GeV/c^{2});crossed line distance (cm);q_{inv} (GeV/c)" ,
741- kTHnSparseF , {{100 , 0 .f , 0 . 1f }, {100 , 0 .f , 10 .f }, {60 , 0 .f , 0 .3f }}, true );
738+ fRegistryCF .add ((sm + " hSparse_MeeRatio_dR_Qinv " ).c_str (),
739+ " crossed-hypothesis QA;min( m_{ee}^{cross})/q_{inv};|R_{1}-R_{2}| (cm);q_{inv} (GeV/c)" ,
740+ kTHnSparseF , {{100 , 0 .f , 2 . f }, {80 , 0 .f , 80 .f }, {60 , 0 .f , 0 .3f }}, true );
742741 auto h = fRegistryCF .add <TH1 >((sm + " hVetoCounter" ).c_str (), " crossed-pair veto;;pairs" , kTH1D , {{2 , -0 .5f , 1 .5f }}, true );
743742 h->GetXaxis ()->SetBinLabel (1 , " evaluated" );
744743 h->GetXaxis ()->SetBinLabel (2 , " vetoed" );
@@ -1274,42 +1273,22 @@ struct Photonhbt {
12741273 return s.u > pairsep.cfgUCut .value ;
12751274 }
12761275
1277- [[nodiscard]] static float lineLineDistance (std::array<float , 3 > const & o1, std::array<float , 3 > const & d1,
1278- std::array<float , 3 > const & o2, std::array<float , 3 > const & d2)
1279- {
1280- const std::array<float , 3 > w = {o2[0 ] - o1[0 ], o2[1 ] - o1[1 ], o2[2 ] - o1[2 ]};
1281- const std::array<float , 3 > n = {d1[1 ] * d2[2 ] - d1[2 ] * d2[1 ],
1282- d1[2 ] * d2[0 ] - d1[0 ] * d2[2 ],
1283- d1[0 ] * d2[1 ] - d1[1 ] * d2[0 ]};
1284- const float nMag = std::sqrt (n[0 ] * n[0 ] + n[1 ] * n[1 ] + n[2 ] * n[2 ]);
1285- const float d1Mag2 = d1[0 ] * d1[0 ] + d1[1 ] * d1[1 ] + d1[2 ] * d1[2 ];
1286- if (nMag < 1e-6f * d1Mag2) { // o2-linter: disable=magic-number (near-parallel: point-to-line distance)
1287- const float wDotD = (w[0 ] * d1[0 ] + w[1 ] * d1[1 ] + w[2 ] * d1[2 ]) / d1Mag2;
1288- const std::array<float , 3 > perp = {w[0 ] - wDotD * d1[0 ], w[1 ] - wDotD * d1[1 ], w[2 ] - wDotD * d1[2 ]};
1289- return std::sqrt (perp[0 ] * perp[0 ] + perp[1 ] * perp[1 ] + perp[2 ] * perp[2 ]);
1290- }
1291- return std::fabs (w[0 ] * n[0 ] + w[1 ] * n[1 ] + w[2 ] * n[2 ]) / nMag;
1292- }
1293-
1294- [[nodiscard]] CrossObs computeCrossObs (PhotonWithLegs const & a, PhotonWithLegs const & b) const
1276+ [[nodiscard]] CrossObs computeCrossObs (PhotonWithLegs const & a, PhotonWithLegs const & b, float qinv) const
12951277 {
12961278 constexpr float kMe = 0 .000510999f ; // electron mass, GeV/c^2
12971279 CrossObs c;
12981280 auto legVec = [](PhotonWithLegs const & p, int i) {
12991281 return ROOT::Math::PtEtaPhiMVector (p.fLegPt [i], p.fLegEta [i], p.fLegPhi [i], kMe );
13001282 };
1301- auto legDir = [](PhotonWithLegs const & p, int i) -> std::array<float , 3 > {
1302- return {p.fLegPt [i] * std::cos (p.fLegPhi [i]), p.fLegPt [i] * std::sin (p.fLegPhi [i]),
1303- p.fLegPt [i] * std::sinh (p.fLegEta [i])};
1304- };
13051283 // Leg index 0 = e+, 1 = e- (makePhotonWithLegs filling order).
13061284 // Combo 0: a's e+ with b's e-. Combo 1: b's e+ with a's e-.
1307- for (int combo = 0 ; combo < 2 ; ++combo) { // o2-linter: disable=magic-number (combinations of fake photons )
1285+ for (int combo = 0 ; combo < 2 ; ++combo) { // o2-linter: disable=magic-number (the two leg-swap combinations )
13081286 PhotonWithLegs const & pPos = (combo == 0 ) ? a : b;
13091287 PhotonWithLegs const & pEle = (combo == 0 ) ? b : a;
13101288 c.mee [combo] = static_cast <float >((legVec (pPos, 0 ) + legVec (pEle, 1 )).M ());
1311- c.dist [combo] = lineLineDistance ({pPos.fVx , pPos.fVy , pPos.fVz }, legDir (pPos, 0 ),
1312- {pEle.fVx , pEle.fVy , pEle.fVz }, legDir (pEle, 1 ));
1289+ }
1290+ if (qinv > 0 .f ) {
1291+ c.meeOverQ = std::min (c.mee [0 ], c.mee [1 ]) / qinv;
13131292 }
13141293 return c;
13151294 }
@@ -1319,25 +1298,19 @@ struct Photonhbt {
13191298 if (!crosspair.cfgDoCrossPairCut .value ) {
13201299 return true ;
13211300 }
1322- for (int i = 0 ; i < 2 ; ++i) { // o2-linter: disable=magic-number (combinations of fake photons)
1323- if (c.mee [i] < crosspair.cfgCrossMaxMee .value && c.dist [i] < crosspair.cfgCrossMaxDist .value ) {
1324- return false ;
1325- }
1326- }
1327- return true ;
1301+ // A photon-like crossed combination means the pairing is ambiguous.
1302+ return c.meeOverQ > crosspair.cfgCrossMaxMeeRatio .value ;
13281303 }
13291304
13301305 template <int ev_id>
1331- inline void fillCrossPair (CrossObs const & c, float qinv, bool vetoed)
1306+ inline void fillCrossPair (CrossObs const & c, float qinv, float deltaR, bool vetoed)
13321307 {
13331308 constexpr auto dir = (ev_id == 0 ) ? " Pair/same/CrossPair/" : " Pair/mix/CrossPair/" ;
13341309 fRegistryCF .fill (HIST (dir) + HIST (" hVetoCounter" ), vetoed ? 1.0 : 0.0 );
13351310 if (qinv > crosspair.cfgCrossMaxQinvQA .value ) {
13361311 return ;
13371312 }
1338- for (int i = 0 ; i < 2 ; ++i) { // o2-linter: disable=magic-number (combinations of fake photons)
1339- fRegistryCF .fill (HIST (dir) + HIST (" hSparse_Mee_Dist_Qinv" ), c.mee [i], c.dist [i], qinv);
1340- }
1313+ fRegistryCF .fill (HIST (dir) + HIST (" hSparse_MeeRatio_dR_Qinv" ), c.meeOverQ , deltaR, qinv);
13411314 }
13421315
13431316 [[nodiscard]] float uTrue (TruthGamma const & g1, TruthGamma const & g2) const
@@ -2008,9 +1981,9 @@ struct Photonhbt {
20081981 continue ;
20091982 }
20101983 if (crosspair.cfgDoCrossPairQA .value || crosspair.cfgDoCrossPairCut .value ) {
2011- const auto cross = computeCrossObs (pwl1, pwl2);
1984+ const auto cross = computeCrossObs (pwl1, pwl2, obs. qinv );
20121985 const bool vetoed = !passCrossPairVeto (cross);
2013- fillCrossPair<0 >(cross, obs.qinv , vetoed);
1986+ fillCrossPair<0 >(cross, obs.qinv , obs. deltaR , vetoed);
20141987 if (vetoed) {
20151988 continue ;
20161989 }
@@ -2103,9 +2076,9 @@ struct Photonhbt {
21032076 continue ;
21042077 }
21052078 if (crosspair.cfgDoCrossPairQA .value || crosspair.cfgDoCrossPairCut .value ) {
2106- const auto cross = computeCrossObs (g1, g2);
2079+ const auto cross = computeCrossObs (g1, g2, obs. qinv );
21072080 const bool vetoed = !passCrossPairVeto (cross);
2108- fillCrossPair<1 >(cross, obs.qinv , vetoed);
2081+ fillCrossPair<1 >(cross, obs.qinv , obs. deltaR , vetoed);
21092082 if (vetoed) {
21102083 continue ;
21112084 }
@@ -2233,9 +2206,9 @@ struct Photonhbt {
22332206 continue ;
22342207 }
22352208 if (crosspair.cfgDoCrossPairQA .value || crosspair.cfgDoCrossPairCut .value ) {
2236- const auto cross = computeCrossObs (pwl1, pwl2);
2209+ const auto cross = computeCrossObs (pwl1, pwl2, obs. qinv );
22372210 const bool vetoed = !passCrossPairVeto (cross);
2238- fillCrossPair<0 >(cross, obs.qinv , vetoed);
2211+ fillCrossPair<0 >(cross, obs.qinv , obs. deltaR , vetoed);
22392212 if (vetoed) {
22402213 continue ;
22412214 }
@@ -2379,9 +2352,9 @@ struct Photonhbt {
23792352 continue ;
23802353 }
23812354 if (crosspair.cfgDoCrossPairQA .value || crosspair.cfgDoCrossPairCut .value ) {
2382- const auto cross = computeCrossObs (g1, g2);
2355+ const auto cross = computeCrossObs (g1, g2, obs. qinv );
23832356 const bool vetoed = !passCrossPairVeto (cross);
2384- fillCrossPair<1 >(cross, obs.qinv , vetoed);
2357+ fillCrossPair<1 >(cross, obs.qinv , obs. deltaR , vetoed);
23852358 if (vetoed) {
23862359 continue ;
23872360 }
@@ -2692,7 +2665,7 @@ struct Photonhbt {
26922665 fRegistryTruthMC .fill (HIST (" MC/TruthAO2D/hQinvVsKt_all4LegsThisColl" ), kt, qinv_true);
26932666 fRegistryTruthMC .fill (HIST (" MC/TruthAO2D/hDEtaDPhi_all4LegsThisColl" ), deta, dphi);
26942667 }
2695- if (g1Sel && g2Sel ) {
2668+ if (g1Built && g2Built ) {
26962669 fRegistryTruthMC .fill (HIST (" MC/TruthAO2D/hSparse_DEtaDPhi_qinv_bothPhotonsBuilt" ), deta, dphi, qinv_true);
26972670 fRegistryTruthMC .fill (HIST (" MC/TruthAO2D/hSparse_DEtaDPhi_kT_bothPhotonsBuilt" ), deta, dphi, kt);
26982671 fRegistryTruthMC .fill (HIST (" MC/TruthAO2D/hQinvVsKt_bothPhotonsBuilt" ), kt, qinv_true);
0 commit comments