CMS 3D CMS Logo

/data/doxygen/doxygen-1.7.3/gen/CMSSW_4_2_8/src/DataFormats/JetReco/src/Jet.cc

Go to the documentation of this file.
00001 // Jet.cc
00002 // Fedor Ratnikov, UMd
00003 // $Id: Jet.cc,v 1.25 2010/10/14 23:01:45 wmtan Exp $
00004 
00005 #include <sstream>
00006 #include <cmath>
00007 
00008 #include "DataFormats/Math/interface/deltaR.h"
00009 #include "DataFormats/Math/interface/deltaPhi.h"
00010 
00011 //Own header file
00012 #include "DataFormats/JetReco/interface/Jet.h"
00013 
00014 using namespace reco;
00015 
00016 namespace {
00017   // approximate simple CALO geometry
00018   // abstract baseclass for geometry.
00019 
00020   class CaloPoint {
00021   public:
00022     static const double depth; // one for all relative depth of the reference point between ECAL begin and HCAL end
00023     static const double R_BARREL;
00024     static const double R_BARREL2;
00025     static const double Z_ENDCAP; // 1/2(EEz+HEz)
00026     static const double R_FORWARD; // eta=3
00027     static const double R_FORWARD2;
00028     static const double Z_FORWARD;
00029     static const double Z_BIG;
00030   };
00031 
00032   const double CaloPoint::depth = 0.1; // one for all relative depth of the reference point between ECAL begin and HCAL end
00033   const double CaloPoint::R_BARREL = (1.-depth)*143.+depth*407.;
00034   const double CaloPoint::R_BARREL2 = R_BARREL * R_BARREL;
00035   const double CaloPoint::Z_ENDCAP = (1.-depth)*320.+depth*568.; // 1/2(EEz+HEz)
00036   const double CaloPoint::R_FORWARD = Z_ENDCAP / std::sqrt (std::cosh(3.)*std::cosh(3.) -1.); // eta=3
00037   const double CaloPoint::R_FORWARD2 = R_FORWARD * R_FORWARD;
00038   const double CaloPoint::Z_FORWARD = 1100.+depth*165.;
00039   const double CaloPoint::Z_BIG = 1.e5;
00040 
00041   //old zvertex only implementation:
00042   class CaloPointZ: private CaloPoint{
00043   public:
00044     CaloPointZ (double fZ, double fEta){
00045       
00046       static const double ETA_MAX = 5.2;
00047       
00048       if (fZ > Z_ENDCAP) fZ = Z_ENDCAP-1.;
00049       if (fZ < -Z_ENDCAP) fZ = -Z_ENDCAP+1; // sanity check
00050       
00051       double tanThetaAbs = std::sqrt (std::cosh(fEta)*std::cosh(fEta) - 1.);
00052       double tanTheta = fEta >= 0 ? tanThetaAbs : -tanThetaAbs;
00053       
00054       double rEndcap = tanTheta == 0 ? 1.e10 : 
00055         fEta > 0 ? (Z_ENDCAP - fZ) / tanTheta : (-Z_ENDCAP - fZ) / tanTheta;
00056       if (rEndcap > R_BARREL) { // barrel
00057         mR = R_BARREL;
00058         mZ = fZ + R_BARREL * tanTheta; 
00059       }
00060       else {
00061         double zRef = Z_BIG; // very forward;
00062         if (rEndcap > R_FORWARD) zRef = Z_ENDCAP; // endcap
00063         else if (std::fabs (fEta) < ETA_MAX) zRef = Z_FORWARD; // forward
00064         
00065         mZ = fEta > 0 ? zRef : -zRef;
00066         mR = std::fabs ((mZ - fZ) / tanTheta);
00067       }
00068     }
00069     double etaReference (double fZ) {
00070       Jet::Point p (r(), 0., z() - fZ);
00071       return p.eta();
00072     }
00073 
00074     double thetaReference (double fZ) {
00075       Jet::Point p (r(), 0., z() - fZ);
00076       return p.theta();
00077     }
00078 
00079     double z() const {return mZ;}
00080     double r() const {return mR;}
00081   private:
00082     CaloPointZ(){};
00083     double mZ;
00084     double mR;
00085   };
00086 
00087   //new implementation to derive CaloPoint for free 3d vertex. 
00088   //code provided thanks to Christophe Saout
00089   template<typename Point>
00090   class CaloPoint3D : private CaloPoint {
00091   public:
00092     template<typename Vector, typename Point2>
00093     CaloPoint3D(const Point2 &vertex, const Vector &dir)
00094     {
00095       // note: no sanity checks here, make sure vertex is inside the detector!
00096 
00097       // check if positive or negative (or none) endcap should be tested
00098       int side = dir.z() < -1e-9 ? -1 : dir.z() > 1e-9 ? +1 : 0;
00099 
00100       double dirR = dir.Rho();
00101 
00102       // normalized direction in x-y plane
00103       double dirUnit[2] = { dir.x() / dirR, dir.y() / dirR };
00104 
00105       // rotate the vertex into a coordinate system where dir lies along x
00106 
00107       // vtxLong is the longitudinal coordinate of the vertex wrt/ dir
00108       double vtxLong = dirUnit[0] * vertex.x() + dirUnit[1] * vertex.y();
00109 
00110       // tIP is the (signed) transverse impact parameter
00111       double tIP = dirUnit[0] * vertex.y() - dirUnit[1] * vertex.x();
00112 
00113       // r and z coordinate
00114       double r, z;
00115 
00116       if (side) {
00117         double slope = dirR / dir.z();
00118 
00119         // check extrapolation to endcap
00120         r = vtxLong + slope * (side * Z_ENDCAP - vertex.z());
00121         double r2 = sqr(r) + sqr(tIP);
00122 
00123         if (r2 < R_FORWARD2) {
00124           // we are in the forward calorimeter, recompute
00125           r = vtxLong + slope * (side * Z_FORWARD - vertex.z());
00126           z = side * Z_FORWARD;
00127         } else if (r2 < R_BARREL2) {
00128           // we are in the endcap
00129           z = side * Z_ENDCAP;
00130         } else {
00131           // we are in the barrel, do the intersection below
00132           side = 0;
00133         }
00134       }
00135 
00136       if (!side) {
00137         // we are in the barrel
00138         double slope = dir.z() / dirR;
00139         r = std::sqrt(R_BARREL2 - sqr(tIP));
00140         z = vertex.z() + slope * (r - vtxLong);
00141       }
00142 
00143       // rotate (r, tIP, z) back into original x-y coordinate system
00144       point = Point(dirUnit[0] * r - dirUnit[1] * tIP,
00145                     dirUnit[1] * r + dirUnit[0] * tIP,
00146                     z);
00147     }
00148 
00149     const Point &caloPoint() const { return point; }
00150 
00151   private:
00152     template<typename T>
00153     static inline T sqr(const T &value) { return value * value; }
00154 
00155     Point point;
00156   };
00157 
00158 }
00159 
00160 Jet::Jet (const LorentzVector& fP4, 
00161           const Point& fVertex, 
00162           const Constituents& fConstituents)
00163   :  CompositePtrCandidate (0, fP4, fVertex),
00164      mJetArea (0),
00165      mPileupEnergy (0),
00166      mPassNumber (0)
00167 {
00168   for (unsigned i = 0; i < fConstituents.size (); i++) {
00169     addDaughter (fConstituents [i]);
00170   }
00171 }  
00172 
00173 Jet::Jet (const LorentzVector& fP4, 
00174           const Point& fVertex) 
00175   :  CompositePtrCandidate (0, fP4, fVertex),
00176      mJetArea (0),
00177      mPileupEnergy (0),
00178      mPassNumber (0)
00179 {}
00180 
00182 Jet::EtaPhiMoments Jet::etaPhiStatistics () const {
00183   std::vector<const Candidate*> towers = getJetConstituentsQuick ();
00184   double phiRef = phi();
00185   double sumw = 0;
00186   double sumEta = 0;
00187   double sumEta2 = 0;
00188   double sumPhi = 0;
00189   double sumPhi2 = 0;
00190   double sumEtaPhi = 0;
00191   int i = towers.size();
00192   while (--i >= 0) {
00193     double eta = towers[i]->eta();
00194     double phi = deltaPhi (towers[i]->phi(), phiRef);
00195     double weight = towers[i]->et();
00196     sumw += weight;
00197     sumEta += eta * weight;
00198     sumEta2 += eta * eta * weight;
00199     sumPhi += phi * weight;
00200     sumPhi2 += phi * phi * weight;
00201     sumEtaPhi += eta * phi * weight;
00202   }
00203   Jet::EtaPhiMoments result;
00204   if (sumw > 0) {
00205     result.etaMean = sumEta / sumw;
00206     result.phiMean = deltaPhi (phiRef + sumPhi, 0.);
00207     result.etaEtaMoment = (sumEta2 - sumEta * sumEta / sumw) / sumw;
00208     result.phiPhiMoment = (sumPhi2 - sumPhi * sumPhi / sumw) / sumw;
00209     result.etaPhiMoment = (sumEtaPhi - sumEta * sumPhi / sumw) / sumw;
00210   }
00211   else {
00212     result.etaMean = 0;
00213     result.phiMean = 0;
00214     result.etaEtaMoment = 0;
00215     result.phiPhiMoment = 0;
00216     result.etaPhiMoment = 0;
00217   }
00218   return result;
00219 }
00220 
00222 float Jet::etaetaMoment () const {
00223   std::vector<const Candidate*> towers = getJetConstituentsQuick ();
00224   double sumw = 0;
00225   double sum = 0;
00226   double sum2 = 0;
00227   int i = towers.size();
00228   while (--i >= 0) {
00229     double value = towers[i]->eta();
00230     double weight = towers[i]->et();
00231     sumw += weight;
00232     sum += value * weight;
00233     sum2 += value * value * weight;
00234   }
00235   return sumw > 0 ? (sum2 - sum*sum/sumw ) / sumw : 0;
00236 }
00237 
00239 float Jet::phiphiMoment () const {
00240   double phiRef = phi();
00241   std::vector<const Candidate*> towers = getJetConstituentsQuick ();
00242   double sumw = 0;
00243   double sum = 0;
00244   double sum2 = 0;
00245   int i = towers.size();
00246   while (--i >= 0) {
00247     double value = deltaPhi (towers[i]->phi(), phiRef);
00248     double weight = towers[i]->et();
00249     sumw += weight;
00250     sum += value * weight;
00251     sum2 += value * value * weight;
00252   }
00253   return sumw > 0 ? (sum2 - sum*sum/sumw ) / sumw : 0;
00254 }
00255 
00257 float Jet::etaphiMoment () const {
00258   double phiRef = phi();
00259   std::vector<const Candidate*> towers = getJetConstituentsQuick ();
00260   double sumw = 0;
00261   double sumA = 0;
00262   double sumB = 0;
00263   double sumAB = 0;
00264   int i = towers.size();
00265   while (--i >= 0) {
00266     double valueA = towers[i]->eta();
00267     double valueB = deltaPhi (towers[i]->phi(), phiRef);
00268     double weight = towers[i]->et();
00269     sumw += weight;
00270     sumA += valueA * weight;
00271     sumB += valueB * weight;
00272     sumAB += valueA * valueB * weight;
00273   }
00274   return sumw > 0 ? (sumAB - sumA*sumB/sumw ) / sumw : 0;
00275 }
00276 
00278 float Jet::etInAnnulus (float fRmin, float fRmax) const {
00279   float result = 0;
00280   std::vector<const Candidate*> towers = getJetConstituentsQuick ();
00281   int i = towers.size ();
00282   while (--i >= 0) {
00283     double r = deltaR (*this, *(towers[i]));
00284     if (r >= fRmin && r < fRmax) result += towers[i]->et ();
00285   }
00286   return result;
00287 }
00288 
00290 int Jet::nCarrying (float fFraction) const {
00291   std::vector<const Candidate*> towers = getJetConstituentsQuick ();
00292   if (fFraction >= 1) return towers.size();
00293   double totalEt = 0;
00294   for (unsigned i = 0; i < towers.size(); ++i) totalEt += towers[i]->et();
00295   double fractionEnergy = totalEt * fFraction;
00296   unsigned result = 0;
00297   for (; result < towers.size(); ++result) {
00298     fractionEnergy -= towers[result]->et();
00299     if (fractionEnergy <= 0) return result+1;
00300   }
00301   return 0;
00302 }
00303 
00305 float Jet::maxDistance () const {
00306   float result = 0;
00307   std::vector<const Candidate*> towers = getJetConstituentsQuick ();
00308   for (unsigned i = 0; i < towers.size(); ++i) {
00309     float dR = deltaR (*(towers[i]), *this);
00310     if (dR > result)  result = dR;
00311   }
00312   return result;
00313 }
00314 
00316 // kept for backwards compatibility, use detector/physicsP4 instead!
00317 float Jet::physicsEta (float fZVertex, float fDetectorEta) {
00318   CaloPointZ refPoint (0., fDetectorEta);
00319   return refPoint.etaReference (fZVertex);
00320 }
00321 
00323 // kept for backwards compatibility, use detector/physicsP4 instead!
00324 float Jet::detectorEta (float fZVertex, float fPhysicsEta) {
00325   CaloPointZ refPoint (fZVertex, fPhysicsEta);
00326   return refPoint.etaReference (0.);
00327 }
00328 
00329 Candidate::LorentzVector Jet::physicsP4 (const Candidate::Point &newVertex, const Candidate &inParticle,const Candidate::Point &oldVertex) {
00330   CaloPoint3D<Point> caloPoint(oldVertex,inParticle.momentum()); // Jet position in Calo.
00331   Vector physicsDir = caloPoint.caloPoint() - newVertex;
00332   double p = inParticle.momentum().r();
00333   Vector p3 = p * physicsDir.unit();
00334   LorentzVector returnVector(p3.x(), p3.y(), p3.z(), inParticle.energy());
00335   return returnVector;
00336 }
00337 
00338 Candidate::LorentzVector Jet::detectorP4 (const Candidate::Point &vertex, const Candidate &inParticle) {
00339   CaloPoint3D<Point> caloPoint(vertex,inParticle.momentum()); // Jet position in Calo.
00340   static const Point np(0,0,0);
00341   Vector detectorDir = caloPoint.caloPoint() - np;
00342   double p = inParticle.momentum().r();
00343   Vector p3 = p * detectorDir.unit();
00344   LorentzVector returnVector(p3.x(), p3.y(), p3.z(), inParticle.energy());
00345   return returnVector;
00346 }
00347 
00348 
00349 Jet::Constituents Jet::getJetConstituents () const {
00350   Jet::Constituents result;
00351   for (unsigned i = 0; i < numberOfDaughters(); i++) {
00352     result.push_back (daughterPtr (i));
00353   }
00354   return result;
00355 }
00356 
00357 std::vector<const Candidate*> Jet::getJetConstituentsQuick () const {
00358   std::vector<const Candidate*> result;
00359   int nDaughters = numberOfDaughters();
00360   for (int i = 0; i < nDaughters; ++i) { 
00361     result.push_back (daughter (i));
00362   }
00363   return result;
00364 }
00365 
00366 std::string Jet::print () const {
00367   std::ostringstream out;
00368   out << "Jet p/px/py/pz/pt: " << p() << '/' << px () << '/' << py() << '/' << pz() << '/' << pt() << std::endl
00369       << "    eta/phi: " << eta () << '/' << phi () << std::endl
00370        << "    # of constituents: " << nConstituents () << std::endl;
00371   out << "    Constituents:" << std::endl;
00372   for (unsigned index = 0; index < numberOfDaughters(); index++) {
00373     Constituent constituent = daughterPtr (index); // deref
00374     if (constituent.isNonnull()) {
00375       out << "      #" << index << " p/pt/eta/phi: " 
00376           << constituent->p() << '/' << constituent->pt() << '/' << constituent->eta() << '/' << constituent->phi() 
00377           << "    productId/index: " << constituent.id() << '/' << constituent.key() << std::endl; 
00378     }
00379     else {
00380       out << "      #" << index << " constituent is not available in the event"  << std::endl;
00381     }
00382   }
00383   return out.str ();
00384 }
00385 
00386 void Jet::scaleEnergy (double fScale) {
00387   setP4 (p4() * fScale);
00388 }
00389 
00390 bool Jet::isJet() const {
00391   return true;
00392 }