CMS 3D CMS Logo

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