CMS 3D CMS Logo

/data/refman/pasoursint/CMSSW_4_1_8_patch12/src/DataFormats/CaloTowers/src/CaloTower.cc

Go to the documentation of this file.
00001 #include "DataFormats/CaloTowers/interface/CaloTower.h"
00002 
00003 
00004 CaloTower::CaloTower() {
00005   emE_=0;
00006   hadE_=0;
00007   outerE_=0;
00008   emLvl1_=0;
00009   hadLvl1_=0;
00010 }
00011 
00012 CaloTower::CaloTower(const CaloTowerDetId& id,
00013                      double emE, double hadE, double outerE,
00014                      int ecal_tp, int hcal_tp,
00015                      const PolarLorentzVector p4,
00016                      GlobalPoint emPos, GlobalPoint hadPos) : 
00017   LeafCandidate(0, p4, Point(0,0,0)),  
00018   id_(id),
00019   emPosition_(emPos), hadPosition_(hadPos), 
00020   emE_(emE), hadE_(hadE), outerE_(outerE),
00021   emLvl1_(ecal_tp), hadLvl1_(hcal_tp) {}
00022 
00023 
00024 CaloTower::CaloTower(const CaloTowerDetId& id,
00025                      double emE, double hadE, double outerE,
00026                      int ecal_tp, int hcal_tp,
00027                      const LorentzVector p4,
00028                      GlobalPoint emPos, GlobalPoint hadPos) : 
00029   LeafCandidate(0, p4, Point(0,0,0)),  
00030   id_(id),
00031   emPosition_(emPos), hadPosition_(hadPos),
00032   emE_(emE), hadE_(hadE), outerE_(outerE),
00033   emLvl1_(ecal_tp), hadLvl1_(hcal_tp) {}
00034 
00035 
00036 // recalculated momentum-related quantities wrt user provided vertex Z position
00037 
00038 
00039 math::PtEtaPhiMLorentzVector CaloTower::hadP4(double vtxZ) const {
00040 
00041   math::PtEtaPhiMLorentzVector newP4(0,0,0,0);
00042 
00043   // note: for now we use the same position for HO as for the other detectors
00044 
00045   double hcalTot;
00046   if (abs(ieta())<16) hcalTot = (energy() - emE_);
00047   else hcalTot = hadE_;
00048 
00049   if (hcalTot>0) {
00050     double ctgTheta = (hadPosition_.z() - vtxZ)/hadPosition_.perp();
00051     double newEta = asinh(ctgTheta);  
00052     double pf = 1.0/cosh(newEta);
00053 
00054     newP4 = PolarLorentzVector(hcalTot * pf, newEta, hadPosition_.phi(), 0.0);   
00055   }
00056   
00057   return newP4;
00058 }
00059 
00060 math::PtEtaPhiMLorentzVector CaloTower::emP4(double vtxZ) const {
00061 
00062   math::PtEtaPhiMLorentzVector newP4(0,0,0,0);
00063 
00064   if (emE_>0) {
00065     double ctgTheta = (emPosition_.z() - vtxZ)/emPosition_.perp();
00066     double newEta = asinh(ctgTheta);  
00067     double pf = 1.0/cosh(newEta);
00068   
00069     newP4 = math::PtEtaPhiMLorentzVector(emE_ * pf, newEta, emPosition_.phi(), 0.0);   
00070   }
00071   
00072   return newP4;
00073 }
00074 
00075 
00076 // recalculated momentum-related quantities wrt user provided 3D vertex 
00077 
00078 
00079 math::PtEtaPhiMLorentzVector CaloTower::hadP4(Point v) const {
00080 
00081   math::PtEtaPhiMLorentzVector newP4(0,0,0,0);
00082 
00083   GlobalPoint p(v.x(), v.y(), v.z());
00084 
00085   // note: for now we use the same position for HO as for the other detectors
00086 
00087   double hcalTot;
00088   if (abs(ieta())<16) hcalTot = (energy() - emE_);
00089   else hcalTot = hadE_;
00090 
00091   if (hcalTot>0) {
00092     math::XYZVector dir = math::XYZVector(hadPosition_ - p);
00093     newP4 = math::PtEtaPhiMLorentzVector(hcalTot * sin(dir.theta()), dir.eta(), dir.phi(), 0.0);  
00094   }
00095 
00096   return newP4;
00097 }
00098 
00099 math::PtEtaPhiMLorentzVector CaloTower::emP4(Point v) const {
00100 
00101   math::PtEtaPhiMLorentzVector newP4(0,0,0,0);
00102 
00103   GlobalPoint p(v.x(), v.y(), v.z());
00104 
00105   if (emE_>0) {
00106     math::XYZVector dir = math::XYZVector(emPosition_ - p);
00107     newP4 = math::PtEtaPhiMLorentzVector(emE_ * sin(dir.theta()), dir.eta(), dir.phi(), 0.0);   
00108   }
00109   
00110   return newP4;
00111 }
00112 
00113 
00114 math::PtEtaPhiMLorentzVector CaloTower::p4(double vtxZ) const {
00115 
00116   math::PtEtaPhiMLorentzVector newP4(0,0,0,0);
00117 
00118   if (abs(ieta())<=29) {
00119     newP4 += emP4(vtxZ);
00120     newP4 += hadP4(vtxZ);
00121   }
00122   else { // em and had energy in HF are defined in a special way
00123     double ctgTheta = (emPosition_.z() - vtxZ)/emPosition_.perp(); // em and had positions in HF are forced to be the same
00124     double newEta = asinh(ctgTheta);  
00125     double pf = 1.0/cosh(newEta);
00126     newP4 = math::PtEtaPhiMLorentzVector(p4().energy() * pf, newEta, emPosition_.phi(), 0.0);   
00127   }
00128 
00129   return newP4;
00130 }
00131 
00132 
00133 math::PtEtaPhiMLorentzVector CaloTower::p4(Point v) const {
00134 
00135   math::PtEtaPhiMLorentzVector newP4(0,0,0,0);
00136 
00137   if (abs(ieta())<=29) {
00138     newP4 += emP4(v);
00139     newP4 += hadP4(v);
00140   }
00141   else { // em and had energy in HF are defined in a special way
00142     GlobalPoint p(v.x(), v.y(), v.z());
00143     math::XYZVector dir = math::XYZVector(emPosition_ - p); // em and had positions in HF are forced to be the same
00144     newP4 = math::PtEtaPhiMLorentzVector(p4().energy() * sin(dir.theta()), dir.eta(), dir.phi(), 0.0);   
00145   }
00146 
00147   return newP4;
00148 }
00149 
00150 
00151 // p4 contribution from HO alone (note: direction is always taken to be the same as used for HB.)
00152 
00153 math::PtEtaPhiMLorentzVector CaloTower::p4_HO(Point v) const {
00154 
00155   math::PtEtaPhiMLorentzVector thisP4(0,0,0,0);
00156 
00157   if (ietaAbs()>15 || outerE_<0) return thisP4;
00158   
00159   GlobalPoint p(v.x(), v.y(), v.z());
00160   math::XYZVector dir = math::XYZVector(hadPosition_ - p);
00161   thisP4 = math::PtEtaPhiMLorentzVector(outerE_ * sin(dir.theta()), dir.eta(), dir.phi(), 0.0);  
00162 
00163   return thisP4; 
00164 }
00165 
00166 math::PtEtaPhiMLorentzVector CaloTower::p4_HO(double vtxZ) const {
00167     Point p(0, 0, vtxZ);
00168     return p4_HO(p);
00169 }
00170 
00171 math::PtEtaPhiMLorentzVector CaloTower::p4_HO() const {
00172 
00173   math::PtEtaPhiMLorentzVector thisP4(0,0,0,0);
00174 
00175   if (ietaAbs()>15 || outerE_<0) return thisP4;
00176   thisP4 = math::PtEtaPhiMLorentzVector(outerE_ * sin(hadPosition_.theta()), hadPosition_.eta(), hadPosition_.phi(), 0.0);  
00177 
00178   return thisP4;
00179 }
00180 
00181 
00182 
00183 
00184 
00185 
00186 void CaloTower::addConstituents( const std::vector<DetId>& ids ) {
00187   constituents_.reserve(constituents_.size()+ids.size());
00188   constituents_.insert(constituents_.end(),ids.begin(),ids.end());
00189 }
00190 
00191 int CaloTower::numCrystals() const {
00192   if (id_.ietaAbs()>29) return 0;
00193   
00194   int nC = 0;
00195   std::vector<DetId>::const_iterator it = constituents_.begin();
00196   for (; it!=constituents_.end(); ++it) {
00197     if (it->det()==DetId::Ecal) ++nC;
00198   }
00199 
00200   return nC;
00201 }
00202 
00203 
00204 
00205 // Set the CaloTower status word from the number of bad/recovered/problematic
00206 // cells in HCAL and ECAL.
00207 
00208 void CaloTower::setCaloTowerStatus(unsigned int numBadHcalChan,unsigned int numBadEcalChan, 
00209                                    unsigned int numRecHcalChan,unsigned int numRecEcalChan,
00210                                    unsigned int numProbHcalChan,unsigned int numProbEcalChan) {
00211 
00212   twrStatusWord_ = 0x0;
00213 
00214   twrStatusWord_ |= (  numBadEcalChan  & 0x1F);
00215   twrStatusWord_ |= ( (numRecEcalChan  & 0x1F) << 5);
00216   twrStatusWord_ |= ( (numProbEcalChan & 0x1F) << 10); 
00217   twrStatusWord_ |= ( (numBadHcalChan  & 0x7)  << 15);
00218   twrStatusWord_ |= ( (numRecHcalChan  & 0x7)  << 18);
00219   twrStatusWord_ |= ( (numProbHcalChan & 0x7)  << 21);
00220 
00221   return;
00222 }
00223 
00224 
00225 
00226 
00227 // energy in the tower by HCAL subdetector
00228 // This is trivia except for tower 16
00229 // needed by JetMET cleanup in AOD.
00230 
00231 double CaloTower::energyInHB() const  { 
00232   if (id_.ietaAbs()<16) return hadE_;
00233   else if (id_.ietaAbs()==16) return hadE_-outerE_;
00234   else return 0.0;
00235 }
00236 
00237 double CaloTower::energyInHE() const { 
00238   if (id_.ietaAbs()>16 && id_.ietaAbs()<30) return hadE_;
00239   else if (id_.ietaAbs()==16) return outerE_;
00240   else return 0.0;
00241 }
00242  
00243 double CaloTower::energyInHF() const {
00244   if (id_.ietaAbs()>29) return energy();
00245   else return 0.0;
00246 }
00247 
00248 // this is actual energy contributed to the tower
00249 // (outerEnergy() returns HO energy regardless if it is used or not)
00250 // Note: rounding error may lead to values not identically equal to zero
00251 // when HO was not used 
00252 
00253 double CaloTower::energyInHO() const {
00254   if (id_.ietaAbs()>15) return 0.0;
00255   else return (energy() - hadE_ -emE_);
00256 }
00257 
00258 
00259 
00260 
00261 
00262 std::ostream& operator<<(std::ostream& s, const CaloTower& ct) {
00263   return s << ct.id() << ":"  << ct.et()
00264            << " GeV ET (EM=" << ct.emEt() <<
00265     " HAD=" << ct.hadEt() << " OUTER=" << ct.outerEt() << ") (" << ct.eta() << "," << ct.phi() << ")";    
00266 }