rivet is hosted by Hepforge, IPPP Durham
Sphericity.cc
Go to the documentation of this file.
00001 // -*- C++ -*-
00002 #include "Rivet/Projections/Sphericity.hh"
00003 
00004 namespace Rivet {
00005 
00006 
00007   Sphericity::Sphericity(const FinalState& fsp, double rparam)
00008     : _regparam(rparam)
00009   {
00010     setName("Sphericity");
00011     addProjection(fsp, "FS");
00012     clear();
00013   }
00014 
00015 
00016   void Sphericity::clear() {
00017     _lambdas = vector<double>(3, 0);
00018     _sphAxes = vector<Vector3>(3, Vector3());
00019   }
00020 
00021 
00022   int Sphericity::compare(const Projection& p) const {
00023     PCmp fscmp = mkNamedPCmp(p, "FS");
00024     if (fscmp != EQUIVALENT) return fscmp;
00025     const Sphericity& other = dynamic_cast<const Sphericity&>(p);
00026     if (fuzzyEquals(_regparam, other._regparam)) return 0;
00027     return cmp(_regparam, other._regparam);
00028   }
00029 
00030 
00031   void Sphericity::project(const Event& e) {
00032     const Particles prts = applyProjection<FinalState>(e, "FS").particles();
00033     calc(prts);
00034   }
00035 
00036 
00037   void Sphericity::calc(const FinalState& fs) {
00038     calc(fs.particles());
00039   }
00040 
00041   void Sphericity::calc(const vector<Particle>& fsparticles) {
00042     vector<Vector3> threeMomenta;
00043     threeMomenta.reserve(fsparticles.size());
00044     foreach (const Particle& p, fsparticles) {
00045       threeMomenta.push_back( p.momentum().vector3() );
00046     }
00047     _calcSphericity(threeMomenta);
00048   }
00049 
00050   void Sphericity::calc(const vector<FourMomentum>& fsmomenta) {
00051     vector<Vector3> threeMomenta;
00052     threeMomenta.reserve(fsmomenta.size());
00053     foreach (const FourMomentum& v, fsmomenta) {
00054       threeMomenta.push_back(v.vector3());
00055     }
00056     _calcSphericity(threeMomenta);
00057   }
00058 
00059   void Sphericity::calc(const vector<Vector3>& fsmomenta) {
00060     _calcSphericity(fsmomenta);
00061   }
00062 
00063 
00064   // Actually do the calculation
00065   void Sphericity::_calcSphericity(const vector<Vector3>& fsmomenta) {
00066     MSG_DEBUG("Calculating sphericity with r = " << _regparam);
00067 
00068     // Return (with "safe nonsense" sphericity params) if there are no final state particles.
00069     if (fsmomenta.empty()) {
00070       MSG_DEBUG("No particles in final state...");
00071       clear();
00072       return;
00073     }
00074 
00075     // Iterate over all the final state particles.
00076     Matrix3 mMom;
00077     double totalMomentum = 0.0;
00078     MSG_DEBUG("Number of particles = " << fsmomenta.size());
00079     foreach (const Vector3& p3, fsmomenta) {
00080       // Build the (regulated) normalising factor.
00081       totalMomentum += pow(p3.mod(), _regparam);
00082 
00083       // Build (regulated) quadratic momentum components.
00084       const double regfactor = pow(p3.mod(), _regparam-2);
00085       if (!fuzzyEquals(regfactor, 1.0)) {
00086         MSG_TRACE("Regfactor (r=" << _regparam << ") = " << regfactor);
00087       }
00088 
00089       Matrix3 mMomPart;
00090       for (size_t i = 0; i < 3; ++i) {
00091         for (size_t j = 0; j < 3; ++j) {
00092           mMomPart.set(i,j, p3[i]*p3[j]);
00093         }
00094       }
00095       mMom += regfactor * mMomPart;
00096     }
00097 
00098     // Normalise to total (regulated) momentum.
00099     mMom /= totalMomentum;
00100     MSG_DEBUG("Momentum tensor = " << "\n" << mMom);
00101 
00102     // Check that the matrix is symmetric.
00103     const bool isSymm = mMom.isSymm();
00104     if (!isSymm) {
00105       MSG_ERROR("Error: momentum tensor not symmetric (r=" << _regparam << ")");
00106       MSG_ERROR("[0,1] vs. [1,0]: " << mMom.get(0,1) << ", " << mMom.get(1,0));
00107       MSG_ERROR("[0,2] vs. [2,0]: " << mMom.get(0,2) << ", " << mMom.get(2,0));
00108       MSG_ERROR("[1,2] vs. [2,1]: " << mMom.get(1,2) << ", " << mMom.get(2,1));
00109     }
00110     // If not symmetric, something's wrong (we made sure the error msg appeared first).
00111     assert(isSymm);
00112 
00113     // Diagonalize momentum matrix.
00114     const EigenSystem<3> eigen3 = diagonalize(mMom);
00115     MSG_DEBUG("Diag momentum tensor = " << "\n" << eigen3.getDiagMatrix());
00116 
00117     // Reset and set eigenvalue/vector parameters.
00118     _lambdas.clear();
00119     _sphAxes.clear();
00120     const EigenSystem<3>::EigenPairs epairs = eigen3.getEigenPairs();
00121     assert(epairs.size() == 3);
00122     for (size_t i = 0; i < 3; ++i) {
00123       _lambdas.push_back(epairs[i].first);
00124       _sphAxes.push_back(Vector3(epairs[i].second));
00125     }
00126 
00127     // Debug output.
00128     MSG_DEBUG("Lambdas = ("
00129              << lambda1() << ", " << lambda2() << ", " << lambda3() << ")");
00130     MSG_DEBUG("Sum of lambdas = " << lambda1() + lambda2() + lambda3());
00131     MSG_DEBUG("Vectors = "
00132              << sphericityAxis() << ", "
00133              << sphericityMajorAxis() << ", "
00134              << sphericityMinorAxis() << ")");
00135   }
00136 
00137 }