CMS 3D CMS Logo

HGCalShowerShapeHelper.cc
Go to the documentation of this file.
2 
3 #include <Math/Vector3D.h>
4 #include <TMatrixD.h>
5 #include <TVectorD.h>
6 
7 #include <algorithm>
8 
11 
13  std::shared_ptr<const hgcal::RecHitTools> recHitTools,
14  std::shared_ptr<const std::unordered_map<uint32_t, const reco::PFRecHit *>> pfRecHitPtrMap,
15  const std::vector<std::pair<DetId, float>> &hitsAndFracs,
16  const double rawEnergy,
17  const double minHitE,
18  const double minHitET,
19  const int minLayer,
20  const int maxLayer,
21  const DetId::Detector subDet)
22  : recHitTools_(recHitTools),
23  pfRecHitPtrMap_(pfRecHitPtrMap),
24  rawEnergy_(rawEnergy),
25  minHitE_(minHitE),
26  minHitET_(minHitET),
27  minHitET2_(minHitET * minHitET),
28  minLayer_(minLayer),
29  maxLayer_(maxLayer <= 0 ? recHitTools_->lastLayerEE() : maxLayer),
30  nLayer_(maxLayer_ - minLayer_ + 1),
31  subDet_(subDet) {
32  assert(nLayer_ > 0);
33  setFilteredHitsAndFractions(hitsAndFracs);
35 }
36 
38  return recHitTools_->getSiThickIndex(detId) == 0 ? kHDWaferCellSize_ : kLDWaferCellSize_;
39 }
40 
41 double HGCalShowerShapeHelper::ShowerShapeCalc::getRvar(double cylinderR, bool useFractions, bool useCellSize) const {
42  if (hitsAndFracs_.empty()) {
43  return 0.0;
44  }
45 
46  if (rawEnergy_ <= 0.0) {
47  edm::LogWarning("HGCalShowerShapeHelper")
48  << "Encountered negative or zero energy for HGCal R-variable denominator: " << rawEnergy_ << std::endl;
49  }
50 
51  double cylinderR2 = cylinderR * cylinderR;
52 
53  double rVar = 0.0;
54 
55  auto hitEnergyIter = useFractions ? hitEnergiesWithFracs_.begin() : hitEnergies_.begin();
56 
57  hitEnergyIter--;
58 
59  for (const auto &hnf : hitsAndFracs_) {
60  hitEnergyIter++;
61 
62  DetId hitId = hnf.first;
63 
64  int hitLayer = recHitTools_->getLayer(hitId) - 1;
65 
66  const auto &hitPos = recHitTools_->getPosition(hitId);
67  ROOT::Math::XYZVector hitXYZ(hitPos.x(), hitPos.y(), hitPos.z());
68 
69  auto distXYZ = hitXYZ - layerCentroids_[hitLayer];
70 
71  double r2 = distXYZ.x() * distXYZ.x() + distXYZ.y() * distXYZ.y();
72 
73  // Including the cell size seems to make the variable less sensitive to the HD/LD transition region
74  if (useCellSize) {
75  if (std::sqrt(r2) > cylinderR + getCellSize(hitId)) {
76  continue;
77  }
78  }
79 
80  else if (r2 > cylinderR2) {
81  continue;
82  }
83 
84  rVar += *hitEnergyIter;
85  }
86 
87  rVar /= rawEnergy_;
88 
89  return rVar;
90 }
91 
93  bool useFractions) const {
94  if (hitsAndFracs_.empty()) {
95  return ShowerWidths();
96  }
97 
98  double cylinderR2 = cylinderR * cylinderR;
99 
100  TMatrixD covMat(3, 3);
101 
102  double dxdx = 0.0;
103  double dydy = 0.0;
104  double dzdz = 0.0;
105 
106  double dxdy = 0.0;
107  double dydz = 0.0;
108  double dzdx = 0.0;
109 
110  double totalW = 0.0;
111 
112  auto hitEnergyIter = useFractions ? hitEnergiesWithFracs_.begin() : hitEnergies_.begin();
113 
114  int nHit = 0;
115  hitEnergyIter--;
116 
117  for (const auto &hnf : hitsAndFracs_) {
118  hitEnergyIter++;
119 
120  DetId hitId = hnf.first;
121 
122  const auto &hitPos = recHitTools_->getPosition(hitId);
123  ROOT::Math::XYZVector hitXYZ(hitPos.x(), hitPos.y(), hitPos.z());
124 
125  int hitLayer = recHitTools_->getLayer(hitId) - 1;
126 
127  ROOT::Math::XYZVector radXYZ = hitXYZ - layerCentroids_[hitLayer];
128 
129  double r2 = radXYZ.x() * radXYZ.x() + radXYZ.y() * radXYZ.y();
130 
131  if (r2 > cylinderR2) {
132  continue;
133  }
134 
135  ROOT::Math::XYZVector dXYZ = hitXYZ - centroid_;
136 
137  double weight = *hitEnergyIter;
138  totalW += weight;
139 
140  dxdx += weight * dXYZ.x() * dXYZ.x();
141  dydy += weight * dXYZ.y() * dXYZ.y();
142  dzdz += weight * dXYZ.z() * dXYZ.z();
143 
144  dxdy += weight * dXYZ.x() * dXYZ.y();
145  dydz += weight * dXYZ.y() * dXYZ.z();
146  dzdx += weight * dXYZ.z() * dXYZ.x();
147 
148  nHit++;
149  }
150 
151  if (!totalW || nHit < 2) {
152  return ShowerWidths();
153  }
154 
155  dxdx /= totalW;
156  dydy /= totalW;
157  dzdz /= totalW;
158 
159  dxdy /= totalW;
160  dydz /= totalW;
161  dzdx /= totalW;
162 
163  covMat(0, 0) = dxdx;
164  covMat(1, 1) = dydy;
165  covMat(2, 2) = dzdz;
166 
167  covMat(0, 1) = covMat(1, 0) = dxdy;
168  covMat(0, 2) = covMat(2, 0) = dzdx;
169  covMat(1, 2) = covMat(2, 1) = dydz;
170 
171  if (!covMat.Sum()) {
172  return ShowerWidths();
173  }
174 
175  // Get eigen values and vectors
176  TVectorD eigVals(3);
177  TMatrixD eigVecMat(3, 3);
178 
179  eigVecMat = covMat.EigenVectors(eigVals);
180 
181  ShowerWidths returnWidths;
182 
183  returnWidths.sigma2xx = dxdx;
184  returnWidths.sigma2yy = dydy;
185  returnWidths.sigma2zz = dzdz;
186 
187  returnWidths.sigma2xy = dxdy;
188  returnWidths.sigma2yz = dydz;
189  returnWidths.sigma2zx = dzdx;
190 
191  returnWidths.sigma2uu = eigVals(1);
192  returnWidths.sigma2vv = eigVals(2);
193  returnWidths.sigma2ww = eigVals(0);
194 
195  return returnWidths;
196 }
197 
199  bool useFractions) const {
200  std::vector<double> sortedEnergies(nrHits, 0.);
201  const auto &hits = useFractions ? hitEnergiesWithFracs_ : hitEnergies_;
202  std::partial_sort_copy(
203  hits.begin(), hits.end(), sortedEnergies.begin(), sortedEnergies.end(), std::greater<double>());
204  return sortedEnergies;
205 }
206 
208  const std::vector<std::pair<DetId, float>> &hitsAndFracs) {
209  hitsAndFracs_.clear();
210  hitEnergies_.clear();
211  hitEnergiesWithFracs_.clear();
212 
213  for (const auto &hnf : hitsAndFracs) {
214  DetId hitId = hnf.first;
215  float hitEfrac = hnf.second;
216 
217  int hitLayer = recHitTools_->getLayer(hitId);
218 
219  if (hitLayer > nLayer_) {
220  continue;
221  }
222 
223  if (hitId.det() != subDet_) {
224  continue;
225  }
226  auto hitIt = pfRecHitPtrMap_->find(hitId.rawId());
227  if (hitIt == pfRecHitPtrMap_->end()) {
228  continue;
229  }
230 
231  const reco::PFRecHit &recHit = *hitIt->second;
232 
233  if (recHit.energy() < minHitE_) {
234  continue;
235  }
236 
237  if (recHit.pt2() < minHitET2_) {
238  continue;
239  }
240 
241  // Fill the vectors
242  hitsAndFracs_.push_back(hnf);
243  hitEnergies_.push_back(recHit.energy());
244  hitEnergiesWithFracs_.push_back(recHit.energy() * hitEfrac);
245  }
246 }
247 
249  layerEnergies_.clear();
250  layerEnergies_.resize(nLayer_);
251 
252  layerCentroids_.clear();
253  layerCentroids_.resize(nLayer_);
254 
255  centroid_.SetXYZ(0, 0, 0);
256 
257  int iHit = -1;
258  double totalW = 0.0;
259 
260  // Compute the centroid per layer
261  for (const auto &hnf : hitsAndFracs_) {
262  iHit++;
263 
264  DetId hitId = hnf.first;
265 
266  double weight = hitEnergies_[iHit];
267  totalW += weight;
268 
269  const auto &hitPos = recHitTools_->getPosition(hitId);
270  ROOT::Math::XYZVector hitXYZ(hitPos.x(), hitPos.y(), hitPos.z());
271 
272  centroid_ += weight * hitXYZ;
273 
274  int hitLayer = recHitTools_->getLayer(hitId) - 1;
275 
276  layerEnergies_[hitLayer] += weight;
277  layerCentroids_[hitLayer] += weight * hitXYZ;
278  }
279 
280  int iLayer = -1;
281 
282  for (auto &centroid : layerCentroids_) {
283  iLayer++;
284 
285  if (layerEnergies_[iLayer]) {
286  centroid /= layerEnergies_[iLayer];
287  }
288  }
289 
290  if (totalW) {
291  centroid_ /= totalW;
292  }
293 }
294 
296  : recHitTools_(std::make_shared<hgcal::RecHitTools>()),
297  pfRecHitPtrMap_(std::make_shared<std::unordered_map<uint32_t, const reco::PFRecHit *>>()) {}
298 
300  : recHitTools_(std::make_shared<hgcal::RecHitTools>()),
301  pfRecHitPtrMap_(std::make_shared<std::unordered_map<uint32_t, const reco::PFRecHit *>>()) {
302  setTokens(sumes);
303 }
304 
306  recHitTools_->setGeometry(iSetup.getData(caloGeometryToken_));
307 }
308 
309 void HGCalShowerShapeHelper::initPerEvent(const std::vector<reco::PFRecHit> &pfRecHits) {
311 }
312 
313 void HGCalShowerShapeHelper::initPerEvent(const edm::EventSetup &iSetup, const std::vector<reco::PFRecHit> &pfRecHits) {
314  initPerSetup(iSetup);
316 }
317 
319  const std::vector<std::pair<DetId, float>> &hitsAndFracs,
320  double rawEnergy,
321  double minHitE,
322  double minHitET,
323  int minLayer,
324  int maxLayer,
325  DetId::Detector subDet) const {
326  return ShowerShapeCalc(
327  recHitTools_, pfRecHitPtrMap_, hitsAndFracs, rawEnergy, minHitE, minHitET, minLayer, maxLayer, subDet);
328 }
329 
330 void HGCalShowerShapeHelper::setPFRecHitPtrMap(const std::vector<reco::PFRecHit> &recHits) {
331  pfRecHitPtrMap_->clear();
332 
333  for (const auto &recHit : recHits) {
334  (*pfRecHitPtrMap_)[recHit.detId()] = &recHit;
335  }
336 }
float dydz
std::shared_ptr< std::unordered_map< uint32_t, const reco::PFRecHit * > > pfRecHitPtrMap_
T const & getData(const ESGetToken< T, R > &iToken) const noexcept(false)
Definition: EventSetup.h:119
double getRvar(double cylinderR, bool useFractions=true, bool useCellSize=true) const
Definition: weight.py:1
static const double kHDWaferCellSize_
assert(be >=bs)
constexpr Detector det() const
get the detector field from this detid
Definition: DetId.h:46
ShowerShapeCalc(std::shared_ptr< const hgcal::RecHitTools > recHitTools, std::shared_ptr< const std::unordered_map< uint32_t, const reco::PFRecHit *> > pfRecHitPtrMap, const std::vector< std::pair< DetId, float > > &hitsAndFracs, const double rawEnergy, const double minHitE=0, const double minHitET=0, const int minLayer=1, const int maxLayer=-1, DetId::Detector subDet=DetId::HGCalEE)
Particle flow rechit (rechit + geometry and topology information). See clustering algorithm in PFClus...
Definition: PFRecHit.h:31
void initPerSetup(const edm::EventSetup &iSetup)
void setFilteredHitsAndFractions(const std::vector< std::pair< DetId, float > > &hitsAndFracs)
void initPerEvent(const std::vector< reco::PFRecHit > &recHits)
T sqrt(T t)
Definition: SSEVec.h:19
static const double kLDWaferCellSize_
std::vector< double > getEnergyHighestHits(unsigned int nrHits, bool useFractions=true) const
std::shared_ptr< hgcal::RecHitTools > recHitTools_
Definition: DetId.h:17
edm::ESGetToken< CaloGeometry, CaloGeometryRecord > caloGeometryToken_
Transform3DPJ::Vector XYZVector
constexpr uint32_t rawId() const
get the raw id
Definition: DetId.h:57
Detector
Definition: DetId.h:24
fixed size matrix
void setTokens(edm::ConsumesCollector consumesCollector)
void setPFRecHitPtrMap(const std::vector< reco::PFRecHit > &recHits)
Log< level::Warning, false > LogWarning
ShowerWidths getPCAWidths(double cylinderR, bool useFractions=false) const
HGCalShowerShapeHelper::ShowerShapeCalc createCalc(const std::vector< std::pair< DetId, float > > &hitsAndFracs, double rawEnergy, double minHitE=0, double minHitET=0, int minLayer=1, int maxLayer=-1, DetId::Detector subDet=DetId::HGCalEE) const