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