CMS 3D CMS Logo

EgammaPCAHelper.cc
Go to the documentation of this file.
1 
3 
8 
10 
11 #include <algorithm>
12 #include <iostream>
13 #include <memory>
14 
15 using namespace hgcal;
16 
18  : // Thickness correction to dEdx weights
19  // (100um, 200um, 300um silicon)
20  // See RecoLocalCalo.HGCalRecProducers.HGCalRecHit_cfi
21  invThicknessCorrection_({1. / 1.132, 1. / 1.092, 1. / 1.084}),
22  pca_(new TPrincipal(3, "D")) {
23  hitMap_ = nullptr;
24  debug_ = false;
25 }
26 
27 void EGammaPCAHelper::setHitMap(const std::unordered_map<DetId, const unsigned int>* hitMap) {
28  hitMap_ = hitMap;
29  pcaIteration_ = 0;
30 }
31 
33  edm::Handle<HGCRecHitCollection> recHitHandleFH,
34  edm::Handle<HGCRecHitCollection> recHitHandleBH) {
35  unsigned int total_size = recHitHandleEE->size() + recHitHandleFH->size() + recHitHandleBH->size();
36  hits_.resize(total_size);
37  unsigned int firstIndex = 0;
38 
39  for (const auto& handle : {recHitHandleEE, recHitHandleFH, recHitHandleBH}) {
40  unsigned int collection_size = handle->size();
41  for (unsigned int i = 0; i < collection_size; ++i) {
42  hits_[firstIndex + i] = &(*handle)[i];
43  }
44  firstIndex += collection_size;
45  }
46 }
47 
49  recHitTools_ = recHitTools;
51 }
52 
54  theCluster_ = &cluster;
55  std::vector<std::pair<DetId, float>> result;
56  for (reco::HGCalMultiCluster::component_iterator it = cluster.begin(); it != cluster.end(); it++) {
57  const std::vector<std::pair<DetId, float>>& hf = (*it)->hitsAndFractions();
58  result.insert(result.end(), hf.begin(), hf.end());
59  }
61 }
62 
64  theCluster_ = &cluster;
65  storeRecHits(cluster.hitsAndFractions());
66 }
67 
68 void EGammaPCAHelper::storeRecHits(const std::vector<std::pair<DetId, float>>& hf) {
69  std::vector<double> pcavars;
70  pcavars.resize(3, 0.);
71  theSpots_.clear();
72  pcaIteration_ = 0;
73 
74  sigu_ = 0.;
75  sigv_ = 0.;
76  sigp_ = 0.;
77  sige_ = 0.;
78 
79  unsigned hfsize = hf.size();
80  if (debug_)
81  std::cout << "The seed cluster constains " << hfsize << " hits " << std::endl;
82 
83  if (hfsize == 0)
84  return;
85 
86  for (unsigned int j = 0; j < hfsize; j++) {
87  unsigned int layer = recHitTools_->getLayerWithOffset(hf[j].first);
88 
89  const DetId rh_detid = hf[j].first;
90  std::unordered_map<DetId, const unsigned int>::const_iterator itcheck = hitMap_->find(rh_detid);
91  if (itcheck == hitMap_->end()) {
92  edm::LogWarning("EgammaPCAHelper") << " Big problem, unable to find a hit " << rh_detid.rawId() << " "
93  << rh_detid.det() << " " << HGCalDetId(rh_detid) << std::endl;
94  continue;
95  }
96 
97  if (debug_) {
98  const HGCRecHit* hit = hits_[itcheck->second];
99  std::cout << "DetId " << rh_detid.rawId() << " " << layer << " " << hit->energy() << std::endl;
100  std::cout << " Hit " << hit << " " << hit->energy() << std::endl;
101  }
102  float fraction = hf[j].second;
103 
104  int thickIndex = recHitTools_->getSiThickIndex(rh_detid);
105  double mip = dEdXWeights_[layer] * 0.001; // convert in GeV
106  if (thickIndex > -1 and thickIndex < 3)
107  mip *= invThicknessCorrection_[thickIndex];
108 
109  pcavars[0] = recHitTools_->getPosition(rh_detid).x();
110  pcavars[1] = recHitTools_->getPosition(rh_detid).y();
111  pcavars[2] = recHitTools_->getPosition(rh_detid).z();
112  if (pcavars[2] == 0.)
113  edm::LogWarning("EgammaPCAHelper") << " Problem, hit with z =0 ";
114  else {
115  const HGCRecHit* hit = hits_[itcheck->second];
116  Spot mySpot(rh_detid, hit->energy(), pcavars, layer, fraction, mip);
117  theSpots_.push_back(mySpot);
118  }
119  }
120  if (debug_) {
121  std::cout << " Stored " << theSpots_.size() << " hits " << std::endl;
122  }
123 }
124 
125 void EGammaPCAHelper::computePCA(float radius, bool withHalo) {
126  // very important - to reset
127  pca_ = std::make_unique<TPrincipal>(3, "D");
128  bool initialCalculation = radius < 0;
129  if (debug_)
130  std::cout << " Initial calculation " << initialCalculation << std::endl;
131  if (initialCalculation && withHalo) {
132  edm::LogWarning("EGammaPCAHelper") << "Warning - in the first iteration, the halo hits are excluded " << std::endl;
133  withHalo = false;
134  }
135 
136  float radius2 = radius * radius;
137  if (!initialCalculation) {
138  math::XYZVector mainAxis(axis_);
139  mainAxis.unit();
140  math::XYZVector phiAxis(barycenter_.x(), barycenter_.y(), 0);
141  math::XYZVector udir(mainAxis.Cross(phiAxis));
142  udir = udir.unit();
145  Point(barycenter_ + udir),
146  Point(0, 0, 0),
147  Point(0., 0., 1.),
148  Point(1., 0., 0.));
149  }
150 
151  std::set<int> layers;
152  for (const auto& spot : theSpots_) {
153  if (spot.layer() > recHitTools_->lastLayerEE())
154  continue;
155  if (!withHalo && (!spot.isCore()))
156  continue;
157  if (initialCalculation) {
158  // initial calculation, take only core hits
159  if (!spot.isCore())
160  continue;
161  layers.insert(spot.layer());
162  for (int i = 0; i < spot.multiplicity(); ++i)
163  pca_->AddRow(spot.row());
164  } else {
165  // use a cylinder, include all hits
166  math::XYZPoint local = trans_(Point(spot.row()[0], spot.row()[1], spot.row()[2]));
167  if (local.Perp2() > radius2)
168  continue;
169  layers.insert(spot.layer());
170  for (int i = 0; i < spot.multiplicity(); ++i)
171  pca_->AddRow(spot.row());
172  }
173  }
174  if (debug_)
175  std::cout << " Nlayers " << layers.size() << std::endl;
176  if (layers.size() < 3) {
177  pcaIteration_ = -1;
178  return;
179  }
180  pca_->MakePrincipals();
181  ++pcaIteration_;
182  const TVectorD& means = *(pca_->GetMeanValues());
183  const TMatrixD& eigens = *(pca_->GetEigenVectors());
184 
186  axis_ = math::XYZVector(eigens(0, 0), eigens(1, 0), eigens(2, 0));
187  if (axis_.z() * barycenter_.z() < 0.0) {
188  axis_ = -1. * axis_;
189  }
190 }
191 
192 void EGammaPCAHelper::computeShowerWidth(float radius, bool withHalo) {
193  sigu_ = 0.;
194  sigv_ = 0.;
195  sigp_ = 0.;
196  sige_ = 0.;
197  double cyl_ene = 0.;
198 
199  float radius2 = radius * radius;
200  for (const auto& spot : theSpots_) {
201  Point globalPoint(spot.row()[0], spot.row()[1], spot.row()[2]);
202  math::XYZPoint local = trans_(globalPoint);
203  if (local.Perp2() > radius2)
204  continue;
205 
206  // Select halo hits or not
207  if (withHalo && spot.fraction() < 0)
208  continue;
209  if (!withHalo && !(spot.isCore()))
210  continue;
211 
212  sige_ += (globalPoint.eta() - theCluster_->eta()) * (globalPoint.eta() - theCluster_->eta()) * spot.energy();
213  sigp_ += deltaPhi(globalPoint.phi(), theCluster_->phi()) * deltaPhi(globalPoint.phi(), theCluster_->phi()) *
214  spot.energy();
215 
216  sigu_ += local.x() * local.x() * spot.energy();
217  sigv_ += local.y() * local.y() * spot.energy();
218  cyl_ene += spot.energy();
219  }
220 
221  if (cyl_ene > 0.) {
222  const double inv_cyl_ene = 1. / cyl_ene;
223  sigu_ = sigu_ * inv_cyl_ene;
224  sigv_ = sigv_ * inv_cyl_ene;
225  sigp_ = sigp_ * inv_cyl_ene;
226  sige_ = sige_ * inv_cyl_ene;
227  }
228  sigu_ = std::sqrt(sigu_);
229  sigv_ = std::sqrt(sigv_);
230  sigp_ = std::sqrt(sigp_);
231  sige_ = std::sqrt(sige_);
232 }
233 
235  if (pcaIteration_ == 0) {
236  if (debug_)
237  std::cout << " The PCA has not been run yet " << std::endl;
238  return false;
239  } else if (pcaIteration_ == 1) {
240  if (debug_)
241  std::cout << " The PCA has been run only once - careful " << std::endl;
242  return false;
243  } else if (pcaIteration_ == -1) {
244  if (debug_)
245  std::cout << " Not enough layers to perform PCA " << std::endl;
246  return false;
247  }
248  return true;
249 }
250 
252  theSpots_.clear();
253  pcaIteration_ = 0;
254  sigu_ = 0.;
255  sigv_ = 0.;
256  sigp_ = 0.;
257  sige_ = 0.;
258 }
259 
261  if (debug_)
262  checkIteration();
263  std::set<int> layers;
264  float radius2 = radius * radius;
265  std::vector<float> energyPerLayer(maxlayer_ + 1, 0.f);
266  math::XYZVector mainAxis(axis_);
267  mainAxis.unit();
268  math::XYZVector phiAxis(barycenter_.x(), barycenter_.y(), 0);
269  math::XYZVector udir(mainAxis.Cross(phiAxis));
270  udir = udir.unit();
273  Point(barycenter_ + udir),
274  Point(0, 0, 0),
275  Point(0., 0., 1.),
276  Point(1., 0., 0.));
277  float energyEE = 0.;
278  float energyFH = 0.;
279  float energyBH = 0.;
280 
281  for (const auto& spot : theSpots_) {
282  if (!withHalo && !spot.isCore())
283  continue;
284  math::XYZPoint local = trans_(Point(spot.row()[0], spot.row()[1], spot.row()[2]));
285  if (local.Perp2() > radius2)
286  continue;
287  energyPerLayer[spot.layer()] += spot.energy();
288  layers.insert(spot.layer());
289  if (spot.detId().det() == DetId::HGCalEE or spot.subdet() == HGCEE) {
290  energyEE += spot.energy();
291  } else if (spot.detId().det() == DetId::HGCalHSi or spot.subdet() == HGCHEF) {
292  energyFH += spot.energy();
293  } else if (spot.detId().det() == DetId::HGCalHSc or spot.subdet() == HGCHEB) {
294  energyBH += spot.energy();
295  }
296  }
297  return LongDeps(radius, energyPerLayer, energyEE, energyFH, energyBH, layers);
298 }
299 
301  unsigned nSpots = theSpots_.size();
302  float radius2 = radius * radius;
303  for (unsigned i = 0; i < nSpots; ++i) {
304  Spot spot(theSpots_[i]);
305  math::XYZPoint local = trans_(Point(spot.row()[0], spot.row()[1], spot.row()[2]));
306  if (local.Perp2() < radius2) {
307  std::cout << i << " " << theSpots_[i].detId().rawId() << " " << theSpots_[i].layer() << " "
308  << theSpots_[i].energy() << " " << theSpots_[i].isCore();
309  std::cout << " " << std::sqrt(local.Perp2()) << std::endl;
310  }
311  }
312 }
313 
315  unsigned int firstLayer = 0;
316  for (unsigned il = 1; il <= maxlayer_; ++il) {
317  if (ld.energyPerLayer()[il] > 0.) {
318  firstLayer = il;
319  break;
320  }
321  }
322  // Make dummy DetId to get abs(z) for layer
323  return recHitTools_->getPositionLayer(firstLayer).z();
324 }
325 
327  float& measuredDepth,
328  float& expectedDepth,
329  float& expectedSigma) {
330  expectedDepth = -999.;
331  expectedSigma = -999.;
332  measuredDepth = -999.;
333  if (!checkIteration())
334  return -999.;
335 
336  float z = findZFirstLayer(ld);
337  math::XYZVector dir = axis_.unit();
338  measuredDepth = std::abs((z - std::abs(barycenter_.z())) / dir.z());
339  return showerDepth_.getClusterDepthCompatibility(measuredDepth, ld.energyEE(), expectedDepth, expectedSigma);
340 }
void computeShowerWidth(float radius, bool withHalo=true)
std::vector< const HGCRecHit * > hits_
void printHits(float radius) const
math::XYZPoint barycenter_
const std::vector< std::pair< DetId, float > > & hitsAndFractions() const
Definition: CaloCluster.h:210
void computePCA(float radius, bool withHalo=true)
LongDeps energyPerLayer(float radius, bool withHalo=true)
T z() const
Definition: PV3DBase.h:61
std::unique_ptr< TPrincipal > pca_
size_type size() const
const double * row() const
Definition: Spot.h:24
const std::vector< float > & energyPerLayer() const
Definition: LongDeps.h:28
constexpr Detector det() const
get the detector field from this detid
Definition: DetId.h:46
double phi() const
azimuthal angle of cluster centroid
Definition: CaloCluster.h:184
void storeRecHits(const reco::CaloCluster &theCluster)
T x() const
Definition: PV3DBase.h:59
T y() const
Definition: PV3DBase.h:60
GlobalPoint getPosition(const DetId &id) const
Definition: RecHitTools.cc:140
T sqrt(T t)
Definition: SSEVec.h:23
The Signals That Services Can Subscribe To This is based on ActivityRegistry and is current per Services can connect to the signals distributed by the ActivityRegistry in order to monitor the activity of the application Each possible callback has some defined which we here list in angle e< void, edm::EventID const &, edm::Timestamp const & > We also list in braces which AR_WATCH_USING_METHOD_ is used for those or
Definition: Activities.doc:12
dictionary firstIndex
Definition: JetHT_cfg.py:140
Abs< T >::type abs(const T &t)
Definition: Abs.h:22
float getClusterDepthCompatibility(float measuredDepth, float emEnergy, float &expectedDepth, float &expectedSigma) const
Definition: ShowerDepth.cc:6
double f[11][100]
std::vector< Spot > theSpots_
const std::unordered_map< DetId, const unsigned int > * hitMap_
ROOT::Math::Transform3D Transform3D
component_iterator end() const
Definition: DetId.h:17
void setRecHitTools(const hgcal::RecHitTools *recHitTools)
float clusterDepthCompatibility(const LongDeps &, float &measuredDepth, float &expectedDepth, float &expectedSigma)
float findZFirstLayer(const LongDeps &) const
XYZVectorD XYZVector
spatial vector with cartesian internal representation
Definition: Vector3D.h:31
constexpr uint32_t rawId() const
get the raw id
Definition: DetId.h:57
XYZPointD XYZPoint
point in space with cartesian internal representation
Definition: Point3D.h:12
void setHitMap(const std::unordered_map< DetId, const unsigned int > *hitMap)
to set once per event
component_iterator begin() const
math::XYZVector axis_
GlobalPoint getPositionLayer(int layer, bool nose=false) const
Definition: RecHitTools.cc:152
unsigned int lastLayerBH() const
Definition: RecHitTools.h:79
Structure Point Contains parameters of Gaussian fits to DMRs.
std::vector< double > invThicknessCorrection_
std::vector< double > dEdXWeights_
const reco::CaloCluster * theCluster_
double eta() const
pseudorapidity of cluster centroid
Definition: CaloCluster.h:181
Log< level::Warning, false > LogWarning
ROOT::Math::Transform3D::Point Point
int getSiThickIndex(const DetId &) const
Definition: RecHitTools.cc:216
void setRecHits(edm::Handle< HGCRecHitCollection > recHitHandleEE, edm::Handle< HGCRecHitCollection > recHitHandleFH, edm::Handle< HGCRecHitCollection > recHitHandleBH)
const hgcal::RecHitTools * recHitTools_
unsigned int lastLayerEE(bool nose=false) const
Definition: RecHitTools.h:76
unsigned int getLayerWithOffset(const DetId &) const
Definition: RecHitTools.cc:381
float energyEE() const
Definition: LongDeps.h:25