00001 #include "RecoParticleFlow/PFClusterShapeProducer/interface/PFClusterShapeAlgo.h"
00002
00003 PFClusterShapeAlgo::PFClusterShapeAlgo(bool useFractions, double w0)
00004 {
00005 useFractions_ = useFractions;
00006 w0_ = w0;
00007 }
00008
00009 PFClusterShapeAlgo::~PFClusterShapeAlgo()
00010 {
00011 }
00012
00013 reco::ClusterShapeCollection *
00014 PFClusterShapeAlgo::makeClusterShapes(edm::Handle<reco::PFClusterCollection> clusterHandle,
00015 edm::Handle<reco::PFRecHitCollection> rechitHandle,
00016 const CaloSubdetectorGeometry * the_barrelGeo_p,
00017 const CaloSubdetectorTopology * the_barrelTop_p,
00018 const CaloSubdetectorGeometry * the_endcapGeo_p,
00019 const CaloSubdetectorTopology * the_endcapTop_p)
00020 {
00021 static const float etaEndOfBarrel = 1.497;
00022
00023 topoVector.push_back(the_barrelTop_p);
00024 topoVector.push_back(the_endcapTop_p);
00025 geomVector.push_back(the_barrelGeo_p);
00026 geomVector.push_back(the_endcapGeo_p);
00027
00028 reco::ClusterShapeCollection * shape_v_p = new reco::ClusterShapeCollection();
00029
00030 currentRecHit_v_p = rechitHandle;
00031
00032 for (unsigned int i = 0; i < clusterHandle->size(); ++i)
00033 {
00034
00035 currentCluster_p = reco::PFClusterRef(clusterHandle, i);
00036 currentClusterIndex_ = i;
00037
00038
00039 topoIndex = BARREL;
00040 geomIndex = BARREL;
00041 const math::XYZVector currentClusterPos(currentCluster_p->position());
00042 if (fabs(currentClusterPos.eta()) > etaEndOfBarrel)
00043 {
00044 topoIndex = ENDCAP;
00045 geomIndex = ENDCAP;
00046 }
00047
00048
00049 shape_v_p->push_back(makeClusterShape());
00050 }
00051
00052 topoVector.clear();
00053 topoVector.clear();
00054 geomVector.clear();
00055 geomVector.clear();
00056
00057 return shape_v_p;
00058 }
00059
00060 reco::ClusterShape PFClusterShapeAlgo::makeClusterShape()
00061 {
00062 find_eMax_e2nd();
00063 fill5x5Map();
00064
00065 find_e2x2();
00066 find_e3x2();
00067 find_e3x3();
00068 find_e4x4();
00069 find_e5x5();
00070
00071 find_e2x5Right();
00072 find_e2x5Left();
00073 find_e2x5Top();
00074 find_e2x5Bottom();
00075
00076 covariances();
00077
00078 double dummyLAT = 0;
00079 double dummyEtaLAT = 0;
00080 double dummyPhiLAT = 0;
00081 double dummyA20 = 0;
00082 double dummyA42 = 0;
00083
00084 std::vector<double> dummyEnergyBasketFractionEta_v;
00085 std::vector<double> dummyEnergyBasketFractionPhi_v;
00086
00087 return reco::ClusterShape(covEtaEta_, covEtaPhi_, covPhiPhi_,
00088 eMax_, eMaxId_, e2nd_, e2ndId_,
00089 e2x2_, e3x2_, e3x3_, e4x4_, e5x5_,
00090 e2x5Right_, e2x5Left_, e2x5Top_, e2x5Bottom_, e3x2Ratio_,
00091 dummyLAT, dummyEtaLAT, dummyPhiLAT, dummyA20, dummyA42,
00092 dummyEnergyBasketFractionEta_v, dummyEnergyBasketFractionPhi_v);
00093 }
00094
00095
00096 void PFClusterShapeAlgo::find_eMax_e2nd()
00097 {
00098 std::map<double, DetId> energyMap;
00099
00100
00101 const std::vector<reco::PFRecHitFraction> & fraction_v = currentCluster_p->recHitFractions();
00102
00103 for (std::vector<reco::PFRecHitFraction>::const_iterator it = fraction_v.begin(); it != fraction_v.end(); ++it)
00104 {
00105
00106
00107 const reco::PFRecHitRef rechit = it->recHitRef();
00108
00109 const DetId rechitDetId = DetId(rechit->detId());
00110
00111 energyMap[rechit->energy()] = rechitDetId;
00112 }
00113
00114 std::map<double, DetId>::reverse_iterator it = energyMap.rbegin();
00115 eMax_ = it->first;
00116 eMaxId_ = it->second;
00117 it++;
00118 e2nd_ = it->first;
00119 e2ndId_ = it->second;
00120 }
00121
00122 int PFClusterShapeAlgo::findPFRHIndexFromDetId(unsigned int id)
00123 {
00124 int index = -1;
00125 for (unsigned int k = 0; k < currentRecHit_v_p->size(); ++k)
00126 {
00127 if ((*currentRecHit_v_p)[k].detId() == id)
00128 {
00129 index = static_cast<int>(k);
00130 break;
00131 }
00132 }
00133 return index;
00134 }
00135
00136
00137 const reco::PFRecHitFraction * PFClusterShapeAlgo::getFractionFromDetId(const DetId & id)
00138 {
00139 const std::vector< reco::PFRecHitFraction > & fraction_v = currentCluster_p->recHitFractions();
00140 for (std::vector<reco::PFRecHitFraction>::const_iterator it = fraction_v.begin(); it != fraction_v.end(); ++it)
00141 {
00142
00143
00144 const reco::PFRecHitRef rh_p = it->recHitRef();
00145 const DetId rhDetId = DetId(rh_p->detId());
00146 if (rhDetId == id)
00147 {
00148 return &(*it);
00149 }
00150 }
00151 return 0;
00152 }
00153
00154
00155 void PFClusterShapeAlgo::fill5x5Map()
00156 {
00157
00158 CaloNavigator<DetId> position = CaloNavigator<DetId>(eMaxId_, topoVector[topoIndex]);
00159
00160 meanPosition_ = math::XYZVector(0.0, 0.0, 0.0);
00161 totalE_ = 0;
00162
00163 for (int i = 0; i < 5; ++i)
00164 {
00165 for (int j = 0; j < 5; ++j)
00166 {
00167 position.home();
00168 position.offsetBy(i - 2, j - 2);
00169
00170 RecHitWithFraction newEntry;
00171 newEntry.detId = DetId(0);
00172 newEntry.energy = 0.0;
00173 newEntry.position = math::XYZVector(0, 0, 0);
00174
00175 if (*position != DetId(0))
00176 {
00177
00178 const int index = findPFRHIndexFromDetId((*position).rawId());
00179
00180 if (index >= 0)
00181 {
00182 double fraction = 1.0;
00183 if (useFractions_)
00184 {
00185 fraction = 0.0;
00186 const reco::PFRecHitFraction * fraction_p = getFractionFromDetId(*position);
00187 if (fraction_p) { fraction = fraction_p->fraction(); }
00188 }
00189
00190 const reco::PFRecHitRef rhRef(currentRecHit_v_p, index);
00191 const math::XYZVector crystalPosition(rhRef->position());
00192 const double energyFraction = rhRef->energy() * fraction;
00193
00194 newEntry.detId = *position;
00195 newEntry.energy = energyFraction;
00196 newEntry.position = crystalPosition;
00197
00198 meanPosition_ = meanPosition_ + crystalPosition * energyFraction;
00199 totalE_ += energyFraction;
00200 }
00201 }
00202 map5x5[i][j] = newEntry;
00203 }
00204 }
00205 meanPosition_ /= totalE_;
00206 }
00207
00208 double PFClusterShapeAlgo::addMapEnergies(int etaIndexLow, int etaIndexHigh, int phiIndexLow, int phiIndexHigh)
00209 {
00210 const int etaLow = etaIndexLow + 2;
00211 const int etaHigh = etaIndexHigh + 2;
00212 const int phiLow = phiIndexLow + 2;
00213 const int phiHigh = phiIndexHigh + 2;
00214
00215 double energy = 0;
00216
00217 for (int i = etaLow; i <= etaHigh; ++i)
00218 {
00219 for (int j = phiLow; j <= phiHigh; ++j)
00220 {
00221 energy += map5x5[i][j].energy;
00222 }
00223 }
00224 return energy;
00225 }
00226
00227 void PFClusterShapeAlgo::find_e3x3() { e3x3_ = addMapEnergies(-1, +1, -1, +1); }
00228 void PFClusterShapeAlgo::find_e5x5() { e5x5_ = addMapEnergies(-2, +2, -2, +2); }
00229 void PFClusterShapeAlgo::find_e2x5Right() { e2x5Right_ = addMapEnergies(-2, +2, +1, +2); }
00230 void PFClusterShapeAlgo::find_e2x5Left() { e2x5Left_ = addMapEnergies(-2, +2, -2, -1); }
00231 void PFClusterShapeAlgo::find_e2x5Top() { e2x5Top_ = addMapEnergies(-2, -1, -2, +2); }
00232 void PFClusterShapeAlgo::find_e2x5Bottom() { e2x5Bottom_ = addMapEnergies(+1, +2, -2, +2); }
00233
00234 void PFClusterShapeAlgo::find_e4x4()
00235 {
00236 if (eMaxDir == SE) { e4x4_ = addMapEnergies(-2, +1, -2, +1); return; }
00237 if (eMaxDir == NE) { e4x4_ = addMapEnergies(-2, +1, -1, +2); return; }
00238 if (eMaxDir == SW) { e4x4_ = addMapEnergies(-1, +2, -2, +1); return; }
00239 if (eMaxDir == NW) { e4x4_ = addMapEnergies(-1, +2, -1, +2); return; }
00240 }
00241
00242 void PFClusterShapeAlgo::find_e2x2()
00243 {
00244 std::map<double, Direction> directionMap;
00245
00246 directionMap[addMapEnergies(-1, +0, -1, +0)] = SE;
00247 directionMap[addMapEnergies(-1, +0, +0, +1)] = NE;
00248 directionMap[addMapEnergies(+0, +1, -1, +0)] = SW;
00249 directionMap[addMapEnergies(+0, +1, +0, +1)] = NW;
00250
00251 const std::map<double, Direction>::reverse_iterator eMaxDir_it = directionMap.rbegin();
00252
00253 eMaxDir = eMaxDir_it->second;
00254
00255 e2x2_ = eMaxDir_it->first;
00256 }
00257
00258 void PFClusterShapeAlgo::find_e3x2()
00259 {
00260
00261 std::map<double, Direction> directionMap;
00262 directionMap[map5x5[2][3].energy] = N;
00263 directionMap[map5x5[2][1].energy] = S;
00264 directionMap[map5x5[1][2].energy] = E;
00265 directionMap[map5x5[3][2].energy] = W;
00266
00267 const Direction dir = directionMap.rbegin()->second;
00268
00269 if (dir == N)
00270 {
00271 e3x2_ = addMapEnergies(-1, +1, +0, +1);
00272 const double numerator = map5x5[3][2].energy + map5x5[1][2].energy;
00273 const double denominator = map5x5[1][3].energy + map5x5[3][3].energy + 0.5;
00274 e3x2Ratio_ = numerator / denominator;
00275 }
00276 else if (dir == S)
00277 {
00278 e3x2_ = addMapEnergies(-1, +1, -1, +0);
00279 const double numerator = map5x5[3][2].energy + map5x5[1][2].energy;
00280 const double denominator = map5x5[1][1].energy + map5x5[3][1].energy + 0.5;
00281 e3x2Ratio_ = numerator / denominator;
00282 }
00283 else if (dir == W)
00284 {
00285 e3x2_ = addMapEnergies(+0, +1, -1, +1);
00286 const double numerator = map5x5[2][3].energy + map5x5[2][1].energy;
00287 const double denominator = map5x5[3][3].energy + map5x5[3][1].energy + 0.5;
00288 e3x2Ratio_ = numerator / denominator;
00289 }
00290 else if (dir == E)
00291 {
00292 e3x2_ = addMapEnergies(-1, +0, -1, +1);
00293 const double numerator = map5x5[2][3].energy + map5x5[2][1].energy;
00294 const double denominator = map5x5[1][1].energy + map5x5[1][3].energy + 0.5;
00295 e3x2Ratio_ = numerator / denominator;
00296 }
00297 }
00298
00299 void PFClusterShapeAlgo::covariances()
00300 {
00301 double numeratorEtaEta = 0;
00302 double numeratorEtaPhi = 0;
00303 double numeratorPhiPhi = 0;
00304 double denominator = 0;
00305
00306 for (int i = 0; i < 5; ++i)
00307 {
00308 for (int j = 0; j < 5; ++j)
00309 {
00310 const math::XYZVector & crystalPosition(map5x5[i][j].position);
00311
00312 double dPhi = crystalPosition.phi() - meanPosition_.phi();
00313 if (dPhi > + Geom::pi()) { dPhi = Geom::twoPi() - dPhi; }
00314 if (dPhi < - Geom::pi()) { dPhi = Geom::twoPi() - dPhi; }
00315
00316 const double dEta = crystalPosition.eta() - meanPosition_.eta();
00317
00318 const double w = std::max(0.0, w0_ + log(map5x5[i][j].energy / totalE_));
00319
00320 denominator += w;
00321 numeratorEtaEta += w * dEta * dEta;
00322 numeratorEtaPhi += w * dEta * dPhi;
00323 numeratorPhiPhi += w * dPhi * dPhi;
00324 }
00325 }
00326
00327 covEtaEta_ = numeratorEtaEta / denominator;
00328 covEtaPhi_ = numeratorEtaPhi / denominator;
00329 covPhiPhi_ = numeratorPhiPhi / denominator;
00330 }
00331
00332
00333