|
[Rivet-svn] r3068 - in trunk: include/Rivet include/Rivet/Projections src/Projectionsblackhole at projects.hepforge.org blackhole at projects.hepforge.orgFri Apr 29 12:33:13 BST 2011
Author: holsch Date: Fri Apr 29 12:33:13 2011 New Revision: 3068 Log: Add Spherocity and FParameter Projections fromthe Banfi paper Added: trunk/include/Rivet/Projections/FParameter.hh trunk/include/Rivet/Projections/Spherocity.hh trunk/src/Projections/FParameter.cc trunk/src/Projections/Spherocity.cc Modified: trunk/include/Rivet/Makefile.am trunk/src/Projections/Makefile.am Modified: trunk/include/Rivet/Makefile.am ============================================================================== --- trunk/include/Rivet/Makefile.am Tue Apr 26 23:13:36 2011 (r3067) +++ trunk/include/Rivet/Makefile.am Fri Apr 29 12:33:13 2011 (r3068) @@ -44,6 +44,7 @@ Projections/FinalState.hh \ Projections/FinalStateHCM.hh \ Projections/FoxWolframMoments.hh \ + Projections/FParameter.hh \ Projections/HadronicFinalState.hh \ Projections/Hemispheres.hh \ Projections/IdentifiedFinalState.hh \ @@ -64,6 +65,7 @@ Projections/ParisiTensor.hh \ Projections/PVertex.hh \ Projections/Sphericity.hh \ + Projections/Spherocity.hh \ Projections/SVertex.hh \ Projections/Thrust.hh \ Projections/TotalVisibleMomentum.hh \ Added: trunk/include/Rivet/Projections/FParameter.hh ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ trunk/include/Rivet/Projections/FParameter.hh Fri Apr 29 12:33:13 2011 (r3068) @@ -0,0 +1,89 @@ +// -*- C++ -*- +#ifndef RIVET_Sphericity_HH +#define RIVET_FParameter_HH + +#include "Rivet/Projection.hh" +#include "Rivet/Projections/FinalState.hh" +#include "Rivet/Event.hh" + + +namespace Rivet { + + class FParameter : public Projection { + + public: + + /// @name Constructors etc. + //@{ + + /// Constructor + FParameter(const FinalState& fsp); + + /// Clone on the heap. + virtual const Projection* clone() const { + return new FParameter(*this); + } + + //@} + + + protected: + + /// Perform the projection on the Event + void project(const Event& e); + + /// Compare with other projections + //int compare(const Projection& p) const; + // Taken from Thrust.hh + int compare(const Projection& p) const { + return mkNamedPCmp(p, "FS"); + } + public: + + /// Reset the projection + void clear(); + + /// @name Access the event shapes by name + /// @{ + /// F-Parametr + double F() const { return lambda1() >= lambda2() ? lambda2()/lambda1() : lambda1()/lambda2(); } + /// @} + + /// @name Access the linearised transverse momentum tensor eigenvalues + /// @{ + double lambda1() const { return _lambdas[0]; } + double lambda2() const { return _lambdas[1]; } + /// @} + + + /// @name Direct methods + /// Ways to do the calculation directly, without engaging the caching system + //@{ + + /// Manually calculate the sphericity, without engaging the caching system + void calc(const FinalState& fs); + + /// Manually calculate the sphericity, without engaging the caching system + void calc(const vector<Particle>& fsparticles); + + /// Manually calculate the sphericity, without engaging the caching system + void calc(const vector<FourMomentum>& fsmomenta); + + /// Manually calculate the sphericity, without engaging the caching system + void calc(const vector<Vector3>& fsmomenta); + + //@} + private: + /// Eigenvalues. + vector<double> _lambdas; + + private: + + /// Actually do the calculation + void _calcFParameter(const vector<Vector3>& fsmomenta); + + }; +} + + +#endif Added: trunk/include/Rivet/Projections/Spherocity.hh ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ trunk/include/Rivet/Projections/Spherocity.hh Fri Apr 29 12:33:13 2011 (r3068) @@ -0,0 +1,128 @@ +// -*- C++ -*- +#ifndef RIVET_Spherocity_HH +#define RIVET_Spherocity_HH + +#include "Rivet/Projection.hh" +#include "Rivet/Projections/AxesDefinition.hh" +#include "Rivet/Projections/FinalState.hh" +#include "Rivet/Event.hh" + +namespace Rivet { + + + /** + @brief Get the transverse spherocity scalars for hadron-colliders. + + @author Holger Schulz + + The scalar (maximum) transverse spherocity is defined as + \f[ + T = \mathrm{max}_{\vec{n_\perp}} \frac{\sum_i \left|\vec{p}_{\perp,i} \cdot \vec{n} \right|}{\sum_i |\vec{p}_{\perp,i}|} + \f], + with the direction of the unit vector \f$ \vec{n_\perp} \f$ which maximises \f$ T \f$ + being identified as the spherocity axis. The unit vector which maximises the spherocity + scalar in the plane perpendicular to \f$ \vec{n} \f$ is the "spherocity major" + direction, and the vector perpendicular to both the spherocity and spherocity major directions + is the spherocity minor. Both the major and minor directions have associated spherocity + scalars. + + Care must be taken in the case of Drell-Yann processes - there we should use the + newly proposed observable a_T. + + */ + class Spherocity : public AxesDefinition { + public: + + /// Constructor. + Spherocity(const FinalState& fsp) + : _calculatedSpherocity(false) + { + setName("Spherocity"); + addProjection(fsp, "FS"); + } + + /// Clone on the heap. + virtual const Projection* clone() const { + return new Spherocity(*this); + } + + protected: + + /// Perform the projection on the Event + void project(const Event& e) { + const vector<Particle> ps + = applyProjection<FinalState>(e, "FS").particles(); + calc(ps); + } + + /// Compare projections + int compare(const Projection& p) const { + return mkNamedPCmp(p, "FS"); + } + + + public: + + ///@{ Spherocity scalar accessors + /// The spherocity scalar, \f$ S \f$, (minimum spherocity). + double spherocity() const { return _spherocities[0]; } + ///@} + + ///@{ Spherocity axis accessors + /// The spherocity axis. + const Vector3& spherocityAxis() const { return _spherocityAxes[0]; } + /// The spherocity major axis (axis of max spherocity perpendicular to spherocity axis). + const Vector3& spherocityMajorAxis() const { return _spherocityAxes[1]; } + /// The spherocity minor axis (axis perpendicular to spherocity and spherocity major). + const Vector3& spherocityMinorAxis() const { return _spherocityAxes[2]; } + ///@} + + ///@{ AxesDefinition axis accessors. + const Vector3& axis1() const { return spherocityAxis(); } + const Vector3& axis2() const { return spherocityMajorAxis(); } + const Vector3& axis3() const { return spherocityMinorAxis(); } + ///@} + + + public: + + /// @name Direct methods + /// Ways to do the calculation directly, without engaging the caching system + //@{ + + /// Manually calculate the spherocity, without engaging the caching system + void calc(const FinalState& fs); + + /// Manually calculate the spherocity, without engaging the caching system + void calc(const vector<Particle>& fsparticles); + + /// Manually calculate the spherocity, without engaging the caching system + void calc(const vector<FourMomentum>& fsmomenta); + + /// Manually calculate the spherocity, without engaging the caching system + void calc(const vector<Vector3>& threeMomenta); + + //@} + + + private: + + /// The spherocity scalars. + vector<double> _spherocities; + + /// The spherocity axes. + vector<Vector3> _spherocityAxes; + + /// Caching flag to avoid costly recalculations. + bool _calculatedSpherocity; + + private: + + /// Explicitly calculate the spherocity values. + void _calcSpherocity(const vector<Vector3>& fsmomenta); + + }; + +} + +#endif Added: trunk/src/Projections/FParameter.cc ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ trunk/src/Projections/FParameter.cc Fri Apr 29 12:33:13 2011 (r3068) @@ -0,0 +1,116 @@ +// -*- C++ -*- +#include "Rivet/Projections/FParameter.hh" +#include "Rivet/Cmp.hh" +#include "Rivet/Tools/Logging.hh" +#include "Rivet/Tools/Utils.hh" + +namespace Rivet { + + FParameter::FParameter(const FinalState& fsp) { + setName("FParameter"); + addProjection(fsp, "FS"); + clear(); + } + + + void FParameter::clear() { + _lambdas = vector<double>(2, 0); + } + + + void FParameter::project(const Event& e) { + const ParticleVector prts = applyProjection<FinalState>(e, "FS").particles(); + calc(prts); + } + + + void FParameter::calc(const FinalState& fs) { + calc(fs.particles()); + } + + void FParameter::calc(const vector<Particle>& fsparticles) { + vector<Vector3> threeMomenta; + threeMomenta.reserve(fsparticles.size()); + foreach (const Particle& p, fsparticles) { + const Vector3 p3 = p.momentum().vector3(); + threeMomenta.push_back(p3); + } + _calcFParameter(threeMomenta); + } + + void FParameter::calc(const vector<FourMomentum>& fsmomenta) { + vector<Vector3> threeMomenta; + threeMomenta.reserve(fsmomenta.size()); + foreach (const FourMomentum& v, fsmomenta) { + threeMomenta.push_back(v.vector3()); + } + _calcFParameter(threeMomenta); + } + + void FParameter::calc(const vector<Vector3>& fsmomenta) { + _calcFParameter(fsmomenta); + } + + // Actually do the calculation + void FParameter::_calcFParameter(const vector<Vector3>& fsmomenta) { + + // Return (with "safe nonsense" sphericity params) if there are no final state particles. + if (fsmomenta.empty()) { + getLog() << Log::DEBUG << "No particles in final state..." << endl; + clear(); + return; + } + + // A small iteration over full momenta but set z-coord. to 0.0 to get transverse momenta + vector <Vector3> fsperpmomenta; + foreach (const Vector3& p, fsmomenta) { + fsperpmomenta.push_back(Vector3(p.x(), p.y(), 0.0)); + } + + // Iterate over all the final state particles. + Matrix<2> mMom; + getLog() << Log::DEBUG << "Number of particles = " << fsperpmomenta.size() << endl; + foreach (const Vector3& p3, fsperpmomenta) { + + double prefactor = 1.0/mod(p3); + + Matrix<2> mMomPart; + for (size_t i = 0; i < 2; ++i) { + for (size_t j = 0; j < 2; ++j) { + mMomPart.set(i,j, p3[i]*p3[j]); + } + } + mMom += prefactor * mMomPart; + } + + getLog() << Log::DEBUG << "Linearised transverse momentum tensor = " << endl << mMom << endl; + + // Check that the matrix is symmetric. + const bool isSymm = mMom.isSymm(); + if (!isSymm) { + getLog() << Log::ERROR << "Error: momentum tensor not symmetric:" << endl; + getLog() << Log::ERROR << "[0,1] vs. [1,0]: " << mMom.get(0,1) << ", " << mMom.get(1,0) << endl; + getLog() << Log::ERROR << "[0,2] vs. [2,0]: " << mMom.get(0,2) << ", " << mMom.get(2,0) << endl; + getLog() << Log::ERROR << "[1,2] vs. [2,1]: " << mMom.get(1,2) << ", " << mMom.get(2,1) << endl; + } + // If not symmetric, something's wrong (we made sure the error msg appeared first). + assert(isSymm); + + // Diagonalize momentum matrix. + const EigenSystem<2> eigen2 = diagonalize(mMom); + getLog() << Log::DEBUG << "Diag momentum tensor = " << endl << eigen2.getDiagMatrix() << endl; + + // Reset and set eigenvalue parameters. + _lambdas.clear(); + const EigenSystem<2>::EigenPairs epairs = eigen2.getEigenPairs(); + assert(epairs.size() == 2); + for (size_t i = 0; i < 2; ++i) { + _lambdas.push_back(epairs[i].first); + } + + // Debug output. + getLog() << Log::DEBUG << "Lambdas = (" + << lambda1() << ", " << lambda2() << ")" << endl; + getLog() << Log::DEBUG << "Sum of lambdas = " << lambda1() + lambda2() << endl; + } +} Modified: trunk/src/Projections/Makefile.am ============================================================================== --- trunk/src/Projections/Makefile.am Tue Apr 26 23:13:36 2011 (r3067) +++ trunk/src/Projections/Makefile.am Fri Apr 29 12:33:13 2011 (r3068) @@ -11,6 +11,7 @@ FinalState.cc \ FinalStateHCM.cc \ FoxWolframMoments.cc \ + FParameter.cc \ HadronicFinalState.cc \ Hemispheres.cc \ IdentifiedFinalState.cc \ @@ -27,6 +28,7 @@ ParisiTensor.cc \ PVertex.cc \ Sphericity.cc \ + Spherocity.cc \ SVertex.cc \ Thrust.cc \ TotalVisibleMomentum.cc \ Added: trunk/src/Projections/Spherocity.cc ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ trunk/src/Projections/Spherocity.cc Fri Apr 29 12:33:13 2011 (r3068) @@ -0,0 +1,213 @@ +// -*- C++ -*- +#include "Rivet/Rivet.hh" +#include "Rivet/Projections/Spherocity.hh" +#include "Rivet/Tools/Logging.hh" + + +namespace Rivet { + + + void Spherocity::calc(const FinalState& fs) { + calc(fs.particles()); + } + + void Spherocity::calc(const vector<Particle>& fsparticles) { + vector<Vector3> threeMomenta; + threeMomenta.reserve(fsparticles.size()); + foreach (const Particle& p, fsparticles) { + const Vector3 p3 = p.momentum().vector3(); + threeMomenta.push_back(p3); + } + _calcSpherocity(threeMomenta); + } + + void Spherocity::calc(const vector<FourMomentum>& fsmomenta) { + vector<Vector3> threeMomenta; + threeMomenta.reserve(fsmomenta.size()); + foreach (const FourMomentum& v, fsmomenta) { + threeMomenta.push_back(v.vector3()); + } + _calcSpherocity(threeMomenta); + } + + void Spherocity::calc(const vector<Vector3>& fsmomenta) { + _calcSpherocity(fsmomenta); + } + + + ///////////////////////////////////////////////// + + + inline bool mod2Cmp(const Vector<2>& a, const Vector<2>& b) { + return a.mod2() > b.mod2(); + } + + // Inline functions to avoid template hell + inline double dot(const Vector<2>& a, const Vector<2>& b) { + return a[0]*b[0] + a[1]*b[1]; + } + + inline Vector<2> unit(const Vector<2>& v) { + assert(mod(v) > 0); + Vector<2> returnthis; + returnthis.set(0, v[0]/mod(v)); + returnthis.set(1, v[1]/mod(v)); + return returnthis; + } + + + + //// Do the general case spherocity calculation + void _calcS(const vector<Vector3 >& perpmomenta, double& sphero, Vector3& saxis) { + // According to the Salam paper, p5, footnote 4, the + // axis n that minimises the Spherocity value ALWAYS coincides with the + // direction of one of the transverse momentum vectors of the events particles. + // Thus we carry out the calculation of Sphero for all particles and pick the + // one that yields the smallerst values + + vector<Vector3> p = perpmomenta; + vector<double> sval; + + + // Prepare vector to store unit vector representation of all particle momenta + // and also calculate the transverse momentum sum + vector<Vector3> units; + double sumperpmomenta = 0.0; + foreach (const Vector3& p, perpmomenta) { + units.push_back(Vector3(p.x(), p.y(), 0.0).unit()); + sumperpmomenta += p.mod(); + } + + // Spherocity calculation + // + // The outer loop is for iteration over all unit vectors + foreach (const Vector3& u, units){ + double s =0.0; + for (unsigned int k=0 ; k<p.size() ; k++) + s += fabs(p[k].cross(u).mod() ); + + sval.push_back(s); + } + + + // Pick the solution with the smallest spherocity + sphero = 999.; + for (unsigned int i=0 ; i<units.size() ; i++) + if (sval[i] < sphero){ + sphero = sval[i]; + saxis = units[i]; + } + + } + + + + // Do the full calculation + void Spherocity::_calcSpherocity(const vector<Vector3>& fsmomenta) { + + // Make a vector of the three-momenta in the final state + // Explicitly set the z-component (parallel to beam axis) to zero + // This creates a 3D-vector representation of the transverse momentum + // but take the full information momentum vectors as input + + vector<Vector3> fsperpmomenta; + // A small iteration over full momenta but set z-coord. to 0.0 to get transverse momenta + foreach (const Vector3& p, fsmomenta) { + fsperpmomenta.push_back(Vector3(p.x(), p.y(), 0.0)); + } + + // This returns the scalar sum of (transverse) momenta + double perpmomentumSum(0.0); + foreach (const Vector3& p, fsperpmomenta) { + perpmomentumSum += mod(p); + } + + // Clear the caches + _spherocities.clear(); + _spherocityAxes.clear(); + + // If there are fewer than 2 visible particles, we can't do much + // This is blindly copied from the Thrust projection + if (fsmomenta.size() < 2) { + for (int i = 0; i < 3; ++i) { + _spherocities.push_back(-1); + _spherocityAxes.push_back(Vector3(0,0,0)); + } + return; + } + + // Handle special case of spherocity = 1 if there are only 2 particles + // This is blindly copied from the Thrust projection + if (fsmomenta.size() == 2) { + Vector3 axis(0,0,0); + _spherocities.push_back(1.0); + _spherocities.push_back(0.0); + _spherocities.push_back(0.0); + axis = fsmomenta[0].unit(); + if (axis.z() < 0) axis = -axis; + _spherocityAxes.push_back(axis); + /// @todo Improve this --- special directions bad... + /// (a,b,c) _|_ 1/(a^2+b^2) (b,-a,0) etc., but which combination minimises error? + if (axis.z() < 0.75) + _spherocityAxes.push_back( (axis.cross(Vector3(0,0,1))).unit() ); + else + _spherocityAxes.push_back( (axis.cross(Vector3(0,1,0))).unit() ); + _spherocityAxes.push_back( _spherocityAxes[0].cross(_spherocityAxes[1]) ); + return; + } + + + // Temporary variables for calcs + Vector3 axis(0,0,0); + double val = 0.; + + + // Get spherocity + _calcS(fsperpmomenta, val, axis); + getLog() << Log::DEBUG << "Mom sum = " << perpmomentumSum << endl; + double spherocity = PI*PI* val*val / (4 * perpmomentumSum*perpmomentumSum); + _spherocities.push_back(spherocity); + + // See if calclulated spherocity value makes sense + if (spherocity < 0.0 || spherocity > 1.0) { + getLog() << Log::WARN << "Spherocity = " << spherocity << endl; + } + + getLog() << Log::DEBUG << "Spherocity value = " << spherocity << endl; + + getLog() << Log::DEBUG << "Sperocity axis = " << axis << endl; + + _spherocityAxes.push_back(axis); + + + //// Get spherocity minor + //// + //// + //// The Beam axis is eZ = (0, 0, 1) + //// + //double perpMinor = 0.0; + //const Vector3 ez = Vector3(0, 0, 1); + //foreach (const Vector3& v, fsperpmomenta) { + //Vector3 temp = Vector3(v[0], v[1], 0.0); + //perpMinor += mod(temp.cross(_spherocityAxes[0])); + //} + //_spherocitys.push_back(perpMinor / perpmomentumSum); + + + //// Manual check + //double test = 0.; + //Vector<2> ex; + //ex.set(0, 1.0); + //ex.set(1, 0); + //foreach (const Vector<2> & v, fsperpmomenta2D) { + //test+=fabs(dot(ex, v)); + //} + //if (test/perpmomentumSum < _spherocities[0]) { + //std::cout << "Warning: " << test/perpmomentumSum << " > " << _spherocitys[0] << " " << _spherocityAxes[0] << endl; + //} + + } + + + +}
More information about the Rivet-svn mailing list |