CMS 3D CMS Logo

EgammaPCAHelper.cc
Go to the documentation of this file.
2 
7 
8 // To retrieve HGCalImagingAlgo::maxlayer
9 // Also available as HGCal3DClustering::lastLayerBH and HGCalDepthPreClusterer::lastLayerBH
11 
12 #include <algorithm>
13 #include <iostream>
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  hitMapOrigin_ = 0;
24  hitMap_ = new std::map<DetId, const HGCRecHit *>();
25  debug_ = false;
26 }
27 
29  if (hitMapOrigin_ == 2) delete hitMap_;
30 }
31 
32 void EGammaPCAHelper::setHitMap( std::map<DetId,const HGCRecHit *> * hitMap) {
33  hitMapOrigin_ = 1;
34  hitMap_ = hitMap ;
35  pcaIteration_ = 0;
36 }
37 
39  recHitTools_ = recHitTools;
40 }
41 
43  const HGCRecHitCollection & rechitsFH,
44  const HGCRecHitCollection & rechitsBH) {
45  hitMap_->clear();
46  for (const auto& hit : rechitsEE) {
47  hitMap_->emplace_hint(hitMap_->end(), hit.detid(), &hit);
48  }
49 
50  for (const auto& hit : rechitsFH) {
51  hitMap_->emplace_hint(hitMap_->end(), hit.detid(), &hit);
52  }
53 
54  for (const auto& hit : rechitsBH) {
55  hitMap_->emplace_hint(hitMap_->end(), hit.detid(), &hit);
56  }
57 
58  pcaIteration_ = 0;
59  hitMapOrigin_ = 2;
60 }
61 
63  theCluster_ = &cluster;
64  std::vector<std::pair<DetId, float>> result;
65  for (reco::HGCalMultiCluster::component_iterator it = cluster.begin(); it != cluster.end();
66  it++) {
67  const std::vector<std::pair<DetId, float>> &hf = (*it)->hitsAndFractions();
68  result.insert(result.end(),hf.begin(),hf.end());
69  }
70  storeRecHits(result);
71 }
72 
74  theCluster_ = &cluster;
75  storeRecHits(cluster.hitsAndFractions());
76 }
77 
78 void EGammaPCAHelper::storeRecHits(const std::vector<std::pair<DetId, float>> &hf) {
79  std::vector<double> pcavars;
80  pcavars.resize(3,0.);
81  theSpots_.clear();
82  pcaIteration_ = 0;
83 
84  sigu_ = 0.;
85  sigv_ = 0.;
86  sigp_ = 0.;
87  sige_ = 0.;
88 
89  unsigned hfsize = hf.size();
90  if (debug_)
91  std::cout << "The seed cluster constains " << hfsize << " hits " << std::endl;
92 
93  if (hfsize == 0) return;
94 
95 
96  for (unsigned int j = 0; j < hfsize; j++) {
97  unsigned int layer = recHitTools_->getLayerWithOffset(hf[j].first);
98 
99  const DetId rh_detid = hf[j].first;
100  std::map<DetId,const HGCRecHit *>::const_iterator itcheck= hitMap_->find(rh_detid);
101  if (itcheck == hitMap_->end()) {
102  edm::LogWarning("EgammaPCAHelper") << " Big problem, unable to find a hit " << rh_detid.rawId() << " " << rh_detid.det() << " " << HGCalDetId(rh_detid) << std::endl;
103  continue;
104  }
105  if (debug_) {
106  std::cout << "DetId " << rh_detid.rawId() << " " << layer << " " << itcheck->second->energy() <<std::endl;
107  std::cout << " Hit " << itcheck->second << " " << itcheck->second->energy() << std::endl;
108  }
109  float fraction = hf[j].second;
110 
111  double thickness = (DetId::Forward == DetId(rh_detid).det()) ? recHitTools_->getSiThickness(rh_detid) : -1;
112  double mip = dEdXWeights_[layer] * 0.001; // convert in GeV
113  if (thickness > 99. && thickness < 101)
114  mip *= invThicknessCorrection_[0];
115  else if (thickness > 199 && thickness < 201)
116  mip *= invThicknessCorrection_[1];
117  else if (thickness > 299 && thickness < 301)
118  mip *= invThicknessCorrection_[2];
119 
120  pcavars[0] = recHitTools_->getPosition(rh_detid).x();
121  pcavars[1] = recHitTools_->getPosition(rh_detid).y();
122  pcavars[2] = recHitTools_->getPosition(rh_detid).z();
123  if (pcavars[2] == 0.)
124  edm::LogWarning("EgammaPCAHelper") << " Problem, hit with z =0 ";
125  else {
126  Spot mySpot(rh_detid,itcheck->second->energy(),pcavars,layer,fraction,mip);
127  theSpots_.push_back(mySpot);
128  }
129  }
130  if (debug_) {
131  std::cout << " Stored " << theSpots_.size() << " hits " << std::endl;
132  }
133 }
134 
135 void EGammaPCAHelper::computePCA(float radius , bool withHalo) {
136  // very important - to reset
137  pca_.reset(new TPrincipal(3, "D"));
138  bool initialCalculation = radius < 0;
139  if (debug_)
140  std::cout << " Initial calculation " << initialCalculation << std::endl;
141  if (initialCalculation && withHalo) {
142  edm::LogWarning("EGammaPCAHelper") << "Warning - in the first iteration, the halo hits are excluded " << std::endl;
143  withHalo=false;
144  }
145 
146  float radius2 = radius*radius;
147  if (! initialCalculation) {
148  math::XYZVector mainAxis(axis_);
149  mainAxis.unit();
150  math::XYZVector phiAxis(barycenter_.x(), barycenter_.y(), 0);
151  math::XYZVector udir(mainAxis.Cross(phiAxis));
152  udir = udir.unit();
154  Point(0., 0., 1.), Point(1., 0., 0.));
155  }
156 
157  std::set<int> layers;
158  for (const auto& spot : theSpots_) {
159  if (spot.layer() > recHitTools_->lastLayerEE()) continue;
160  if (!withHalo && (! spot.isCore() ))
161  continue;
162  if (initialCalculation) {
163  // initial calculation, take only core hits
164  if ( ! spot.isCore() ) continue;
165  layers.insert(spot.layer());
166  for (int i = 0; i < spot.multiplicity(); ++i)
167  pca_->AddRow(spot.row());
168  }
169  else {
170  // use a cylinder, include all hits
171  math::XYZPoint local = trans_(Point( spot.row()[0],spot.row()[1],spot.row()[2]));
172  if (local.Perp2() > radius2) continue;
173  layers.insert(spot.layer());
174  for (int i = 0; i < spot.multiplicity(); ++i)
175  pca_->AddRow(spot.row());
176  }
177  }
178  if (debug_)
179  std::cout << " Nlayers " << layers.size() << std::endl;
180  if (layers.size() < 3) {
181  pcaIteration_ = -1;
182  return;
183  }
184  pca_->MakePrincipals();
185  ++pcaIteration_;
186  const TVectorD& means = *(pca_->GetMeanValues());
187  const TMatrixD& eigens = *(pca_->GetEigenVectors());
188 
189  barycenter_ = math::XYZPoint(means[0], means[1], means[2]);
190  axis_ = math::XYZVector(eigens(0, 0), eigens(1, 0), eigens(2, 0));
191  if (axis_.z() * barycenter_.z() < 0.0) {
192  axis_ = -1. * axis_;
193  }
194 }
195 
196  void EGammaPCAHelper::computeShowerWidth(float radius, bool withHalo){
197  sigu_ = 0.;
198  sigv_ = 0.;
199  sigp_ = 0.;
200  sige_ = 0.;
201  double cyl_ene = 0.;
202 
203  float radius2 = radius * radius;
204  for (const auto& spot : theSpots_) {
205  Point globalPoint(spot.row()[0],spot.row()[1],spot.row()[2]);
206  math::XYZPoint local = trans_(globalPoint);
207  if (local.Perp2() > radius2) continue;
208 
209  // Select halo hits or not
210  if (withHalo && spot.fraction() < 0) continue;
211  if (!withHalo && !(spot.isCore())) continue;
212 
213  sige_ += (globalPoint.eta() - theCluster_->eta()) * (globalPoint.eta() - theCluster_->eta()) * spot.energy();
214  sigp_ += deltaPhi(globalPoint.phi(), theCluster_->phi()) * deltaPhi(globalPoint.phi(), theCluster_->phi()) *
215  spot.energy();
216 
217  sigu_ += local.x() * local.x() * spot.energy();
218  sigv_ += local.y() * local.y() * spot.energy();
219  cyl_ene += spot.energy();
220  }
221 
222  if (cyl_ene > 0.) {
223  const double inv_cyl_ene = 1. / cyl_ene;
224  sigu_ = sigu_ * inv_cyl_ene;
225  sigv_ = sigv_ * inv_cyl_ene;
226  sigp_ = sigp_ * inv_cyl_ene;
227  sige_ = sige_ * inv_cyl_ene;
228  }
229  sigu_ = std::sqrt(sigu_);
230  sigv_ = std::sqrt(sigv_);
231  sigp_ = std::sqrt(sigp_);
232  sige_ = std::sqrt(sige_);
233 }
234 
236  if (pcaIteration_ == 0) {
237  if(debug_)
238  std::cout << " The PCA has not been run yet " << std::endl;
239  return false;
240  } else if (pcaIteration_ == 1) {
241  if (debug_)
242  std::cout << " The PCA has been run only once - careful " << std::endl;
243  return false;
244  } else if (pcaIteration_ == -1){
245  if (debug_)
246  std::cout << " Not enough layers to perform PCA " << std::endl;
247  return false;
248  }
249  return true;
250 }
251 
253  theSpots_.clear();
254  pcaIteration_ = 0;
255  sigu_ = 0.;
256  sigv_ = 0.;
257  sigp_ = 0.;
258  sige_ = 0.;
259 }
260 
262  if (debug_) checkIteration();
263  std::set<int> layers;
264  float radius2 = radius*radius;
265  std::vector<float> energyPerLayer(HGCalImagingAlgo::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();
272  Point(0., 0., 1.), Point(1., 0., 0.));
273  float energyEE = 0.;
274  float energyFH = 0.;
275  float energyBH = 0.;
276 
277  for (const auto& spot : theSpots_) {
278  if (!withHalo && ! spot.isCore())
279  continue;
280  math::XYZPoint local = trans_(Point( spot.row()[0],spot.row()[1],spot.row()[2]));
281  if (local.Perp2() > radius2) continue;
282  energyPerLayer[spot.layer()] += spot.energy();
283  layers.insert(spot.layer());
284  if (spot.subdet() == HGCEE) { energyEE += spot.energy();}
285  else if (spot.subdet() == HGCHEF) { energyFH += spot.energy();}
286  else if (spot.subdet() == HGCHEB) { energyBH += spot.energy();}
287 
288  }
289  return LongDeps(radius,energyPerLayer,energyEE,energyFH,energyBH,layers);
290 }
291 
293  unsigned nSpots = theSpots_.size();
294  float radius2=radius*radius;
295  for ( unsigned i =0; i< nSpots ; ++i) {
296  Spot spot(theSpots_[i]);
297  math::XYZPoint local = trans_(Point( spot.row()[0],spot.row()[1],spot.row()[2]));
298  if (local.Perp2() < radius2 ) {
299  std::cout << i << " " << theSpots_[i].detId().rawId() << " " << theSpots_[i].layer() << " " << theSpots_[i].energy() << " " <<theSpots_[i].isCore() ;
300  std::cout << " " << std::sqrt(local.Perp2()) << std::endl;
301  }
302  }
303 }
304 
306  unsigned int firstLayer = 0;
307  for(unsigned il=1;il<=HGCalImagingAlgo::maxlayer;++il) {
308  if (ld.energyPerLayer()[il] > 0.) {
309  firstLayer = il;
310  break;
311  }
312  }
313  // Make dummy DetId to get abs(z) for layer
314  DetId id;
315  if (firstLayer <= recHitTools_->lastLayerEE()) id = HGCalDetId(ForwardSubdetector::HGCEE, 1, firstLayer, 1, 50, 1);
316  else if (firstLayer <= recHitTools_->lastLayerFH()) id = HGCalDetId(ForwardSubdetector::HGCHEF, 1, firstLayer - recHitTools_->lastLayerEE(), 1, 50, 1);
317  else id = HcalDetId(HcalSubdetector::HcalEndcap, 50, 100, firstLayer - recHitTools_->lastLayerFH());
318  return recHitTools_->getPosition(id).z();
319 }
320 
321 float EGammaPCAHelper::clusterDepthCompatibility(const LongDeps & ld, float & measuredDepth, float& expectedDepth, float&expectedSigma) {
322  expectedDepth = -999.;
323  expectedSigma = -999.;
324  measuredDepth = -999.;
325  if (!checkIteration()) return -999.;
326 
327  float z = findZFirstLayer(ld);
328  math::XYZVector dir=axis_.unit();
329  measuredDepth = std::abs((z-std::abs(barycenter_.z()))/dir.z());
330  return showerDepth_.getClusterDepthCompatibility(measuredDepth,ld.energyEE(), expectedDepth,expectedSigma);
331 }
void computeShowerWidth(float radius, bool withHalo=true)
math::XYZPoint barycenter_
float energyEE() const
Definition: LongDeps.h:20
static const unsigned int maxlayer
std::vector< LayerSetAndLayers > layers(const SeedingLayerSetsHits &sets)
Definition: LayerTriplets.cc:4
void computePCA(float radius, bool withHalo=true)
std::map< DetId, const HGCRecHit * > * hitMap_
LongDeps energyPerLayer(float radius, bool withHalo=true)
float findZFirstLayer(const LongDeps &) const
std::unique_ptr< TPrincipal > pca_
component_iterator begin() const
ROOT::Math::Transform3DPJ Transform3D
T y() const
Definition: PV3DBase.h:63
const std::vector< std::pair< DetId, float > > & hitsAndFractions() const
Definition: CaloCluster.h:195
float getClusterDepthCompatibility(float measuredDepth, float emEnergy, float &expectedDepth, float &expectedSigma) const
Definition: ShowerDepth.cc:6
double eta() const
pseudorapidity of cluster centroid
Definition: CaloCluster.h:166
uint32_t rawId() const
get the raw id
Definition: DetId.h:43
void storeRecHits(const reco::CaloCluster &theCluster)
ROOT::Math::Transform3DPJ::Point Point
T sqrt(T t)
Definition: SSEVec.h:18
T z() const
Definition: PV3DBase.h:64
void setHitMap(std::map< DetId, const HGCRecHit * > *hitMap)
to set from outside - once per event
Abs< T >::type abs(const T &t)
Definition: Abs.h:22
double f[11][100]
std::vector< Spot > theSpots_
unsigned int lastLayerEE() const
Definition: RecHitTools.h:52
component_iterator end() const
std::float_t getSiThickness(const DetId &) const
Definition: RecHitTools.cc:103
Definition: DetId.h:18
void setRecHitTools(const hgcal::RecHitTools *recHitTools)
unsigned int getLayerWithOffset(const DetId &) const
Definition: RecHitTools.cc:179
float clusterDepthCompatibility(const LongDeps &, float &measuredDepth, float &expectedDepth, float &expectedSigma)
XYZVectorD XYZVector
spatial vector with cartesian internal representation
Definition: Vector3D.h:30
XYZPointD XYZPoint
point in space with cartesian internal representation
Definition: Point3D.h:12
const std::vector< float > & energyPerLayer() const
Definition: LongDeps.h:23
void printHits(float radius) const
GlobalPoint getPosition(const DetId &id) const
Definition: RecHitTools.cc:77
const double * row() const
Definition: Spot.h:17
std::vector< double > invThicknessCorrection_
void fillHitMap(const HGCRecHitCollection &HGCEERecHits, const HGCRecHitCollection &HGCFHRecHits, const HGCRecHitCollection &HGCBHRecHits)
to compute from inside - once per event
std::vector< double > dEdXWeights_
const reco::CaloCluster * theCluster_
bool checkIteration() const
dbl *** dir
Definition: mlp_gen.cc:35
double phi() const
azimuthal angle of cluster centroid
Definition: CaloCluster.h:169
Detector det() const
get the detector field from this detid
Definition: DetId.h:35
T x() const
Definition: PV3DBase.h:62
const hgcal::RecHitTools * recHitTools_
unsigned int lastLayerFH() const
Definition: RecHitTools.h:53