Sphericity.cc

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