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 #include "CLHEP/Matrix/Matrix.h"
00007 #include "CLHEP/Matrix/SymMatrix.h"
00008 
00009 using namespace Rivet;
00010 using namespace std;
00011 
00012 
00013 int Sphericity::compare(const Projection& p) const {
00014   const Sphericity& other = dynamic_cast<const Sphericity&>(p);
00015   int fscmp = pcmp(_fsproj, other._fsproj);
00016   if (fscmp != 0) return fscmp;
00017   if (fuzzyEquals(_regparam, other._regparam)) return 0;
00018   return (_regparam > other._regparam) ? 1 : -1;
00019 }
00020 
00021 
00022 void Sphericity::project(const Event& e) {
00023   Log& log = getLog();
00024   log << Log::DEBUG << "Calculating sphericity with r = " << _regparam << endl;
00025 
00026   // Reset parameters
00027   _sphericity = -1;  
00028   _planarity = -1;
00029   _aplanarity = -1;
00030   for (size_t i =0 ; i < 3; ++i) _lambdas[i] = -1;
00031 
00032   // Get final state.
00033   const FinalState& fs = e.applyProjection(_fsproj);
00034   const ParticleVector prts = fs.particles();
00035 
00036   // Return (with "safe nonsense" sphericity params) if there are no final state particles.
00037   if (prts.empty()) {
00038     log << Log::DEBUG << "No particles in final state..." << endl; 
00039     return;
00040   }
00041 
00042   // Iterate over all the final state particles.
00043   CLHEP::HepMatrix mMom(3,3,0);
00044   double totalMomentum = 0.0;
00045   for (ParticleVector::const_iterator p = prts.begin(); p != prts.end(); ++p) {
00046     
00047     // Get the momentum vector for the final state particle.
00048     LorentzVector lv = p->getMomentum();
00049     
00050     // Build the (regulated) normalising factor.
00051     totalMomentum += pow(lv.vect().mag(), _regparam);
00052     
00053     // Build (regulated) quadratic momentum components.
00054     const double regfactor = pow(lv.vect().mag(), _regparam-2);
00055     if (!fuzzyEquals(regfactor, 1.0)) {
00056       log << Log::DEBUG << "Regfactor (r=" << _regparam << ") = " << regfactor << endl;
00057     }
00058     mMom[0][0] += regfactor * lv.x() * lv.x(); 
00059     mMom[1][1] += regfactor * lv.y() * lv.y();
00060     mMom[2][2] += regfactor * lv.z() * lv.z();
00061     mMom[0][1] += regfactor * lv.y() * lv.x(); 
00062     mMom[1][0] += regfactor * lv.x() * lv.y();
00063     mMom[0][2] += regfactor * lv.z() * lv.x(); 
00064     mMom[2][0] += regfactor * lv.x() * lv.z();
00065     mMom[1][2] += regfactor * lv.z() * lv.y();
00066     mMom[2][1] += regfactor * lv.y() * lv.z(); 
00067   }
00068 
00069   // Normalise to total (regulated) momentum.
00070   mMom /= totalMomentum;
00071   log << Log::DEBUG << "Momentum tensor = " << endl << mMom << endl;
00072 
00073   // Check that the matrix is symmetric.
00074   const bool isSymm = 
00075     fuzzyEquals(mMom[0][1], mMom[1][0]) && 
00076     fuzzyEquals(mMom[0][2], mMom[2][0]) && 
00077     fuzzyEquals(mMom[1][2], mMom[2][1]);
00078   if (!isSymm) {
00079     log << Log::ERROR << "Error: momentum tensor not symmetric (r=" << _regparam << ")" << endl;
00080     log << Log::ERROR << "[0,1] vs. [1,0]: " << mMom[0][1] << ", " << mMom[1][0] << endl;
00081     log << Log::ERROR << "[0,2] vs. [2,0]: " << mMom[0][2] << ", " << mMom[2][0] << endl;
00082     log << Log::ERROR << "[1,2] vs. [2,1]: " << mMom[1][2] << ", " << mMom[2][1] << endl;
00083   }
00084   // If not symmetric, something's wrong (we made sure the error msg appeared first).
00085   assert(isSymm); 
00086 
00087   // Convert to a SymMatrix and diagonalize.
00088   CLHEP::HepSymMatrix symMat;
00089   symMat.assign(mMom);
00090   CLHEP::diagonalize(&symMat);
00091   log << Log::DEBUG << "Diag momentum tensor = " << endl << symMat << endl;
00092   
00093   // Put the eigenvalues in the correct order.
00094   for (int i=0; i!=3; ++i){
00095     _lambdas[i] = symMat[i][i]; 
00096   }
00097   const int N = sizeof(_lambdas) / sizeof(double);
00098   sort(_lambdas, _lambdas + N); 
00099   reverse(_lambdas, _lambdas + N); 
00100   log << Log::DEBUG << "Sum of lambdas = " << lambda1() + lambda2() + lambda3() << endl;
00101   
00102   // Construct standard eigenvalue combinations.
00103   _sphericity = 3 / 2.0 * (lambda2() + lambda3());
00104   _aplanarity = 3 / 2.0 *  lambda3();
00105   _planarity  = 2 * (_sphericity - 2 * _aplanarity) / 3.0; 
00106   
00107 }