rivet is hosted by Hepforge, IPPP Durham
Spherocity.cc
Go to the documentation of this file.
00001 // -*- C++ -*-
00002 #include "Rivet/Config/RivetCommon.hh"
00003 #include "Rivet/Projections/Spherocity.hh"
00004 #include "Rivet/Tools/Logging.hh"
00005 
00006 
00007 namespace Rivet {
00008 
00009 
00010   void Spherocity::calc(const FinalState& fs) {
00011     calc(fs.particles());
00012   }
00013 
00014 
00015   void Spherocity::calc(const vector<Particle>& fsparticles) {
00016     vector<Vector3> threeMomenta;
00017     threeMomenta.reserve(fsparticles.size());
00018     foreach (const Particle& p, fsparticles) {
00019       threeMomenta.push_back( p.momentum().vector3() );
00020     }
00021     _calcSpherocity(threeMomenta);
00022   }
00023 
00024 
00025   void Spherocity::calc(const vector<FourMomentum>& fsmomenta) {
00026     vector<Vector3> threeMomenta;
00027     threeMomenta.reserve(fsmomenta.size());
00028     foreach (const FourMomentum& v, fsmomenta) {
00029       threeMomenta.push_back(v.vector3());
00030     }
00031     _calcSpherocity(threeMomenta);
00032   }
00033 
00034 
00035   void Spherocity::calc(const vector<Vector3>& fsmomenta) {
00036     _calcSpherocity(fsmomenta);
00037   }
00038 
00039 
00040   /////////////////////////////////////////////////
00041 
00042 
00043   /// @brief Do the general case spherocity calculation
00044   ///
00045   /// According to the Salam paper, p5, footnote 4, the
00046   /// axis n that minimises the Spherocity value ALWAYS coincides with the
00047   /// direction of one of the transverse momentum vectors of the events particles.
00048   /// Thus we carry out the calculation of S for all particles and pick the
00049   /// one that yields the smallest values
00050   void _calcS(const vector<Vector3 >& perpmomenta, double& sphero, Vector3& saxis) {
00051     vector<Vector3> p = perpmomenta;
00052     vector<double> sval;
00053 
00054     // Prepare vector to store unit vector representation of all particle momenta
00055     vector<Vector3> units;
00056     foreach (const Vector3& p, perpmomenta) {
00057       units.push_back(Vector3(p.x(), p.y(), 0.0).unit());
00058     }
00059 
00060     // Spherocity calculation
00061     //
00062     // Pick the solution with the smallest spherocity
00063     sphero = 99999.;
00064     // The outer loop is for iteration over all unit vectors
00065     foreach (const Vector3& u, units){
00066       double s =0.0;
00067       for (unsigned int k=0 ; k<p.size() ; k++) {
00068         s += fabs( p[k].cross(u).mod() );
00069       }
00070       if (s < sphero) {
00071         sphero = s;
00072         saxis = u;
00073       }
00074     }
00075   }
00076 
00077 
00078   // Do the full calculation
00079   void Spherocity::_calcSpherocity(const vector<Vector3>& fsmomenta) {
00080 
00081     // Make a vector of the three-momenta in the final state
00082     // Explicitly set the z-component (parallel to beam axis) to zero
00083     // This creates a 3D-vector representation of the transverse momentum
00084     // but takes the full information momentum vectors as input
00085 
00086     // A small iteration over full momenta but set z-coord. to 0.0 to get transverse momenta
00087     vector<Vector3> fsperpmomenta;
00088     foreach (const Vector3& p, fsmomenta) {
00089       fsperpmomenta.push_back(Vector3(p.x(), p.y(), 0.0));
00090     }
00091 
00092     // This returns the scalar sum of (transverse) momenta
00093     double perpmomentumSum(0.0);
00094     foreach (const Vector3& p, fsperpmomenta) {
00095       perpmomentumSum += p.mod();
00096     }
00097 
00098     // Clear the caches
00099     _spherocities.clear();
00100     _spherocityAxes.clear();
00101 
00102 
00103     // Temporary variables for calcs
00104     Vector3 axis(0,0,0);
00105     double val = 0.;
00106 
00107     // Get spherocity
00108     _calcS(fsperpmomenta, val, axis);
00109     MSG_DEBUG("Mom sum = " << perpmomentumSum);
00110     double spherocity = 0.25 * PI * PI * val * val / (perpmomentumSum * perpmomentumSum);
00111     _spherocities.push_back(spherocity);
00112 
00113     // See if calculated spherocity value makes sense
00114     if (spherocity < 0.0 || spherocity > 1.0) {
00115       MSG_WARNING("Spherocity = " << spherocity);
00116     }
00117 
00118     MSG_DEBUG("Spherocity value = " << spherocity);
00119 
00120     MSG_DEBUG("Sperocity axis = " << axis);
00121 
00122     _spherocityAxes.push_back(axis);
00123   }
00124 
00125 
00126 }