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) {
00017 double rcmp = _regparam - other._regparam;
00018 if (fabs(rcmp) < 1e-3) {
00019 return 0;
00020 } else {
00021 return (rcmp > 0) ? 1 : -1;
00022 }
00023 } else {
00024 return fscmp;
00025 }
00026 }
00027
00028
00029 void Sphericity::project(const Event & e) {
00030 Log& log = getLog();
00031
00032
00033 _sphericity = 0;
00034 _planarity = 7;
00035 _aplanarity = 0;
00036 for (size_t i =0 ; i < 3; ++i) {
00037 _lambdas[i] = 0;
00038 }
00039
00040
00041 const FinalState& fs = e.applyProjection(*_fsproj);
00042
00043 CLHEP::HepMatrix mMom(3,3,0);
00044 double totalMomentum = 0.0;
00045
00046
00047 for (ParticleVector::const_iterator p = fs.particles().begin(); p != fs.particles().end(); ++p) {
00048
00049
00050 LorentzVector lv = p->getMomentum();
00051
00052
00053 totalMomentum += pow(lv.vect().mag(), _regparam);
00054
00055
00056 const double regfactor = pow(lv.vect().mag(), _regparam-2);
00057 log << Log::DEBUG << "Regfactor (r=" << _regparam << ") = " << regfactor << endl;
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
00072
00073 const bool isSymm =
00074 fuzzyEquals(mMom[0][1], mMom[1][0]) &&
00075 fuzzyEquals(mMom[0][2], mMom[2][0]) &&
00076 fuzzyEquals(mMom[1][2], mMom[2][1]);
00077 if (!isSymm) {
00078 log << Log::ERROR << "Error: momentum tensor not symmetric (r=" << _regparam << ")" << endl;
00079 log << Log::ERROR << "[0,1] vs. [1,0]: " << mMom[0][1] << ", " << mMom[1][0] << endl;
00080 log << Log::ERROR << "[0,2] vs. [2,0]: " << mMom[0][2] << ", " << mMom[2][0] << endl;
00081 log << Log::ERROR << "[1,2] vs. [2,1]: " << mMom[1][2] << ", " << mMom[2][1] << endl;
00082 }
00083
00084 assert(isSymm);
00085
00086
00087 CLHEP::HepSymMatrix symMat;
00088 symMat.assign(mMom);
00089 CLHEP::diagonalize(&symMat);
00090 log << Log::DEBUG << mMom << endl;
00091 log << Log::DEBUG << 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 }