00001
00002
00003
00004
00005 #include <sstream>
00006 #include <cmath>
00007
00008 #include "DataFormats/Math/interface/deltaR.h"
00009 #include "DataFormats/Math/interface/deltaPhi.h"
00010
00011
00012 #include "DataFormats/JetReco/interface/Jet.h"
00013
00014 using namespace reco;
00015
00016 namespace {
00017
00018
00019
00020 class CaloPoint {
00021 public:
00022 static const double depth;
00023 static const double R_BARREL;
00024 static const double R_BARREL2;
00025 static const double Z_ENDCAP;
00026 static const double R_FORWARD;
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;
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.;
00036 const double CaloPoint::R_FORWARD = Z_ENDCAP / std::sqrt (std::cosh(3.)*std::cosh(3.) -1.);
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
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;
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) {
00057 mR = R_BARREL;
00058 mZ = fZ + R_BARREL * tanTheta;
00059 }
00060 else {
00061 double zRef = Z_BIG;
00062 if (rEndcap > R_FORWARD) zRef = Z_ENDCAP;
00063 else if (std::fabs (fEta) < ETA_MAX) zRef = Z_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
00088
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
00096
00097
00098 int side = dir.z() < -1e-9 ? -1 : dir.z() > 1e-9 ? +1 : 0;
00099
00100 double dirR = dir.Rho();
00101
00102
00103 double dirUnit[2] = { dir.x() / dirR, dir.y() / dirR };
00104
00105
00106
00107
00108 double vtxLong = dirUnit[0] * vertex.x() + dirUnit[1] * vertex.y();
00109
00110
00111 double tIP = dirUnit[0] * vertex.y() - dirUnit[1] * vertex.x();
00112
00113
00114 double r, z;
00115
00116 if (side) {
00117 double slope = dirR / dir.z();
00118
00119
00120 r = vtxLong + slope * (side * Z_ENDCAP - vertex.z());
00121 double r2 = sqr(r) + sqr(tIP);
00122
00123 if (r2 < R_FORWARD2) {
00124
00125 r = vtxLong + slope * (side * Z_FORWARD - vertex.z());
00126 z = side * Z_FORWARD;
00127 } else if (r2 < R_BARREL2) {
00128
00129 z = side * Z_ENDCAP;
00130 } else {
00131
00132 side = 0;
00133 }
00134 }
00135
00136 if (!side) {
00137
00138 double slope = dir.z() / dirR;
00139 r = std::sqrt(R_BARREL2 - sqr(tIP));
00140 z = vertex.z() + slope * (r - vtxLong);
00141 }
00142
00143
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
00317 float Jet::physicsEta (float fZVertex, float fDetectorEta) {
00318 CaloPointZ refPoint (0., fDetectorEta);
00319 return refPoint.etaReference (fZVertex);
00320 }
00321
00323
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());
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());
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);
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 }