00001
00002
00003
00004
00006 #ifndef FOURMOMUTILS_P4HELPERS_H
00007 #define FOURMOMUTILS_P4HELPERS_H
00008
00018
00019 #ifndef XAOD_ANALYSIS
00020
00021
00022
00023 #include <cmath>
00024 #include <algorithm>
00025 #include <limits>
00026
00027
00028 #include "CxxUtils/fpcompare.h"
00029
00030
00031 #include "EventKernel/I4Momentum.h"
00032
00033 namespace P4Helpers
00034 {
00036 inline
00037 double deltaEta( const I4Momentum& p1, const I4Momentum& p2 )
00038 {
00039 double dEta(999);
00040 if ( p1.kind() == I4Momentum::P4PXPYPZE && p2.kind() == I4Momentum::P4PXPYPZE )
00041 {
00042 const double mom1 = p1.p(); const double pz1 = p1.pz();
00043 const double mom2 = p2.p(); const double pz2 = p2.pz();
00044 if ( ( mom1 + pz1 ) * ( mom2 - pz2 ) > 0 )
00045 dEta = -0.5 * std::log( ( mom1 - pz1 ) / ( mom1 + pz1 )
00046 * ( mom2 + pz2 ) / ( mom2 - pz2 ) );
00047 }
00048 else if ( p1.kind() == I4Momentum::P4PXPYPZE )
00049 {
00050 const double mom1 = p1.p(); const double pz1 = p1.pz();
00051 if ( mom1 + pz1 > 0 )
00052 dEta = -0.5 * std::log( ( mom1 - pz1 ) / ( mom1 + pz1 ) ) - p2.eta();
00053 }
00054 else if ( p2.kind() == I4Momentum::P4PXPYPZE )
00055 {
00056 const double mom2 = p2.p(); const double pz2 = p2.pz();
00057 if ( mom2 - pz2 > 0 )
00058 dEta = p1.eta() - 0.5 * std::log( ( mom2 + pz2 ) / ( mom2 - pz2 ) );
00059 }
00060 else
00061 {
00062 dEta = p1.eta() - p2.eta();
00063 }
00064 return dEta;
00065 }
00066
00068 inline
00069 double deltaEtaSq( const I4Momentum& p1, const I4Momentum& p2 )
00070 {
00071 double dEtaSq(999);
00072 if ( p1.kind() == I4Momentum::P4PXPYPZE && p2.kind() == I4Momentum::P4PXPYPZE )
00073 {
00074 const double mom1 = p1.p(); const double pz1 = p1.pz();
00075 const double mom2 = p2.p(); const double pz2 = p2.pz();
00076 if ( ( mom1 + pz1 ) * ( mom2 - pz2 ) > 0 )
00077 {
00078 dEtaSq = std::log( ( mom1 - pz1 ) / ( mom1 + pz1 )
00079 * ( mom2 + pz2 ) / ( mom2 - pz2 ) );
00080 dEtaSq = 0.25 * dEtaSq * dEtaSq;
00081 }
00082 }
00083 else if ( p1.kind() == I4Momentum::P4PXPYPZE )
00084 {
00085 const double mom1 = p1.p(); const double pz1 = p1.pz();
00086 if ( mom1 + pz1 > 0 )
00087 {
00088 dEtaSq = - 0.5 * std::log( ( mom1 - pz1 ) / ( mom1 + pz1 ) ) - p2.eta();
00089 dEtaSq = dEtaSq * dEtaSq;
00090 }
00091 }
00092 else if ( p2.kind() == I4Momentum::P4PXPYPZE )
00093 {
00094 const double mom2 = p2.p(); const double pz2 = p2.pz();
00095 if ( mom2 - pz2 > 0 )
00096 {
00097 dEtaSq = p1.eta() - 0.5 * std::log( ( mom2 + pz2 ) / ( mom2 - pz2 ) );
00098 dEtaSq = dEtaSq * dEtaSq;
00099 }
00100 }
00101 else
00102 {
00103 dEtaSq = p1.eta() - p2.eta();
00104 dEtaSq = dEtaSq * dEtaSq;
00105 }
00106 return dEtaSq;
00107 }
00108
00110 inline
00111 double deltaEta( const I4Momentum * const p1, const I4Momentum * const p2 )
00112 {
00113 return deltaEta(*p1, *p2);
00114 }
00115
00117 inline
00118 double deltaPhi( double phiA, double phiB )
00119 {
00120 return -remainder( -phiA + phiB, 2*M_PI );
00121 }
00122
00124 inline
00125 double deltaPhi( const I4Momentum& p4, const double phi )
00126 {
00127 return P4Helpers::deltaPhi( p4.phi(), phi );
00128 }
00129
00131 inline
00132 double deltaPhi( const I4Momentum & pA, const I4Momentum & pB )
00133 {
00134 double dPhi(999);
00135 if ( pA.kind() == I4Momentum::P4PXPYPZE && pB.kind() == I4Momentum::P4PXPYPZE )
00136 {
00137 double xp = pA.px() * pB.px() ;
00138 double xyp1 = 0;
00139 if ( xp != 0 )
00140 {
00141 xyp1 = 1.0 + pA.py() * pB.py() / xp ;
00142 dPhi = 0;
00143 if ( xyp1 != 0 )
00144 dPhi = atan( ( pA.py() / pA.px() - pB.py() / pB.px() ) / xyp1 );
00145 if ( xyp1 < 0 )
00146 {
00147 if ( pA.py() / pA.px() > 0 )
00148 dPhi += M_PI;
00149 else
00150 dPhi -= M_PI;
00151 }
00152 }
00153 }
00154 else
00155 {
00156 dPhi = remainder( -pA.phi() + pB.phi(), 2*M_PI );
00157 }
00158 return dPhi;
00159 }
00160
00162 inline
00163 double deltaPhiSq( const I4Momentum & pA, const I4Momentum & pB )
00164 {
00165 double dPhiSq(999);
00166 if ( pA.kind() == I4Momentum::P4PXPYPZE && pB.kind() == I4Momentum::P4PXPYPZE )
00167 {
00168 double cosPhi = ( pA.px() * pB.px() + pA.py() * pB.py() ) / pA.pt() / pB.pt();
00169 double phi = acos(cosPhi);
00170 dPhiSq = phi*phi;
00171 }
00172 else
00173 {
00174 dPhiSq = remainder( -pA.phi() + pB.phi(), 2*M_PI );
00175 dPhiSq = dPhiSq * dPhiSq;
00176 }
00177 return dPhiSq;
00178 }
00179
00181 inline
00182 double deltaPhi( const I4Momentum * const pA, const I4Momentum * const pB )
00183 { return deltaPhi( pA->phi(), pB->phi() ); }
00184
00186 inline
00187 double deltaR( const I4Momentum& p4, double eta, double phi )
00188 {
00189 using std::sqrt;
00190 const double dEta = p4.eta() - eta;
00191 const double dPhi = P4Helpers::deltaPhi( p4, phi );
00192 return sqrt( dEta*dEta + dPhi*dPhi );
00193 }
00194
00196 inline
00197 double deltaR( const I4Momentum& pA, const I4Momentum& pB )
00198 {
00199 using std::sqrt;
00200 const double dEtaSq = P4Helpers::deltaEtaSq( pA, pB );
00201 const double dPhiSq = P4Helpers::deltaPhiSq( pA, pB );
00202 return sqrt( dEtaSq + dPhiSq );
00203 }
00204
00206 inline
00207 double deltaR( const I4Momentum * const pA, const I4Momentum * const pB )
00208 { return P4Helpers::deltaR( *pA, *pB ); }
00209
00213 inline
00214 bool isInDeltaR( const I4Momentum& p1, const I4Momentum& p2,
00215 double dR )
00216 {
00217 using std::abs;
00218 using std::sqrt;
00219 const double dPhi = abs( P4Helpers::deltaPhi(p1,p2) );
00220 if ( dPhi > dR ) return false;
00221 const double dEta = abs( P4Helpers::deltaEta(p1,p2) );
00222 if ( dEta > dR ) return false;
00223 const double deltaR2 = dEta*dEta + dPhi*dPhi;
00224 if ( deltaR2 > dR*dR ) return false;
00225 return true;
00226 }
00227
00229 inline
00230 double invMass( const I4Momentum & pA, const I4Momentum & pB )
00231 { return (pA.hlv()+pB.hlv()).m(); }
00232
00234 inline
00235 double invMass( const I4Momentum * const pA, const I4Momentum * const pB )
00236 { return invMass( *pA, *pB ); }
00237
00239 inline
00240 double invMass( const I4Momentum & pA, const I4Momentum & pB,
00241 const I4Momentum & pC, const I4Momentum & pD )
00242 { return (pA.hlv()+pB.hlv()+pC.hlv()+pD.hlv()).m(); }
00243
00245 inline
00246 double invMass( const I4Momentum * const pA, const I4Momentum * const pB,
00247 const I4Momentum * const pC, const I4Momentum * const pD )
00248 { return invMass( *pA, *pB, *pC, *pD ); }
00249
00250
00251
00252
00253
00255 template<class Iterator_t, class Predicate_t>
00256 inline
00257 void sort( Iterator_t itr, Iterator_t itrEnd, Predicate_t p )
00258 {
00259
00260
00261 using std::sort;
00262 return sort( itr, itrEnd, p );
00263 }
00264
00266 template<class Container_t, class Predicate_t>
00267 inline
00268 void sort( Container_t& container, Predicate_t p )
00269 {
00270 return P4Helpers::sort( container.begin(), container.end(), p );
00271 }
00272
00273
00274
00275
00276
00281 template <class Container_t>
00282 inline
00283 bool closestDeltaR( const double eta, const double phi,
00284 Container_t& coll, std::size_t& index, double& deltaR )
00285 {
00286 deltaR = std::numeric_limits<double>::max();
00287 bool l_return = false;
00288 std::size_t l_idx = 0;
00289 typename Container_t::const_iterator it = coll.begin();
00290 typename Container_t::const_iterator itE = coll.end();
00291 for (; it != itE; ++it,++l_idx) {
00292 double rtu = P4Helpers::deltaR(**it, eta, phi);
00293 if ( CxxUtils::fpcompare::less(rtu, deltaR) ) {
00294 index = l_idx;
00295 deltaR = rtu;
00296 l_return = true;
00297 }
00298 }
00299 return l_return;
00300 }
00301
00306 template <class Container_t>
00307 inline
00308 bool closestDeltaR( const I4Momentum& p4,
00309 Container_t& coll, std::size_t& index, double& deltaR )
00310 {
00311 return P4Helpers::closestDeltaR( p4.eta(), p4.phi(),
00312 coll, index, deltaR );
00313 }
00314
00320 template <class Container_t>
00321 inline
00322 bool closestDeltaR( const double eta, const double phi, const double ene,
00323 Container_t& coll, std::size_t& index,
00324 double &deltaR, double &deltaE )
00325 {
00326 using std::abs;
00327 deltaR = deltaE = std::numeric_limits<double>::max();
00328 bool l_return = false;
00329 std::size_t l_idx = 0;
00330 typename Container_t::const_iterator it = coll.begin();
00331 typename Container_t::const_iterator itE = coll.end();
00332 for (; it != itE; ++it,++l_idx) {
00333 const double dE = abs( ene - (*it)->e() );
00334 if ( CxxUtils::fpcompare::less(dE, deltaE) ) {
00335 const double rtu = P4Helpers::deltaR(**it,eta,phi);
00336 if ( CxxUtils::fpcompare::less(rtu, deltaR) ) {
00337 index = l_idx;
00338 deltaR = rtu;
00339 deltaE = dE;
00340 l_return = true;
00341 }
00342 }
00343 }
00344 return l_return;
00345 }
00346
00352 template <class Container_t>
00353 inline
00354 bool closestDeltaR( const I4Momentum& p4,
00355 Container_t& coll, std::size_t& index,
00356 double &deltaR, double &deltaE )
00357 {
00358 return P4Helpers::closestDeltaR( p4.eta(), p4.phi(), p4.e(),
00359 coll, index, deltaR, deltaE );
00360 }
00361
00362 }
00363
00364
00365 #endif
00366
00367 #endif // FOURMOMUTILS_P4HELPERS_H