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
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
00069 void Sphericity::_calcSphericity(const vector<Vector3>& fsmomenta) {
00070 getLog() << Log::DEBUG << "Calculating sphericity with r = " << _regparam << endl;
00071
00072
00073 if (fsmomenta.empty()) {
00074 getLog() << Log::DEBUG << "No particles in final state..." << endl;
00075 clear();
00076 return;
00077 }
00078
00079
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
00085 totalMomentum += pow(p3.mod(), _regparam);
00086
00087
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
00103 mMom /= totalMomentum;
00104 getLog() << Log::DEBUG << "Momentum tensor = " << endl << mMom << endl;
00105
00106
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
00115 assert(isSymm);
00116
00117
00118 const EigenSystem<3> eigen3 = diagonalize(mMom);
00119 getLog() << Log::DEBUG << "Diag momentum tensor = " << endl << eigen3.getDiagMatrix() << endl;
00120
00121
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
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 }