00001
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
00027 _sphericity = -1;
00028 _planarity = -1;
00029 _aplanarity = -1;
00030 for (size_t i =0 ; i < 3; ++i) _lambdas[i] = -1;
00031
00032
00033 const FinalState& fs = e.applyProjection(_fsproj);
00034 const ParticleVector prts = fs.particles();
00035
00036
00037 if (prts.empty()) {
00038 log << Log::DEBUG << "No particles in final state..." << endl;
00039 return;
00040 }
00041
00042
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
00048 LorentzVector lv = p->getMomentum();
00049
00050
00051 totalMomentum += pow(lv.vect().mag(), _regparam);
00052
00053
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
00070 mMom /= totalMomentum;
00071 log << Log::DEBUG << "Momentum tensor = " << endl << mMom << endl;
00072
00073
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
00085 assert(isSymm);
00086
00087
00088 CLHEP::HepSymMatrix symMat;
00089 symMat.assign(mMom);
00090 CLHEP::diagonalize(&symMat);
00091 log << Log::DEBUG << "Diag momentum tensor = " << endl << symMat << endl;
00092
00093
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
00103 _sphericity = 3 / 2.0 * (lambda2() + lambda3());
00104 _aplanarity = 3 / 2.0 * lambda3();
00105 _planarity = 2 * (_sphericity - 2 * _aplanarity) / 3.0;
00106
00107 }