00001 #include "QCDAnalysis/ChargedHadronSpectra/interface/EcalShowerProperties.h"
00002
00003 #include "FWCore/Framework/interface/Event.h"
00004 #include "FWCore/Framework/interface/EventSetup.h"
00005 #include "FWCore/Framework/interface/ESHandle.h"
00006
00007 #include "DataFormats/TrackReco/interface/Track.h"
00008 #include "DataFormats/EcalDetId/interface/EcalSubdetector.h"
00009 #include "DataFormats/GeometrySurface/interface/Cylinder.h"
00010 #include "DataFormats/EcalDetId/interface/EBDetId.h"
00011 #include "DataFormats/EcalDetId/interface/EEDetId.h"
00012
00013 #include "Geometry/CaloGeometry/interface/CaloGeometry.h"
00014 #include "Geometry/CaloGeometry/interface/CaloSubdetectorGeometry.h"
00015
00016 #include "TrackingTools/TrajectoryState/interface/FreeTrajectoryState.h"
00017 #include "TrackingTools/TrajectoryParametrization/interface/GlobalTrajectoryParameters.h"
00018 #include "TrackingTools/Records/interface/TrackingComponentsRecord.h"
00019 #include "TrackingTools/MaterialEffects/interface/PropagatorWithMaterial.h"
00020
00021 #include "MagneticField/Records/interface/IdealMagneticFieldRecord.h"
00022 #include "MagneticField/Engine/interface/MagneticField.h"
00023
00024 using namespace std;
00025
00026 const double R_M = 2.2;
00027
00028
00029
00030 EcalShowerProperties::EcalShowerProperties
00031 (const edm::Event & ev, const edm::EventSetup & es)
00032 {
00033
00034 edm::ESHandle<MagneticField> theMagneticFieldHandle;
00035 es.get<IdealMagneticFieldRecord>().get(theMagneticFieldHandle);
00036 theMagneticField = theMagneticFieldHandle.product();
00037
00038
00039 edm::ESHandle<Propagator> thePropagatorHandle;
00040 es.get<TrackingComponentsRecord>().get("PropagatorWithMaterial",
00041 thePropagatorHandle);
00042 thePropagator = thePropagatorHandle.product();
00043
00044
00045 edm::ESHandle<CaloGeometry> theCaloGeometryHandle;
00046 es.get<IdealGeometryRecord>().get(theCaloGeometryHandle);
00047 theCaloGeometry = (const CaloGeometry*)theCaloGeometryHandle.product();
00048
00049
00050 ev.getByLabel("ecalRecHit", "EcalRecHitsEB", recHitsBarrel);
00051 ev.getByLabel("ecalRecHit", "EcalRecHitsEE", recHitsEndcap);
00052 }
00053
00054
00055 FreeTrajectoryState EcalShowerProperties::getTrajectoryAtOuterPoint
00056 (const reco::Track & track)
00057 {
00058 GlobalPoint pos(track.outerX() , track.outerY() , track.outerZ() );
00059 GlobalVector mom(track.outerPx(), track.outerPy(), track.outerPz());
00060
00061 GlobalTrajectoryParameters gtp(pos,mom, track.charge(), theMagneticField);
00062
00063 return FreeTrajectoryState(gtp, track.outerStateCovariance());
00064 }
00065
00066
00067 Plane::PlanePointer EcalShowerProperties::getSurface
00068 (const CaloCellGeometry* cell, int i)
00069 {
00070 int j = i * 4;
00071
00072
00073 const CaloCellGeometry::CornersVec & c(cell->getCorners());
00074
00075
00076 GlobalPoint center( (c[j].x() + c[j+1].x() + c[j+2].x() + c[j+3].x()) / 4,
00077 (c[j].y() + c[j+1].y() + c[j+2].y() + c[j+3].y()) / 4,
00078 (c[j].z() + c[j+1].z() + c[j+2].z() + c[j+3].z()) / 4);
00079
00080
00081 Surface::PositionType pos(center);
00082 Surface::RotationType rot(c[j+1]-c[j], c[j+3]-c[j]);
00083 return Plane::build(pos, rot);
00084 }
00085
00086
00087 vector<TrajectoryStateOnSurface> EcalShowerProperties::getEndpoints
00088 (const FreeTrajectoryState & ftsAtLastPoint,
00089 const TrajectoryStateOnSurface & tsosBeforeEcal, int subDet)
00090 {
00091 std::vector<TrajectoryStateOnSurface> tsosEnds;
00092
00093 const CaloSubdetectorGeometry* geom =
00094 theCaloGeometry->getSubdetectorGeometry(DetId::Ecal,subDet);
00095
00096
00097 DetId detId(geom->getClosestCell(ftsAtLastPoint.position()));
00098
00099 if(!geom->present(detId)) return tsosEnds;
00100
00101 const CaloCellGeometry* cell = geom->getGeometry(detId);
00102 const CaloCellGeometry* oldcell;
00103 TrajectoryStateOnSurface tsos;
00104
00105
00106 for(int i = 0; i < 2; i++)
00107 {
00108 int step = 0;
00109
00110 do
00111 {
00112 oldcell = cell;
00113
00114 Plane::PlanePointer thePlane = getSurface(oldcell, i);
00115 tsos = thePropagator->propagate(ftsAtLastPoint,*thePlane);
00116
00117 if(!tsos.isValid()) return tsosEnds;
00118
00119 detId = geom->getClosestCell(tsos.globalPosition());
00120
00121 if(!geom->present(detId)) return tsosEnds;
00122 cell = geom->getGeometry(detId);
00123 }
00124 while(cell != oldcell && step++ < 5);
00125
00126 if(step++ < 5)
00127 tsosEnds.push_back(tsos);
00128 }
00129
00130 return tsosEnds;
00131 }
00132
00133
00134 double EcalShowerProperties::getDistance
00135 (const std::vector<TrajectoryStateOnSurface> & tsosEnds,
00136 const CaloCellGeometry* cell)
00137 {
00138 double dmin = 1e+9;
00139 LocalPoint p;
00140
00141
00142 p = tsosEnds[0].surface().toLocal(tsosEnds[0].globalPosition());
00143 LocalPoint p1(p.x(), p.y(), 0);
00144
00145 p = tsosEnds[0].surface().toLocal(tsosEnds[1].globalPosition());
00146 LocalPoint p2(p.x(), p.y(), 0);
00147
00148 const CaloCellGeometry::CornersVec & c(cell->getCorners());
00149
00150
00151 for(int i = 0; i < 4; i++)
00152 {
00153 p = tsosEnds[0].surface().toLocal(GlobalPoint(c[i].x(),c[i].y(),c[i].z()));
00154 LocalPoint c(p.x(), p.y(), 0);
00155
00156
00157 double d1 = (p1 - c).mag2();
00158 double d2 = (p2 - c).mag2();
00159 double dm = min(d1,d2);
00160
00161
00162 double lambda = (c - p1) * (p2 - p1) / (p2 - p1).mag2();
00163 if(lambda > 0 && lambda < 1)
00164 {
00165 double dp = (c - p1 - lambda * (p2 - p1)).mag2();
00166 dm = min (dm,dp);
00167 }
00168
00169 dmin = min(dm, dmin);
00170 }
00171
00172 return(sqrt(dmin));
00173 }
00174
00175
00176 pair<double,double> EcalShowerProperties::processEcalRecHits
00177 (const std::vector<TrajectoryStateOnSurface> & tsosEnds, int subDet, int & ntime)
00178 {
00179 const CaloSubdetectorGeometry* geom =
00180 theCaloGeometry->getSubdetectorGeometry(DetId::Ecal,subDet);
00181
00182 std::vector<DetId> detIds;
00183 detIds.push_back(geom->getClosestCell(tsosEnds[0].globalPosition()));
00184 detIds.push_back(geom->getClosestCell(tsosEnds[1].globalPosition()));
00185
00186 double energy = 0, time = 0;
00187 ntime = 0;
00188
00189 if(subDet == EcalBarrel)
00190 {
00191 EBDetId frontId(detIds[0]);
00192 EBDetId backId(detIds[1]);
00193
00194 double ieta = (frontId.ieta() + backId.ieta())/2.;
00195 double weta = fabs(frontId.ieta() - backId.ieta())/2.;
00196
00197 double iphi = (frontId.iphi() + backId.iphi())/2.;
00198 double wphi = fabs(frontId.iphi() - backId.iphi())/2.;
00199
00200 for(EBRecHitCollection::const_iterator recHit = recHitsBarrel->begin();
00201 recHit!= recHitsBarrel->end();
00202 recHit++)
00203 {
00204 EBDetId detId(recHit->id());
00205 const CaloCellGeometry* cell = geom->getGeometry(detId);
00206
00207 if(fabs(detId.ieta() - ieta) < weta + 4 &&
00208 fabs(detId.iphi() - iphi) < wphi + 4)
00209 if(getDistance(tsosEnds, cell) < R_M)
00210 {
00211 energy += recHit->energy();
00212 time += recHit->energy() * recHit->time();
00213 ntime++;
00214 }
00215 }
00216 }
00217 else
00218 {
00219 EEDetId frontId(detIds[0]);
00220 EEDetId backId(detIds[1]);
00221
00222 double ix = (frontId.ix() + backId.ix())/2.;
00223 double wx = fabs(frontId.ix() - backId.ix())/2.;
00224
00225 double iy = (frontId.iy() + backId.iy())/2.;
00226 double wy = fabs(frontId.iy() - backId.iy())/2.;
00227
00228 for(EERecHitCollection::const_iterator recHit = recHitsEndcap->begin();
00229 recHit!= recHitsEndcap->end();
00230 recHit++)
00231 {
00232 EEDetId detId(recHit->id());
00233 const CaloCellGeometry* cell = geom->getGeometry(detId);
00234
00235 if(detId.zside() == frontId.zside() &&
00236 detId.zside() == backId.zside())
00237 if( fabs(detId.ix() - ix) < wx + 4 &&
00238 fabs(detId.iy() - iy) < wy + 4)
00239 if(getDistance(tsosEnds, cell) < R_M)
00240 {
00241 energy += recHit->energy();
00242 time += recHit->energy() * recHit->time();
00243 ntime++;
00244 }
00245 }
00246 }
00247
00248 if(energy > 0) time /= energy;
00249
00250 return std::pair<double,double> (energy,time);
00251 }
00252
00253
00254 pair<double,double> EcalShowerProperties::processTrack
00255 (const reco::Track & track, int & ntime)
00256 {
00257
00258 FreeTrajectoryState ftsAtLastPoint = getTrajectoryAtOuterPoint(track);
00259
00260
00261 double radius = 129.0;
00262 double z = 320.9;
00263 Surface::RotationType rot;
00264
00265
00266 std::vector<int> subDets;
00267 subDets.push_back(EcalBarrel);
00268 subDets.push_back(EcalEndcap);
00269
00270 std::pair<double,double> result(0,0);
00271
00272
00273 for(std::vector<int>::const_iterator subDet = subDets.begin();
00274 subDet!= subDets.end(); subDet++)
00275 {
00276 TrajectoryStateOnSurface tsosBeforeEcal;
00277
00278 if(*subDet == EcalBarrel)
00279 {
00280 Surface::PositionType pos(0,0,0);
00281 Cylinder::CylinderPointer theBarrel = Cylinder::build(pos, rot, radius);
00282 tsosBeforeEcal = thePropagator->propagate(ftsAtLastPoint, *theBarrel);
00283
00284 if(!tsosBeforeEcal.isValid()) continue;
00285 if(fabs(tsosBeforeEcal.globalPosition().z()) > z) continue;
00286 }
00287 else
00288 {
00289 Surface::PositionType pos(0,0,z);
00290 Plane::PlanePointer theEndcap = Plane::build(pos, rot);
00291 tsosBeforeEcal = thePropagator->propagate(ftsAtLastPoint, *theEndcap);
00292
00293 if(!tsosBeforeEcal.isValid()) continue;
00294 if(fabs(tsosBeforeEcal.globalPosition().perp()) > radius) continue;
00295 }
00296
00297 std::vector<TrajectoryStateOnSurface> tsosEnds =
00298 getEndpoints(ftsAtLastPoint, tsosBeforeEcal, *subDet);
00299
00300 if(tsosEnds.size() == 2)
00301 result = processEcalRecHits(tsosEnds, *subDet, ntime);
00302 }
00303
00304 return result;
00305 }