Skip to content

[math][genvector] Implement pair acoplanarity and asymmetry functions #19618

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 6 commits into from
Aug 14, 2025
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
78 changes: 72 additions & 6 deletions math/genvector/inc/Math/GenVector/LorentzVector.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,9 @@
#define ROOT_Math_GenVector_LorentzVector 1

#include "Math/GenVector/PxPyPzE4D.h"

#include "Math/GenVector/DisplacementVector3D.h"

#include "Math/GenVector/GenVectorIO.h"
#include "Math/Vector2D.h"

#include "TMath.h"

Expand All @@ -43,16 +42,17 @@ In the case of LorentzVector we don't distinguish the concepts
of points and displacement vectors as in the 3D case,
since the main use case for 4D Vectors is to describe the kinematics of
relativistic particles. A LorentzVector behaves like a
DisplacementVector in 4D. The Minkowski components could be viewed as
DisplacementVector in 4D. The Minkowski components could be viewed as
v and t, or for kinematic 4-vectors, as p and E.

ROOT provides specialisations and aliases to them of the ROOT::Math::LorentzVector template:
ROOT provides specialisations (and aliases to them) of the ROOT::Math::LorentzVector template:
- ROOT::Math::PtEtaPhiMVector based on pt (rho),eta,phi and M (t) coordinates in double precision
- ROOT::Math::PtEtaPhiEVector based on pt (rho),eta,phi and E (t) coordinates in double precision
- ROOT::Math::PxPyPzMVector based on px,py,pz and M (mass) coordinates in double precision
- ROOT::Math::PxPyPzEVector based on px,py,pz and E (energy) coordinates in double precision
- ROOT::Math::PxPyPzMVector based on px,py,pz and M coordinates in double precision
- ROOT::Math::PxPyPzEVector based on px,py,pz and E coordinates in double precision
- ROOT::Math::XYZTVector based on x,y,z,t coordinates (cartesian) in double precision (same as PxPyPzEVector)
- ROOT::Math::XYZTVectorF based on x,y,z,t coordinates (cartesian) in float precision (same as PxPyPzEVector but float)
Pt (or rho) refers to transverse momentum, whereas eta refers to pseudorapidity. M is mass, E is energy, p is momentum.

@see GenVector
*/
Expand Down Expand Up @@ -731,6 +731,72 @@ ROOT provides specialisations and aliases to them of the ROOT::Math::LorentzVect
return tmp;
}

/**
pair (p+ p-) acoplanarity `alpha = 1 - |phi+ - phi-|/pi`.
\param pp p+, mathcore::LorentzVector based on any coordinate system
\param pm p-, mathcore::LorentzVector based on any coordinate system
\return a scalar
\ingroup GenVector
\see http://doi.org/10.1103/PhysRevLett.121.212301
*/
template< class CoordSystem >
typename LorentzVector<CoordSystem>::Scalar Acoplanarity(LorentzVector<CoordSystem> const &pp, LorentzVector<CoordSystem> const &pm)
{
auto dphi = pp.Phi() - pm.Phi();
// convert dphi angle to the interval (-PI,PI]
if (dphi > TMath::Pi() || dphi <= -TMath::Pi()) {
if (dphi > 0) {
int n = static_cast<int>(dphi / TMath::TwoPi() + 0.5);
dphi -= TMath::TwoPi() * n;
} else {
int n = static_cast<int>(0.5 - dphi / TMath::TwoPi());
dphi += TMath::TwoPi() * n;
}
}
return 1 - std::abs(dphi)/TMath::Pi();
}

/**
pair (p+ p-) vectorial asymmetry `Av = |Pt+ - Pt-|/|Pt+ + Pt-|`.
In an experimental setting, it reflects a convolution of the experimental resolutions
of particle energy and azimuthal angle measurement.
\param pp p+, mathcore::LorentzVector based on any coordinate system
\param pm p-, mathcore::LorentzVector based on any coordinate system
\return a scalar. Returns -1 if both momenta are exactly mirrored.
\ingroup GenVector
\see http://doi.org/10.1103/PhysRevLett.121.212301, https://doi.org/10.1103/PhysRevD.99.093013
*/
template< class CoordSystem >
typename LorentzVector<CoordSystem>::Scalar AsymmetryVectorial(LorentzVector<CoordSystem> const &pp, LorentzVector<CoordSystem> const &pm)
{
ROOT::Math::XYVector vp(pp.Px(), pp.Py());
ROOT::Math::XYVector vm(pm.Px(), pm.Py());
auto denom = (vp + vm).R();
if (denom == 0.)
return -1;
return (vp - vm).R() / denom;
}

/**
pair (p+ p-) scalar asymmetry `As = ||Pt+| - |Pt-|/||Pt+| + |Pt-||`.
Measures the relative difference in transverse momentum of the pair, e.g. two photons,
and would be ideally zero for two back-to-back photons.
\param pp p+, mathcore::LorentzVector based on any coordinate system
\param pm p-, mathcore::LorentzVector based on any coordinate system
\return a scalar. Returns 0 if both transverse momenta are zero
\ingroup GenVector
\see http://doi.org/10.1103/PhysRevLett.121.212301, https://doi.org/10.1103/PhysRevD.99.093013
*/
template< class CoordSystem >
typename LorentzVector<CoordSystem>::Scalar AsymmetryScalar(LorentzVector<CoordSystem> const &pp, LorentzVector<CoordSystem> const &pm)
{
auto ptp = pp.Pt();
auto ptm = pm.Pt();
if (ptp == 0 && ptm == 0)
return 0;
return std::abs(ptp - ptm) / (ptp + ptm);
}

// ------------- I/O to/from streams -------------

template< class char_t, class traits_t, class Coords >
Expand Down
Loading