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
00015
00016 using namespace reco;
00017
00018 namespace {
00019
00020
00021
00022 class CaloPoint {
00023 public:
00024 static const double depth;
00025 static const double R_BARREL;
00026 static const double R_BARREL2;
00027 static const double Z_ENDCAP;
00028 static const double R_FORWARD;
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;
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.;
00038 const double CaloPoint::R_FORWARD = Z_ENDCAP / std::sqrt (std::cosh(3.)*std::cosh(3.) -1.);
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
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;
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) {
00059 mR = R_BARREL;
00060 mZ = fZ + R_BARREL * tanTheta;
00061 }
00062 else {
00063 double zRef = Z_BIG;
00064 if (rEndcap > R_FORWARD) zRef = Z_ENDCAP;
00065 else if (std::fabs (fEta) < ETA_MAX) zRef = Z_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
00090
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
00098
00099
00100 int side = dir.z() < -1e-9 ? -1 : dir.z() > 1e-9 ? +1 : 0;
00101
00102 double dirR = dir.Rho();
00103
00104
00105 double dirUnit[2] = { dir.x() / dirR, dir.y() / dirR };
00106
00107
00108
00109
00110 double vtxLong = dirUnit[0] * vertex.x() + dirUnit[1] * vertex.y();
00111
00112
00113 double tIP = dirUnit[0] * vertex.y() - dirUnit[1] * vertex.x();
00114
00115
00116 double r, z;
00117
00118 if (side) {
00119 double slope = dirR / dir.z();
00120
00121
00122 r = vtxLong + slope * (side * Z_ENDCAP - vertex.z());
00123 double r2 = sqr(r) + sqr(tIP);
00124
00125 if (r2 < R_FORWARD2) {
00126
00127 r = vtxLong + slope * (side * Z_FORWARD - vertex.z());
00128 z = side * Z_FORWARD;
00129 } else if (r2 < R_BARREL2) {
00130
00131 z = side * Z_ENDCAP;
00132 } else {
00133
00134 side = 0;
00135 }
00136 }
00137
00138 if (!side) {
00139
00140 double slope = dir.z() / dirR;
00141 r = std::sqrt(R_BARREL2 - sqr(tIP));
00142 z = vertex.z() + slope * (r - vtxLong);
00143 }
00144
00145
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
00319 float Jet::physicsEta (float fZVertex, float fDetectorEta) {
00320 CaloPointZ refPoint (0., fDetectorEta);
00321 return refPoint.etaReference (fZVertex);
00322 }
00323
00325
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());
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());
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 }
00386
00387 float ptD_value = (sum_pt>0.) ? sqrt( sum_pt2 / (sum_pt*sum_pt) ) : 0.;
00388
00389 return ptD_value;
00390
00391 }
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 }
00416
00417 float rmsCand_value = (sum_pt2>0.) ? sum_pt2deltaR2/sum_pt2 : 0.;
00418
00419 return rmsCand_value;
00420
00421 }
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);
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 }